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 33677 : is_oacc_parallel_or_serial (omp_context *ctx)
216 : {
217 33677 : enum gimple_code outer_type = gimple_code (ctx->stmt);
218 33677 : return ((outer_type == GIMPLE_OMP_TARGET)
219 33677 : && ((gimple_omp_target_kind (ctx->stmt)
220 : == GF_OMP_TARGET_KIND_OACC_PARALLEL)
221 15335 : || (gimple_omp_target_kind (ctx->stmt)
222 33677 : == 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 42990 : is_omp_target (gimple *stmt)
255 : {
256 42990 : 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 540868 : omp_member_access_dummy_var (tree decl)
273 : {
274 540868 : if (!VAR_P (decl)
275 331755 : || !DECL_ARTIFICIAL (decl)
276 162893 : || !DECL_IGNORED_P (decl)
277 157465 : || !DECL_HAS_VALUE_EXPR_P (decl)
278 553691 : || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
279 538608 : 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 339357 : scan_omp_op (tree *tp, omp_context *ctx)
338 : {
339 339357 : struct walk_stmt_info wi;
340 :
341 339357 : memset (&wi, 0, sizeof (wi));
342 339357 : wi.info = ctx;
343 339357 : wi.want_locations = true;
344 :
345 339357 : 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 777399 : is_parallel_ctx (omp_context *ctx)
356 : {
357 61299 : 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 236839 : is_task_ctx (omp_context *ctx)
365 : {
366 38944 : 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 8193 : is_taskloop_ctx (omp_context *ctx)
374 : {
375 8193 : return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
376 8193 : && 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 522004 : is_host_teams_ctx (omp_context *ctx)
384 : {
385 522004 : return gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
386 522004 : && 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 664575 : is_taskreg_ctx (omp_context *ctx)
395 : {
396 664575 : 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 907490 : is_variable_sized (const_tree expr, bool is_ref = false)
405 : {
406 907490 : if (is_ref)
407 2178 : expr = TREE_TYPE (expr);
408 907490 : 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 717555 : lookup_decl (tree var, omp_context *ctx)
417 : {
418 1435011 : tree *n = ctx->cb.decl_map->get (var);
419 717555 : return *n;
420 : }
421 :
422 : static inline tree
423 720027 : maybe_lookup_decl (const_tree var, omp_context *ctx)
424 : {
425 720027 : tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
426 720027 : return n ? *n : NULL_TREE;
427 : }
428 :
429 : static inline tree
430 127629 : lookup_field (tree var, omp_context *ctx)
431 : {
432 127629 : splay_tree_node n;
433 255258 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
434 127629 : return (tree) n->value;
435 : }
436 :
437 : static inline tree
438 169719 : lookup_sfield (splay_tree_key key, omp_context *ctx)
439 : {
440 169719 : splay_tree_node n;
441 169719 : n = splay_tree_lookup (ctx->sfield_map
442 : ? ctx->sfield_map : ctx->field_map, key);
443 169719 : 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 221918 : maybe_lookup_field (splay_tree_key key, omp_context *ctx)
454 : {
455 221918 : splay_tree_node n;
456 221918 : n = splay_tree_lookup (ctx->field_map, key);
457 221918 : return n ? (tree) n->value : NULL_TREE;
458 : }
459 :
460 : static inline tree
461 221918 : 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 233057 : use_pointer_for_field (tree decl, omp_context *shared_ctx)
471 : {
472 454538 : if (AGGREGATE_TYPE_P (TREE_TYPE (decl))
473 216274 : || TYPE_ATOMIC (TREE_TYPE (decl))
474 449331 : || 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 216244 : if (shared_ctx)
480 : {
481 29571 : 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 29571 : 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 29571 : 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 28657 : 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 27425 : 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 18514 : if (TREE_READONLY (decl)
524 18514 : || ((TREE_CODE (decl) == RESULT_DECL
525 11868 : || 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 11636 : 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 9993 : 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 230114 : omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
598 : {
599 230114 : tree copy = copy_var_decl (var, name, type);
600 :
601 230114 : DECL_CONTEXT (copy) = current_function_decl;
602 :
603 230114 : if (ctx)
604 : {
605 229833 : DECL_CHAIN (copy) = ctx->block_vars;
606 229833 : 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 230114 : if (TREE_ADDRESSABLE (var)
616 230114 : && ((make_addressable_vars
617 3469 : && bitmap_bit_p (make_addressable_vars, DECL_UID (var)))
618 39791 : || (global_nonaddressable_vars
619 515 : && bitmap_bit_p (global_nonaddressable_vars, DECL_UID (var)))))
620 2079 : TREE_ADDRESSABLE (copy) = 0;
621 :
622 230114 : return copy;
623 : }
624 :
625 : static tree
626 230114 : omp_copy_decl_1 (tree var, omp_context *ctx)
627 : {
628 230114 : 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 123171 : build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
635 : {
636 123171 : 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 123171 : x = maybe_lookup_field (field, ctx);
641 123171 : if (x != NULL)
642 11245 : field = x;
643 :
644 123171 : x = build_simple_mem_ref (ctx->receiver_decl);
645 123171 : TREE_THIS_NOTRAP (x) = 1;
646 123171 : x = omp_build_component_ref (x, field);
647 123171 : if (by_ref)
648 : {
649 36260 : x = build_simple_mem_ref (x);
650 36260 : TREE_THIS_NOTRAP (x) = 1;
651 : }
652 :
653 123171 : 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 114639 : build_outer_var_ref (tree var, omp_context *ctx,
662 : enum omp_clause_code code = OMP_CLAUSE_ERROR)
663 : {
664 114639 : tree x;
665 114639 : omp_context *outer = ctx->outer;
666 115028 : for (; outer; outer = outer->outer)
667 : {
668 82594 : if (gimple_code (outer->stmt) == GIMPLE_OMP_TASKGROUP)
669 373 : continue;
670 82237 : if (gimple_code (outer->stmt) == GIMPLE_OMP_SCOPE
671 82221 : && !maybe_lookup_decl (var, outer))
672 16 : continue;
673 : break;
674 : }
675 :
676 114639 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
677 : x = var;
678 106498 : 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 106451 : else if (is_taskreg_ctx (ctx))
685 : {
686 63850 : bool by_ref = use_pointer_for_field (var, NULL);
687 63850 : x = build_receiver_ref (var, by_ref, ctx);
688 : }
689 42601 : else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
690 41228 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
691 14133 : || ctx->loop_p
692 13360 : || code == OMP_CLAUSE_ALLOCATE
693 55705 : || (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 29517 : x = NULL_TREE;
703 29517 : if (outer && is_taskreg_ctx (outer))
704 1002 : x = lookup_decl (var, outer);
705 28515 : else if (outer)
706 22321 : x = maybe_lookup_decl_in_outer_ctx (var, ctx);
707 23323 : if (x == NULL_TREE)
708 : x = var;
709 : }
710 13084 : 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 12395 : else if (outer)
739 12203 : 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 114639 : if (x == var)
750 : {
751 16326 : tree t = omp_member_access_dummy_var (var);
752 16326 : 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 114639 : if (omp_privatize_by_reference (var))
764 3092 : x = build_simple_mem_ref (x);
765 :
766 114639 : return x;
767 : }
768 :
769 : /* Build tree nodes to access the field for VAR on the sender side. */
770 :
771 : static tree
772 168673 : build_sender_ref (splay_tree_key key, omp_context *ctx)
773 : {
774 168673 : tree field = lookup_sfield (key, ctx);
775 168673 : tree tmp = ctx->sender_decl;
776 168673 : if (POINTER_TYPE_P (TREE_TYPE (tmp)))
777 451 : tmp = build_fold_indirect_ref (tmp);
778 168673 : return omp_build_component_ref (tmp, field);
779 : }
780 :
781 : static tree
782 164519 : 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 131520 : install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
801 : tree key_expr = NULL_TREE)
802 : {
803 131520 : tree field, type, sfield = NULL_TREE;
804 131520 : splay_tree_key key = (splay_tree_key) var;
805 :
806 131520 : if (key_expr)
807 : /* Allow caller to explicitly set the expression used as the key. */
808 44775 : key = (splay_tree_key) key_expr;
809 : else
810 : {
811 86745 : 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 86745 : 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 131520 : gcc_assert ((mask & 1) == 0
823 : || !splay_tree_lookup (ctx->field_map, key));
824 131520 : gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
825 : || !splay_tree_lookup (ctx->sfield_map, key));
826 131520 : gcc_assert ((mask & 3) == 3
827 : || !is_gimple_omp_oacc (ctx->stmt));
828 :
829 131520 : type = TREE_TYPE (var);
830 131520 : 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 131520 : if (POINTER_TYPE_P (type)
837 131520 : && TYPE_RESTRICT (type))
838 7058 : type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
839 :
840 131520 : 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 131095 : else if (by_ref)
846 64157 : type = build_pointer_type (type);
847 66938 : else if ((mask & (32 | 3)) == 1
848 66938 : && omp_privatize_by_reference (var))
849 162 : type = TREE_TYPE (type);
850 :
851 131520 : field = build_decl (DECL_SOURCE_LOCATION (var),
852 131520 : 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 131520 : DECL_ABSTRACT_ORIGIN (field) = var;
858 131520 : if ((mask & 16) == 0 && type == TREE_TYPE (var))
859 : {
860 62399 : SET_DECL_ALIGN (field, DECL_ALIGN (var));
861 62399 : DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
862 62399 : TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
863 : }
864 : else
865 69121 : SET_DECL_ALIGN (field, TYPE_ALIGN (type));
866 :
867 131520 : if ((mask & 3) == 3)
868 : {
869 130468 : insert_field_into_struct (ctx->record_type, field);
870 130468 : if (ctx->srecord_type)
871 : {
872 680 : sfield = build_decl (DECL_SOURCE_LOCATION (var),
873 680 : FIELD_DECL, DECL_NAME (var), type);
874 680 : DECL_ABSTRACT_ORIGIN (sfield) = var;
875 680 : SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
876 680 : DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
877 680 : TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
878 680 : insert_field_into_struct (ctx->srecord_type, sfield);
879 : }
880 : }
881 : else
882 : {
883 1052 : if (ctx->srecord_type == NULL_TREE)
884 : {
885 544 : tree t;
886 :
887 544 : ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
888 544 : ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
889 2027 : 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 1052 : sfield = field;
901 1052 : insert_field_into_struct ((mask & 1) ? ctx->record_type
902 : : ctx->srecord_type, field);
903 : }
904 :
905 131520 : if (mask & 1)
906 131133 : splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
907 131520 : if ((mask & 2) && ctx->sfield_map)
908 1067 : splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
909 131520 : }
910 :
911 : static tree
912 229683 : install_var_local (tree var, omp_context *ctx)
913 : {
914 229683 : tree new_var = omp_copy_decl_1 (var, ctx);
915 229683 : insert_decl_map (&ctx->cb, var, new_var);
916 229683 : 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 204831 : fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
924 : {
925 204831 : tree new_decl, size;
926 :
927 204831 : new_decl = lookup_decl (decl, ctx);
928 :
929 204831 : TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
930 :
931 408529 : if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
932 205020 : && 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 204831 : 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 204831 : }
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 464607 : omp_copy_decl (tree var, copy_body_data *cb)
961 : {
962 464607 : omp_context *ctx = (omp_context *) cb;
963 464607 : tree new_var;
964 :
965 464607 : if (TREE_CODE (var) == LABEL_DECL)
966 : {
967 189033 : if (FORCED_LABEL (var) || DECL_NONLOCAL (var))
968 : return var;
969 189027 : new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
970 189027 : DECL_CONTEXT (new_var) = current_function_decl;
971 189027 : insert_decl_map (&ctx->cb, var, new_var);
972 189027 : return new_var;
973 : }
974 :
975 357419 : while (!is_taskreg_ctx (ctx))
976 : {
977 338179 : ctx = ctx->outer;
978 338179 : if (ctx == NULL)
979 : return var;
980 279911 : new_var = maybe_lookup_decl (var, ctx);
981 279911 : if (new_var)
982 : return new_var;
983 : }
984 :
985 19240 : if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
986 13383 : return var;
987 :
988 5857 : return error_mark_node;
989 : }
990 :
991 : /* Create a new context, with OUTER_CTX being the surrounding context. */
992 :
993 : static omp_context *
994 137898 : new_omp_context (gimple *stmt, omp_context *outer_ctx)
995 : {
996 137898 : omp_context *ctx = XCNEW (omp_context);
997 :
998 137898 : splay_tree_insert (all_contexts, (splay_tree_key) stmt,
999 : (splay_tree_value) ctx);
1000 137898 : ctx->stmt = stmt;
1001 :
1002 137898 : if (outer_ctx)
1003 : {
1004 74563 : ctx->outer = outer_ctx;
1005 74563 : ctx->cb = outer_ctx->cb;
1006 74563 : ctx->cb.block = NULL;
1007 74563 : ctx->depth = outer_ctx->depth + 1;
1008 : }
1009 : else
1010 : {
1011 63335 : ctx->cb.src_fn = current_function_decl;
1012 63335 : ctx->cb.dst_fn = current_function_decl;
1013 63335 : ctx->cb.src_node = cgraph_node::get (current_function_decl);
1014 63335 : gcc_checking_assert (ctx->cb.src_node);
1015 63335 : ctx->cb.dst_node = ctx->cb.src_node;
1016 63335 : ctx->cb.src_cfun = cfun;
1017 63335 : ctx->cb.copy_decl = omp_copy_decl;
1018 63335 : ctx->cb.eh_lp_nr = 0;
1019 63335 : ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1020 63335 : ctx->cb.adjust_array_error_bounds = true;
1021 63335 : ctx->cb.dont_remap_vla_if_no_change = true;
1022 63335 : ctx->depth = 1;
1023 : }
1024 :
1025 137898 : ctx->cb.decl_map = new hash_map<tree, tree>;
1026 :
1027 137898 : return ctx;
1028 : }
1029 :
1030 : static gimple_seq maybe_catch_exception (gimple_seq);
1031 :
1032 : /* Finalize task copyfn. */
1033 :
1034 : static void
1035 504 : finalize_task_copyfn (gomp_task *task_stmt)
1036 : {
1037 504 : struct function *child_cfun;
1038 504 : tree child_fn;
1039 504 : gimple_seq seq = NULL, new_seq;
1040 504 : gbind *bind;
1041 :
1042 504 : child_fn = gimple_omp_task_copy_fn (task_stmt);
1043 504 : if (child_fn == NULL_TREE)
1044 0 : return;
1045 :
1046 504 : child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1047 504 : DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1048 :
1049 504 : push_cfun (child_cfun);
1050 504 : bind = gimplify_body (child_fn, false);
1051 504 : gimple_seq_add_stmt (&seq, bind);
1052 504 : new_seq = maybe_catch_exception (seq);
1053 504 : 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 504 : gimple_set_body (child_fn, seq);
1060 504 : pop_cfun ();
1061 :
1062 : /* Inform the callgraph about the new function. */
1063 504 : cgraph_node *node = cgraph_node::get_create (child_fn);
1064 504 : node->parallelized_function = 1;
1065 504 : 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 137892 : delete_omp_context (splay_tree_value value)
1073 : {
1074 137892 : omp_context *ctx = (omp_context *) value;
1075 :
1076 275784 : delete ctx->cb.decl_map;
1077 :
1078 137892 : if (ctx->field_map)
1079 69230 : splay_tree_delete (ctx->field_map);
1080 137892 : if (ctx->sfield_map)
1081 544 : 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 137892 : if (ctx->record_type)
1086 : {
1087 53503 : tree t;
1088 222842 : for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1089 169339 : DECL_ABSTRACT_ORIGIN (t) = NULL;
1090 : }
1091 137892 : if (ctx->srecord_type)
1092 : {
1093 544 : tree t;
1094 3094 : for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1095 2550 : DECL_ABSTRACT_ORIGIN (t) = NULL;
1096 : }
1097 :
1098 137892 : if (ctx->task_reduction_map)
1099 : {
1100 1173 : ctx->task_reductions.release ();
1101 2346 : delete ctx->task_reduction_map;
1102 : }
1103 :
1104 138165 : delete ctx->lastprivate_conditional_map;
1105 139280 : delete ctx->allocate_map;
1106 :
1107 137892 : XDELETE (ctx);
1108 137892 : }
1109 :
1110 : /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1111 : context. */
1112 :
1113 : static void
1114 36892 : fixup_child_record_type (omp_context *ctx)
1115 : {
1116 36892 : tree f, type = ctx->record_type;
1117 :
1118 36892 : 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 161986 : for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1125 126375 : if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1126 : break;
1127 36892 : if (f)
1128 : {
1129 1281 : tree name, new_fields = NULL;
1130 :
1131 1281 : type = lang_hooks.types.make_type (RECORD_TYPE);
1132 1281 : name = DECL_NAME (TYPE_NAME (ctx->record_type));
1133 1281 : name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1134 : TYPE_DECL, name, type);
1135 1281 : TYPE_NAME (type) = name;
1136 :
1137 13520 : for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1138 : {
1139 12239 : tree new_f = copy_node (f);
1140 12239 : DECL_CONTEXT (new_f) = type;
1141 12239 : TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1142 12239 : DECL_CHAIN (new_f) = new_fields;
1143 12239 : walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1144 12239 : walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1145 : &ctx->cb, NULL);
1146 12239 : walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1147 : &ctx->cb, NULL);
1148 12239 : new_fields = new_f;
1149 :
1150 : /* Arrange to be able to look up the receiver field
1151 : given the sender field. */
1152 12239 : splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1153 : (splay_tree_value) new_f);
1154 : }
1155 1281 : TYPE_FIELDS (type) = nreverse (new_fields);
1156 1281 : 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 36892 : if (is_gimple_omp_offloaded (ctx->stmt))
1162 17627 : type = build_qualified_type (type, TYPE_QUAL_CONST);
1163 :
1164 36892 : TREE_TYPE (ctx->receiver_decl)
1165 110676 : = build_qualified_type (flexible_array_type_p (type)
1166 107 : ? build_pointer_type (type)
1167 36785 : : 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 130045 : scan_sharing_clauses (tree clauses, omp_context *ctx)
1175 : {
1176 130045 : tree c, decl;
1177 130045 : bool scan_array_reductions = false;
1178 130045 : bool flex_array_ptr = false;
1179 :
1180 551008 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1181 420963 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
1182 420963 : && (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
1183 : /* omp_default_mem_alloc is 1 */
1184 1297 : || !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 1865 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
1192 1096 : && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1193 2949 : && omp_maybe_offloaded_ctx (ctx))
1194 14 : error_at (OMP_CLAUSE_LOCATION (c), "%<allocate%> clause must"
1195 : " specify an allocator here");
1196 1865 : if ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0
1197 1853 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) != NULL_TREE
1198 769 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
1199 2374 : && !DECL_ARTIFICIAL (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
1200 : {
1201 279 : tree alloc2 = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
1202 279 : if (TREE_CODE (alloc2) == MEM_REF
1203 279 : || TREE_CODE (alloc2) == INDIRECT_REF)
1204 0 : alloc2 = TREE_OPERAND (alloc2, 0);
1205 279 : omp_context *ctx2 = ctx;
1206 740 : for (; ctx2; ctx2 = ctx2->outer)
1207 480 : if (is_gimple_omp_offloaded (ctx2->stmt))
1208 : break;
1209 279 : if (ctx2 != NULL)
1210 : {
1211 19 : tree c2 = gimple_omp_target_clauses (ctx2->stmt);
1212 108 : for (; c2; c2 = OMP_CLAUSE_CHAIN (c2))
1213 106 : if (OMP_CLAUSE_CODE (c2) == OMP_CLAUSE_USES_ALLOCATORS
1214 123 : && operand_equal_p (
1215 17 : alloc2, OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c2)))
1216 : break;
1217 19 : 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 1865 : if (ctx->allocate_map == NULL)
1227 1388 : ctx->allocate_map = new hash_map<tree, tree>;
1228 1865 : tree val = integer_zero_node;
1229 1865 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
1230 769 : val = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
1231 1865 : if (OMP_CLAUSE_ALLOCATE_ALIGN (c))
1232 295 : val = build_tree_list (val, OMP_CLAUSE_ALLOCATE_ALIGN (c));
1233 1865 : ctx->allocate_map->put (OMP_CLAUSE_DECL (c), val);
1234 : }
1235 :
1236 551008 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1237 : {
1238 420963 : bool by_ref;
1239 :
1240 420963 : switch (OMP_CLAUSE_CODE (c))
1241 : {
1242 73306 : case OMP_CLAUSE_PRIVATE:
1243 73306 : decl = OMP_CLAUSE_DECL (c);
1244 73306 : if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1245 165 : goto do_private;
1246 73141 : else if (!is_variable_sized (decl))
1247 72778 : install_var_local (decl, ctx);
1248 : break;
1249 :
1250 46884 : case OMP_CLAUSE_SHARED:
1251 46884 : decl = OMP_CLAUSE_DECL (c);
1252 46884 : 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 46884 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
1257 46884 : && !is_host_teams_ctx (ctx))
1258 : {
1259 : /* Global variables don't need to be copied,
1260 : the receiver side will use them directly. */
1261 11862 : tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1262 11862 : if (is_global_var (odecl))
1263 : break;
1264 8133 : insert_decl_map (&ctx->cb, decl, odecl);
1265 8133 : break;
1266 : }
1267 35022 : gcc_assert (is_taskreg_ctx (ctx));
1268 35022 : 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 35022 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1273 : break;
1274 28957 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1275 : {
1276 86 : use_pointer_for_field (decl, ctx);
1277 86 : break;
1278 : }
1279 28871 : by_ref = use_pointer_for_field (decl, NULL);
1280 55234 : if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1281 19334 : || TREE_ADDRESSABLE (decl)
1282 18977 : || by_ref
1283 47848 : || omp_privatize_by_reference (decl))
1284 : {
1285 12048 : by_ref = use_pointer_for_field (decl, ctx);
1286 12048 : install_var_field (decl, by_ref, 3, ctx);
1287 12048 : install_var_local (decl, ctx);
1288 12048 : break;
1289 : }
1290 : /* We don't need to copy const scalar vars back. */
1291 16823 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1292 16823 : goto do_private;
1293 :
1294 14566 : case OMP_CLAUSE_REDUCTION:
1295 : /* Collect 'reduction' clauses on OpenACC compute construct. */
1296 14566 : if (is_gimple_omp_oacc (ctx->stmt)
1297 14566 : && 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 16640 : case OMP_CLAUSE_IN_REDUCTION:
1310 16640 : decl = OMP_CLAUSE_DECL (c);
1311 16640 : if (ctx->allocate_map
1312 16640 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1313 389 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
1314 389 : || OMP_CLAUSE_REDUCTION_TASK (c)))
1315 397 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
1316 389 : || 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 16640 : 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 14274 : 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 13939 : if (is_task_ctx (ctx)
1395 26808 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1396 12869 : && OMP_CLAUSE_REDUCTION_TASK (c)
1397 381 : && 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 12789 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1411 12789 : && OMP_CLAUSE_REDUCTION_TASK (c))
1412 : {
1413 301 : install_var_local (decl, ctx);
1414 301 : break;
1415 : }
1416 12488 : goto do_private;
1417 :
1418 22747 : case OMP_CLAUSE_LASTPRIVATE:
1419 : /* Let the corresponding firstprivate clause create
1420 : the variable. */
1421 22747 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1422 : break;
1423 : /* FALLTHRU */
1424 :
1425 59407 : case OMP_CLAUSE_FIRSTPRIVATE:
1426 59407 : case OMP_CLAUSE_LINEAR:
1427 59407 : decl = OMP_CLAUSE_DECL (c);
1428 89271 : do_private:
1429 89271 : 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 45834 : && is_gimple_omp_offloaded (ctx->stmt))
1433 : {
1434 16274 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1435 16274 : || (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 15905 : tree k = (is_oacc_parallel_or_serial (ctx) ? c : NULL_TREE);
1443 15905 : by_ref = !omp_privatize_by_reference (decl);
1444 15905 : 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 89271 : 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 89211 : else if (is_taskreg_ctx (ctx))
1473 : {
1474 38408 : bool global
1475 38408 : = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1476 38408 : by_ref = use_pointer_for_field (decl, NULL);
1477 :
1478 38408 : if (is_task_ctx (ctx)
1479 38408 : && (global || by_ref || omp_privatize_by_reference (decl)))
1480 : {
1481 619 : if (ctx->allocate_map
1482 619 : && ctx->allocate_map->get (decl))
1483 59 : install_var_field (decl, by_ref, 32 | 1, ctx);
1484 : else
1485 560 : install_var_field (decl, false, 1, ctx);
1486 619 : if (!global)
1487 355 : install_var_field (decl, by_ref, 2, ctx);
1488 : }
1489 37789 : else if (!global)
1490 36520 : install_var_field (decl, by_ref, 3, ctx);
1491 : }
1492 89211 : install_var_local (decl, ctx);
1493 : /* For descr arrays on target: firstprivatize data + attach ptr. */
1494 89211 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1495 45399 : && is_gimple_omp_offloaded (ctx->stmt)
1496 15880 : && !is_gimple_omp_oacc (ctx->stmt)
1497 11632 : && lang_hooks.decls.omp_array_data (decl, true)
1498 89242 : && 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 20123 : case OMP_CLAUSE__LOOPTEMP_:
1543 20123 : case OMP_CLAUSE__REDUCTEMP_:
1544 20123 : gcc_assert (is_taskreg_ctx (ctx));
1545 20123 : decl = OMP_CLAUSE_DECL (c);
1546 20123 : install_var_field (decl, false, 3, ctx);
1547 20123 : install_var_local (decl, ctx);
1548 20123 : 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 55395 : case OMP_CLAUSE_FINAL:
1558 55395 : case OMP_CLAUSE_IF:
1559 55395 : case OMP_CLAUSE_SELF:
1560 55395 : case OMP_CLAUSE_NUM_THREADS:
1561 55395 : case OMP_CLAUSE_NUM_TEAMS:
1562 55395 : case OMP_CLAUSE_THREAD_LIMIT:
1563 55395 : case OMP_CLAUSE_DEVICE:
1564 55395 : case OMP_CLAUSE_SCHEDULE:
1565 55395 : case OMP_CLAUSE_DIST_SCHEDULE:
1566 55395 : case OMP_CLAUSE_DEPEND:
1567 55395 : case OMP_CLAUSE_PRIORITY:
1568 55395 : case OMP_CLAUSE_GRAINSIZE:
1569 55395 : case OMP_CLAUSE_NUM_TASKS:
1570 55395 : case OMP_CLAUSE_NUM_GANGS:
1571 55395 : case OMP_CLAUSE_NUM_WORKERS:
1572 55395 : case OMP_CLAUSE_VECTOR_LENGTH:
1573 55395 : case OMP_CLAUSE_DETACH:
1574 55395 : case OMP_CLAUSE_FILTER:
1575 55395 : if (ctx->outer)
1576 17618 : scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1577 : break;
1578 :
1579 88352 : case OMP_CLAUSE_TO:
1580 88352 : case OMP_CLAUSE_FROM:
1581 88352 : case OMP_CLAUSE_MAP:
1582 88352 : if (ctx->outer)
1583 15385 : scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1584 88352 : decl = OMP_CLAUSE_DECL (c);
1585 : /* If requested, make 'decl' addressable. */
1586 88352 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1587 88352 : && 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 88352 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1633 80567 : && DECL_P (decl)
1634 44377 : && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
1635 40555 : && (OMP_CLAUSE_MAP_KIND (c)
1636 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE)
1637 40126 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
1638 39892 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH)
1639 4550 : || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1640 41030 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TO
1641 40895 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_FROM
1642 40866 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TOFROM
1643 40378 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_PRESENT_TO
1644 40348 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_PRESENT_FROM
1645 40326 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_PRESENT_TOFROM
1646 40312 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
1647 36321 : && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1648 7560 : && varpool_node::get_create (decl)->offloadable
1649 93618 : && !lookup_attribute ("omp declare target link",
1650 5266 : DECL_ATTRIBUTES (decl)))
1651 : break;
1652 83114 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1653 83114 : && 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 82850 : if (!flex_array_ptr)
1663 82622 : flex_array_ptr = lang_hooks.decls.omp_deep_mapping_p (ctx->stmt, c);
1664 82850 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1665 75065 : && DECL_P (decl)
1666 38875 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
1667 38641 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
1668 83149 : && 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 82589 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1705 82589 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
1706 70984 : || (OMP_CLAUSE_MAP_KIND (c)
1707 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
1708 : {
1709 4249 : if (TREE_CODE (decl) == COMPONENT_REF
1710 4249 : || (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 4249 : if (DECL_SIZE (decl)
1718 4249 : && 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 4249 : install_var_local (decl, ctx);
1727 4249 : break;
1728 : }
1729 78340 : if (DECL_P (decl))
1730 : {
1731 40527 : if (DECL_SIZE (decl)
1732 40527 : && !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 40527 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1745 34365 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1746 5204 : && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1747 45731 : && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1748 425 : install_var_field (decl, true, 7, ctx, c);
1749 : else
1750 40102 : install_var_field (decl, true, 3, ctx, c);
1751 40527 : if (is_gimple_omp_offloaded (ctx->stmt)
1752 40527 : && !(is_gimple_omp_oacc (ctx->stmt)
1753 13857 : && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
1754 23843 : install_var_local (decl, ctx);
1755 : }
1756 : }
1757 : else
1758 : {
1759 37813 : tree base = get_base_address (decl);
1760 37813 : tree nc = OMP_CLAUSE_CHAIN (c);
1761 37813 : if (DECL_P (base)
1762 9267 : && nc != NULL_TREE
1763 6678 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1764 5516 : && OMP_CLAUSE_DECL (nc) == base
1765 1184 : && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1766 38481 : && 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 37813 : if (ctx->outer)
1774 : {
1775 7152 : scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1776 7152 : decl = OMP_CLAUSE_DECL (c);
1777 : }
1778 37813 : gcc_assert (!splay_tree_lookup (ctx->field_map,
1779 : (splay_tree_key) decl));
1780 37813 : tree field
1781 37813 : = build_decl (OMP_CLAUSE_LOCATION (c),
1782 : FIELD_DECL, NULL_TREE, ptr_type_node);
1783 37813 : SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
1784 37813 : insert_field_into_struct (ctx->record_type, field);
1785 37813 : 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 112 : case OMP_CLAUSE_USES_ALLOCATORS:
1831 112 : decl = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
1832 112 : gcc_assert (DECL_P (decl));
1833 112 : gcc_assert (is_gimple_omp_offloaded (ctx->stmt));
1834 112 : install_var_field (decl, false, 3, ctx);
1835 112 : install_var_local (decl, ctx);
1836 112 : 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 361 : case OMP_CLAUSE__CONDTEMP_:
1846 361 : decl = OMP_CLAUSE_DECL (c);
1847 361 : if (is_parallel_ctx (ctx))
1848 : {
1849 118 : install_var_field (decl, false, 3, ctx);
1850 118 : install_var_local (decl, ctx);
1851 : }
1852 243 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1853 243 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
1854 368 : && !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 : case OMP_CLAUSE_MESSAGE:
1862 : break;
1863 :
1864 0 : case OMP_CLAUSE__CACHE_:
1865 0 : case OMP_CLAUSE_NOHOST:
1866 0 : default:
1867 0 : gcc_unreachable ();
1868 : }
1869 : }
1870 :
1871 551008 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1872 : {
1873 420963 : switch (OMP_CLAUSE_CODE (c))
1874 : {
1875 22747 : case OMP_CLAUSE_LASTPRIVATE:
1876 : /* Let the corresponding firstprivate clause create
1877 : the variable. */
1878 22747 : if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1879 7245 : scan_array_reductions = true;
1880 22747 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1881 : break;
1882 : /* FALLTHRU */
1883 :
1884 149924 : case OMP_CLAUSE_FIRSTPRIVATE:
1885 149924 : case OMP_CLAUSE_PRIVATE:
1886 149924 : case OMP_CLAUSE_LINEAR:
1887 149924 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
1888 149924 : case OMP_CLAUSE_IS_DEVICE_PTR:
1889 149924 : decl = OMP_CLAUSE_DECL (c);
1890 149924 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1891 : {
1892 256 : while (INDIRECT_REF_P (decl)
1893 256 : || TREE_CODE (decl) == ARRAY_REF)
1894 17 : decl = TREE_OPERAND (decl, 0);
1895 : }
1896 :
1897 149924 : if (is_variable_sized (decl))
1898 : {
1899 423 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1900 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
1901 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
1902 53 : && is_gimple_omp_offloaded (ctx->stmt))
1903 : {
1904 12 : tree decl2 = DECL_VALUE_EXPR (decl);
1905 12 : gcc_assert (INDIRECT_REF_P (decl2));
1906 12 : decl2 = TREE_OPERAND (decl2, 0);
1907 12 : gcc_assert (DECL_P (decl2));
1908 12 : install_var_local (decl2, ctx);
1909 12 : fixup_remapped_decl (decl2, ctx, false);
1910 : }
1911 423 : install_var_local (decl, ctx);
1912 : }
1913 299848 : fixup_remapped_decl (decl, ctx,
1914 149924 : OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1915 149924 : && OMP_CLAUSE_PRIVATE_DEBUG (c));
1916 149924 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1917 149924 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1918 : scan_array_reductions = true;
1919 : break;
1920 :
1921 16640 : case OMP_CLAUSE_REDUCTION:
1922 16640 : case OMP_CLAUSE_IN_REDUCTION:
1923 16640 : decl = OMP_CLAUSE_DECL (c);
1924 16640 : if (TREE_CODE (decl) != MEM_REF && !is_omp_target (ctx->stmt))
1925 : {
1926 13939 : if (is_variable_sized (decl))
1927 0 : install_var_local (decl, ctx);
1928 13939 : fixup_remapped_decl (decl, ctx, false);
1929 : }
1930 16640 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1931 2852 : scan_array_reductions = true;
1932 : break;
1933 :
1934 530 : case OMP_CLAUSE_TASK_REDUCTION:
1935 530 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1936 2852 : scan_array_reductions = true;
1937 : break;
1938 :
1939 30061 : case OMP_CLAUSE_SHARED:
1940 : /* Ignore shared directives in teams construct inside of
1941 : target construct. */
1942 30061 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
1943 30061 : && !is_host_teams_ctx (ctx))
1944 : break;
1945 18199 : decl = OMP_CLAUSE_DECL (c);
1946 18199 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1947 : break;
1948 12134 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1949 : {
1950 86 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
1951 : ctx->outer)))
1952 : break;
1953 79 : bool by_ref = use_pointer_for_field (decl, ctx);
1954 79 : install_var_field (decl, by_ref, 11, ctx);
1955 79 : break;
1956 : }
1957 12048 : fixup_remapped_decl (decl, ctx, false);
1958 12048 : break;
1959 :
1960 80567 : case OMP_CLAUSE_MAP:
1961 80567 : if (!is_gimple_omp_offloaded (ctx->stmt))
1962 : break;
1963 53828 : decl = OMP_CLAUSE_DECL (c);
1964 53828 : if (DECL_P (decl)
1965 33904 : && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
1966 30250 : && (OMP_CLAUSE_MAP_KIND (c)
1967 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
1968 4083 : || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1969 31024 : && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1970 61211 : && varpool_node::get_create (decl)->offloadable)
1971 : break;
1972 48146 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
1973 45934 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
1974 2212 : && is_omp_target (ctx->stmt)
1975 50149 : && !is_gimple_omp_offloaded (ctx->stmt))
1976 : break;
1977 48146 : if (DECL_P (decl))
1978 : {
1979 28222 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1980 25169 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
1981 6705 : && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1982 29847 : && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1983 : {
1984 24 : tree new_decl = lookup_decl (decl, ctx);
1985 24 : TREE_TYPE (new_decl)
1986 48 : = remap_type (TREE_TYPE (decl), &ctx->cb);
1987 : }
1988 28198 : else if (DECL_SIZE (decl)
1989 28198 : && !poly_int_tree_p (DECL_SIZE (decl)))
1990 : {
1991 710 : tree decl2 = DECL_VALUE_EXPR (decl);
1992 710 : gcc_assert (INDIRECT_REF_P (decl2));
1993 710 : decl2 = TREE_OPERAND (decl2, 0);
1994 710 : gcc_assert (DECL_P (decl2));
1995 710 : fixup_remapped_decl (decl2, ctx, false);
1996 710 : fixup_remapped_decl (decl, ctx, true);
1997 : }
1998 : else
1999 27488 : fixup_remapped_decl (decl, ctx, false);
2000 : }
2001 : break;
2002 :
2003 : case OMP_CLAUSE_COPYPRIVATE:
2004 : case OMP_CLAUSE_COPYIN:
2005 : case OMP_CLAUSE_DEFAULT:
2006 : case OMP_CLAUSE_IF:
2007 : case OMP_CLAUSE_SELF:
2008 : case OMP_CLAUSE_NUM_THREADS:
2009 : case OMP_CLAUSE_NUM_TEAMS:
2010 : case OMP_CLAUSE_THREAD_LIMIT:
2011 : case OMP_CLAUSE_DEVICE:
2012 : case OMP_CLAUSE_SCHEDULE:
2013 : case OMP_CLAUSE_DIST_SCHEDULE:
2014 : case OMP_CLAUSE_NOWAIT:
2015 : case OMP_CLAUSE_ORDERED:
2016 : case OMP_CLAUSE_COLLAPSE:
2017 : case OMP_CLAUSE_UNTIED:
2018 : case OMP_CLAUSE_FINAL:
2019 : case OMP_CLAUSE_MERGEABLE:
2020 : case OMP_CLAUSE_PROC_BIND:
2021 : case OMP_CLAUSE_SAFELEN:
2022 : case OMP_CLAUSE_SIMDLEN:
2023 : case OMP_CLAUSE_ALIGNED:
2024 : case OMP_CLAUSE_DEPEND:
2025 : case OMP_CLAUSE_DETACH:
2026 : case OMP_CLAUSE_ALLOCATE:
2027 : case OMP_CLAUSE__LOOPTEMP_:
2028 : case OMP_CLAUSE__REDUCTEMP_:
2029 : case OMP_CLAUSE_TO:
2030 : case OMP_CLAUSE_FROM:
2031 : case OMP_CLAUSE_PRIORITY:
2032 : case OMP_CLAUSE_GRAINSIZE:
2033 : case OMP_CLAUSE_NUM_TASKS:
2034 : case OMP_CLAUSE_THREADS:
2035 : case OMP_CLAUSE_SIMD:
2036 : case OMP_CLAUSE_NOGROUP:
2037 : case OMP_CLAUSE_DEFAULTMAP:
2038 : case OMP_CLAUSE_ORDER:
2039 : case OMP_CLAUSE_BIND:
2040 : case OMP_CLAUSE_USE_DEVICE_PTR:
2041 : case OMP_CLAUSE_USE_DEVICE_ADDR:
2042 : case OMP_CLAUSE_NONTEMPORAL:
2043 : case OMP_CLAUSE_ASYNC:
2044 : case OMP_CLAUSE_WAIT:
2045 : case OMP_CLAUSE_NUM_GANGS:
2046 : case OMP_CLAUSE_NUM_WORKERS:
2047 : case OMP_CLAUSE_VECTOR_LENGTH:
2048 : case OMP_CLAUSE_GANG:
2049 : case OMP_CLAUSE_WORKER:
2050 : case OMP_CLAUSE_VECTOR:
2051 : case OMP_CLAUSE_INDEPENDENT:
2052 : case OMP_CLAUSE_AUTO:
2053 : case OMP_CLAUSE_SEQ:
2054 : case OMP_CLAUSE_TILE:
2055 : case OMP_CLAUSE__SIMT_:
2056 : case OMP_CLAUSE_IF_PRESENT:
2057 : case OMP_CLAUSE_FINALIZE:
2058 : case OMP_CLAUSE_FILTER:
2059 : case OMP_CLAUSE__CONDTEMP_:
2060 : case OMP_CLAUSE_INIT:
2061 : case OMP_CLAUSE_USE:
2062 : case OMP_CLAUSE_DESTROY:
2063 : case OMP_CLAUSE_DEVICE_TYPE:
2064 : case OMP_CLAUSE_USES_ALLOCATORS:
2065 : case OMP_CLAUSE_MESSAGE:
2066 : break;
2067 :
2068 0 : case OMP_CLAUSE__CACHE_:
2069 0 : case OMP_CLAUSE_NOHOST:
2070 0 : default:
2071 0 : gcc_unreachable ();
2072 : }
2073 : }
2074 :
2075 130045 : gcc_checking_assert (!scan_array_reductions
2076 : || !is_gimple_omp_oacc (ctx->stmt));
2077 : if (scan_array_reductions)
2078 : {
2079 34654 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2080 29452 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2081 27058 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
2082 26434 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
2083 30156 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2084 : {
2085 2196 : omp_context *rctx = ctx;
2086 2196 : if (is_omp_target (ctx->stmt))
2087 60 : rctx = ctx->outer;
2088 2196 : scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), rctx);
2089 2196 : scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), rctx);
2090 : }
2091 27256 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2092 27256 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2093 7245 : scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2094 20011 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2095 20011 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2096 656 : scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2097 : }
2098 130045 : if (flex_array_ptr)
2099 : {
2100 144 : tree field = build_range_type (size_type_node,
2101 : build_int_cstu (size_type_node, 0),
2102 : NULL_TREE);
2103 144 : field = build_array_type (ptr_type_node, field);
2104 144 : field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, field);
2105 144 : SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2106 144 : DECL_CONTEXT (field) = ctx->record_type;
2107 144 : DECL_CHAIN (field) = TYPE_FIELDS (ctx->record_type);
2108 144 : TYPE_FIELDS (ctx->record_type) = field;
2109 : }
2110 130045 : }
2111 :
2112 : /* Create a new name for omp child function. Returns an identifier. */
2113 :
2114 : static tree
2115 51515 : create_omp_child_function_name (bool task_copy)
2116 : {
2117 102486 : return clone_function_name_numbered (current_function_decl,
2118 51515 : task_copy ? "_omp_cpyfn" : "_omp_fn");
2119 : }
2120 :
2121 : /* Return true if CTX may belong to offloaded code: either if current function
2122 : is offloaded, or any enclosing context corresponds to a target region. */
2123 :
2124 : static bool
2125 123099 : omp_maybe_offloaded_ctx (omp_context *ctx)
2126 : {
2127 123099 : if (cgraph_node::get (current_function_decl)->offloadable)
2128 : return true;
2129 203688 : for (; ctx; ctx = ctx->outer)
2130 120376 : if (is_gimple_omp_offloaded (ctx->stmt))
2131 : return true;
2132 : return false;
2133 : }
2134 :
2135 : /* Build a decl for the omp child function. It'll not contain a body
2136 : yet, just the bare decl. If HOST_ONLY, do not create a device version. */
2137 :
2138 : static void
2139 51515 : create_omp_child_function (omp_context *ctx, bool task_copy, bool host_only)
2140 : {
2141 51515 : tree decl, type, name, t;
2142 :
2143 51515 : name = create_omp_child_function_name (task_copy);
2144 51515 : if (task_copy)
2145 544 : type = build_function_type_list (void_type_node, ptr_type_node,
2146 : ptr_type_node, NULL_TREE);
2147 : else
2148 50971 : type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2149 :
2150 51515 : decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2151 :
2152 51515 : gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2153 : || !task_copy);
2154 40129 : if (!task_copy)
2155 50971 : ctx->cb.dst_fn = decl;
2156 : else
2157 544 : gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2158 :
2159 51515 : TREE_STATIC (decl) = 1;
2160 51515 : TREE_USED (decl) = 1;
2161 51515 : DECL_ARTIFICIAL (decl) = 1;
2162 51515 : DECL_IGNORED_P (decl) = 0;
2163 51515 : TREE_PUBLIC (decl) = 0;
2164 51515 : DECL_UNINLINABLE (decl) = 1;
2165 51515 : DECL_EXTERNAL (decl) = 0;
2166 51515 : DECL_CONTEXT (decl) = NULL_TREE;
2167 51515 : DECL_INITIAL (decl) = make_node (BLOCK);
2168 51515 : BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
2169 51515 : DECL_ATTRIBUTES (decl) = DECL_ATTRIBUTES (current_function_decl);
2170 : /* Remove omp declare simd attribute from the new attributes. */
2171 51515 : if (tree a = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (decl)))
2172 : {
2173 9 : while (tree a2 = lookup_attribute ("omp declare simd", TREE_CHAIN (a)))
2174 : a = a2;
2175 9 : a = TREE_CHAIN (a);
2176 22 : for (tree *p = &DECL_ATTRIBUTES (decl); *p != a;)
2177 13 : if (is_attribute_p ("omp declare simd", get_attribute_name (*p)))
2178 9 : *p = TREE_CHAIN (*p);
2179 : else
2180 : {
2181 4 : tree chain = TREE_CHAIN (*p);
2182 4 : *p = copy_node (*p);
2183 4 : p = &TREE_CHAIN (*p);
2184 4 : *p = chain;
2185 : }
2186 : }
2187 103030 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
2188 51515 : = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl);
2189 103030 : DECL_FUNCTION_SPECIFIC_TARGET (decl)
2190 51515 : = DECL_FUNCTION_SPECIFIC_TARGET (current_function_decl);
2191 103030 : DECL_FUNCTION_VERSIONED (decl)
2192 51515 : = DECL_FUNCTION_VERSIONED (current_function_decl);
2193 :
2194 51515 : if (omp_maybe_offloaded_ctx (ctx) && !host_only)
2195 : {
2196 31046 : cgraph_node::get_create (decl)->offloadable = 1;
2197 31046 : if (ENABLE_OFFLOADING)
2198 : g->have_offload = true;
2199 : }
2200 :
2201 51515 : if (cgraph_node::get_create (decl)->offloadable)
2202 : {
2203 31046 : const char *target_attr = (is_gimple_omp_offloaded (ctx->stmt)
2204 31046 : ? "omp target entrypoint"
2205 6216 : : "omp declare target");
2206 31046 : if (lookup_attribute ("omp declare target",
2207 31046 : DECL_ATTRIBUTES (current_function_decl)))
2208 : {
2209 3032 : if (is_gimple_omp_offloaded (ctx->stmt))
2210 1620 : DECL_ATTRIBUTES (decl)
2211 1620 : = remove_attribute ("omp declare target",
2212 1620 : copy_list (DECL_ATTRIBUTES (decl)));
2213 : else
2214 : target_attr = NULL;
2215 : }
2216 1620 : if (target_attr
2217 29634 : && is_gimple_omp_offloaded (ctx->stmt)
2218 24830 : && lookup_attribute ("noclone", DECL_ATTRIBUTES (decl)) == NULL_TREE)
2219 19323 : DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("noclone"),
2220 19323 : NULL_TREE, DECL_ATTRIBUTES (decl));
2221 31046 : if (target_attr)
2222 29634 : DECL_ATTRIBUTES (decl)
2223 59268 : = tree_cons (get_identifier (target_attr),
2224 29634 : NULL_TREE, DECL_ATTRIBUTES (decl));
2225 : }
2226 :
2227 51515 : t = build_decl (DECL_SOURCE_LOCATION (decl),
2228 : RESULT_DECL, NULL_TREE, void_type_node);
2229 51515 : DECL_ARTIFICIAL (t) = 1;
2230 51515 : DECL_IGNORED_P (t) = 1;
2231 51515 : DECL_CONTEXT (t) = decl;
2232 51515 : DECL_RESULT (decl) = t;
2233 :
2234 51515 : tree data_name = get_identifier (".omp_data_i");
2235 51515 : t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2236 : ptr_type_node);
2237 51515 : DECL_ARTIFICIAL (t) = 1;
2238 51515 : DECL_NAMELESS (t) = 1;
2239 51515 : DECL_ARG_TYPE (t) = ptr_type_node;
2240 51515 : DECL_CONTEXT (t) = current_function_decl;
2241 51515 : TREE_USED (t) = 1;
2242 51515 : TREE_READONLY (t) = 1;
2243 51515 : DECL_ARGUMENTS (decl) = t;
2244 51515 : if (!task_copy)
2245 50971 : ctx->receiver_decl = t;
2246 : else
2247 : {
2248 544 : t = build_decl (DECL_SOURCE_LOCATION (decl),
2249 : PARM_DECL, get_identifier (".omp_data_o"),
2250 : ptr_type_node);
2251 544 : DECL_ARTIFICIAL (t) = 1;
2252 544 : DECL_NAMELESS (t) = 1;
2253 544 : DECL_ARG_TYPE (t) = ptr_type_node;
2254 544 : DECL_CONTEXT (t) = current_function_decl;
2255 544 : TREE_USED (t) = 1;
2256 544 : TREE_ADDRESSABLE (t) = 1;
2257 544 : DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2258 544 : DECL_ARGUMENTS (decl) = t;
2259 : }
2260 :
2261 : /* Allocate memory for the function structure. The call to
2262 : allocate_struct_function clobbers CFUN, so we need to restore
2263 : it afterward. */
2264 51515 : push_struct_function (decl);
2265 51515 : cfun->function_end_locus = gimple_location (ctx->stmt);
2266 51515 : init_tree_ssa (cfun);
2267 51515 : pop_cfun ();
2268 51515 : }
2269 :
2270 : /* Callback for walk_gimple_seq. Check if combined parallel
2271 : contains gimple_omp_for_combined_into_p OMP_FOR. */
2272 :
2273 : tree
2274 35681 : omp_find_combined_for (gimple_stmt_iterator *gsi_p,
2275 : bool *handled_ops_p,
2276 : struct walk_stmt_info *wi)
2277 : {
2278 35681 : gimple *stmt = gsi_stmt (*gsi_p);
2279 :
2280 35681 : *handled_ops_p = true;
2281 35681 : switch (gimple_code (stmt))
2282 : {
2283 19989 : WALK_SUBSTMTS;
2284 :
2285 13519 : case GIMPLE_OMP_FOR:
2286 13519 : if (gimple_omp_for_combined_into_p (stmt)
2287 13519 : && gimple_omp_for_kind (stmt)
2288 7966 : == *(const enum gf_mask *) (wi->info))
2289 : {
2290 7966 : wi->info = stmt;
2291 7966 : return integer_zero_node;
2292 : }
2293 : break;
2294 : default:
2295 : break;
2296 : }
2297 : return NULL;
2298 : }
2299 :
2300 : /* Add _LOOPTEMP_/_REDUCTEMP_ clauses on OpenMP parallel or task. */
2301 :
2302 : static void
2303 14104 : add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2304 : omp_context *outer_ctx)
2305 : {
2306 14104 : struct walk_stmt_info wi;
2307 :
2308 14104 : memset (&wi, 0, sizeof (wi));
2309 14104 : wi.val_only = true;
2310 14104 : wi.info = (void *) &msk;
2311 14104 : walk_gimple_seq (gimple_omp_body (stmt), omp_find_combined_for, NULL, &wi);
2312 14104 : if (wi.info != (void *) &msk)
2313 : {
2314 7966 : gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2315 7966 : struct omp_for_data fd;
2316 7966 : omp_extract_for_data (for_stmt, &fd, NULL);
2317 : /* We need two temporaries with fd.loop.v type (istart/iend)
2318 : and then (fd.collapse - 1) temporaries with the same
2319 : type for count2 ... countN-1 vars if not constant. */
2320 7966 : size_t count = 2, i;
2321 7966 : tree type = fd.iter_type;
2322 7966 : if (fd.collapse > 1
2323 2648 : && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2324 : {
2325 1466 : count += fd.collapse - 1;
2326 : /* If there are lastprivate clauses on the inner
2327 : GIMPLE_OMP_FOR, add one more temporaries for the total number
2328 : of iterations (product of count1 ... countN-1). */
2329 1466 : if (omp_find_clause (gimple_omp_for_clauses (for_stmt),
2330 : OMP_CLAUSE_LASTPRIVATE)
2331 1466 : || (msk == GF_OMP_FOR_KIND_FOR
2332 1335 : && omp_find_clause (gimple_omp_parallel_clauses (stmt),
2333 : OMP_CLAUSE_LASTPRIVATE)))
2334 : {
2335 726 : tree temp = create_tmp_var (type);
2336 726 : tree c = build_omp_clause (UNKNOWN_LOCATION,
2337 : OMP_CLAUSE__LOOPTEMP_);
2338 726 : insert_decl_map (&outer_ctx->cb, temp, temp);
2339 726 : OMP_CLAUSE_DECL (c) = temp;
2340 726 : OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2341 726 : gimple_omp_taskreg_set_clauses (stmt, c);
2342 : }
2343 1466 : if (fd.non_rect
2344 24 : && fd.last_nonrect == fd.first_nonrect + 1)
2345 12 : if (tree v = gimple_omp_for_index (for_stmt, fd.last_nonrect))
2346 12 : if (!TYPE_UNSIGNED (TREE_TYPE (v)))
2347 : {
2348 12 : v = gimple_omp_for_index (for_stmt, fd.first_nonrect);
2349 12 : tree type2 = TREE_TYPE (v);
2350 12 : count++;
2351 48 : for (i = 0; i < 3; i++)
2352 : {
2353 36 : tree temp = create_tmp_var (type2);
2354 36 : tree c = build_omp_clause (UNKNOWN_LOCATION,
2355 : OMP_CLAUSE__LOOPTEMP_);
2356 36 : insert_decl_map (&outer_ctx->cb, temp, temp);
2357 36 : OMP_CLAUSE_DECL (c) = temp;
2358 36 : OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2359 36 : gimple_omp_taskreg_set_clauses (stmt, c);
2360 : }
2361 : }
2362 : }
2363 26743 : for (i = 0; i < count; i++)
2364 : {
2365 18777 : tree temp = create_tmp_var (type);
2366 18777 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2367 18777 : insert_decl_map (&outer_ctx->cb, temp, temp);
2368 18777 : OMP_CLAUSE_DECL (c) = temp;
2369 18777 : OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2370 18777 : gimple_omp_taskreg_set_clauses (stmt, c);
2371 : }
2372 : }
2373 14104 : if (msk == GF_OMP_FOR_KIND_TASKLOOP
2374 15671 : && omp_find_clause (gimple_omp_task_clauses (stmt),
2375 : OMP_CLAUSE_REDUCTION))
2376 : {
2377 517 : tree type = build_pointer_type (pointer_sized_int_node);
2378 517 : tree temp = create_tmp_var (type);
2379 517 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
2380 517 : insert_decl_map (&outer_ctx->cb, temp, temp);
2381 517 : OMP_CLAUSE_DECL (c) = temp;
2382 517 : OMP_CLAUSE_CHAIN (c) = gimple_omp_task_clauses (stmt);
2383 517 : gimple_omp_task_set_clauses (stmt, c);
2384 : }
2385 14104 : }
2386 :
2387 : /* Scan an OpenMP parallel directive. */
2388 :
2389 : static void
2390 18243 : scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2391 : {
2392 18243 : omp_context *ctx;
2393 18243 : tree name;
2394 18243 : gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2395 :
2396 : /* Ignore parallel directives with empty bodies, unless there
2397 : are copyin clauses. */
2398 18243 : if (optimize > 0
2399 12515 : && empty_body_p (gimple_omp_body (stmt))
2400 18290 : && omp_find_clause (gimple_omp_parallel_clauses (stmt),
2401 : OMP_CLAUSE_COPYIN) == NULL)
2402 : {
2403 41 : gsi_replace (gsi, gimple_build_nop (), false);
2404 41 : return;
2405 : }
2406 :
2407 18202 : if (gimple_omp_parallel_combined_p (stmt))
2408 12537 : add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2409 18202 : for (tree c = omp_find_clause (gimple_omp_parallel_clauses (stmt),
2410 : OMP_CLAUSE_REDUCTION);
2411 21036 : c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_REDUCTION))
2412 3921 : if (OMP_CLAUSE_REDUCTION_TASK (c))
2413 : {
2414 67 : tree type = build_pointer_type (pointer_sized_int_node);
2415 67 : tree temp = create_tmp_var (type);
2416 67 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
2417 67 : if (outer_ctx)
2418 18 : insert_decl_map (&outer_ctx->cb, temp, temp);
2419 67 : OMP_CLAUSE_DECL (c) = temp;
2420 67 : OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2421 67 : gimple_omp_parallel_set_clauses (stmt, c);
2422 67 : break;
2423 : }
2424 3854 : else if (OMP_CLAUSE_CHAIN (c) == NULL_TREE)
2425 : break;
2426 :
2427 18202 : ctx = new_omp_context (stmt, outer_ctx);
2428 18202 : taskreg_contexts.safe_push (ctx);
2429 18202 : if (taskreg_nesting_level > 1)
2430 6222 : ctx->is_nested = true;
2431 18202 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2432 18202 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2433 18202 : name = create_tmp_var_name (".omp_data_s");
2434 18202 : name = build_decl (gimple_location (stmt),
2435 : TYPE_DECL, name, ctx->record_type);
2436 18202 : DECL_ARTIFICIAL (name) = 1;
2437 18202 : DECL_NAMELESS (name) = 1;
2438 18202 : TYPE_NAME (ctx->record_type) = name;
2439 18202 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
2440 18202 : create_omp_child_function (ctx, false, false);
2441 18202 : gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2442 :
2443 18202 : scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2444 18202 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
2445 :
2446 18202 : if (TYPE_FIELDS (ctx->record_type) == NULL)
2447 3584 : ctx->record_type = ctx->receiver_decl = NULL;
2448 : }
2449 :
2450 : /* Scan an OpenMP task directive. */
2451 :
2452 : static void
2453 5374 : scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2454 : {
2455 5374 : omp_context *ctx;
2456 5374 : tree name, t;
2457 5374 : gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2458 :
2459 : /* Ignore task directives with empty bodies, unless they have depend
2460 : clause. */
2461 5374 : if (optimize > 0
2462 2552 : && gimple_omp_body (stmt)
2463 2509 : && empty_body_p (gimple_omp_body (stmt))
2464 5428 : && !omp_find_clause (gimple_omp_task_clauses (stmt), OMP_CLAUSE_DEPEND))
2465 : {
2466 19 : gsi_replace (gsi, gimple_build_nop (), false);
2467 131 : return;
2468 : }
2469 :
2470 5355 : if (gimple_omp_task_taskloop_p (stmt))
2471 1567 : add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2472 :
2473 5355 : ctx = new_omp_context (stmt, outer_ctx);
2474 :
2475 5355 : if (gimple_omp_task_taskwait_p (stmt))
2476 : {
2477 93 : scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2478 93 : return;
2479 : }
2480 :
2481 5262 : taskreg_contexts.safe_push (ctx);
2482 5262 : if (taskreg_nesting_level > 1)
2483 2326 : ctx->is_nested = true;
2484 5262 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2485 5262 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2486 5262 : name = create_tmp_var_name (".omp_data_s");
2487 5262 : name = build_decl (gimple_location (stmt),
2488 : TYPE_DECL, name, ctx->record_type);
2489 5262 : DECL_ARTIFICIAL (name) = 1;
2490 5262 : DECL_NAMELESS (name) = 1;
2491 5262 : TYPE_NAME (ctx->record_type) = name;
2492 5262 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
2493 5262 : create_omp_child_function (ctx, false, false);
2494 5262 : gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2495 :
2496 5262 : scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2497 :
2498 5262 : if (ctx->srecord_type)
2499 : {
2500 544 : name = create_tmp_var_name (".omp_data_a");
2501 544 : name = build_decl (gimple_location (stmt),
2502 : TYPE_DECL, name, ctx->srecord_type);
2503 544 : DECL_ARTIFICIAL (name) = 1;
2504 544 : DECL_NAMELESS (name) = 1;
2505 544 : TYPE_NAME (ctx->srecord_type) = name;
2506 544 : TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2507 544 : create_omp_child_function (ctx, true, false);
2508 : }
2509 :
2510 5262 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
2511 :
2512 5262 : if (TYPE_FIELDS (ctx->record_type) == NULL)
2513 : {
2514 1837 : ctx->record_type = ctx->receiver_decl = NULL;
2515 1837 : t = build_int_cst (long_integer_type_node, 0);
2516 1837 : gimple_omp_task_set_arg_size (stmt, t);
2517 1837 : t = build_int_cst (long_integer_type_node, 1);
2518 1837 : gimple_omp_task_set_arg_align (stmt, t);
2519 : }
2520 : }
2521 :
2522 : /* Helper function for finish_taskreg_scan, called through walk_tree.
2523 : If maybe_lookup_decl_in_outer_context returns non-NULL for some
2524 : tree, replace it in the expression. */
2525 :
2526 : static tree
2527 276 : finish_taskreg_remap (tree *tp, int *walk_subtrees, void *data)
2528 : {
2529 276 : if (VAR_P (*tp))
2530 : {
2531 96 : omp_context *ctx = (omp_context *) data;
2532 96 : tree t = maybe_lookup_decl_in_outer_ctx (*tp, ctx);
2533 96 : if (t != *tp)
2534 : {
2535 9 : if (DECL_HAS_VALUE_EXPR_P (t))
2536 0 : t = unshare_expr (DECL_VALUE_EXPR (t));
2537 9 : *tp = t;
2538 : }
2539 96 : *walk_subtrees = 0;
2540 : }
2541 180 : else if (IS_TYPE_OR_DECL_P (*tp))
2542 0 : *walk_subtrees = 0;
2543 276 : return NULL_TREE;
2544 : }
2545 :
2546 : /* If any decls have been made addressable during scan_omp,
2547 : adjust their fields if needed, and layout record types
2548 : of parallel/task constructs. */
2549 :
2550 : static void
2551 26135 : finish_taskreg_scan (omp_context *ctx)
2552 : {
2553 26135 : if (ctx->record_type == NULL_TREE)
2554 : return;
2555 :
2556 : /* If any make_addressable_vars were needed, verify all
2557 : OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK,TEAMS}
2558 : statements if use_pointer_for_field hasn't changed
2559 : because of that. If it did, update field types now. */
2560 19265 : if (make_addressable_vars)
2561 : {
2562 2211 : tree c;
2563 :
2564 12357 : for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2565 12357 : c; c = OMP_CLAUSE_CHAIN (c))
2566 10146 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2567 10146 : && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2568 : {
2569 2620 : tree decl = OMP_CLAUSE_DECL (c);
2570 :
2571 : /* Global variables don't need to be copied,
2572 : the receiver side will use them directly. */
2573 2620 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2574 282 : continue;
2575 2338 : if (!bitmap_bit_p (make_addressable_vars, DECL_UID (decl))
2576 2338 : || !use_pointer_for_field (decl, ctx))
2577 1787 : continue;
2578 551 : tree field = lookup_field (decl, ctx);
2579 551 : if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2580 551 : && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2581 497 : continue;
2582 54 : TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2583 54 : TREE_THIS_VOLATILE (field) = 0;
2584 54 : DECL_USER_ALIGN (field) = 0;
2585 54 : SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2586 54 : if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2587 16 : SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2588 54 : if (ctx->srecord_type)
2589 : {
2590 0 : tree sfield = lookup_sfield (decl, ctx);
2591 0 : TREE_TYPE (sfield) = TREE_TYPE (field);
2592 0 : TREE_THIS_VOLATILE (sfield) = 0;
2593 0 : DECL_USER_ALIGN (sfield) = 0;
2594 0 : SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2595 0 : if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2596 0 : SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2597 : }
2598 : }
2599 : }
2600 :
2601 19265 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2602 : {
2603 14618 : tree clauses = gimple_omp_parallel_clauses (ctx->stmt);
2604 14618 : tree c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
2605 14618 : if (c)
2606 : {
2607 : /* Move the _reductemp_ clause first. GOMP_parallel_reductions
2608 : expects to find it at the start of data. */
2609 67 : tree f = lookup_field (OMP_CLAUSE_DECL (c), ctx);
2610 67 : tree *p = &TYPE_FIELDS (ctx->record_type);
2611 153 : while (*p)
2612 153 : if (*p == f)
2613 : {
2614 67 : *p = DECL_CHAIN (*p);
2615 67 : break;
2616 : }
2617 : else
2618 86 : p = &DECL_CHAIN (*p);
2619 67 : DECL_CHAIN (f) = TYPE_FIELDS (ctx->record_type);
2620 67 : TYPE_FIELDS (ctx->record_type) = f;
2621 : }
2622 14618 : layout_type (ctx->record_type);
2623 14618 : fixup_child_record_type (ctx);
2624 : }
2625 4647 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2626 : {
2627 1222 : layout_type (ctx->record_type);
2628 1222 : fixup_child_record_type (ctx);
2629 : }
2630 : else
2631 : {
2632 3425 : location_t loc = gimple_location (ctx->stmt);
2633 3425 : tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2634 3425 : tree detach_clause
2635 3425 : = omp_find_clause (gimple_omp_task_clauses (ctx->stmt),
2636 : OMP_CLAUSE_DETACH);
2637 : /* Move VLA fields to the end. */
2638 3425 : p = &TYPE_FIELDS (ctx->record_type);
2639 15329 : while (*p)
2640 11904 : if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2641 11904 : || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2642 : {
2643 96 : *q = *p;
2644 96 : *p = TREE_CHAIN (*p);
2645 96 : TREE_CHAIN (*q) = NULL_TREE;
2646 96 : q = &TREE_CHAIN (*q);
2647 : }
2648 : else
2649 11808 : p = &DECL_CHAIN (*p);
2650 3425 : *p = vla_fields;
2651 3425 : if (gimple_omp_task_taskloop_p (ctx->stmt))
2652 : {
2653 : /* Move fields corresponding to first and second _looptemp_
2654 : clause first. There are filled by GOMP_taskloop
2655 : and thus need to be in specific positions. */
2656 1567 : tree clauses = gimple_omp_task_clauses (ctx->stmt);
2657 1567 : tree c1 = omp_find_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
2658 1567 : tree c2 = omp_find_clause (OMP_CLAUSE_CHAIN (c1),
2659 : OMP_CLAUSE__LOOPTEMP_);
2660 1567 : tree c3 = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
2661 1567 : tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2662 1567 : tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2663 2084 : tree f3 = c3 ? lookup_field (OMP_CLAUSE_DECL (c3), ctx) : NULL_TREE;
2664 1567 : p = &TYPE_FIELDS (ctx->record_type);
2665 8873 : while (*p)
2666 7306 : if (*p == f1 || *p == f2 || *p == f3)
2667 3651 : *p = DECL_CHAIN (*p);
2668 : else
2669 3655 : p = &DECL_CHAIN (*p);
2670 1567 : DECL_CHAIN (f1) = f2;
2671 1567 : if (c3)
2672 : {
2673 517 : DECL_CHAIN (f2) = f3;
2674 517 : DECL_CHAIN (f3) = TYPE_FIELDS (ctx->record_type);
2675 : }
2676 : else
2677 1050 : DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2678 1567 : TYPE_FIELDS (ctx->record_type) = f1;
2679 1567 : if (ctx->srecord_type)
2680 : {
2681 389 : f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2682 389 : f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2683 389 : if (c3)
2684 186 : f3 = lookup_sfield (OMP_CLAUSE_DECL (c3), ctx);
2685 389 : p = &TYPE_FIELDS (ctx->srecord_type);
2686 2099 : while (*p)
2687 1710 : if (*p == f1 || *p == f2 || *p == f3)
2688 964 : *p = DECL_CHAIN (*p);
2689 : else
2690 746 : p = &DECL_CHAIN (*p);
2691 389 : DECL_CHAIN (f1) = f2;
2692 389 : DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2693 389 : if (c3)
2694 : {
2695 186 : DECL_CHAIN (f2) = f3;
2696 186 : DECL_CHAIN (f3) = TYPE_FIELDS (ctx->srecord_type);
2697 : }
2698 : else
2699 203 : DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2700 389 : TYPE_FIELDS (ctx->srecord_type) = f1;
2701 : }
2702 : }
2703 3425 : if (detach_clause)
2704 : {
2705 189 : tree c, field;
2706 :
2707 : /* Look for a firstprivate clause with the detach event handle. */
2708 540 : for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2709 540 : c; c = OMP_CLAUSE_CHAIN (c))
2710 : {
2711 540 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
2712 347 : continue;
2713 193 : if (maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c), ctx)
2714 193 : == OMP_CLAUSE_DECL (detach_clause))
2715 : break;
2716 : }
2717 :
2718 189 : gcc_assert (c);
2719 189 : field = lookup_field (OMP_CLAUSE_DECL (c), ctx);
2720 :
2721 : /* Move field corresponding to the detach clause first.
2722 : This is filled by GOMP_task and needs to be in a
2723 : specific position. */
2724 189 : p = &TYPE_FIELDS (ctx->record_type);
2725 518 : while (*p)
2726 329 : if (*p == field)
2727 189 : *p = DECL_CHAIN (*p);
2728 : else
2729 140 : p = &DECL_CHAIN (*p);
2730 189 : DECL_CHAIN (field) = TYPE_FIELDS (ctx->record_type);
2731 189 : TYPE_FIELDS (ctx->record_type) = field;
2732 189 : if (ctx->srecord_type)
2733 : {
2734 3 : field = lookup_sfield (OMP_CLAUSE_DECL (c), ctx);
2735 3 : p = &TYPE_FIELDS (ctx->srecord_type);
2736 9 : while (*p)
2737 6 : if (*p == field)
2738 3 : *p = DECL_CHAIN (*p);
2739 : else
2740 3 : p = &DECL_CHAIN (*p);
2741 3 : DECL_CHAIN (field) = TYPE_FIELDS (ctx->srecord_type);
2742 3 : TYPE_FIELDS (ctx->srecord_type) = field;
2743 : }
2744 : }
2745 3425 : layout_type (ctx->record_type);
2746 3425 : fixup_child_record_type (ctx);
2747 3425 : if (ctx->srecord_type)
2748 544 : layout_type (ctx->srecord_type);
2749 3425 : tree t = fold_convert_loc (loc, long_integer_type_node,
2750 3425 : TYPE_SIZE_UNIT (ctx->record_type));
2751 3425 : if (TREE_CODE (t) != INTEGER_CST)
2752 : {
2753 21 : t = unshare_expr (t);
2754 21 : walk_tree (&t, finish_taskreg_remap, ctx, NULL);
2755 : }
2756 3425 : gimple_omp_task_set_arg_size (ctx->stmt, t);
2757 3425 : t = build_int_cst (long_integer_type_node,
2758 3425 : TYPE_ALIGN_UNIT (ctx->record_type));
2759 3425 : gimple_omp_task_set_arg_align (ctx->stmt, t);
2760 : }
2761 : }
2762 :
2763 : /* Find the enclosing offload context. */
2764 :
2765 : static omp_context *
2766 9665 : enclosing_target_ctx (omp_context *ctx)
2767 : {
2768 43359 : for (; ctx; ctx = ctx->outer)
2769 41745 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2770 : break;
2771 :
2772 22111 : return ctx;
2773 : }
2774 :
2775 : /* Return whether CTX's parent compute construct is an OpenACC 'kernels'
2776 : construct.
2777 : (This doesn't include OpenACC 'kernels' decomposed parts.) */
2778 :
2779 : static bool
2780 11325 : ctx_in_oacc_kernels_region (omp_context *ctx)
2781 : {
2782 39137 : for (;ctx != NULL; ctx = ctx->outer)
2783 : {
2784 29472 : gimple *stmt = ctx->stmt;
2785 29472 : if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2786 29472 : && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2787 : return true;
2788 : }
2789 :
2790 : return false;
2791 : }
2792 :
2793 : /* Check the parallelism clauses inside a OpenACC 'kernels' region.
2794 : (This doesn't include OpenACC 'kernels' decomposed parts.)
2795 : Until kernels handling moves to use the same loop indirection
2796 : scheme as parallel, we need to do this checking early. */
2797 :
2798 : static unsigned
2799 7151 : check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2800 : {
2801 7151 : bool checking = true;
2802 7151 : unsigned outer_mask = 0;
2803 7151 : unsigned this_mask = 0;
2804 7151 : bool has_seq = false, has_auto = false;
2805 :
2806 7151 : if (ctx->outer)
2807 4819 : outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2808 7151 : if (!stmt)
2809 : {
2810 4819 : checking = false;
2811 4819 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2812 : return outer_mask;
2813 1730 : stmt = as_a <gomp_for *> (ctx->stmt);
2814 : }
2815 :
2816 11330 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2817 : {
2818 7268 : switch (OMP_CLAUSE_CODE (c))
2819 : {
2820 645 : case OMP_CLAUSE_GANG:
2821 645 : this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2822 645 : break;
2823 439 : case OMP_CLAUSE_WORKER:
2824 439 : this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2825 439 : break;
2826 342 : case OMP_CLAUSE_VECTOR:
2827 342 : this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2828 342 : break;
2829 63 : case OMP_CLAUSE_SEQ:
2830 63 : has_seq = true;
2831 63 : break;
2832 94 : case OMP_CLAUSE_AUTO:
2833 94 : has_auto = true;
2834 94 : break;
2835 : default:
2836 : break;
2837 : }
2838 : }
2839 :
2840 4062 : if (checking)
2841 : {
2842 2332 : if (has_seq && (this_mask || has_auto))
2843 36 : error_at (gimple_location (stmt), "%<seq%> overrides other"
2844 : " OpenACC loop specifiers");
2845 2296 : else if (has_auto && this_mask)
2846 30 : error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2847 : " OpenACC loop specifiers");
2848 :
2849 2332 : if (this_mask & outer_mask)
2850 15 : error_at (gimple_location (stmt), "inner loop uses same"
2851 : " OpenACC parallelism as containing loop");
2852 : }
2853 :
2854 4062 : return outer_mask | this_mask;
2855 : }
2856 :
2857 : /* Scan a GIMPLE_OMP_FOR. */
2858 :
2859 : static omp_context *
2860 52725 : scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2861 : {
2862 52725 : omp_context *ctx;
2863 52725 : size_t i;
2864 52725 : tree clauses = gimple_omp_for_clauses (stmt);
2865 :
2866 52725 : ctx = new_omp_context (stmt, outer_ctx);
2867 :
2868 52725 : if (is_gimple_omp_oacc (stmt))
2869 : {
2870 12446 : omp_context *tgt = enclosing_target_ctx (outer_ctx);
2871 :
2872 12446 : if (!(tgt && is_oacc_kernels (tgt)))
2873 32251 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2874 : {
2875 22137 : tree c_op0;
2876 22137 : switch (OMP_CLAUSE_CODE (c))
2877 : {
2878 1952 : case OMP_CLAUSE_GANG:
2879 1952 : c_op0 = OMP_CLAUSE_GANG_EXPR (c);
2880 1952 : break;
2881 :
2882 1426 : case OMP_CLAUSE_WORKER:
2883 1426 : c_op0 = OMP_CLAUSE_WORKER_EXPR (c);
2884 1426 : break;
2885 :
2886 1627 : case OMP_CLAUSE_VECTOR:
2887 1627 : c_op0 = OMP_CLAUSE_VECTOR_EXPR (c);
2888 1627 : break;
2889 :
2890 17132 : default:
2891 17132 : continue;
2892 : }
2893 :
2894 5005 : if (c_op0)
2895 : {
2896 : /* By construction, this is impossible for OpenACC 'kernels'
2897 : decomposed parts. */
2898 210 : gcc_assert (!(tgt && is_oacc_kernels_decomposed_part (tgt)));
2899 :
2900 210 : error_at (OMP_CLAUSE_LOCATION (c),
2901 : "argument not permitted on %qs clause",
2902 210 : omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
2903 210 : if (tgt)
2904 180 : inform (gimple_location (tgt->stmt),
2905 : "enclosing parent compute construct");
2906 30 : else if (oacc_get_fn_attrib (current_function_decl))
2907 30 : inform (DECL_SOURCE_LOCATION (current_function_decl),
2908 : "enclosing routine");
2909 : else
2910 0 : gcc_unreachable ();
2911 : }
2912 : }
2913 :
2914 12446 : if (tgt && is_oacc_kernels (tgt))
2915 2332 : check_oacc_kernel_gwv (stmt, ctx);
2916 :
2917 : /* Collect all variables named in reductions on this loop. Ensure
2918 : that, if this loop has a reduction on some variable v, and there is
2919 : a reduction on v somewhere in an outer context, then there is a
2920 : reduction on v on all intervening loops as well. */
2921 12446 : tree local_reduction_clauses = NULL;
2922 39374 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2923 : {
2924 26928 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2925 4712 : local_reduction_clauses
2926 4712 : = tree_cons (NULL, c, local_reduction_clauses);
2927 : }
2928 12446 : if (ctx->outer_reduction_clauses == NULL && ctx->outer != NULL)
2929 11920 : ctx->outer_reduction_clauses
2930 11920 : = chainon (unshare_expr (ctx->outer->local_reduction_clauses),
2931 : ctx->outer->outer_reduction_clauses);
2932 12446 : tree outer_reduction_clauses = ctx->outer_reduction_clauses;
2933 12446 : tree local_iter = local_reduction_clauses;
2934 17158 : for (; local_iter; local_iter = TREE_CHAIN (local_iter))
2935 : {
2936 4712 : tree local_clause = TREE_VALUE (local_iter);
2937 4712 : tree local_var = OMP_CLAUSE_DECL (local_clause);
2938 4712 : tree_code local_op = OMP_CLAUSE_REDUCTION_CODE (local_clause);
2939 4712 : bool have_outer_reduction = false;
2940 4712 : tree ctx_iter = outer_reduction_clauses;
2941 5826 : for (; ctx_iter; ctx_iter = TREE_CHAIN (ctx_iter))
2942 : {
2943 3325 : tree outer_clause = TREE_VALUE (ctx_iter);
2944 3325 : tree outer_var = OMP_CLAUSE_DECL (outer_clause);
2945 3325 : tree_code outer_op = OMP_CLAUSE_REDUCTION_CODE (outer_clause);
2946 3325 : if (outer_var == local_var && outer_op != local_op)
2947 : {
2948 535 : if (warning_at (OMP_CLAUSE_LOCATION (local_clause),
2949 535 : OPT_Wopenmp, "conflicting reduction "
2950 : "operations for %qE",
2951 : local_var))
2952 535 : inform (OMP_CLAUSE_LOCATION (outer_clause),
2953 : "location of the previous reduction for %qE",
2954 : outer_var);
2955 : }
2956 3325 : if (outer_var == local_var)
2957 : {
2958 : have_outer_reduction = true;
2959 : break;
2960 : }
2961 : }
2962 4712 : if (have_outer_reduction)
2963 : {
2964 : /* There is a reduction on outer_var both on this loop and on
2965 : some enclosing loop. Walk up the context tree until such a
2966 : loop with a reduction on outer_var is found, and complain
2967 : about all intervening loops that do not have such a
2968 : reduction. */
2969 2211 : struct omp_context *curr_loop = ctx->outer;
2970 2211 : bool found = false;
2971 2826 : while (curr_loop != NULL)
2972 : {
2973 2826 : tree curr_iter = curr_loop->local_reduction_clauses;
2974 3460 : for (; curr_iter; curr_iter = TREE_CHAIN (curr_iter))
2975 : {
2976 2845 : tree curr_clause = TREE_VALUE (curr_iter);
2977 2845 : tree curr_var = OMP_CLAUSE_DECL (curr_clause);
2978 2845 : if (curr_var == local_var)
2979 : {
2980 : found = true;
2981 : break;
2982 : }
2983 : }
2984 2826 : if (!found)
2985 615 : warning_at (gimple_location (curr_loop->stmt), OPT_Wopenmp,
2986 : "nested loop in reduction needs "
2987 : "reduction clause for %qE",
2988 : local_var);
2989 : else
2990 : break;
2991 615 : curr_loop = curr_loop->outer;
2992 : }
2993 : }
2994 : }
2995 12446 : ctx->local_reduction_clauses = local_reduction_clauses;
2996 12446 : ctx->outer_reduction_clauses
2997 12446 : = chainon (unshare_expr (ctx->local_reduction_clauses),
2998 : ctx->outer_reduction_clauses);
2999 :
3000 12446 : if (tgt && is_oacc_kernels (tgt))
3001 : {
3002 : /* Strip out reductions, as they are not handled yet. */
3003 : tree *prev_ptr = &clauses;
3004 :
3005 7123 : while (tree probe = *prev_ptr)
3006 : {
3007 4791 : tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3008 :
3009 4791 : if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3010 718 : *prev_ptr = *next_ptr;
3011 : else
3012 : prev_ptr = next_ptr;
3013 : }
3014 :
3015 2332 : gimple_omp_for_set_clauses (stmt, clauses);
3016 : }
3017 : }
3018 :
3019 52725 : scan_sharing_clauses (clauses, ctx);
3020 :
3021 52725 : scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3022 180213 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3023 : {
3024 74763 : scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3025 74763 : scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3026 74763 : scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3027 74763 : scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3028 : }
3029 52725 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3030 52725 : return ctx;
3031 : }
3032 :
3033 : /* Duplicate #pragma omp simd, one for SIMT, another one for SIMD. */
3034 :
3035 : static void
3036 0 : scan_omp_simd (gimple_stmt_iterator *gsi, gomp_for *stmt,
3037 : omp_context *outer_ctx)
3038 : {
3039 0 : gbind *bind = gimple_build_bind (NULL, NULL, NULL);
3040 0 : gsi_replace (gsi, bind, false);
3041 0 : gimple_seq seq = NULL;
3042 0 : gimple *g = gimple_build_call_internal (IFN_GOMP_USE_SIMT, 0);
3043 0 : tree cond = create_tmp_var_raw (integer_type_node);
3044 0 : DECL_CONTEXT (cond) = current_function_decl;
3045 0 : DECL_SEEN_IN_BIND_EXPR_P (cond) = 1;
3046 0 : gimple_bind_set_vars (bind, cond);
3047 0 : gimple_call_set_lhs (g, cond);
3048 0 : gimple_seq_add_stmt (&seq, g);
3049 0 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
3050 0 : tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
3051 0 : tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
3052 0 : g = gimple_build_cond (NE_EXPR, cond, integer_zero_node, lab1, lab2);
3053 0 : gimple_seq_add_stmt (&seq, g);
3054 0 : g = gimple_build_label (lab1);
3055 0 : gimple_seq_add_stmt (&seq, g);
3056 0 : gimple_seq new_seq = copy_gimple_seq_and_replace_locals (stmt);
3057 0 : gomp_for *new_stmt = as_a <gomp_for *> (new_seq);
3058 0 : tree clause = build_omp_clause (gimple_location (stmt), OMP_CLAUSE__SIMT_);
3059 0 : OMP_CLAUSE_CHAIN (clause) = gimple_omp_for_clauses (new_stmt);
3060 0 : gimple_omp_for_set_clauses (new_stmt, clause);
3061 0 : gimple_seq_add_stmt (&seq, new_stmt);
3062 0 : g = gimple_build_goto (lab3);
3063 0 : gimple_seq_add_stmt (&seq, g);
3064 0 : g = gimple_build_label (lab2);
3065 0 : gimple_seq_add_stmt (&seq, g);
3066 0 : gimple_seq_add_stmt (&seq, stmt);
3067 0 : g = gimple_build_label (lab3);
3068 0 : gimple_seq_add_stmt (&seq, g);
3069 0 : gimple_bind_set_body (bind, seq);
3070 0 : update_stmt (bind);
3071 0 : scan_omp_for (new_stmt, outer_ctx);
3072 0 : scan_omp_for (stmt, outer_ctx)->simt_stmt = new_stmt;
3073 0 : }
3074 :
3075 : static tree omp_find_scan (gimple_stmt_iterator *, bool *,
3076 : struct walk_stmt_info *);
3077 : static omp_context *maybe_lookup_ctx (gimple *);
3078 :
3079 : /* Duplicate #pragma omp simd, one for the scan input phase loop and one
3080 : for scan phase loop. */
3081 :
3082 : static void
3083 83 : scan_omp_simd_scan (gimple_stmt_iterator *gsi, gomp_for *stmt,
3084 : omp_context *outer_ctx)
3085 : {
3086 : /* The only change between inclusive and exclusive scan will be
3087 : within the first simd loop, so just use inclusive in the
3088 : worksharing loop. */
3089 83 : outer_ctx->scan_inclusive = true;
3090 83 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_INCLUSIVE);
3091 83 : OMP_CLAUSE_DECL (c) = integer_zero_node;
3092 :
3093 83 : gomp_scan *input_stmt = gimple_build_omp_scan (NULL, NULL_TREE);
3094 83 : gomp_scan *scan_stmt = gimple_build_omp_scan (NULL, c);
3095 83 : gsi_replace (gsi, input_stmt, false);
3096 83 : gimple_seq input_body = NULL;
3097 83 : gimple_seq_add_stmt (&input_body, stmt);
3098 83 : gsi_insert_after (gsi, scan_stmt, GSI_NEW_STMT);
3099 :
3100 83 : gimple_stmt_iterator input1_gsi = gsi_none ();
3101 83 : struct walk_stmt_info wi;
3102 83 : memset (&wi, 0, sizeof (wi));
3103 83 : wi.val_only = true;
3104 83 : wi.info = (void *) &input1_gsi;
3105 83 : walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), omp_find_scan, NULL, &wi);
3106 83 : gcc_assert (!gsi_end_p (input1_gsi));
3107 :
3108 83 : gimple *input_stmt1 = gsi_stmt (input1_gsi);
3109 83 : gsi_next (&input1_gsi);
3110 83 : gimple *scan_stmt1 = gsi_stmt (input1_gsi);
3111 83 : gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN);
3112 83 : c = gimple_omp_scan_clauses (as_a <gomp_scan *> (scan_stmt1));
3113 166 : if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE)
3114 : std::swap (input_stmt1, scan_stmt1);
3115 :
3116 83 : gimple_seq input_body1 = gimple_omp_body (input_stmt1);
3117 83 : gimple_omp_set_body (input_stmt1, NULL);
3118 :
3119 83 : gimple_seq scan_body = copy_gimple_seq_and_replace_locals (stmt);
3120 83 : gomp_for *new_stmt = as_a <gomp_for *> (scan_body);
3121 :
3122 83 : gimple_omp_set_body (input_stmt1, input_body1);
3123 83 : gimple_omp_set_body (scan_stmt1, NULL);
3124 :
3125 83 : gimple_stmt_iterator input2_gsi = gsi_none ();
3126 83 : memset (&wi, 0, sizeof (wi));
3127 83 : wi.val_only = true;
3128 83 : wi.info = (void *) &input2_gsi;
3129 83 : walk_gimple_seq_mod (gimple_omp_body_ptr (new_stmt), omp_find_scan,
3130 : NULL, &wi);
3131 83 : gcc_assert (!gsi_end_p (input2_gsi));
3132 :
3133 83 : gimple *input_stmt2 = gsi_stmt (input2_gsi);
3134 83 : gsi_next (&input2_gsi);
3135 83 : gimple *scan_stmt2 = gsi_stmt (input2_gsi);
3136 83 : gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN);
3137 166 : if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_EXCLUSIVE)
3138 : std::swap (input_stmt2, scan_stmt2);
3139 :
3140 83 : gimple_omp_set_body (input_stmt2, NULL);
3141 :
3142 83 : gimple_omp_set_body (input_stmt, input_body);
3143 83 : gimple_omp_set_body (scan_stmt, scan_body);
3144 :
3145 83 : omp_context *ctx = new_omp_context (input_stmt, outer_ctx);
3146 83 : scan_omp (gimple_omp_body_ptr (input_stmt), ctx);
3147 :
3148 83 : ctx = new_omp_context (scan_stmt, outer_ctx);
3149 83 : scan_omp (gimple_omp_body_ptr (scan_stmt), ctx);
3150 :
3151 83 : maybe_lookup_ctx (new_stmt)->for_simd_scan_phase = true;
3152 83 : }
3153 :
3154 : /* Scan an OpenMP sections directive. */
3155 :
3156 : static void
3157 589 : scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3158 : {
3159 589 : omp_context *ctx;
3160 :
3161 589 : ctx = new_omp_context (stmt, outer_ctx);
3162 589 : scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3163 589 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3164 589 : }
3165 :
3166 : /* Scan an OpenMP single directive. */
3167 :
3168 : static void
3169 1236 : scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3170 : {
3171 1236 : omp_context *ctx;
3172 1236 : tree name;
3173 :
3174 1236 : ctx = new_omp_context (stmt, outer_ctx);
3175 1236 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3176 1236 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3177 1236 : name = create_tmp_var_name (".omp_copy_s");
3178 1236 : name = build_decl (gimple_location (stmt),
3179 : TYPE_DECL, name, ctx->record_type);
3180 1236 : TYPE_NAME (ctx->record_type) = name;
3181 :
3182 1236 : scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3183 1236 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3184 :
3185 1236 : if (TYPE_FIELDS (ctx->record_type) == NULL)
3186 1089 : ctx->record_type = NULL;
3187 : else
3188 147 : layout_type (ctx->record_type);
3189 1236 : }
3190 :
3191 : /* Scan a GIMPLE_OMP_TARGET. */
3192 :
3193 : static void
3194 41865 : scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3195 : {
3196 41865 : omp_context *ctx;
3197 41865 : tree name;
3198 41865 : bool offloaded = is_gimple_omp_offloaded (stmt);
3199 41865 : tree clauses = gimple_omp_target_clauses (stmt);
3200 :
3201 41865 : ctx = new_omp_context (stmt, outer_ctx);
3202 41865 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3203 41865 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3204 41865 : name = create_tmp_var_name (".omp_data_t");
3205 41865 : name = build_decl (gimple_location (stmt),
3206 : TYPE_DECL, name, ctx->record_type);
3207 41865 : DECL_ARTIFICIAL (name) = 1;
3208 41865 : DECL_NAMELESS (name) = 1;
3209 41865 : TYPE_NAME (ctx->record_type) = name;
3210 41865 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
3211 :
3212 41865 : if (offloaded)
3213 : {
3214 24836 : tree c = omp_find_clause (clauses, OMP_CLAUSE_DEVICE_TYPE);
3215 24836 : bool host_only
3216 24836 : = c && OMP_CLAUSE_DEVICE_TYPE_KIND (c) == OMP_CLAUSE_DEVICE_TYPE_HOST;
3217 24836 : create_omp_child_function (ctx, false, host_only);
3218 24836 : gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3219 : }
3220 :
3221 41865 : scan_sharing_clauses (clauses, ctx);
3222 41865 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3223 :
3224 41865 : if (TYPE_FIELDS (ctx->record_type) == NULL)
3225 7768 : ctx->record_type = ctx->receiver_decl = NULL;
3226 : else
3227 : {
3228 34097 : TYPE_FIELDS (ctx->record_type)
3229 34097 : = nreverse (TYPE_FIELDS (ctx->record_type));
3230 34097 : if (flag_checking)
3231 : {
3232 34097 : unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3233 34097 : for (tree field = TYPE_FIELDS (ctx->record_type);
3234 131392 : field;
3235 97295 : field = DECL_CHAIN (field))
3236 97295 : gcc_assert (DECL_ALIGN (field) == align);
3237 : }
3238 34097 : layout_type (ctx->record_type);
3239 34097 : if (offloaded)
3240 17627 : fixup_child_record_type (ctx);
3241 : }
3242 :
3243 41865 : if (ctx->teams_nested_p && ctx->nonteams_nested_p)
3244 : {
3245 4 : error_at (gimple_location (stmt),
3246 : "%<target%> construct with nested %<teams%> construct "
3247 : "contains directives outside of the %<teams%> construct");
3248 4 : gimple_omp_set_body (stmt, gimple_build_bind (NULL, NULL, NULL));
3249 : }
3250 41865 : }
3251 :
3252 : /* Scan an OpenMP teams directive. */
3253 :
3254 : static void
3255 8797 : scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3256 : {
3257 8797 : omp_context *ctx = new_omp_context (stmt, outer_ctx);
3258 :
3259 8797 : if (!gimple_omp_teams_host (stmt))
3260 : {
3261 6126 : scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3262 6126 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3263 6126 : return;
3264 : }
3265 2671 : taskreg_contexts.safe_push (ctx);
3266 2671 : gcc_assert (taskreg_nesting_level == 1);
3267 2671 : ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3268 2671 : ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3269 2671 : tree name = create_tmp_var_name (".omp_data_s");
3270 2671 : name = build_decl (gimple_location (stmt),
3271 : TYPE_DECL, name, ctx->record_type);
3272 2671 : DECL_ARTIFICIAL (name) = 1;
3273 2671 : DECL_NAMELESS (name) = 1;
3274 2671 : TYPE_NAME (ctx->record_type) = name;
3275 2671 : TYPE_ARTIFICIAL (ctx->record_type) = 1;
3276 2671 : create_omp_child_function (ctx, false, false);
3277 2671 : gimple_omp_teams_set_child_fn (stmt, ctx->cb.dst_fn);
3278 :
3279 2671 : scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3280 2671 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
3281 :
3282 2671 : if (TYPE_FIELDS (ctx->record_type) == NULL)
3283 1449 : ctx->record_type = ctx->receiver_decl = NULL;
3284 : }
3285 :
3286 : /* Check nesting restrictions. */
3287 : static bool
3288 157188 : check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3289 : {
3290 157188 : tree c;
3291 :
3292 : /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3293 : inside an OpenACC CTX. */
3294 157188 : if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3295 157188 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)
3296 : /* ..., except for the atomic codes that OpenACC shares with OpenMP. */
3297 : ;
3298 282499 : else if (!(is_gimple_omp (stmt)
3299 139139 : && is_gimple_omp_oacc (stmt)))
3300 : {
3301 113096 : if (oacc_get_fn_attrib (cfun->decl) != NULL)
3302 : {
3303 48 : error_at (gimple_location (stmt),
3304 : "non-OpenACC construct inside of OpenACC routine");
3305 48 : return false;
3306 : }
3307 : else
3308 236650 : for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3309 247380 : if (is_gimple_omp (octx->stmt)
3310 123778 : && is_gimple_omp_oacc (octx->stmt))
3311 : {
3312 176 : error_at (gimple_location (stmt),
3313 : "non-OpenACC construct inside of OpenACC region");
3314 176 : return false;
3315 : }
3316 : }
3317 :
3318 156964 : if (ctx != NULL)
3319 : {
3320 84256 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
3321 84256 : && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
3322 : {
3323 8335 : c = omp_find_clause (gimple_omp_target_clauses (ctx->stmt),
3324 : OMP_CLAUSE_DEVICE);
3325 8335 : if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
3326 : {
3327 9 : error_at (gimple_location (stmt),
3328 : "OpenMP constructs are not allowed in target region "
3329 : "with %<ancestor%>");
3330 9 : return false;
3331 : }
3332 :
3333 8326 : if (gimple_code (stmt) == GIMPLE_OMP_TEAMS && !ctx->teams_nested_p)
3334 6122 : ctx->teams_nested_p = true;
3335 : else
3336 2204 : ctx->nonteams_nested_p = true;
3337 : }
3338 84247 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN
3339 172 : && ctx->outer
3340 84419 : && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
3341 : ctx = ctx->outer;
3342 84247 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3343 28325 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
3344 86056 : && !ctx->loop_p)
3345 : {
3346 1589 : c = NULL_TREE;
3347 1589 : if (ctx->order_concurrent
3348 1589 : && (gimple_code (stmt) == GIMPLE_OMP_ORDERED
3349 280 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3350 190 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3351 : {
3352 210 : error_at (gimple_location (stmt),
3353 : "OpenMP constructs other than %<parallel%>, %<loop%>"
3354 : " or %<simd%> may not be nested inside a region with"
3355 : " the %<order(concurrent)%> clause");
3356 210 : return false;
3357 : }
3358 1379 : if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3359 : {
3360 133 : c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3361 133 : if (omp_find_clause (c, OMP_CLAUSE_SIMD))
3362 : {
3363 133 : if (omp_find_clause (c, OMP_CLAUSE_THREADS)
3364 133 : && (ctx->outer == NULL
3365 29 : || !gimple_omp_for_combined_into_p (ctx->stmt)
3366 25 : || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3367 25 : || (gimple_omp_for_kind (ctx->outer->stmt)
3368 : != GF_OMP_FOR_KIND_FOR)
3369 25 : || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3370 : {
3371 8 : error_at (gimple_location (stmt),
3372 : "%<ordered simd threads%> must be closely "
3373 : "nested inside of %<%s simd%> region",
3374 8 : lang_GNU_Fortran () ? "do" : "for");
3375 8 : return false;
3376 : }
3377 : return true;
3378 : }
3379 : }
3380 : else if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3381 : || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE
3382 : || gimple_code (stmt) == GIMPLE_OMP_SCAN
3383 : || gimple_code (stmt) == GIMPLE_OMP_STRUCTURED_BLOCK)
3384 : return true;
3385 : else if (gimple_code (stmt) == GIMPLE_OMP_FOR
3386 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
3387 : return true;
3388 60 : error_at (gimple_location (stmt),
3389 : "OpenMP constructs other than "
3390 : "%<ordered simd%>, %<simd%>, %<loop%> or %<atomic%> may "
3391 : "not be nested inside %<simd%> region");
3392 60 : return false;
3393 : }
3394 82658 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3395 : {
3396 5873 : if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3397 5555 : || (gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_DISTRIBUTE
3398 25 : && omp_find_clause (gimple_omp_for_clauses (stmt),
3399 : OMP_CLAUSE_BIND) == NULL_TREE))
3400 5889 : && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3401 : {
3402 132 : error_at (gimple_location (stmt),
3403 : "only %<distribute%>, %<parallel%> or %<loop%> "
3404 : "regions are allowed to be strictly nested inside "
3405 : "%<teams%> region");
3406 132 : return false;
3407 : }
3408 : }
3409 76785 : else if (ctx->order_concurrent
3410 1944 : && gimple_code (stmt) != GIMPLE_OMP_PARALLEL
3411 1465 : && (gimple_code (stmt) != GIMPLE_OMP_FOR
3412 1191 : || gimple_omp_for_kind (stmt) != GF_OMP_FOR_KIND_SIMD)
3413 289 : && gimple_code (stmt) != GIMPLE_OMP_SCAN
3414 77074 : && gimple_code (stmt) != GIMPLE_OMP_STRUCTURED_BLOCK)
3415 : {
3416 285 : if (ctx->loop_p)
3417 135 : error_at (gimple_location (stmt),
3418 : "OpenMP constructs other than %<parallel%>, %<loop%> or "
3419 : "%<simd%> may not be nested inside a %<loop%> region");
3420 : else
3421 150 : error_at (gimple_location (stmt),
3422 : "OpenMP constructs other than %<parallel%>, %<loop%> or "
3423 : "%<simd%> may not be nested inside a region with "
3424 : "the %<order(concurrent)%> clause");
3425 285 : return false;
3426 : }
3427 : }
3428 154949 : switch (gimple_code (stmt))
3429 : {
3430 52844 : case GIMPLE_OMP_FOR:
3431 52844 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD)
3432 : return true;
3433 42083 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3434 : {
3435 8247 : if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3436 : {
3437 0 : error_at (gimple_location (stmt),
3438 : "%<distribute%> region must be strictly nested "
3439 : "inside %<teams%> construct");
3440 0 : return false;
3441 : }
3442 : return true;
3443 : }
3444 : /* We split taskloop into task and nested taskloop in it. */
3445 33836 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3446 : return true;
3447 : /* For now, hope this will change and loop bind(parallel) will not
3448 : be allowed in lots of contexts. */
3449 30702 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
3450 48893 : && omp_find_clause (gimple_omp_for_clauses (stmt), OMP_CLAUSE_BIND))
3451 : return true;
3452 30073 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3453 : {
3454 12511 : bool ok = false;
3455 :
3456 12511 : if (ctx)
3457 11964 : switch (gimple_code (ctx->stmt))
3458 : {
3459 4049 : case GIMPLE_OMP_FOR:
3460 4049 : ok = (gimple_omp_for_kind (ctx->stmt)
3461 : == GF_OMP_FOR_KIND_OACC_LOOP);
3462 4049 : break;
3463 :
3464 7887 : case GIMPLE_OMP_TARGET:
3465 7887 : switch (gimple_omp_target_kind (ctx->stmt))
3466 : {
3467 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3468 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
3469 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
3470 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3471 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3472 : ok = true;
3473 : break;
3474 :
3475 : default:
3476 : break;
3477 : }
3478 :
3479 : default:
3480 : break;
3481 : }
3482 547 : else if (oacc_get_fn_attrib (current_function_decl))
3483 : ok = true;
3484 4049 : if (!ok)
3485 : {
3486 65 : error_at (gimple_location (stmt),
3487 : "OpenACC loop directive must be associated with"
3488 : " an OpenACC compute region");
3489 65 : return false;
3490 : }
3491 : }
3492 : /* FALLTHRU */
3493 34169 : case GIMPLE_CALL:
3494 34169 : if (is_gimple_call (stmt)
3495 34169 : && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3496 : == BUILT_IN_GOMP_CANCEL
3497 3057 : || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3498 : == BUILT_IN_GOMP_CANCELLATION_POINT))
3499 : {
3500 1907 : const char *bad = NULL;
3501 1907 : const char *kind = NULL;
3502 1907 : const char *construct
3503 1907 : = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3504 : == BUILT_IN_GOMP_CANCEL)
3505 1907 : ? "cancel"
3506 803 : : "cancellation point";
3507 1907 : if (ctx == NULL)
3508 : {
3509 41 : error_at (gimple_location (stmt), "orphaned %qs construct",
3510 : construct);
3511 41 : return false;
3512 : }
3513 1866 : switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3514 1866 : ? tree_to_shwi (gimple_call_arg (stmt, 0))
3515 : : 0)
3516 : {
3517 528 : case 1:
3518 528 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3519 : bad = "parallel";
3520 208 : else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3521 : == BUILT_IN_GOMP_CANCEL
3522 208 : && !integer_zerop (gimple_call_arg (stmt, 1)))
3523 164 : ctx->cancellable = true;
3524 164 : kind = "parallel";
3525 164 : break;
3526 427 : case 2:
3527 427 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3528 427 : || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3529 : bad = "for";
3530 117 : else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3531 : == BUILT_IN_GOMP_CANCEL
3532 117 : && !integer_zerop (gimple_call_arg (stmt, 1)))
3533 : {
3534 106 : ctx->cancellable = true;
3535 106 : if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3536 : OMP_CLAUSE_NOWAIT))
3537 5 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3538 : "%<cancel for%> inside "
3539 : "%<nowait%> for construct");
3540 106 : if (omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3541 : OMP_CLAUSE_ORDERED))
3542 5 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3543 : "%<cancel for%> inside "
3544 : "%<ordered%> for construct");
3545 : }
3546 5 : kind = "for";
3547 5 : break;
3548 383 : case 4:
3549 383 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3550 383 : && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3551 : bad = "sections";
3552 93 : else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3553 : == BUILT_IN_GOMP_CANCEL
3554 93 : && !integer_zerop (gimple_call_arg (stmt, 1)))
3555 : {
3556 73 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3557 : {
3558 0 : ctx->cancellable = true;
3559 0 : if (omp_find_clause (gimple_omp_sections_clauses
3560 0 : (ctx->stmt),
3561 : OMP_CLAUSE_NOWAIT))
3562 0 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3563 : "%<cancel sections%> inside "
3564 : "%<nowait%> sections construct");
3565 : }
3566 : else
3567 : {
3568 73 : gcc_assert (ctx->outer
3569 : && gimple_code (ctx->outer->stmt)
3570 : == GIMPLE_OMP_SECTIONS);
3571 73 : ctx->outer->cancellable = true;
3572 73 : if (omp_find_clause (gimple_omp_sections_clauses
3573 73 : (ctx->outer->stmt),
3574 : OMP_CLAUSE_NOWAIT))
3575 10 : warning_at (gimple_location (stmt), OPT_Wopenmp,
3576 : "%<cancel sections%> inside "
3577 : "%<nowait%> sections construct");
3578 : }
3579 : }
3580 10 : kind = "sections";
3581 10 : break;
3582 528 : case 8:
3583 528 : if (!is_task_ctx (ctx)
3584 528 : && (!is_taskloop_ctx (ctx)
3585 54 : || ctx->outer == NULL
3586 54 : || !is_task_ctx (ctx->outer)))
3587 : bad = "task";
3588 : else
3589 : {
3590 248 : for (omp_context *octx = ctx->outer;
3591 439 : octx; octx = octx->outer)
3592 : {
3593 425 : switch (gimple_code (octx->stmt))
3594 : {
3595 : case GIMPLE_OMP_TASKGROUP:
3596 : break;
3597 40 : case GIMPLE_OMP_TARGET:
3598 40 : if (gimple_omp_target_kind (octx->stmt)
3599 : != GF_OMP_TARGET_KIND_REGION)
3600 20 : continue;
3601 : /* FALLTHRU */
3602 99 : case GIMPLE_OMP_PARALLEL:
3603 99 : case GIMPLE_OMP_TEAMS:
3604 99 : error_at (gimple_location (stmt),
3605 : "%<%s taskgroup%> construct not closely "
3606 : "nested inside of %<taskgroup%> region",
3607 : construct);
3608 99 : return false;
3609 104 : case GIMPLE_OMP_TASK:
3610 104 : if (gimple_omp_task_taskloop_p (octx->stmt)
3611 94 : && octx->outer
3612 198 : && is_taskloop_ctx (octx->outer))
3613 : {
3614 94 : tree clauses
3615 94 : = gimple_omp_for_clauses (octx->outer->stmt);
3616 94 : if (!omp_find_clause (clauses, OMP_CLAUSE_NOGROUP))
3617 : break;
3618 : }
3619 60 : continue;
3620 111 : default:
3621 111 : continue;
3622 171 : }
3623 : break;
3624 : }
3625 149 : ctx->cancellable = true;
3626 : }
3627 149 : kind = "taskgroup";
3628 149 : break;
3629 0 : default:
3630 0 : error_at (gimple_location (stmt), "invalid arguments");
3631 0 : return false;
3632 : }
3633 328 : if (bad)
3634 : {
3635 1200 : error_at (gimple_location (stmt),
3636 : "%<%s %s%> construct not closely nested inside of %qs",
3637 : construct, kind, bad);
3638 1200 : return false;
3639 : }
3640 : }
3641 : /* FALLTHRU */
3642 : case GIMPLE_OMP_SECTIONS:
3643 : case GIMPLE_OMP_SINGLE:
3644 55645 : for (; ctx != NULL; ctx = ctx->outer)
3645 37534 : switch (gimple_code (ctx->stmt))
3646 : {
3647 6873 : case GIMPLE_OMP_FOR:
3648 6873 : if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3649 6873 : && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3650 : break;
3651 : /* FALLTHRU */
3652 778 : case GIMPLE_OMP_SECTIONS:
3653 778 : case GIMPLE_OMP_SINGLE:
3654 778 : case GIMPLE_OMP_ORDERED:
3655 778 : case GIMPLE_OMP_MASTER:
3656 778 : case GIMPLE_OMP_MASKED:
3657 778 : case GIMPLE_OMP_TASK:
3658 778 : case GIMPLE_OMP_CRITICAL:
3659 778 : if (is_gimple_call (stmt))
3660 : {
3661 707 : if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3662 : != BUILT_IN_GOMP_BARRIER)
3663 : return true;
3664 23 : error_at (gimple_location (stmt),
3665 : "barrier region may not be closely nested inside "
3666 : "of work-sharing, %<loop%>, %<critical%>, "
3667 : "%<ordered%>, %<master%>, %<masked%>, explicit "
3668 : "%<task%> or %<taskloop%> region");
3669 23 : return false;
3670 : }
3671 71 : error_at (gimple_location (stmt),
3672 : "work-sharing region may not be closely nested inside "
3673 : "of work-sharing, %<loop%>, %<critical%>, %<ordered%>, "
3674 : "%<master%>, %<masked%>, explicit %<task%> or "
3675 : "%<taskloop%> region");
3676 71 : return false;
3677 : case GIMPLE_OMP_PARALLEL:
3678 : case GIMPLE_OMP_TEAMS:
3679 : return true;
3680 13437 : case GIMPLE_OMP_TARGET:
3681 13437 : if (gimple_omp_target_kind (ctx->stmt)
3682 : == GF_OMP_TARGET_KIND_REGION)
3683 : return true;
3684 : break;
3685 : default:
3686 : break;
3687 : }
3688 : break;
3689 : case GIMPLE_OMP_MASTER:
3690 : case GIMPLE_OMP_MASKED:
3691 1523 : for (; ctx != NULL; ctx = ctx->outer)
3692 1014 : switch (gimple_code (ctx->stmt))
3693 : {
3694 14 : case GIMPLE_OMP_FOR:
3695 14 : if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3696 14 : && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3697 : break;
3698 : /* FALLTHRU */
3699 30 : case GIMPLE_OMP_SECTIONS:
3700 30 : case GIMPLE_OMP_SINGLE:
3701 30 : case GIMPLE_OMP_TASK:
3702 60 : error_at (gimple_location (stmt),
3703 : "%qs region may not be closely nested inside "
3704 : "of work-sharing, %<loop%>, explicit %<task%> or "
3705 : "%<taskloop%> region",
3706 30 : gimple_code (stmt) == GIMPLE_OMP_MASTER
3707 : ? "master" : "masked");
3708 30 : return false;
3709 : case GIMPLE_OMP_PARALLEL:
3710 : case GIMPLE_OMP_TEAMS:
3711 : return true;
3712 10 : case GIMPLE_OMP_TARGET:
3713 10 : if (gimple_omp_target_kind (ctx->stmt)
3714 : == GF_OMP_TARGET_KIND_REGION)
3715 : return true;
3716 : break;
3717 : default:
3718 : break;
3719 : }
3720 : break;
3721 : case GIMPLE_OMP_SCOPE:
3722 302 : for (; ctx != NULL; ctx = ctx->outer)
3723 183 : switch (gimple_code (ctx->stmt))
3724 : {
3725 7 : case GIMPLE_OMP_FOR:
3726 7 : if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3727 7 : && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3728 : break;
3729 : /* FALLTHRU */
3730 25 : case GIMPLE_OMP_SECTIONS:
3731 25 : case GIMPLE_OMP_SINGLE:
3732 25 : case GIMPLE_OMP_TASK:
3733 25 : case GIMPLE_OMP_CRITICAL:
3734 25 : case GIMPLE_OMP_ORDERED:
3735 25 : case GIMPLE_OMP_MASTER:
3736 25 : case GIMPLE_OMP_MASKED:
3737 25 : error_at (gimple_location (stmt),
3738 : "%<scope%> region may not be closely nested inside "
3739 : "of work-sharing, %<loop%>, explicit %<task%>, "
3740 : "%<taskloop%>, %<critical%>, %<ordered%>, %<master%>, "
3741 : "or %<masked%> region");
3742 25 : return false;
3743 : case GIMPLE_OMP_PARALLEL:
3744 : case GIMPLE_OMP_TEAMS:
3745 : return true;
3746 5 : case GIMPLE_OMP_TARGET:
3747 5 : if (gimple_omp_target_kind (ctx->stmt)
3748 : == GF_OMP_TARGET_KIND_REGION)
3749 : return true;
3750 : break;
3751 : default:
3752 : break;
3753 : }
3754 : break;
3755 5378 : case GIMPLE_OMP_TASK:
3756 22942 : for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3757 17568 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
3758 : {
3759 4 : enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
3760 4 : error_at (OMP_CLAUSE_LOCATION (c),
3761 : "%<%s(%s)%> is only allowed in %<omp ordered%>",
3762 4 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross",
3763 : kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
3764 4 : return false;
3765 : }
3766 : break;
3767 1631 : case GIMPLE_OMP_ORDERED:
3768 2873 : for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3769 2873 : c; c = OMP_CLAUSE_CHAIN (c))
3770 : {
3771 1258 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS)
3772 : {
3773 169 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
3774 : {
3775 4 : error_at (OMP_CLAUSE_LOCATION (c),
3776 : "invalid depend kind in omp %<ordered%> %<depend%>");
3777 4 : return false;
3778 : }
3779 165 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3780 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3781 165 : continue;
3782 : }
3783 :
3784 1089 : tree oclause;
3785 : /* Look for containing ordered(N) loop. */
3786 1089 : if (ctx == NULL
3787 1077 : || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3788 1089 : || (oclause
3789 1077 : = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3790 : OMP_CLAUSE_ORDERED)) == NULL_TREE)
3791 : {
3792 12 : error_at (OMP_CLAUSE_LOCATION (c),
3793 : "%<ordered%> construct with %<depend%> clause "
3794 : "must be closely nested inside an %<ordered%> loop");
3795 12 : return false;
3796 : }
3797 : }
3798 1615 : c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3799 1615 : if (omp_find_clause (c, OMP_CLAUSE_SIMD))
3800 : {
3801 : /* ordered simd must be closely nested inside of simd region,
3802 : and simd region must not encounter constructs other than
3803 : ordered simd, therefore ordered simd may be either orphaned,
3804 : or ctx->stmt must be simd. The latter case is handled already
3805 : earlier. */
3806 34 : if (ctx != NULL)
3807 : {
3808 10 : error_at (gimple_location (stmt),
3809 : "%<ordered%> %<simd%> must be closely nested inside "
3810 : "%<simd%> region");
3811 10 : return false;
3812 : }
3813 : }
3814 1605 : for (; ctx != NULL; ctx = ctx->outer)
3815 1474 : switch (gimple_code (ctx->stmt))
3816 : {
3817 38 : case GIMPLE_OMP_CRITICAL:
3818 38 : case GIMPLE_OMP_TASK:
3819 38 : case GIMPLE_OMP_ORDERED:
3820 38 : ordered_in_taskloop:
3821 38 : error_at (gimple_location (stmt),
3822 : "%<ordered%> region may not be closely nested inside "
3823 : "of %<critical%>, %<ordered%>, explicit %<task%> or "
3824 : "%<taskloop%> region");
3825 38 : return false;
3826 1416 : case GIMPLE_OMP_FOR:
3827 1416 : if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3828 10 : goto ordered_in_taskloop;
3829 1406 : tree o;
3830 1406 : o = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3831 : OMP_CLAUSE_ORDERED);
3832 1406 : if (o == NULL)
3833 : {
3834 22 : error_at (gimple_location (stmt),
3835 : "%<ordered%> region must be closely nested inside "
3836 : "a loop region with an %<ordered%> clause");
3837 22 : return false;
3838 : }
3839 1384 : if (!gimple_omp_ordered_standalone_p (stmt))
3840 : {
3841 375 : if (OMP_CLAUSE_ORDERED_DOACROSS (o))
3842 : {
3843 10 : error_at (gimple_location (stmt),
3844 : "%<ordered%> construct without %<doacross%> or "
3845 : "%<depend%> clauses must not have the same "
3846 : "binding region as %<ordered%> construct with "
3847 : "those clauses");
3848 10 : return false;
3849 : }
3850 365 : else if (OMP_CLAUSE_ORDERED_EXPR (o))
3851 : {
3852 23 : tree co
3853 23 : = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
3854 : OMP_CLAUSE_COLLAPSE);
3855 23 : HOST_WIDE_INT
3856 23 : o_n = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (o));
3857 23 : HOST_WIDE_INT c_n = 1;
3858 23 : if (co)
3859 5 : c_n = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (co));
3860 23 : if (o_n != c_n)
3861 : {
3862 10 : error_at (gimple_location (stmt),
3863 : "%<ordered%> construct without %<doacross%> "
3864 : "or %<depend%> clauses binds to loop where "
3865 : "%<collapse%> argument %wd is different from "
3866 : "%<ordered%> argument %wd", c_n, o_n);
3867 10 : return false;
3868 : }
3869 : }
3870 : }
3871 : return true;
3872 10 : case GIMPLE_OMP_TARGET:
3873 10 : if (gimple_omp_target_kind (ctx->stmt)
3874 : != GF_OMP_TARGET_KIND_REGION)
3875 : break;
3876 : /* FALLTHRU */
3877 30 : case GIMPLE_OMP_PARALLEL:
3878 30 : case GIMPLE_OMP_TEAMS:
3879 30 : error_at (gimple_location (stmt),
3880 : "%<ordered%> region must be closely nested inside "
3881 : "a loop region with an %<ordered%> clause");
3882 30 : return false;
3883 : default:
3884 : break;
3885 : }
3886 : break;
3887 462 : case GIMPLE_OMP_CRITICAL:
3888 462 : {
3889 462 : tree this_stmt_name
3890 462 : = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3891 888 : for (; ctx != NULL; ctx = ctx->outer)
3892 432 : if (gomp_critical *other_crit
3893 451 : = dyn_cast <gomp_critical *> (ctx->stmt))
3894 25 : if (this_stmt_name == gimple_omp_critical_name (other_crit))
3895 : {
3896 6 : error_at (gimple_location (stmt),
3897 : "%<critical%> region may not be nested inside "
3898 : "a %<critical%> region with the same name");
3899 6 : return false;
3900 : }
3901 : }
3902 : break;
3903 8841 : case GIMPLE_OMP_TEAMS:
3904 8841 : if (ctx == NULL)
3905 : break;
3906 6170 : else if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3907 6170 : || (gimple_omp_target_kind (ctx->stmt)
3908 : != GF_OMP_TARGET_KIND_REGION))
3909 : {
3910 : /* Teams construct can appear either strictly nested inside of
3911 : target construct with no intervening stmts, or can be encountered
3912 : only by initial task (so must not appear inside any OpenMP
3913 : construct. */
3914 44 : error_at (gimple_location (stmt),
3915 : "%<teams%> construct must be closely nested inside of "
3916 : "%<target%> construct or not nested in any OpenMP "
3917 : "construct");
3918 44 : return false;
3919 : }
3920 : break;
3921 42248 : case GIMPLE_OMP_TARGET:
3922 189464 : for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3923 147220 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS)
3924 : {
3925 4 : enum omp_clause_doacross_kind kind = OMP_CLAUSE_DOACROSS_KIND (c);
3926 4 : error_at (OMP_CLAUSE_LOCATION (c),
3927 : "%<depend(%s)%> is only allowed in %<omp ordered%>",
3928 : kind == OMP_CLAUSE_DOACROSS_SOURCE ? "source" : "sink");
3929 4 : return false;
3930 : }
3931 42244 : if (is_gimple_omp_offloaded (stmt)
3932 42244 : && oacc_get_fn_attrib (cfun->decl) != NULL)
3933 : {
3934 4 : error_at (gimple_location (stmt),
3935 : "OpenACC region inside of OpenACC routine, nested "
3936 : "parallelism not supported yet");
3937 4 : return false;
3938 : }
3939 49654 : for (; ctx != NULL; ctx = ctx->outer)
3940 : {
3941 7820 : if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3942 : {
3943 768 : if (is_gimple_omp (stmt)
3944 768 : && is_gimple_omp_oacc (stmt)
3945 242 : && is_gimple_omp (ctx->stmt))
3946 : {
3947 242 : error_at (gimple_location (stmt),
3948 : "OpenACC construct inside of non-OpenACC region");
3949 242 : return false;
3950 : }
3951 526 : continue;
3952 : }
3953 :
3954 7052 : const char *stmt_name, *ctx_stmt_name;
3955 7052 : switch (gimple_omp_target_kind (stmt))
3956 : {
3957 : case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3958 399 : case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3959 1688 : case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3960 12 : case GF_OMP_TARGET_KIND_ENTER_DATA:
3961 12 : stmt_name = "target enter data"; break;
3962 18 : case GF_OMP_TARGET_KIND_EXIT_DATA:
3963 18 : stmt_name = "target exit data"; break;
3964 1442 : case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3965 1621 : case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3966 183 : case GF_OMP_TARGET_KIND_OACC_SERIAL: stmt_name = "serial"; break;
3967 386 : case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3968 256 : case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3969 94 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
3970 94 : stmt_name = "enter data"; break;
3971 86 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
3972 86 : stmt_name = "exit data"; break;
3973 64 : case GF_OMP_TARGET_KIND_OACC_DECLARE: stmt_name = "declare"; break;
3974 128 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3975 128 : break;
3976 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3977 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3978 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
3979 : /* OpenACC 'kernels' decomposed parts. */
3980 1621 : stmt_name = "kernels"; break;
3981 0 : default: gcc_unreachable ();
3982 : }
3983 7052 : switch (gimple_omp_target_kind (ctx->stmt))
3984 : {
3985 : case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3986 2712 : case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3987 35 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3988 35 : ctx_stmt_name = "parallel"; break;
3989 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
3990 1037 : ctx_stmt_name = "kernels"; break;
3991 35 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
3992 35 : ctx_stmt_name = "serial"; break;
3993 3117 : case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3994 8 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3995 8 : ctx_stmt_name = "host_data"; break;
3996 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
3997 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
3998 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
3999 : /* OpenACC 'kernels' decomposed parts. */
4000 1037 : ctx_stmt_name = "kernels"; break;
4001 0 : default: gcc_unreachable ();
4002 : }
4003 :
4004 : /* OpenACC/OpenMP mismatch? */
4005 14104 : if (is_gimple_omp_oacc (stmt)
4006 7052 : != is_gimple_omp_oacc (ctx->stmt))
4007 : {
4008 56 : error_at (gimple_location (stmt),
4009 : "%s %qs construct inside of %s %qs region",
4010 : (is_gimple_omp_oacc (stmt)
4011 : ? "OpenACC" : "OpenMP"), stmt_name,
4012 : (is_gimple_omp_oacc (ctx->stmt)
4013 : ? "OpenACC" : "OpenMP"), ctx_stmt_name);
4014 28 : return false;
4015 : }
4016 7024 : if (is_gimple_omp_offloaded (ctx->stmt))
4017 : {
4018 : /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
4019 185 : if (is_gimple_omp_oacc (ctx->stmt))
4020 : {
4021 105 : error_at (gimple_location (stmt),
4022 : "%qs construct inside of %qs region",
4023 : stmt_name, ctx_stmt_name);
4024 105 : return false;
4025 : }
4026 : else
4027 : {
4028 80 : if ((gimple_omp_target_kind (ctx->stmt)
4029 : == GF_OMP_TARGET_KIND_REGION)
4030 80 : && (gimple_omp_target_kind (stmt)
4031 : == GF_OMP_TARGET_KIND_REGION))
4032 : {
4033 58 : c = omp_find_clause (gimple_omp_target_clauses (stmt),
4034 : OMP_CLAUSE_DEVICE);
4035 58 : if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
4036 : break;
4037 : }
4038 49 : warning_at (gimple_location (stmt), OPT_Wopenmp,
4039 : "%qs construct inside of %qs region",
4040 : stmt_name, ctx_stmt_name);
4041 : }
4042 : }
4043 : }
4044 : break;
4045 : default:
4046 : break;
4047 : }
4048 : return true;
4049 : }
4050 :
4051 :
4052 : /* Helper function scan_omp.
4053 :
4054 : Callback for walk_tree or operators in walk_gimple_stmt used to
4055 : scan for OMP directives in TP. */
4056 :
4057 : static tree
4058 9832877 : scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
4059 : {
4060 9832877 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
4061 9832877 : omp_context *ctx = (omp_context *) wi->info;
4062 9832877 : tree t = *tp;
4063 9832877 : tree tmp;
4064 :
4065 9832877 : switch (TREE_CODE (t))
4066 : {
4067 4162241 : case VAR_DECL:
4068 4162241 : case PARM_DECL:
4069 4162241 : case LABEL_DECL:
4070 4162241 : case RESULT_DECL:
4071 4162241 : if (ctx)
4072 : {
4073 2131652 : tmp = NULL_TREE;
4074 2131652 : if (TREE_CODE (t) == VAR_DECL
4075 3818894 : && (tmp = lookup_attribute ("omp allocate var",
4076 1687242 : DECL_ATTRIBUTES (t))) != NULL_TREE)
4077 61 : t = TREE_VALUE (TREE_VALUE (tmp));
4078 2131652 : tree repl = remap_decl (t, &ctx->cb);
4079 2131652 : gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
4080 2131652 : if (tmp != NULL_TREE && t != repl)
4081 31 : *tp = build_fold_addr_expr (repl);
4082 2131621 : else if (tmp == NULL_TREE)
4083 2131591 : *tp = repl;
4084 : }
4085 : break;
4086 :
4087 193682 : case INDIRECT_REF:
4088 193682 : case MEM_REF:
4089 193682 : if (ctx
4090 78127 : && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
4091 252751 : && ((tmp = lookup_attribute ("omp allocate var",
4092 59069 : DECL_ATTRIBUTES (TREE_OPERAND (t, 0))))
4093 : != NULL_TREE))
4094 : {
4095 127 : tmp = TREE_VALUE (TREE_VALUE (tmp));
4096 127 : tree repl = remap_decl (tmp, &ctx->cb);
4097 127 : gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
4098 127 : if (tmp != repl)
4099 118 : *tp = repl;
4100 : break;
4101 : }
4102 5670509 : gcc_fallthrough ();
4103 :
4104 5670509 : default:
4105 5670509 : if (ctx && TYPE_P (t))
4106 5 : *tp = remap_type (t, &ctx->cb);
4107 5670504 : else if (!DECL_P (t))
4108 : {
4109 4704126 : *walk_subtrees = 1;
4110 4704126 : if (ctx)
4111 : {
4112 1430117 : tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
4113 1430117 : if (tem != TREE_TYPE (t))
4114 : {
4115 9946 : if (TREE_CODE (t) == INTEGER_CST)
4116 4202 : *tp = wide_int_to_tree (tem, wi::to_wide (t));
4117 : else
4118 5744 : TREE_TYPE (t) = tem;
4119 : }
4120 : }
4121 : }
4122 : break;
4123 : }
4124 :
4125 9832877 : return NULL_TREE;
4126 : }
4127 :
4128 : /* Return true if FNDECL is a setjmp or a longjmp. */
4129 :
4130 : static bool
4131 3042 : setjmp_or_longjmp_p (const_tree fndecl)
4132 : {
4133 3042 : if (fndecl_built_in_p (fndecl, BUILT_IN_SETJMP, BUILT_IN_LONGJMP))
4134 : return true;
4135 :
4136 3042 : tree declname = DECL_NAME (fndecl);
4137 3042 : if (!declname
4138 3042 : || (DECL_CONTEXT (fndecl) != NULL_TREE
4139 2347 : && TREE_CODE (DECL_CONTEXT (fndecl)) != TRANSLATION_UNIT_DECL)
4140 5833 : || !TREE_PUBLIC (fndecl))
4141 : return false;
4142 :
4143 2629 : const char *name = IDENTIFIER_POINTER (declname);
4144 2629 : return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
4145 : }
4146 :
4147 : /* Helper function for scan_omp.
4148 :
4149 : Callback for walk_gimple_stmt used to scan for OMP directives in
4150 : the current statement in GSI. */
4151 :
4152 : static tree
4153 3417779 : scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
4154 : struct walk_stmt_info *wi)
4155 : {
4156 3417779 : gimple *stmt = gsi_stmt (*gsi);
4157 3417779 : omp_context *ctx = (omp_context *) wi->info;
4158 :
4159 3417779 : if (gimple_has_location (stmt))
4160 2788885 : input_location = gimple_location (stmt);
4161 :
4162 : /* Check the nesting restrictions. */
4163 3417779 : bool remove = false;
4164 3417779 : if (is_gimple_omp (stmt))
4165 152967 : remove = !check_omp_nesting_restrictions (stmt, ctx);
4166 3264812 : else if (is_gimple_call (stmt))
4167 : {
4168 233079 : tree fndecl = gimple_call_fndecl (stmt);
4169 233079 : if (fndecl)
4170 : {
4171 217244 : if (ctx
4172 68122 : && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4173 14714 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD
4174 3042 : && setjmp_or_longjmp_p (fndecl)
4175 217252 : && !ctx->loop_p)
4176 : {
4177 4 : remove = true;
4178 4 : error_at (gimple_location (stmt),
4179 : "setjmp/longjmp inside %<simd%> construct");
4180 : }
4181 217240 : else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
4182 63866 : switch (DECL_FUNCTION_CODE (fndecl))
4183 : {
4184 4221 : case BUILT_IN_GOMP_BARRIER:
4185 4221 : case BUILT_IN_GOMP_CANCEL:
4186 4221 : case BUILT_IN_GOMP_CANCELLATION_POINT:
4187 4221 : case BUILT_IN_GOMP_TASKYIELD:
4188 4221 : case BUILT_IN_GOMP_TASKWAIT:
4189 4221 : case BUILT_IN_GOMP_TASKGROUP_START:
4190 4221 : case BUILT_IN_GOMP_TASKGROUP_END:
4191 4221 : remove = !check_omp_nesting_restrictions (stmt, ctx);
4192 4221 : break;
4193 : default:
4194 : break;
4195 : }
4196 153374 : else if (ctx)
4197 : {
4198 46120 : omp_context *octx = ctx;
4199 46120 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN && ctx->outer)
4200 46120 : octx = ctx->outer;
4201 46120 : if (octx->order_concurrent && omp_runtime_api_call (fndecl))
4202 : {
4203 240 : remove = true;
4204 240 : error_at (gimple_location (stmt),
4205 : "OpenMP runtime API call %qD in a region with "
4206 : "%<order(concurrent)%> clause", fndecl);
4207 : }
4208 46120 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
4209 3339 : && omp_runtime_api_call (fndecl)
4210 339 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4211 : != strlen ("omp_get_num_teams"))
4212 185 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4213 : "omp_get_num_teams") != 0)
4214 169 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4215 : != strlen ("omp_get_num_teams_dim"))
4216 6 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4217 : "omp_get_num_teams_dim") != 0)
4218 163 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4219 : != strlen ("omp_get_team_num"))
4220 124 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4221 : "omp_get_team_num") != 0)
4222 46159 : && ((IDENTIFIER_LENGTH (DECL_NAME (fndecl))
4223 : != strlen ("omp_get_team_num_dim"))
4224 12 : || strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
4225 : "omp_get_team_num_dim") != 0))
4226 : {
4227 27 : remove = true;
4228 27 : error_at (gimple_location (stmt),
4229 : "OpenMP runtime API call %qD strictly nested in a "
4230 : "%<teams%> region", fndecl);
4231 : }
4232 46120 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
4233 13374 : && (gimple_omp_target_kind (ctx->stmt)
4234 : == GF_OMP_TARGET_KIND_REGION)
4235 51108 : && omp_runtime_api_call (fndecl))
4236 : {
4237 411 : tree tgt_clauses = gimple_omp_target_clauses (ctx->stmt);
4238 411 : tree c = omp_find_clause (tgt_clauses, OMP_CLAUSE_DEVICE);
4239 411 : if (c && OMP_CLAUSE_DEVICE_ANCESTOR (c))
4240 5 : error_at (gimple_location (stmt),
4241 : "OpenMP runtime API call %qD in a region with "
4242 : "%<device(ancestor)%> clause", fndecl);
4243 : }
4244 : }
4245 : }
4246 : }
4247 203312 : if (remove)
4248 : {
4249 3326 : stmt = gimple_build_nop ();
4250 3326 : gsi_replace (gsi, stmt, false);
4251 : }
4252 :
4253 3417779 : *handled_ops_p = true;
4254 :
4255 3417779 : switch (gimple_code (stmt))
4256 : {
4257 18243 : case GIMPLE_OMP_PARALLEL:
4258 18243 : taskreg_nesting_level++;
4259 18243 : scan_omp_parallel (gsi, ctx);
4260 18243 : taskreg_nesting_level--;
4261 18243 : break;
4262 :
4263 5374 : case GIMPLE_OMP_TASK:
4264 5374 : taskreg_nesting_level++;
4265 5374 : scan_omp_task (gsi, ctx);
4266 5374 : taskreg_nesting_level--;
4267 5374 : break;
4268 :
4269 52808 : case GIMPLE_OMP_FOR:
4270 52808 : if ((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
4271 : == GF_OMP_FOR_KIND_SIMD)
4272 10813 : && gimple_omp_for_combined_into_p (stmt)
4273 60503 : && gimple_code (ctx->stmt) != GIMPLE_OMP_SCAN)
4274 : {
4275 7529 : tree clauses = gimple_omp_for_clauses (as_a <gomp_for *> (stmt));
4276 7529 : tree c = omp_find_clause (clauses, OMP_CLAUSE_REDUCTION);
4277 7529 : if (c && OMP_CLAUSE_REDUCTION_INSCAN (c) && !seen_error ())
4278 : {
4279 83 : scan_omp_simd_scan (gsi, as_a <gomp_for *> (stmt), ctx);
4280 83 : break;
4281 : }
4282 : }
4283 52725 : if ((gimple_omp_for_kind (as_a <gomp_for *> (stmt))
4284 : == GF_OMP_FOR_KIND_SIMD)
4285 10730 : && omp_maybe_offloaded_ctx (ctx)
4286 3643 : && omp_max_simt_vf ()
4287 52725 : && gimple_omp_for_collapse (stmt) == 1)
4288 0 : scan_omp_simd (gsi, as_a <gomp_for *> (stmt), ctx);
4289 : else
4290 52725 : scan_omp_for (as_a <gomp_for *> (stmt), ctx);
4291 : break;
4292 :
4293 212 : case GIMPLE_OMP_SCOPE:
4294 212 : ctx = new_omp_context (stmt, ctx);
4295 212 : scan_sharing_clauses (gimple_omp_scope_clauses (stmt), ctx);
4296 212 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4297 212 : break;
4298 :
4299 852 : case GIMPLE_OMP_DISPATCH:
4300 852 : ctx = new_omp_context (stmt, ctx);
4301 852 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4302 852 : break;
4303 :
4304 612 : case GIMPLE_OMP_INTEROP:
4305 612 : ctx = new_omp_context (stmt, ctx);
4306 612 : break;
4307 :
4308 589 : case GIMPLE_OMP_SECTIONS:
4309 589 : scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
4310 589 : break;
4311 :
4312 1236 : case GIMPLE_OMP_SINGLE:
4313 1236 : scan_omp_single (as_a <gomp_single *> (stmt), ctx);
4314 1236 : break;
4315 :
4316 1292 : case GIMPLE_OMP_SCAN:
4317 1292 : if (tree clauses = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)))
4318 : {
4319 610 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_INCLUSIVE)
4320 308 : ctx->scan_inclusive = true;
4321 302 : else if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_EXCLUSIVE)
4322 302 : ctx->scan_exclusive = true;
4323 : }
4324 : /* FALLTHRU */
4325 6223 : case GIMPLE_OMP_SECTION:
4326 6223 : case GIMPLE_OMP_STRUCTURED_BLOCK:
4327 6223 : case GIMPLE_OMP_MASTER:
4328 6223 : case GIMPLE_OMP_ORDERED:
4329 6223 : case GIMPLE_OMP_CRITICAL:
4330 6223 : ctx = new_omp_context (stmt, ctx);
4331 6223 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4332 6223 : break;
4333 :
4334 457 : case GIMPLE_OMP_MASKED:
4335 457 : ctx = new_omp_context (stmt, ctx);
4336 457 : scan_sharing_clauses (gimple_omp_masked_clauses (stmt), ctx);
4337 457 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4338 457 : break;
4339 :
4340 607 : case GIMPLE_OMP_TASKGROUP:
4341 607 : ctx = new_omp_context (stmt, ctx);
4342 607 : scan_sharing_clauses (gimple_omp_taskgroup_clauses (stmt), ctx);
4343 607 : scan_omp (gimple_omp_body_ptr (stmt), ctx);
4344 607 : break;
4345 :
4346 41865 : case GIMPLE_OMP_TARGET:
4347 41865 : if (is_gimple_omp_offloaded (stmt))
4348 : {
4349 24836 : taskreg_nesting_level++;
4350 24836 : scan_omp_target (as_a <gomp_target *> (stmt), ctx);
4351 24836 : taskreg_nesting_level--;
4352 : }
4353 : else
4354 17029 : scan_omp_target (as_a <gomp_target *> (stmt), ctx);
4355 : break;
4356 :
4357 8797 : case GIMPLE_OMP_TEAMS:
4358 8797 : if (gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
4359 : {
4360 2671 : taskreg_nesting_level++;
4361 2671 : scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
4362 2671 : taskreg_nesting_level--;
4363 : }
4364 : else
4365 6126 : scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
4366 : break;
4367 :
4368 282832 : case GIMPLE_BIND:
4369 282832 : {
4370 282832 : tree var;
4371 :
4372 282832 : *handled_ops_p = false;
4373 282832 : if (ctx)
4374 152930 : for (var = gimple_bind_vars (as_a <gbind *> (stmt));
4375 580368 : var ;
4376 427438 : var = DECL_CHAIN (var))
4377 427438 : insert_decl_map (&ctx->cb, var, var);
4378 : }
4379 : break;
4380 2997072 : default:
4381 2997072 : *handled_ops_p = false;
4382 2997072 : break;
4383 : }
4384 :
4385 3417779 : return NULL_TREE;
4386 : }
4387 :
4388 :
4389 : /* Scan all the statements starting at the current statement. CTX
4390 : contains context information about the OMP directives and
4391 : clauses found during the scan. */
4392 :
4393 : static void
4394 259403 : scan_omp (gimple_seq *body_p, omp_context *ctx)
4395 : {
4396 259403 : location_t saved_location;
4397 259403 : struct walk_stmt_info wi;
4398 :
4399 259403 : memset (&wi, 0, sizeof (wi));
4400 259403 : wi.info = ctx;
4401 259403 : wi.want_locations = true;
4402 :
4403 259403 : saved_location = input_location;
4404 259403 : walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4405 259403 : input_location = saved_location;
4406 259403 : }
4407 :
4408 : /* Re-gimplification and code generation routines. */
4409 :
4410 : /* Remove omp_member_access_dummy_var variables from gimple_bind_vars
4411 : of BIND if in a method. */
4412 :
4413 : static void
4414 259143 : maybe_remove_omp_member_access_dummy_vars (gbind *bind)
4415 : {
4416 259143 : if (DECL_ARGUMENTS (current_function_decl)
4417 98195 : && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
4418 269893 : && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
4419 : == POINTER_TYPE))
4420 : {
4421 3520 : tree vars = gimple_bind_vars (bind);
4422 19340 : for (tree *pvar = &vars; *pvar; )
4423 15820 : if (omp_member_access_dummy_var (*pvar))
4424 719 : *pvar = DECL_CHAIN (*pvar);
4425 : else
4426 15101 : pvar = &DECL_CHAIN (*pvar);
4427 3520 : gimple_bind_set_vars (bind, vars);
4428 : }
4429 259143 : }
4430 :
4431 : /* Remove omp_member_access_dummy_var variables from BLOCK_VARS of
4432 : block and its subblocks. */
4433 :
4434 : static void
4435 12877 : remove_member_access_dummy_vars (tree block)
4436 : {
4437 22439 : for (tree *pvar = &BLOCK_VARS (block); *pvar; )
4438 9562 : if (omp_member_access_dummy_var (*pvar))
4439 108 : *pvar = DECL_CHAIN (*pvar);
4440 : else
4441 9454 : pvar = &DECL_CHAIN (*pvar);
4442 :
4443 16764 : for (block = BLOCK_SUBBLOCKS (block); block; block = BLOCK_CHAIN (block))
4444 3887 : remove_member_access_dummy_vars (block);
4445 12877 : }
4446 :
4447 : /* If a context was created for STMT when it was scanned, return it. */
4448 :
4449 : static omp_context *
4450 121530 : maybe_lookup_ctx (gimple *stmt)
4451 : {
4452 121530 : splay_tree_node n;
4453 121530 : n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4454 121530 : return n ? (omp_context *) n->value : NULL;
4455 : }
4456 :
4457 :
4458 : /* Find the mapping for DECL in CTX or the immediately enclosing
4459 : context that has a mapping for DECL.
4460 :
4461 : If CTX is a nested parallel directive, we may have to use the decl
4462 : mappings created in CTX's parent context. Suppose that we have the
4463 : following parallel nesting (variable UIDs showed for clarity):
4464 :
4465 : iD.1562 = 0;
4466 : #omp parallel shared(iD.1562) -> outer parallel
4467 : iD.1562 = iD.1562 + 1;
4468 :
4469 : #omp parallel shared (iD.1562) -> inner parallel
4470 : iD.1562 = iD.1562 - 1;
4471 :
4472 : Each parallel structure will create a distinct .omp_data_s structure
4473 : for copying iD.1562 in/out of the directive:
4474 :
4475 : outer parallel .omp_data_s.1.i -> iD.1562
4476 : inner parallel .omp_data_s.2.i -> iD.1562
4477 :
4478 : A shared variable mapping will produce a copy-out operation before
4479 : the parallel directive and a copy-in operation after it. So, in
4480 : this case we would have:
4481 :
4482 : iD.1562 = 0;
4483 : .omp_data_o.1.i = iD.1562;
4484 : #omp parallel shared(iD.1562) -> outer parallel
4485 : .omp_data_i.1 = &.omp_data_o.1
4486 : .omp_data_i.1->i = .omp_data_i.1->i + 1;
4487 :
4488 : .omp_data_o.2.i = iD.1562; -> **
4489 : #omp parallel shared(iD.1562) -> inner parallel
4490 : .omp_data_i.2 = &.omp_data_o.2
4491 : .omp_data_i.2->i = .omp_data_i.2->i - 1;
4492 :
4493 :
4494 : ** This is a problem. The symbol iD.1562 cannot be referenced
4495 : inside the body of the outer parallel region. But since we are
4496 : emitting this copy operation while expanding the inner parallel
4497 : directive, we need to access the CTX structure of the outer
4498 : parallel directive to get the correct mapping:
4499 :
4500 : .omp_data_o.2.i = .omp_data_i.1->i
4501 :
4502 : Since there may be other workshare or parallel directives enclosing
4503 : the parallel directive, it may be necessary to walk up the context
4504 : parent chain. This is not a problem in general because nested
4505 : parallelism happens only rarely. */
4506 :
4507 : static tree
4508 126457 : lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4509 : {
4510 126457 : tree t;
4511 126457 : omp_context *up;
4512 :
4513 183235 : for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4514 56778 : t = maybe_lookup_decl (decl, up);
4515 :
4516 126457 : gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4517 :
4518 98095 : return t ? t : decl;
4519 : }
4520 :
4521 :
4522 : /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4523 : in outer contexts. */
4524 :
4525 : static tree
4526 357741 : maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4527 : {
4528 357741 : tree t = NULL;
4529 357741 : omp_context *up;
4530 :
4531 629162 : for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4532 271421 : t = maybe_lookup_decl (decl, up);
4533 :
4534 357741 : return t ? t : decl;
4535 : }
4536 :
4537 :
4538 : /* Construct the initialization value for reduction operation OP. */
4539 :
4540 : tree
4541 13138 : omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4542 : {
4543 13138 : switch (op)
4544 : {
4545 10803 : case PLUS_EXPR:
4546 10803 : case MINUS_EXPR:
4547 10803 : case BIT_IOR_EXPR:
4548 10803 : case BIT_XOR_EXPR:
4549 10803 : case TRUTH_OR_EXPR:
4550 10803 : case TRUTH_ORIF_EXPR:
4551 10803 : case TRUTH_XOR_EXPR:
4552 10803 : case NE_EXPR:
4553 10803 : return build_zero_cst (type);
4554 :
4555 1431 : case MULT_EXPR:
4556 1431 : case TRUTH_AND_EXPR:
4557 1431 : case TRUTH_ANDIF_EXPR:
4558 1431 : case EQ_EXPR:
4559 1431 : return fold_convert_loc (loc, type, integer_one_node);
4560 :
4561 208 : case BIT_AND_EXPR:
4562 208 : return fold_convert_loc (loc, type, integer_minus_one_node);
4563 :
4564 388 : case MAX_EXPR:
4565 388 : if (SCALAR_FLOAT_TYPE_P (type))
4566 : {
4567 158 : REAL_VALUE_TYPE min;
4568 158 : if (HONOR_INFINITIES (type))
4569 158 : real_arithmetic (&min, NEGATE_EXPR, &dconstinf, NULL);
4570 : else
4571 0 : real_maxval (&min, 1, TYPE_MODE (type));
4572 158 : return build_real (type, min);
4573 : }
4574 230 : else if (POINTER_TYPE_P (type))
4575 : {
4576 2 : wide_int min
4577 2 : = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4578 2 : return wide_int_to_tree (type, min);
4579 2 : }
4580 : else
4581 : {
4582 228 : gcc_assert (INTEGRAL_TYPE_P (type));
4583 228 : return TYPE_MIN_VALUE (type);
4584 : }
4585 :
4586 308 : case MIN_EXPR:
4587 308 : if (SCALAR_FLOAT_TYPE_P (type))
4588 : {
4589 108 : REAL_VALUE_TYPE max;
4590 108 : if (HONOR_INFINITIES (type))
4591 108 : max = dconstinf;
4592 : else
4593 0 : real_maxval (&max, 0, TYPE_MODE (type));
4594 108 : return build_real (type, max);
4595 : }
4596 200 : else if (POINTER_TYPE_P (type))
4597 : {
4598 2 : wide_int max
4599 2 : = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4600 2 : return wide_int_to_tree (type, max);
4601 2 : }
4602 : else
4603 : {
4604 198 : gcc_assert (INTEGRAL_TYPE_P (type));
4605 198 : return TYPE_MAX_VALUE (type);
4606 : }
4607 :
4608 0 : default:
4609 0 : gcc_unreachable ();
4610 : }
4611 : }
4612 :
4613 : /* Construct the initialization value for reduction CLAUSE. */
4614 :
4615 : tree
4616 10517 : omp_reduction_init (tree clause, tree type)
4617 : {
4618 10517 : return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4619 10517 : OMP_CLAUSE_REDUCTION_CODE (clause), type);
4620 : }
4621 :
4622 : /* Return alignment to be assumed for var in CLAUSE, which should be
4623 : OMP_CLAUSE_ALIGNED. */
4624 :
4625 : static tree
4626 140 : omp_clause_aligned_alignment (tree clause)
4627 : {
4628 140 : if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4629 123 : return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4630 :
4631 : /* Otherwise return implementation defined alignment. */
4632 17 : unsigned int al = 1;
4633 17 : opt_scalar_mode mode_iter;
4634 17 : auto_vector_modes modes;
4635 17 : targetm.vectorize.autovectorize_vector_modes (&modes, true);
4636 17 : static enum mode_class classes[]
4637 : = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4638 51 : for (int i = 0; i < 4; i += 2)
4639 : /* The for loop above dictates that we only walk through scalar classes. */
4640 255 : FOR_EACH_MODE_IN_CLASS (mode_iter, classes[i])
4641 : {
4642 221 : scalar_mode mode = mode_iter.require ();
4643 221 : machine_mode vmode = targetm.vectorize.preferred_simd_mode (mode);
4644 221 : if (GET_MODE_CLASS (vmode) != classes[i + 1])
4645 323 : continue;
4646 : machine_mode alt_vmode;
4647 476 : for (unsigned int j = 0; j < modes.length (); ++j)
4648 527 : if (related_vector_mode (modes[j], mode).exists (&alt_vmode)
4649 578 : && known_ge (GET_MODE_SIZE (alt_vmode), GET_MODE_SIZE (vmode)))
4650 119 : vmode = alt_vmode;
4651 :
4652 119 : tree type = lang_hooks.types.type_for_mode (mode, 1);
4653 119 : if (type == NULL_TREE || TYPE_MODE (type) != mode)
4654 17 : continue;
4655 102 : type = build_vector_type_for_mode (type, vmode);
4656 102 : if (TYPE_MODE (type) != vmode)
4657 0 : continue;
4658 102 : if (TYPE_ALIGN_UNIT (type) > al)
4659 17 : al = TYPE_ALIGN_UNIT (type);
4660 : }
4661 17 : return build_int_cst (integer_type_node, al);
4662 17 : }
4663 :
4664 :
4665 : /* This structure is part of the interface between lower_rec_simd_input_clauses
4666 : and lower_rec_input_clauses. */
4667 :
4668 : class omplow_simd_context {
4669 : public:
4670 77364 : omplow_simd_context () { memset (this, 0, sizeof (*this)); }
4671 : tree idx;
4672 : tree lane;
4673 : tree lastlane;
4674 : vec<tree, va_heap> simt_eargs;
4675 : gimple_seq simt_dlist;
4676 : poly_uint64 max_vf;
4677 : bool is_simt;
4678 : };
4679 :
4680 : /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4681 : privatization. */
4682 :
4683 : static bool
4684 10228 : lower_rec_simd_input_clauses (tree new_var, omp_context *ctx,
4685 : omplow_simd_context *sctx, tree &ivar,
4686 : tree &lvar, tree *rvar = NULL,
4687 : tree *rvar2 = NULL)
4688 : {
4689 10228 : if (known_eq (sctx->max_vf, 0U))
4690 : {
4691 4790 : sctx->max_vf = (sctx->is_simt ? omp_max_simt_vf ()
4692 4790 : : omp_max_vf (omp_maybe_offloaded_ctx (ctx)));
4693 4790 : if (maybe_gt (sctx->max_vf, 1U))
4694 : {
4695 3452 : tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
4696 : OMP_CLAUSE_SAFELEN);
4697 3452 : if (c)
4698 : {
4699 89 : poly_uint64 safe_len;
4700 89 : if (!poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
4701 89 : || maybe_lt (safe_len, 1U))
4702 6 : sctx->max_vf = 1;
4703 : else
4704 83 : sctx->max_vf = lower_bound (sctx->max_vf, safe_len);
4705 : }
4706 : }
4707 4790 : if (sctx->is_simt && !known_eq (sctx->max_vf, 1U))
4708 : {
4709 0 : for (tree c = gimple_omp_for_clauses (ctx->stmt); c;
4710 0 : c = OMP_CLAUSE_CHAIN (c))
4711 : {
4712 0 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4713 0 : continue;
4714 :
4715 0 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4716 : {
4717 : /* UDR reductions are not supported yet for SIMT, disable
4718 : SIMT. */
4719 0 : sctx->max_vf = 1;
4720 0 : break;
4721 : }
4722 :
4723 0 : if (truth_value_p (OMP_CLAUSE_REDUCTION_CODE (c))
4724 0 : && !INTEGRAL_TYPE_P (TREE_TYPE (new_var)))
4725 : {
4726 : /* Doing boolean operations on non-integral types is
4727 : for conformance only, it's not worth supporting this
4728 : for SIMT. */
4729 0 : sctx->max_vf = 1;
4730 0 : break;
4731 : }
4732 : }
4733 : }
4734 4790 : if (maybe_gt (sctx->max_vf, 1U))
4735 : {
4736 3433 : sctx->idx = create_tmp_var (unsigned_type_node);
4737 3433 : sctx->lane = create_tmp_var (unsigned_type_node);
4738 : }
4739 : }
4740 10228 : if (known_eq (sctx->max_vf, 1U))
4741 : return false;
4742 :
4743 7174 : if (sctx->is_simt)
4744 : {
4745 0 : if (is_gimple_reg (new_var))
4746 : {
4747 0 : ivar = lvar = new_var;
4748 0 : return true;
4749 : }
4750 0 : tree type = TREE_TYPE (new_var), ptype = build_pointer_type (type);
4751 0 : ivar = lvar = create_tmp_var (type);
4752 0 : TREE_ADDRESSABLE (ivar) = 1;
4753 0 : DECL_ATTRIBUTES (ivar) = tree_cons (get_identifier ("omp simt private"),
4754 0 : NULL, DECL_ATTRIBUTES (ivar));
4755 0 : sctx->simt_eargs.safe_push (build1 (ADDR_EXPR, ptype, ivar));
4756 0 : tree clobber = build_clobber (type);
4757 0 : gimple *g = gimple_build_assign (ivar, clobber);
4758 0 : gimple_seq_add_stmt (&sctx->simt_dlist, g);
4759 : }
4760 : else
4761 : {
4762 7174 : tree atype = build_array_type_nelts (TREE_TYPE (new_var), sctx->max_vf);
4763 7174 : tree avar = create_tmp_var_raw (atype);
4764 7174 : if (TREE_ADDRESSABLE (new_var))
4765 912 : TREE_ADDRESSABLE (avar) = 1;
4766 7174 : DECL_ATTRIBUTES (avar)
4767 7174 : = tree_cons (get_identifier ("omp simd array"), NULL,
4768 7174 : DECL_ATTRIBUTES (avar));
4769 7174 : gimple_add_tmp_var (avar);
4770 7174 : tree iavar = avar;
4771 7174 : if (rvar && !ctx->for_simd_scan_phase)
4772 : {
4773 : /* For inscan reductions, create another array temporary,
4774 : which will hold the reduced value. */
4775 232 : iavar = create_tmp_var_raw (atype);
4776 232 : if (TREE_ADDRESSABLE (new_var))
4777 33 : TREE_ADDRESSABLE (iavar) = 1;
4778 232 : DECL_ATTRIBUTES (iavar)
4779 232 : = tree_cons (get_identifier ("omp simd array"), NULL,
4780 : tree_cons (get_identifier ("omp simd inscan"), NULL,
4781 232 : DECL_ATTRIBUTES (iavar)));
4782 232 : gimple_add_tmp_var (iavar);
4783 232 : ctx->cb.decl_map->put (avar, iavar);
4784 232 : if (sctx->lastlane == NULL_TREE)
4785 184 : sctx->lastlane = create_tmp_var (unsigned_type_node);
4786 232 : *rvar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar,
4787 : sctx->lastlane, NULL_TREE, NULL_TREE);
4788 232 : TREE_THIS_NOTRAP (*rvar) = 1;
4789 :
4790 232 : if (ctx->scan_exclusive)
4791 : {
4792 : /* And for exclusive scan yet another one, which will
4793 : hold the value during the scan phase. */
4794 114 : tree savar = create_tmp_var_raw (atype);
4795 114 : if (TREE_ADDRESSABLE (new_var))
4796 17 : TREE_ADDRESSABLE (savar) = 1;
4797 114 : DECL_ATTRIBUTES (savar)
4798 114 : = tree_cons (get_identifier ("omp simd array"), NULL,
4799 : tree_cons (get_identifier ("omp simd inscan "
4800 : "exclusive"), NULL,
4801 114 : DECL_ATTRIBUTES (savar)));
4802 114 : gimple_add_tmp_var (savar);
4803 114 : ctx->cb.decl_map->put (iavar, savar);
4804 114 : *rvar2 = build4 (ARRAY_REF, TREE_TYPE (new_var), savar,
4805 : sctx->idx, NULL_TREE, NULL_TREE);
4806 114 : TREE_THIS_NOTRAP (*rvar2) = 1;
4807 : }
4808 : }
4809 7174 : ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), iavar, sctx->idx,
4810 : NULL_TREE, NULL_TREE);
4811 7174 : lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, sctx->lane,
4812 : NULL_TREE, NULL_TREE);
4813 7174 : TREE_THIS_NOTRAP (ivar) = 1;
4814 7174 : TREE_THIS_NOTRAP (lvar) = 1;
4815 : }
4816 7174 : if (DECL_P (new_var))
4817 : {
4818 7020 : SET_DECL_VALUE_EXPR (new_var, lvar);
4819 7020 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4820 : }
4821 : return true;
4822 : }
4823 :
4824 : /* Helper function of lower_rec_input_clauses. For a reference
4825 : in simd reduction, add an underlying variable it will reference. */
4826 :
4827 : static void
4828 64 : handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4829 : {
4830 64 : tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4831 64 : if (TREE_CONSTANT (z))
4832 : {
4833 64 : z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4834 : get_name (new_vard));
4835 64 : gimple_add_tmp_var (z);
4836 64 : TREE_ADDRESSABLE (z) = 1;
4837 64 : z = build_fold_addr_expr_loc (loc, z);
4838 64 : gimplify_assign (new_vard, z, ilist);
4839 : }
4840 64 : }
4841 :
4842 : /* Helper function for lower_rec_input_clauses. Emit into ilist sequence
4843 : code to emit (type) (tskred_temp[idx]). */
4844 :
4845 : static tree
4846 1128 : task_reduction_read (gimple_seq *ilist, tree tskred_temp, tree type,
4847 : unsigned idx)
4848 : {
4849 1128 : unsigned HOST_WIDE_INT sz
4850 1128 : = tree_to_uhwi (TYPE_SIZE_UNIT (pointer_sized_int_node));
4851 1128 : tree r = build2 (MEM_REF, pointer_sized_int_node,
4852 1128 : tskred_temp, build_int_cst (TREE_TYPE (tskred_temp),
4853 1128 : idx * sz));
4854 1128 : tree v = create_tmp_var (pointer_sized_int_node);
4855 1128 : gimple *g = gimple_build_assign (v, r);
4856 1128 : gimple_seq_add_stmt (ilist, g);
4857 1128 : if (!useless_type_conversion_p (type, pointer_sized_int_node))
4858 : {
4859 880 : v = create_tmp_var (type);
4860 880 : g = gimple_build_assign (v, NOP_EXPR, gimple_assign_lhs (g));
4861 880 : gimple_seq_add_stmt (ilist, g);
4862 : }
4863 1128 : return v;
4864 : }
4865 :
4866 : /* Lower early initialization of privatized variable NEW_VAR
4867 : if it needs an allocator (has allocate clause). */
4868 :
4869 : static bool
4870 144780 : lower_private_allocate (tree var, tree new_var, tree &allocator,
4871 : tree &allocate_ptr, gimple_seq *ilist,
4872 : omp_context *ctx, bool is_ref, tree size)
4873 : {
4874 144780 : if (allocator)
4875 : return false;
4876 144686 : gcc_assert (allocate_ptr == NULL_TREE);
4877 144686 : if (ctx->allocate_map
4878 3108 : && (DECL_P (new_var) || (TYPE_P (new_var) && size)))
4879 3105 : if (tree *allocatorp = ctx->allocate_map->get (var))
4880 1161 : allocator = *allocatorp;
4881 144686 : if (allocator == NULL_TREE)
4882 : return false;
4883 1161 : if (!is_ref && omp_privatize_by_reference (var))
4884 : {
4885 0 : allocator = NULL_TREE;
4886 0 : return false;
4887 : }
4888 :
4889 1161 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET && DECL_P (allocator))
4890 : {
4891 4 : allocator = lookup_decl (allocator, ctx);
4892 4 : gcc_checking_assert (allocator != NULL_TREE);
4893 : }
4894 :
4895 1161 : unsigned HOST_WIDE_INT ialign = 0;
4896 1161 : if (TREE_CODE (allocator) == TREE_LIST)
4897 : {
4898 248 : ialign = tree_to_uhwi (TREE_VALUE (allocator));
4899 248 : allocator = TREE_PURPOSE (allocator);
4900 : }
4901 1161 : if (TREE_CODE (allocator) != INTEGER_CST)
4902 443 : allocator = build_outer_var_ref (allocator, ctx, OMP_CLAUSE_ALLOCATE);
4903 1161 : allocator = fold_convert (pointer_sized_int_node, allocator);
4904 1161 : if (TREE_CODE (allocator) != INTEGER_CST)
4905 : {
4906 443 : tree var = create_tmp_var (TREE_TYPE (allocator));
4907 443 : gimplify_assign (var, allocator, ilist);
4908 443 : allocator = var;
4909 : }
4910 :
4911 1161 : tree ptr_type, align, sz = size;
4912 1161 : if (TYPE_P (new_var))
4913 : {
4914 225 : ptr_type = build_pointer_type (new_var);
4915 225 : ialign = MAX (ialign, TYPE_ALIGN_UNIT (new_var));
4916 : }
4917 936 : else if (is_ref)
4918 : {
4919 114 : ptr_type = build_pointer_type (TREE_TYPE (TREE_TYPE (new_var)));
4920 114 : ialign = MAX (ialign, TYPE_ALIGN_UNIT (TREE_TYPE (ptr_type)));
4921 : }
4922 : else
4923 : {
4924 822 : ptr_type = build_pointer_type (TREE_TYPE (new_var));
4925 822 : ialign = MAX (ialign, DECL_ALIGN_UNIT (new_var));
4926 822 : if (sz == NULL_TREE)
4927 720 : sz = fold_convert (size_type_node, DECL_SIZE_UNIT (new_var));
4928 : }
4929 1161 : align = build_int_cst (size_type_node, ialign);
4930 1161 : if (TREE_CODE (sz) != INTEGER_CST)
4931 : {
4932 54 : tree szvar = create_tmp_var (size_type_node);
4933 54 : gimplify_assign (szvar, sz, ilist);
4934 54 : sz = szvar;
4935 : }
4936 1161 : allocate_ptr = create_tmp_var (ptr_type);
4937 1161 : tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
4938 1161 : gimple *g = gimple_build_call (a, 3, align, sz, allocator);
4939 1161 : gimple_call_set_lhs (g, allocate_ptr);
4940 1161 : gimple_seq_add_stmt (ilist, g);
4941 1161 : if (!is_ref)
4942 : {
4943 822 : tree x = build_simple_mem_ref (allocate_ptr);
4944 822 : TREE_THIS_NOTRAP (x) = 1;
4945 822 : SET_DECL_VALUE_EXPR (new_var, x);
4946 822 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4947 : }
4948 : return true;
4949 : }
4950 :
4951 : /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4952 : from the receiver (aka child) side and initializers for REFERENCE_TYPE
4953 : private variables. Initialization statements go in ILIST, while calls
4954 : to destructors go in DLIST. */
4955 :
4956 : static void
4957 77364 : lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4958 : omp_context *ctx, struct omp_for_data *fd)
4959 : {
4960 77364 : tree c, copyin_seq, x, ptr;
4961 77364 : bool copyin_by_ref = false;
4962 77364 : bool lastprivate_firstprivate = false;
4963 77364 : bool reduction_omp_orig_ref = false;
4964 77364 : int pass;
4965 77364 : bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4966 77364 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
4967 77364 : omplow_simd_context sctx = omplow_simd_context ();
4968 77364 : tree simt_lane = NULL_TREE, simtrec = NULL_TREE;
4969 77364 : tree ivar = NULL_TREE, lvar = NULL_TREE, uid = NULL_TREE;
4970 77364 : gimple_seq llist[4] = { };
4971 77364 : tree nonconst_simd_if = NULL_TREE;
4972 :
4973 77364 : copyin_seq = NULL;
4974 77364 : sctx.is_simt = is_simd && omp_find_clause (clauses, OMP_CLAUSE__SIMT_);
4975 :
4976 : /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4977 : with data sharing clauses referencing variable sized vars. That
4978 : is unnecessarily hard to support and very unlikely to result in
4979 : vectorized code anyway. */
4980 9358 : if (is_simd)
4981 61475 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4982 52117 : switch (OMP_CLAUSE_CODE (c))
4983 : {
4984 7582 : case OMP_CLAUSE_LINEAR:
4985 7582 : if (OMP_CLAUSE_LINEAR_ARRAY (c))
4986 216 : sctx.max_vf = 1;
4987 : /* FALLTHRU */
4988 25158 : case OMP_CLAUSE_PRIVATE:
4989 25158 : case OMP_CLAUSE_FIRSTPRIVATE:
4990 25158 : case OMP_CLAUSE_LASTPRIVATE:
4991 25158 : if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4992 0 : sctx.max_vf = 1;
4993 25158 : else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
4994 : {
4995 279 : tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
4996 279 : if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
4997 96 : sctx.max_vf = 1;
4998 : }
4999 : break;
5000 2578 : case OMP_CLAUSE_REDUCTION:
5001 2578 : case OMP_CLAUSE_IN_REDUCTION:
5002 2578 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
5003 2578 : || is_variable_sized (OMP_CLAUSE_DECL (c)))
5004 180 : sctx.max_vf = 1;
5005 2398 : else if (omp_privatize_by_reference (OMP_CLAUSE_DECL (c)))
5006 : {
5007 144 : tree rtype = TREE_TYPE (TREE_TYPE (OMP_CLAUSE_DECL (c)));
5008 144 : if (!TREE_CONSTANT (TYPE_SIZE_UNIT (rtype)))
5009 0 : sctx.max_vf = 1;
5010 : }
5011 : break;
5012 759 : case OMP_CLAUSE_IF:
5013 759 : if (integer_zerop (OMP_CLAUSE_IF_EXPR (c)))
5014 124 : sctx.max_vf = 1;
5015 635 : else if (TREE_CODE (OMP_CLAUSE_IF_EXPR (c)) != INTEGER_CST)
5016 625 : nonconst_simd_if = OMP_CLAUSE_IF_EXPR (c);
5017 : break;
5018 626 : case OMP_CLAUSE_SIMDLEN:
5019 626 : if (integer_onep (OMP_CLAUSE_SIMDLEN_EXPR (c)))
5020 110 : sctx.max_vf = 1;
5021 : break;
5022 184 : case OMP_CLAUSE__CONDTEMP_:
5023 : /* FIXME: lastprivate(conditional:) not handled for SIMT yet. */
5024 184 : if (sctx.is_simt)
5025 0 : sctx.max_vf = 1;
5026 : break;
5027 22812 : default:
5028 22812 : continue;
5029 22812 : }
5030 :
5031 : /* Add a placeholder for simduid. */
5032 77364 : if (sctx.is_simt && maybe_ne (sctx.max_vf, 1U))
5033 0 : sctx.simt_eargs.safe_push (NULL_TREE);
5034 :
5035 : unsigned task_reduction_cnt = 0;
5036 : unsigned task_reduction_cntorig = 0;
5037 : unsigned task_reduction_cnt_full = 0;
5038 : unsigned task_reduction_cntorig_full = 0;
5039 : unsigned task_reduction_other_cnt = 0;
5040 235163 : tree tskred_atype = NULL_TREE, tskred_avar = NULL_TREE;
5041 : tree tskred_base = NULL_TREE, tskred_temp = NULL_TREE;
5042 : /* Do all the fixed sized types in the first pass, and the variable sized
5043 : types in the second pass. This makes sure that the scalar arguments to
5044 : the variable sized types are processed before we use them in the
5045 : variable sized operations. For task reductions we use 4 passes, in the
5046 : first two we ignore them, in the third one gather arguments for
5047 : GOMP_task_reduction_remap call and in the last pass actually handle
5048 : the task reductions. */
5049 392962 : for (pass = 0; pass < ((task_reduction_cnt || task_reduction_other_cnt)
5050 235163 : ? 4 : 2); ++pass)
5051 : {
5052 157803 : if (pass == 2 && task_reduction_cnt)
5053 : {
5054 871 : tskred_atype
5055 871 : = build_array_type_nelts (ptr_type_node, task_reduction_cnt
5056 871 : + task_reduction_cntorig);
5057 871 : tskred_avar = create_tmp_var_raw (tskred_atype);
5058 871 : gimple_add_tmp_var (tskred_avar);
5059 871 : TREE_ADDRESSABLE (tskred_avar) = 1;
5060 871 : task_reduction_cnt_full = task_reduction_cnt;
5061 871 : task_reduction_cntorig_full = task_reduction_cntorig;
5062 : }
5063 156932 : else if (pass == 3 && task_reduction_cnt)
5064 : {
5065 871 : x = builtin_decl_explicit (BUILT_IN_GOMP_TASK_REDUCTION_REMAP);
5066 871 : gimple *g
5067 871 : = gimple_build_call (x, 3, size_int (task_reduction_cnt),
5068 871 : size_int (task_reduction_cntorig),
5069 : build_fold_addr_expr (tskred_avar));
5070 871 : gimple_seq_add_stmt (ilist, g);
5071 : }
5072 157803 : if (pass == 3 && task_reduction_other_cnt)
5073 : {
5074 : /* For reduction clauses, build
5075 : tskred_base = (void *) tskred_temp[2]
5076 : + omp_get_thread_num () * tskred_temp[1]
5077 : or if tskred_temp[1] is known to be constant, that constant
5078 : directly. This is the start of the private reduction copy block
5079 : for the current thread. */
5080 846 : tree v = create_tmp_var (integer_type_node);
5081 846 : x = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5082 846 : gimple *g = gimple_build_call (x, 0);
5083 846 : gimple_call_set_lhs (g, v);
5084 846 : gimple_seq_add_stmt (ilist, g);
5085 846 : c = omp_find_clause (clauses, OMP_CLAUSE__REDUCTEMP_);
5086 846 : tskred_temp = OMP_CLAUSE_DECL (c);
5087 846 : if (is_taskreg_ctx (ctx))
5088 557 : tskred_temp = lookup_decl (tskred_temp, ctx);
5089 846 : tree v2 = create_tmp_var (sizetype);
5090 846 : g = gimple_build_assign (v2, NOP_EXPR, v);
5091 846 : gimple_seq_add_stmt (ilist, g);
5092 846 : if (ctx->task_reductions[0])
5093 829 : v = fold_convert (sizetype, ctx->task_reductions[0]);
5094 : else
5095 17 : v = task_reduction_read (ilist, tskred_temp, sizetype, 1);
5096 846 : tree v3 = create_tmp_var (sizetype);
5097 846 : g = gimple_build_assign (v3, MULT_EXPR, v2, v);
5098 846 : gimple_seq_add_stmt (ilist, g);
5099 846 : v = task_reduction_read (ilist, tskred_temp, ptr_type_node, 2);
5100 846 : tskred_base = create_tmp_var (ptr_type_node);
5101 846 : g = gimple_build_assign (tskred_base, POINTER_PLUS_EXPR, v, v3);
5102 846 : gimple_seq_add_stmt (ilist, g);
5103 : }
5104 157803 : task_reduction_cnt = 0;
5105 157803 : task_reduction_cntorig = 0;
5106 157803 : task_reduction_other_cnt = 0;
5107 762782 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5108 : {
5109 604983 : enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
5110 604983 : tree var, new_var;
5111 604983 : bool by_ref;
5112 604983 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5113 604983 : bool task_reduction_p = false;
5114 604983 : bool task_reduction_needs_orig_p = false;
5115 604983 : tree cond = NULL_TREE;
5116 604983 : tree allocator, allocate_ptr;
5117 :
5118 604983 : switch (c_kind)
5119 : {
5120 136166 : case OMP_CLAUSE_PRIVATE:
5121 136166 : if (OMP_CLAUSE_PRIVATE_DEBUG (c))
5122 436275 : continue;
5123 : break;
5124 60138 : case OMP_CLAUSE_SHARED:
5125 : /* Ignore shared directives in teams construct inside
5126 : of target construct. */
5127 60138 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
5128 60138 : && !is_host_teams_ctx (ctx))
5129 23506 : continue;
5130 36632 : if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
5131 : {
5132 12080 : gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
5133 : || is_global_var (OMP_CLAUSE_DECL (c)));
5134 12080 : continue;
5135 : }
5136 : case OMP_CLAUSE_FIRSTPRIVATE:
5137 : case OMP_CLAUSE_COPYIN:
5138 : break;
5139 15618 : case OMP_CLAUSE_LINEAR:
5140 15618 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
5141 15618 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5142 : lastprivate_firstprivate = true;
5143 : break;
5144 37306 : case OMP_CLAUSE_REDUCTION:
5145 37306 : case OMP_CLAUSE_IN_REDUCTION:
5146 37306 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
5147 29058 : || is_task_ctx (ctx)
5148 64024 : || OMP_CLAUSE_REDUCTION_TASK (c))
5149 : {
5150 12812 : task_reduction_p = true;
5151 12812 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5152 : {
5153 4564 : task_reduction_other_cnt++;
5154 4564 : if (pass == 2)
5155 1141 : continue;
5156 : }
5157 : else
5158 8248 : task_reduction_cnt++;
5159 11671 : if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5160 : {
5161 696 : var = OMP_CLAUSE_DECL (c);
5162 : /* If var is a global variable that isn't privatized
5163 : in outer contexts, we don't need to look up the
5164 : original address, it is always the address of the
5165 : global variable itself. */
5166 696 : if (!DECL_P (var)
5167 272 : || omp_privatize_by_reference (var)
5168 923 : || !is_global_var
5169 227 : (maybe_lookup_decl_in_outer_ctx (var, ctx)))
5170 : {
5171 594 : task_reduction_needs_orig_p = true;
5172 594 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5173 492 : task_reduction_cntorig++;
5174 : }
5175 : }
5176 : }
5177 24494 : else if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5178 358115 : reduction_omp_orig_ref = true;
5179 : break;
5180 3384 : case OMP_CLAUSE__REDUCTEMP_:
5181 3384 : if (!is_taskreg_ctx (ctx))
5182 1156 : continue;
5183 : /* FALLTHRU */
5184 111492 : case OMP_CLAUSE__LOOPTEMP_:
5185 : /* Handle _looptemp_/_reductemp_ clauses only on
5186 : parallel/task. */
5187 111492 : if (fd)
5188 69234 : continue;
5189 : break;
5190 43724 : case OMP_CLAUSE_LASTPRIVATE:
5191 43724 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5192 : {
5193 2066 : lastprivate_firstprivate = true;
5194 2066 : if (pass != 0 || is_taskloop_ctx (ctx))
5195 1347 : continue;
5196 : }
5197 : /* Even without corresponding firstprivate, if
5198 : decl is Fortran allocatable, it needs outer var
5199 : reference. */
5200 41658 : else if (pass == 0
5201 62451 : && lang_hooks.decls.omp_private_outer_ref
5202 20793 : (OMP_CLAUSE_DECL (c)))
5203 : lastprivate_firstprivate = true;
5204 : break;
5205 280 : case OMP_CLAUSE_ALIGNED:
5206 280 : if (pass != 1)
5207 140 : continue;
5208 140 : var = OMP_CLAUSE_DECL (c);
5209 140 : if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
5210 140 : && !is_global_var (var))
5211 : {
5212 76 : new_var = maybe_lookup_decl (var, ctx);
5213 76 : if (new_var == NULL_TREE)
5214 6 : new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
5215 76 : x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
5216 76 : tree alarg = omp_clause_aligned_alignment (c);
5217 76 : alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
5218 76 : x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
5219 76 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5220 76 : x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5221 76 : gimplify_and_add (x, ilist);
5222 : }
5223 64 : else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
5224 64 : && is_global_var (var))
5225 : {
5226 64 : tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
5227 64 : new_var = lookup_decl (var, ctx);
5228 64 : t = maybe_lookup_decl_in_outer_ctx (var, ctx);
5229 64 : t = build_fold_addr_expr_loc (clause_loc, t);
5230 64 : t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
5231 64 : tree alarg = omp_clause_aligned_alignment (c);
5232 64 : alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
5233 64 : t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
5234 64 : t = fold_convert_loc (clause_loc, ptype, t);
5235 64 : x = create_tmp_var (ptype);
5236 64 : t = build2 (MODIFY_EXPR, ptype, x, t);
5237 64 : gimplify_and_add (t, ilist);
5238 64 : t = build_simple_mem_ref_loc (clause_loc, x);
5239 64 : SET_DECL_VALUE_EXPR (new_var, t);
5240 64 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5241 : }
5242 140 : continue;
5243 1514 : case OMP_CLAUSE__CONDTEMP_:
5244 1514 : if (is_parallel_ctx (ctx)
5245 1514 : || (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c)))
5246 : break;
5247 1094 : continue;
5248 136108 : default:
5249 136108 : continue;
5250 137342 : }
5251 :
5252 358115 : if (task_reduction_p != (pass >= 2))
5253 15632 : continue;
5254 :
5255 342483 : allocator = NULL_TREE;
5256 342483 : allocate_ptr = NULL_TREE;
5257 342483 : new_var = var = OMP_CLAUSE_DECL (c);
5258 342483 : if ((c_kind == OMP_CLAUSE_REDUCTION
5259 342483 : || c_kind == OMP_CLAUSE_IN_REDUCTION)
5260 29705 : && TREE_CODE (var) == MEM_REF)
5261 : {
5262 4356 : var = TREE_OPERAND (var, 0);
5263 4356 : if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5264 773 : var = TREE_OPERAND (var, 0);
5265 4356 : if (TREE_CODE (var) == INDIRECT_REF
5266 4168 : || TREE_CODE (var) == ADDR_EXPR)
5267 2506 : var = TREE_OPERAND (var, 0);
5268 4356 : if (is_variable_sized (var))
5269 : {
5270 179 : gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5271 179 : var = DECL_VALUE_EXPR (var);
5272 179 : gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5273 179 : var = TREE_OPERAND (var, 0);
5274 179 : gcc_assert (DECL_P (var));
5275 : }
5276 4356 : new_var = var;
5277 : }
5278 29705 : if (c_kind == OMP_CLAUSE_IN_REDUCTION && is_omp_target (ctx->stmt))
5279 : {
5280 844 : splay_tree_key key = (splay_tree_key) &DECL_CONTEXT (var);
5281 844 : new_var = (tree) splay_tree_lookup (ctx->field_map, key)->value;
5282 : }
5283 341639 : else if (c_kind != OMP_CLAUSE_COPYIN)
5284 340611 : new_var = lookup_decl (var, ctx);
5285 :
5286 342483 : if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
5287 : {
5288 24904 : if (pass != 0)
5289 12451 : continue;
5290 : }
5291 : /* C/C++ array section reductions. */
5292 317579 : else if ((c_kind == OMP_CLAUSE_REDUCTION
5293 : || c_kind == OMP_CLAUSE_IN_REDUCTION)
5294 317579 : && var != OMP_CLAUSE_DECL (c))
5295 : {
5296 4356 : if (pass == 0)
5297 873 : continue;
5298 :
5299 3483 : tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
5300 3483 : tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
5301 :
5302 3483 : if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
5303 : {
5304 723 : tree b = TREE_OPERAND (orig_var, 1);
5305 723 : if (is_omp_target (ctx->stmt))
5306 : b = NULL_TREE;
5307 : else
5308 723 : b = maybe_lookup_decl (b, ctx);
5309 723 : if (b == NULL)
5310 : {
5311 17 : b = TREE_OPERAND (orig_var, 1);
5312 17 : b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5313 : }
5314 723 : if (integer_zerop (bias))
5315 : bias = b;
5316 : else
5317 : {
5318 0 : bias = fold_convert_loc (clause_loc,
5319 0 : TREE_TYPE (b), bias);
5320 0 : bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5321 0 : TREE_TYPE (b), b, bias);
5322 : }
5323 723 : orig_var = TREE_OPERAND (orig_var, 0);
5324 : }
5325 3483 : if (pass == 2)
5326 : {
5327 1149 : tree out = maybe_lookup_decl_in_outer_ctx (var, ctx);
5328 1149 : if (is_global_var (out)
5329 241 : && TREE_CODE (TREE_TYPE (out)) != POINTER_TYPE
5330 1336 : && (TREE_CODE (TREE_TYPE (out)) != REFERENCE_TYPE
5331 0 : || (TREE_CODE (TREE_TYPE (TREE_TYPE (out)))
5332 : != POINTER_TYPE)))
5333 : x = var;
5334 962 : else if (is_omp_target (ctx->stmt))
5335 : x = out;
5336 : else
5337 : {
5338 866 : bool by_ref = use_pointer_for_field (var, NULL);
5339 866 : x = build_receiver_ref (var, by_ref, ctx);
5340 866 : if (TREE_CODE (TREE_TYPE (var)) == REFERENCE_TYPE
5341 866 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (var)))
5342 : == POINTER_TYPE))
5343 32 : x = build_fold_addr_expr (x);
5344 : }
5345 1149 : if (TREE_CODE (orig_var) == INDIRECT_REF)
5346 40 : x = build_simple_mem_ref (x);
5347 1109 : else if (TREE_CODE (orig_var) == ADDR_EXPR)
5348 : {
5349 646 : if (var == TREE_OPERAND (orig_var, 0))
5350 583 : x = build_fold_addr_expr (x);
5351 : }
5352 1149 : bias = fold_convert (sizetype, bias);
5353 1149 : x = fold_convert (ptr_type_node, x);
5354 1149 : x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5355 1149 : TREE_TYPE (x), x, bias);
5356 1149 : unsigned cnt = task_reduction_cnt - 1;
5357 1149 : if (!task_reduction_needs_orig_p)
5358 1061 : cnt += (task_reduction_cntorig_full
5359 1061 : - task_reduction_cntorig);
5360 : else
5361 88 : cnt = task_reduction_cntorig - 1;
5362 1149 : tree r = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5363 1149 : size_int (cnt), NULL_TREE, NULL_TREE);
5364 1149 : gimplify_assign (r, x, ilist);
5365 1149 : continue;
5366 1149 : }
5367 :
5368 2334 : if (TREE_CODE (orig_var) == INDIRECT_REF
5369 2240 : || TREE_CODE (orig_var) == ADDR_EXPR)
5370 1362 : orig_var = TREE_OPERAND (orig_var, 0);
5371 2334 : tree d = OMP_CLAUSE_DECL (c);
5372 2334 : tree type = TREE_TYPE (d);
5373 2334 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
5374 2334 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5375 2334 : tree sz = v;
5376 2334 : const char *name = get_name (orig_var);
5377 2334 : if (pass != 3 && !TREE_CONSTANT (v))
5378 : {
5379 93 : tree t;
5380 93 : if (is_omp_target (ctx->stmt))
5381 : t = NULL_TREE;
5382 : else
5383 93 : t = maybe_lookup_decl (v, ctx);
5384 93 : if (t)
5385 88 : v = t;
5386 : else
5387 5 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5388 93 : gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
5389 186 : t = fold_build2_loc (clause_loc, PLUS_EXPR,
5390 93 : TREE_TYPE (v), v,
5391 93 : build_int_cst (TREE_TYPE (v), 1));
5392 93 : sz = fold_build2_loc (clause_loc, MULT_EXPR,
5393 93 : TREE_TYPE (v), t,
5394 93 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5395 : }
5396 2334 : if (pass == 3)
5397 : {
5398 1461 : tree xv = create_tmp_var (ptr_type_node);
5399 1461 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5400 : {
5401 1149 : unsigned cnt = task_reduction_cnt - 1;
5402 1149 : if (!task_reduction_needs_orig_p)
5403 1061 : cnt += (task_reduction_cntorig_full
5404 1061 : - task_reduction_cntorig);
5405 : else
5406 88 : cnt = task_reduction_cntorig - 1;
5407 1149 : x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5408 1149 : size_int (cnt), NULL_TREE, NULL_TREE);
5409 :
5410 1149 : gimple *g = gimple_build_assign (xv, x);
5411 1149 : gimple_seq_add_stmt (ilist, g);
5412 : }
5413 : else
5414 : {
5415 312 : unsigned int idx = *ctx->task_reduction_map->get (c);
5416 312 : tree off;
5417 312 : if (ctx->task_reductions[1 + idx])
5418 81 : off = fold_convert (sizetype,
5419 : ctx->task_reductions[1 + idx]);
5420 : else
5421 231 : off = task_reduction_read (ilist, tskred_temp, sizetype,
5422 231 : 7 + 3 * idx + 1);
5423 312 : gimple *g = gimple_build_assign (xv, POINTER_PLUS_EXPR,
5424 : tskred_base, off);
5425 312 : gimple_seq_add_stmt (ilist, g);
5426 : }
5427 1461 : x = fold_convert (build_pointer_type (boolean_type_node),
5428 : xv);
5429 1461 : if (TREE_CONSTANT (v))
5430 1065 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (x), x,
5431 : TYPE_SIZE_UNIT (type));
5432 : else
5433 : {
5434 396 : tree t;
5435 396 : if (is_omp_target (ctx->stmt))
5436 : t = NULL_TREE;
5437 : else
5438 336 : t = maybe_lookup_decl (v, ctx);
5439 336 : if (t)
5440 316 : v = t;
5441 : else
5442 80 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5443 396 : gimplify_expr (&v, ilist, NULL, is_gimple_val,
5444 : fb_rvalue);
5445 792 : t = fold_build2_loc (clause_loc, PLUS_EXPR,
5446 396 : TREE_TYPE (v), v,
5447 396 : build_int_cst (TREE_TYPE (v), 1));
5448 396 : t = fold_build2_loc (clause_loc, MULT_EXPR,
5449 396 : TREE_TYPE (v), t,
5450 396 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5451 396 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (x), x, t);
5452 : }
5453 1461 : cond = create_tmp_var (TREE_TYPE (x));
5454 1461 : gimplify_assign (cond, x, ilist);
5455 1461 : x = xv;
5456 : }
5457 873 : else if (lower_private_allocate (var, type, allocator,
5458 : allocate_ptr, ilist, ctx,
5459 : true,
5460 873 : TREE_CONSTANT (v)
5461 780 : ? TYPE_SIZE_UNIT (type)
5462 : : sz))
5463 225 : x = allocate_ptr;
5464 648 : else if (TREE_CONSTANT (v))
5465 : {
5466 560 : x = create_tmp_var_raw (type, name);
5467 560 : gimple_add_tmp_var (x);
5468 560 : TREE_ADDRESSABLE (x) = 1;
5469 560 : x = build_fold_addr_expr_loc (clause_loc, x);
5470 : }
5471 : else
5472 : {
5473 88 : tree atmp
5474 88 : = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5475 88 : tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
5476 88 : x = build_call_expr_loc (clause_loc, atmp, 2, sz, al);
5477 : }
5478 :
5479 2334 : tree ptype = build_pointer_type (TREE_TYPE (type));
5480 2334 : x = fold_convert_loc (clause_loc, ptype, x);
5481 2334 : tree y = create_tmp_var (ptype, name);
5482 2334 : gimplify_assign (y, x, ilist);
5483 2334 : x = y;
5484 2334 : tree yb = y;
5485 :
5486 2334 : if (!integer_zerop (bias))
5487 : {
5488 1512 : bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
5489 : bias);
5490 1512 : yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
5491 : x);
5492 1512 : yb = fold_build2_loc (clause_loc, MINUS_EXPR,
5493 : pointer_sized_int_node, yb, bias);
5494 1512 : x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
5495 1512 : yb = create_tmp_var (ptype, name);
5496 1512 : gimplify_assign (yb, x, ilist);
5497 1512 : x = yb;
5498 : }
5499 :
5500 2334 : d = TREE_OPERAND (d, 0);
5501 2334 : if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5502 420 : d = TREE_OPERAND (d, 0);
5503 2334 : if (TREE_CODE (d) == ADDR_EXPR)
5504 : {
5505 1268 : if (orig_var != var)
5506 : {
5507 91 : gcc_assert (is_variable_sized (orig_var));
5508 91 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
5509 : x);
5510 91 : gimplify_assign (new_var, x, ilist);
5511 91 : tree new_orig_var = lookup_decl (orig_var, ctx);
5512 91 : tree t = build_fold_indirect_ref (new_var);
5513 91 : DECL_IGNORED_P (new_var) = 0;
5514 91 : TREE_THIS_NOTRAP (t) = 1;
5515 91 : SET_DECL_VALUE_EXPR (new_orig_var, t);
5516 91 : DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
5517 : }
5518 : else
5519 : {
5520 1177 : x = build2 (MEM_REF, TREE_TYPE (new_var), x,
5521 : build_int_cst (ptype, 0));
5522 1177 : SET_DECL_VALUE_EXPR (new_var, x);
5523 1177 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5524 : }
5525 : }
5526 : else
5527 : {
5528 1066 : gcc_assert (orig_var == var);
5529 1066 : if (TREE_CODE (d) == INDIRECT_REF)
5530 : {
5531 94 : x = create_tmp_var (ptype, name);
5532 94 : TREE_ADDRESSABLE (x) = 1;
5533 94 : gimplify_assign (x, yb, ilist);
5534 94 : x = build_fold_addr_expr_loc (clause_loc, x);
5535 : }
5536 1066 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5537 1066 : gimplify_assign (new_var, x, ilist);
5538 : }
5539 : /* GOMP_taskgroup_reduction_register memsets the whole
5540 : array to zero. If the initializer is zero, we don't
5541 : need to initialize it again, just mark it as ever
5542 : used unconditionally, i.e. cond = true. */
5543 2334 : if (cond
5544 1461 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE
5545 3267 : && initializer_zerop (omp_reduction_init (c,
5546 933 : TREE_TYPE (type))))
5547 : {
5548 624 : gimple *g = gimple_build_assign (build_simple_mem_ref (cond),
5549 : boolean_true_node);
5550 624 : gimple_seq_add_stmt (ilist, g);
5551 624 : continue;
5552 624 : }
5553 1710 : tree end = create_artificial_label (UNKNOWN_LOCATION);
5554 1710 : if (cond)
5555 : {
5556 837 : gimple *g;
5557 837 : if (!is_parallel_ctx (ctx))
5558 : {
5559 786 : tree condv = create_tmp_var (boolean_type_node);
5560 786 : g = gimple_build_assign (condv,
5561 : build_simple_mem_ref (cond));
5562 786 : gimple_seq_add_stmt (ilist, g);
5563 786 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
5564 786 : g = gimple_build_cond (NE_EXPR, condv,
5565 : boolean_false_node, end, lab1);
5566 786 : gimple_seq_add_stmt (ilist, g);
5567 786 : gimple_seq_add_stmt (ilist, gimple_build_label (lab1));
5568 : }
5569 837 : g = gimple_build_assign (build_simple_mem_ref (cond),
5570 : boolean_true_node);
5571 837 : gimple_seq_add_stmt (ilist, g);
5572 : }
5573 :
5574 1710 : tree y1 = create_tmp_var (ptype);
5575 1710 : gimplify_assign (y1, y, ilist);
5576 1710 : tree i2 = NULL_TREE, y2 = NULL_TREE;
5577 1710 : tree body2 = NULL_TREE, end2 = NULL_TREE;
5578 1710 : tree y3 = NULL_TREE, y4 = NULL_TREE;
5579 1710 : if (task_reduction_needs_orig_p)
5580 : {
5581 112 : y3 = create_tmp_var (ptype);
5582 112 : tree ref;
5583 112 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5584 88 : ref = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5585 88 : size_int (task_reduction_cnt_full
5586 : + task_reduction_cntorig - 1),
5587 : NULL_TREE, NULL_TREE);
5588 : else
5589 : {
5590 24 : unsigned int idx = *ctx->task_reduction_map->get (c);
5591 24 : ref = task_reduction_read (ilist, tskred_temp, ptype,
5592 24 : 7 + 3 * idx);
5593 : }
5594 112 : gimplify_assign (y3, ref, ilist);
5595 : }
5596 1598 : else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
5597 : {
5598 668 : if (pass != 3)
5599 : {
5600 252 : y2 = create_tmp_var (ptype);
5601 252 : gimplify_assign (y2, y, ilist);
5602 : }
5603 668 : if (is_simd || OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5604 : {
5605 188 : tree ref = build_outer_var_ref (var, ctx);
5606 : /* For ref build_outer_var_ref already performs this. */
5607 188 : if (TREE_CODE (d) == INDIRECT_REF)
5608 0 : gcc_assert (omp_privatize_by_reference (var));
5609 188 : else if (TREE_CODE (d) == ADDR_EXPR)
5610 96 : ref = build_fold_addr_expr (ref);
5611 92 : else if (omp_privatize_by_reference (var))
5612 8 : ref = build_fold_addr_expr (ref);
5613 188 : ref = fold_convert_loc (clause_loc, ptype, ref);
5614 188 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5615 188 : && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
5616 : {
5617 8 : y3 = create_tmp_var (ptype);
5618 8 : gimplify_assign (y3, unshare_expr (ref), ilist);
5619 : }
5620 188 : if (is_simd)
5621 : {
5622 180 : y4 = create_tmp_var (ptype);
5623 180 : gimplify_assign (y4, ref, dlist);
5624 : }
5625 : }
5626 : }
5627 1710 : tree i = create_tmp_var (TREE_TYPE (v));
5628 1710 : gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
5629 1710 : tree body = create_artificial_label (UNKNOWN_LOCATION);
5630 1710 : gimple_seq_add_stmt (ilist, gimple_build_label (body));
5631 1710 : if (y2)
5632 : {
5633 252 : i2 = create_tmp_var (TREE_TYPE (v));
5634 252 : gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
5635 252 : body2 = create_artificial_label (UNKNOWN_LOCATION);
5636 252 : end2 = create_artificial_label (UNKNOWN_LOCATION);
5637 252 : gimple_seq_add_stmt (dlist, gimple_build_label (body2));
5638 : }
5639 1710 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5640 : {
5641 600 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5642 600 : tree decl_placeholder
5643 600 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5644 600 : SET_DECL_VALUE_EXPR (decl_placeholder,
5645 : build_simple_mem_ref (y1));
5646 600 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5647 600 : SET_DECL_VALUE_EXPR (placeholder,
5648 : y3 ? build_simple_mem_ref (y3)
5649 : : error_mark_node);
5650 600 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5651 600 : x = lang_hooks.decls.omp_clause_default_ctor
5652 720 : (c, build_simple_mem_ref (y1),
5653 120 : y3 ? build_simple_mem_ref (y3) : NULL_TREE);
5654 600 : if (x)
5655 152 : gimplify_and_add (x, ilist);
5656 600 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5657 : {
5658 576 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5659 576 : lower_omp (&tseq, ctx);
5660 576 : gimple_seq_add_seq (ilist, tseq);
5661 : }
5662 600 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5663 600 : if (is_simd)
5664 : {
5665 0 : SET_DECL_VALUE_EXPR (decl_placeholder,
5666 : build_simple_mem_ref (y2));
5667 0 : SET_DECL_VALUE_EXPR (placeholder,
5668 : build_simple_mem_ref (y4));
5669 0 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5670 0 : lower_omp (&tseq, ctx);
5671 0 : gimple_seq_add_seq (dlist, tseq);
5672 0 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5673 : }
5674 600 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5675 600 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
5676 600 : if (y2)
5677 : {
5678 72 : x = lang_hooks.decls.omp_clause_dtor
5679 72 : (c, build_simple_mem_ref (y2));
5680 72 : if (x)
5681 40 : gimplify_and_add (x, dlist);
5682 : }
5683 : }
5684 : else
5685 : {
5686 1110 : x = omp_reduction_init (c, TREE_TYPE (type));
5687 1110 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5688 :
5689 : /* reduction(-:var) sums up the partial results, so it
5690 : acts identically to reduction(+:var). */
5691 1110 : if (code == MINUS_EXPR)
5692 0 : code = PLUS_EXPR;
5693 :
5694 1110 : gimplify_assign (build_simple_mem_ref (y1), x, ilist);
5695 1110 : if (is_simd)
5696 : {
5697 180 : x = build2 (code, TREE_TYPE (type),
5698 : build_simple_mem_ref (y4),
5699 : build_simple_mem_ref (y2));
5700 180 : gimplify_assign (build_simple_mem_ref (y4), x, dlist);
5701 : }
5702 : }
5703 1710 : gimple *g
5704 1710 : = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
5705 1710 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5706 1710 : gimple_seq_add_stmt (ilist, g);
5707 1710 : if (y3)
5708 : {
5709 120 : g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
5710 120 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5711 120 : gimple_seq_add_stmt (ilist, g);
5712 : }
5713 1710 : g = gimple_build_assign (i, PLUS_EXPR, i,
5714 1710 : build_int_cst (TREE_TYPE (i), 1));
5715 1710 : gimple_seq_add_stmt (ilist, g);
5716 1710 : g = gimple_build_cond (LE_EXPR, i, v, body, end);
5717 1710 : gimple_seq_add_stmt (ilist, g);
5718 1710 : gimple_seq_add_stmt (ilist, gimple_build_label (end));
5719 1710 : if (y2)
5720 : {
5721 252 : g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
5722 252 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5723 252 : gimple_seq_add_stmt (dlist, g);
5724 252 : if (y4)
5725 : {
5726 180 : g = gimple_build_assign
5727 180 : (y4, POINTER_PLUS_EXPR, y4,
5728 180 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5729 180 : gimple_seq_add_stmt (dlist, g);
5730 : }
5731 252 : g = gimple_build_assign (i2, PLUS_EXPR, i2,
5732 252 : build_int_cst (TREE_TYPE (i2), 1));
5733 252 : gimple_seq_add_stmt (dlist, g);
5734 252 : g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
5735 252 : gimple_seq_add_stmt (dlist, g);
5736 252 : gimple_seq_add_stmt (dlist, gimple_build_label (end2));
5737 : }
5738 1710 : if (allocator)
5739 : {
5740 225 : tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
5741 225 : g = gimple_build_call (f, 2, allocate_ptr, allocator);
5742 225 : gimple_seq_add_stmt (dlist, g);
5743 : }
5744 1710 : continue;
5745 1710 : }
5746 313223 : else if (pass == 2)
5747 : {
5748 913 : tree out = maybe_lookup_decl_in_outer_ctx (var, ctx);
5749 913 : if (is_global_var (out))
5750 : x = var;
5751 361 : else if (is_omp_target (ctx->stmt))
5752 : x = out;
5753 : else
5754 : {
5755 301 : bool by_ref = use_pointer_for_field (var, ctx);
5756 301 : x = build_receiver_ref (var, by_ref, ctx);
5757 : }
5758 913 : if (!omp_privatize_by_reference (var))
5759 823 : x = build_fold_addr_expr (x);
5760 913 : x = fold_convert (ptr_type_node, x);
5761 913 : unsigned cnt = task_reduction_cnt - 1;
5762 913 : if (!task_reduction_needs_orig_p)
5763 878 : cnt += task_reduction_cntorig_full - task_reduction_cntorig;
5764 : else
5765 35 : cnt = task_reduction_cntorig - 1;
5766 913 : tree r = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5767 913 : size_int (cnt), NULL_TREE, NULL_TREE);
5768 913 : gimplify_assign (r, x, ilist);
5769 913 : continue;
5770 913 : }
5771 312310 : else if (pass == 3)
5772 : {
5773 1742 : tree type = TREE_TYPE (new_var);
5774 1742 : if (!omp_privatize_by_reference (var))
5775 1636 : type = build_pointer_type (type);
5776 1742 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5777 : {
5778 913 : unsigned cnt = task_reduction_cnt - 1;
5779 913 : if (!task_reduction_needs_orig_p)
5780 878 : cnt += (task_reduction_cntorig_full
5781 878 : - task_reduction_cntorig);
5782 : else
5783 35 : cnt = task_reduction_cntorig - 1;
5784 913 : x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
5785 913 : size_int (cnt), NULL_TREE, NULL_TREE);
5786 : }
5787 : else
5788 : {
5789 829 : unsigned int idx = *ctx->task_reduction_map->get (c);
5790 829 : tree off;
5791 829 : if (ctx->task_reductions[1 + idx])
5792 829 : off = fold_convert (sizetype,
5793 : ctx->task_reductions[1 + idx]);
5794 : else
5795 0 : off = task_reduction_read (ilist, tskred_temp, sizetype,
5796 0 : 7 + 3 * idx + 1);
5797 829 : x = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
5798 : tskred_base, off);
5799 : }
5800 1742 : x = fold_convert (type, x);
5801 1742 : tree t;
5802 1742 : if (omp_privatize_by_reference (var))
5803 : {
5804 106 : gimplify_assign (new_var, x, ilist);
5805 106 : t = new_var;
5806 106 : new_var = build_simple_mem_ref (new_var);
5807 : }
5808 : else
5809 : {
5810 1636 : t = create_tmp_var (type);
5811 1636 : gimplify_assign (t, x, ilist);
5812 1636 : SET_DECL_VALUE_EXPR (new_var, build_simple_mem_ref (t));
5813 1636 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5814 : }
5815 1742 : t = fold_convert (build_pointer_type (boolean_type_node), t);
5816 1742 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t,
5817 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
5818 1742 : cond = create_tmp_var (TREE_TYPE (t));
5819 1742 : gimplify_assign (cond, t, ilist);
5820 : }
5821 310568 : else if (is_variable_sized (var))
5822 : {
5823 : /* For variable sized types, we need to allocate the
5824 : actual storage here. Call alloca and store the
5825 : result in the pointer decl that we created elsewhere. */
5826 262 : if (pass == 0)
5827 134 : continue;
5828 :
5829 128 : if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
5830 : {
5831 114 : tree tmp;
5832 :
5833 114 : ptr = DECL_VALUE_EXPR (new_var);
5834 114 : gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
5835 114 : ptr = TREE_OPERAND (ptr, 0);
5836 114 : gcc_assert (DECL_P (ptr));
5837 114 : x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
5838 :
5839 114 : if (lower_private_allocate (var, new_var, allocator,
5840 : allocate_ptr, ilist, ctx,
5841 : false, x))
5842 8 : tmp = allocate_ptr;
5843 : else
5844 : {
5845 : /* void *tmp = __builtin_alloca */
5846 106 : tree atmp
5847 106 : = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5848 106 : gcall *stmt
5849 106 : = gimple_build_call (atmp, 2, x,
5850 106 : size_int (DECL_ALIGN (var)));
5851 106 : cfun->calls_alloca = 1;
5852 106 : tmp = create_tmp_var_raw (ptr_type_node);
5853 106 : gimple_add_tmp_var (tmp);
5854 106 : gimple_call_set_lhs (stmt, tmp);
5855 :
5856 106 : gimple_seq_add_stmt (ilist, stmt);
5857 : }
5858 :
5859 114 : x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
5860 114 : gimplify_assign (ptr, x, ilist);
5861 : }
5862 : }
5863 310306 : else if (omp_privatize_by_reference (var)
5864 310306 : && (c_kind != OMP_CLAUSE_FIRSTPRIVATE
5865 2016 : || !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)))
5866 : {
5867 : /* For references that are being privatized for Fortran,
5868 : allocate new backing storage for the new pointer
5869 : variable. This allows us to avoid changing all the
5870 : code that expects a pointer to something that expects
5871 : a direct variable. */
5872 4895 : if (pass == 0)
5873 2550 : continue;
5874 :
5875 2345 : x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
5876 2345 : if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
5877 : {
5878 146 : x = build_receiver_ref (var, false, ctx);
5879 146 : if (ctx->allocate_map)
5880 16 : if (tree *allocatep = ctx->allocate_map->get (var))
5881 : {
5882 16 : allocator = *allocatep;
5883 16 : if (TREE_CODE (allocator) == TREE_LIST)
5884 0 : allocator = TREE_PURPOSE (allocator);
5885 16 : if (TREE_CODE (allocator) != INTEGER_CST)
5886 8 : allocator = build_outer_var_ref (allocator, ctx);
5887 16 : allocator = fold_convert (pointer_sized_int_node,
5888 : allocator);
5889 16 : allocate_ptr = unshare_expr (x);
5890 : }
5891 146 : if (allocator == NULL_TREE)
5892 130 : x = build_fold_addr_expr_loc (clause_loc, x);
5893 : }
5894 2199 : else if (lower_private_allocate (var, new_var, allocator,
5895 : allocate_ptr,
5896 : ilist, ctx, true, x))
5897 86 : x = allocate_ptr;
5898 2113 : else if (TREE_CONSTANT (x))
5899 : {
5900 : /* For reduction in SIMD loop, defer adding the
5901 : initialization of the reference, because if we decide
5902 : to use SIMD array for it, the initialization could cause
5903 : expansion ICE. Ditto for other privatization clauses. */
5904 1404 : if (is_simd)
5905 : x = NULL_TREE;
5906 : else
5907 : {
5908 1077 : x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
5909 : get_name (var));
5910 1077 : gimple_add_tmp_var (x);
5911 1077 : TREE_ADDRESSABLE (x) = 1;
5912 1077 : x = build_fold_addr_expr_loc (clause_loc, x);
5913 : }
5914 : }
5915 : else
5916 : {
5917 709 : tree atmp
5918 709 : = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
5919 709 : tree rtype = TREE_TYPE (TREE_TYPE (new_var));
5920 709 : tree al = size_int (TYPE_ALIGN (rtype));
5921 709 : x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
5922 : }
5923 :
5924 2018 : if (x)
5925 : {
5926 2018 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
5927 2018 : gimplify_assign (new_var, x, ilist);
5928 : }
5929 :
5930 2345 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5931 : }
5932 305411 : else if ((c_kind == OMP_CLAUSE_REDUCTION
5933 : || c_kind == OMP_CLAUSE_IN_REDUCTION)
5934 305411 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5935 : {
5936 1980 : if (pass == 0)
5937 990 : continue;
5938 : }
5939 303431 : else if (pass != 0)
5940 151459 : continue;
5941 :
5942 169630 : switch (OMP_CLAUSE_CODE (c))
5943 : {
5944 11939 : case OMP_CLAUSE_SHARED:
5945 : /* Ignore shared directives in teams construct inside
5946 : target construct. */
5947 11939 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS
5948 11939 : && !is_host_teams_ctx (ctx))
5949 0 : continue;
5950 : /* Shared global vars are just accessed directly. */
5951 11939 : if (is_global_var (new_var))
5952 : break;
5953 : /* For taskloop firstprivate/lastprivate, represented
5954 : as firstprivate and shared clause on the task, new_var
5955 : is the firstprivate var. */
5956 11785 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5957 : break;
5958 : /* Set up the DECL_VALUE_EXPR for shared variables now. This
5959 : needs to be delayed until after fixup_child_record_type so
5960 : that we get the correct type during the dereference. */
5961 11473 : by_ref = use_pointer_for_field (var, ctx);
5962 11473 : x = build_receiver_ref (var, by_ref, ctx);
5963 11473 : SET_DECL_VALUE_EXPR (new_var, x);
5964 11473 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5965 :
5966 : /* ??? If VAR is not passed by reference, and the variable
5967 : hasn't been initialized yet, then we'll get a warning for
5968 : the store into the omp_data_s structure. Ideally, we'd be
5969 : able to notice this and not store anything at all, but
5970 : we're generating code too early. Suppress the warning. */
5971 11473 : if (!by_ref)
5972 5242 : suppress_warning (var, OPT_Wuninitialized);
5973 : break;
5974 :
5975 210 : case OMP_CLAUSE__CONDTEMP_:
5976 210 : if (is_parallel_ctx (ctx))
5977 : {
5978 103 : x = build_receiver_ref (var, false, ctx);
5979 103 : SET_DECL_VALUE_EXPR (new_var, x);
5980 103 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5981 : }
5982 107 : else if (is_simd && !OMP_CLAUSE__CONDTEMP__ITER (c))
5983 : {
5984 107 : x = build_zero_cst (TREE_TYPE (var));
5985 107 : goto do_private;
5986 : }
5987 : break;
5988 :
5989 21301 : case OMP_CLAUSE_LASTPRIVATE:
5990 21301 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5991 : break;
5992 : /* FALLTHRU */
5993 :
5994 87472 : case OMP_CLAUSE_PRIVATE:
5995 87472 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
5996 20793 : x = build_outer_var_ref (var, ctx);
5997 66679 : else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5998 : {
5999 163 : if (is_task_ctx (ctx))
6000 12 : x = build_receiver_ref (var, false, ctx);
6001 : else
6002 151 : x = build_outer_var_ref (var, ctx, OMP_CLAUSE_PRIVATE);
6003 : }
6004 : else
6005 : x = NULL;
6006 94119 : do_private:
6007 94119 : tree nx;
6008 94119 : bool copy_ctor;
6009 94119 : copy_ctor = false;
6010 94119 : lower_private_allocate (var, new_var, allocator, allocate_ptr,
6011 : ilist, ctx, false, NULL_TREE);
6012 94119 : nx = unshare_expr (new_var);
6013 94119 : if (is_simd
6014 24202 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6015 101505 : && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
6016 22 : copy_ctor = true;
6017 94119 : if (copy_ctor)
6018 22 : nx = lang_hooks.decls.omp_clause_copy_ctor (c, nx, x);
6019 : else
6020 94097 : nx = lang_hooks.decls.omp_clause_default_ctor (c, nx, x);
6021 94119 : if (is_simd)
6022 : {
6023 24202 : tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
6024 23520 : if ((TREE_ADDRESSABLE (new_var) || nx || y
6025 23504 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6026 7010 : && (gimple_omp_for_collapse (ctx->stmt) != 1
6027 1375 : || (gimple_omp_for_index (ctx->stmt, 0)
6028 : != new_var)))
6029 16796 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_
6030 16689 : || omp_privatize_by_reference (var))
6031 31067 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6032 : ivar, lvar))
6033 : {
6034 5981 : if (omp_privatize_by_reference (var))
6035 : {
6036 52 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6037 52 : tree new_vard = TREE_OPERAND (new_var, 0);
6038 52 : gcc_assert (DECL_P (new_vard));
6039 52 : SET_DECL_VALUE_EXPR (new_vard,
6040 : build_fold_addr_expr (lvar));
6041 52 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6042 : }
6043 :
6044 5981 : if (nx)
6045 : {
6046 30 : tree iv = unshare_expr (ivar);
6047 30 : if (copy_ctor)
6048 22 : x = lang_hooks.decls.omp_clause_copy_ctor (c, iv,
6049 : x);
6050 : else
6051 8 : x = lang_hooks.decls.omp_clause_default_ctor (c,
6052 : iv,
6053 : x);
6054 : }
6055 5951 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__CONDTEMP_)
6056 : {
6057 37 : x = build2 (MODIFY_EXPR, TREE_TYPE (ivar),
6058 : unshare_expr (ivar), x);
6059 37 : nx = x;
6060 : }
6061 5981 : if (nx && x)
6062 67 : gimplify_and_add (x, &llist[0]);
6063 5981 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6064 5981 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
6065 : {
6066 37 : tree v = new_var;
6067 37 : if (!DECL_P (v))
6068 : {
6069 4 : gcc_assert (TREE_CODE (v) == MEM_REF);
6070 4 : v = TREE_OPERAND (v, 0);
6071 4 : gcc_assert (DECL_P (v));
6072 : }
6073 37 : v = *ctx->lastprivate_conditional_map->get (v);
6074 37 : tree t = create_tmp_var (TREE_TYPE (v));
6075 37 : tree z = build_zero_cst (TREE_TYPE (v));
6076 37 : tree orig_v
6077 37 : = build_outer_var_ref (var, ctx,
6078 : OMP_CLAUSE_LASTPRIVATE);
6079 37 : gimple_seq_add_stmt (dlist,
6080 37 : gimple_build_assign (t, z));
6081 37 : gcc_assert (DECL_HAS_VALUE_EXPR_P (v));
6082 37 : tree civar = DECL_VALUE_EXPR (v);
6083 37 : gcc_assert (TREE_CODE (civar) == ARRAY_REF);
6084 37 : civar = unshare_expr (civar);
6085 37 : TREE_OPERAND (civar, 1) = sctx.idx;
6086 37 : x = build2 (MODIFY_EXPR, TREE_TYPE (t), t,
6087 : unshare_expr (civar));
6088 74 : x = build2 (COMPOUND_EXPR, TREE_TYPE (orig_v), x,
6089 37 : build2 (MODIFY_EXPR, TREE_TYPE (orig_v),
6090 : orig_v, unshare_expr (ivar)));
6091 37 : tree cond = build2 (LT_EXPR, boolean_type_node, t,
6092 : civar);
6093 37 : x = build3 (COND_EXPR, void_type_node, cond, x,
6094 : void_node);
6095 37 : gimple_seq tseq = NULL;
6096 37 : gimplify_and_add (x, &tseq);
6097 37 : if (ctx->outer)
6098 27 : lower_omp (&tseq, ctx->outer);
6099 37 : gimple_seq_add_seq (&llist[1], tseq);
6100 : }
6101 5981 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6102 5981 : && ctx->for_simd_scan_phase)
6103 : {
6104 9 : x = unshare_expr (ivar);
6105 9 : tree orig_v
6106 9 : = build_outer_var_ref (var, ctx,
6107 : OMP_CLAUSE_LASTPRIVATE);
6108 9 : x = lang_hooks.decls.omp_clause_assign_op (c, x,
6109 : orig_v);
6110 9 : gimplify_and_add (x, &llist[0]);
6111 : }
6112 5981 : if (y)
6113 : {
6114 30 : y = lang_hooks.decls.omp_clause_dtor (c, ivar);
6115 30 : if (y)
6116 30 : gimplify_and_add (y, &llist[1]);
6117 : }
6118 : break;
6119 : }
6120 18221 : if (omp_privatize_by_reference (var))
6121 : {
6122 28 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6123 28 : tree new_vard = TREE_OPERAND (new_var, 0);
6124 28 : gcc_assert (DECL_P (new_vard));
6125 28 : tree type = TREE_TYPE (TREE_TYPE (new_vard));
6126 28 : x = TYPE_SIZE_UNIT (type);
6127 28 : if (TREE_CONSTANT (x))
6128 : {
6129 28 : x = create_tmp_var_raw (type, get_name (var));
6130 28 : gimple_add_tmp_var (x);
6131 28 : TREE_ADDRESSABLE (x) = 1;
6132 28 : x = build_fold_addr_expr_loc (clause_loc, x);
6133 28 : x = fold_convert_loc (clause_loc,
6134 28 : TREE_TYPE (new_vard), x);
6135 28 : gimplify_assign (new_vard, x, ilist);
6136 : }
6137 : }
6138 : }
6139 88138 : if (nx)
6140 488 : gimplify_and_add (nx, ilist);
6141 88138 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6142 15170 : && is_simd
6143 89901 : && ctx->for_simd_scan_phase)
6144 : {
6145 5 : tree orig_v = build_outer_var_ref (var, ctx,
6146 : OMP_CLAUSE_LASTPRIVATE);
6147 5 : x = lang_hooks.decls.omp_clause_assign_op (c, new_var,
6148 : orig_v);
6149 5 : gimplify_and_add (x, ilist);
6150 : }
6151 : /* FALLTHRU */
6152 :
6153 119032 : do_dtor:
6154 119032 : x = lang_hooks.decls.omp_clause_dtor (c, new_var);
6155 119032 : if (x)
6156 1134 : gimplify_and_add (x, dlist);
6157 119032 : if (allocator)
6158 : {
6159 864 : if (!is_gimple_val (allocator))
6160 : {
6161 22 : tree avar = create_tmp_var (TREE_TYPE (allocator));
6162 22 : gimplify_assign (avar, allocator, dlist);
6163 22 : allocator = avar;
6164 : }
6165 864 : if (!is_gimple_val (allocate_ptr))
6166 : {
6167 50 : tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr));
6168 50 : gimplify_assign (apvar, allocate_ptr, dlist);
6169 50 : allocate_ptr = apvar;
6170 : }
6171 864 : tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
6172 864 : gimple *g
6173 864 : = gimple_build_call (f, 2, allocate_ptr, allocator);
6174 864 : gimple_seq_add_stmt (dlist, g);
6175 : }
6176 : break;
6177 :
6178 7809 : case OMP_CLAUSE_LINEAR:
6179 7809 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
6180 1269 : goto do_firstprivate;
6181 6540 : if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
6182 : x = NULL;
6183 : else
6184 3601 : x = build_outer_var_ref (var, ctx);
6185 6540 : goto do_private;
6186 :
6187 28731 : case OMP_CLAUSE_FIRSTPRIVATE:
6188 28731 : if (is_task_ctx (ctx))
6189 : {
6190 4631 : if ((omp_privatize_by_reference (var)
6191 146 : && !OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c))
6192 4631 : || is_variable_sized (var))
6193 160 : goto do_dtor;
6194 4471 : else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
6195 : ctx))
6196 4471 : || use_pointer_for_field (var, NULL))
6197 : {
6198 421 : x = build_receiver_ref (var, false, ctx);
6199 421 : if (ctx->allocate_map)
6200 34 : if (tree *allocatep = ctx->allocate_map->get (var))
6201 : {
6202 34 : allocator = *allocatep;
6203 34 : if (TREE_CODE (allocator) == TREE_LIST)
6204 4 : allocator = TREE_PURPOSE (allocator);
6205 34 : if (TREE_CODE (allocator) != INTEGER_CST)
6206 14 : allocator = build_outer_var_ref (allocator, ctx);
6207 34 : allocator = fold_convert (pointer_sized_int_node,
6208 : allocator);
6209 34 : allocate_ptr = unshare_expr (x);
6210 34 : x = build_simple_mem_ref (x);
6211 34 : TREE_THIS_NOTRAP (x) = 1;
6212 : }
6213 421 : SET_DECL_VALUE_EXPR (new_var, x);
6214 421 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
6215 421 : goto do_dtor;
6216 : }
6217 : }
6218 28150 : if (OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c)
6219 28150 : && omp_privatize_by_reference (var))
6220 : {
6221 0 : x = build_outer_var_ref (var, ctx);
6222 0 : gcc_assert (TREE_CODE (x) == MEM_REF
6223 : && integer_zerop (TREE_OPERAND (x, 1)));
6224 0 : x = TREE_OPERAND (x, 0);
6225 0 : x = lang_hooks.decls.omp_clause_copy_ctor
6226 0 : (c, unshare_expr (new_var), x);
6227 0 : gimplify_and_add (x, ilist);
6228 0 : goto do_dtor;
6229 : }
6230 29419 : do_firstprivate:
6231 29419 : lower_private_allocate (var, new_var, allocator, allocate_ptr,
6232 : ilist, ctx, false, NULL_TREE);
6233 29419 : x = build_outer_var_ref (var, ctx);
6234 29419 : if (is_simd)
6235 : {
6236 1063 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
6237 1063 : && gimple_omp_for_combined_into_p (ctx->stmt))
6238 : {
6239 668 : tree t = OMP_CLAUSE_LINEAR_STEP (c);
6240 668 : if (DECL_P (t))
6241 114 : t = build_outer_var_ref (t, ctx);
6242 668 : tree stept = TREE_TYPE (t);
6243 668 : tree ct = omp_find_clause (clauses,
6244 : OMP_CLAUSE__LOOPTEMP_);
6245 668 : gcc_assert (ct);
6246 668 : tree l = OMP_CLAUSE_DECL (ct);
6247 668 : tree n1 = fd->loop.n1;
6248 668 : tree step = fd->loop.step;
6249 668 : tree itype = TREE_TYPE (l);
6250 668 : if (POINTER_TYPE_P (itype))
6251 0 : itype = signed_type_for (itype);
6252 668 : l = fold_build2 (MINUS_EXPR, itype, l, n1);
6253 668 : if (TYPE_UNSIGNED (itype)
6254 668 : && fd->loop.cond_code == GT_EXPR)
6255 0 : l = fold_build2 (TRUNC_DIV_EXPR, itype,
6256 : fold_build1 (NEGATE_EXPR, itype, l),
6257 : fold_build1 (NEGATE_EXPR,
6258 : itype, step));
6259 : else
6260 668 : l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
6261 668 : t = fold_build2 (MULT_EXPR, stept,
6262 : fold_convert (stept, l), t);
6263 :
6264 668 : if (OMP_CLAUSE_LINEAR_ARRAY (c))
6265 : {
6266 108 : if (omp_privatize_by_reference (var))
6267 : {
6268 72 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6269 72 : tree new_vard = TREE_OPERAND (new_var, 0);
6270 72 : gcc_assert (DECL_P (new_vard));
6271 72 : tree type = TREE_TYPE (TREE_TYPE (new_vard));
6272 72 : nx = TYPE_SIZE_UNIT (type);
6273 72 : if (TREE_CONSTANT (nx))
6274 : {
6275 24 : nx = create_tmp_var_raw (type,
6276 : get_name (var));
6277 24 : gimple_add_tmp_var (nx);
6278 24 : TREE_ADDRESSABLE (nx) = 1;
6279 24 : nx = build_fold_addr_expr_loc (clause_loc,
6280 : nx);
6281 24 : nx = fold_convert_loc (clause_loc,
6282 24 : TREE_TYPE (new_vard),
6283 : nx);
6284 24 : gimplify_assign (new_vard, nx, ilist);
6285 : }
6286 : }
6287 :
6288 108 : x = lang_hooks.decls.omp_clause_linear_ctor
6289 108 : (c, new_var, x, t);
6290 108 : gimplify_and_add (x, ilist);
6291 108 : goto do_dtor;
6292 : }
6293 :
6294 560 : if (POINTER_TYPE_P (TREE_TYPE (x)))
6295 11 : x = fold_build_pointer_plus (x, t);
6296 : else
6297 549 : x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x,
6298 : fold_convert (TREE_TYPE (x), t));
6299 : }
6300 :
6301 955 : if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
6302 934 : || TREE_ADDRESSABLE (new_var)
6303 799 : || omp_privatize_by_reference (var))
6304 1217 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6305 : ivar, lvar))
6306 : {
6307 152 : if (omp_privatize_by_reference (var))
6308 : {
6309 22 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6310 22 : tree new_vard = TREE_OPERAND (new_var, 0);
6311 22 : gcc_assert (DECL_P (new_vard));
6312 22 : SET_DECL_VALUE_EXPR (new_vard,
6313 : build_fold_addr_expr (lvar));
6314 22 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6315 : }
6316 152 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
6317 : {
6318 131 : tree iv = create_tmp_var (TREE_TYPE (new_var));
6319 131 : x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
6320 131 : gimplify_and_add (x, ilist);
6321 131 : gimple_stmt_iterator gsi
6322 131 : = gsi_start (*gimple_omp_body_ptr (ctx->stmt));
6323 131 : gassign *g
6324 131 : = gimple_build_assign (unshare_expr (lvar), iv);
6325 131 : gsi_insert_before_without_update (&gsi, g,
6326 : GSI_SAME_STMT);
6327 131 : tree t = OMP_CLAUSE_LINEAR_STEP (c);
6328 131 : enum tree_code code = PLUS_EXPR;
6329 131 : if (POINTER_TYPE_P (TREE_TYPE (new_var)))
6330 : code = POINTER_PLUS_EXPR;
6331 131 : g = gimple_build_assign (iv, code, iv, t);
6332 131 : gsi_insert_before_without_update (&gsi, g,
6333 : GSI_SAME_STMT);
6334 131 : break;
6335 : }
6336 21 : x = lang_hooks.decls.omp_clause_copy_ctor
6337 21 : (c, unshare_expr (ivar), x);
6338 21 : gimplify_and_add (x, &llist[0]);
6339 21 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6340 21 : if (x)
6341 21 : gimplify_and_add (x, &llist[1]);
6342 : break;
6343 : }
6344 803 : if (omp_privatize_by_reference (var))
6345 : {
6346 105 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6347 105 : tree new_vard = TREE_OPERAND (new_var, 0);
6348 105 : gcc_assert (DECL_P (new_vard));
6349 105 : tree type = TREE_TYPE (TREE_TYPE (new_vard));
6350 105 : nx = TYPE_SIZE_UNIT (type);
6351 105 : if (TREE_CONSTANT (nx))
6352 : {
6353 57 : nx = create_tmp_var_raw (type, get_name (var));
6354 57 : gimple_add_tmp_var (nx);
6355 57 : TREE_ADDRESSABLE (nx) = 1;
6356 57 : nx = build_fold_addr_expr_loc (clause_loc, nx);
6357 57 : nx = fold_convert_loc (clause_loc,
6358 57 : TREE_TYPE (new_vard), nx);
6359 57 : gimplify_assign (new_vard, nx, ilist);
6360 : }
6361 : }
6362 : }
6363 29159 : x = lang_hooks.decls.omp_clause_copy_ctor
6364 29159 : (c, unshare_expr (new_var), x);
6365 29155 : gimplify_and_add (x, ilist);
6366 29155 : goto do_dtor;
6367 :
6368 19358 : case OMP_CLAUSE__LOOPTEMP_:
6369 19358 : case OMP_CLAUSE__REDUCTEMP_:
6370 19358 : gcc_assert (is_taskreg_ctx (ctx));
6371 19358 : x = build_outer_var_ref (var, ctx);
6372 19358 : x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
6373 19358 : gimplify_and_add (x, ilist);
6374 19358 : break;
6375 :
6376 514 : case OMP_CLAUSE_COPYIN:
6377 514 : by_ref = use_pointer_for_field (var, NULL);
6378 514 : x = build_receiver_ref (var, by_ref, ctx);
6379 514 : x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
6380 514 : append_to_statement_list (x, ©in_seq);
6381 514 : copyin_by_ref |= by_ref;
6382 514 : break;
6383 :
6384 13089 : case OMP_CLAUSE_REDUCTION:
6385 13089 : case OMP_CLAUSE_IN_REDUCTION:
6386 : /* OpenACC reductions are initialized using the
6387 : GOACC_REDUCTION internal function. */
6388 13089 : if (is_gimple_omp_oacc (ctx->stmt))
6389 : break;
6390 9107 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
6391 : {
6392 1458 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
6393 1458 : gimple *tseq;
6394 1458 : tree ptype = TREE_TYPE (placeholder);
6395 1458 : if (cond)
6396 : {
6397 295 : x = error_mark_node;
6398 295 : if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c)
6399 295 : && !task_reduction_needs_orig_p)
6400 28 : x = var;
6401 267 : else if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
6402 : {
6403 45 : tree pptype = build_pointer_type (ptype);
6404 45 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
6405 35 : x = build4 (ARRAY_REF, ptr_type_node, tskred_avar,
6406 35 : size_int (task_reduction_cnt_full
6407 : + task_reduction_cntorig - 1),
6408 : NULL_TREE, NULL_TREE);
6409 : else
6410 : {
6411 10 : unsigned int idx
6412 10 : = *ctx->task_reduction_map->get (c);
6413 10 : x = task_reduction_read (ilist, tskred_temp,
6414 10 : pptype, 7 + 3 * idx);
6415 : }
6416 45 : x = fold_convert (pptype, x);
6417 45 : x = build_simple_mem_ref (x);
6418 : }
6419 : }
6420 : else
6421 : {
6422 1163 : lower_private_allocate (var, new_var, allocator,
6423 : allocate_ptr, ilist, ctx, false,
6424 : NULL_TREE);
6425 1163 : x = build_outer_var_ref (var, ctx);
6426 :
6427 1163 : if (omp_privatize_by_reference (var)
6428 1163 : && !useless_type_conversion_p (ptype, TREE_TYPE (x)))
6429 49 : x = build_fold_addr_expr_loc (clause_loc, x);
6430 : }
6431 1458 : SET_DECL_VALUE_EXPR (placeholder, x);
6432 1458 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
6433 1458 : tree new_vard = new_var;
6434 1458 : if (omp_privatize_by_reference (var))
6435 : {
6436 203 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6437 203 : new_vard = TREE_OPERAND (new_var, 0);
6438 203 : gcc_assert (DECL_P (new_vard));
6439 : }
6440 1458 : tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
6441 1458 : if (is_simd
6442 311 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6443 1769 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6444 : rvarp = &rvar;
6445 1458 : if (is_simd
6446 1458 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6447 : ivar, lvar, rvarp,
6448 : &rvar2))
6449 : {
6450 174 : if (new_vard == new_var)
6451 : {
6452 128 : gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
6453 128 : SET_DECL_VALUE_EXPR (new_var, ivar);
6454 : }
6455 : else
6456 : {
6457 46 : SET_DECL_VALUE_EXPR (new_vard,
6458 : build_fold_addr_expr (ivar));
6459 46 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6460 : }
6461 174 : x = lang_hooks.decls.omp_clause_default_ctor
6462 174 : (c, unshare_expr (ivar),
6463 : build_outer_var_ref (var, ctx));
6464 174 : if (rvarp && ctx->for_simd_scan_phase)
6465 : {
6466 16 : if (x)
6467 8 : gimplify_and_add (x, &llist[0]);
6468 16 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6469 16 : if (x)
6470 8 : gimplify_and_add (x, &llist[1]);
6471 469 : break;
6472 : }
6473 78 : else if (rvarp)
6474 : {
6475 78 : if (x)
6476 : {
6477 38 : gimplify_and_add (x, &llist[0]);
6478 :
6479 38 : tree ivar2 = unshare_expr (lvar);
6480 38 : TREE_OPERAND (ivar2, 1) = sctx.idx;
6481 38 : x = lang_hooks.decls.omp_clause_default_ctor
6482 38 : (c, ivar2, build_outer_var_ref (var, ctx));
6483 38 : gimplify_and_add (x, &llist[0]);
6484 :
6485 38 : if (rvar2)
6486 : {
6487 16 : x = lang_hooks.decls.omp_clause_default_ctor
6488 16 : (c, unshare_expr (rvar2),
6489 : build_outer_var_ref (var, ctx));
6490 16 : gimplify_and_add (x, &llist[0]);
6491 : }
6492 :
6493 : /* For types that need construction, add another
6494 : private var which will be default constructed
6495 : and optionally initialized with
6496 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT, as in the
6497 : loop we want to assign this value instead of
6498 : constructing and destructing it in each
6499 : iteration. */
6500 38 : tree nv = create_tmp_var_raw (TREE_TYPE (ivar));
6501 38 : gimple_add_tmp_var (nv);
6502 60 : ctx->cb.decl_map->put (TREE_OPERAND (rvar2
6503 : ? rvar2
6504 : : ivar, 0),
6505 : nv);
6506 38 : x = lang_hooks.decls.omp_clause_default_ctor
6507 38 : (c, nv, build_outer_var_ref (var, ctx));
6508 38 : gimplify_and_add (x, ilist);
6509 :
6510 38 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6511 : {
6512 19 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6513 19 : x = DECL_VALUE_EXPR (new_vard);
6514 19 : tree vexpr = nv;
6515 19 : if (new_vard != new_var)
6516 11 : vexpr = build_fold_addr_expr (nv);
6517 19 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
6518 19 : lower_omp (&tseq, ctx);
6519 19 : SET_DECL_VALUE_EXPR (new_vard, x);
6520 19 : gimple_seq_add_seq (ilist, tseq);
6521 19 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6522 : }
6523 :
6524 38 : x = lang_hooks.decls.omp_clause_dtor (c, nv);
6525 38 : if (x)
6526 38 : gimplify_and_add (x, dlist);
6527 : }
6528 :
6529 78 : tree ref = build_outer_var_ref (var, ctx);
6530 78 : x = unshare_expr (ivar);
6531 78 : x = lang_hooks.decls.omp_clause_assign_op (c, x,
6532 : ref);
6533 78 : gimplify_and_add (x, &llist[0]);
6534 :
6535 78 : ref = build_outer_var_ref (var, ctx);
6536 78 : x = lang_hooks.decls.omp_clause_assign_op (c, ref,
6537 : rvar);
6538 78 : gimplify_and_add (x, &llist[3]);
6539 :
6540 78 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6541 78 : if (new_vard == new_var)
6542 48 : SET_DECL_VALUE_EXPR (new_var, lvar);
6543 : else
6544 30 : SET_DECL_VALUE_EXPR (new_vard,
6545 : build_fold_addr_expr (lvar));
6546 :
6547 78 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6548 78 : if (x)
6549 38 : gimplify_and_add (x, &llist[1]);
6550 :
6551 78 : tree ivar2 = unshare_expr (lvar);
6552 78 : TREE_OPERAND (ivar2, 1) = sctx.idx;
6553 78 : x = lang_hooks.decls.omp_clause_dtor (c, ivar2);
6554 78 : if (x)
6555 38 : gimplify_and_add (x, &llist[1]);
6556 :
6557 78 : if (rvar2)
6558 : {
6559 36 : x = lang_hooks.decls.omp_clause_dtor (c, rvar2);
6560 36 : if (x)
6561 16 : gimplify_and_add (x, &llist[1]);
6562 : }
6563 : break;
6564 : }
6565 80 : if (x)
6566 34 : gimplify_and_add (x, &llist[0]);
6567 80 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6568 : {
6569 76 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6570 76 : lower_omp (&tseq, ctx);
6571 76 : gimple_seq_add_seq (&llist[0], tseq);
6572 : }
6573 80 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6574 80 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
6575 80 : lower_omp (&tseq, ctx);
6576 80 : gimple_seq_add_seq (&llist[1], tseq);
6577 80 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
6578 80 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6579 80 : if (new_vard == new_var)
6580 70 : SET_DECL_VALUE_EXPR (new_var, lvar);
6581 : else
6582 10 : SET_DECL_VALUE_EXPR (new_vard,
6583 : build_fold_addr_expr (lvar));
6584 80 : x = lang_hooks.decls.omp_clause_dtor (c, ivar);
6585 80 : if (x)
6586 38 : gimplify_and_add (x, &llist[1]);
6587 : break;
6588 : }
6589 : /* If this is a reference to constant size reduction var
6590 : with placeholder, we haven't emitted the initializer
6591 : for it because it is undesirable if SIMD arrays are used.
6592 : But if they aren't used, we need to emit the deferred
6593 : initialization now. */
6594 1284 : else if (omp_privatize_by_reference (var) && is_simd)
6595 46 : handle_simd_reference (clause_loc, new_vard, ilist);
6596 :
6597 1284 : tree lab2 = NULL_TREE;
6598 1284 : if (cond)
6599 : {
6600 295 : gimple *g;
6601 295 : if (!is_parallel_ctx (ctx))
6602 : {
6603 278 : tree condv = create_tmp_var (boolean_type_node);
6604 278 : tree m = build_simple_mem_ref (cond);
6605 278 : g = gimple_build_assign (condv, m);
6606 278 : gimple_seq_add_stmt (ilist, g);
6607 278 : tree lab1
6608 278 : = create_artificial_label (UNKNOWN_LOCATION);
6609 278 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
6610 278 : g = gimple_build_cond (NE_EXPR, condv,
6611 : boolean_false_node,
6612 : lab2, lab1);
6613 278 : gimple_seq_add_stmt (ilist, g);
6614 278 : gimple_seq_add_stmt (ilist,
6615 278 : gimple_build_label (lab1));
6616 : }
6617 295 : g = gimple_build_assign (build_simple_mem_ref (cond),
6618 : boolean_true_node);
6619 295 : gimple_seq_add_stmt (ilist, g);
6620 : }
6621 295 : x = lang_hooks.decls.omp_clause_default_ctor
6622 1284 : (c, unshare_expr (new_var),
6623 : cond ? NULL_TREE
6624 989 : : build_outer_var_ref (var, ctx));
6625 1284 : if (x)
6626 286 : gimplify_and_add (x, ilist);
6627 :
6628 1284 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6629 1284 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6630 : {
6631 158 : if (ctx->for_simd_scan_phase)
6632 989 : goto do_dtor;
6633 142 : if (x || (!is_simd
6634 32 : && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c)))
6635 : {
6636 70 : tree nv = create_tmp_var_raw (TREE_TYPE (new_var));
6637 70 : gimple_add_tmp_var (nv);
6638 70 : ctx->cb.decl_map->put (new_vard, nv);
6639 70 : x = lang_hooks.decls.omp_clause_default_ctor
6640 70 : (c, nv, build_outer_var_ref (var, ctx));
6641 70 : if (x)
6642 70 : gimplify_and_add (x, ilist);
6643 70 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6644 : {
6645 35 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6646 35 : tree vexpr = nv;
6647 35 : if (new_vard != new_var)
6648 19 : vexpr = build_fold_addr_expr (nv);
6649 35 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
6650 35 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6651 35 : lower_omp (&tseq, ctx);
6652 35 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
6653 35 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
6654 35 : gimple_seq_add_seq (ilist, tseq);
6655 : }
6656 70 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6657 70 : if (is_simd && ctx->scan_exclusive)
6658 : {
6659 16 : tree nv2
6660 16 : = create_tmp_var_raw (TREE_TYPE (new_var));
6661 16 : gimple_add_tmp_var (nv2);
6662 16 : ctx->cb.decl_map->put (nv, nv2);
6663 16 : x = lang_hooks.decls.omp_clause_default_ctor
6664 16 : (c, nv2, build_outer_var_ref (var, ctx));
6665 16 : gimplify_and_add (x, ilist);
6666 16 : x = lang_hooks.decls.omp_clause_dtor (c, nv2);
6667 16 : if (x)
6668 16 : gimplify_and_add (x, dlist);
6669 : }
6670 70 : x = lang_hooks.decls.omp_clause_dtor (c, nv);
6671 70 : if (x)
6672 70 : gimplify_and_add (x, dlist);
6673 : }
6674 72 : else if (is_simd
6675 40 : && ctx->scan_exclusive
6676 92 : && TREE_ADDRESSABLE (TREE_TYPE (new_var)))
6677 : {
6678 0 : tree nv2 = create_tmp_var_raw (TREE_TYPE (new_var));
6679 0 : gimple_add_tmp_var (nv2);
6680 0 : ctx->cb.decl_map->put (new_vard, nv2);
6681 0 : x = lang_hooks.decls.omp_clause_dtor (c, nv2);
6682 0 : if (x)
6683 0 : gimplify_and_add (x, dlist);
6684 : }
6685 142 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6686 142 : goto do_dtor;
6687 : }
6688 :
6689 1126 : if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
6690 : {
6691 1078 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
6692 1078 : if (c_kind == OMP_CLAUSE_IN_REDUCTION
6693 1078 : && is_omp_target (ctx->stmt))
6694 : {
6695 12 : tree d = maybe_lookup_decl_in_outer_ctx (var, ctx);
6696 12 : tree oldv = NULL_TREE;
6697 12 : gcc_assert (d);
6698 12 : if (DECL_HAS_VALUE_EXPR_P (d))
6699 6 : oldv = DECL_VALUE_EXPR (d);
6700 12 : SET_DECL_VALUE_EXPR (d, new_vard);
6701 12 : DECL_HAS_VALUE_EXPR_P (d) = 1;
6702 12 : lower_omp (&tseq, ctx);
6703 12 : if (oldv)
6704 6 : SET_DECL_VALUE_EXPR (d, oldv);
6705 : else
6706 : {
6707 6 : SET_DECL_VALUE_EXPR (d, NULL_TREE);
6708 6 : DECL_HAS_VALUE_EXPR_P (d) = 0;
6709 : }
6710 : }
6711 : else
6712 1066 : lower_omp (&tseq, ctx);
6713 1078 : gimple_seq_add_seq (ilist, tseq);
6714 : }
6715 1126 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
6716 1126 : if (is_simd)
6717 : {
6718 43 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
6719 43 : lower_omp (&tseq, ctx);
6720 43 : gimple_seq_add_seq (dlist, tseq);
6721 43 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
6722 : }
6723 1126 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
6724 1126 : if (cond)
6725 : {
6726 295 : if (lab2)
6727 278 : gimple_seq_add_stmt (ilist, gimple_build_label (lab2));
6728 : break;
6729 : }
6730 831 : goto do_dtor;
6731 : }
6732 : else
6733 : {
6734 7649 : x = omp_reduction_init (c, TREE_TYPE (new_var));
6735 7649 : gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
6736 7649 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
6737 :
6738 7649 : if (cond)
6739 : {
6740 1447 : gimple *g;
6741 1447 : tree lab2 = NULL_TREE;
6742 : /* GOMP_taskgroup_reduction_register memsets the whole
6743 : array to zero. If the initializer is zero, we don't
6744 : need to initialize it again, just mark it as ever
6745 : used unconditionally, i.e. cond = true. */
6746 1447 : if (initializer_zerop (x))
6747 : {
6748 1266 : g = gimple_build_assign (build_simple_mem_ref (cond),
6749 : boolean_true_node);
6750 1266 : gimple_seq_add_stmt (ilist, g);
6751 3243 : break;
6752 : }
6753 :
6754 : /* Otherwise, emit
6755 : if (!cond) { cond = true; new_var = x; } */
6756 181 : if (!is_parallel_ctx (ctx))
6757 : {
6758 177 : tree condv = create_tmp_var (boolean_type_node);
6759 177 : tree m = build_simple_mem_ref (cond);
6760 177 : g = gimple_build_assign (condv, m);
6761 177 : gimple_seq_add_stmt (ilist, g);
6762 177 : tree lab1
6763 177 : = create_artificial_label (UNKNOWN_LOCATION);
6764 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
6765 177 : g = gimple_build_cond (NE_EXPR, condv,
6766 : boolean_false_node,
6767 : lab2, lab1);
6768 177 : gimple_seq_add_stmt (ilist, g);
6769 177 : gimple_seq_add_stmt (ilist,
6770 177 : gimple_build_label (lab1));
6771 : }
6772 181 : g = gimple_build_assign (build_simple_mem_ref (cond),
6773 : boolean_true_node);
6774 181 : gimple_seq_add_stmt (ilist, g);
6775 181 : gimplify_assign (new_var, x, ilist);
6776 181 : if (lab2)
6777 177 : gimple_seq_add_stmt (ilist, gimple_build_label (lab2));
6778 : break;
6779 : }
6780 :
6781 : /* reduction(-:var) sums up the partial results, so it
6782 : acts identically to reduction(+:var). */
6783 6202 : if (code == MINUS_EXPR)
6784 33 : code = PLUS_EXPR;
6785 :
6786 6202 : bool is_truth_op
6787 6202 : = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR);
6788 6202 : tree new_vard = new_var;
6789 6202 : if (is_simd && omp_privatize_by_reference (var))
6790 : {
6791 52 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
6792 52 : new_vard = TREE_OPERAND (new_var, 0);
6793 52 : gcc_assert (DECL_P (new_vard));
6794 : }
6795 6202 : tree rvar = NULL_TREE, *rvarp = NULL, rvar2 = NULL_TREE;
6796 6202 : if (is_simd
6797 2087 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6798 8289 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6799 : rvarp = &rvar;
6800 6202 : if (is_simd
6801 6202 : && lower_rec_simd_input_clauses (new_var, ctx, &sctx,
6802 : ivar, lvar, rvarp,
6803 : &rvar2))
6804 : {
6805 867 : if (new_vard != new_var)
6806 : {
6807 34 : SET_DECL_VALUE_EXPR (new_vard,
6808 : build_fold_addr_expr (lvar));
6809 34 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
6810 : }
6811 :
6812 867 : tree ref = build_outer_var_ref (var, ctx);
6813 :
6814 867 : if (rvarp)
6815 : {
6816 193 : if (ctx->for_simd_scan_phase)
6817 : break;
6818 154 : gimplify_assign (ivar, ref, &llist[0]);
6819 154 : ref = build_outer_var_ref (var, ctx);
6820 154 : gimplify_assign (ref, rvar, &llist[3]);
6821 154 : break;
6822 : }
6823 :
6824 674 : gimplify_assign (unshare_expr (ivar), x, &llist[0]);
6825 :
6826 674 : if (sctx.is_simt)
6827 : {
6828 0 : if (!simt_lane)
6829 0 : simt_lane = create_tmp_var (unsigned_type_node);
6830 0 : x = build_call_expr_internal_loc
6831 0 : (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_BFLY,
6832 0 : TREE_TYPE (ivar), 2, ivar, simt_lane);
6833 : /* Make sure x is evaluated unconditionally. */
6834 0 : tree bfly_var = create_tmp_var (TREE_TYPE (ivar));
6835 0 : gimplify_assign (bfly_var, x, &llist[2]);
6836 0 : x = build2 (code, TREE_TYPE (ivar), ivar, bfly_var);
6837 0 : gimplify_assign (ivar, x, &llist[2]);
6838 : }
6839 674 : tree ivar2 = ivar;
6840 674 : tree ref2 = ref;
6841 674 : if (is_truth_op)
6842 : {
6843 99 : tree zero = build_zero_cst (TREE_TYPE (ivar));
6844 99 : ivar2 = fold_build2_loc (clause_loc, NE_EXPR,
6845 : boolean_type_node, ivar,
6846 : zero);
6847 99 : ref2 = fold_build2_loc (clause_loc, NE_EXPR,
6848 : boolean_type_node, ref,
6849 : zero);
6850 : }
6851 674 : x = build2 (code, TREE_TYPE (ref), ref2, ivar2);
6852 674 : if (is_truth_op)
6853 99 : x = fold_convert (TREE_TYPE (ref), x);
6854 674 : ref = build_outer_var_ref (var, ctx);
6855 674 : gimplify_assign (ref, x, &llist[1]);
6856 :
6857 : }
6858 : else
6859 : {
6860 5335 : lower_private_allocate (var, new_var, allocator,
6861 : allocate_ptr, ilist, ctx,
6862 : false, NULL_TREE);
6863 5335 : if (omp_privatize_by_reference (var) && is_simd)
6864 18 : handle_simd_reference (clause_loc, new_vard, ilist);
6865 5335 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6866 5335 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
6867 : break;
6868 4998 : gimplify_assign (new_var, x, ilist);
6869 4998 : if (is_simd)
6870 : {
6871 1028 : tree ref = build_outer_var_ref (var, ctx);
6872 1028 : tree new_var2 = new_var;
6873 1028 : tree ref2 = ref;
6874 1028 : if (is_truth_op)
6875 : {
6876 24 : tree zero = build_zero_cst (TREE_TYPE (new_var));
6877 24 : new_var2
6878 24 : = fold_build2_loc (clause_loc, NE_EXPR,
6879 : boolean_type_node, new_var,
6880 : zero);
6881 24 : ref2 = fold_build2_loc (clause_loc, NE_EXPR,
6882 : boolean_type_node, ref,
6883 : zero);
6884 : }
6885 1028 : x = build2 (code, TREE_TYPE (ref2), ref2, new_var2);
6886 1028 : if (is_truth_op)
6887 24 : x = fold_convert (TREE_TYPE (new_var), x);
6888 1028 : ref = build_outer_var_ref (var, ctx);
6889 1028 : gimplify_assign (ref, x, dlist);
6890 : }
6891 4998 : if (allocator)
6892 61 : goto do_dtor;
6893 : }
6894 : }
6895 5611 : break;
6896 :
6897 0 : default:
6898 0 : gcc_unreachable ();
6899 : }
6900 : }
6901 : }
6902 77360 : if (tskred_avar)
6903 : {
6904 871 : tree clobber = build_clobber (TREE_TYPE (tskred_avar));
6905 871 : gimple_seq_add_stmt (ilist, gimple_build_assign (tskred_avar, clobber));
6906 : }
6907 :
6908 77360 : if (known_eq (sctx.max_vf, 1U))
6909 : {
6910 1779 : sctx.is_simt = false;
6911 1779 : if (ctx->lastprivate_conditional_map)
6912 : {
6913 52 : if (gimple_omp_for_combined_into_p (ctx->stmt))
6914 : {
6915 : /* Signal to lower_omp_1 that it should use parent context. */
6916 43 : ctx->combined_into_simd_safelen1 = true;
6917 370 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6918 327 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
6919 327 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
6920 : {
6921 57 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
6922 57 : omp_context *outer = ctx->outer;
6923 57 : if (gimple_code (outer->stmt) == GIMPLE_OMP_SCAN)
6924 6 : outer = outer->outer;
6925 57 : tree *v = ctx->lastprivate_conditional_map->get (o);
6926 57 : tree po = lookup_decl (OMP_CLAUSE_DECL (c), outer);
6927 57 : tree *pv = outer->lastprivate_conditional_map->get (po);
6928 57 : *v = *pv;
6929 : }
6930 : }
6931 : else
6932 : {
6933 : /* When not vectorized, treat lastprivate(conditional:) like
6934 : normal lastprivate, as there will be just one simd lane
6935 : writing the privatized variable. */
6936 9 : delete ctx->lastprivate_conditional_map;
6937 9 : ctx->lastprivate_conditional_map = NULL;
6938 : }
6939 : }
6940 : }
6941 :
6942 77360 : if (nonconst_simd_if)
6943 : {
6944 625 : if (sctx.lane == NULL_TREE)
6945 : {
6946 570 : sctx.idx = create_tmp_var (unsigned_type_node);
6947 570 : sctx.lane = create_tmp_var (unsigned_type_node);
6948 : }
6949 : /* FIXME: For now. */
6950 625 : sctx.is_simt = false;
6951 : }
6952 :
6953 77360 : if (sctx.lane || sctx.is_simt)
6954 : {
6955 4003 : uid = create_tmp_var (ptr_type_node, "simduid");
6956 : /* Don't want uninit warnings on simduid, it is always uninitialized,
6957 : but we use it not for the value, but for the DECL_UID only. */
6958 4003 : suppress_warning (uid, OPT_Wuninitialized);
6959 4003 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
6960 4003 : OMP_CLAUSE__SIMDUID__DECL (c) = uid;
6961 4003 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
6962 4003 : gimple_omp_for_set_clauses (ctx->stmt, c);
6963 : }
6964 : /* Emit calls denoting privatized variables and initializing a pointer to
6965 : structure that holds private variables as fields after ompdevlow pass. */
6966 77360 : if (sctx.is_simt)
6967 : {
6968 0 : sctx.simt_eargs[0] = uid;
6969 0 : gimple *g
6970 0 : = gimple_build_call_internal_vec (IFN_GOMP_SIMT_ENTER, sctx.simt_eargs);
6971 0 : gimple_call_set_lhs (g, uid);
6972 0 : gimple_seq_add_stmt (ilist, g);
6973 0 : sctx.simt_eargs.release ();
6974 :
6975 0 : simtrec = create_tmp_var (ptr_type_node, ".omp_simt");
6976 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_ENTER_ALLOC, 1, uid);
6977 0 : gimple_call_set_lhs (g, simtrec);
6978 0 : gimple_seq_add_stmt (ilist, g);
6979 : }
6980 77360 : if (sctx.lane)
6981 : {
6982 7381 : gimple *g = gimple_build_call_internal (IFN_GOMP_SIMD_LANE,
6983 : 2 + (nonconst_simd_if != NULL),
6984 : uid, integer_zero_node,
6985 : nonconst_simd_if);
6986 4003 : gimple_call_set_lhs (g, sctx.lane);
6987 4003 : gimple_stmt_iterator gsi = gsi_start (*gimple_omp_body_ptr (ctx->stmt));
6988 4003 : gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
6989 4003 : g = gimple_build_assign (sctx.lane, INTEGER_CST,
6990 : build_int_cst (unsigned_type_node, 0));
6991 4003 : gimple_seq_add_stmt (ilist, g);
6992 4003 : if (sctx.lastlane)
6993 : {
6994 184 : g = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
6995 : 2, uid, sctx.lane);
6996 184 : gimple_call_set_lhs (g, sctx.lastlane);
6997 184 : gimple_seq_add_stmt (dlist, g);
6998 184 : gimple_seq_add_seq (dlist, llist[3]);
6999 : }
7000 : /* Emit reductions across SIMT lanes in log_2(simt_vf) steps. */
7001 4003 : if (llist[2])
7002 : {
7003 0 : tree simt_vf = create_tmp_var (unsigned_type_node);
7004 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_VF, 0);
7005 0 : gimple_call_set_lhs (g, simt_vf);
7006 0 : gimple_seq_add_stmt (dlist, g);
7007 :
7008 0 : tree t = build_int_cst (unsigned_type_node, 1);
7009 0 : g = gimple_build_assign (simt_lane, INTEGER_CST, t);
7010 0 : gimple_seq_add_stmt (dlist, g);
7011 :
7012 0 : t = build_int_cst (unsigned_type_node, 0);
7013 0 : g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
7014 0 : gimple_seq_add_stmt (dlist, g);
7015 :
7016 0 : tree body = create_artificial_label (UNKNOWN_LOCATION);
7017 0 : tree header = create_artificial_label (UNKNOWN_LOCATION);
7018 0 : tree end = create_artificial_label (UNKNOWN_LOCATION);
7019 0 : gimple_seq_add_stmt (dlist, gimple_build_goto (header));
7020 0 : gimple_seq_add_stmt (dlist, gimple_build_label (body));
7021 :
7022 0 : gimple_seq_add_seq (dlist, llist[2]);
7023 :
7024 0 : g = gimple_build_assign (simt_lane, LSHIFT_EXPR, simt_lane, integer_one_node);
7025 0 : gimple_seq_add_stmt (dlist, g);
7026 :
7027 0 : gimple_seq_add_stmt (dlist, gimple_build_label (header));
7028 0 : g = gimple_build_cond (LT_EXPR, simt_lane, simt_vf, body, end);
7029 0 : gimple_seq_add_stmt (dlist, g);
7030 :
7031 0 : gimple_seq_add_stmt (dlist, gimple_build_label (end));
7032 : }
7033 12009 : for (int i = 0; i < 2; i++)
7034 8006 : if (llist[i])
7035 : {
7036 1716 : tree vf = create_tmp_var (unsigned_type_node);
7037 1716 : g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
7038 1716 : gimple_call_set_lhs (g, vf);
7039 1716 : gimple_seq *seq = i == 0 ? ilist : dlist;
7040 1716 : gimple_seq_add_stmt (seq, g);
7041 1716 : tree t = build_int_cst (unsigned_type_node, 0);
7042 1716 : g = gimple_build_assign (sctx.idx, INTEGER_CST, t);
7043 1716 : gimple_seq_add_stmt (seq, g);
7044 1716 : tree body = create_artificial_label (UNKNOWN_LOCATION);
7045 1716 : tree header = create_artificial_label (UNKNOWN_LOCATION);
7046 1716 : tree end = create_artificial_label (UNKNOWN_LOCATION);
7047 1716 : gimple_seq_add_stmt (seq, gimple_build_goto (header));
7048 1716 : gimple_seq_add_stmt (seq, gimple_build_label (body));
7049 1716 : gimple_seq_add_seq (seq, llist[i]);
7050 1716 : t = build_int_cst (unsigned_type_node, 1);
7051 1716 : g = gimple_build_assign (sctx.idx, PLUS_EXPR, sctx.idx, t);
7052 1716 : gimple_seq_add_stmt (seq, g);
7053 1716 : gimple_seq_add_stmt (seq, gimple_build_label (header));
7054 1716 : g = gimple_build_cond (LT_EXPR, sctx.idx, vf, body, end);
7055 1716 : gimple_seq_add_stmt (seq, g);
7056 1716 : gimple_seq_add_stmt (seq, gimple_build_label (end));
7057 : }
7058 : }
7059 77360 : if (sctx.is_simt)
7060 : {
7061 0 : gimple_seq_add_seq (dlist, sctx.simt_dlist);
7062 0 : gimple *g
7063 0 : = gimple_build_call_internal (IFN_GOMP_SIMT_EXIT, 1, simtrec);
7064 0 : gimple_seq_add_stmt (dlist, g);
7065 : }
7066 :
7067 : /* The copyin sequence is not to be executed by the main thread, since
7068 : that would result in self-copies. Perhaps not visible to scalars,
7069 : but it certainly is to C++ operator=. */
7070 77360 : if (copyin_seq)
7071 : {
7072 440 : x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
7073 : 0);
7074 440 : x = build2 (NE_EXPR, boolean_type_node, x,
7075 440 : build_int_cst (TREE_TYPE (x), 0));
7076 440 : x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
7077 440 : gimplify_and_add (x, ilist);
7078 : }
7079 :
7080 : /* If any copyin variable is passed by reference, we must ensure the
7081 : master thread doesn't modify it before it is copied over in all
7082 : threads. Similarly for variables in both firstprivate and
7083 : lastprivate clauses we need to ensure the lastprivate copying
7084 : happens after firstprivate copying in all threads. And similarly
7085 : for UDRs if initializer expression refers to omp_orig. */
7086 77360 : if (copyin_by_ref || lastprivate_firstprivate
7087 75420 : || (reduction_omp_orig_ref
7088 101 : && !ctx->scan_inclusive
7089 101 : && !ctx->scan_exclusive))
7090 : {
7091 : /* Don't add any barrier for #pragma omp simd or
7092 : #pragma omp distribute. */
7093 2041 : if (!is_task_ctx (ctx)
7094 2041 : && (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
7095 1486 : || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR))
7096 : {
7097 904 : int barrier_kind;
7098 904 : switch (gimple_code (ctx->stmt))
7099 : {
7100 : case GIMPLE_OMP_SECTIONS:
7101 : case GIMPLE_OMP_SCOPE:
7102 : case GIMPLE_OMP_FOR:
7103 : barrier_kind = GOMP_BARRIER_IMPLICIT_WORKSHARE;
7104 : break;
7105 540 : case GIMPLE_OMP_PARALLEL:
7106 540 : case GIMPLE_OMP_TEAMS:
7107 540 : barrier_kind = GOMP_BARRIER_IMPLICIT_PARALLEL;
7108 540 : break;
7109 0 : default:
7110 0 : gcc_unreachable ();
7111 : }
7112 904 : gimple_seq_add_stmt (ilist,
7113 : omp_build_barrier (NULL_TREE, barrier_kind));
7114 : }
7115 : }
7116 :
7117 : /* If max_vf is non-zero, then we can use only a vectorization factor
7118 : up to the max_vf we chose. So stick it into the safelen clause. */
7119 77360 : if (maybe_ne (sctx.max_vf, 0U))
7120 : {
7121 5212 : tree c = omp_find_clause (gimple_omp_for_clauses (ctx->stmt),
7122 : OMP_CLAUSE_SAFELEN);
7123 5212 : poly_uint64 safe_len;
7124 5212 : if (c == NULL_TREE
7125 5212 : || (poly_int_tree_p (OMP_CLAUSE_SAFELEN_EXPR (c), &safe_len)
7126 613 : && maybe_gt (safe_len, sctx.max_vf)))
7127 : {
7128 5122 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
7129 5122 : OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
7130 5122 : sctx.max_vf);
7131 5122 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
7132 5122 : gimple_omp_for_set_clauses (ctx->stmt, c);
7133 : }
7134 : }
7135 77360 : }
7136 :
7137 : /* Create temporary variables for lastprivate(conditional:) implementation
7138 : in context CTX with CLAUSES. */
7139 :
7140 : static void
7141 47352 : lower_lastprivate_conditional_clauses (tree *clauses, omp_context *ctx)
7142 : {
7143 47352 : tree iter_type = NULL_TREE;
7144 47352 : tree cond_ptr = NULL_TREE;
7145 47352 : tree iter_var = NULL_TREE;
7146 47352 : bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7147 47352 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD);
7148 47352 : tree next = *clauses;
7149 227306 : for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
7150 179954 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7151 179954 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
7152 : {
7153 386 : if (is_simd)
7154 : {
7155 107 : tree cc = omp_find_clause (next, OMP_CLAUSE__CONDTEMP_);
7156 107 : gcc_assert (cc);
7157 107 : if (iter_type == NULL_TREE)
7158 : {
7159 77 : iter_type = TREE_TYPE (OMP_CLAUSE_DECL (cc));
7160 77 : iter_var = create_tmp_var_raw (iter_type);
7161 77 : DECL_CONTEXT (iter_var) = current_function_decl;
7162 77 : DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
7163 77 : DECL_CHAIN (iter_var) = ctx->block_vars;
7164 77 : ctx->block_vars = iter_var;
7165 77 : tree c3
7166 77 : = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
7167 77 : OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
7168 77 : OMP_CLAUSE_DECL (c3) = iter_var;
7169 77 : OMP_CLAUSE_CHAIN (c3) = *clauses;
7170 77 : *clauses = c3;
7171 77 : ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
7172 : }
7173 107 : next = OMP_CLAUSE_CHAIN (cc);
7174 107 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7175 107 : tree v = lookup_decl (OMP_CLAUSE_DECL (cc), ctx);
7176 107 : ctx->lastprivate_conditional_map->put (o, v);
7177 107 : continue;
7178 107 : }
7179 279 : if (iter_type == NULL)
7180 : {
7181 205 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR)
7182 : {
7183 193 : struct omp_for_data fd;
7184 193 : omp_extract_for_data (as_a <gomp_for *> (ctx->stmt), &fd,
7185 : NULL);
7186 193 : iter_type = unsigned_type_for (fd.iter_type);
7187 : }
7188 12 : else if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
7189 12 : iter_type = unsigned_type_node;
7190 205 : tree c2 = omp_find_clause (*clauses, OMP_CLAUSE__CONDTEMP_);
7191 205 : if (c2)
7192 : {
7193 103 : cond_ptr
7194 103 : = lookup_decl_in_outer_ctx (OMP_CLAUSE_DECL (c2), ctx);
7195 103 : OMP_CLAUSE_DECL (c2) = cond_ptr;
7196 : }
7197 : else
7198 : {
7199 102 : cond_ptr = create_tmp_var_raw (build_pointer_type (iter_type));
7200 102 : DECL_CONTEXT (cond_ptr) = current_function_decl;
7201 102 : DECL_SEEN_IN_BIND_EXPR_P (cond_ptr) = 1;
7202 102 : DECL_CHAIN (cond_ptr) = ctx->block_vars;
7203 102 : ctx->block_vars = cond_ptr;
7204 102 : c2 = build_omp_clause (UNKNOWN_LOCATION,
7205 : OMP_CLAUSE__CONDTEMP_);
7206 102 : OMP_CLAUSE_DECL (c2) = cond_ptr;
7207 102 : OMP_CLAUSE_CHAIN (c2) = *clauses;
7208 102 : *clauses = c2;
7209 : }
7210 205 : iter_var = create_tmp_var_raw (iter_type);
7211 205 : DECL_CONTEXT (iter_var) = current_function_decl;
7212 205 : DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
7213 205 : DECL_CHAIN (iter_var) = ctx->block_vars;
7214 205 : ctx->block_vars = iter_var;
7215 205 : tree c3
7216 205 : = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
7217 205 : OMP_CLAUSE__CONDTEMP__ITER (c3) = 1;
7218 205 : OMP_CLAUSE_DECL (c3) = iter_var;
7219 205 : OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2);
7220 205 : OMP_CLAUSE_CHAIN (c2) = c3;
7221 205 : ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
7222 : }
7223 279 : tree v = create_tmp_var_raw (iter_type);
7224 279 : DECL_CONTEXT (v) = current_function_decl;
7225 279 : DECL_SEEN_IN_BIND_EXPR_P (v) = 1;
7226 279 : DECL_CHAIN (v) = ctx->block_vars;
7227 279 : ctx->block_vars = v;
7228 279 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7229 279 : ctx->lastprivate_conditional_map->put (o, v);
7230 : }
7231 47352 : }
7232 :
7233 :
7234 : /* Generate code to implement the LASTPRIVATE clauses. This is used for
7235 : both parallel and workshare constructs. PREDICATE may be NULL if it's
7236 : always true. BODY_P is the sequence to insert early initialization
7237 : if needed, STMT_LIST is where the non-conditional lastprivate handling
7238 : goes into and CSTMT_LIST is a sequence that needs to be run in a critical
7239 : section. */
7240 :
7241 : static void
7242 47352 : lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
7243 : gimple_seq *stmt_list, gimple_seq *cstmt_list,
7244 : omp_context *ctx)
7245 : {
7246 47352 : tree x, c, label = NULL, orig_clauses = clauses;
7247 47352 : bool par_clauses = false;
7248 47352 : tree simduid = NULL, lastlane = NULL, simtcond = NULL, simtlast = NULL;
7249 47352 : unsigned HOST_WIDE_INT conditional_off = 0;
7250 47352 : gimple_seq post_stmt_list = NULL;
7251 :
7252 : /* Early exit if there are no lastprivate or linear clauses. */
7253 196544 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
7254 161684 : if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
7255 161684 : || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
7256 6766 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
7257 : break;
7258 47352 : if (clauses == NULL)
7259 : {
7260 : /* If this was a workshare clause, see if it had been combined
7261 : with its parallel. In that case, look for the clauses on the
7262 : parallel statement itself. */
7263 34860 : if (is_parallel_ctx (ctx))
7264 30857 : return;
7265 :
7266 34860 : ctx = ctx->outer;
7267 34860 : if (ctx == NULL || !is_parallel_ctx (ctx))
7268 : return;
7269 :
7270 12271 : clauses = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
7271 : OMP_CLAUSE_LASTPRIVATE);
7272 12271 : if (clauses == NULL)
7273 : return;
7274 : par_clauses = true;
7275 : }
7276 :
7277 16495 : bool maybe_simt = false;
7278 16495 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7279 16495 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
7280 : {
7281 7427 : maybe_simt = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMT_);
7282 7427 : simduid = omp_find_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
7283 7427 : if (simduid)
7284 3551 : simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7285 : }
7286 :
7287 16495 : if (predicate)
7288 : {
7289 16372 : gcond *stmt;
7290 16372 : tree label_true, arm1, arm2;
7291 16372 : enum tree_code pred_code = TREE_CODE (predicate);
7292 :
7293 16372 : label = create_artificial_label (UNKNOWN_LOCATION);
7294 16372 : label_true = create_artificial_label (UNKNOWN_LOCATION);
7295 16372 : if (TREE_CODE_CLASS (pred_code) == tcc_comparison)
7296 : {
7297 16372 : arm1 = TREE_OPERAND (predicate, 0);
7298 16372 : arm2 = TREE_OPERAND (predicate, 1);
7299 16372 : gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
7300 16372 : gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
7301 : }
7302 : else
7303 : {
7304 0 : arm1 = predicate;
7305 0 : gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
7306 0 : arm2 = boolean_false_node;
7307 0 : pred_code = NE_EXPR;
7308 : }
7309 16372 : if (maybe_simt)
7310 : {
7311 0 : c = build2 (pred_code, boolean_type_node, arm1, arm2);
7312 0 : c = fold_convert (integer_type_node, c);
7313 0 : simtcond = create_tmp_var (integer_type_node);
7314 0 : gimplify_assign (simtcond, c, stmt_list);
7315 0 : gcall *g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY,
7316 : 1, simtcond);
7317 0 : c = create_tmp_var (integer_type_node);
7318 0 : gimple_call_set_lhs (g, c);
7319 0 : gimple_seq_add_stmt (stmt_list, g);
7320 0 : stmt = gimple_build_cond (NE_EXPR, c, integer_zero_node,
7321 : label_true, label);
7322 : }
7323 : else
7324 16372 : stmt = gimple_build_cond (pred_code, arm1, arm2, label_true, label);
7325 16372 : gimple_seq_add_stmt (stmt_list, stmt);
7326 16372 : gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
7327 : }
7328 :
7329 16495 : tree cond_ptr = NULL_TREE;
7330 61602 : for (c = clauses; c ;)
7331 : {
7332 56370 : tree var, new_var;
7333 56370 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
7334 56370 : gimple_seq *this_stmt_list = stmt_list;
7335 56370 : tree lab2 = NULL_TREE;
7336 :
7337 56370 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7338 21824 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
7339 386 : && ctx->lastprivate_conditional_map
7340 56743 : && !ctx->combined_into_simd_safelen1)
7341 : {
7342 316 : gcc_assert (body_p);
7343 316 : if (simduid)
7344 37 : goto next;
7345 279 : if (cond_ptr == NULL_TREE)
7346 : {
7347 205 : cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
7348 205 : cond_ptr = OMP_CLAUSE_DECL (cond_ptr);
7349 : }
7350 279 : tree type = TREE_TYPE (TREE_TYPE (cond_ptr));
7351 279 : tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
7352 279 : tree v = *ctx->lastprivate_conditional_map->get (o);
7353 279 : gimplify_assign (v, build_zero_cst (type), body_p);
7354 279 : this_stmt_list = cstmt_list;
7355 279 : tree mem;
7356 279 : if (POINTER_TYPE_P (TREE_TYPE (cond_ptr)))
7357 : {
7358 136 : mem = build2 (MEM_REF, type, cond_ptr,
7359 136 : build_int_cst (TREE_TYPE (cond_ptr),
7360 136 : conditional_off));
7361 136 : conditional_off += tree_to_uhwi (TYPE_SIZE_UNIT (type));
7362 : }
7363 : else
7364 143 : mem = build4 (ARRAY_REF, type, cond_ptr,
7365 143 : size_int (conditional_off++), NULL_TREE, NULL_TREE);
7366 279 : tree mem2 = copy_node (mem);
7367 279 : gimple_seq seq = NULL;
7368 279 : mem = force_gimple_operand (mem, &seq, true, NULL_TREE);
7369 279 : gimple_seq_add_seq (this_stmt_list, seq);
7370 279 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
7371 279 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
7372 279 : gimple *g = gimple_build_cond (GT_EXPR, v, mem, lab1, lab2);
7373 279 : gimple_seq_add_stmt (this_stmt_list, g);
7374 279 : gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab1));
7375 279 : gimplify_assign (mem2, v, this_stmt_list);
7376 : }
7377 56054 : else if (predicate
7378 55808 : && ctx->combined_into_simd_safelen1
7379 116 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7380 57 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
7381 56111 : && ctx->lastprivate_conditional_map)
7382 : this_stmt_list = &post_stmt_list;
7383 :
7384 56333 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7385 56333 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7386 4870 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
7387 : {
7388 26657 : var = OMP_CLAUSE_DECL (c);
7389 26657 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7390 21787 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
7391 27688 : && is_taskloop_ctx (ctx))
7392 : {
7393 312 : gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
7394 312 : new_var = lookup_decl (var, ctx->outer);
7395 : }
7396 : else
7397 : {
7398 26345 : new_var = lookup_decl (var, ctx);
7399 : /* Avoid uninitialized warnings for lastprivate and
7400 : for linear iterators. */
7401 26345 : if (predicate
7402 52497 : && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7403 4870 : || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
7404 24883 : suppress_warning (new_var, OPT_Wuninitialized);
7405 : }
7406 :
7407 26657 : if (!maybe_simt && simduid && DECL_HAS_VALUE_EXPR_P (new_var))
7408 : {
7409 5864 : tree val = DECL_VALUE_EXPR (new_var);
7410 5864 : if (TREE_CODE (val) == ARRAY_REF
7411 5816 : && VAR_P (TREE_OPERAND (val, 0))
7412 11680 : && lookup_attribute ("omp simd array",
7413 5816 : DECL_ATTRIBUTES (TREE_OPERAND (val,
7414 : 0))))
7415 : {
7416 5816 : if (lastlane == NULL)
7417 : {
7418 2759 : lastlane = create_tmp_var (unsigned_type_node);
7419 2759 : gcall *g
7420 2759 : = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
7421 : 2, simduid,
7422 2759 : TREE_OPERAND (val, 1));
7423 2759 : gimple_call_set_lhs (g, lastlane);
7424 2759 : gimple_seq_add_stmt (this_stmt_list, g);
7425 : }
7426 5816 : new_var = build4 (ARRAY_REF, TREE_TYPE (val),
7427 5816 : TREE_OPERAND (val, 0), lastlane,
7428 : NULL_TREE, NULL_TREE);
7429 5816 : TREE_THIS_NOTRAP (new_var) = 1;
7430 : }
7431 : }
7432 20793 : else if (maybe_simt)
7433 : {
7434 0 : tree val = (DECL_HAS_VALUE_EXPR_P (new_var)
7435 0 : ? DECL_VALUE_EXPR (new_var)
7436 : : new_var);
7437 0 : if (simtlast == NULL)
7438 : {
7439 0 : simtlast = create_tmp_var (unsigned_type_node);
7440 0 : gcall *g = gimple_build_call_internal
7441 0 : (IFN_GOMP_SIMT_LAST_LANE, 1, simtcond);
7442 0 : gimple_call_set_lhs (g, simtlast);
7443 0 : gimple_seq_add_stmt (this_stmt_list, g);
7444 : }
7445 0 : x = build_call_expr_internal_loc
7446 0 : (UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_IDX,
7447 0 : TREE_TYPE (val), 2, val, simtlast);
7448 0 : new_var = unshare_expr (new_var);
7449 0 : gimplify_assign (new_var, x, this_stmt_list);
7450 0 : new_var = unshare_expr (new_var);
7451 : }
7452 :
7453 26657 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7454 26657 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
7455 : {
7456 7159 : lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
7457 7159 : gimple_seq_add_seq (this_stmt_list,
7458 7159 : OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
7459 7159 : OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
7460 : }
7461 19498 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7462 19498 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
7463 : {
7464 426 : lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
7465 426 : gimple_seq_add_seq (this_stmt_list,
7466 426 : OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
7467 426 : OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
7468 : }
7469 :
7470 26657 : x = NULL_TREE;
7471 26657 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
7472 21787 : && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c)
7473 26717 : && is_taskloop_ctx (ctx))
7474 : {
7475 76 : tree ovar = maybe_lookup_decl_in_outer_ctx (var,
7476 38 : ctx->outer->outer);
7477 38 : if (is_global_var (ovar))
7478 7 : x = ovar;
7479 : }
7480 7 : if (!x)
7481 26650 : x = build_outer_var_ref (var, ctx, OMP_CLAUSE_LASTPRIVATE);
7482 26657 : if (omp_privatize_by_reference (var))
7483 657 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7484 26657 : x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
7485 26657 : gimplify_and_add (x, this_stmt_list);
7486 :
7487 26657 : if (lab2)
7488 279 : gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
7489 : }
7490 :
7491 56370 : next:
7492 56370 : c = OMP_CLAUSE_CHAIN (c);
7493 56370 : if (c == NULL && !par_clauses)
7494 : {
7495 : /* If this was a workshare clause, see if it had been combined
7496 : with its parallel. In that case, continue looking for the
7497 : clauses also on the parallel statement itself. */
7498 12492 : if (is_parallel_ctx (ctx))
7499 : break;
7500 :
7501 12492 : ctx = ctx->outer;
7502 12492 : if (ctx == NULL || !is_parallel_ctx (ctx))
7503 : break;
7504 :
7505 1229 : c = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
7506 : OMP_CLAUSE_LASTPRIVATE);
7507 1229 : par_clauses = true;
7508 : }
7509 : }
7510 :
7511 16495 : if (label)
7512 16372 : gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
7513 16495 : gimple_seq_add_seq (stmt_list, post_stmt_list);
7514 : }
7515 :
7516 : /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
7517 : (which might be a placeholder). INNER is true if this is an inner
7518 : axis of a multi-axis loop. FORK and JOIN are (optional) fork and
7519 : join markers. Generate the before-loop forking sequence in
7520 : FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
7521 : general form of these sequences is
7522 :
7523 : GOACC_REDUCTION_SETUP
7524 : GOACC_FORK
7525 : GOACC_REDUCTION_INIT
7526 : ...
7527 : GOACC_REDUCTION_FINI
7528 : GOACC_JOIN
7529 : GOACC_REDUCTION_TEARDOWN. */
7530 :
7531 : static void
7532 25946 : lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
7533 : gcall *fork, gcall *private_marker, gcall *join,
7534 : gimple_seq *fork_seq, gimple_seq *join_seq,
7535 : omp_context *ctx)
7536 : {
7537 25946 : gimple_seq before_fork = NULL;
7538 25946 : gimple_seq after_fork = NULL;
7539 25946 : gimple_seq before_join = NULL;
7540 25946 : gimple_seq after_join = NULL;
7541 25946 : tree init_code = NULL_TREE, fini_code = NULL_TREE,
7542 25946 : setup_code = NULL_TREE, teardown_code = NULL_TREE;
7543 25946 : unsigned offset = 0;
7544 :
7545 96516 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
7546 70570 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
7547 : {
7548 : /* No 'reduction' clauses on OpenACC 'kernels'. */
7549 7751 : gcc_checking_assert (!is_oacc_kernels (ctx));
7550 : /* Likewise, on OpenACC 'kernels' decomposed parts. */
7551 7751 : gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
7552 :
7553 7751 : tree orig = OMP_CLAUSE_DECL (c);
7554 7751 : tree orig_clause;
7555 7751 : tree var = maybe_lookup_decl (orig, ctx);
7556 7751 : tree ref_to_res = NULL_TREE;
7557 7751 : tree incoming, outgoing, v1, v2, v3;
7558 7751 : bool is_private = false;
7559 :
7560 7751 : enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
7561 7751 : if (rcode == MINUS_EXPR)
7562 : rcode = PLUS_EXPR;
7563 6609 : else if (rcode == TRUTH_ANDIF_EXPR)
7564 : rcode = BIT_AND_EXPR;
7565 6431 : else if (rcode == TRUTH_ORIF_EXPR)
7566 433 : rcode = BIT_IOR_EXPR;
7567 7751 : tree op = build_int_cst (unsigned_type_node, rcode);
7568 :
7569 7751 : if (!var)
7570 4 : var = orig;
7571 :
7572 7751 : incoming = outgoing = var;
7573 :
7574 7751 : if (!inner)
7575 : {
7576 : /* See if an outer construct also reduces this variable. */
7577 : omp_context *outer = ctx;
7578 :
7579 7385 : while (omp_context *probe = outer->outer)
7580 : {
7581 4708 : enum gimple_code type = gimple_code (probe->stmt);
7582 4708 : tree cls;
7583 :
7584 4708 : switch (type)
7585 : {
7586 2220 : case GIMPLE_OMP_FOR:
7587 2220 : cls = gimple_omp_for_clauses (probe->stmt);
7588 2220 : break;
7589 :
7590 2488 : case GIMPLE_OMP_TARGET:
7591 : /* No 'reduction' clauses inside OpenACC 'kernels'
7592 : regions. */
7593 2488 : gcc_checking_assert (!is_oacc_kernels (probe));
7594 :
7595 2488 : if (!is_gimple_omp_offloaded (probe->stmt))
7596 26 : goto do_lookup;
7597 :
7598 2462 : cls = gimple_omp_target_clauses (probe->stmt);
7599 2462 : break;
7600 :
7601 0 : default:
7602 0 : goto do_lookup;
7603 : }
7604 :
7605 14249 : outer = probe;
7606 14249 : for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
7607 11632 : if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
7608 11632 : && orig == OMP_CLAUSE_DECL (cls))
7609 : {
7610 1772 : incoming = outgoing = lookup_decl (orig, probe);
7611 1772 : goto has_outer_reduction;
7612 : }
7613 9860 : else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
7614 8971 : || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
7615 11164 : && orig == OMP_CLAUSE_DECL (cls))
7616 : {
7617 293 : is_private = true;
7618 293 : goto do_lookup;
7619 : }
7620 : }
7621 :
7622 2677 : do_lookup:
7623 : /* This is the outermost construct with this reduction,
7624 : see if there's a mapping for it. */
7625 2996 : orig_clause = NULL_TREE;
7626 2996 : if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET)
7627 7557 : for (tree cls = gimple_omp_target_clauses (outer->stmt);
7628 7557 : cls; cls = OMP_CLAUSE_CHAIN (cls))
7629 7250 : if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_MAP
7630 4823 : && orig == OMP_CLAUSE_DECL (cls)
7631 9805 : && maybe_lookup_field (cls, outer))
7632 : {
7633 : orig_clause = cls;
7634 : break;
7635 : }
7636 2996 : if (orig_clause != NULL_TREE && !is_private)
7637 : {
7638 2553 : ref_to_res = build_receiver_ref (orig_clause, false, outer);
7639 2553 : if (omp_privatize_by_reference (orig))
7640 79 : ref_to_res = build_simple_mem_ref (ref_to_res);
7641 :
7642 2553 : tree type = TREE_TYPE (var);
7643 2553 : if (POINTER_TYPE_P (type))
7644 79 : type = TREE_TYPE (type);
7645 :
7646 2553 : outgoing = var;
7647 2553 : incoming = omp_reduction_init_op (loc, rcode, type);
7648 : }
7649 : else
7650 : {
7651 : /* Try to look at enclosing contexts for reduction var,
7652 : use original if no mapping found. */
7653 443 : tree t = NULL_TREE;
7654 443 : omp_context *c = ctx->outer;
7655 895 : while (c && !t)
7656 : {
7657 452 : t = maybe_lookup_decl (orig, c);
7658 452 : c = c->outer;
7659 : }
7660 443 : incoming = outgoing = (t ? t : orig);
7661 : }
7662 :
7663 2553 : has_outer_reduction:;
7664 : }
7665 :
7666 4325 : if (!ref_to_res)
7667 5198 : ref_to_res = integer_zero_node;
7668 :
7669 7751 : if (omp_privatize_by_reference (orig))
7670 : {
7671 159 : tree type = TREE_TYPE (var);
7672 159 : const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
7673 :
7674 159 : if (!inner)
7675 : {
7676 110 : tree x = create_tmp_var (TREE_TYPE (type), id);
7677 110 : gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
7678 : }
7679 :
7680 159 : v1 = create_tmp_var (type, id);
7681 159 : v2 = create_tmp_var (type, id);
7682 159 : v3 = create_tmp_var (type, id);
7683 :
7684 159 : gimplify_assign (v1, var, fork_seq);
7685 159 : gimplify_assign (v2, var, fork_seq);
7686 159 : gimplify_assign (v3, var, fork_seq);
7687 :
7688 159 : var = build_simple_mem_ref (var);
7689 159 : v1 = build_simple_mem_ref (v1);
7690 159 : v2 = build_simple_mem_ref (v2);
7691 159 : v3 = build_simple_mem_ref (v3);
7692 159 : outgoing = build_simple_mem_ref (outgoing);
7693 :
7694 159 : if (!TREE_CONSTANT (incoming))
7695 80 : incoming = build_simple_mem_ref (incoming);
7696 : }
7697 : else
7698 : /* Note that 'var' might be a mem ref. */
7699 : v1 = v2 = v3 = var;
7700 :
7701 : /* Determine position in reduction buffer, which may be used
7702 : by target. The parser has ensured that this is not a
7703 : variable-sized type. */
7704 7751 : fixed_size_mode mode
7705 7751 : = as_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (var)));
7706 7751 : unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
7707 7751 : offset = (offset + align - 1) & ~(align - 1);
7708 7751 : tree off = build_int_cst (sizetype, offset);
7709 7751 : offset += GET_MODE_SIZE (mode);
7710 :
7711 7751 : if (!init_code)
7712 : {
7713 6969 : init_code = build_int_cst (integer_type_node,
7714 : IFN_GOACC_REDUCTION_INIT);
7715 6969 : fini_code = build_int_cst (integer_type_node,
7716 : IFN_GOACC_REDUCTION_FINI);
7717 6969 : setup_code = build_int_cst (integer_type_node,
7718 : IFN_GOACC_REDUCTION_SETUP);
7719 6969 : teardown_code = build_int_cst (integer_type_node,
7720 : IFN_GOACC_REDUCTION_TEARDOWN);
7721 : }
7722 :
7723 7751 : tree setup_call
7724 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7725 7751 : TREE_TYPE (var), 6, setup_code,
7726 : unshare_expr (ref_to_res),
7727 : unshare_expr (incoming),
7728 : level, op, off);
7729 7751 : tree init_call
7730 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7731 7751 : TREE_TYPE (var), 6, init_code,
7732 : unshare_expr (ref_to_res),
7733 : unshare_expr (v1), level, op, off);
7734 7751 : tree fini_call
7735 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7736 7751 : TREE_TYPE (var), 6, fini_code,
7737 : unshare_expr (ref_to_res),
7738 : unshare_expr (v2), level, op, off);
7739 7751 : tree teardown_call
7740 15502 : = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
7741 7751 : TREE_TYPE (var), 6, teardown_code,
7742 : ref_to_res, unshare_expr (v3),
7743 : level, op, off);
7744 :
7745 7751 : gimplify_assign (unshare_expr (v1), setup_call, &before_fork);
7746 7751 : gimplify_assign (unshare_expr (v2), init_call, &after_fork);
7747 7751 : gimplify_assign (unshare_expr (v3), fini_call, &before_join);
7748 7751 : gimplify_assign (unshare_expr (outgoing), teardown_call, &after_join);
7749 : }
7750 :
7751 : /* Now stitch things together. */
7752 25946 : gimple_seq_add_seq (fork_seq, before_fork);
7753 25946 : if (private_marker)
7754 259 : gimple_seq_add_stmt (fork_seq, private_marker);
7755 25946 : if (fork)
7756 16551 : gimple_seq_add_stmt (fork_seq, fork);
7757 25946 : gimple_seq_add_seq (fork_seq, after_fork);
7758 :
7759 25946 : gimple_seq_add_seq (join_seq, before_join);
7760 25946 : if (join)
7761 16551 : gimple_seq_add_stmt (join_seq, join);
7762 25946 : gimple_seq_add_seq (join_seq, after_join);
7763 25946 : }
7764 :
7765 : /* Generate code to implement the REDUCTION clauses, append it
7766 : to STMT_SEQP. CLIST if non-NULL is a pointer to a sequence
7767 : that should be emitted also inside of the critical section,
7768 : in that case clear *CLIST afterwards, otherwise leave it as is
7769 : and let the caller emit it itself. */
7770 :
7771 : static void
7772 72141 : lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
7773 : gimple_seq *clist, omp_context *ctx)
7774 : {
7775 72141 : gimple_seq sub_seq = NULL;
7776 72141 : gimple *stmt;
7777 72141 : tree x, c;
7778 72141 : int count = 0;
7779 :
7780 : /* OpenACC loop reductions are handled elsewhere. */
7781 72141 : if (is_gimple_omp_oacc (ctx->stmt))
7782 71082 : return;
7783 :
7784 : /* SIMD reductions are handled in lower_rec_input_clauses. */
7785 60816 : if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
7786 60816 : && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
7787 : return;
7788 :
7789 : /* inscan reductions are handled elsewhere. */
7790 51458 : if (ctx->scan_inclusive || ctx->scan_exclusive)
7791 : return;
7792 :
7793 : /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
7794 : update in that case, otherwise use a lock. */
7795 242781 : for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
7796 192362 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
7797 192362 : && !OMP_CLAUSE_REDUCTION_TASK (c))
7798 : {
7799 4635 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
7800 4635 : || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
7801 : {
7802 : /* Never use OMP_ATOMIC for array reductions or UDRs. */
7803 : count = -1;
7804 : break;
7805 : }
7806 3773 : count++;
7807 : }
7808 :
7809 51281 : if (count == 0)
7810 : return;
7811 :
7812 15006 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
7813 : {
7814 13947 : tree var, ref, new_var, orig_var;
7815 13947 : enum tree_code code;
7816 13947 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
7817 :
7818 22447 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
7819 13947 : || OMP_CLAUSE_REDUCTION_TASK (c))
7820 8500 : continue;
7821 :
7822 5447 : enum omp_clause_code ccode = OMP_CLAUSE_REDUCTION;
7823 5447 : orig_var = var = OMP_CLAUSE_DECL (c);
7824 5447 : if (TREE_CODE (var) == MEM_REF)
7825 : {
7826 689 : var = TREE_OPERAND (var, 0);
7827 689 : if (TREE_CODE (var) == POINTER_PLUS_EXPR)
7828 50 : var = TREE_OPERAND (var, 0);
7829 689 : if (TREE_CODE (var) == ADDR_EXPR)
7830 304 : var = TREE_OPERAND (var, 0);
7831 : else
7832 : {
7833 : /* If this is a pointer or referenced based array
7834 : section, the var could be private in the outer
7835 : context e.g. on orphaned loop construct. Pretend this
7836 : is private variable's outer reference. */
7837 385 : ccode = OMP_CLAUSE_PRIVATE;
7838 385 : if (INDIRECT_REF_P (var))
7839 54 : var = TREE_OPERAND (var, 0);
7840 : }
7841 689 : orig_var = var;
7842 689 : if (is_variable_sized (var))
7843 : {
7844 25 : gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
7845 25 : var = DECL_VALUE_EXPR (var);
7846 25 : gcc_assert (INDIRECT_REF_P (var));
7847 25 : var = TREE_OPERAND (var, 0);
7848 25 : gcc_assert (DECL_P (var));
7849 : }
7850 : }
7851 5447 : new_var = lookup_decl (var, ctx);
7852 5447 : if (var == OMP_CLAUSE_DECL (c)
7853 5447 : && omp_privatize_by_reference (var))
7854 152 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7855 5447 : ref = build_outer_var_ref (var, ctx, ccode);
7856 5447 : code = OMP_CLAUSE_REDUCTION_CODE (c);
7857 :
7858 : /* reduction(-:var) sums up the partial results, so it acts
7859 : identically to reduction(+:var). */
7860 5447 : if (code == MINUS_EXPR)
7861 57 : code = PLUS_EXPR;
7862 :
7863 5447 : bool is_truth_op = (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR);
7864 5447 : if (count == 1)
7865 : {
7866 3324 : tree addr = build_fold_addr_expr_loc (clause_loc, ref);
7867 :
7868 3324 : addr = save_expr (addr);
7869 3324 : ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
7870 3324 : tree new_var2 = new_var;
7871 3324 : tree ref2 = ref;
7872 3324 : if (is_truth_op)
7873 : {
7874 784 : tree zero = build_zero_cst (TREE_TYPE (new_var));
7875 784 : new_var2 = fold_build2_loc (clause_loc, NE_EXPR,
7876 : boolean_type_node, new_var, zero);
7877 784 : ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node,
7878 : ref, zero);
7879 : }
7880 3324 : x = fold_build2_loc (clause_loc, code, TREE_TYPE (new_var2), ref2,
7881 : new_var2);
7882 3324 : if (is_truth_op)
7883 784 : x = fold_convert (TREE_TYPE (new_var), x);
7884 3324 : x = build2 (OMP_ATOMIC, void_type_node, addr, x);
7885 3324 : OMP_ATOMIC_MEMORY_ORDER (x) = OMP_MEMORY_ORDER_RELAXED;
7886 3324 : gimplify_and_add (x, stmt_seqp);
7887 3324 : return;
7888 : }
7889 2123 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
7890 : {
7891 689 : tree d = OMP_CLAUSE_DECL (c);
7892 689 : tree type = TREE_TYPE (d);
7893 689 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
7894 689 : tree i = create_tmp_var (TREE_TYPE (v));
7895 689 : tree ptype = build_pointer_type (TREE_TYPE (type));
7896 689 : tree bias = TREE_OPERAND (d, 1);
7897 689 : d = TREE_OPERAND (d, 0);
7898 689 : if (TREE_CODE (d) == POINTER_PLUS_EXPR)
7899 : {
7900 50 : tree b = TREE_OPERAND (d, 1);
7901 50 : b = maybe_lookup_decl (b, ctx);
7902 50 : if (b == NULL)
7903 : {
7904 2 : b = TREE_OPERAND (d, 1);
7905 2 : b = maybe_lookup_decl_in_outer_ctx (b, ctx);
7906 : }
7907 50 : if (integer_zerop (bias))
7908 : bias = b;
7909 : else
7910 : {
7911 0 : bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
7912 0 : bias = fold_build2_loc (clause_loc, PLUS_EXPR,
7913 0 : TREE_TYPE (b), b, bias);
7914 : }
7915 50 : d = TREE_OPERAND (d, 0);
7916 : }
7917 : /* For ref build_outer_var_ref already performs this, so
7918 : only new_var needs a dereference. */
7919 689 : if (INDIRECT_REF_P (d))
7920 : {
7921 54 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
7922 54 : gcc_assert (omp_privatize_by_reference (var)
7923 : && var == orig_var);
7924 : }
7925 635 : else if (TREE_CODE (d) == ADDR_EXPR)
7926 : {
7927 304 : if (orig_var == var)
7928 : {
7929 279 : new_var = build_fold_addr_expr (new_var);
7930 279 : ref = build_fold_addr_expr (ref);
7931 : }
7932 : }
7933 : else
7934 : {
7935 331 : gcc_assert (orig_var == var);
7936 331 : if (omp_privatize_by_reference (var))
7937 79 : ref = build_fold_addr_expr (ref);
7938 : }
7939 689 : if (DECL_P (v))
7940 : {
7941 93 : tree t = maybe_lookup_decl (v, ctx);
7942 93 : if (t)
7943 88 : v = t;
7944 : else
7945 5 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
7946 93 : gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
7947 : }
7948 689 : if (!integer_zerop (bias))
7949 : {
7950 402 : bias = fold_convert_loc (clause_loc, sizetype, bias);
7951 804 : new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
7952 402 : TREE_TYPE (new_var), new_var,
7953 : unshare_expr (bias));
7954 402 : ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
7955 402 : TREE_TYPE (ref), ref, bias);
7956 : }
7957 689 : new_var = fold_convert_loc (clause_loc, ptype, new_var);
7958 689 : ref = fold_convert_loc (clause_loc, ptype, ref);
7959 689 : tree m = create_tmp_var (ptype);
7960 689 : gimplify_assign (m, new_var, stmt_seqp);
7961 689 : new_var = m;
7962 689 : m = create_tmp_var (ptype);
7963 689 : gimplify_assign (m, ref, stmt_seqp);
7964 689 : ref = m;
7965 689 : gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
7966 689 : tree body = create_artificial_label (UNKNOWN_LOCATION);
7967 689 : tree end = create_artificial_label (UNKNOWN_LOCATION);
7968 689 : gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
7969 689 : tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
7970 689 : tree out = build_simple_mem_ref_loc (clause_loc, ref);
7971 689 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
7972 : {
7973 72 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
7974 72 : tree decl_placeholder
7975 72 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
7976 72 : SET_DECL_VALUE_EXPR (placeholder, out);
7977 72 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
7978 72 : SET_DECL_VALUE_EXPR (decl_placeholder, priv);
7979 72 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
7980 72 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
7981 72 : gimple_seq_add_seq (&sub_seq,
7982 72 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
7983 72 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
7984 72 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
7985 72 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
7986 : }
7987 : else
7988 : {
7989 617 : tree out2 = out;
7990 617 : tree priv2 = priv;
7991 617 : if (is_truth_op)
7992 : {
7993 0 : tree zero = build_zero_cst (TREE_TYPE (out));
7994 0 : out2 = fold_build2_loc (clause_loc, NE_EXPR,
7995 : boolean_type_node, out, zero);
7996 0 : priv2 = fold_build2_loc (clause_loc, NE_EXPR,
7997 : boolean_type_node, priv, zero);
7998 : }
7999 617 : x = build2 (code, TREE_TYPE (out2), out2, priv2);
8000 617 : if (is_truth_op)
8001 0 : x = fold_convert (TREE_TYPE (out), x);
8002 617 : out = unshare_expr (out);
8003 617 : gimplify_assign (out, x, &sub_seq);
8004 : }
8005 689 : gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
8006 689 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
8007 689 : gimple_seq_add_stmt (&sub_seq, g);
8008 689 : g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
8009 689 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
8010 689 : gimple_seq_add_stmt (&sub_seq, g);
8011 689 : g = gimple_build_assign (i, PLUS_EXPR, i,
8012 689 : build_int_cst (TREE_TYPE (i), 1));
8013 689 : gimple_seq_add_stmt (&sub_seq, g);
8014 689 : g = gimple_build_cond (LE_EXPR, i, v, body, end);
8015 689 : gimple_seq_add_stmt (&sub_seq, g);
8016 689 : gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
8017 : }
8018 1434 : else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
8019 : {
8020 788 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
8021 :
8022 788 : if (omp_privatize_by_reference (var)
8023 845 : && !useless_type_conversion_p (TREE_TYPE (placeholder),
8024 57 : TREE_TYPE (ref)))
8025 49 : ref = build_fold_addr_expr_loc (clause_loc, ref);
8026 788 : SET_DECL_VALUE_EXPR (placeholder, ref);
8027 788 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
8028 788 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
8029 788 : gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
8030 788 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
8031 788 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
8032 : }
8033 : else
8034 : {
8035 646 : tree new_var2 = new_var;
8036 646 : tree ref2 = ref;
8037 646 : if (is_truth_op)
8038 : {
8039 78 : tree zero = build_zero_cst (TREE_TYPE (new_var));
8040 78 : new_var2 = fold_build2_loc (clause_loc, NE_EXPR,
8041 : boolean_type_node, new_var, zero);
8042 78 : ref2 = fold_build2_loc (clause_loc, NE_EXPR, boolean_type_node,
8043 : ref, zero);
8044 : }
8045 646 : x = build2 (code, TREE_TYPE (ref), ref2, new_var2);
8046 646 : if (is_truth_op)
8047 78 : x = fold_convert (TREE_TYPE (new_var), x);
8048 646 : ref = build_outer_var_ref (var, ctx);
8049 646 : gimplify_assign (ref, x, &sub_seq);
8050 : }
8051 : }
8052 :
8053 1059 : stmt
8054 1059 : = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START),
8055 : 0);
8056 1059 : gimple_seq_add_stmt (stmt_seqp, stmt);
8057 :
8058 1059 : gimple_seq_add_seq (stmt_seqp, sub_seq);
8059 :
8060 1059 : if (clist)
8061 : {
8062 173 : gimple_seq_add_seq (stmt_seqp, *clist);
8063 173 : *clist = NULL;
8064 : }
8065 :
8066 1059 : stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END),
8067 : 0);
8068 1059 : gimple_seq_add_stmt (stmt_seqp, stmt);
8069 : }
8070 :
8071 :
8072 : /* Generate code to implement the COPYPRIVATE clauses. */
8073 :
8074 : static void
8075 115 : lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
8076 : omp_context *ctx)
8077 : {
8078 115 : tree c;
8079 :
8080 463 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
8081 : {
8082 348 : tree var, new_var, ref, x;
8083 348 : bool by_ref;
8084 348 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
8085 :
8086 348 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
8087 6 : continue;
8088 :
8089 342 : var = OMP_CLAUSE_DECL (c);
8090 342 : by_ref = use_pointer_for_field (var, NULL);
8091 :
8092 342 : ref = build_sender_ref (var, ctx);
8093 342 : x = new_var = lookup_decl_in_outer_ctx (var, ctx);
8094 342 : if (by_ref)
8095 : {
8096 74 : x = build_fold_addr_expr_loc (clause_loc, new_var);
8097 74 : x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
8098 : }
8099 342 : gimplify_assign (ref, x, slist);
8100 :
8101 342 : ref = build_receiver_ref (var, false, ctx);
8102 342 : if (by_ref)
8103 : {
8104 74 : ref = fold_convert_loc (clause_loc,
8105 74 : build_pointer_type (TREE_TYPE (new_var)),
8106 : ref);
8107 74 : ref = build_fold_indirect_ref_loc (clause_loc, ref);
8108 : }
8109 342 : if (omp_privatize_by_reference (var))
8110 : {
8111 171 : ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
8112 171 : ref = build_simple_mem_ref_loc (clause_loc, ref);
8113 171 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
8114 : }
8115 342 : x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
8116 342 : gimplify_and_add (x, rlist);
8117 : }
8118 115 : }
8119 :
8120 :
8121 : /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
8122 : and REDUCTION from the sender (aka parent) side. */
8123 :
8124 : static void
8125 22482 : lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
8126 : omp_context *ctx)
8127 : {
8128 22482 : tree c, t;
8129 22482 : int ignored_looptemp = 0;
8130 22482 : bool is_taskloop = false;
8131 :
8132 : /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
8133 : by GOMP_taskloop. */
8134 22482 : if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
8135 : {
8136 : ignored_looptemp = 2;
8137 : is_taskloop = true;
8138 : }
8139 :
8140 117247 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
8141 : {
8142 94765 : tree val, ref, x, var;
8143 94765 : bool by_ref, do_in = false, do_out = false;
8144 94765 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
8145 :
8146 94765 : switch (OMP_CLAUSE_CODE (c))
8147 : {
8148 4660 : case OMP_CLAUSE_PRIVATE:
8149 4660 : if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
8150 : break;
8151 4505 : continue;
8152 : case OMP_CLAUSE_FIRSTPRIVATE:
8153 : case OMP_CLAUSE_COPYIN:
8154 : case OMP_CLAUSE_LASTPRIVATE:
8155 : case OMP_CLAUSE_IN_REDUCTION:
8156 : case OMP_CLAUSE__REDUCTEMP_:
8157 : break;
8158 4811 : case OMP_CLAUSE_REDUCTION:
8159 4811 : if (is_task_ctx (ctx) || OMP_CLAUSE_REDUCTION_TASK (c))
8160 745 : continue;
8161 : break;
8162 17603 : case OMP_CLAUSE_SHARED:
8163 17603 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
8164 : break;
8165 17291 : continue;
8166 18801 : case OMP_CLAUSE__LOOPTEMP_:
8167 18801 : if (ignored_looptemp)
8168 : {
8169 2660 : ignored_looptemp--;
8170 2660 : continue;
8171 : }
8172 : break;
8173 11985 : default:
8174 11985 : continue;
8175 : }
8176 :
8177 57579 : val = OMP_CLAUSE_DECL (c);
8178 57579 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
8179 53513 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
8180 59219 : && TREE_CODE (val) == MEM_REF)
8181 : {
8182 1578 : val = TREE_OPERAND (val, 0);
8183 1578 : if (TREE_CODE (val) == POINTER_PLUS_EXPR)
8184 351 : val = TREE_OPERAND (val, 0);
8185 1578 : if (INDIRECT_REF_P (val)
8186 1494 : || TREE_CODE (val) == ADDR_EXPR)
8187 906 : val = TREE_OPERAND (val, 0);
8188 1578 : if (is_variable_sized (val))
8189 56 : continue;
8190 : }
8191 :
8192 : /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
8193 : outer taskloop region. */
8194 57523 : omp_context *ctx_for_o = ctx;
8195 57523 : if (is_taskloop
8196 3911 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
8197 57835 : && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
8198 312 : ctx_for_o = ctx->outer;
8199 :
8200 57523 : var = lookup_decl_in_outer_ctx (val, ctx_for_o);
8201 :
8202 57523 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
8203 57009 : && is_global_var (var)
8204 59828 : && (val == OMP_CLAUSE_DECL (c)
8205 273 : || !is_task_ctx (ctx)
8206 241 : || (TREE_CODE (TREE_TYPE (val)) != POINTER_TYPE
8207 187 : && (TREE_CODE (TREE_TYPE (val)) != REFERENCE_TYPE
8208 0 : || (TREE_CODE (TREE_TYPE (TREE_TYPE (val)))
8209 : != POINTER_TYPE)))))
8210 2251 : continue;
8211 :
8212 55272 : t = omp_member_access_dummy_var (var);
8213 55272 : if (t)
8214 : {
8215 249 : var = DECL_VALUE_EXPR (var);
8216 249 : tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
8217 249 : if (o != t)
8218 69 : var = unshare_and_remap (var, t, o);
8219 : else
8220 180 : var = unshare_expr (var);
8221 : }
8222 :
8223 55272 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
8224 : {
8225 : /* Handle taskloop firstprivate/lastprivate, where the
8226 : lastprivate on GIMPLE_OMP_TASK is represented as
8227 : OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
8228 79 : tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
8229 79 : x = omp_build_component_ref (ctx->sender_decl, f);
8230 79 : if (use_pointer_for_field (val, ctx))
8231 59 : var = build_fold_addr_expr (var);
8232 79 : gimplify_assign (x, var, ilist);
8233 79 : DECL_ABSTRACT_ORIGIN (f) = NULL;
8234 79 : continue;
8235 79 : }
8236 :
8237 55247 : if (((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
8238 51872 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION)
8239 4457 : || val == OMP_CLAUSE_DECL (c))
8240 109083 : && is_variable_sized (val))
8241 54 : continue;
8242 55139 : by_ref = use_pointer_for_field (val, NULL);
8243 :
8244 55139 : switch (OMP_CLAUSE_CODE (c))
8245 : {
8246 26849 : case OMP_CLAUSE_FIRSTPRIVATE:
8247 26849 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
8248 7262 : && !by_ref
8249 34059 : && is_task_ctx (ctx))
8250 2331 : suppress_warning (var);
8251 : do_in = true;
8252 : break;
8253 :
8254 : case OMP_CLAUSE_PRIVATE:
8255 : case OMP_CLAUSE_COPYIN:
8256 : case OMP_CLAUSE__LOOPTEMP_:
8257 : case OMP_CLAUSE__REDUCTEMP_:
8258 : do_in = true;
8259 : break;
8260 :
8261 6467 : case OMP_CLAUSE_LASTPRIVATE:
8262 6467 : if (by_ref || omp_privatize_by_reference (val))
8263 : {
8264 384 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
8265 239 : continue;
8266 : do_in = true;
8267 : }
8268 : else
8269 : {
8270 6083 : do_out = true;
8271 6083 : if (lang_hooks.decls.omp_private_outer_ref (val))
8272 : do_in = true;
8273 : }
8274 : break;
8275 :
8276 4457 : case OMP_CLAUSE_REDUCTION:
8277 4457 : case OMP_CLAUSE_IN_REDUCTION:
8278 4457 : do_in = true;
8279 4457 : if (val == OMP_CLAUSE_DECL (c))
8280 : {
8281 3154 : if (is_task_ctx (ctx))
8282 301 : by_ref = use_pointer_for_field (val, ctx);
8283 : else
8284 2853 : do_out = !(by_ref || omp_privatize_by_reference (val));
8285 : }
8286 : else
8287 1303 : by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
8288 : break;
8289 :
8290 0 : default:
8291 0 : gcc_unreachable ();
8292 : }
8293 :
8294 1604 : if (do_in)
8295 : {
8296 48841 : ref = build_sender_ref (val, ctx);
8297 48841 : x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
8298 48841 : gimplify_assign (ref, x, ilist);
8299 48841 : if (is_task_ctx (ctx))
8300 6232 : DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
8301 : }
8302 :
8303 54900 : if (do_out)
8304 : {
8305 8393 : ref = build_sender_ref (val, ctx);
8306 8393 : gimplify_assign (var, ref, olist);
8307 : }
8308 : }
8309 22482 : }
8310 :
8311 : /* Generate code to implement SHARED from the sender (aka parent)
8312 : side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
8313 : list things that got automatically shared. */
8314 :
8315 : static void
8316 22482 : lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
8317 : {
8318 22482 : tree var, ovar, nvar, t, f, x, record_type;
8319 :
8320 22482 : if (ctx->record_type == NULL)
8321 4464 : return;
8322 :
8323 18018 : record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
8324 86978 : for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
8325 : {
8326 68960 : ovar = DECL_ABSTRACT_ORIGIN (f);
8327 68960 : if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
8328 6311 : continue;
8329 :
8330 62649 : nvar = maybe_lookup_decl (ovar, ctx);
8331 113621 : if (!nvar
8332 62236 : || !DECL_HAS_VALUE_EXPR_P (nvar)
8333 74524 : || (ctx->allocate_map
8334 291 : && ctx->allocate_map->get (ovar)))
8335 50972 : continue;
8336 :
8337 : /* If CTX is a nested parallel directive. Find the immediately
8338 : enclosing parallel or workshare construct that contains a
8339 : mapping for OVAR. */
8340 11677 : var = lookup_decl_in_outer_ctx (ovar, ctx);
8341 :
8342 11677 : t = omp_member_access_dummy_var (var);
8343 11677 : if (t)
8344 : {
8345 49 : var = DECL_VALUE_EXPR (var);
8346 49 : tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
8347 49 : if (o != t)
8348 18 : var = unshare_and_remap (var, t, o);
8349 : else
8350 31 : var = unshare_expr (var);
8351 : }
8352 :
8353 11677 : if (use_pointer_for_field (ovar, ctx))
8354 : {
8355 6437 : x = build_sender_ref (ovar, ctx);
8356 6437 : if (TREE_CODE (TREE_TYPE (f)) == ARRAY_TYPE
8357 6437 : && TREE_TYPE (f) == TREE_TYPE (ovar))
8358 : {
8359 103 : gcc_assert (is_parallel_ctx (ctx)
8360 : && DECL_ARTIFICIAL (ovar));
8361 : /* _condtemp_ clause. */
8362 103 : var = build_constructor (TREE_TYPE (x), NULL);
8363 : }
8364 : else
8365 6334 : var = build_fold_addr_expr (var);
8366 6437 : gimplify_assign (x, var, ilist);
8367 : }
8368 : else
8369 : {
8370 5240 : x = build_sender_ref (ovar, ctx);
8371 5240 : gimplify_assign (x, var, ilist);
8372 :
8373 5240 : if (!TREE_READONLY (var)
8374 : /* We don't need to receive a new reference to a result
8375 : or parm decl. In fact we may not store to it as we will
8376 : invalidate any pending RSO and generate wrong gimple
8377 : during inlining. */
8378 5240 : && !((TREE_CODE (var) == RESULT_DECL
8379 3338 : || TREE_CODE (var) == PARM_DECL)
8380 182 : && DECL_BY_REFERENCE (var)))
8381 : {
8382 3267 : x = build_sender_ref (ovar, ctx);
8383 3267 : gimplify_assign (var, x, olist);
8384 : }
8385 : }
8386 : }
8387 : }
8388 :
8389 : /* Emit an OpenACC head marker call, encapulating the partitioning and
8390 : other information that must be processed by the target compiler.
8391 : Return the maximum number of dimensions the associated loop might
8392 : be partitioned over. */
8393 :
8394 : static unsigned
8395 9665 : lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
8396 : gimple_seq *seq, omp_context *ctx)
8397 : {
8398 9665 : unsigned levels = 0;
8399 9665 : unsigned tag = 0;
8400 9665 : tree gang_static = NULL_TREE;
8401 9665 : auto_vec<tree, 5> args;
8402 :
8403 19330 : args.quick_push (build_int_cst
8404 9665 : (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
8405 9665 : args.quick_push (ddvar);
8406 30854 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
8407 : {
8408 21189 : switch (OMP_CLAUSE_CODE (c))
8409 : {
8410 1856 : case OMP_CLAUSE_GANG:
8411 1856 : tag |= OLF_DIM_GANG;
8412 1856 : gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
8413 : /* static:* is represented by -1, and we can ignore it, as
8414 : scheduling is always static. */
8415 1856 : if (gang_static && integer_minus_onep (gang_static))
8416 70 : gang_static = NULL_TREE;
8417 1856 : levels++;
8418 1856 : break;
8419 :
8420 1330 : case OMP_CLAUSE_WORKER:
8421 1330 : tag |= OLF_DIM_WORKER;
8422 1330 : levels++;
8423 1330 : break;
8424 :
8425 1523 : case OMP_CLAUSE_VECTOR:
8426 1523 : tag |= OLF_DIM_VECTOR;
8427 1523 : levels++;
8428 1523 : break;
8429 :
8430 314 : case OMP_CLAUSE_SEQ:
8431 314 : tag |= OLF_SEQ;
8432 314 : break;
8433 :
8434 409 : case OMP_CLAUSE_AUTO:
8435 409 : tag |= OLF_AUTO;
8436 409 : break;
8437 :
8438 260 : case OMP_CLAUSE_INDEPENDENT:
8439 260 : tag |= OLF_INDEPENDENT;
8440 260 : break;
8441 :
8442 136 : case OMP_CLAUSE_TILE:
8443 136 : tag |= OLF_TILE;
8444 136 : break;
8445 :
8446 3986 : case OMP_CLAUSE_REDUCTION:
8447 3986 : tag |= OLF_REDUCTION;
8448 3986 : break;
8449 :
8450 11375 : default:
8451 11375 : continue;
8452 : }
8453 : }
8454 :
8455 9665 : if (gang_static)
8456 : {
8457 146 : if (DECL_P (gang_static))
8458 16 : gang_static = build_outer_var_ref (gang_static, ctx);
8459 146 : tag |= OLF_GANG_STATIC;
8460 : }
8461 :
8462 9665 : omp_context *tgt = enclosing_target_ctx (ctx);
8463 9665 : if (!tgt || is_oacc_parallel_or_serial (tgt))
8464 : ;
8465 62 : else if (is_oacc_kernels (tgt))
8466 : /* Not using this loops handling inside OpenACC 'kernels' regions. */
8467 0 : gcc_unreachable ();
8468 62 : else if (is_oacc_kernels_decomposed_part (tgt))
8469 : ;
8470 : else
8471 0 : gcc_unreachable ();
8472 :
8473 : /* In a parallel region, loops are implicitly INDEPENDENT. */
8474 9665 : if (!tgt || is_oacc_parallel_or_serial (tgt))
8475 9603 : tag |= OLF_INDEPENDENT;
8476 :
8477 : /* Loops inside OpenACC 'kernels' decomposed parts' regions are expected to
8478 : have an explicit 'seq' or 'independent' clause, and no 'auto' clause. */
8479 9665 : if (tgt && is_oacc_kernels_decomposed_part (tgt))
8480 : {
8481 62 : gcc_assert (tag & (OLF_SEQ | OLF_INDEPENDENT));
8482 62 : gcc_assert (!(tag & OLF_AUTO));
8483 : }
8484 :
8485 9665 : if (tag & OLF_TILE)
8486 : /* Tiling could use all 3 levels. */
8487 : levels = 3;
8488 : else
8489 : {
8490 : /* A loop lacking SEQ, GANG, WORKER and/or VECTOR could be AUTO.
8491 : Ensure at least one level, or 2 for possible auto
8492 : partitioning */
8493 9529 : bool maybe_auto = !(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
8494 : << OLF_DIM_BASE) | OLF_SEQ));
8495 :
8496 9529 : if (levels < 1u + maybe_auto)
8497 : levels = 1u + maybe_auto;
8498 : }
8499 :
8500 9665 : args.quick_push (build_int_cst (integer_type_node, levels));
8501 9665 : args.quick_push (build_int_cst (integer_type_node, tag));
8502 9665 : if (gang_static)
8503 146 : args.quick_push (gang_static);
8504 :
8505 9665 : gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
8506 9665 : gimple_set_location (call, loc);
8507 9665 : gimple_set_lhs (call, ddvar);
8508 9665 : gimple_seq_add_stmt (seq, call);
8509 :
8510 9665 : return levels;
8511 9665 : }
8512 :
8513 : /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
8514 : partitioning level of the enclosed region. */
8515 :
8516 : static void
8517 42767 : lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
8518 : tree tofollow, gimple_seq *seq)
8519 : {
8520 42767 : int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
8521 : : IFN_UNIQUE_OACC_TAIL_MARK);
8522 42767 : tree marker = build_int_cst (integer_type_node, marker_kind);
8523 42767 : int nargs = 2 + (tofollow != NULL_TREE);
8524 42767 : gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
8525 : marker, ddvar, tofollow);
8526 42767 : gimple_set_location (call, loc);
8527 42767 : gimple_set_lhs (call, ddvar);
8528 42767 : gimple_seq_add_stmt (seq, call);
8529 42767 : }
8530 :
8531 : /* Generate the before and after OpenACC loop sequences. CLAUSES are
8532 : the loop clauses, from which we extract reductions. Initialize
8533 : HEAD and TAIL. */
8534 :
8535 : static void
8536 9665 : lower_oacc_head_tail (location_t loc, tree clauses, gcall *private_marker,
8537 : gimple_seq *head, gimple_seq *tail, omp_context *ctx)
8538 : {
8539 9665 : bool inner = false;
8540 9665 : tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
8541 9665 : gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
8542 :
8543 9665 : unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
8544 :
8545 9665 : if (private_marker)
8546 : {
8547 229 : gimple_set_location (private_marker, loc);
8548 229 : gimple_call_set_lhs (private_marker, ddvar);
8549 229 : gimple_call_set_arg (private_marker, 1, ddvar);
8550 : }
8551 :
8552 9665 : tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
8553 9665 : tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
8554 :
8555 9665 : gcc_assert (count);
8556 26216 : for (unsigned done = 1; count; count--, done++)
8557 : {
8558 16551 : gimple_seq fork_seq = NULL;
8559 16551 : gimple_seq join_seq = NULL;
8560 :
8561 16551 : tree place = build_int_cst (integer_type_node, -1);
8562 16551 : gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
8563 : fork_kind, ddvar, place);
8564 16551 : gimple_set_location (fork, loc);
8565 16551 : gimple_set_lhs (fork, ddvar);
8566 :
8567 16551 : gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
8568 : join_kind, ddvar, place);
8569 16551 : gimple_set_location (join, loc);
8570 16551 : gimple_set_lhs (join, ddvar);
8571 :
8572 : /* Mark the beginning of this level sequence. */
8573 16551 : if (inner)
8574 6886 : lower_oacc_loop_marker (loc, ddvar, true,
8575 6886 : build_int_cst (integer_type_node, count),
8576 : &fork_seq);
8577 16551 : lower_oacc_loop_marker (loc, ddvar, false,
8578 16551 : build_int_cst (integer_type_node, done),
8579 : &join_seq);
8580 :
8581 23437 : lower_oacc_reductions (loc, clauses, place, inner,
8582 : fork, (count == 1) ? private_marker : NULL,
8583 : join, &fork_seq, &join_seq, ctx);
8584 :
8585 : /* Append this level to head. */
8586 16551 : gimple_seq_add_seq (head, fork_seq);
8587 : /* Prepend it to tail. */
8588 16551 : gimple_seq_add_seq (&join_seq, *tail);
8589 16551 : *tail = join_seq;
8590 :
8591 16551 : inner = true;
8592 : }
8593 :
8594 : /* Mark the end of the sequence. */
8595 9665 : lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
8596 9665 : lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
8597 9665 : }
8598 :
8599 : /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
8600 : catch handler and return it. This prevents programs from violating the
8601 : structured block semantics with throws. */
8602 :
8603 : static gimple_seq
8604 95335 : maybe_catch_exception (gimple_seq body)
8605 : {
8606 95335 : gimple *g;
8607 95335 : tree decl;
8608 :
8609 95335 : if (!flag_exceptions)
8610 : return body;
8611 :
8612 42704 : if (lang_hooks.eh_protect_cleanup_actions != NULL)
8613 42676 : decl = lang_hooks.eh_protect_cleanup_actions ();
8614 : else
8615 28 : decl = builtin_decl_explicit (BUILT_IN_TRAP);
8616 :
8617 42704 : g = gimple_build_eh_must_not_throw (decl);
8618 42704 : g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
8619 : GIMPLE_TRY_CATCH);
8620 :
8621 42704 : return gimple_seq_alloc_with_stmt (g);
8622 : }
8623 :
8624 :
8625 : /* Routines to lower OMP directives into OMP-GIMPLE. */
8626 :
8627 : /* If ctx is a worksharing context inside of a cancellable parallel
8628 : region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
8629 : and conditional branch to parallel's cancel_label to handle
8630 : cancellation in the implicit barrier. */
8631 :
8632 : static void
8633 48640 : maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple *omp_return,
8634 : gimple_seq *body)
8635 : {
8636 48640 : gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
8637 48640 : if (gimple_omp_return_nowait_p (omp_return))
8638 : return;
8639 19644 : for (omp_context *outer = ctx->outer; outer; outer = outer->outer)
8640 16027 : if (gimple_code (outer->stmt) == GIMPLE_OMP_PARALLEL
8641 16027 : && outer->cancellable)
8642 : {
8643 64 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
8644 64 : tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
8645 64 : tree lhs = create_tmp_var (c_bool_type);
8646 64 : gimple_omp_return_set_lhs (omp_return, lhs);
8647 64 : tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
8648 64 : gimple *g = gimple_build_cond (NE_EXPR, lhs,
8649 : fold_convert (c_bool_type,
8650 : boolean_false_node),
8651 : outer->cancel_label, fallthru_label);
8652 64 : gimple_seq_add_stmt (body, g);
8653 64 : gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
8654 : }
8655 15963 : else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
8656 15963 : && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
8657 : return;
8658 : }
8659 :
8660 : /* Find the first task_reduction or reduction clause or return NULL
8661 : if there are none. */
8662 :
8663 : static inline tree
8664 48895 : omp_task_reductions_find_first (tree clauses, enum tree_code code,
8665 : enum omp_clause_code ccode)
8666 : {
8667 64277 : while (1)
8668 : {
8669 56586 : clauses = omp_find_clause (clauses, ccode);
8670 56586 : if (clauses == NULL_TREE)
8671 : return NULL_TREE;
8672 9153 : if (ccode != OMP_CLAUSE_REDUCTION
8673 9153 : || code == OMP_TASKLOOP
8674 9153 : || OMP_CLAUSE_REDUCTION_TASK (clauses))
8675 : return clauses;
8676 7691 : clauses = OMP_CLAUSE_CHAIN (clauses);
8677 : }
8678 : }
8679 :
8680 : static void lower_omp_task_reductions (omp_context *, enum tree_code, tree,
8681 : gimple_seq *, gimple_seq *);
8682 :
8683 : /* Lower the OpenMP sections directive in the current statement in GSI_P.
8684 : CTX is the enclosing OMP context for the current statement. */
8685 :
8686 : static void
8687 386 : lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8688 : {
8689 386 : tree block, control;
8690 386 : gimple_stmt_iterator tgsi;
8691 386 : gomp_sections *stmt;
8692 386 : gimple *t;
8693 386 : gbind *new_stmt, *bind;
8694 386 : gimple_seq ilist, dlist, olist, tred_dlist = NULL, clist = NULL, new_body;
8695 :
8696 386 : stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
8697 :
8698 386 : push_gimplify_context ();
8699 :
8700 386 : dlist = NULL;
8701 386 : ilist = NULL;
8702 :
8703 386 : tree rclauses
8704 386 : = omp_task_reductions_find_first (gimple_omp_sections_clauses (stmt),
8705 : OMP_SECTIONS, OMP_CLAUSE_REDUCTION);
8706 386 : tree rtmp = NULL_TREE;
8707 386 : if (rclauses)
8708 : {
8709 8 : tree type = build_pointer_type (pointer_sized_int_node);
8710 8 : tree temp = create_tmp_var (type);
8711 8 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
8712 8 : OMP_CLAUSE_DECL (c) = temp;
8713 8 : OMP_CLAUSE_CHAIN (c) = gimple_omp_sections_clauses (stmt);
8714 8 : gimple_omp_sections_set_clauses (stmt, c);
8715 8 : lower_omp_task_reductions (ctx, OMP_SECTIONS,
8716 : gimple_omp_sections_clauses (stmt),
8717 : &ilist, &tred_dlist);
8718 8 : rclauses = c;
8719 8 : rtmp = make_ssa_name (type);
8720 8 : gimple_seq_add_stmt (&ilist, gimple_build_assign (rtmp, temp));
8721 : }
8722 :
8723 386 : tree *clauses_ptr = gimple_omp_sections_clauses_ptr (stmt);
8724 386 : lower_lastprivate_conditional_clauses (clauses_ptr, ctx);
8725 :
8726 386 : lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
8727 : &ilist, &dlist, ctx, NULL);
8728 :
8729 386 : control = create_tmp_var (unsigned_type_node, ".section");
8730 386 : gimple_omp_sections_set_control (stmt, control);
8731 :
8732 386 : new_body = gimple_omp_body (stmt);
8733 386 : gimple_omp_set_body (stmt, NULL);
8734 386 : tgsi = gsi_start (new_body);
8735 1249 : for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
8736 : {
8737 863 : omp_context *sctx;
8738 863 : gimple *sec_start;
8739 :
8740 863 : sec_start = gsi_stmt (tgsi);
8741 863 : sctx = maybe_lookup_ctx (sec_start);
8742 863 : gcc_assert (sctx);
8743 :
8744 863 : lower_omp (gimple_omp_body_ptr (sec_start), sctx);
8745 863 : gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
8746 : GSI_CONTINUE_LINKING);
8747 863 : gimple_omp_set_body (sec_start, NULL);
8748 :
8749 863 : if (gsi_one_before_end_p (tgsi))
8750 : {
8751 386 : gimple_seq l = NULL;
8752 386 : lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
8753 : &ilist, &l, &clist, ctx);
8754 386 : gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
8755 386 : gimple_omp_section_set_last (sec_start);
8756 : }
8757 :
8758 863 : gsi_insert_after (&tgsi, gimple_build_omp_return (false),
8759 : GSI_CONTINUE_LINKING);
8760 : }
8761 :
8762 386 : block = make_node (BLOCK);
8763 386 : bind = gimple_build_bind (NULL, new_body, block);
8764 :
8765 386 : olist = NULL;
8766 386 : lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist,
8767 : &clist, ctx);
8768 386 : if (clist)
8769 : {
8770 10 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
8771 10 : gcall *g = gimple_build_call (fndecl, 0);
8772 10 : gimple_seq_add_stmt (&olist, g);
8773 10 : gimple_seq_add_seq (&olist, clist);
8774 10 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
8775 10 : g = gimple_build_call (fndecl, 0);
8776 10 : gimple_seq_add_stmt (&olist, g);
8777 : }
8778 :
8779 386 : block = make_node (BLOCK);
8780 386 : new_stmt = gimple_build_bind (NULL, NULL, block);
8781 386 : gsi_replace (gsi_p, new_stmt, true);
8782 :
8783 386 : pop_gimplify_context (new_stmt);
8784 386 : gimple_bind_append_vars (new_stmt, ctx->block_vars);
8785 386 : BLOCK_VARS (block) = gimple_bind_vars (bind);
8786 386 : if (BLOCK_VARS (block))
8787 0 : TREE_USED (block) = 1;
8788 :
8789 386 : new_body = NULL;
8790 386 : gimple_seq_add_seq (&new_body, ilist);
8791 386 : gimple_seq_add_stmt (&new_body, stmt);
8792 386 : gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
8793 386 : gimple_seq_add_stmt (&new_body, bind);
8794 :
8795 386 : t = gimple_build_omp_continue (control, control);
8796 386 : gimple_seq_add_stmt (&new_body, t);
8797 :
8798 386 : gimple_seq_add_seq (&new_body, olist);
8799 386 : if (ctx->cancellable)
8800 19 : gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
8801 386 : gimple_seq_add_seq (&new_body, dlist);
8802 :
8803 386 : new_body = maybe_catch_exception (new_body);
8804 :
8805 386 : bool nowait = omp_find_clause (gimple_omp_sections_clauses (stmt),
8806 386 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
8807 386 : t = gimple_build_omp_return (nowait);
8808 386 : gimple_seq_add_stmt (&new_body, t);
8809 386 : gimple_seq_add_seq (&new_body, tred_dlist);
8810 386 : maybe_add_implicit_barrier_cancel (ctx, t, &new_body);
8811 :
8812 386 : if (rclauses)
8813 8 : OMP_CLAUSE_DECL (rclauses) = rtmp;
8814 :
8815 386 : gimple_bind_set_body (new_stmt, new_body);
8816 386 : }
8817 :
8818 :
8819 : /* A subroutine of lower_omp_single. Expand the simple form of
8820 : a GIMPLE_OMP_SINGLE, without a copyprivate clause:
8821 :
8822 : if (GOMP_single_start ())
8823 : BODY;
8824 : [ GOMP_barrier (); ] -> unless 'nowait' is present.
8825 :
8826 : FIXME. It may be better to delay expanding the logic of this until
8827 : pass_expand_omp. The expanded logic may make the job more difficult
8828 : to a synchronization analysis pass. */
8829 :
8830 : static void
8831 1012 : lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
8832 : {
8833 1012 : location_t loc = gimple_location (single_stmt);
8834 1012 : tree tlabel = create_artificial_label (loc);
8835 1012 : tree flabel = create_artificial_label (loc);
8836 1012 : gimple *call, *cond;
8837 1012 : tree lhs, decl;
8838 :
8839 2020 : decl = builtin_decl_explicit (flag_openmp_ompt
8840 : ? BUILT_IN_GOMP_SINGLE_START_WITH_END
8841 : : BUILT_IN_GOMP_SINGLE_START);
8842 1012 : lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
8843 1012 : call = gimple_build_call (decl, 0);
8844 1012 : gimple_call_set_lhs (call, lhs);
8845 1012 : gimple_seq_add_stmt (pre_p, call);
8846 :
8847 1012 : cond = gimple_build_cond (EQ_EXPR, lhs,
8848 1012 : fold_convert_loc (loc, TREE_TYPE (lhs),
8849 : boolean_true_node),
8850 : tlabel, flabel);
8851 1012 : gimple_seq_add_stmt (pre_p, cond);
8852 1012 : gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
8853 1012 : gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8854 1012 : gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
8855 1012 : }
8856 :
8857 :
8858 : /* A subroutine of lower_omp_single. Expand the simple form of
8859 : a GIMPLE_OMP_SINGLE, with a copyprivate clause:
8860 :
8861 : #pragma omp single copyprivate (a, b, c)
8862 :
8863 : Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
8864 :
8865 : {
8866 : if ((copyout_p = GOMP_single_copy_start ()) == NULL)
8867 : {
8868 : BODY;
8869 : copyout.a = a;
8870 : copyout.b = b;
8871 : copyout.c = c;
8872 : GOMP_single_copy_end (©out);
8873 : }
8874 : else
8875 : {
8876 : a = copyout_p->a;
8877 : b = copyout_p->b;
8878 : c = copyout_p->c;
8879 : }
8880 : GOMP_barrier ();
8881 : }
8882 :
8883 : FIXME. It may be better to delay expanding the logic of this until
8884 : pass_expand_omp. The expanded logic may make the job more difficult
8885 : to a synchronization analysis pass. */
8886 :
8887 : static void
8888 115 : lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
8889 : omp_context *ctx)
8890 : {
8891 115 : tree ptr_type, t, l0, l1, l2, bfn_decl;
8892 115 : gimple_seq copyin_seq;
8893 115 : location_t loc = gimple_location (single_stmt);
8894 :
8895 115 : ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
8896 :
8897 115 : ptr_type = build_pointer_type (ctx->record_type);
8898 115 : ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
8899 :
8900 115 : l0 = create_artificial_label (loc);
8901 115 : l1 = create_artificial_label (loc);
8902 115 : l2 = create_artificial_label (loc);
8903 :
8904 115 : bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
8905 115 : t = build_call_expr_loc (loc, bfn_decl, 0);
8906 115 : t = fold_convert_loc (loc, ptr_type, t);
8907 115 : gimplify_assign (ctx->receiver_decl, t, pre_p);
8908 :
8909 115 : t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
8910 : build_int_cst (ptr_type, 0));
8911 115 : t = build3 (COND_EXPR, void_type_node, t,
8912 : build_and_jump (&l0), build_and_jump (&l1));
8913 115 : gimplify_and_add (t, pre_p);
8914 :
8915 115 : gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
8916 :
8917 115 : gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
8918 :
8919 115 : copyin_seq = NULL;
8920 115 : lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
8921 : ©in_seq, ctx);
8922 :
8923 115 : t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
8924 115 : bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
8925 115 : t = build_call_expr_loc (loc, bfn_decl, 1, t);
8926 115 : gimplify_and_add (t, pre_p);
8927 :
8928 115 : t = build_and_jump (&l2);
8929 115 : gimplify_and_add (t, pre_p);
8930 :
8931 115 : gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
8932 :
8933 115 : gimple_seq_add_seq (pre_p, copyin_seq);
8934 :
8935 115 : gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
8936 115 : }
8937 :
8938 :
8939 : /* Expand code for an OpenMP single directive. */
8940 :
8941 : static void
8942 1127 : lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
8943 : {
8944 1127 : tree block;
8945 1127 : gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
8946 1127 : gbind *bind;
8947 1127 : gimple_seq bind_body, bind_body_tail = NULL, dlist;
8948 :
8949 1127 : push_gimplify_context ();
8950 :
8951 1127 : block = make_node (BLOCK);
8952 1127 : bind = gimple_build_bind (NULL, NULL, block);
8953 1127 : gsi_replace (gsi_p, bind, true);
8954 1127 : bind_body = NULL;
8955 1127 : dlist = NULL;
8956 1127 : lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
8957 : &bind_body, &dlist, ctx, NULL);
8958 1127 : lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
8959 :
8960 1127 : gimple_seq_add_stmt (&bind_body, single_stmt);
8961 :
8962 1127 : if (ctx->record_type)
8963 115 : lower_omp_single_copy (single_stmt, &bind_body, ctx);
8964 : else
8965 1012 : lower_omp_single_simple (single_stmt, &bind_body);
8966 :
8967 1127 : gimple_omp_set_body (single_stmt, NULL);
8968 :
8969 1127 : gimple_seq_add_seq (&bind_body, dlist);
8970 :
8971 1127 : bind_body = maybe_catch_exception (bind_body);
8972 :
8973 1127 : bool nowait = omp_find_clause (gimple_omp_single_clauses (single_stmt),
8974 1127 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
8975 1127 : gimple *g = gimple_build_omp_return (nowait);
8976 1127 : gimple_seq_add_stmt (&bind_body_tail, g);
8977 1127 : maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
8978 :
8979 1127 : if (flag_openmp_ompt && !ctx->record_type)
8980 : {
8981 : /* Insert call to GOMP_single_end. */
8982 4 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_END);
8983 4 : gimple *stmt = gimple_build_call (decl, 0);
8984 4 : gimple_seq_add_stmt (&bind_body_tail, stmt);
8985 : }
8986 :
8987 1127 : if (ctx->record_type)
8988 : {
8989 115 : gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
8990 115 : tree clobber = build_clobber (ctx->record_type);
8991 115 : gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
8992 : clobber), GSI_SAME_STMT);
8993 : }
8994 1127 : gimple_seq_add_seq (&bind_body, bind_body_tail);
8995 1127 : gimple_bind_set_body (bind, bind_body);
8996 :
8997 1127 : pop_gimplify_context (bind);
8998 :
8999 1127 : gimple_bind_append_vars (bind, ctx->block_vars);
9000 1127 : BLOCK_VARS (block) = ctx->block_vars;
9001 1127 : if (BLOCK_VARS (block))
9002 26 : TREE_USED (block) = 1;
9003 1127 : }
9004 :
9005 :
9006 : /* Lower code for an OMP scope directive. */
9007 :
9008 : static void
9009 161 : lower_omp_scope (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9010 : {
9011 161 : tree block;
9012 161 : gimple *scope_stmt = gsi_stmt (*gsi_p);
9013 161 : gbind *bind;
9014 161 : gimple_seq bind_body, bind_body_tail = NULL, dlist;
9015 161 : gimple_seq tred_dlist = NULL;
9016 :
9017 161 : push_gimplify_context ();
9018 :
9019 161 : block = make_node (BLOCK);
9020 161 : bind = gimple_build_bind (NULL, NULL, block);
9021 161 : gsi_replace (gsi_p, bind, true);
9022 161 : bind_body = NULL;
9023 161 : dlist = NULL;
9024 :
9025 161 : tree rclauses
9026 161 : = omp_task_reductions_find_first (gimple_omp_scope_clauses (scope_stmt),
9027 : OMP_SCOPE, OMP_CLAUSE_REDUCTION);
9028 161 : if (rclauses)
9029 : {
9030 54 : tree type = build_pointer_type (pointer_sized_int_node);
9031 54 : tree temp = create_tmp_var (type);
9032 54 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
9033 54 : OMP_CLAUSE_DECL (c) = temp;
9034 54 : OMP_CLAUSE_CHAIN (c) = gimple_omp_scope_clauses (scope_stmt);
9035 54 : gimple_omp_scope_set_clauses (scope_stmt, c);
9036 54 : lower_omp_task_reductions (ctx, OMP_SCOPE,
9037 : gimple_omp_scope_clauses (scope_stmt),
9038 : &bind_body, &tred_dlist);
9039 54 : rclauses = c;
9040 54 : tree fndecl = builtin_decl_explicit (
9041 54 : flag_openmp_ompt ? BUILT_IN_GOMP_SCOPE_START_WITH_END
9042 : : BUILT_IN_GOMP_SCOPE_START);
9043 54 : gimple *stmt = gimple_build_call (fndecl, 1, temp);
9044 54 : gimple_seq_add_stmt (&bind_body, stmt);
9045 : }
9046 107 : else if (flag_openmp_ompt)
9047 : {
9048 4 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_SCOPE_START_WITH_END);
9049 4 : gimple *stmt = gimple_build_call (fndecl, 1, null_pointer_node);
9050 4 : gimple_seq_add_stmt (&bind_body, stmt);
9051 : }
9052 :
9053 161 : lower_rec_input_clauses (gimple_omp_scope_clauses (scope_stmt),
9054 : &bind_body, &dlist, ctx, NULL);
9055 161 : lower_omp (gimple_omp_body_ptr (scope_stmt), ctx);
9056 :
9057 161 : gimple_seq_add_stmt (&bind_body, scope_stmt);
9058 :
9059 161 : gimple_seq_add_seq (&bind_body, gimple_omp_body (scope_stmt));
9060 :
9061 161 : gimple_omp_set_body (scope_stmt, NULL);
9062 :
9063 161 : gimple_seq clist = NULL;
9064 161 : lower_reduction_clauses (gimple_omp_scope_clauses (scope_stmt),
9065 : &bind_body, &clist, ctx);
9066 161 : if (clist)
9067 : {
9068 0 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
9069 0 : gcall *g = gimple_build_call (fndecl, 0);
9070 0 : gimple_seq_add_stmt (&bind_body, g);
9071 0 : gimple_seq_add_seq (&bind_body, clist);
9072 0 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
9073 0 : g = gimple_build_call (fndecl, 0);
9074 0 : gimple_seq_add_stmt (&bind_body, g);
9075 : }
9076 :
9077 161 : gimple_seq_add_seq (&bind_body, dlist);
9078 :
9079 161 : bind_body = maybe_catch_exception (bind_body);
9080 :
9081 161 : if (flag_openmp_ompt)
9082 : {
9083 8 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_SCOPE_END);
9084 8 : gcall *g = gimple_build_call (fndecl, 0);
9085 8 : gimple_seq_add_stmt (&bind_body_tail, g);
9086 : }
9087 :
9088 161 : bool nowait = omp_find_clause (gimple_omp_scope_clauses (scope_stmt),
9089 161 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
9090 161 : gimple *g = gimple_build_omp_return (nowait);
9091 161 : gimple_seq_add_stmt (&bind_body_tail, g);
9092 161 : gimple_seq_add_seq (&bind_body_tail, tred_dlist);
9093 161 : maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
9094 161 : if (ctx->record_type)
9095 : {
9096 0 : gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
9097 0 : tree clobber = build_clobber (ctx->record_type);
9098 0 : gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
9099 : clobber), GSI_SAME_STMT);
9100 : }
9101 161 : gimple_seq_add_seq (&bind_body, bind_body_tail);
9102 :
9103 161 : gimple_bind_set_body (bind, bind_body);
9104 :
9105 161 : pop_gimplify_context (bind);
9106 :
9107 161 : gimple_bind_append_vars (bind, ctx->block_vars);
9108 161 : BLOCK_VARS (block) = ctx->block_vars;
9109 161 : if (BLOCK_VARS (block))
9110 121 : TREE_USED (block) = 1;
9111 161 : }
9112 :
9113 : /* Lower code for an OMP dispatch directive. */
9114 :
9115 : static void
9116 659 : lower_omp_dispatch (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9117 : {
9118 659 : tree block;
9119 659 : gimple *stmt = gsi_stmt (*gsi_p);
9120 659 : gbind *bind;
9121 :
9122 659 : push_gimplify_context ();
9123 :
9124 659 : block = make_node (BLOCK);
9125 659 : bind = gimple_build_bind (NULL, NULL, block);
9126 659 : gsi_replace (gsi_p, bind, true);
9127 :
9128 659 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
9129 659 : gimple_bind_set_body (bind, maybe_catch_exception (gimple_omp_body (stmt)));
9130 :
9131 659 : pop_gimplify_context (bind);
9132 :
9133 659 : gimple_bind_append_vars (bind, ctx->block_vars);
9134 659 : BLOCK_VARS (block) = ctx->block_vars;
9135 659 : }
9136 :
9137 : /* Expand code for an OpenMP master or masked directive. */
9138 :
9139 : static void
9140 1118 : lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9141 : {
9142 1118 : tree block, lab = NULL, x, bfn_decl;
9143 1118 : gimple *stmt = gsi_stmt (*gsi_p);
9144 1118 : gbind *bind;
9145 1118 : location_t loc = gimple_location (stmt);
9146 1118 : gimple_seq tseq;
9147 1118 : tree filter = integer_zero_node;
9148 :
9149 1118 : push_gimplify_context ();
9150 :
9151 1118 : if (gimple_code (stmt) == GIMPLE_OMP_MASKED)
9152 : {
9153 387 : filter = omp_find_clause (gimple_omp_masked_clauses (stmt),
9154 : OMP_CLAUSE_FILTER);
9155 387 : if (filter)
9156 252 : filter = fold_convert (integer_type_node,
9157 : OMP_CLAUSE_FILTER_EXPR (filter));
9158 : else
9159 135 : filter = integer_zero_node;
9160 : }
9161 1118 : block = make_node (BLOCK);
9162 1118 : bind = gimple_build_bind (NULL, NULL, block);
9163 1118 : gsi_replace (gsi_p, bind, true);
9164 1118 : gimple_bind_add_stmt (bind, stmt);
9165 :
9166 1118 : bfn_decl = builtin_decl_explicit (
9167 1118 : flag_openmp_ompt ? BUILT_IN_GOMP_HAS_MASKED_THREAD_NUM_WITH_END
9168 : : BUILT_IN_GOMP_HAS_MASKED_THREAD_NUM);
9169 1118 : x = build_call_expr_loc (loc, bfn_decl, 1, filter);
9170 1118 : x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
9171 1118 : tseq = NULL;
9172 1118 : gimplify_and_add (x, &tseq);
9173 1118 : gimple_bind_add_seq (bind, tseq);
9174 :
9175 1118 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
9176 1118 : gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
9177 1118 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9178 1118 : gimple_omp_set_body (stmt, NULL);
9179 :
9180 1118 : if (flag_openmp_ompt)
9181 : {
9182 : /* Insert call to GOMP_masked_end at the end of the body. */
9183 4 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_MASKED_END);
9184 4 : gcall *g = gimple_build_call (decl, 0);
9185 4 : gimple_bind_add_stmt (bind, g);
9186 : }
9187 :
9188 1118 : gimple_bind_add_stmt (bind, gimple_build_label (lab));
9189 :
9190 1118 : gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
9191 :
9192 1118 : pop_gimplify_context (bind);
9193 :
9194 1118 : gimple_bind_append_vars (bind, ctx->block_vars);
9195 1118 : BLOCK_VARS (block) = ctx->block_vars;
9196 1118 : }
9197 :
9198 : /* Helper function for lower_omp_task_reductions. For a specific PASS
9199 : find out the current clause it should be processed, or return false
9200 : if all have been processed already. */
9201 :
9202 : static inline bool
9203 8000 : omp_task_reduction_iterate (int pass, enum tree_code code,
9204 : enum omp_clause_code ccode, tree *c, tree *decl,
9205 : tree *type, tree *next)
9206 : {
9207 11364 : for (; *c; *c = omp_find_clause (OMP_CLAUSE_CHAIN (*c), ccode))
9208 : {
9209 6728 : if (ccode == OMP_CLAUSE_REDUCTION
9210 6672 : && code != OMP_TASKLOOP
9211 6672 : && !OMP_CLAUSE_REDUCTION_TASK (*c))
9212 56 : continue;
9213 6616 : *decl = OMP_CLAUSE_DECL (*c);
9214 6616 : *type = TREE_TYPE (*decl);
9215 6616 : if (TREE_CODE (*decl) == MEM_REF)
9216 : {
9217 1940 : if (pass != 1)
9218 970 : continue;
9219 : }
9220 : else
9221 : {
9222 4676 : if (omp_privatize_by_reference (*decl))
9223 152 : *type = TREE_TYPE (*type);
9224 4676 : if (pass != (!TREE_CONSTANT (TYPE_SIZE_UNIT (*type))))
9225 2338 : continue;
9226 : }
9227 3308 : *next = omp_find_clause (OMP_CLAUSE_CHAIN (*c), ccode);
9228 3308 : return true;
9229 : }
9230 4692 : *decl = NULL_TREE;
9231 4692 : *type = NULL_TREE;
9232 4692 : *next = NULL_TREE;
9233 4692 : return false;
9234 : }
9235 :
9236 : /* Lower task_reduction and reduction clauses (the latter unless CODE is
9237 : OMP_TASKGROUP only with task modifier). Register mapping of those in
9238 : START sequence and reducing them and unregister them in the END sequence. */
9239 :
9240 : static void
9241 1382 : lower_omp_task_reductions (omp_context *ctx, enum tree_code code, tree clauses,
9242 : gimple_seq *start, gimple_seq *end)
9243 : {
9244 846 : enum omp_clause_code ccode
9245 : = (code == OMP_TASKGROUP
9246 1382 : ? OMP_CLAUSE_TASK_REDUCTION : OMP_CLAUSE_REDUCTION);
9247 1382 : tree cancellable = NULL_TREE;
9248 1382 : clauses = omp_task_reductions_find_first (clauses, code, ccode);
9249 1382 : if (clauses == NULL_TREE)
9250 209 : return;
9251 1173 : if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9252 : {
9253 324 : for (omp_context *outer = ctx->outer; outer; outer = outer->outer)
9254 238 : if (gimple_code (outer->stmt) == GIMPLE_OMP_PARALLEL
9255 238 : && outer->cancellable)
9256 : {
9257 14 : cancellable = error_mark_node;
9258 14 : break;
9259 : }
9260 224 : else if (gimple_code (outer->stmt) != GIMPLE_OMP_TASKGROUP
9261 224 : && gimple_code (outer->stmt) != GIMPLE_OMP_SCOPE)
9262 : break;
9263 : }
9264 1173 : tree record_type = lang_hooks.types.make_type (RECORD_TYPE);
9265 1173 : tree *last = &TYPE_FIELDS (record_type);
9266 1173 : unsigned cnt = 0;
9267 1173 : if (cancellable)
9268 : {
9269 14 : tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
9270 : ptr_type_node);
9271 14 : tree ifield = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE,
9272 : integer_type_node);
9273 14 : *last = field;
9274 14 : DECL_CHAIN (field) = ifield;
9275 14 : last = &DECL_CHAIN (ifield);
9276 14 : DECL_CONTEXT (field) = record_type;
9277 14 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (field))
9278 0 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (field));
9279 14 : DECL_CONTEXT (ifield) = record_type;
9280 14 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (ifield))
9281 0 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (ifield));
9282 : }
9283 3519 : for (int pass = 0; pass < 2; pass++)
9284 : {
9285 2346 : tree decl, type, next;
9286 2346 : for (tree c = clauses;
9287 4000 : omp_task_reduction_iterate (pass, code, ccode,
9288 1654 : &c, &decl, &type, &next); c = next)
9289 : {
9290 1654 : ++cnt;
9291 1654 : tree new_type = type;
9292 1654 : if (ctx->outer)
9293 1165 : new_type = remap_type (type, &ctx->outer->cb);
9294 1654 : tree field
9295 1654 : = build_decl (OMP_CLAUSE_LOCATION (c), FIELD_DECL,
9296 1654 : DECL_P (decl) ? DECL_NAME (decl) : NULL_TREE,
9297 : new_type);
9298 1654 : if (DECL_P (decl) && type == TREE_TYPE (decl))
9299 : {
9300 1131 : SET_DECL_ALIGN (field, DECL_ALIGN (decl));
9301 1131 : DECL_USER_ALIGN (field) = DECL_USER_ALIGN (decl);
9302 1131 : TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (decl);
9303 : }
9304 : else
9305 523 : SET_DECL_ALIGN (field, TYPE_ALIGN (type));
9306 1654 : DECL_CONTEXT (field) = record_type;
9307 1654 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (field))
9308 1195 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (field));
9309 1654 : *last = field;
9310 1654 : last = &DECL_CHAIN (field);
9311 1654 : tree bfield
9312 1654 : = build_decl (OMP_CLAUSE_LOCATION (c), FIELD_DECL, NULL_TREE,
9313 : boolean_type_node);
9314 1654 : DECL_CONTEXT (bfield) = record_type;
9315 1654 : if (TYPE_ALIGN (record_type) < DECL_ALIGN (bfield))
9316 0 : SET_TYPE_ALIGN (record_type, DECL_ALIGN (bfield));
9317 1654 : *last = bfield;
9318 1654 : last = &DECL_CHAIN (bfield);
9319 : }
9320 : }
9321 1173 : *last = NULL_TREE;
9322 1173 : layout_type (record_type);
9323 :
9324 : /* Build up an array which registers with the runtime all the reductions
9325 : and deregisters them at the end. Format documented in libgomp/task.c. */
9326 1173 : tree atype = build_array_type_nelts (pointer_sized_int_node, 7 + cnt * 3);
9327 1173 : tree avar = create_tmp_var_raw (atype);
9328 1173 : gimple_add_tmp_var (avar);
9329 1173 : TREE_ADDRESSABLE (avar) = 1;
9330 1173 : tree r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_zero_node,
9331 : NULL_TREE, NULL_TREE);
9332 1173 : tree t = build_int_cst (pointer_sized_int_node, cnt);
9333 1173 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9334 1173 : gimple_seq seq = NULL;
9335 1173 : tree sz = fold_convert (pointer_sized_int_node,
9336 : TYPE_SIZE_UNIT (record_type));
9337 1173 : int cachesz = 64;
9338 1173 : sz = fold_build2 (PLUS_EXPR, pointer_sized_int_node, sz,
9339 : build_int_cst (pointer_sized_int_node, cachesz - 1));
9340 1173 : sz = fold_build2 (BIT_AND_EXPR, pointer_sized_int_node, sz,
9341 : build_int_cst (pointer_sized_int_node, ~(cachesz - 1)));
9342 1173 : ctx->task_reductions.create (1 + cnt);
9343 1173 : ctx->task_reduction_map = new hash_map<tree, unsigned>;
9344 2346 : ctx->task_reductions.quick_push (TREE_CODE (sz) == INTEGER_CST
9345 1213 : ? sz : NULL_TREE);
9346 1173 : sz = force_gimple_operand (sz, &seq, true, NULL_TREE);
9347 1173 : gimple_seq_add_seq (start, seq);
9348 1173 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_one_node,
9349 : NULL_TREE, NULL_TREE);
9350 1173 : gimple_seq_add_stmt (start, gimple_build_assign (r, sz));
9351 1173 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (2),
9352 : NULL_TREE, NULL_TREE);
9353 1173 : t = build_int_cst (pointer_sized_int_node,
9354 1173 : MAX (TYPE_ALIGN_UNIT (record_type), (unsigned) cachesz));
9355 1173 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9356 1173 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (3),
9357 : NULL_TREE, NULL_TREE);
9358 1173 : t = build_int_cst (pointer_sized_int_node, -1);
9359 1173 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9360 1173 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (4),
9361 : NULL_TREE, NULL_TREE);
9362 1173 : t = build_int_cst (pointer_sized_int_node, 0);
9363 1173 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9364 :
9365 : /* In end, build a loop that iterates from 0 to < omp_get_num_threads ()
9366 : and for each task reduction checks a bool right after the private variable
9367 : within that thread's chunk; if the bool is clear, it hasn't been
9368 : initialized and thus isn't going to be reduced nor destructed, otherwise
9369 : reduce and destruct it. */
9370 1173 : tree idx = create_tmp_var (size_type_node);
9371 1173 : gimple_seq_add_stmt (end, gimple_build_assign (idx, size_zero_node));
9372 1173 : tree num_thr_sz = create_tmp_var (size_type_node);
9373 1173 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
9374 1173 : tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
9375 1173 : tree lab3 = NULL_TREE, lab7 = NULL_TREE;
9376 1173 : gimple *g;
9377 1173 : if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9378 : {
9379 : /* For worksharing constructs or scope, only perform it in the master
9380 : thread, with the exception of cancelled implicit barriers - then only
9381 : handle the current thread. */
9382 289 : tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
9383 289 : t = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9384 289 : tree thr_num = create_tmp_var (integer_type_node);
9385 289 : g = gimple_build_call (t, 0);
9386 289 : gimple_call_set_lhs (g, thr_num);
9387 289 : gimple_seq_add_stmt (end, g);
9388 289 : if (cancellable)
9389 : {
9390 14 : tree c;
9391 14 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9392 14 : tree lab6 = create_artificial_label (UNKNOWN_LOCATION);
9393 14 : lab3 = create_artificial_label (UNKNOWN_LOCATION);
9394 14 : if (code == OMP_FOR)
9395 4 : c = gimple_omp_for_clauses (ctx->stmt);
9396 10 : else if (code == OMP_SECTIONS)
9397 0 : c = gimple_omp_sections_clauses (ctx->stmt);
9398 : else /* if (code == OMP_SCOPE) */
9399 10 : c = gimple_omp_scope_clauses (ctx->stmt);
9400 14 : c = OMP_CLAUSE_DECL (omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_));
9401 14 : cancellable = c;
9402 14 : g = gimple_build_cond (NE_EXPR, c, build_zero_cst (TREE_TYPE (c)),
9403 : lab5, lab6);
9404 14 : gimple_seq_add_stmt (end, g);
9405 14 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9406 14 : g = gimple_build_assign (idx, NOP_EXPR, thr_num);
9407 14 : gimple_seq_add_stmt (end, g);
9408 14 : g = gimple_build_assign (num_thr_sz, PLUS_EXPR, idx,
9409 14 : build_one_cst (TREE_TYPE (idx)));
9410 14 : gimple_seq_add_stmt (end, g);
9411 14 : gimple_seq_add_stmt (end, gimple_build_goto (lab3));
9412 14 : gimple_seq_add_stmt (end, gimple_build_label (lab6));
9413 : }
9414 289 : g = gimple_build_cond (NE_EXPR, thr_num, integer_zero_node, lab2, lab4);
9415 289 : gimple_seq_add_stmt (end, g);
9416 289 : gimple_seq_add_stmt (end, gimple_build_label (lab4));
9417 : }
9418 1173 : if (code != OMP_PARALLEL)
9419 : {
9420 1113 : t = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9421 1113 : tree num_thr = create_tmp_var (integer_type_node);
9422 1113 : g = gimple_build_call (t, 0);
9423 1113 : gimple_call_set_lhs (g, num_thr);
9424 1113 : gimple_seq_add_stmt (end, g);
9425 1113 : g = gimple_build_assign (num_thr_sz, NOP_EXPR, num_thr);
9426 1113 : gimple_seq_add_stmt (end, g);
9427 1113 : if (cancellable)
9428 14 : gimple_seq_add_stmt (end, gimple_build_label (lab3));
9429 : }
9430 : else
9431 : {
9432 60 : tree c = omp_find_clause (gimple_omp_parallel_clauses (ctx->stmt),
9433 : OMP_CLAUSE__REDUCTEMP_);
9434 60 : t = fold_convert (pointer_sized_int_node, OMP_CLAUSE_DECL (c));
9435 60 : t = fold_convert (size_type_node, t);
9436 60 : gimplify_assign (num_thr_sz, t, end);
9437 : }
9438 1173 : t = build4 (ARRAY_REF, pointer_sized_int_node, avar, size_int (2),
9439 : NULL_TREE, NULL_TREE);
9440 1173 : tree data = create_tmp_var (pointer_sized_int_node);
9441 1173 : gimple_seq_add_stmt (end, gimple_build_assign (data, t));
9442 1173 : if (code == OMP_TASKLOOP)
9443 : {
9444 497 : lab7 = create_artificial_label (UNKNOWN_LOCATION);
9445 497 : g = gimple_build_cond (NE_EXPR, data,
9446 : build_zero_cst (pointer_sized_int_node),
9447 : lab1, lab7);
9448 497 : gimple_seq_add_stmt (end, g);
9449 : }
9450 1173 : gimple_seq_add_stmt (end, gimple_build_label (lab1));
9451 1173 : tree ptr;
9452 1173 : if (TREE_CODE (TYPE_SIZE_UNIT (record_type)) == INTEGER_CST)
9453 1133 : ptr = create_tmp_var (build_pointer_type (record_type));
9454 : else
9455 40 : ptr = create_tmp_var (ptr_type_node);
9456 1173 : gimple_seq_add_stmt (end, gimple_build_assign (ptr, NOP_EXPR, data));
9457 :
9458 1173 : tree field = TYPE_FIELDS (record_type);
9459 1173 : cnt = 0;
9460 1173 : if (cancellable)
9461 14 : field = DECL_CHAIN (DECL_CHAIN (field));
9462 3519 : for (int pass = 0; pass < 2; pass++)
9463 : {
9464 2346 : tree decl, type, next;
9465 2346 : for (tree c = clauses;
9466 4000 : omp_task_reduction_iterate (pass, code, ccode,
9467 1654 : &c, &decl, &type, &next); c = next)
9468 : {
9469 1654 : tree var = decl, ref;
9470 1654 : if (TREE_CODE (decl) == MEM_REF)
9471 : {
9472 485 : var = TREE_OPERAND (var, 0);
9473 485 : if (TREE_CODE (var) == POINTER_PLUS_EXPR)
9474 108 : var = TREE_OPERAND (var, 0);
9475 485 : tree v = var;
9476 485 : if (TREE_CODE (var) == ADDR_EXPR)
9477 310 : var = TREE_OPERAND (var, 0);
9478 175 : else if (INDIRECT_REF_P (var))
9479 4 : var = TREE_OPERAND (var, 0);
9480 485 : tree orig_var = var;
9481 485 : if (is_variable_sized (var))
9482 : {
9483 31 : gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
9484 31 : var = DECL_VALUE_EXPR (var);
9485 31 : gcc_assert (INDIRECT_REF_P (var));
9486 31 : var = TREE_OPERAND (var, 0);
9487 31 : gcc_assert (DECL_P (var));
9488 : }
9489 485 : t = ref = maybe_lookup_decl_in_outer_ctx (var, ctx);
9490 485 : if (orig_var != var)
9491 31 : gcc_assert (TREE_CODE (v) == ADDR_EXPR);
9492 454 : else if (TREE_CODE (v) == ADDR_EXPR)
9493 279 : t = build_fold_addr_expr (t);
9494 175 : else if (INDIRECT_REF_P (v))
9495 4 : t = build_fold_indirect_ref (t);
9496 485 : if (TREE_CODE (TREE_OPERAND (decl, 0)) == POINTER_PLUS_EXPR)
9497 : {
9498 108 : tree b = TREE_OPERAND (TREE_OPERAND (decl, 0), 1);
9499 108 : b = maybe_lookup_decl_in_outer_ctx (b, ctx);
9500 108 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, b);
9501 : }
9502 485 : if (!integer_zerop (TREE_OPERAND (decl, 1)))
9503 219 : t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t,
9504 : fold_convert (size_type_node,
9505 : TREE_OPERAND (decl, 1)));
9506 : }
9507 : else
9508 : {
9509 1169 : t = ref = maybe_lookup_decl_in_outer_ctx (var, ctx);
9510 1169 : if (!omp_privatize_by_reference (decl))
9511 1131 : t = build_fold_addr_expr (t);
9512 : }
9513 1654 : t = fold_convert (pointer_sized_int_node, t);
9514 1654 : seq = NULL;
9515 1654 : t = force_gimple_operand (t, &seq, true, NULL_TREE);
9516 1654 : gimple_seq_add_seq (start, seq);
9517 1654 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9518 1654 : size_int (7 + cnt * 3), NULL_TREE, NULL_TREE);
9519 1654 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9520 1654 : t = unshare_expr (byte_position (field));
9521 1654 : t = fold_convert (pointer_sized_int_node, t);
9522 1654 : ctx->task_reduction_map->put (c, cnt);
9523 3308 : ctx->task_reductions.quick_push (TREE_CODE (t) == INTEGER_CST
9524 2026 : ? t : NULL_TREE);
9525 1654 : seq = NULL;
9526 1654 : t = force_gimple_operand (t, &seq, true, NULL_TREE);
9527 1654 : gimple_seq_add_seq (start, seq);
9528 1654 : r = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9529 1654 : size_int (7 + cnt * 3 + 1), NULL_TREE, NULL_TREE);
9530 1654 : gimple_seq_add_stmt (start, gimple_build_assign (r, t));
9531 :
9532 1654 : tree bfield = DECL_CHAIN (field);
9533 1654 : tree cond;
9534 1654 : if (code == OMP_PARALLEL
9535 1654 : || code == OMP_FOR
9536 : || code == OMP_SECTIONS
9537 : || code == OMP_SCOPE)
9538 : /* In parallel, worksharing or scope all threads unconditionally
9539 : initialize all their task reduction private variables. */
9540 556 : cond = boolean_true_node;
9541 1098 : else if (TREE_TYPE (ptr) == ptr_type_node)
9542 : {
9543 261 : cond = build2 (POINTER_PLUS_EXPR, ptr_type_node, ptr,
9544 : unshare_expr (byte_position (bfield)));
9545 261 : seq = NULL;
9546 261 : cond = force_gimple_operand (cond, &seq, true, NULL_TREE);
9547 261 : gimple_seq_add_seq (end, seq);
9548 261 : tree pbool = build_pointer_type (TREE_TYPE (bfield));
9549 261 : cond = build2 (MEM_REF, TREE_TYPE (bfield), cond,
9550 : build_int_cst (pbool, 0));
9551 : }
9552 : else
9553 837 : cond = build3 (COMPONENT_REF, TREE_TYPE (bfield),
9554 : build_simple_mem_ref (ptr), bfield, NULL_TREE);
9555 1654 : tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
9556 1654 : tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
9557 1654 : tree condv = create_tmp_var (boolean_type_node);
9558 1654 : gimple_seq_add_stmt (end, gimple_build_assign (condv, cond));
9559 1654 : g = gimple_build_cond (NE_EXPR, condv, boolean_false_node,
9560 : lab3, lab4);
9561 1654 : gimple_seq_add_stmt (end, g);
9562 1654 : gimple_seq_add_stmt (end, gimple_build_label (lab3));
9563 1654 : if (cancellable && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE)
9564 : {
9565 : /* If this reduction doesn't need destruction and parallel
9566 : has been cancelled, there is nothing to do for this
9567 : reduction, so jump around the merge operation. */
9568 18 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9569 18 : g = gimple_build_cond (NE_EXPR, cancellable,
9570 18 : build_zero_cst (TREE_TYPE (cancellable)),
9571 : lab4, lab5);
9572 18 : gimple_seq_add_stmt (end, g);
9573 18 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9574 : }
9575 :
9576 1654 : tree new_var;
9577 1654 : if (TREE_TYPE (ptr) == ptr_type_node)
9578 : {
9579 428 : new_var = build2 (POINTER_PLUS_EXPR, ptr_type_node, ptr,
9580 : unshare_expr (byte_position (field)));
9581 428 : seq = NULL;
9582 428 : new_var = force_gimple_operand (new_var, &seq, true, NULL_TREE);
9583 428 : gimple_seq_add_seq (end, seq);
9584 428 : tree pbool = build_pointer_type (TREE_TYPE (field));
9585 428 : new_var = build2 (MEM_REF, TREE_TYPE (field), new_var,
9586 : build_int_cst (pbool, 0));
9587 : }
9588 : else
9589 1226 : new_var = build3 (COMPONENT_REF, TREE_TYPE (field),
9590 : build_simple_mem_ref (ptr), field, NULL_TREE);
9591 :
9592 1654 : enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
9593 1654 : if (TREE_CODE (decl) != MEM_REF
9594 1654 : && omp_privatize_by_reference (decl))
9595 38 : ref = build_simple_mem_ref (ref);
9596 : /* reduction(-:var) sums up the partial results, so it acts
9597 : identically to reduction(+:var). */
9598 1654 : if (rcode == MINUS_EXPR)
9599 0 : rcode = PLUS_EXPR;
9600 1654 : if (TREE_CODE (decl) == MEM_REF)
9601 : {
9602 485 : tree type = TREE_TYPE (new_var);
9603 485 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
9604 485 : tree i = create_tmp_var (TREE_TYPE (v));
9605 485 : tree ptype = build_pointer_type (TREE_TYPE (type));
9606 485 : if (DECL_P (v))
9607 : {
9608 142 : v = maybe_lookup_decl_in_outer_ctx (v, ctx);
9609 142 : tree vv = create_tmp_var (TREE_TYPE (v));
9610 142 : gimplify_assign (vv, v, start);
9611 142 : v = vv;
9612 : }
9613 485 : ref = build4 (ARRAY_REF, pointer_sized_int_node, avar,
9614 485 : size_int (7 + cnt * 3), NULL_TREE, NULL_TREE);
9615 485 : new_var = build_fold_addr_expr (new_var);
9616 485 : new_var = fold_convert (ptype, new_var);
9617 485 : ref = fold_convert (ptype, ref);
9618 485 : tree m = create_tmp_var (ptype);
9619 485 : gimplify_assign (m, new_var, end);
9620 485 : new_var = m;
9621 485 : m = create_tmp_var (ptype);
9622 485 : gimplify_assign (m, ref, end);
9623 485 : ref = m;
9624 485 : gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), end);
9625 485 : tree body = create_artificial_label (UNKNOWN_LOCATION);
9626 485 : tree endl = create_artificial_label (UNKNOWN_LOCATION);
9627 485 : gimple_seq_add_stmt (end, gimple_build_label (body));
9628 485 : tree priv = build_simple_mem_ref (new_var);
9629 485 : tree out = build_simple_mem_ref (ref);
9630 485 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
9631 : {
9632 161 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
9633 161 : tree decl_placeholder
9634 161 : = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
9635 161 : tree lab6 = NULL_TREE;
9636 161 : if (cancellable)
9637 : {
9638 : /* If this reduction needs destruction and parallel
9639 : has been cancelled, jump around the merge operation
9640 : to the destruction. */
9641 4 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9642 4 : lab6 = create_artificial_label (UNKNOWN_LOCATION);
9643 4 : tree zero = build_zero_cst (TREE_TYPE (cancellable));
9644 4 : g = gimple_build_cond (NE_EXPR, cancellable, zero,
9645 : lab6, lab5);
9646 4 : gimple_seq_add_stmt (end, g);
9647 4 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9648 : }
9649 161 : SET_DECL_VALUE_EXPR (placeholder, out);
9650 161 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
9651 161 : SET_DECL_VALUE_EXPR (decl_placeholder, priv);
9652 161 : DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
9653 161 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
9654 322 : gimple_seq_add_seq (end,
9655 161 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
9656 161 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
9657 161 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
9658 : {
9659 56 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
9660 56 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
9661 : }
9662 161 : if (cancellable)
9663 4 : gimple_seq_add_stmt (end, gimple_build_label (lab6));
9664 161 : tree x = lang_hooks.decls.omp_clause_dtor (c, priv);
9665 161 : if (x)
9666 : {
9667 137 : gimple_seq tseq = NULL;
9668 137 : gimplify_stmt (&x, &tseq);
9669 137 : gimple_seq_add_seq (end, tseq);
9670 : }
9671 : }
9672 : else
9673 : {
9674 324 : tree x = build2 (rcode, TREE_TYPE (out), out, priv);
9675 324 : out = unshare_expr (out);
9676 324 : gimplify_assign (out, x, end);
9677 : }
9678 485 : gimple *g
9679 485 : = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
9680 485 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
9681 485 : gimple_seq_add_stmt (end, g);
9682 485 : g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
9683 485 : TYPE_SIZE_UNIT (TREE_TYPE (type)));
9684 485 : gimple_seq_add_stmt (end, g);
9685 485 : g = gimple_build_assign (i, PLUS_EXPR, i,
9686 485 : build_int_cst (TREE_TYPE (i), 1));
9687 485 : gimple_seq_add_stmt (end, g);
9688 485 : g = gimple_build_cond (LE_EXPR, i, v, body, endl);
9689 485 : gimple_seq_add_stmt (end, g);
9690 485 : gimple_seq_add_stmt (end, gimple_build_label (endl));
9691 : }
9692 1169 : else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
9693 : {
9694 127 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
9695 127 : tree oldv = NULL_TREE;
9696 127 : tree lab6 = NULL_TREE;
9697 127 : if (cancellable)
9698 : {
9699 : /* If this reduction needs destruction and parallel
9700 : has been cancelled, jump around the merge operation
9701 : to the destruction. */
9702 4 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
9703 4 : lab6 = create_artificial_label (UNKNOWN_LOCATION);
9704 4 : tree zero = build_zero_cst (TREE_TYPE (cancellable));
9705 4 : g = gimple_build_cond (NE_EXPR, cancellable, zero,
9706 : lab6, lab5);
9707 4 : gimple_seq_add_stmt (end, g);
9708 4 : gimple_seq_add_stmt (end, gimple_build_label (lab5));
9709 : }
9710 127 : if (omp_privatize_by_reference (decl)
9711 137 : && !useless_type_conversion_p (TREE_TYPE (placeholder),
9712 10 : TREE_TYPE (ref)))
9713 0 : ref = build_fold_addr_expr_loc (OMP_CLAUSE_LOCATION (c), ref);
9714 127 : ref = build_fold_addr_expr_loc (OMP_CLAUSE_LOCATION (c), ref);
9715 127 : tree refv = create_tmp_var (TREE_TYPE (ref));
9716 127 : gimplify_assign (refv, ref, end);
9717 127 : ref = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), refv);
9718 127 : SET_DECL_VALUE_EXPR (placeholder, ref);
9719 127 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
9720 127 : tree d = maybe_lookup_decl (decl, ctx);
9721 127 : gcc_assert (d);
9722 127 : if (DECL_HAS_VALUE_EXPR_P (d))
9723 7 : oldv = DECL_VALUE_EXPR (d);
9724 127 : if (omp_privatize_by_reference (var))
9725 : {
9726 10 : tree v = fold_convert (TREE_TYPE (d),
9727 : build_fold_addr_expr (new_var));
9728 10 : SET_DECL_VALUE_EXPR (d, v);
9729 : }
9730 : else
9731 117 : SET_DECL_VALUE_EXPR (d, new_var);
9732 127 : DECL_HAS_VALUE_EXPR_P (d) = 1;
9733 127 : lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
9734 127 : if (oldv)
9735 7 : SET_DECL_VALUE_EXPR (d, oldv);
9736 : else
9737 : {
9738 120 : SET_DECL_VALUE_EXPR (d, NULL_TREE);
9739 120 : DECL_HAS_VALUE_EXPR_P (d) = 0;
9740 : }
9741 127 : gimple_seq_add_seq (end, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
9742 127 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
9743 127 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
9744 24 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
9745 127 : if (cancellable)
9746 4 : gimple_seq_add_stmt (end, gimple_build_label (lab6));
9747 127 : tree x = lang_hooks.decls.omp_clause_dtor (c, new_var);
9748 127 : if (x)
9749 : {
9750 29 : gimple_seq tseq = NULL;
9751 29 : gimplify_stmt (&x, &tseq);
9752 29 : gimple_seq_add_seq (end, tseq);
9753 : }
9754 : }
9755 : else
9756 : {
9757 1042 : tree x = build2 (rcode, TREE_TYPE (ref), ref, new_var);
9758 1042 : ref = unshare_expr (ref);
9759 1042 : gimplify_assign (ref, x, end);
9760 : }
9761 1654 : gimple_seq_add_stmt (end, gimple_build_label (lab4));
9762 1654 : ++cnt;
9763 1654 : field = DECL_CHAIN (bfield);
9764 : }
9765 : }
9766 :
9767 1173 : if (code == OMP_TASKGROUP)
9768 : {
9769 327 : t = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_REDUCTION_REGISTER);
9770 327 : g = gimple_build_call (t, 1, build_fold_addr_expr (avar));
9771 327 : gimple_seq_add_stmt (start, g);
9772 : }
9773 : else
9774 : {
9775 846 : tree c;
9776 846 : if (code == OMP_FOR)
9777 227 : c = gimple_omp_for_clauses (ctx->stmt);
9778 619 : else if (code == OMP_SECTIONS)
9779 8 : c = gimple_omp_sections_clauses (ctx->stmt);
9780 611 : else if (code == OMP_SCOPE)
9781 54 : c = gimple_omp_scope_clauses (ctx->stmt);
9782 : else
9783 557 : c = gimple_omp_taskreg_clauses (ctx->stmt);
9784 846 : c = omp_find_clause (c, OMP_CLAUSE__REDUCTEMP_);
9785 846 : t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (c)),
9786 : build_fold_addr_expr (avar));
9787 846 : gimplify_assign (OMP_CLAUSE_DECL (c), t, start);
9788 : }
9789 :
9790 1173 : gimple_seq_add_stmt (end, gimple_build_assign (data, PLUS_EXPR, data, sz));
9791 1173 : gimple_seq_add_stmt (end, gimple_build_assign (idx, PLUS_EXPR, idx,
9792 : size_one_node));
9793 1173 : g = gimple_build_cond (NE_EXPR, idx, num_thr_sz, lab1, lab2);
9794 1173 : gimple_seq_add_stmt (end, g);
9795 1173 : gimple_seq_add_stmt (end, gimple_build_label (lab2));
9796 1173 : if (code == OMP_FOR || code == OMP_SECTIONS || code == OMP_SCOPE)
9797 : {
9798 289 : enum built_in_function bfn
9799 : = BUILT_IN_GOMP_WORKSHARE_TASK_REDUCTION_UNREGISTER;
9800 289 : t = builtin_decl_explicit (bfn);
9801 289 : tree c_bool_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (t)));
9802 289 : tree arg;
9803 289 : if (cancellable)
9804 : {
9805 14 : arg = create_tmp_var (c_bool_type);
9806 14 : gimple_seq_add_stmt (end, gimple_build_assign (arg, NOP_EXPR,
9807 : cancellable));
9808 : }
9809 : else
9810 275 : arg = build_int_cst (c_bool_type, 0);
9811 289 : g = gimple_build_call (t, 1, arg);
9812 289 : }
9813 : else
9814 : {
9815 884 : t = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_REDUCTION_UNREGISTER);
9816 884 : g = gimple_build_call (t, 1, build_fold_addr_expr (avar));
9817 : }
9818 1173 : gimple_seq_add_stmt (end, g);
9819 1173 : if (lab7)
9820 497 : gimple_seq_add_stmt (end, gimple_build_label (lab7));
9821 1173 : t = build_constructor (atype, NULL);
9822 1173 : TREE_THIS_VOLATILE (t) = 1;
9823 1173 : gimple_seq_add_stmt (end, gimple_build_assign (avar, t));
9824 : }
9825 :
9826 : /* Expand code for an OpenMP taskgroup directive. */
9827 :
9828 : static void
9829 536 : lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9830 : {
9831 536 : gimple *stmt = gsi_stmt (*gsi_p);
9832 536 : gcall *x;
9833 536 : gbind *bind;
9834 536 : gimple_seq dseq = NULL;
9835 536 : tree block = make_node (BLOCK);
9836 :
9837 536 : bind = gimple_build_bind (NULL, NULL, block);
9838 536 : gsi_replace (gsi_p, bind, true);
9839 536 : gimple_bind_add_stmt (bind, stmt);
9840 :
9841 536 : push_gimplify_context ();
9842 :
9843 536 : x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
9844 : 0);
9845 536 : gimple_bind_add_stmt (bind, x);
9846 :
9847 536 : lower_omp_task_reductions (ctx, OMP_TASKGROUP,
9848 : gimple_omp_taskgroup_clauses (stmt),
9849 : gimple_bind_body_ptr (bind), &dseq);
9850 :
9851 536 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
9852 536 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
9853 536 : gimple_omp_set_body (stmt, NULL);
9854 :
9855 536 : gimple_bind_add_seq (bind, dseq);
9856 :
9857 536 : pop_gimplify_context (bind);
9858 :
9859 536 : gimple_bind_append_vars (bind, ctx->block_vars);
9860 536 : BLOCK_VARS (block) = ctx->block_vars;
9861 536 : }
9862 :
9863 :
9864 : /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
9865 :
9866 : static void
9867 0 : lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
9868 : omp_context *ctx)
9869 : {
9870 0 : struct omp_for_data fd;
9871 0 : if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
9872 0 : return;
9873 :
9874 0 : unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
9875 0 : struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
9876 0 : omp_extract_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
9877 0 : if (!fd.ordered)
9878 : return;
9879 :
9880 0 : tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
9881 0 : tree c = gimple_omp_ordered_clauses (ord_stmt);
9882 0 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
9883 0 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
9884 : {
9885 : /* Merge depend clauses from multiple adjacent
9886 : #pragma omp ordered depend(sink:...) constructs
9887 : into one #pragma omp ordered depend(sink:...), so that
9888 : we can optimize them together. */
9889 0 : gimple_stmt_iterator gsi = *gsi_p;
9890 0 : gsi_next (&gsi);
9891 0 : while (!gsi_end_p (gsi))
9892 : {
9893 0 : gimple *stmt = gsi_stmt (gsi);
9894 0 : if (is_gimple_debug (stmt)
9895 0 : || gimple_code (stmt) == GIMPLE_NOP)
9896 : {
9897 0 : gsi_next (&gsi);
9898 0 : continue;
9899 : }
9900 0 : if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
9901 : break;
9902 0 : gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
9903 0 : c = gimple_omp_ordered_clauses (ord_stmt2);
9904 0 : if (c == NULL_TREE
9905 0 : || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DOACROSS
9906 0 : || OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
9907 : break;
9908 0 : while (*list_p)
9909 0 : list_p = &OMP_CLAUSE_CHAIN (*list_p);
9910 0 : *list_p = c;
9911 0 : gsi_remove (&gsi, true);
9912 : }
9913 : }
9914 :
9915 : /* Canonicalize sink dependence clauses into one folded clause if
9916 : possible.
9917 :
9918 : The basic algorithm is to create a sink vector whose first
9919 : element is the GCD of all the first elements, and whose remaining
9920 : elements are the minimum of the subsequent columns.
9921 :
9922 : We ignore dependence vectors whose first element is zero because
9923 : such dependencies are known to be executed by the same thread.
9924 :
9925 : We take into account the direction of the loop, so a minimum
9926 : becomes a maximum if the loop is iterating forwards. We also
9927 : ignore sink clauses where the loop direction is unknown, or where
9928 : the offsets are clearly invalid because they are not a multiple
9929 : of the loop increment.
9930 :
9931 : For example:
9932 :
9933 : #pragma omp for ordered(2)
9934 : for (i=0; i < N; ++i)
9935 : for (j=0; j < M; ++j)
9936 : {
9937 : #pragma omp ordered \
9938 : depend(sink:i-8,j-2) \
9939 : depend(sink:i,j-1) \ // Completely ignored because i+0.
9940 : depend(sink:i-4,j-3) \
9941 : depend(sink:i-6,j-4)
9942 : #pragma omp ordered depend(source)
9943 : }
9944 :
9945 : Folded clause is:
9946 :
9947 : depend(sink:-gcd(8,4,6),-min(2,3,4))
9948 : -or-
9949 : depend(sink:-2,-2)
9950 : */
9951 :
9952 : /* FIXME: Computing GCD's where the first element is zero is
9953 : non-trivial in the presence of collapsed loops. Do this later. */
9954 0 : if (fd.collapse > 1)
9955 : return;
9956 :
9957 0 : wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
9958 :
9959 : /* wide_int is not a POD so it must be default-constructed. */
9960 0 : for (unsigned i = 0; i != 2 * len - 1; ++i)
9961 0 : new (static_cast<void*>(folded_deps + i)) wide_int ();
9962 :
9963 : tree folded_dep = NULL_TREE;
9964 : /* TRUE if the first dimension's offset is negative. */
9965 : bool neg_offset_p = false;
9966 :
9967 : list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
9968 : unsigned int i;
9969 0 : while ((c = *list_p) != NULL)
9970 : {
9971 0 : bool remove = false;
9972 :
9973 0 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS);
9974 0 : if (OMP_CLAUSE_DOACROSS_KIND (c) != OMP_CLAUSE_DOACROSS_SINK)
9975 0 : goto next_ordered_clause;
9976 :
9977 0 : tree vec;
9978 0 : for (vec = OMP_CLAUSE_DECL (c), i = 0;
9979 0 : vec && TREE_CODE (vec) == TREE_LIST;
9980 0 : vec = TREE_CHAIN (vec), ++i)
9981 : {
9982 0 : gcc_assert (i < len);
9983 :
9984 : /* omp_extract_for_data has canonicalized the condition. */
9985 0 : gcc_assert (fd.loops[i].cond_code == LT_EXPR
9986 : || fd.loops[i].cond_code == GT_EXPR);
9987 0 : bool forward = fd.loops[i].cond_code == LT_EXPR;
9988 0 : bool maybe_lexically_later = true;
9989 :
9990 : /* While the committee makes up its mind, bail if we have any
9991 : non-constant steps. */
9992 0 : if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
9993 0 : goto lower_omp_ordered_ret;
9994 :
9995 0 : tree itype = TREE_TYPE (TREE_VALUE (vec));
9996 0 : if (POINTER_TYPE_P (itype))
9997 0 : itype = sizetype;
9998 0 : wide_int offset = wide_int::from (wi::to_wide (TREE_PURPOSE (vec)),
9999 0 : TYPE_PRECISION (itype),
10000 0 : TYPE_SIGN (itype));
10001 :
10002 : /* Ignore invalid offsets that are not multiples of the step. */
10003 0 : if (!wi::multiple_of_p (wi::abs (offset),
10004 0 : wi::abs (wi::to_wide (fd.loops[i].step)),
10005 : UNSIGNED))
10006 : {
10007 0 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
10008 : "ignoring %<sink%> clause with offset that is not "
10009 : "a multiple of the loop step");
10010 0 : remove = true;
10011 0 : goto next_ordered_clause;
10012 : }
10013 :
10014 : /* Calculate the first dimension. The first dimension of
10015 : the folded dependency vector is the GCD of the first
10016 : elements, while ignoring any first elements whose offset
10017 : is 0. */
10018 0 : if (i == 0)
10019 : {
10020 : /* Ignore dependence vectors whose first dimension is 0. */
10021 0 : if (offset == 0)
10022 : {
10023 0 : remove = true;
10024 0 : goto next_ordered_clause;
10025 : }
10026 : else
10027 : {
10028 0 : if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
10029 : {
10030 0 : error_at (OMP_CLAUSE_LOCATION (c),
10031 : "first offset must be in opposite direction "
10032 : "of loop iterations");
10033 0 : goto lower_omp_ordered_ret;
10034 : }
10035 0 : if (forward)
10036 0 : offset = -offset;
10037 0 : neg_offset_p = forward;
10038 : /* Initialize the first time around. */
10039 0 : if (folded_dep == NULL_TREE)
10040 : {
10041 0 : folded_dep = c;
10042 0 : folded_deps[0] = offset;
10043 : }
10044 : else
10045 0 : folded_deps[0] = wi::gcd (folded_deps[0],
10046 0 : offset, UNSIGNED);
10047 : }
10048 : }
10049 : /* Calculate minimum for the remaining dimensions. */
10050 : else
10051 : {
10052 0 : folded_deps[len + i - 1] = offset;
10053 0 : if (folded_dep == c)
10054 0 : folded_deps[i] = offset;
10055 0 : else if (maybe_lexically_later
10056 0 : && !wi::eq_p (folded_deps[i], offset))
10057 : {
10058 0 : if (forward ^ wi::gts_p (folded_deps[i], offset))
10059 : {
10060 : unsigned int j;
10061 0 : folded_dep = c;
10062 0 : for (j = 1; j <= i; j++)
10063 0 : folded_deps[j] = folded_deps[len + j - 1];
10064 : }
10065 : else
10066 0 : maybe_lexically_later = false;
10067 : }
10068 : }
10069 0 : }
10070 0 : gcc_assert (i == len);
10071 :
10072 : remove = true;
10073 :
10074 0 : next_ordered_clause:
10075 0 : if (remove)
10076 0 : *list_p = OMP_CLAUSE_CHAIN (c);
10077 : else
10078 0 : list_p = &OMP_CLAUSE_CHAIN (c);
10079 : }
10080 :
10081 0 : if (folded_dep)
10082 : {
10083 0 : if (neg_offset_p)
10084 0 : folded_deps[0] = -folded_deps[0];
10085 :
10086 0 : tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
10087 0 : if (POINTER_TYPE_P (itype))
10088 0 : itype = sizetype;
10089 :
10090 0 : TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
10091 0 : = wide_int_to_tree (itype, folded_deps[0]);
10092 0 : OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
10093 0 : *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
10094 : }
10095 :
10096 0 : lower_omp_ordered_ret:
10097 :
10098 : /* Ordered without clauses is #pragma omp threads, while we want
10099 : a nop instead if we remove all clauses. */
10100 0 : if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
10101 0 : gsi_replace (gsi_p, gimple_build_nop (), true);
10102 : }
10103 :
10104 :
10105 : /* Expand code for an OpenMP ordered directive. */
10106 :
10107 : static void
10108 1124 : lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10109 : {
10110 1124 : tree block;
10111 1124 : gimple *stmt = gsi_stmt (*gsi_p), *g;
10112 1124 : gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
10113 1124 : gcall *x;
10114 1124 : gbind *bind;
10115 1124 : bool simd = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
10116 1124 : OMP_CLAUSE_SIMD);
10117 : /* FIXME: this should check presence of OMP_CLAUSE__SIMT_ on the enclosing
10118 : loop. */
10119 1124 : bool maybe_simt
10120 1124 : = simd && omp_maybe_offloaded_ctx (ctx) && omp_max_simt_vf () > 1;
10121 1124 : bool threads = omp_find_clause (gimple_omp_ordered_clauses (ord_stmt),
10122 1124 : OMP_CLAUSE_THREADS);
10123 :
10124 1124 : if (gimple_omp_ordered_standalone_p (ord_stmt))
10125 : {
10126 : /* FIXME: This is needs to be moved to the expansion to verify various
10127 : conditions only testable on cfg with dominators computed, and also
10128 : all the depend clauses to be merged still might need to be available
10129 : for the runtime checks. */
10130 : if (0)
10131 : lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
10132 1124 : return;
10133 : }
10134 :
10135 411 : push_gimplify_context ();
10136 :
10137 411 : block = make_node (BLOCK);
10138 411 : bind = gimple_build_bind (NULL, NULL, block);
10139 411 : gsi_replace (gsi_p, bind, true);
10140 411 : gimple_bind_add_stmt (bind, stmt);
10141 :
10142 411 : if (simd)
10143 : {
10144 79 : x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
10145 79 : build_int_cst (NULL_TREE, threads));
10146 79 : cfun->has_simduid_loops = true;
10147 : }
10148 : else
10149 332 : x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10150 : 0);
10151 411 : gimple_bind_add_stmt (bind, x);
10152 :
10153 411 : tree counter = NULL_TREE, test = NULL_TREE, body = NULL_TREE;
10154 411 : if (maybe_simt)
10155 : {
10156 0 : counter = create_tmp_var (integer_type_node);
10157 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_LANE, 0);
10158 0 : gimple_call_set_lhs (g, counter);
10159 0 : gimple_bind_add_stmt (bind, g);
10160 :
10161 0 : body = create_artificial_label (UNKNOWN_LOCATION);
10162 0 : test = create_artificial_label (UNKNOWN_LOCATION);
10163 0 : gimple_bind_add_stmt (bind, gimple_build_label (body));
10164 :
10165 0 : tree simt_pred = create_tmp_var (integer_type_node);
10166 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_ORDERED_PRED, 1, counter);
10167 0 : gimple_call_set_lhs (g, simt_pred);
10168 0 : gimple_bind_add_stmt (bind, g);
10169 :
10170 0 : tree t = create_artificial_label (UNKNOWN_LOCATION);
10171 0 : g = gimple_build_cond (EQ_EXPR, simt_pred, integer_zero_node, t, test);
10172 0 : gimple_bind_add_stmt (bind, g);
10173 :
10174 0 : gimple_bind_add_stmt (bind, gimple_build_label (t));
10175 : }
10176 411 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
10177 411 : gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10178 411 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10179 411 : gimple_omp_set_body (stmt, NULL);
10180 :
10181 411 : if (maybe_simt)
10182 : {
10183 0 : gimple_bind_add_stmt (bind, gimple_build_label (test));
10184 0 : g = gimple_build_assign (counter, MINUS_EXPR, counter, integer_one_node);
10185 0 : gimple_bind_add_stmt (bind, g);
10186 :
10187 0 : tree c = build2 (GE_EXPR, boolean_type_node, counter, integer_zero_node);
10188 0 : tree nonneg = create_tmp_var (integer_type_node);
10189 0 : gimple_seq tseq = NULL;
10190 0 : gimplify_assign (nonneg, fold_convert (integer_type_node, c), &tseq);
10191 0 : gimple_bind_add_seq (bind, tseq);
10192 :
10193 0 : g = gimple_build_call_internal (IFN_GOMP_SIMT_VOTE_ANY, 1, nonneg);
10194 0 : gimple_call_set_lhs (g, nonneg);
10195 0 : gimple_bind_add_stmt (bind, g);
10196 :
10197 0 : tree end = create_artificial_label (UNKNOWN_LOCATION);
10198 0 : g = gimple_build_cond (NE_EXPR, nonneg, integer_zero_node, body, end);
10199 0 : gimple_bind_add_stmt (bind, g);
10200 :
10201 0 : gimple_bind_add_stmt (bind, gimple_build_label (end));
10202 : }
10203 411 : if (simd)
10204 79 : x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
10205 79 : build_int_cst (NULL_TREE, threads));
10206 : else
10207 332 : x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
10208 : 0);
10209 411 : gimple_bind_add_stmt (bind, x);
10210 :
10211 411 : gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10212 :
10213 411 : pop_gimplify_context (bind);
10214 :
10215 411 : gimple_bind_append_vars (bind, ctx->block_vars);
10216 411 : BLOCK_VARS (block) = gimple_bind_vars (bind);
10217 : }
10218 :
10219 :
10220 : /* Expand code for an OpenMP scan directive and the structured block
10221 : before the scan directive. */
10222 :
10223 : static void
10224 1544 : lower_omp_scan (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10225 : {
10226 1544 : gimple *stmt = gsi_stmt (*gsi_p);
10227 1544 : bool has_clauses
10228 1544 : = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)) != NULL;
10229 1544 : tree lane = NULL_TREE;
10230 1544 : gimple_seq before = NULL;
10231 1544 : omp_context *octx = ctx->outer;
10232 1544 : gcc_assert (octx);
10233 1544 : if (octx->scan_exclusive && !has_clauses)
10234 : {
10235 536 : gimple_stmt_iterator gsi2 = *gsi_p;
10236 536 : gsi_next (&gsi2);
10237 536 : gimple *stmt2 = gsi_stmt (gsi2);
10238 : /* For exclusive scan, swap GIMPLE_OMP_SCAN without clauses
10239 : with following GIMPLE_OMP_SCAN with clauses, so that input_phase,
10240 : the one with exclusive clause(s), comes first. */
10241 536 : if (stmt2
10242 274 : && gimple_code (stmt2) == GIMPLE_OMP_SCAN
10243 804 : && gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt2)) != NULL)
10244 : {
10245 268 : gsi_remove (gsi_p, false);
10246 268 : gsi_insert_after (gsi_p, stmt, GSI_SAME_STMT);
10247 268 : ctx = maybe_lookup_ctx (stmt2);
10248 268 : gcc_assert (ctx);
10249 268 : lower_omp_scan (gsi_p, ctx);
10250 268 : return;
10251 : }
10252 : }
10253 :
10254 1276 : bool input_phase = has_clauses ^ octx->scan_inclusive;
10255 1276 : bool is_simd = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
10256 1276 : && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_SIMD);
10257 1276 : bool is_for = (gimple_code (octx->stmt) == GIMPLE_OMP_FOR
10258 1276 : && gimple_omp_for_kind (octx->stmt) == GF_OMP_FOR_KIND_FOR
10259 1630 : && !gimple_omp_for_combined_p (octx->stmt));
10260 1276 : bool is_for_simd = is_simd && gimple_omp_for_combined_into_p (octx->stmt);
10261 332 : if (is_for_simd && octx->for_simd_scan_phase)
10262 : is_simd = false;
10263 1110 : if (is_simd)
10264 756 : if (tree c = omp_find_clause (gimple_omp_for_clauses (octx->stmt),
10265 : OMP_CLAUSE__SIMDUID_))
10266 : {
10267 368 : tree uid = OMP_CLAUSE__SIMDUID__DECL (c);
10268 368 : lane = create_tmp_var (unsigned_type_node);
10269 368 : tree t = build_int_cst (integer_type_node,
10270 552 : input_phase ? 1
10271 184 : : octx->scan_inclusive ? 2 : 3);
10272 368 : gimple *g
10273 368 : = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 2, uid, t);
10274 368 : gimple_call_set_lhs (g, lane);
10275 368 : gimple_seq_add_stmt (&before, g);
10276 : }
10277 :
10278 1276 : if (is_simd || is_for)
10279 : {
10280 5004 : for (tree c = gimple_omp_for_clauses (octx->stmt);
10281 5004 : c; c = OMP_CLAUSE_CHAIN (c))
10282 4060 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
10283 4060 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
10284 : {
10285 1168 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
10286 1168 : tree var = OMP_CLAUSE_DECL (c);
10287 1168 : tree new_var = lookup_decl (var, octx);
10288 1168 : tree val = new_var;
10289 1168 : tree var2 = NULL_TREE;
10290 1168 : tree var3 = NULL_TREE;
10291 1168 : tree var4 = NULL_TREE;
10292 1168 : tree lane0 = NULL_TREE;
10293 1168 : tree new_vard = new_var;
10294 1168 : if (omp_privatize_by_reference (var))
10295 : {
10296 184 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
10297 184 : val = new_var;
10298 : }
10299 1168 : if (DECL_HAS_VALUE_EXPR_P (new_vard))
10300 : {
10301 464 : val = DECL_VALUE_EXPR (new_vard);
10302 464 : if (new_vard != new_var)
10303 : {
10304 76 : gcc_assert (TREE_CODE (val) == ADDR_EXPR);
10305 76 : val = TREE_OPERAND (val, 0);
10306 : }
10307 464 : if (TREE_CODE (val) == ARRAY_REF
10308 464 : && VAR_P (TREE_OPERAND (val, 0)))
10309 : {
10310 464 : tree v = TREE_OPERAND (val, 0);
10311 464 : if (lookup_attribute ("omp simd array",
10312 464 : DECL_ATTRIBUTES (v)))
10313 : {
10314 464 : val = unshare_expr (val);
10315 464 : lane0 = TREE_OPERAND (val, 1);
10316 464 : TREE_OPERAND (val, 1) = lane;
10317 464 : var2 = lookup_decl (v, octx);
10318 464 : if (octx->scan_exclusive)
10319 228 : var4 = lookup_decl (var2, octx);
10320 464 : if (input_phase
10321 464 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10322 120 : var3 = maybe_lookup_decl (var4 ? var4 : var2, octx);
10323 464 : if (!input_phase)
10324 : {
10325 232 : var2 = build4 (ARRAY_REF, TREE_TYPE (val),
10326 : var2, lane, NULL_TREE, NULL_TREE);
10327 232 : TREE_THIS_NOTRAP (var2) = 1;
10328 232 : if (octx->scan_exclusive)
10329 : {
10330 114 : var4 = build4 (ARRAY_REF, TREE_TYPE (val),
10331 : var4, lane, NULL_TREE,
10332 : NULL_TREE);
10333 114 : TREE_THIS_NOTRAP (var4) = 1;
10334 : }
10335 : }
10336 : else
10337 : var2 = val;
10338 : }
10339 : }
10340 464 : gcc_assert (var2);
10341 : }
10342 : else
10343 : {
10344 704 : var2 = build_outer_var_ref (var, octx);
10345 704 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10346 : {
10347 220 : var3 = maybe_lookup_decl (new_vard, octx);
10348 220 : if (var3 == new_vard || var3 == NULL_TREE)
10349 : var3 = NULL_TREE;
10350 108 : else if (is_simd && octx->scan_exclusive && !input_phase)
10351 : {
10352 16 : var4 = maybe_lookup_decl (var3, octx);
10353 16 : if (var4 == var3 || var4 == NULL_TREE)
10354 : {
10355 0 : if (TREE_ADDRESSABLE (TREE_TYPE (new_var)))
10356 : {
10357 : var4 = var3;
10358 : var3 = NULL_TREE;
10359 : }
10360 : else
10361 16 : var4 = NULL_TREE;
10362 : }
10363 : }
10364 : }
10365 672 : if (is_simd
10366 484 : && octx->scan_exclusive
10367 244 : && !input_phase
10368 244 : && var4 == NULL_TREE)
10369 106 : var4 = create_tmp_var (TREE_TYPE (val));
10370 : }
10371 1168 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
10372 : {
10373 376 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
10374 376 : if (input_phase)
10375 : {
10376 188 : if (var3)
10377 : {
10378 : /* If we've added a separate identity element
10379 : variable, copy it over into val. */
10380 92 : tree x = lang_hooks.decls.omp_clause_assign_op (c, val,
10381 : var3);
10382 92 : gimplify_and_add (x, &before);
10383 : }
10384 96 : else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
10385 : {
10386 : /* Otherwise, assign to it the identity element. */
10387 96 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
10388 96 : if (is_for)
10389 16 : tseq = copy_gimple_seq_and_replace_locals (tseq);
10390 96 : tree ref = build_outer_var_ref (var, octx);
10391 96 : tree x = (DECL_HAS_VALUE_EXPR_P (new_vard)
10392 96 : ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
10393 40 : if (x)
10394 : {
10395 40 : if (new_vard != new_var)
10396 8 : val = build_fold_addr_expr_loc (clause_loc, val);
10397 40 : SET_DECL_VALUE_EXPR (new_vard, val);
10398 : }
10399 96 : SET_DECL_VALUE_EXPR (placeholder, ref);
10400 96 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
10401 96 : lower_omp (&tseq, octx);
10402 96 : if (x)
10403 40 : SET_DECL_VALUE_EXPR (new_vard, x);
10404 96 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
10405 96 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
10406 96 : gimple_seq_add_seq (&before, tseq);
10407 96 : if (is_simd)
10408 80 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
10409 : }
10410 : }
10411 188 : else if (is_simd)
10412 : {
10413 156 : tree x;
10414 156 : if (octx->scan_exclusive)
10415 : {
10416 72 : tree v4 = unshare_expr (var4);
10417 72 : tree v2 = unshare_expr (var2);
10418 72 : x = lang_hooks.decls.omp_clause_assign_op (c, v4, v2);
10419 72 : gimplify_and_add (x, &before);
10420 : }
10421 156 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
10422 156 : x = (DECL_HAS_VALUE_EXPR_P (new_vard)
10423 156 : ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
10424 156 : tree vexpr = val;
10425 156 : if (x && new_vard != new_var)
10426 30 : vexpr = build_fold_addr_expr_loc (clause_loc, val);
10427 156 : if (x)
10428 78 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
10429 156 : SET_DECL_VALUE_EXPR (placeholder, var2);
10430 156 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
10431 156 : lower_omp (&tseq, octx);
10432 156 : gimple_seq_add_seq (&before, tseq);
10433 156 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
10434 156 : if (x)
10435 78 : SET_DECL_VALUE_EXPR (new_vard, x);
10436 156 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
10437 156 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
10438 156 : if (octx->scan_inclusive)
10439 : {
10440 84 : x = lang_hooks.decls.omp_clause_assign_op (c, val,
10441 : var2);
10442 84 : gimplify_and_add (x, &before);
10443 : }
10444 72 : else if (lane0 == NULL_TREE)
10445 : {
10446 36 : x = lang_hooks.decls.omp_clause_assign_op (c, val,
10447 : var4);
10448 36 : gimplify_and_add (x, &before);
10449 : }
10450 : }
10451 : }
10452 : else
10453 : {
10454 792 : if (input_phase)
10455 : {
10456 : /* input phase. Set val to initializer before
10457 : the body. */
10458 396 : tree x = omp_reduction_init (c, TREE_TYPE (new_var));
10459 396 : gimplify_assign (val, x, &before);
10460 : }
10461 396 : else if (is_simd)
10462 : {
10463 : /* scan phase. */
10464 318 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
10465 318 : if (code == MINUS_EXPR)
10466 0 : code = PLUS_EXPR;
10467 :
10468 318 : tree x = build2 (code, TREE_TYPE (var2),
10469 : unshare_expr (var2), unshare_expr (val));
10470 318 : if (octx->scan_inclusive)
10471 : {
10472 154 : gimplify_assign (unshare_expr (var2), x, &before);
10473 154 : gimplify_assign (val, var2, &before);
10474 : }
10475 : else
10476 : {
10477 164 : gimplify_assign (unshare_expr (var4),
10478 : unshare_expr (var2), &before);
10479 164 : gimplify_assign (var2, x, &before);
10480 164 : if (lane0 == NULL_TREE)
10481 86 : gimplify_assign (val, var4, &before);
10482 : }
10483 : }
10484 : }
10485 1168 : if (octx->scan_exclusive && !input_phase && lane0)
10486 : {
10487 114 : tree vexpr = unshare_expr (var4);
10488 114 : TREE_OPERAND (vexpr, 1) = lane0;
10489 114 : if (new_vard != new_var)
10490 16 : vexpr = build_fold_addr_expr_loc (clause_loc, vexpr);
10491 114 : SET_DECL_VALUE_EXPR (new_vard, vexpr);
10492 : }
10493 : }
10494 : }
10495 1276 : if (is_simd && !is_for_simd)
10496 : {
10497 590 : gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT);
10498 590 : gsi_insert_seq_after (gsi_p, before, GSI_SAME_STMT);
10499 590 : gsi_replace (gsi_p, gimple_build_nop (), true);
10500 590 : return;
10501 : }
10502 686 : lower_omp (gimple_omp_body_ptr (stmt), octx);
10503 686 : if (before)
10504 : {
10505 260 : gimple_stmt_iterator gsi = gsi_start (*gimple_omp_body_ptr (stmt));
10506 260 : gsi_insert_seq_before (&gsi, before, GSI_SAME_STMT);
10507 : }
10508 : }
10509 :
10510 :
10511 : /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10512 : substitution of a couple of function calls. But in the NAMED case,
10513 : requires that languages coordinate a symbol name. It is therefore
10514 : best put here in common code. */
10515 :
10516 : static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10517 :
10518 : static void
10519 311 : lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10520 : {
10521 311 : tree block;
10522 311 : tree name, lock, unlock;
10523 311 : gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10524 311 : gbind *bind;
10525 311 : location_t loc = gimple_location (stmt);
10526 311 : gimple_seq tbody;
10527 :
10528 311 : name = gimple_omp_critical_name (stmt);
10529 311 : if (name)
10530 : {
10531 88 : tree decl;
10532 :
10533 88 : if (!critical_name_mutexes)
10534 48 : critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10535 :
10536 88 : tree *n = critical_name_mutexes->get (name);
10537 88 : if (n == NULL)
10538 : {
10539 70 : char *new_str;
10540 :
10541 70 : decl = create_tmp_var_raw (ptr_type_node);
10542 :
10543 70 : new_str = ACONCAT ((".gomp_critical_user_",
10544 : IDENTIFIER_POINTER (name), NULL));
10545 70 : DECL_NAME (decl) = get_identifier (new_str);
10546 70 : TREE_PUBLIC (decl) = 1;
10547 70 : TREE_STATIC (decl) = 1;
10548 70 : DECL_COMMON (decl) = 1;
10549 70 : DECL_ARTIFICIAL (decl) = 1;
10550 70 : DECL_IGNORED_P (decl) = 1;
10551 :
10552 70 : varpool_node::finalize_decl (decl);
10553 :
10554 70 : critical_name_mutexes->put (name, decl);
10555 : }
10556 : else
10557 18 : decl = *n;
10558 :
10559 : /* If '#pragma omp critical' is inside offloaded region or
10560 : inside function marked as offloadable, the symbol must be
10561 : marked as offloadable too. */
10562 88 : omp_context *octx;
10563 88 : if (cgraph_node::get (current_function_decl)->offloadable)
10564 1 : varpool_node::get_create (decl)->offloadable = 1;
10565 : else
10566 173 : for (octx = ctx->outer; octx; octx = octx->outer)
10567 87 : if (is_gimple_omp_offloaded (octx->stmt))
10568 : {
10569 1 : varpool_node::get_create (decl)->offloadable = 1;
10570 1 : break;
10571 : }
10572 :
10573 88 : lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10574 88 : lock = build_call_expr_loc (loc, lock, 1,
10575 : build_fold_addr_expr_loc (loc, decl));
10576 :
10577 88 : unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10578 88 : unlock = build_call_expr_loc (loc, unlock, 1,
10579 : build_fold_addr_expr_loc (loc, decl));
10580 : }
10581 : else
10582 : {
10583 223 : lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10584 223 : lock = build_call_expr_loc (loc, lock, 0);
10585 :
10586 223 : unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10587 223 : unlock = build_call_expr_loc (loc, unlock, 0);
10588 : }
10589 :
10590 311 : push_gimplify_context ();
10591 :
10592 311 : block = make_node (BLOCK);
10593 311 : bind = gimple_build_bind (NULL, NULL, block);
10594 311 : gsi_replace (gsi_p, bind, true);
10595 311 : gimple_bind_add_stmt (bind, stmt);
10596 :
10597 311 : tbody = gimple_bind_body (bind);
10598 311 : gimplify_and_add (lock, &tbody);
10599 311 : gimple_bind_set_body (bind, tbody);
10600 :
10601 311 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
10602 311 : gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10603 311 : gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10604 311 : gimple_omp_set_body (stmt, NULL);
10605 :
10606 311 : tbody = gimple_bind_body (bind);
10607 311 : gimplify_and_add (unlock, &tbody);
10608 311 : gimple_bind_set_body (bind, tbody);
10609 :
10610 311 : gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10611 :
10612 311 : pop_gimplify_context (bind);
10613 311 : gimple_bind_append_vars (bind, ctx->block_vars);
10614 311 : BLOCK_VARS (block) = gimple_bind_vars (bind);
10615 311 : }
10616 :
10617 : /* A subroutine of lower_omp_for. Generate code to emit the predicate
10618 : for a lastprivate clause. Given a loop control predicate of (V
10619 : cond N2), we gate the clause on (!(V cond N2)). The lowered form
10620 : is appended to *DLIST, iterator initialization is appended to
10621 : *BODY_P. *CLIST is for lastprivate(conditional:) code that needs
10622 : to be emitted in a critical section. */
10623 :
10624 : static void
10625 46966 : lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10626 : gimple_seq *dlist, gimple_seq *clist,
10627 : struct omp_context *ctx)
10628 : {
10629 46966 : tree clauses, cond, vinit;
10630 46966 : enum tree_code cond_code;
10631 46966 : gimple_seq stmts;
10632 :
10633 46966 : cond_code = fd->loop.cond_code;
10634 46966 : cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10635 :
10636 : /* When possible, use a strict equality expression. This can let VRP
10637 : type optimizations deduce the value and remove a copy. */
10638 46966 : if (tree_fits_shwi_p (fd->loop.step))
10639 : {
10640 44727 : HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10641 44727 : if (step == 1 || step == -1)
10642 46966 : cond_code = EQ_EXPR;
10643 : }
10644 :
10645 46966 : tree n2 = fd->loop.n2;
10646 46966 : if (fd->collapse > 1
10647 11251 : && TREE_CODE (n2) != INTEGER_CST
10648 53180 : && gimple_omp_for_combined_into_p (fd->for_stmt))
10649 : {
10650 2692 : struct omp_context *taskreg_ctx = NULL;
10651 2692 : if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10652 : {
10653 1226 : gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10654 1226 : if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
10655 1226 : || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
10656 : {
10657 1194 : if (gimple_omp_for_combined_into_p (gfor))
10658 : {
10659 672 : gcc_assert (ctx->outer->outer
10660 : && is_parallel_ctx (ctx->outer->outer));
10661 : taskreg_ctx = ctx->outer->outer;
10662 : }
10663 : else
10664 : {
10665 522 : struct omp_for_data outer_fd;
10666 522 : omp_extract_for_data (gfor, &outer_fd, NULL);
10667 522 : n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10668 : }
10669 : }
10670 32 : else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
10671 32 : taskreg_ctx = ctx->outer->outer;
10672 : }
10673 1466 : else if (is_taskreg_ctx (ctx->outer))
10674 : taskreg_ctx = ctx->outer;
10675 2692 : if (taskreg_ctx)
10676 : {
10677 2170 : int i;
10678 2170 : tree taskreg_clauses
10679 2170 : = gimple_omp_taskreg_clauses (taskreg_ctx->stmt);
10680 2170 : tree innerc = omp_find_clause (taskreg_clauses,
10681 : OMP_CLAUSE__LOOPTEMP_);
10682 2170 : gcc_assert (innerc);
10683 2170 : int count = fd->collapse;
10684 2170 : if (fd->non_rect
10685 24 : && fd->last_nonrect == fd->first_nonrect + 1)
10686 12 : if (tree v = gimple_omp_for_index (fd->for_stmt, fd->last_nonrect))
10687 12 : if (!TYPE_UNSIGNED (TREE_TYPE (v)))
10688 12 : count += 4;
10689 8582 : for (i = 0; i < count; i++)
10690 : {
10691 6412 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
10692 : OMP_CLAUSE__LOOPTEMP_);
10693 6412 : gcc_assert (innerc);
10694 : }
10695 2170 : innerc = omp_find_clause (OMP_CLAUSE_CHAIN (innerc),
10696 : OMP_CLAUSE__LOOPTEMP_);
10697 2170 : if (innerc)
10698 1419 : n2 = fold_convert (TREE_TYPE (n2),
10699 : lookup_decl (OMP_CLAUSE_DECL (innerc),
10700 : taskreg_ctx));
10701 : }
10702 : }
10703 46966 : cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10704 :
10705 46966 : clauses = gimple_omp_for_clauses (fd->for_stmt);
10706 46966 : stmts = NULL;
10707 46966 : lower_lastprivate_clauses (clauses, cond, body_p, &stmts, clist, ctx);
10708 46966 : if (!gimple_seq_empty_p (stmts))
10709 : {
10710 16372 : gimple_seq_add_seq (&stmts, *dlist);
10711 16372 : *dlist = stmts;
10712 :
10713 : /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10714 16372 : vinit = fd->loop.n1;
10715 16372 : if (cond_code == EQ_EXPR
10716 14385 : && tree_fits_shwi_p (fd->loop.n2)
10717 25943 : && ! integer_zerop (fd->loop.n2))
10718 8355 : vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10719 : else
10720 8017 : vinit = unshare_expr (vinit);
10721 :
10722 : /* Initialize the iterator variable, so that threads that don't execute
10723 : any iterations don't execute the lastprivate clauses by accident. */
10724 16372 : gimplify_assign (fd->loop.v, vinit, body_p);
10725 : }
10726 46966 : }
10727 :
10728 : /* OpenACC privatization.
10729 :
10730 : Or, in other words, *sharing* at the respective OpenACC level of
10731 : parallelism.
10732 :
10733 : From a correctness perspective, a non-addressable variable can't be accessed
10734 : outside the current thread, so it can go in a (faster than shared memory)
10735 : register -- though that register may need to be broadcast in some
10736 : circumstances. A variable can only meaningfully be "shared" across workers
10737 : or vector lanes if its address is taken, e.g. by a call to an atomic
10738 : builtin.
10739 :
10740 : From an optimisation perspective, the answer might be fuzzier: maybe
10741 : sometimes, using shared memory directly would be faster than
10742 : broadcasting. */
10743 :
10744 : static void
10745 18997 : oacc_privatization_begin_diagnose_var (const dump_flags_t l_dump_flags,
10746 : const location_t loc, const tree c,
10747 : const tree decl)
10748 : {
10749 18997 : const dump_user_location_t d_u_loc
10750 18997 : = dump_user_location_t::from_location_t (loc);
10751 : /* PR100695 "Format decoder, quoting in 'dump_printf' etc." */
10752 : #if __GNUC__ >= 10
10753 18997 : # pragma GCC diagnostic push
10754 18997 : # pragma GCC diagnostic ignored "-Wformat"
10755 : #endif
10756 18997 : dump_printf_loc (l_dump_flags, d_u_loc,
10757 : "variable %<%T%> ", decl);
10758 : #if __GNUC__ >= 10
10759 18997 : # pragma GCC diagnostic pop
10760 : #endif
10761 18997 : if (c)
10762 2797 : dump_printf (l_dump_flags,
10763 : "in %qs clause ",
10764 2797 : omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
10765 : else
10766 16200 : dump_printf (l_dump_flags,
10767 : "declared in block ");
10768 18997 : }
10769 :
10770 : static bool
10771 41114 : oacc_privatization_candidate_p (const location_t loc, const tree c,
10772 : const tree decl)
10773 : {
10774 41114 : dump_flags_t l_dump_flags = get_openacc_privatization_dump_flags ();
10775 :
10776 : /* There is some differentiation depending on block vs. clause. */
10777 41114 : bool block = !c;
10778 :
10779 41114 : bool res = true;
10780 :
10781 41114 : if (res && !VAR_P (decl))
10782 : {
10783 : /* A PARM_DECL (appearing in a 'private' clause) is expected to have been
10784 : privatized into a new VAR_DECL. */
10785 712 : gcc_checking_assert (TREE_CODE (decl) != PARM_DECL);
10786 :
10787 712 : res = false;
10788 :
10789 712 : if (dump_enabled_p ())
10790 : {
10791 683 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10792 683 : dump_printf (l_dump_flags,
10793 : "potentially has improper OpenACC privatization level: %qs\n",
10794 683 : get_tree_code_name (TREE_CODE (decl)));
10795 : }
10796 : }
10797 :
10798 41085 : if (res && block && TREE_STATIC (decl))
10799 : {
10800 53 : res = false;
10801 :
10802 53 : if (dump_enabled_p ())
10803 : {
10804 28 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10805 28 : dump_printf (l_dump_flags,
10806 : "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10807 : "static");
10808 : }
10809 : }
10810 :
10811 41089 : if (res && block && DECL_EXTERNAL (decl))
10812 : {
10813 12 : res = false;
10814 :
10815 12 : if (dump_enabled_p ())
10816 : {
10817 12 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10818 12 : dump_printf (l_dump_flags,
10819 : "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10820 : "external");
10821 : }
10822 : }
10823 :
10824 41114 : if (res && !TREE_ADDRESSABLE (decl))
10825 : {
10826 39245 : res = false;
10827 :
10828 39245 : if (dump_enabled_p ())
10829 : {
10830 17456 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10831 17456 : dump_printf (l_dump_flags,
10832 : "isn%'t candidate for adjusting OpenACC privatization level: %s\n",
10833 : "not addressable");
10834 : }
10835 : }
10836 :
10837 : /* If an artificial variable has been added to a bind, e.g.
10838 : a compiler-generated temporary structure used by the Fortran front-end, do
10839 : not consider it as a privatization candidate. Note that variables on
10840 : the stack are private per-thread by default: making them "gang-private"
10841 : for OpenACC actually means to share a single instance of a variable
10842 : amongst all workers and threads spawned within each gang.
10843 : At present, no compiler-generated artificial variables require such
10844 : sharing semantics, so this is safe. */
10845 :
10846 18548 : if (res && block && DECL_ARTIFICIAL (decl))
10847 : {
10848 548 : res = false;
10849 :
10850 548 : if (dump_enabled_p ())
10851 : {
10852 360 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10853 360 : dump_printf (l_dump_flags,
10854 : "isn%'t candidate for adjusting OpenACC privatization "
10855 : "level: %s\n", "artificial");
10856 : }
10857 : }
10858 :
10859 40926 : if (res)
10860 : {
10861 544 : if (dump_enabled_p ())
10862 : {
10863 458 : oacc_privatization_begin_diagnose_var (l_dump_flags, loc, c, decl);
10864 458 : dump_printf (l_dump_flags,
10865 : "is candidate for adjusting OpenACC privatization level\n");
10866 : }
10867 : }
10868 :
10869 41114 : if (dump_file && (dump_flags & TDF_DETAILS))
10870 : {
10871 0 : print_generic_decl (dump_file, decl, dump_flags);
10872 0 : fprintf (dump_file, "\n");
10873 : }
10874 :
10875 41114 : return res;
10876 : }
10877 :
10878 : /* Scan CLAUSES for candidates for adjusting OpenACC privatization level in
10879 : CTX. */
10880 :
10881 : static void
10882 11325 : oacc_privatization_scan_clause_chain (omp_context *ctx, tree clauses)
10883 : {
10884 35223 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10885 23898 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE)
10886 : {
10887 12986 : tree decl = OMP_CLAUSE_DECL (c);
10888 :
10889 12986 : tree new_decl = lookup_decl (decl, ctx);
10890 :
10891 12986 : if (!oacc_privatization_candidate_p (OMP_CLAUSE_LOCATION (c), c,
10892 : new_decl))
10893 12654 : continue;
10894 :
10895 332 : gcc_checking_assert
10896 : (!ctx->oacc_privatization_candidates.contains (new_decl));
10897 332 : ctx->oacc_privatization_candidates.safe_push (new_decl);
10898 : }
10899 11325 : }
10900 :
10901 : /* Scan DECLS for candidates for adjusting OpenACC privatization level in
10902 : CTX. */
10903 :
10904 : static void
10905 23090 : oacc_privatization_scan_decl_chain (omp_context *ctx, tree decls)
10906 : {
10907 51218 : for (tree decl = decls; decl; decl = DECL_CHAIN (decl))
10908 : {
10909 28128 : tree new_decl = lookup_decl (decl, ctx);
10910 28128 : gcc_checking_assert (new_decl == decl);
10911 :
10912 28128 : if (!oacc_privatization_candidate_p (gimple_location (ctx->stmt), NULL,
10913 : new_decl))
10914 27916 : continue;
10915 :
10916 212 : gcc_checking_assert
10917 : (!ctx->oacc_privatization_candidates.contains (new_decl));
10918 212 : ctx->oacc_privatization_candidates.safe_push (new_decl);
10919 : }
10920 23090 : }
10921 :
10922 : /* Callback for walk_gimple_seq. Find #pragma omp scan statement. */
10923 :
10924 : static tree
10925 2233 : omp_find_scan (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
10926 : struct walk_stmt_info *wi)
10927 : {
10928 2233 : gimple *stmt = gsi_stmt (*gsi_p);
10929 :
10930 2233 : *handled_ops_p = true;
10931 2233 : switch (gimple_code (stmt))
10932 : {
10933 418 : WALK_SUBSTMTS;
10934 :
10935 166 : case GIMPLE_OMP_FOR:
10936 166 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_SIMD
10937 166 : && gimple_omp_for_combined_into_p (stmt))
10938 166 : *handled_ops_p = false;
10939 : break;
10940 :
10941 686 : case GIMPLE_OMP_SCAN:
10942 686 : *(gimple_stmt_iterator *) (wi->info) = *gsi_p;
10943 686 : return integer_zero_node;
10944 : default:
10945 : break;
10946 : }
10947 : return NULL;
10948 : }
10949 :
10950 : /* Helper function for lower_omp_for, add transformations for a worksharing
10951 : loop with scan directives inside of it.
10952 : For worksharing loop not combined with simd, transform:
10953 : #pragma omp for reduction(inscan,+:r) private(i)
10954 : for (i = 0; i < n; i = i + 1)
10955 : {
10956 : {
10957 : update (r);
10958 : }
10959 : #pragma omp scan inclusive(r)
10960 : {
10961 : use (r);
10962 : }
10963 : }
10964 :
10965 : into two worksharing loops + code to merge results:
10966 :
10967 : num_threads = omp_get_num_threads ();
10968 : thread_num = omp_get_thread_num ();
10969 : if (thread_num == 0) goto <D.2099>; else goto <D.2100>;
10970 : <D.2099>:
10971 : var2 = r;
10972 : goto <D.2101>;
10973 : <D.2100>:
10974 : // For UDRs this is UDR init, or if ctors are needed, copy from
10975 : // var3 that has been constructed to contain the neutral element.
10976 : var2 = 0;
10977 : <D.2101>:
10978 : ivar = 0;
10979 : // The _scantemp_ clauses will arrange for rpriva to be initialized to
10980 : // a shared array with num_threads elements and rprivb to a local array
10981 : // number of elements equal to the number of (contiguous) iterations the
10982 : // current thread will perform. controlb and controlp variables are
10983 : // temporaries to handle deallocation of rprivb at the end of second
10984 : // GOMP_FOR.
10985 : #pragma omp for _scantemp_(rpriva) _scantemp_(rprivb) _scantemp_(controlb) \
10986 : _scantemp_(controlp) reduction(inscan,+:r) private(i) nowait
10987 : for (i = 0; i < n; i = i + 1)
10988 : {
10989 : {
10990 : // For UDRs this is UDR init or copy from var3.
10991 : r = 0;
10992 : // This is the input phase from user code.
10993 : update (r);
10994 : }
10995 : {
10996 : // For UDRs this is UDR merge.
10997 : var2 = var2 + r;
10998 : // Rather than handing it over to the user, save to local thread's
10999 : // array.
11000 : rprivb[ivar] = var2;
11001 : // For exclusive scan, the above two statements are swapped.
11002 : ivar = ivar + 1;
11003 : }
11004 : }
11005 : // And remember the final value from this thread's into the shared
11006 : // rpriva array.
11007 : rpriva[(sizetype) thread_num] = var2;
11008 : // If more than one thread, compute using Work-Efficient prefix sum
11009 : // the inclusive parallel scan of the rpriva array.
11010 : if (num_threads > 1) goto <D.2102>; else goto <D.2103>;
11011 : <D.2102>:
11012 : GOMP_barrier ();
11013 : down = 0;
11014 : k = 1;
11015 : num_threadsu = (unsigned int) num_threads;
11016 : thread_numup1 = (unsigned int) thread_num + 1;
11017 : <D.2108>:
11018 : twok = k << 1;
11019 : if (twok > num_threadsu) goto <D.2110>; else goto <D.2111>;
11020 : <D.2110>:
11021 : down = 4294967295;
11022 : k = k >> 1;
11023 : if (k == num_threadsu) goto <D.2112>; else goto <D.2111>;
11024 : <D.2112>:
11025 : k = k >> 1;
11026 : <D.2111>:
11027 : twok = k << 1;
11028 : cplx = .MUL_OVERFLOW (thread_nump1, twok);
11029 : mul = REALPART_EXPR <cplx>;
11030 : ovf = IMAGPART_EXPR <cplx>;
11031 : if (ovf == 0) goto <D.2116>; else goto <D.2117>;
11032 : <D.2116>:
11033 : andv = k & down;
11034 : andvm1 = andv + 4294967295;
11035 : l = mul + andvm1;
11036 : if (l < num_threadsu) goto <D.2120>; else goto <D.2117>;
11037 : <D.2120>:
11038 : // For UDRs this is UDR merge, performed using var2 variable as temporary,
11039 : // i.e. var2 = rpriva[l - k]; UDR merge (var2, rpriva[l]); rpriva[l] = var2;
11040 : rpriva[l] = rpriva[l - k] + rpriva[l];
11041 : <D.2117>:
11042 : if (down == 0) goto <D.2121>; else goto <D.2122>;
11043 : <D.2121>:
11044 : k = k << 1;
11045 : goto <D.2123>;
11046 : <D.2122>:
11047 : k = k >> 1;
11048 : <D.2123>:
11049 : GOMP_barrier ();
11050 : if (k != 0) goto <D.2108>; else goto <D.2103>;
11051 : <D.2103>:
11052 : if (thread_num == 0) goto <D.2124>; else goto <D.2125>;
11053 : <D.2124>:
11054 : // For UDRs this is UDR init or copy from var3.
11055 : var2 = 0;
11056 : goto <D.2126>;
11057 : <D.2125>:
11058 : var2 = rpriva[thread_num - 1];
11059 : <D.2126>:
11060 : ivar = 0;
11061 : #pragma omp for _scantemp_(controlb) _scantemp_(controlp) \
11062 : reduction(inscan,+:r) private(i)
11063 : for (i = 0; i < n; i = i + 1)
11064 : {
11065 : {
11066 : // For UDRs, this is r = var2; UDR merge (r, rprivb[ivar]);
11067 : r = var2 + rprivb[ivar];
11068 : }
11069 : {
11070 : // This is the scan phase from user code.
11071 : use (r);
11072 : // Plus a bump of the iterator.
11073 : ivar = ivar + 1;
11074 : }
11075 : } */
11076 :
11077 : static void
11078 177 : lower_omp_for_scan (gimple_seq *body_p, gimple_seq *dlist, gomp_for *stmt,
11079 : struct omp_for_data *fd, omp_context *ctx)
11080 : {
11081 177 : bool is_for_simd = gimple_omp_for_combined_p (stmt);
11082 177 : gcc_assert (ctx->scan_inclusive || ctx->scan_exclusive);
11083 :
11084 177 : gimple_seq body = gimple_omp_body (stmt);
11085 177 : gimple_stmt_iterator input1_gsi = gsi_none ();
11086 177 : struct walk_stmt_info wi;
11087 177 : memset (&wi, 0, sizeof (wi));
11088 177 : wi.val_only = true;
11089 177 : wi.info = (void *) &input1_gsi;
11090 177 : walk_gimple_seq_mod (&body, omp_find_scan, NULL, &wi);
11091 177 : gcc_assert (!gsi_end_p (input1_gsi));
11092 :
11093 177 : gimple *input_stmt1 = gsi_stmt (input1_gsi);
11094 177 : gimple_stmt_iterator gsi = input1_gsi;
11095 177 : gsi_next (&gsi);
11096 177 : gimple_stmt_iterator scan1_gsi = gsi;
11097 177 : gimple *scan_stmt1 = gsi_stmt (gsi);
11098 177 : gcc_assert (scan_stmt1 && gimple_code (scan_stmt1) == GIMPLE_OMP_SCAN);
11099 :
11100 177 : gimple_seq input_body = gimple_omp_body (input_stmt1);
11101 177 : gimple_seq scan_body = gimple_omp_body (scan_stmt1);
11102 177 : gimple_omp_set_body (input_stmt1, NULL);
11103 177 : gimple_omp_set_body (scan_stmt1, NULL);
11104 177 : gimple_omp_set_body (stmt, NULL);
11105 :
11106 177 : gomp_for *new_stmt = as_a <gomp_for *> (gimple_copy (stmt));
11107 177 : gimple_seq new_body = copy_gimple_seq_and_replace_locals (body);
11108 177 : gimple_omp_set_body (stmt, body);
11109 177 : gimple_omp_set_body (input_stmt1, input_body);
11110 :
11111 177 : gimple_stmt_iterator input2_gsi = gsi_none ();
11112 177 : memset (&wi, 0, sizeof (wi));
11113 177 : wi.val_only = true;
11114 177 : wi.info = (void *) &input2_gsi;
11115 177 : walk_gimple_seq_mod (&new_body, omp_find_scan, NULL, &wi);
11116 177 : gcc_assert (!gsi_end_p (input2_gsi));
11117 :
11118 177 : gimple *input_stmt2 = gsi_stmt (input2_gsi);
11119 177 : gsi = input2_gsi;
11120 177 : gsi_next (&gsi);
11121 177 : gimple_stmt_iterator scan2_gsi = gsi;
11122 177 : gimple *scan_stmt2 = gsi_stmt (gsi);
11123 177 : gcc_assert (scan_stmt2 && gimple_code (scan_stmt2) == GIMPLE_OMP_SCAN);
11124 177 : gimple_omp_set_body (scan_stmt2, scan_body);
11125 :
11126 177 : gimple_stmt_iterator input3_gsi = gsi_none ();
11127 177 : gimple_stmt_iterator scan3_gsi = gsi_none ();
11128 177 : gimple_stmt_iterator input4_gsi = gsi_none ();
11129 177 : gimple_stmt_iterator scan4_gsi = gsi_none ();
11130 177 : gimple *input_stmt3 = NULL, *scan_stmt3 = NULL;
11131 177 : gimple *input_stmt4 = NULL, *scan_stmt4 = NULL;
11132 177 : omp_context *input_simd_ctx = NULL, *scan_simd_ctx = NULL;
11133 177 : if (is_for_simd)
11134 : {
11135 83 : memset (&wi, 0, sizeof (wi));
11136 83 : wi.val_only = true;
11137 83 : wi.info = (void *) &input3_gsi;
11138 83 : walk_gimple_seq_mod (&input_body, omp_find_scan, NULL, &wi);
11139 83 : gcc_assert (!gsi_end_p (input3_gsi));
11140 :
11141 83 : input_stmt3 = gsi_stmt (input3_gsi);
11142 83 : gsi = input3_gsi;
11143 83 : gsi_next (&gsi);
11144 83 : scan3_gsi = gsi;
11145 83 : scan_stmt3 = gsi_stmt (gsi);
11146 83 : gcc_assert (scan_stmt3 && gimple_code (scan_stmt3) == GIMPLE_OMP_SCAN);
11147 :
11148 83 : memset (&wi, 0, sizeof (wi));
11149 83 : wi.val_only = true;
11150 83 : wi.info = (void *) &input4_gsi;
11151 83 : walk_gimple_seq_mod (&scan_body, omp_find_scan, NULL, &wi);
11152 83 : gcc_assert (!gsi_end_p (input4_gsi));
11153 :
11154 83 : input_stmt4 = gsi_stmt (input4_gsi);
11155 83 : gsi = input4_gsi;
11156 83 : gsi_next (&gsi);
11157 83 : scan4_gsi = gsi;
11158 83 : scan_stmt4 = gsi_stmt (gsi);
11159 83 : gcc_assert (scan_stmt4 && gimple_code (scan_stmt4) == GIMPLE_OMP_SCAN);
11160 :
11161 83 : input_simd_ctx = maybe_lookup_ctx (input_stmt3)->outer;
11162 83 : scan_simd_ctx = maybe_lookup_ctx (input_stmt4)->outer;
11163 : }
11164 :
11165 177 : tree num_threads = create_tmp_var (integer_type_node);
11166 177 : tree thread_num = create_tmp_var (integer_type_node);
11167 177 : tree nthreads_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
11168 177 : tree threadnum_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
11169 177 : gimple *g = gimple_build_call (nthreads_decl, 0);
11170 177 : gimple_call_set_lhs (g, num_threads);
11171 177 : gimple_seq_add_stmt (body_p, g);
11172 177 : g = gimple_build_call (threadnum_decl, 0);
11173 177 : gimple_call_set_lhs (g, thread_num);
11174 177 : gimple_seq_add_stmt (body_p, g);
11175 :
11176 177 : tree ivar = create_tmp_var (sizetype);
11177 177 : tree new_clauses1 = NULL_TREE, new_clauses2 = NULL_TREE;
11178 177 : tree *cp1 = &new_clauses1, *cp2 = &new_clauses2;
11179 177 : tree k = create_tmp_var (unsigned_type_node);
11180 177 : tree l = create_tmp_var (unsigned_type_node);
11181 :
11182 177 : gimple_seq clist = NULL, mdlist = NULL;
11183 177 : gimple_seq thr01_list = NULL, thrn1_list = NULL;
11184 177 : gimple_seq thr02_list = NULL, thrn2_list = NULL;
11185 177 : gimple_seq scan1_list = NULL, input2_list = NULL;
11186 177 : gimple_seq last_list = NULL, reduc_list = NULL;
11187 686 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
11188 509 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
11189 509 : && OMP_CLAUSE_REDUCTION_INSCAN (c))
11190 : {
11191 209 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
11192 209 : tree var = OMP_CLAUSE_DECL (c);
11193 209 : tree new_var = lookup_decl (var, ctx);
11194 209 : tree var3 = NULL_TREE;
11195 209 : tree new_vard = new_var;
11196 209 : if (omp_privatize_by_reference (var))
11197 32 : new_var = build_simple_mem_ref_loc (clause_loc, new_var);
11198 209 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
11199 : {
11200 64 : var3 = maybe_lookup_decl (new_vard, ctx);
11201 64 : if (var3 == new_vard)
11202 177 : var3 = NULL_TREE;
11203 : }
11204 :
11205 209 : tree ptype = build_pointer_type (TREE_TYPE (new_var));
11206 209 : tree rpriva = create_tmp_var (ptype);
11207 209 : tree nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
11208 209 : OMP_CLAUSE_DECL (nc) = rpriva;
11209 209 : *cp1 = nc;
11210 209 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11211 :
11212 209 : tree rprivb = create_tmp_var (ptype);
11213 209 : nc = build_omp_clause (clause_loc, OMP_CLAUSE__SCANTEMP_);
11214 209 : OMP_CLAUSE_DECL (nc) = rprivb;
11215 209 : OMP_CLAUSE__SCANTEMP__ALLOC (nc) = 1;
11216 209 : *cp1 = nc;
11217 209 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11218 :
11219 209 : tree var2 = create_tmp_var_raw (TREE_TYPE (new_var));
11220 209 : if (new_vard != new_var)
11221 32 : TREE_ADDRESSABLE (var2) = 1;
11222 209 : gimple_add_tmp_var (var2);
11223 :
11224 209 : tree x = fold_convert_loc (clause_loc, sizetype, thread_num);
11225 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11226 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11227 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11228 209 : tree rpriva_ref = build_simple_mem_ref_loc (clause_loc, x);
11229 :
11230 209 : x = fold_build2_loc (clause_loc, PLUS_EXPR, integer_type_node,
11231 : thread_num, integer_minus_one_node);
11232 209 : x = fold_convert_loc (clause_loc, sizetype, x);
11233 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11234 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11235 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11236 209 : tree rprivam1_ref = build_simple_mem_ref_loc (clause_loc, x);
11237 :
11238 209 : x = fold_convert_loc (clause_loc, sizetype, l);
11239 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11240 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11241 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11242 209 : tree rprival_ref = build_simple_mem_ref_loc (clause_loc, x);
11243 :
11244 209 : x = fold_build2_loc (clause_loc, MINUS_EXPR, unsigned_type_node, l, k);
11245 209 : x = fold_convert_loc (clause_loc, sizetype, x);
11246 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, x,
11247 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11248 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rpriva), rpriva, x);
11249 209 : tree rprivalmk_ref = build_simple_mem_ref_loc (clause_loc, x);
11250 :
11251 209 : x = fold_build2_loc (clause_loc, MULT_EXPR, sizetype, ivar,
11252 209 : TYPE_SIZE_UNIT (TREE_TYPE (ptype)));
11253 209 : x = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (rprivb), rprivb, x);
11254 209 : tree rprivb_ref = build_simple_mem_ref_loc (clause_loc, x);
11255 :
11256 209 : tree var4 = is_for_simd ? new_var : var2;
11257 99 : tree var5 = NULL_TREE, var6 = NULL_TREE;
11258 99 : if (is_for_simd)
11259 : {
11260 99 : var5 = lookup_decl (var, input_simd_ctx);
11261 99 : var6 = lookup_decl (var, scan_simd_ctx);
11262 99 : if (new_vard != new_var)
11263 : {
11264 16 : var5 = build_simple_mem_ref_loc (clause_loc, var5);
11265 16 : var6 = build_simple_mem_ref_loc (clause_loc, var6);
11266 : }
11267 : }
11268 209 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
11269 : {
11270 64 : tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
11271 64 : tree val = var2;
11272 :
11273 64 : x = lang_hooks.decls.omp_clause_default_ctor
11274 64 : (c, var2, build_outer_var_ref (var, ctx));
11275 64 : if (x)
11276 32 : gimplify_and_add (x, &clist);
11277 :
11278 64 : x = build_outer_var_ref (var, ctx);
11279 64 : x = lang_hooks.decls.omp_clause_assign_op (c, unshare_expr (var4),
11280 : x);
11281 64 : gimplify_and_add (x, &thr01_list);
11282 :
11283 64 : tree y = (DECL_HAS_VALUE_EXPR_P (new_vard)
11284 64 : ? DECL_VALUE_EXPR (new_vard) : NULL_TREE);
11285 64 : if (var3)
11286 : {
11287 32 : x = unshare_expr (var4);
11288 32 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var3);
11289 32 : gimplify_and_add (x, &thrn1_list);
11290 32 : x = unshare_expr (var4);
11291 32 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var3);
11292 32 : gimplify_and_add (x, &thr02_list);
11293 : }
11294 32 : else if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
11295 : {
11296 : /* Otherwise, assign to it the identity element. */
11297 32 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
11298 32 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11299 32 : if (!is_for_simd)
11300 : {
11301 16 : if (new_vard != new_var)
11302 4 : val = build_fold_addr_expr_loc (clause_loc, val);
11303 16 : SET_DECL_VALUE_EXPR (new_vard, val);
11304 16 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11305 : }
11306 32 : SET_DECL_VALUE_EXPR (placeholder, error_mark_node);
11307 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11308 32 : lower_omp (&tseq, ctx);
11309 32 : gimple_seq_add_seq (&thrn1_list, tseq);
11310 32 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
11311 32 : lower_omp (&tseq, ctx);
11312 32 : gimple_seq_add_seq (&thr02_list, tseq);
11313 32 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
11314 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11315 32 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
11316 32 : if (y)
11317 0 : SET_DECL_VALUE_EXPR (new_vard, y);
11318 : else
11319 : {
11320 32 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11321 32 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11322 : }
11323 : }
11324 :
11325 64 : x = unshare_expr (var4);
11326 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x, rprivam1_ref);
11327 64 : gimplify_and_add (x, &thrn2_list);
11328 :
11329 64 : if (is_for_simd)
11330 : {
11331 32 : x = unshare_expr (rprivb_ref);
11332 32 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var5);
11333 32 : gimplify_and_add (x, &scan1_list);
11334 : }
11335 : else
11336 : {
11337 32 : if (ctx->scan_exclusive)
11338 : {
11339 16 : x = unshare_expr (rprivb_ref);
11340 16 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
11341 16 : gimplify_and_add (x, &scan1_list);
11342 : }
11343 :
11344 32 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11345 32 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11346 32 : SET_DECL_VALUE_EXPR (placeholder, var2);
11347 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11348 32 : lower_omp (&tseq, ctx);
11349 32 : gimple_seq_add_seq (&scan1_list, tseq);
11350 :
11351 32 : if (ctx->scan_inclusive)
11352 : {
11353 16 : x = unshare_expr (rprivb_ref);
11354 16 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var2);
11355 16 : gimplify_and_add (x, &scan1_list);
11356 : }
11357 : }
11358 :
11359 64 : x = unshare_expr (rpriva_ref);
11360 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x,
11361 : unshare_expr (var4));
11362 64 : gimplify_and_add (x, &mdlist);
11363 :
11364 96 : x = unshare_expr (is_for_simd ? var6 : new_var);
11365 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x, var4);
11366 64 : gimplify_and_add (x, &input2_list);
11367 :
11368 64 : val = rprivb_ref;
11369 64 : if (new_vard != new_var)
11370 24 : val = build_fold_addr_expr_loc (clause_loc, val);
11371 :
11372 64 : gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11373 64 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11374 64 : SET_DECL_VALUE_EXPR (new_vard, val);
11375 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11376 64 : if (is_for_simd)
11377 : {
11378 32 : SET_DECL_VALUE_EXPR (placeholder, var6);
11379 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11380 : }
11381 : else
11382 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11383 64 : lower_omp (&tseq, ctx);
11384 64 : if (y)
11385 0 : SET_DECL_VALUE_EXPR (new_vard, y);
11386 : else
11387 : {
11388 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11389 64 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11390 : }
11391 64 : if (!is_for_simd)
11392 : {
11393 32 : SET_DECL_VALUE_EXPR (placeholder, new_var);
11394 32 : DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
11395 32 : lower_omp (&tseq, ctx);
11396 : }
11397 64 : gimple_seq_add_seq (&input2_list, tseq);
11398 :
11399 64 : x = build_outer_var_ref (var, ctx);
11400 64 : x = lang_hooks.decls.omp_clause_assign_op (c, x, rpriva_ref);
11401 64 : gimplify_and_add (x, &last_list);
11402 :
11403 64 : x = lang_hooks.decls.omp_clause_assign_op (c, var2, rprivalmk_ref);
11404 64 : gimplify_and_add (x, &reduc_list);
11405 64 : tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
11406 64 : tseq = copy_gimple_seq_and_replace_locals (tseq);
11407 64 : val = rprival_ref;
11408 64 : if (new_vard != new_var)
11409 24 : val = build_fold_addr_expr_loc (clause_loc, val);
11410 64 : SET_DECL_VALUE_EXPR (new_vard, val);
11411 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
11412 64 : SET_DECL_VALUE_EXPR (placeholder, var2);
11413 64 : lower_omp (&tseq, ctx);
11414 64 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
11415 64 : SET_DECL_VALUE_EXPR (placeholder, NULL_TREE);
11416 64 : DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
11417 64 : if (y)
11418 0 : SET_DECL_VALUE_EXPR (new_vard, y);
11419 : else
11420 : {
11421 64 : DECL_HAS_VALUE_EXPR_P (new_vard) = 0;
11422 64 : SET_DECL_VALUE_EXPR (new_vard, NULL_TREE);
11423 : }
11424 64 : gimple_seq_add_seq (&reduc_list, tseq);
11425 64 : x = lang_hooks.decls.omp_clause_assign_op (c, rprival_ref, var2);
11426 64 : gimplify_and_add (x, &reduc_list);
11427 :
11428 64 : x = lang_hooks.decls.omp_clause_dtor (c, var2);
11429 64 : if (x)
11430 32 : gimplify_and_add (x, dlist);
11431 : }
11432 : else
11433 : {
11434 145 : x = build_outer_var_ref (var, ctx);
11435 145 : gimplify_assign (unshare_expr (var4), x, &thr01_list);
11436 :
11437 145 : x = omp_reduction_init (c, TREE_TYPE (new_var));
11438 145 : gimplify_assign (unshare_expr (var4), unshare_expr (x),
11439 : &thrn1_list);
11440 145 : gimplify_assign (unshare_expr (var4), x, &thr02_list);
11441 :
11442 145 : gimplify_assign (unshare_expr (var4), rprivam1_ref, &thrn2_list);
11443 :
11444 145 : enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
11445 145 : if (code == MINUS_EXPR)
11446 0 : code = PLUS_EXPR;
11447 :
11448 145 : if (is_for_simd)
11449 67 : gimplify_assign (unshare_expr (rprivb_ref), var5, &scan1_list);
11450 : else
11451 : {
11452 78 : if (ctx->scan_exclusive)
11453 28 : gimplify_assign (unshare_expr (rprivb_ref), var2,
11454 : &scan1_list);
11455 78 : x = build2 (code, TREE_TYPE (new_var), var2, new_var);
11456 78 : gimplify_assign (var2, x, &scan1_list);
11457 78 : if (ctx->scan_inclusive)
11458 50 : gimplify_assign (unshare_expr (rprivb_ref), var2,
11459 : &scan1_list);
11460 : }
11461 :
11462 145 : gimplify_assign (unshare_expr (rpriva_ref), unshare_expr (var4),
11463 : &mdlist);
11464 :
11465 145 : x = build2 (code, TREE_TYPE (new_var), var4, rprivb_ref);
11466 223 : gimplify_assign (is_for_simd ? var6 : new_var, x, &input2_list);
11467 :
11468 145 : gimplify_assign (build_outer_var_ref (var, ctx), rpriva_ref,
11469 : &last_list);
11470 :
11471 145 : x = build2 (code, TREE_TYPE (new_var), rprivalmk_ref,
11472 : unshare_expr (rprival_ref));
11473 145 : gimplify_assign (rprival_ref, x, &reduc_list);
11474 : }
11475 : }
11476 :
11477 177 : g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
11478 177 : gimple_seq_add_stmt (&scan1_list, g);
11479 177 : g = gimple_build_assign (ivar, PLUS_EXPR, ivar, size_one_node);
11480 271 : gimple_seq_add_stmt (gimple_omp_body_ptr (is_for_simd
11481 : ? scan_stmt4 : scan_stmt2), g);
11482 :
11483 177 : tree controlb = create_tmp_var (boolean_type_node);
11484 177 : tree controlp = create_tmp_var (ptr_type_node);
11485 177 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11486 177 : OMP_CLAUSE_DECL (nc) = controlb;
11487 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11488 177 : *cp1 = nc;
11489 177 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11490 177 : nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11491 177 : OMP_CLAUSE_DECL (nc) = controlp;
11492 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11493 177 : *cp1 = nc;
11494 177 : cp1 = &OMP_CLAUSE_CHAIN (nc);
11495 177 : nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11496 177 : OMP_CLAUSE_DECL (nc) = controlb;
11497 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11498 177 : *cp2 = nc;
11499 177 : cp2 = &OMP_CLAUSE_CHAIN (nc);
11500 177 : nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SCANTEMP_);
11501 177 : OMP_CLAUSE_DECL (nc) = controlp;
11502 177 : OMP_CLAUSE__SCANTEMP__CONTROL (nc) = 1;
11503 177 : *cp2 = nc;
11504 177 : cp2 = &OMP_CLAUSE_CHAIN (nc);
11505 :
11506 177 : *cp1 = gimple_omp_for_clauses (stmt);
11507 177 : gimple_omp_for_set_clauses (stmt, new_clauses1);
11508 177 : *cp2 = gimple_omp_for_clauses (new_stmt);
11509 177 : gimple_omp_for_set_clauses (new_stmt, new_clauses2);
11510 :
11511 177 : if (is_for_simd)
11512 : {
11513 83 : gimple_seq_add_seq (gimple_omp_body_ptr (scan_stmt3), scan1_list);
11514 83 : gimple_seq_add_seq (gimple_omp_body_ptr (input_stmt4), input2_list);
11515 :
11516 83 : gsi_insert_seq_after (&input3_gsi, gimple_omp_body (input_stmt3),
11517 : GSI_SAME_STMT);
11518 83 : gsi_remove (&input3_gsi, true);
11519 83 : gsi_insert_seq_after (&scan3_gsi, gimple_omp_body (scan_stmt3),
11520 : GSI_SAME_STMT);
11521 83 : gsi_remove (&scan3_gsi, true);
11522 83 : gsi_insert_seq_after (&input4_gsi, gimple_omp_body (input_stmt4),
11523 : GSI_SAME_STMT);
11524 83 : gsi_remove (&input4_gsi, true);
11525 83 : gsi_insert_seq_after (&scan4_gsi, gimple_omp_body (scan_stmt4),
11526 : GSI_SAME_STMT);
11527 83 : gsi_remove (&scan4_gsi, true);
11528 : }
11529 : else
11530 : {
11531 94 : gimple_omp_set_body (scan_stmt1, scan1_list);
11532 94 : gimple_omp_set_body (input_stmt2, input2_list);
11533 : }
11534 :
11535 177 : gsi_insert_seq_after (&input1_gsi, gimple_omp_body (input_stmt1),
11536 : GSI_SAME_STMT);
11537 177 : gsi_remove (&input1_gsi, true);
11538 177 : gsi_insert_seq_after (&scan1_gsi, gimple_omp_body (scan_stmt1),
11539 : GSI_SAME_STMT);
11540 177 : gsi_remove (&scan1_gsi, true);
11541 177 : gsi_insert_seq_after (&input2_gsi, gimple_omp_body (input_stmt2),
11542 : GSI_SAME_STMT);
11543 177 : gsi_remove (&input2_gsi, true);
11544 177 : gsi_insert_seq_after (&scan2_gsi, gimple_omp_body (scan_stmt2),
11545 : GSI_SAME_STMT);
11546 177 : gsi_remove (&scan2_gsi, true);
11547 :
11548 177 : gimple_seq_add_seq (body_p, clist);
11549 :
11550 177 : tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
11551 177 : tree lab2 = create_artificial_label (UNKNOWN_LOCATION);
11552 177 : tree lab3 = create_artificial_label (UNKNOWN_LOCATION);
11553 177 : g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
11554 177 : gimple_seq_add_stmt (body_p, g);
11555 177 : g = gimple_build_label (lab1);
11556 177 : gimple_seq_add_stmt (body_p, g);
11557 177 : gimple_seq_add_seq (body_p, thr01_list);
11558 177 : g = gimple_build_goto (lab3);
11559 177 : gimple_seq_add_stmt (body_p, g);
11560 177 : g = gimple_build_label (lab2);
11561 177 : gimple_seq_add_stmt (body_p, g);
11562 177 : gimple_seq_add_seq (body_p, thrn1_list);
11563 177 : g = gimple_build_label (lab3);
11564 177 : gimple_seq_add_stmt (body_p, g);
11565 :
11566 177 : g = gimple_build_assign (ivar, size_zero_node);
11567 177 : gimple_seq_add_stmt (body_p, g);
11568 :
11569 177 : gimple_seq_add_stmt (body_p, stmt);
11570 177 : gimple_seq_add_seq (body_p, body);
11571 177 : gimple_seq_add_stmt (body_p, gimple_build_omp_continue (fd->loop.v,
11572 : fd->loop.v));
11573 :
11574 177 : g = gimple_build_omp_return (true);
11575 177 : gimple_seq_add_stmt (body_p, g);
11576 177 : gimple_seq_add_seq (body_p, mdlist);
11577 :
11578 177 : lab1 = create_artificial_label (UNKNOWN_LOCATION);
11579 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
11580 177 : g = gimple_build_cond (GT_EXPR, num_threads, integer_one_node, lab1, lab2);
11581 177 : gimple_seq_add_stmt (body_p, g);
11582 177 : g = gimple_build_label (lab1);
11583 177 : gimple_seq_add_stmt (body_p, g);
11584 :
11585 177 : g = omp_build_barrier (NULL, GOMP_BARRIER_IMPLICIT_WORKSHARE);
11586 177 : gimple_seq_add_stmt (body_p, g);
11587 :
11588 177 : tree down = create_tmp_var (unsigned_type_node);
11589 177 : g = gimple_build_assign (down, build_zero_cst (unsigned_type_node));
11590 177 : gimple_seq_add_stmt (body_p, g);
11591 :
11592 177 : g = gimple_build_assign (k, build_one_cst (unsigned_type_node));
11593 177 : gimple_seq_add_stmt (body_p, g);
11594 :
11595 177 : tree num_threadsu = create_tmp_var (unsigned_type_node);
11596 177 : g = gimple_build_assign (num_threadsu, NOP_EXPR, num_threads);
11597 177 : gimple_seq_add_stmt (body_p, g);
11598 :
11599 177 : tree thread_numu = create_tmp_var (unsigned_type_node);
11600 177 : g = gimple_build_assign (thread_numu, NOP_EXPR, thread_num);
11601 177 : gimple_seq_add_stmt (body_p, g);
11602 :
11603 177 : tree thread_nump1 = create_tmp_var (unsigned_type_node);
11604 177 : g = gimple_build_assign (thread_nump1, PLUS_EXPR, thread_numu,
11605 : build_int_cst (unsigned_type_node, 1));
11606 177 : gimple_seq_add_stmt (body_p, g);
11607 :
11608 177 : lab3 = create_artificial_label (UNKNOWN_LOCATION);
11609 177 : g = gimple_build_label (lab3);
11610 177 : gimple_seq_add_stmt (body_p, g);
11611 :
11612 177 : tree twok = create_tmp_var (unsigned_type_node);
11613 177 : g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
11614 177 : gimple_seq_add_stmt (body_p, g);
11615 :
11616 177 : tree lab4 = create_artificial_label (UNKNOWN_LOCATION);
11617 177 : tree lab5 = create_artificial_label (UNKNOWN_LOCATION);
11618 177 : tree lab6 = create_artificial_label (UNKNOWN_LOCATION);
11619 177 : g = gimple_build_cond (GT_EXPR, twok, num_threadsu, lab4, lab5);
11620 177 : gimple_seq_add_stmt (body_p, g);
11621 177 : g = gimple_build_label (lab4);
11622 177 : gimple_seq_add_stmt (body_p, g);
11623 177 : g = gimple_build_assign (down, build_all_ones_cst (unsigned_type_node));
11624 177 : gimple_seq_add_stmt (body_p, g);
11625 177 : g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11626 177 : gimple_seq_add_stmt (body_p, g);
11627 :
11628 177 : g = gimple_build_cond (EQ_EXPR, k, num_threadsu, lab6, lab5);
11629 177 : gimple_seq_add_stmt (body_p, g);
11630 177 : g = gimple_build_label (lab6);
11631 177 : gimple_seq_add_stmt (body_p, g);
11632 :
11633 177 : g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11634 177 : gimple_seq_add_stmt (body_p, g);
11635 :
11636 177 : g = gimple_build_label (lab5);
11637 177 : gimple_seq_add_stmt (body_p, g);
11638 :
11639 177 : g = gimple_build_assign (twok, LSHIFT_EXPR, k, integer_one_node);
11640 177 : gimple_seq_add_stmt (body_p, g);
11641 :
11642 177 : tree cplx = create_tmp_var (build_complex_type (unsigned_type_node, false));
11643 177 : g = gimple_build_call_internal (IFN_MUL_OVERFLOW, 2, thread_nump1, twok);
11644 177 : gimple_call_set_lhs (g, cplx);
11645 177 : gimple_seq_add_stmt (body_p, g);
11646 177 : tree mul = create_tmp_var (unsigned_type_node);
11647 177 : g = gimple_build_assign (mul, REALPART_EXPR,
11648 : build1 (REALPART_EXPR, unsigned_type_node, cplx));
11649 177 : gimple_seq_add_stmt (body_p, g);
11650 177 : tree ovf = create_tmp_var (unsigned_type_node);
11651 177 : g = gimple_build_assign (ovf, IMAGPART_EXPR,
11652 : build1 (IMAGPART_EXPR, unsigned_type_node, cplx));
11653 177 : gimple_seq_add_stmt (body_p, g);
11654 :
11655 177 : tree lab7 = create_artificial_label (UNKNOWN_LOCATION);
11656 177 : tree lab8 = create_artificial_label (UNKNOWN_LOCATION);
11657 177 : g = gimple_build_cond (EQ_EXPR, ovf, build_zero_cst (unsigned_type_node),
11658 : lab7, lab8);
11659 177 : gimple_seq_add_stmt (body_p, g);
11660 177 : g = gimple_build_label (lab7);
11661 177 : gimple_seq_add_stmt (body_p, g);
11662 :
11663 177 : tree andv = create_tmp_var (unsigned_type_node);
11664 177 : g = gimple_build_assign (andv, BIT_AND_EXPR, k, down);
11665 177 : gimple_seq_add_stmt (body_p, g);
11666 177 : tree andvm1 = create_tmp_var (unsigned_type_node);
11667 177 : g = gimple_build_assign (andvm1, PLUS_EXPR, andv,
11668 : build_minus_one_cst (unsigned_type_node));
11669 177 : gimple_seq_add_stmt (body_p, g);
11670 :
11671 177 : g = gimple_build_assign (l, PLUS_EXPR, mul, andvm1);
11672 177 : gimple_seq_add_stmt (body_p, g);
11673 :
11674 177 : tree lab9 = create_artificial_label (UNKNOWN_LOCATION);
11675 177 : g = gimple_build_cond (LT_EXPR, l, num_threadsu, lab9, lab8);
11676 177 : gimple_seq_add_stmt (body_p, g);
11677 177 : g = gimple_build_label (lab9);
11678 177 : gimple_seq_add_stmt (body_p, g);
11679 177 : gimple_seq_add_seq (body_p, reduc_list);
11680 177 : g = gimple_build_label (lab8);
11681 177 : gimple_seq_add_stmt (body_p, g);
11682 :
11683 177 : tree lab10 = create_artificial_label (UNKNOWN_LOCATION);
11684 177 : tree lab11 = create_artificial_label (UNKNOWN_LOCATION);
11685 177 : tree lab12 = create_artificial_label (UNKNOWN_LOCATION);
11686 177 : g = gimple_build_cond (EQ_EXPR, down, build_zero_cst (unsigned_type_node),
11687 : lab10, lab11);
11688 177 : gimple_seq_add_stmt (body_p, g);
11689 177 : g = gimple_build_label (lab10);
11690 177 : gimple_seq_add_stmt (body_p, g);
11691 177 : g = gimple_build_assign (k, LSHIFT_EXPR, k, integer_one_node);
11692 177 : gimple_seq_add_stmt (body_p, g);
11693 177 : g = gimple_build_goto (lab12);
11694 177 : gimple_seq_add_stmt (body_p, g);
11695 177 : g = gimple_build_label (lab11);
11696 177 : gimple_seq_add_stmt (body_p, g);
11697 177 : g = gimple_build_assign (k, RSHIFT_EXPR, k, integer_one_node);
11698 177 : gimple_seq_add_stmt (body_p, g);
11699 177 : g = gimple_build_label (lab12);
11700 177 : gimple_seq_add_stmt (body_p, g);
11701 :
11702 177 : g = omp_build_barrier (NULL, GOMP_BARRIER_IMPLICIT_WORKSHARE);
11703 177 : gimple_seq_add_stmt (body_p, g);
11704 :
11705 177 : g = gimple_build_cond (NE_EXPR, k, build_zero_cst (unsigned_type_node),
11706 : lab3, lab2);
11707 177 : gimple_seq_add_stmt (body_p, g);
11708 :
11709 177 : g = gimple_build_label (lab2);
11710 177 : gimple_seq_add_stmt (body_p, g);
11711 :
11712 177 : lab1 = create_artificial_label (UNKNOWN_LOCATION);
11713 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
11714 177 : lab3 = create_artificial_label (UNKNOWN_LOCATION);
11715 177 : g = gimple_build_cond (EQ_EXPR, thread_num, integer_zero_node, lab1, lab2);
11716 177 : gimple_seq_add_stmt (body_p, g);
11717 177 : g = gimple_build_label (lab1);
11718 177 : gimple_seq_add_stmt (body_p, g);
11719 177 : gimple_seq_add_seq (body_p, thr02_list);
11720 177 : g = gimple_build_goto (lab3);
11721 177 : gimple_seq_add_stmt (body_p, g);
11722 177 : g = gimple_build_label (lab2);
11723 177 : gimple_seq_add_stmt (body_p, g);
11724 177 : gimple_seq_add_seq (body_p, thrn2_list);
11725 177 : g = gimple_build_label (lab3);
11726 177 : gimple_seq_add_stmt (body_p, g);
11727 :
11728 177 : g = gimple_build_assign (ivar, size_zero_node);
11729 177 : gimple_seq_add_stmt (body_p, g);
11730 177 : gimple_seq_add_stmt (body_p, new_stmt);
11731 177 : gimple_seq_add_seq (body_p, new_body);
11732 :
11733 177 : gimple_seq new_dlist = NULL;
11734 177 : lab1 = create_artificial_label (UNKNOWN_LOCATION);
11735 177 : lab2 = create_artificial_label (UNKNOWN_LOCATION);
11736 177 : tree num_threadsm1 = create_tmp_var (integer_type_node);
11737 177 : g = gimple_build_assign (num_threadsm1, PLUS_EXPR, num_threads,
11738 : integer_minus_one_node);
11739 177 : gimple_seq_add_stmt (&new_dlist, g);
11740 177 : g = gimple_build_cond (EQ_EXPR, thread_num, num_threadsm1, lab1, lab2);
11741 177 : gimple_seq_add_stmt (&new_dlist, g);
11742 177 : g = gimple_build_label (lab1);
11743 177 : gimple_seq_add_stmt (&new_dlist, g);
11744 177 : gimple_seq_add_seq (&new_dlist, last_list);
11745 177 : g = gimple_build_label (lab2);
11746 177 : gimple_seq_add_stmt (&new_dlist, g);
11747 177 : gimple_seq_add_seq (&new_dlist, *dlist);
11748 177 : *dlist = new_dlist;
11749 177 : }
11750 :
11751 : /* Build an internal UNIQUE function with type IFN_UNIQUE_OACC_PRIVATE listing
11752 : the addresses of variables to be made private at the surrounding
11753 : parallelism level. Such functions appear in the gimple code stream in two
11754 : forms, e.g. for a partitioned loop:
11755 :
11756 : .data_dep.6 = .UNIQUE (OACC_HEAD_MARK, .data_dep.6, 1, 68);
11757 : .data_dep.6 = .UNIQUE (OACC_PRIVATE, .data_dep.6, -1, &w);
11758 : .data_dep.6 = .UNIQUE (OACC_FORK, .data_dep.6, -1);
11759 : .data_dep.6 = .UNIQUE (OACC_HEAD_MARK, .data_dep.6);
11760 :
11761 : or alternatively, OACC_PRIVATE can appear at the top level of a parallel,
11762 : not as part of a HEAD_MARK sequence:
11763 :
11764 : .UNIQUE (OACC_PRIVATE, 0, 0, &w);
11765 :
11766 : For such stand-alone appearances, the 3rd argument is always 0, denoting
11767 : gang partitioning. */
11768 :
11769 : static gcall *
11770 19728 : lower_oacc_private_marker (omp_context *ctx)
11771 : {
11772 19728 : if (ctx->oacc_privatization_candidates.length () == 0)
11773 : return NULL;
11774 :
11775 308 : auto_vec<tree, 5> args;
11776 :
11777 308 : args.quick_push (build_int_cst (integer_type_node, IFN_UNIQUE_OACC_PRIVATE));
11778 308 : args.quick_push (integer_zero_node);
11779 308 : args.quick_push (integer_minus_one_node);
11780 :
11781 308 : int i;
11782 308 : tree decl;
11783 696 : FOR_EACH_VEC_ELT (ctx->oacc_privatization_candidates, i, decl)
11784 : {
11785 388 : gcc_checking_assert (TREE_ADDRESSABLE (decl));
11786 388 : tree addr = build_fold_addr_expr (decl);
11787 388 : args.safe_push (addr);
11788 : }
11789 :
11790 308 : return gimple_build_call_internal_vec (IFN_UNIQUE, args);
11791 308 : }
11792 :
11793 : /* Lower code for an OMP loop directive. */
11794 :
11795 : static void
11796 46966 : lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11797 : {
11798 46966 : tree *rhs_p, block;
11799 46966 : struct omp_for_data fd, *fdp = NULL;
11800 46966 : gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
11801 46966 : gbind *new_stmt;
11802 46966 : gimple_seq omp_for_body, body, dlist, tred_ilist = NULL, tred_dlist = NULL;
11803 46966 : gimple_seq cnt_list = NULL, clist = NULL;
11804 46966 : gimple_seq oacc_head = NULL, oacc_tail = NULL;
11805 46966 : size_t i;
11806 :
11807 46966 : push_gimplify_context ();
11808 :
11809 46966 : if (is_gimple_omp_oacc (ctx->stmt))
11810 11325 : oacc_privatization_scan_clause_chain (ctx, gimple_omp_for_clauses (stmt));
11811 :
11812 46966 : lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
11813 :
11814 46966 : block = make_node (BLOCK);
11815 46966 : new_stmt = gimple_build_bind (NULL, NULL, block);
11816 : /* Replace at gsi right away, so that 'stmt' is no member
11817 : of a sequence anymore as we're going to add to a different
11818 : one below. */
11819 46966 : gsi_replace (gsi_p, new_stmt, true);
11820 :
11821 : /* Move declaration of temporaries in the loop body before we make
11822 : it go away. */
11823 46966 : omp_for_body = gimple_omp_body (stmt);
11824 46966 : if (!gimple_seq_empty_p (omp_for_body)
11825 46966 : && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
11826 : {
11827 19621 : gbind *inner_bind
11828 19621 : = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
11829 19621 : tree vars = gimple_bind_vars (inner_bind);
11830 19621 : if (is_gimple_omp_oacc (ctx->stmt))
11831 5305 : oacc_privatization_scan_decl_chain (ctx, vars);
11832 19621 : gimple_bind_append_vars (new_stmt, vars);
11833 : /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
11834 : keep them on the inner_bind and it's block. */
11835 19621 : gimple_bind_set_vars (inner_bind, NULL_TREE);
11836 19621 : if (gimple_bind_block (inner_bind))
11837 17062 : BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
11838 : }
11839 :
11840 46966 : if (gimple_omp_for_combined_into_p (stmt))
11841 : {
11842 14604 : omp_extract_for_data (stmt, &fd, NULL);
11843 14604 : fdp = &fd;
11844 :
11845 : /* We need two temporaries with fd.loop.v type (istart/iend)
11846 : and then (fd.collapse - 1) temporaries with the same
11847 : type for count2 ... countN-1 vars if not constant. */
11848 14604 : size_t count = 2;
11849 14604 : tree type = fd.iter_type;
11850 14604 : if (fd.collapse > 1
11851 4867 : && TREE_CODE (fd.loop.n2) != INTEGER_CST)
11852 2692 : count += fd.collapse - 1;
11853 14604 : size_t count2 = 0;
11854 14604 : tree type2 = NULL_TREE;
11855 14604 : bool taskreg_for
11856 14604 : = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
11857 14604 : || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
11858 14604 : tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
11859 14604 : tree simtc = NULL;
11860 14604 : tree clauses = *pc;
11861 14604 : if (fd.collapse > 1
11862 4867 : && fd.non_rect
11863 137 : && fd.last_nonrect == fd.first_nonrect + 1
11864 89 : && TREE_CODE (fd.loop.n2) != INTEGER_CST)
11865 64 : if (tree v = gimple_omp_for_index (stmt, fd.last_nonrect))
11866 64 : if (!TYPE_UNSIGNED (TREE_TYPE (v)))
11867 : {
11868 60 : v = gimple_omp_for_index (stmt, fd.first_nonrect);
11869 60 : type2 = TREE_TYPE (v);
11870 60 : count++;
11871 60 : count2 = 3;
11872 : }
11873 14604 : if (taskreg_for)
11874 7597 : outerc
11875 7597 : = omp_find_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
11876 : OMP_CLAUSE__LOOPTEMP_);
11877 14604 : if (ctx->simt_stmt)
11878 0 : simtc = omp_find_clause (gimple_omp_for_clauses (ctx->simt_stmt),
11879 : OMP_CLAUSE__LOOPTEMP_);
11880 49221 : for (i = 0; i < count + count2; i++)
11881 : {
11882 34617 : tree temp;
11883 34617 : if (taskreg_for)
11884 : {
11885 18075 : gcc_assert (outerc);
11886 18075 : temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
11887 18075 : outerc = omp_find_clause (OMP_CLAUSE_CHAIN (outerc),
11888 : OMP_CLAUSE__LOOPTEMP_);
11889 : }
11890 : else
11891 : {
11892 : /* If there are 2 adjacent SIMD stmts, one with _simt_
11893 : clause, another without, make sure they have the same
11894 : decls in _looptemp_ clauses, because the outer stmt
11895 : they are combined into will look up just one inner_stmt. */
11896 16542 : if (ctx->simt_stmt)
11897 0 : temp = OMP_CLAUSE_DECL (simtc);
11898 : else
11899 32940 : temp = create_tmp_var (i >= count ? type2 : type);
11900 16542 : insert_decl_map (&ctx->outer->cb, temp, temp);
11901 : }
11902 34617 : *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
11903 34617 : OMP_CLAUSE_DECL (*pc) = temp;
11904 34617 : pc = &OMP_CLAUSE_CHAIN (*pc);
11905 34617 : if (ctx->simt_stmt)
11906 0 : simtc = omp_find_clause (OMP_CLAUSE_CHAIN (simtc),
11907 : OMP_CLAUSE__LOOPTEMP_);
11908 : }
11909 14604 : *pc = clauses;
11910 : }
11911 :
11912 : /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
11913 46966 : dlist = NULL;
11914 46966 : body = NULL;
11915 46966 : tree rclauses
11916 46966 : = omp_task_reductions_find_first (gimple_omp_for_clauses (stmt), OMP_FOR,
11917 : OMP_CLAUSE_REDUCTION);
11918 46966 : tree rtmp = NULL_TREE;
11919 46966 : if (rclauses)
11920 : {
11921 227 : tree type = build_pointer_type (pointer_sized_int_node);
11922 227 : tree temp = create_tmp_var (type);
11923 227 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__REDUCTEMP_);
11924 227 : OMP_CLAUSE_DECL (c) = temp;
11925 227 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (stmt);
11926 227 : gimple_omp_for_set_clauses (stmt, c);
11927 227 : lower_omp_task_reductions (ctx, OMP_FOR,
11928 : gimple_omp_for_clauses (stmt),
11929 : &tred_ilist, &tred_dlist);
11930 227 : rclauses = c;
11931 227 : rtmp = make_ssa_name (type);
11932 227 : gimple_seq_add_stmt (&body, gimple_build_assign (rtmp, temp));
11933 : }
11934 :
11935 46966 : lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
11936 : ctx);
11937 :
11938 46966 : lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
11939 : fdp);
11940 93705 : gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
11941 : gimple_omp_for_pre_body (stmt));
11942 :
11943 46966 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
11944 :
11945 46966 : gcall *private_marker = NULL;
11946 46966 : if (is_gimple_omp_oacc (ctx->stmt)
11947 46966 : && !gimple_seq_empty_p (omp_for_body))
11948 10333 : private_marker = lower_oacc_private_marker (ctx);
11949 :
11950 : /* Lower the header expressions. At this point, we can assume that
11951 : the header is of the form:
11952 :
11953 : #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
11954 :
11955 : We just need to make sure that VAL1, VAL2 and VAL3 are lowered
11956 : using the .omp_data_s mapping, if needed. */
11957 115216 : for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
11958 : {
11959 68250 : rhs_p = gimple_omp_for_initial_ptr (stmt, i);
11960 68250 : if (TREE_CODE (*rhs_p) == TREE_VEC)
11961 : {
11962 639 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
11963 149 : TREE_VEC_ELT (*rhs_p, 1)
11964 298 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
11965 639 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
11966 161 : TREE_VEC_ELT (*rhs_p, 2)
11967 322 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
11968 : }
11969 67611 : else if (!is_gimple_min_invariant (*rhs_p))
11970 11465 : *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11971 56146 : else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
11972 4713 : recompute_tree_invariant_for_addr_expr (*rhs_p);
11973 :
11974 68250 : rhs_p = gimple_omp_for_final_ptr (stmt, i);
11975 68250 : if (TREE_CODE (*rhs_p) == TREE_VEC)
11976 : {
11977 519 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 1)))
11978 142 : TREE_VEC_ELT (*rhs_p, 1)
11979 284 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 1), &cnt_list);
11980 519 : if (!is_gimple_min_invariant (TREE_VEC_ELT (*rhs_p, 2)))
11981 157 : TREE_VEC_ELT (*rhs_p, 2)
11982 314 : = get_formal_tmp_var (TREE_VEC_ELT (*rhs_p, 2), &cnt_list);
11983 : }
11984 67731 : else if (!is_gimple_min_invariant (*rhs_p))
11985 16851 : *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11986 50880 : else if (TREE_CODE (*rhs_p) == ADDR_EXPR)
11987 4630 : recompute_tree_invariant_for_addr_expr (*rhs_p);
11988 :
11989 68250 : rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
11990 68250 : if (!is_gimple_min_invariant (*rhs_p))
11991 6318 : *rhs_p = get_formal_tmp_var (*rhs_p, &cnt_list);
11992 : }
11993 46966 : if (rclauses)
11994 227 : gimple_seq_add_seq (&tred_ilist, cnt_list);
11995 : else
11996 46739 : gimple_seq_add_seq (&body, cnt_list);
11997 :
11998 : /* Once lowered, extract the bounds and clauses. */
11999 46966 : omp_extract_for_data (stmt, &fd, NULL);
12000 :
12001 46966 : if (is_gimple_omp_oacc (ctx->stmt)
12002 46966 : && !ctx_in_oacc_kernels_region (ctx))
12003 9665 : lower_oacc_head_tail (gimple_location (stmt),
12004 : gimple_omp_for_clauses (stmt), private_marker,
12005 : &oacc_head, &oacc_tail, ctx);
12006 :
12007 : /* Add OpenACC partitioning and reduction markers just before the loop. */
12008 46966 : if (oacc_head)
12009 9665 : gimple_seq_add_seq (&body, oacc_head);
12010 :
12011 46966 : lower_omp_for_lastprivate (&fd, &body, &dlist, &clist, ctx);
12012 :
12013 46966 : if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
12014 85950 : for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
12015 70332 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
12016 70332 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
12017 : {
12018 227 : OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
12019 227 : if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
12020 42 : OMP_CLAUSE_LINEAR_STEP (c)
12021 84 : = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
12022 : ctx);
12023 : }
12024 :
12025 46596 : if ((ctx->scan_inclusive || ctx->scan_exclusive)
12026 47234 : && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
12027 177 : lower_omp_for_scan (&body, &dlist, stmt, &fd, ctx);
12028 : else
12029 : {
12030 46789 : gimple_seq_add_stmt (&body, stmt);
12031 46789 : gimple_seq_add_seq (&body, gimple_omp_body (stmt));
12032 : }
12033 :
12034 46966 : gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
12035 : fd.loop.v));
12036 :
12037 : /* After the loop, add exit clauses. */
12038 46966 : lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, &clist, ctx);
12039 :
12040 46966 : if (clist)
12041 : {
12042 179 : tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
12043 179 : gcall *g = gimple_build_call (fndecl, 0);
12044 179 : gimple_seq_add_stmt (&body, g);
12045 179 : gimple_seq_add_seq (&body, clist);
12046 179 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
12047 179 : g = gimple_build_call (fndecl, 0);
12048 179 : gimple_seq_add_stmt (&body, g);
12049 : }
12050 :
12051 46966 : if (ctx->cancellable)
12052 84 : gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
12053 :
12054 46966 : gimple_seq_add_seq (&body, dlist);
12055 :
12056 46966 : if (rclauses)
12057 : {
12058 227 : gimple_seq_add_seq (&tred_ilist, body);
12059 227 : body = tred_ilist;
12060 : }
12061 :
12062 46966 : body = maybe_catch_exception (body);
12063 :
12064 : /* Region exit marker goes at the end of the loop body. */
12065 46966 : gimple *g = gimple_build_omp_return (fd.have_nowait);
12066 46966 : gimple_seq_add_stmt (&body, g);
12067 :
12068 46966 : gimple_seq_add_seq (&body, tred_dlist);
12069 :
12070 46966 : maybe_add_implicit_barrier_cancel (ctx, g, &body);
12071 :
12072 46966 : if (rclauses)
12073 227 : OMP_CLAUSE_DECL (rclauses) = rtmp;
12074 :
12075 : /* Add OpenACC joining and reduction markers just after the loop. */
12076 46966 : if (oacc_tail)
12077 9665 : gimple_seq_add_seq (&body, oacc_tail);
12078 :
12079 46966 : pop_gimplify_context (new_stmt);
12080 :
12081 46966 : gimple_bind_append_vars (new_stmt, ctx->block_vars);
12082 46966 : maybe_remove_omp_member_access_dummy_vars (new_stmt);
12083 46966 : BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
12084 46966 : if (BLOCK_VARS (block))
12085 46323 : TREE_USED (block) = 1;
12086 :
12087 46966 : gimple_bind_set_body (new_stmt, body);
12088 46966 : gimple_omp_set_body (stmt, NULL);
12089 46966 : gimple_omp_for_set_pre_body (stmt, NULL);
12090 46966 : }
12091 :
12092 : /* Callback for walk_stmts. Check if the current statement only contains
12093 : GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
12094 :
12095 : static tree
12096 214603 : check_combined_parallel (gimple_stmt_iterator *gsi_p,
12097 : bool *handled_ops_p,
12098 : struct walk_stmt_info *wi)
12099 : {
12100 214603 : int *info = (int *) wi->info;
12101 214603 : gimple *stmt = gsi_stmt (*gsi_p);
12102 :
12103 214603 : *handled_ops_p = true;
12104 214603 : switch (gimple_code (stmt))
12105 : {
12106 11697 : WALK_SUBSTMTS;
12107 :
12108 : case GIMPLE_DEBUG:
12109 : break;
12110 1910 : case GIMPLE_OMP_FOR:
12111 1910 : case GIMPLE_OMP_SECTIONS:
12112 1910 : *info = *info == 0 ? 1 : -1;
12113 1910 : break;
12114 200957 : default:
12115 200957 : *info = -1;
12116 200957 : break;
12117 : }
12118 214603 : return NULL;
12119 : }
12120 :
12121 : struct omp_taskcopy_context
12122 : {
12123 : /* This field must be at the beginning, as we do "inheritance": Some
12124 : callback functions for tree-inline.cc (e.g., omp_copy_decl)
12125 : receive a copy_body_data pointer that is up-casted to an
12126 : omp_context pointer. */
12127 : copy_body_data cb;
12128 : omp_context *ctx;
12129 : };
12130 :
12131 : static tree
12132 366 : task_copyfn_copy_decl (tree var, copy_body_data *cb)
12133 : {
12134 366 : struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
12135 :
12136 366 : if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
12137 158 : return create_tmp_var (TREE_TYPE (var));
12138 :
12139 : return var;
12140 : }
12141 :
12142 : static tree
12143 50 : task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
12144 : {
12145 50 : tree name, new_fields = NULL, type, f;
12146 :
12147 50 : type = lang_hooks.types.make_type (RECORD_TYPE);
12148 50 : name = DECL_NAME (TYPE_NAME (orig_type));
12149 50 : name = build_decl (gimple_location (tcctx->ctx->stmt),
12150 : TYPE_DECL, name, type);
12151 50 : TYPE_NAME (type) = name;
12152 :
12153 1140 : for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
12154 : {
12155 1090 : tree new_f = copy_node (f);
12156 1090 : DECL_CONTEXT (new_f) = type;
12157 1090 : TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
12158 1090 : TREE_CHAIN (new_f) = new_fields;
12159 1090 : walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
12160 1090 : walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
12161 1090 : walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
12162 : &tcctx->cb, NULL);
12163 1090 : new_fields = new_f;
12164 1090 : tcctx->cb.decl_map->put (f, new_f);
12165 : }
12166 50 : TYPE_FIELDS (type) = nreverse (new_fields);
12167 50 : layout_type (type);
12168 50 : return type;
12169 : }
12170 :
12171 : /* Create task copyfn. */
12172 :
12173 : static void
12174 504 : create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
12175 : {
12176 504 : struct function *child_cfun;
12177 504 : tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
12178 504 : tree record_type, srecord_type, bind, list;
12179 504 : bool record_needs_remap = false, srecord_needs_remap = false;
12180 504 : splay_tree_node n;
12181 504 : struct omp_taskcopy_context tcctx;
12182 504 : location_t loc = gimple_location (task_stmt);
12183 504 : size_t looptempno = 0;
12184 :
12185 504 : child_fn = gimple_omp_task_copy_fn (task_stmt);
12186 504 : task_cpyfns.safe_push (task_stmt);
12187 504 : child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12188 504 : gcc_assert (child_cfun->cfg == NULL);
12189 504 : DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
12190 :
12191 : /* Reset DECL_CONTEXT on function arguments. */
12192 1512 : for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12193 1008 : DECL_CONTEXT (t) = child_fn;
12194 :
12195 : /* Populate the function. */
12196 504 : push_gimplify_context ();
12197 504 : push_cfun (child_cfun);
12198 :
12199 504 : bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
12200 504 : TREE_SIDE_EFFECTS (bind) = 1;
12201 504 : list = NULL;
12202 504 : DECL_SAVED_TREE (child_fn) = bind;
12203 504 : DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
12204 :
12205 : /* Remap src and dst argument types if needed. */
12206 504 : record_type = ctx->record_type;
12207 504 : srecord_type = ctx->srecord_type;
12208 3102 : for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
12209 2623 : if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
12210 : {
12211 : record_needs_remap = true;
12212 : break;
12213 : }
12214 2841 : for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
12215 2362 : if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
12216 : {
12217 : srecord_needs_remap = true;
12218 : break;
12219 : }
12220 :
12221 504 : if (record_needs_remap || srecord_needs_remap)
12222 : {
12223 25 : memset (&tcctx, '\0', sizeof (tcctx));
12224 25 : tcctx.cb.src_fn = ctx->cb.src_fn;
12225 25 : tcctx.cb.dst_fn = child_fn;
12226 25 : tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
12227 25 : gcc_checking_assert (tcctx.cb.src_node);
12228 25 : tcctx.cb.dst_node = tcctx.cb.src_node;
12229 25 : tcctx.cb.src_cfun = ctx->cb.src_cfun;
12230 25 : tcctx.cb.copy_decl = task_copyfn_copy_decl;
12231 25 : tcctx.cb.eh_lp_nr = 0;
12232 25 : tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
12233 25 : tcctx.cb.decl_map = new hash_map<tree, tree>;
12234 25 : tcctx.ctx = ctx;
12235 :
12236 25 : if (record_needs_remap)
12237 25 : record_type = task_copyfn_remap_type (&tcctx, record_type);
12238 25 : if (srecord_needs_remap)
12239 25 : srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
12240 : }
12241 : else
12242 479 : tcctx.cb.decl_map = NULL;
12243 :
12244 504 : arg = DECL_ARGUMENTS (child_fn);
12245 504 : TREE_TYPE (arg) = build_pointer_type (record_type);
12246 504 : sarg = DECL_CHAIN (arg);
12247 504 : TREE_TYPE (sarg) = build_pointer_type (srecord_type);
12248 :
12249 : /* First pass: initialize temporaries used in record_type and srecord_type
12250 : sizes and field offsets. */
12251 504 : if (tcctx.cb.decl_map)
12252 631 : for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12253 606 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
12254 : {
12255 497 : tree *p;
12256 :
12257 497 : decl = OMP_CLAUSE_DECL (c);
12258 497 : p = tcctx.cb.decl_map->get (decl);
12259 497 : if (p == NULL)
12260 339 : continue;
12261 158 : n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12262 158 : sf = (tree) n->value;
12263 158 : sf = *tcctx.cb.decl_map->get (sf);
12264 158 : src = build_simple_mem_ref_loc (loc, sarg);
12265 158 : src = omp_build_component_ref (src, sf);
12266 158 : t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
12267 158 : append_to_statement_list (t, &list);
12268 : }
12269 :
12270 : /* Second pass: copy shared var pointers and copy construct non-VLA
12271 : firstprivate vars. */
12272 5850 : for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12273 5346 : switch (OMP_CLAUSE_CODE (c))
12274 : {
12275 583 : splay_tree_key key;
12276 583 : case OMP_CLAUSE_SHARED:
12277 583 : decl = OMP_CLAUSE_DECL (c);
12278 583 : key = (splay_tree_key) decl;
12279 583 : if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
12280 273 : key = (splay_tree_key) &DECL_UID (decl);
12281 583 : n = splay_tree_lookup (ctx->field_map, key);
12282 583 : if (n == NULL)
12283 : break;
12284 149 : f = (tree) n->value;
12285 149 : if (tcctx.cb.decl_map)
12286 12 : f = *tcctx.cb.decl_map->get (f);
12287 149 : n = splay_tree_lookup (ctx->sfield_map, key);
12288 149 : sf = (tree) n->value;
12289 149 : if (tcctx.cb.decl_map)
12290 12 : sf = *tcctx.cb.decl_map->get (sf);
12291 149 : src = build_simple_mem_ref_loc (loc, sarg);
12292 149 : src = omp_build_component_ref (src, sf);
12293 149 : dst = build_simple_mem_ref_loc (loc, arg);
12294 149 : dst = omp_build_component_ref (dst, f);
12295 149 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12296 149 : append_to_statement_list (t, &list);
12297 149 : break;
12298 460 : case OMP_CLAUSE_REDUCTION:
12299 460 : case OMP_CLAUSE_IN_REDUCTION:
12300 460 : decl = OMP_CLAUSE_DECL (c);
12301 460 : if (TREE_CODE (decl) == MEM_REF)
12302 : {
12303 160 : decl = TREE_OPERAND (decl, 0);
12304 160 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
12305 38 : decl = TREE_OPERAND (decl, 0);
12306 160 : if (TREE_CODE (decl) == INDIRECT_REF
12307 128 : || TREE_CODE (decl) == ADDR_EXPR)
12308 95 : decl = TREE_OPERAND (decl, 0);
12309 : }
12310 460 : key = (splay_tree_key) decl;
12311 460 : n = splay_tree_lookup (ctx->field_map, key);
12312 460 : if (n == NULL)
12313 : break;
12314 101 : f = (tree) n->value;
12315 101 : if (tcctx.cb.decl_map)
12316 20 : f = *tcctx.cb.decl_map->get (f);
12317 101 : n = splay_tree_lookup (ctx->sfield_map, key);
12318 101 : sf = (tree) n->value;
12319 101 : if (tcctx.cb.decl_map)
12320 20 : sf = *tcctx.cb.decl_map->get (sf);
12321 101 : src = build_simple_mem_ref_loc (loc, sarg);
12322 101 : src = omp_build_component_ref (src, sf);
12323 101 : if (decl != OMP_CLAUSE_DECL (c)
12324 95 : && TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12325 173 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12326 32 : src = build_simple_mem_ref_loc (loc, src);
12327 101 : dst = build_simple_mem_ref_loc (loc, arg);
12328 101 : dst = omp_build_component_ref (dst, f);
12329 101 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12330 101 : append_to_statement_list (t, &list);
12331 101 : break;
12332 754 : case OMP_CLAUSE__LOOPTEMP_:
12333 : /* Fields for first two _looptemp_ clauses are initialized by
12334 : GOMP_taskloop*, the rest are handled like firstprivate. */
12335 754 : if (looptempno < 2)
12336 : {
12337 748 : looptempno++;
12338 748 : break;
12339 : }
12340 : /* FALLTHRU */
12341 1731 : case OMP_CLAUSE__REDUCTEMP_:
12342 1731 : case OMP_CLAUSE_FIRSTPRIVATE:
12343 1731 : decl = OMP_CLAUSE_DECL (c);
12344 1731 : if (is_variable_sized (decl))
12345 : break;
12346 1717 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12347 1717 : if (n == NULL)
12348 : break;
12349 1717 : f = (tree) n->value;
12350 1717 : if (tcctx.cb.decl_map)
12351 490 : f = *tcctx.cb.decl_map->get (f);
12352 1717 : n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12353 1717 : if (n != NULL)
12354 : {
12355 1467 : sf = (tree) n->value;
12356 1467 : if (tcctx.cb.decl_map)
12357 490 : sf = *tcctx.cb.decl_map->get (sf);
12358 1467 : src = build_simple_mem_ref_loc (loc, sarg);
12359 1467 : src = omp_build_component_ref (src, sf);
12360 1467 : if (use_pointer_for_field (decl, NULL)
12361 1467 : || omp_privatize_by_reference (decl))
12362 317 : src = build_simple_mem_ref_loc (loc, src);
12363 : }
12364 : else
12365 : src = decl;
12366 1717 : dst = build_simple_mem_ref_loc (loc, arg);
12367 1717 : dst = omp_build_component_ref (dst, f);
12368 1717 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
12369 192 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12370 : else
12371 : {
12372 1525 : if (ctx->allocate_map)
12373 84 : if (tree *allocatorp = ctx->allocate_map->get (decl))
12374 : {
12375 50 : tree allocator = *allocatorp;
12376 50 : HOST_WIDE_INT ialign = 0;
12377 50 : if (TREE_CODE (allocator) == TREE_LIST)
12378 : {
12379 4 : ialign = tree_to_uhwi (TREE_VALUE (allocator));
12380 4 : allocator = TREE_PURPOSE (allocator);
12381 : }
12382 50 : if (TREE_CODE (allocator) != INTEGER_CST)
12383 : {
12384 22 : n = splay_tree_lookup (ctx->sfield_map,
12385 : (splay_tree_key) allocator);
12386 22 : allocator = (tree) n->value;
12387 22 : if (tcctx.cb.decl_map)
12388 0 : allocator = *tcctx.cb.decl_map->get (allocator);
12389 22 : tree a = build_simple_mem_ref_loc (loc, sarg);
12390 22 : allocator = omp_build_component_ref (a, allocator);
12391 : }
12392 50 : allocator = fold_convert (pointer_sized_int_node, allocator);
12393 50 : tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
12394 50 : tree align = build_int_cst (size_type_node,
12395 50 : MAX (ialign,
12396 : DECL_ALIGN_UNIT (decl)));
12397 50 : tree sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dst)));
12398 50 : tree ptr = build_call_expr_loc (loc, a, 3, align, sz,
12399 : allocator);
12400 50 : ptr = fold_convert (TREE_TYPE (dst), ptr);
12401 50 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, ptr);
12402 50 : append_to_statement_list (t, &list);
12403 50 : dst = build_simple_mem_ref_loc (loc, dst);
12404 : }
12405 1525 : t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
12406 : }
12407 1717 : append_to_statement_list (t, &list);
12408 1717 : break;
12409 489 : case OMP_CLAUSE_PRIVATE:
12410 489 : if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
12411 : break;
12412 12 : decl = OMP_CLAUSE_DECL (c);
12413 12 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12414 12 : f = (tree) n->value;
12415 12 : if (tcctx.cb.decl_map)
12416 0 : f = *tcctx.cb.decl_map->get (f);
12417 12 : n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
12418 12 : if (n != NULL)
12419 : {
12420 12 : sf = (tree) n->value;
12421 12 : if (tcctx.cb.decl_map)
12422 0 : sf = *tcctx.cb.decl_map->get (sf);
12423 12 : src = build_simple_mem_ref_loc (loc, sarg);
12424 12 : src = omp_build_component_ref (src, sf);
12425 12 : if (use_pointer_for_field (decl, NULL))
12426 12 : src = build_simple_mem_ref_loc (loc, src);
12427 : }
12428 : else
12429 : src = decl;
12430 12 : dst = build_simple_mem_ref_loc (loc, arg);
12431 12 : dst = omp_build_component_ref (dst, f);
12432 12 : t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
12433 12 : append_to_statement_list (t, &list);
12434 12 : break;
12435 : default:
12436 : break;
12437 : }
12438 :
12439 : /* Last pass: handle VLA firstprivates. */
12440 504 : if (tcctx.cb.decl_map)
12441 631 : for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
12442 606 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
12443 : {
12444 497 : tree ind, ptr, df;
12445 :
12446 497 : decl = OMP_CLAUSE_DECL (c);
12447 497 : if (!is_variable_sized (decl))
12448 483 : continue;
12449 14 : n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
12450 14 : if (n == NULL)
12451 0 : continue;
12452 14 : f = (tree) n->value;
12453 14 : f = *tcctx.cb.decl_map->get (f);
12454 14 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
12455 14 : ind = DECL_VALUE_EXPR (decl);
12456 14 : gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
12457 14 : gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
12458 42 : n = splay_tree_lookup (ctx->sfield_map,
12459 14 : (splay_tree_key) TREE_OPERAND (ind, 0));
12460 14 : sf = (tree) n->value;
12461 14 : sf = *tcctx.cb.decl_map->get (sf);
12462 14 : src = build_simple_mem_ref_loc (loc, sarg);
12463 14 : src = omp_build_component_ref (src, sf);
12464 14 : src = build_simple_mem_ref_loc (loc, src);
12465 14 : dst = build_simple_mem_ref_loc (loc, arg);
12466 14 : dst = omp_build_component_ref (dst, f);
12467 14 : t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
12468 14 : append_to_statement_list (t, &list);
12469 42 : n = splay_tree_lookup (ctx->field_map,
12470 14 : (splay_tree_key) TREE_OPERAND (ind, 0));
12471 14 : df = (tree) n->value;
12472 14 : df = *tcctx.cb.decl_map->get (df);
12473 14 : ptr = build_simple_mem_ref_loc (loc, arg);
12474 14 : ptr = omp_build_component_ref (ptr, df);
12475 14 : t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
12476 : build_fold_addr_expr_loc (loc, dst));
12477 14 : append_to_statement_list (t, &list);
12478 : }
12479 :
12480 504 : t = build1 (RETURN_EXPR, void_type_node, NULL);
12481 504 : append_to_statement_list (t, &list);
12482 :
12483 504 : if (tcctx.cb.decl_map)
12484 25 : delete tcctx.cb.decl_map;
12485 504 : pop_gimplify_context (NULL);
12486 504 : BIND_EXPR_BODY (bind) = list;
12487 504 : pop_cfun ();
12488 504 : }
12489 :
12490 : static void
12491 1553 : lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
12492 : {
12493 1553 : tree c, clauses;
12494 1553 : gimple *g;
12495 1553 : size_t cnt[5] = { 0, 0, 0, 0, 0 }, idx = 2, i;
12496 :
12497 1553 : clauses = omp_find_clause (*pclauses, OMP_CLAUSE_DEPEND);
12498 1553 : gcc_assert (clauses);
12499 6314 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12500 4886 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
12501 1713 : switch (OMP_CLAUSE_DEPEND_KIND (c))
12502 : {
12503 125 : case OMP_CLAUSE_DEPEND_LAST:
12504 : /* Lowering already done at gimplification. */
12505 125 : return;
12506 481 : case OMP_CLAUSE_DEPEND_IN:
12507 481 : cnt[2]++;
12508 481 : break;
12509 969 : case OMP_CLAUSE_DEPEND_OUT:
12510 969 : case OMP_CLAUSE_DEPEND_INOUT:
12511 969 : cnt[0]++;
12512 969 : break;
12513 30 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
12514 30 : cnt[1]++;
12515 30 : break;
12516 76 : case OMP_CLAUSE_DEPEND_DEPOBJ:
12517 76 : cnt[3]++;
12518 76 : break;
12519 32 : case OMP_CLAUSE_DEPEND_INOUTSET:
12520 32 : cnt[4]++;
12521 32 : break;
12522 0 : default:
12523 0 : gcc_unreachable ();
12524 : }
12525 1428 : if (cnt[1] || cnt[3] || cnt[4])
12526 135 : idx = 5;
12527 1428 : size_t total = cnt[0] + cnt[1] + cnt[2] + cnt[3] + cnt[4];
12528 1428 : size_t inoutidx = total + idx;
12529 1428 : tree type = build_array_type_nelts (ptr_type_node, total + idx + 2 * cnt[4]);
12530 1428 : tree array = create_tmp_var (type);
12531 1428 : TREE_ADDRESSABLE (array) = 1;
12532 1428 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
12533 : NULL_TREE);
12534 1428 : if (idx == 5)
12535 : {
12536 135 : g = gimple_build_assign (r, build_int_cst (ptr_type_node, 0));
12537 135 : gimple_seq_add_stmt (iseq, g);
12538 135 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
12539 : NULL_TREE);
12540 : }
12541 1428 : g = gimple_build_assign (r, build_int_cst (ptr_type_node, total));
12542 1428 : gimple_seq_add_stmt (iseq, g);
12543 7140 : for (i = 0; i < (idx == 5 ? 3 : 1); i++)
12544 : {
12545 1698 : r = build4 (ARRAY_REF, ptr_type_node, array,
12546 1698 : size_int (i + 1 + (idx == 5)), NULL_TREE, NULL_TREE);
12547 1698 : g = gimple_build_assign (r, build_int_cst (ptr_type_node, cnt[i]));
12548 1698 : gimple_seq_add_stmt (iseq, g);
12549 : }
12550 8568 : for (i = 0; i < 5; i++)
12551 : {
12552 7140 : if (cnt[i] == 0)
12553 5656 : continue;
12554 6563 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12555 5079 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
12556 3352 : continue;
12557 : else
12558 : {
12559 1727 : switch (OMP_CLAUSE_DEPEND_KIND (c))
12560 : {
12561 547 : case OMP_CLAUSE_DEPEND_IN:
12562 547 : if (i != 2)
12563 139 : continue;
12564 : break;
12565 1025 : case OMP_CLAUSE_DEPEND_OUT:
12566 1025 : case OMP_CLAUSE_DEPEND_INOUT:
12567 1025 : if (i != 0)
12568 56 : continue;
12569 : break;
12570 44 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
12571 44 : if (i != 1)
12572 14 : continue;
12573 : break;
12574 79 : case OMP_CLAUSE_DEPEND_DEPOBJ:
12575 79 : if (i != 3)
12576 3 : continue;
12577 : break;
12578 32 : case OMP_CLAUSE_DEPEND_INOUTSET:
12579 32 : if (i != 4)
12580 0 : continue;
12581 : break;
12582 0 : default:
12583 0 : gcc_unreachable ();
12584 : }
12585 1588 : tree t = OMP_CLAUSE_DECL (c);
12586 1588 : if (i == 4)
12587 : {
12588 32 : t = build4 (ARRAY_REF, ptr_type_node, array,
12589 32 : size_int (inoutidx), NULL_TREE, NULL_TREE);
12590 32 : t = build_fold_addr_expr (t);
12591 32 : inoutidx += 2;
12592 : }
12593 1588 : t = fold_convert (ptr_type_node, t);
12594 1588 : gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
12595 1588 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
12596 : NULL_TREE, NULL_TREE);
12597 1588 : g = gimple_build_assign (r, t);
12598 1588 : gimple_seq_add_stmt (iseq, g);
12599 : }
12600 : }
12601 1428 : if (cnt[4])
12602 81 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12603 49 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
12604 49 : && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_INOUTSET)
12605 : {
12606 32 : tree t = OMP_CLAUSE_DECL (c);
12607 32 : t = fold_convert (ptr_type_node, t);
12608 32 : gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
12609 32 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
12610 : NULL_TREE, NULL_TREE);
12611 32 : g = gimple_build_assign (r, t);
12612 32 : gimple_seq_add_stmt (iseq, g);
12613 32 : t = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
12614 32 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
12615 : NULL_TREE, NULL_TREE);
12616 32 : g = gimple_build_assign (r, t);
12617 32 : gimple_seq_add_stmt (iseq, g);
12618 : }
12619 :
12620 1428 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
12621 1428 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
12622 1428 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
12623 1428 : OMP_CLAUSE_CHAIN (c) = *pclauses;
12624 1428 : *pclauses = c;
12625 1428 : tree clobber = build_clobber (type);
12626 1428 : g = gimple_build_assign (array, clobber);
12627 1428 : gimple_seq_add_stmt (oseq, g);
12628 : }
12629 :
12630 : /* Lower the OpenMP parallel or task directive in the current statement
12631 : in GSI_P. CTX holds context information for the directive. */
12632 :
12633 : static void
12634 22570 : lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12635 : {
12636 22570 : tree clauses;
12637 22570 : tree child_fn, t;
12638 22570 : gimple *stmt = gsi_stmt (*gsi_p);
12639 22570 : gbind *par_bind, *bind, *dep_bind = NULL;
12640 22570 : gimple_seq par_body;
12641 22570 : location_t loc = gimple_location (stmt);
12642 :
12643 22570 : clauses = gimple_omp_taskreg_clauses (stmt);
12644 22570 : if (gimple_code (stmt) == GIMPLE_OMP_TASK
12645 22570 : && gimple_omp_task_taskwait_p (stmt))
12646 : {
12647 84 : par_bind = NULL;
12648 84 : par_body = NULL;
12649 : }
12650 : else
12651 : {
12652 22486 : par_bind
12653 22486 : = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
12654 22486 : par_body = gimple_bind_body (par_bind);
12655 : }
12656 22570 : child_fn = ctx->cb.dst_fn;
12657 22570 : if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
12658 22570 : && !gimple_omp_parallel_combined_p (stmt))
12659 : {
12660 4257 : struct walk_stmt_info wi;
12661 4257 : int ws_num = 0;
12662 :
12663 4257 : memset (&wi, 0, sizeof (wi));
12664 4257 : wi.info = &ws_num;
12665 4257 : wi.val_only = true;
12666 4257 : walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
12667 4257 : if (ws_num == 1)
12668 386 : gimple_omp_parallel_set_combined_p (stmt, true);
12669 : }
12670 22570 : gimple_seq dep_ilist = NULL;
12671 22570 : gimple_seq dep_olist = NULL;
12672 22570 : if (gimple_code (stmt) == GIMPLE_OMP_TASK
12673 22570 : && omp_find_clause (clauses, OMP_CLAUSE_DEPEND))
12674 : {
12675 1189 : push_gimplify_context ();
12676 1189 : dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12677 1189 : lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
12678 : &dep_ilist, &dep_olist);
12679 : }
12680 :
12681 22570 : if (gimple_code (stmt) == GIMPLE_OMP_TASK
12682 22570 : && gimple_omp_task_taskwait_p (stmt))
12683 : {
12684 84 : if (dep_bind)
12685 : {
12686 84 : gsi_replace (gsi_p, dep_bind, true);
12687 84 : gimple_bind_add_seq (dep_bind, dep_ilist);
12688 84 : gimple_bind_add_stmt (dep_bind, stmt);
12689 84 : gimple_bind_add_seq (dep_bind, dep_olist);
12690 84 : pop_gimplify_context (dep_bind);
12691 : }
12692 84 : return;
12693 : }
12694 :
12695 22486 : if (ctx->srecord_type)
12696 504 : create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
12697 :
12698 22486 : gimple_seq tskred_ilist = NULL;
12699 22486 : gimple_seq tskred_olist = NULL;
12700 22486 : if ((is_task_ctx (ctx)
12701 3778 : && gimple_omp_task_taskloop_p (ctx->stmt)
12702 1330 : && omp_find_clause (gimple_omp_task_clauses (ctx->stmt),
12703 : OMP_CLAUSE_REDUCTION))
12704 25767 : || (is_parallel_ctx (ctx)
12705 16174 : && omp_find_clause (gimple_omp_parallel_clauses (stmt),
12706 : OMP_CLAUSE__REDUCTEMP_)))
12707 : {
12708 557 : if (dep_bind == NULL)
12709 : {
12710 557 : push_gimplify_context ();
12711 557 : dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12712 : }
12713 617 : lower_omp_task_reductions (ctx, is_task_ctx (ctx) ? OMP_TASKLOOP
12714 : : OMP_PARALLEL,
12715 557 : gimple_omp_taskreg_clauses (ctx->stmt),
12716 : &tskred_ilist, &tskred_olist);
12717 : }
12718 :
12719 22486 : push_gimplify_context ();
12720 :
12721 22486 : gimple_seq par_olist = NULL;
12722 22486 : gimple_seq par_ilist = NULL;
12723 22486 : gimple_seq par_rlist = NULL;
12724 22486 : lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
12725 22482 : lower_omp (&par_body, ctx);
12726 22482 : if (gimple_code (stmt) != GIMPLE_OMP_TASK)
12727 18704 : lower_reduction_clauses (clauses, &par_rlist, NULL, ctx);
12728 :
12729 : /* Declare all the variables created by mapping and the variables
12730 : declared in the scope of the parallel body. */
12731 22482 : record_vars_into (ctx->block_vars, child_fn);
12732 22482 : maybe_remove_omp_member_access_dummy_vars (par_bind);
12733 22482 : record_vars_into (gimple_bind_vars (par_bind), child_fn);
12734 :
12735 22482 : if (ctx->record_type)
12736 : {
12737 18018 : ctx->sender_decl
12738 35532 : = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
12739 : : ctx->record_type, ".omp_data_o");
12740 18018 : DECL_NAMELESS (ctx->sender_decl) = 1;
12741 18018 : TREE_ADDRESSABLE (ctx->sender_decl) = 1;
12742 18018 : gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
12743 : }
12744 :
12745 22482 : gimple_seq olist = NULL;
12746 22482 : gimple_seq ilist = NULL;
12747 22482 : lower_send_clauses (clauses, &ilist, &olist, ctx);
12748 22482 : lower_send_shared_vars (&ilist, &olist, ctx);
12749 :
12750 22482 : if (ctx->record_type)
12751 : {
12752 18018 : tree clobber = build_clobber (TREE_TYPE (ctx->sender_decl));
12753 18018 : gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
12754 : clobber));
12755 : }
12756 :
12757 : /* Once all the expansions are done, sequence all the different
12758 : fragments inside gimple_omp_body. */
12759 :
12760 22482 : gimple_seq new_body = NULL;
12761 :
12762 22482 : if (ctx->record_type)
12763 : {
12764 18018 : t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
12765 : /* fixup_child_record_type might have changed receiver_decl's type. */
12766 18018 : t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
12767 18018 : gimple_seq_add_stmt (&new_body,
12768 18018 : gimple_build_assign (ctx->receiver_decl, t));
12769 : }
12770 :
12771 22482 : gimple_seq_add_seq (&new_body, par_ilist);
12772 22482 : gimple_seq_add_seq (&new_body, par_body);
12773 22482 : gimple_seq_add_seq (&new_body, par_rlist);
12774 22482 : if (ctx->cancellable)
12775 135 : gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
12776 22482 : gimple_seq_add_seq (&new_body, par_olist);
12777 22482 : new_body = maybe_catch_exception (new_body);
12778 22482 : if (gimple_code (stmt) == GIMPLE_OMP_TASK)
12779 3778 : gimple_seq_add_stmt (&new_body,
12780 3778 : gimple_build_omp_continue (integer_zero_node,
12781 : integer_zero_node));
12782 22482 : gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
12783 22482 : gimple_omp_set_body (stmt, new_body);
12784 :
12785 22482 : if (dep_bind && gimple_bind_block (par_bind) == NULL_TREE)
12786 497 : bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12787 : else
12788 21985 : bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
12789 43302 : gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
12790 22482 : gimple_bind_add_seq (bind, ilist);
12791 22482 : gimple_bind_add_stmt (bind, stmt);
12792 22482 : gimple_bind_add_seq (bind, olist);
12793 :
12794 22482 : pop_gimplify_context (NULL);
12795 :
12796 22482 : if (dep_bind)
12797 : {
12798 1662 : gimple_bind_add_seq (dep_bind, dep_ilist);
12799 1662 : gimple_bind_add_seq (dep_bind, tskred_ilist);
12800 1662 : gimple_bind_add_stmt (dep_bind, bind);
12801 1662 : gimple_bind_add_seq (dep_bind, tskred_olist);
12802 1662 : gimple_bind_add_seq (dep_bind, dep_olist);
12803 1662 : pop_gimplify_context (dep_bind);
12804 : }
12805 : }
12806 :
12807 : /* Set EXPR as the hostaddr expression that should result from the clause C
12808 : in the target statement STMT. Returns the tree that should be
12809 : passed as the hostaddr (a pointer to the array containing the expanded
12810 : hostaddrs and sizes of the clause). */
12811 :
12812 : static tree
12813 37312 : lower_omp_map_iterator_expr (tree expr, tree c, gomp_target *stmt)
12814 : {
12815 37312 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
12816 : return expr;
12817 :
12818 215 : tree iterator = OMP_CLAUSE_ITERATORS (c);
12819 215 : tree index = OMP_ITERATOR_INDEX (iterator);
12820 215 : tree elems = OMP_ITERATOR_ELEMS (iterator);
12821 215 : gimple_seq *loop_body_p = enter_omp_iterator_loop_context (c, stmt);
12822 :
12823 : /* IN LOOP BODY: */
12824 : /* elems[idx] = <expr>; */
12825 215 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, index,
12826 : NULL_TREE, NULL_TREE);
12827 215 : tree mod_expr = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
12828 : void_type_node, lhs, expr);
12829 215 : gimplify_and_add (mod_expr, loop_body_p);
12830 215 : exit_omp_iterator_loop_context (c);
12831 :
12832 215 : return build_fold_addr_expr_with_type (elems, ptr_type_node);
12833 : }
12834 :
12835 : /* Set SIZE as the size expression that should result from the clause C
12836 : in the target statement STMT. Returns the tree that should be
12837 : passed as the clause size (a size_int with the value SIZE_MAX, indicating
12838 : that the clause uses an iterator). */
12839 :
12840 : static tree
12841 80146 : lower_omp_map_iterator_size (tree size, tree c, gomp_target *stmt)
12842 : {
12843 80146 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
12844 : return size;
12845 :
12846 219 : tree iterator = OMP_CLAUSE_ITERATORS (c);
12847 219 : tree index = OMP_ITERATOR_INDEX (iterator);
12848 219 : tree elems = OMP_ITERATOR_ELEMS (iterator);
12849 219 : gimple_seq *loop_body_p = enter_omp_iterator_loop_context (c, stmt);
12850 :
12851 : /* IN LOOP BODY: */
12852 : /* elems[idx+1] = <size>; */
12853 219 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems,
12854 : size_binop (PLUS_EXPR, index, size_int (1)),
12855 : NULL_TREE, NULL_TREE);
12856 219 : tree mod_expr = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
12857 : void_type_node, lhs, size);
12858 219 : gimplify_and_add (mod_expr, loop_body_p);
12859 219 : exit_omp_iterator_loop_context (c);
12860 :
12861 219 : return size_int (SIZE_MAX);
12862 : }
12863 :
12864 : /* Lower the GIMPLE_OMP_TARGET in the current statement
12865 : in GSI_P. CTX holds context information for the directive. */
12866 :
12867 : static void
12868 37170 : lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12869 : {
12870 37170 : tree clauses;
12871 37170 : tree child_fn, t, c;
12872 37170 : gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
12873 37170 : gbind *tgt_bind, *bind, *dep_bind = NULL;
12874 37170 : gimple_seq tgt_body, olist, ilist, fplist, new_body;
12875 37170 : location_t loc = gimple_location (stmt);
12876 37170 : bool offloaded, data_region;
12877 37170 : unsigned int map_cnt = 0;
12878 37170 : tree in_reduction_clauses = NULL_TREE;
12879 :
12880 37170 : tree deep_map_cnt = NULL_TREE;
12881 37170 : tree deep_map_data = NULL_TREE;
12882 37170 : tree deep_map_offset_data = NULL_TREE;
12883 37170 : tree deep_map_offset = NULL_TREE;
12884 :
12885 37170 : offloaded = is_gimple_omp_offloaded (stmt);
12886 37170 : switch (gimple_omp_target_kind (stmt))
12887 : {
12888 11815 : case GF_OMP_TARGET_KIND_REGION:
12889 11815 : tree *p, *q;
12890 11815 : q = &in_reduction_clauses;
12891 79451 : for (p = gimple_omp_target_clauses_ptr (stmt); *p; )
12892 67636 : if (OMP_CLAUSE_CODE (*p) == OMP_CLAUSE_IN_REDUCTION)
12893 : {
12894 422 : *q = *p;
12895 422 : q = &OMP_CLAUSE_CHAIN (*q);
12896 422 : *p = OMP_CLAUSE_CHAIN (*p);
12897 : }
12898 : else
12899 67214 : p = &OMP_CLAUSE_CHAIN (*p);
12900 11815 : *q = NULL_TREE;
12901 11815 : *p = in_reduction_clauses;
12902 : /* FALLTHRU */
12903 : case GF_OMP_TARGET_KIND_UPDATE:
12904 : case GF_OMP_TARGET_KIND_ENTER_DATA:
12905 : case GF_OMP_TARGET_KIND_EXIT_DATA:
12906 : case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12907 : case GF_OMP_TARGET_KIND_OACC_KERNELS:
12908 : case GF_OMP_TARGET_KIND_OACC_SERIAL:
12909 : case GF_OMP_TARGET_KIND_OACC_UPDATE:
12910 : case GF_OMP_TARGET_KIND_OACC_ENTER_DATA:
12911 : case GF_OMP_TARGET_KIND_OACC_EXIT_DATA:
12912 : case GF_OMP_TARGET_KIND_OACC_DECLARE:
12913 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_PARALLELIZED:
12914 : case GF_OMP_TARGET_KIND_OACC_PARALLEL_KERNELS_GANG_SINGLE:
12915 : data_region = false;
12916 : break;
12917 : case GF_OMP_TARGET_KIND_DATA:
12918 : case GF_OMP_TARGET_KIND_OACC_DATA:
12919 : case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12920 : case GF_OMP_TARGET_KIND_OACC_DATA_KERNELS:
12921 : data_region = true;
12922 : break;
12923 0 : default:
12924 0 : gcc_unreachable ();
12925 : }
12926 :
12927 : /* Ensure that requires map is written via output_offload_tables, even if only
12928 : 'target (enter/exit) data' is used in the translation unit. */
12929 37170 : if (ENABLE_OFFLOADING && (omp_requires_mask & OMP_REQUIRES_TARGET_USED))
12930 : g->have_offload = true;
12931 :
12932 37170 : clauses = gimple_omp_target_clauses (stmt);
12933 :
12934 37170 : gimple_seq dep_ilist = NULL;
12935 37170 : gimple_seq dep_olist = NULL;
12936 37170 : bool has_depend = omp_find_clause (clauses, OMP_CLAUSE_DEPEND) != NULL_TREE;
12937 37170 : if (has_depend || in_reduction_clauses)
12938 : {
12939 392 : push_gimplify_context ();
12940 392 : dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
12941 392 : if (has_depend)
12942 329 : lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
12943 : &dep_ilist, &dep_olist);
12944 392 : if (in_reduction_clauses)
12945 314 : lower_rec_input_clauses (in_reduction_clauses, &dep_ilist, &dep_olist,
12946 : ctx, NULL);
12947 : }
12948 :
12949 37170 : tgt_bind = NULL;
12950 37170 : tgt_body = NULL;
12951 37170 : if (offloaded)
12952 : {
12953 21210 : tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
12954 21210 : tgt_body = gimple_bind_body (tgt_bind);
12955 : }
12956 15960 : else if (data_region)
12957 4021 : tgt_body = gimple_omp_body (stmt);
12958 37170 : child_fn = ctx->cb.dst_fn;
12959 :
12960 37170 : push_gimplify_context ();
12961 37170 : fplist = NULL;
12962 :
12963 37170 : ilist = NULL;
12964 37170 : olist = NULL;
12965 :
12966 37170 : gimple_seq alloc_dlist = NULL;
12967 37170 : hash_map<tree, tree> alloc_map;
12968 74340 : hash_map<tree, gimple_seq> alloc_seq_map;
12969 :
12970 : /* The value expression for USES_ALLOCATORS needs to be setup before the
12971 : allocator is used via lower_private_allocate. */
12972 176484 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
12973 139314 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USES_ALLOCATORS)
12974 : {
12975 86 : tree allocator = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
12976 86 : tree new_allocator = lookup_decl (allocator, ctx);
12977 86 : tree x = build_receiver_ref (allocator, false, ctx);
12978 86 : SET_DECL_VALUE_EXPR (new_allocator, x);
12979 86 : DECL_HAS_VALUE_EXPR_P (new_allocator) = 1;
12980 86 : map_cnt++;
12981 : }
12982 :
12983 176484 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
12984 139314 : switch (OMP_CLAUSE_CODE (c))
12985 : {
12986 : tree var, x, new_var, allocator, allocate_ptr, size;
12987 : gimple_seq alloc_seq;
12988 : bool by_ref;
12989 :
12990 : default:
12991 92890 : break;
12992 77876 : case OMP_CLAUSE_MAP:
12993 : #if CHECKING_P
12994 : /* First check what we're prepared to handle in the following. */
12995 77876 : switch (OMP_CLAUSE_MAP_KIND (c))
12996 : {
12997 : case GOMP_MAP_ALLOC:
12998 : case GOMP_MAP_TO:
12999 : case GOMP_MAP_FROM:
13000 : case GOMP_MAP_TOFROM:
13001 : case GOMP_MAP_POINTER:
13002 : case GOMP_MAP_TO_PSET:
13003 : case GOMP_MAP_DELETE:
13004 : case GOMP_MAP_RELEASE:
13005 : case GOMP_MAP_ALWAYS_TO:
13006 : case GOMP_MAP_ALWAYS_FROM:
13007 : case GOMP_MAP_ALWAYS_TOFROM:
13008 : case GOMP_MAP_FORCE_PRESENT:
13009 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
13010 : case GOMP_MAP_ALWAYS_PRESENT_TO:
13011 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
13012 :
13013 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
13014 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
13015 : case GOMP_MAP_STRUCT:
13016 : case GOMP_MAP_STRUCT_UNORD:
13017 : case GOMP_MAP_ALWAYS_POINTER:
13018 : case GOMP_MAP_ATTACH:
13019 : case GOMP_MAP_DETACH:
13020 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
13021 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
13022 : break;
13023 2587 : case GOMP_MAP_IF_PRESENT:
13024 2587 : case GOMP_MAP_FORCE_ALLOC:
13025 2587 : case GOMP_MAP_FORCE_TO:
13026 2587 : case GOMP_MAP_FORCE_FROM:
13027 2587 : case GOMP_MAP_FORCE_TOFROM:
13028 2587 : case GOMP_MAP_FORCE_DEVICEPTR:
13029 2587 : case GOMP_MAP_DEVICE_RESIDENT:
13030 2587 : case GOMP_MAP_LINK:
13031 2587 : case GOMP_MAP_FORCE_DETACH:
13032 2587 : gcc_assert (is_gimple_omp_oacc (stmt));
13033 : break;
13034 0 : default:
13035 0 : gcc_unreachable ();
13036 : }
13037 : #endif
13038 : /* FALLTHRU */
13039 89446 : case OMP_CLAUSE_TO:
13040 89446 : case OMP_CLAUSE_FROM:
13041 89446 : oacc_firstprivate:
13042 89446 : var = OMP_CLAUSE_DECL (c);
13043 89446 : {
13044 89446 : tree extra = lang_hooks.decls.omp_deep_mapping_cnt (stmt, c, &ilist);
13045 89446 : if (extra != NULL_TREE && deep_map_cnt != NULL_TREE)
13046 59 : deep_map_cnt = fold_build2_loc (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
13047 : size_type_node, deep_map_cnt,
13048 : extra);
13049 89387 : else if (extra != NULL_TREE)
13050 : deep_map_cnt = extra;
13051 : }
13052 :
13053 89302 : if (deep_map_cnt
13054 89668 : && OMP_CLAUSE_HAS_ITERATORS (c))
13055 0 : sorry ("iterators used together with deep mapping are not "
13056 : "supported yet");
13057 :
13058 89446 : if (!DECL_P (var))
13059 : {
13060 36887 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
13061 36887 : || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
13062 35281 : && (OMP_CLAUSE_MAP_KIND (c)
13063 : != GOMP_MAP_FIRSTPRIVATE_POINTER)))
13064 36887 : map_cnt++;
13065 46424 : continue;
13066 : }
13067 :
13068 52559 : if (DECL_SIZE (var)
13069 52559 : && !poly_int_tree_p (DECL_SIZE (var)))
13070 : {
13071 717 : tree var2 = DECL_VALUE_EXPR (var);
13072 717 : gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
13073 717 : var2 = TREE_OPERAND (var2, 0);
13074 717 : gcc_assert (DECL_P (var2));
13075 : var = var2;
13076 : }
13077 :
13078 52559 : if (offloaded
13079 36693 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13080 85356 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
13081 29557 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
13082 : {
13083 3669 : if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
13084 : {
13085 415 : if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
13086 415 : && varpool_node::get_create (var)->offloadable)
13087 2 : continue;
13088 :
13089 413 : tree type = build_pointer_type (TREE_TYPE (var));
13090 413 : tree new_var = lookup_decl (var, ctx);
13091 413 : x = create_tmp_var_raw (type, get_name (new_var));
13092 413 : gimple_add_tmp_var (x);
13093 413 : x = build_simple_mem_ref (x);
13094 413 : SET_DECL_VALUE_EXPR (new_var, x);
13095 413 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13096 : }
13097 3667 : continue;
13098 3667 : }
13099 :
13100 48890 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13101 38926 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13102 38719 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
13103 49151 : && is_omp_target (stmt))
13104 : {
13105 237 : gcc_assert (maybe_lookup_field (c, ctx));
13106 237 : map_cnt++;
13107 237 : continue;
13108 : }
13109 :
13110 48653 : if (!maybe_lookup_field (c, ctx))
13111 5631 : continue;
13112 :
13113 : /* Don't remap compute constructs' reduction variables, because the
13114 : intermediate result must be local to each gang. */
13115 70872 : if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13116 23954 : && is_gimple_omp_oacc (ctx->stmt)
13117 13572 : && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
13118 : {
13119 27070 : x = build_receiver_ref (c, true, ctx);
13120 27070 : tree new_var = lookup_decl (var, ctx);
13121 :
13122 27070 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13123 23174 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
13124 3014 : && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
13125 30084 : && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
13126 425 : x = build_simple_mem_ref (x);
13127 27070 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13128 : {
13129 3896 : gcc_assert (is_gimple_omp_oacc (ctx->stmt));
13130 3896 : if (omp_privatize_by_reference (new_var)
13131 3896 : && (TREE_CODE (TREE_TYPE (new_var)) != POINTER_TYPE
13132 44 : || DECL_BY_REFERENCE (var)))
13133 : {
13134 : /* Create a local object to hold the instance
13135 : value. */
13136 455 : tree type = TREE_TYPE (TREE_TYPE (new_var));
13137 455 : const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
13138 455 : tree inst = create_tmp_var (type, id);
13139 455 : gimplify_assign (inst, fold_indirect_ref (x), &fplist);
13140 455 : x = build_fold_addr_expr (inst);
13141 : }
13142 3896 : gimplify_assign (new_var, x, &fplist);
13143 : }
13144 23174 : else if (DECL_P (new_var))
13145 : {
13146 23174 : SET_DECL_VALUE_EXPR (new_var, x);
13147 23174 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13148 : }
13149 : else
13150 0 : gcc_unreachable ();
13151 : }
13152 43022 : map_cnt++;
13153 43022 : break;
13154 :
13155 15306 : case OMP_CLAUSE_FIRSTPRIVATE:
13156 15306 : omp_firstprivate_recv:
13157 15306 : gcc_checking_assert (offloaded);
13158 15306 : if (is_gimple_omp_oacc (ctx->stmt))
13159 : {
13160 : /* No 'firstprivate' clauses on OpenACC 'kernels'. */
13161 3896 : gcc_checking_assert (!is_oacc_kernels (ctx));
13162 : /* Likewise, on OpenACC 'kernels' decomposed parts. */
13163 3896 : gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
13164 :
13165 3896 : goto oacc_firstprivate;
13166 : }
13167 11410 : map_cnt++;
13168 11410 : var = OMP_CLAUSE_DECL (c);
13169 11410 : new_var = lookup_decl (var, ctx);
13170 11410 : allocator = NULL_TREE;
13171 11410 : allocate_ptr = NULL_TREE;
13172 11410 : size = TREE_TYPE (var);
13173 11410 : by_ref = omp_privatize_by_reference (var);
13174 11410 : if (by_ref)
13175 828 : size = TREE_TYPE (size);
13176 11410 : size = TYPE_SIZE_UNIT (size);
13177 11410 : if (is_variable_sized (var, by_ref))
13178 35 : size = lookup_decl (size, ctx);
13179 11410 : alloc_seq = NULL;
13180 11410 : if (lower_private_allocate (var, new_var, allocator, allocate_ptr,
13181 : &alloc_seq, ctx, by_ref, size))
13182 : {
13183 65 : alloc_map.put (new_var, allocate_ptr);
13184 65 : alloc_seq_map.put (new_var, alloc_seq);
13185 : }
13186 11410 : if (!by_ref && !is_gimple_reg_type (TREE_TYPE (var)))
13187 : {
13188 143 : if (is_variable_sized (var))
13189 : {
13190 6 : tree pvar = DECL_VALUE_EXPR (var);
13191 6 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13192 6 : pvar = TREE_OPERAND (pvar, 0);
13193 6 : gcc_assert (DECL_P (pvar));
13194 6 : tree new_pvar = lookup_decl (pvar, ctx);
13195 6 : x = build_fold_indirect_ref (new_pvar);
13196 6 : TREE_THIS_NOTRAP (x) = 1;
13197 : }
13198 137 : else if (allocate_ptr)
13199 19 : x = build_fold_indirect_ref (allocate_ptr);
13200 : else
13201 118 : x = build_receiver_ref (var, true, ctx);
13202 143 : SET_DECL_VALUE_EXPR (new_var, x);
13203 143 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13204 : }
13205 : /* Fortran array descriptors: firstprivate of data + attach. */
13206 11410 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
13207 11391 : && lang_hooks.decls.omp_array_data (var, true)
13208 11441 : && lang_hooks.decls.omp_array_data_privatize (var))
13209 23 : map_cnt += 2;
13210 :
13211 11558 : do_dtor:
13212 11558 : if (allocator)
13213 : {
13214 122 : if (!is_gimple_val (allocator))
13215 : {
13216 0 : tree avar = create_tmp_var (TREE_TYPE (allocator));
13217 0 : gimplify_assign (avar, allocator, &alloc_dlist);
13218 0 : allocator = avar;
13219 : }
13220 122 : if (!is_gimple_val (allocate_ptr))
13221 : {
13222 0 : tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr));
13223 0 : gimplify_assign (apvar, allocate_ptr, &alloc_dlist);
13224 0 : allocate_ptr = apvar;
13225 : }
13226 122 : tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
13227 122 : gimple *g = gimple_build_call (f, 2, allocate_ptr, allocator);
13228 122 : gimple_seq_add_stmt (&alloc_dlist, g);
13229 : }
13230 : break;
13231 :
13232 228 : case OMP_CLAUSE_PRIVATE:
13233 228 : gcc_checking_assert (offloaded);
13234 228 : if (is_gimple_omp_oacc (ctx->stmt))
13235 : {
13236 : /* No 'private' clauses on OpenACC 'kernels'. */
13237 80 : gcc_checking_assert (!is_oacc_kernels (ctx));
13238 : /* Likewise, on OpenACC 'kernels' decomposed parts. */
13239 80 : gcc_checking_assert (!is_oacc_kernels_decomposed_part (ctx));
13240 :
13241 : break;
13242 : }
13243 148 : var = OMP_CLAUSE_DECL (c);
13244 148 : new_var = lookup_decl (var, ctx);
13245 148 : allocator = NULL_TREE;
13246 148 : allocate_ptr = NULL_TREE;
13247 148 : alloc_seq = NULL;
13248 148 : size = TREE_TYPE (var);
13249 148 : by_ref = omp_privatize_by_reference (var);
13250 148 : if (by_ref)
13251 22 : size = TREE_TYPE (size);
13252 148 : size = TYPE_SIZE_UNIT (size);
13253 148 : if (is_variable_sized (var, by_ref))
13254 21 : size = lookup_decl (size, ctx);
13255 148 : lower_private_allocate (var, new_var, allocator, allocate_ptr,
13256 : &alloc_seq, ctx, by_ref, size);
13257 148 : if (allocate_ptr)
13258 : {
13259 57 : alloc_map.put (new_var, allocate_ptr);
13260 57 : alloc_seq_map.put (new_var, alloc_seq);
13261 : }
13262 148 : if (!allocate_ptr && is_variable_sized (var))
13263 : {
13264 1 : tree new_var = lookup_decl (var, ctx);
13265 1 : tree pvar = DECL_VALUE_EXPR (var);
13266 1 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13267 1 : pvar = TREE_OPERAND (pvar, 0);
13268 1 : gcc_assert (DECL_P (pvar));
13269 1 : tree new_pvar = lookup_decl (pvar, ctx);
13270 1 : x = build_fold_indirect_ref (new_pvar);
13271 1 : TREE_THIS_NOTRAP (x) = 1;
13272 1 : SET_DECL_VALUE_EXPR (new_var, x);
13273 1 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13274 : }
13275 148 : goto do_dtor;
13276 :
13277 2430 : case OMP_CLAUSE_USE_DEVICE_PTR:
13278 2430 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13279 2430 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13280 2430 : case OMP_CLAUSE_IS_DEVICE_PTR:
13281 2430 : var = OMP_CLAUSE_DECL (c);
13282 2430 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13283 : {
13284 252 : while (TREE_CODE (var) == INDIRECT_REF
13285 252 : || TREE_CODE (var) == ARRAY_REF)
13286 17 : var = TREE_OPERAND (var, 0);
13287 235 : if (lang_hooks.decls.omp_array_data (var, true))
13288 19 : goto omp_firstprivate_recv;
13289 : }
13290 2411 : map_cnt++;
13291 2411 : if (is_variable_sized (var))
13292 : {
13293 12 : tree new_var = lookup_decl (var, ctx);
13294 12 : tree pvar = DECL_VALUE_EXPR (var);
13295 12 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
13296 12 : pvar = TREE_OPERAND (pvar, 0);
13297 12 : gcc_assert (DECL_P (pvar));
13298 12 : tree new_pvar = lookup_decl (pvar, ctx);
13299 12 : x = build_fold_indirect_ref (new_pvar);
13300 12 : TREE_THIS_NOTRAP (x) = 1;
13301 12 : SET_DECL_VALUE_EXPR (new_var, x);
13302 12 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13303 : }
13304 2399 : else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
13305 542 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13306 2071 : && !omp_privatize_by_reference (var)
13307 703 : && !omp_is_allocatable_or_ptr (var)
13308 564 : && !lang_hooks.decls.omp_array_data (var, true))
13309 4433 : || TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
13310 : {
13311 389 : tree new_var = lookup_decl (var, ctx);
13312 389 : tree type = build_pointer_type (TREE_TYPE (var));
13313 389 : x = create_tmp_var_raw (type, get_name (new_var));
13314 389 : gimple_add_tmp_var (x);
13315 389 : x = build_simple_mem_ref (x);
13316 389 : SET_DECL_VALUE_EXPR (new_var, x);
13317 389 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13318 : }
13319 : else
13320 : {
13321 2010 : tree new_var = lookup_decl (var, ctx);
13322 2010 : x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
13323 2010 : gimple_add_tmp_var (x);
13324 2010 : SET_DECL_VALUE_EXPR (new_var, x);
13325 2010 : DECL_HAS_VALUE_EXPR_P (new_var) = 1;
13326 : }
13327 : break;
13328 : }
13329 :
13330 37170 : if (offloaded)
13331 : {
13332 21210 : target_nesting_level++;
13333 21210 : lower_omp (&tgt_body, ctx);
13334 21210 : target_nesting_level--;
13335 : }
13336 15960 : else if (data_region)
13337 4021 : lower_omp (&tgt_body, ctx);
13338 :
13339 37170 : if (offloaded)
13340 : {
13341 : /* Declare all the variables created by mapping and the variables
13342 : declared in the scope of the target body. */
13343 21210 : record_vars_into (ctx->block_vars, child_fn);
13344 21210 : maybe_remove_omp_member_access_dummy_vars (tgt_bind);
13345 21210 : record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
13346 : }
13347 :
13348 37170 : if (ctx->record_type)
13349 : {
13350 32279 : if (deep_map_cnt && TREE_CODE (deep_map_cnt) == INTEGER_CST)
13351 : /* map_cnt = map_cnt + tree_to_hwi (deep_map_cnt); */
13352 : /* deep_map_cnt = NULL_TREE; */
13353 0 : gcc_unreachable ();
13354 144 : else if (deep_map_cnt)
13355 : {
13356 144 : gcc_assert (flexible_array_type_p (ctx->record_type));
13357 144 : tree n = create_tmp_var_raw (size_type_node, "nn_map");
13358 144 : gimple_add_tmp_var (n);
13359 144 : gimplify_assign (n, deep_map_cnt, &ilist);
13360 144 : deep_map_cnt = n;
13361 : }
13362 144 : ctx->sender_decl
13363 32279 : = create_tmp_var (deep_map_cnt ? build_pointer_type (ctx->record_type)
13364 : : ctx->record_type, ".omp_data_arr");
13365 32279 : DECL_NAMELESS (ctx->sender_decl) = 1;
13366 32279 : TREE_ADDRESSABLE (ctx->sender_decl) = 1;
13367 64414 : t = make_tree_vec (deep_map_cnt ? 4 : 3);
13368 32279 : TREE_VEC_ELT (t, 0) = ctx->sender_decl;
13369 32279 : TREE_VEC_ELT (t, 1)
13370 64558 : = create_tmp_var (deep_map_cnt
13371 144 : ? build_pointer_type (size_type_node)
13372 32135 : : build_array_type_nelts (size_type_node, map_cnt),
13373 : ".omp_data_sizes");
13374 32279 : DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
13375 32279 : TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
13376 32279 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
13377 32279 : tree tkind_type = short_unsigned_type_node;
13378 32279 : int talign_shift = 8;
13379 32279 : TREE_VEC_ELT (t, 2)
13380 64558 : = create_tmp_var (deep_map_cnt
13381 144 : ? build_pointer_type (tkind_type)
13382 32135 : : build_array_type_nelts (tkind_type, map_cnt),
13383 : ".omp_data_kinds");
13384 32279 : DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
13385 32279 : TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
13386 32279 : TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
13387 32279 : gimple_omp_target_set_data_arg (stmt, t);
13388 :
13389 32279 : if (deep_map_cnt)
13390 : {
13391 144 : tree tmp, size;
13392 144 : size = create_tmp_var (size_type_node, NULL);
13393 144 : DECL_NAMELESS (size) = 1;
13394 144 : gimplify_assign (size,
13395 : fold_build2_loc (UNKNOWN_LOCATION, PLUS_EXPR,
13396 : size_type_node, deep_map_cnt,
13397 : build_int_cst (size_type_node,
13398 144 : map_cnt)), &ilist);
13399 144 : TREE_VEC_ELT (t, 3) = size;
13400 :
13401 144 : tree call = builtin_decl_explicit (BUILT_IN_MALLOC);
13402 144 : size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR,
13403 : size_type_node, deep_map_cnt,
13404 144 : TYPE_SIZE_UNIT (ptr_type_node));
13405 144 : size = fold_build2_loc (UNKNOWN_LOCATION, PLUS_EXPR,
13406 : size_type_node, size,
13407 144 : TYPE_SIZE_UNIT (ctx->record_type));
13408 144 : tmp = build_call_expr_loc (input_location, call, 1, size);
13409 144 : gimplify_assign (ctx->sender_decl, tmp, &ilist);
13410 :
13411 144 : size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR,
13412 144 : size_type_node, TREE_VEC_ELT (t, 3),
13413 144 : TYPE_SIZE_UNIT (size_type_node));
13414 144 : tmp = build_call_expr_loc (input_location, call, 1, size);
13415 144 : gimplify_assign (TREE_VEC_ELT (t, 1), tmp, &ilist);
13416 :
13417 144 : size = fold_build2_loc (UNKNOWN_LOCATION, MULT_EXPR,
13418 144 : size_type_node, TREE_VEC_ELT (t, 3),
13419 144 : TYPE_SIZE_UNIT (tkind_type));
13420 144 : tmp = build_call_expr_loc (input_location, call, 1, size);
13421 144 : gimplify_assign (TREE_VEC_ELT (t, 2), tmp, &ilist);
13422 144 : tree field = TYPE_FIELDS (TREE_TYPE (TREE_TYPE (ctx->sender_decl)));
13423 595 : for ( ; DECL_CHAIN (field) != NULL_TREE; field = DECL_CHAIN (field))
13424 : ;
13425 144 : gcc_assert (TREE_CODE (TREE_TYPE (field)));
13426 144 : tmp = build_fold_indirect_ref (ctx->sender_decl);
13427 144 : deep_map_data = omp_build_component_ref (tmp, field);
13428 144 : deep_map_offset_data = create_tmp_var_raw (size_type_node,
13429 : "map_offset_data");
13430 144 : deep_map_offset = create_tmp_var_raw (size_type_node, "map_offset");
13431 144 : gimple_add_tmp_var (deep_map_offset_data);
13432 144 : gimple_add_tmp_var (deep_map_offset);
13433 144 : gimplify_assign (deep_map_offset_data, build_int_cst (size_type_node,
13434 : 0), &ilist);
13435 144 : gimplify_assign (deep_map_offset, build_int_cst (size_type_node,
13436 144 : map_cnt), &ilist);
13437 : }
13438 :
13439 32279 : vec<constructor_elt, va_gc> *vsize;
13440 32279 : vec<constructor_elt, va_gc> *vkind;
13441 32279 : vec_alloc (vsize, map_cnt);
13442 32279 : vec_alloc (vkind, map_cnt);
13443 32279 : unsigned int map_idx = 0;
13444 :
13445 162202 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
13446 129923 : switch (OMP_CLAUSE_CODE (c))
13447 : {
13448 : tree ovar, nc, s, purpose, var, x, type;
13449 : unsigned int talign;
13450 :
13451 : default:
13452 125959 : break;
13453 :
13454 87947 : case OMP_CLAUSE_MAP:
13455 87947 : case OMP_CLAUSE_TO:
13456 87947 : case OMP_CLAUSE_FROM:
13457 87947 : oacc_firstprivate_map:
13458 87947 : nc = c;
13459 87947 : ovar = OMP_CLAUSE_DECL (c);
13460 87947 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13461 87947 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
13462 72969 : || (OMP_CLAUSE_MAP_KIND (c)
13463 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
13464 : break;
13465 84110 : if (deep_map_cnt)
13466 : {
13467 428 : unsigned HOST_WIDE_INT tkind2;
13468 428 : switch (OMP_CLAUSE_CODE (c))
13469 : {
13470 424 : case OMP_CLAUSE_MAP:
13471 424 : tkind2 = OMP_CLAUSE_MAP_KIND (c);
13472 424 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (c)
13473 424 : && (((tkind2 & GOMP_MAP_FLAG_SPECIAL_BITS)
13474 : & ~GOMP_MAP_IMPLICIT)
13475 : == 0))
13476 : {
13477 : /* If this is an implicit map, and the GOMP_MAP_IMPLICIT
13478 : bits are not interfered by other special bit
13479 : encodings, then turn the GOMP_IMPLICIT_BIT flag on
13480 : for the runtime to see. */
13481 120 : tkind2 |= GOMP_MAP_IMPLICIT;
13482 : }
13483 : break;
13484 : case OMP_CLAUSE_FIRSTPRIVATE: tkind2 = GOMP_MAP_TO; break;
13485 : case OMP_CLAUSE_TO: tkind2 = GOMP_MAP_TO; break;
13486 2 : case OMP_CLAUSE_FROM: tkind2 = GOMP_MAP_FROM; break;
13487 0 : default: gcc_unreachable ();
13488 : }
13489 428 : lang_hooks.decls.omp_deep_mapping (stmt, c, tkind2,
13490 : deep_map_data,
13491 428 : TREE_VEC_ELT (t, 1),
13492 428 : TREE_VEC_ELT (t, 2),
13493 : deep_map_offset_data,
13494 : deep_map_offset, &ilist);
13495 : }
13496 84110 : if (!DECL_P (ovar))
13497 : {
13498 36887 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13499 36887 : && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
13500 : {
13501 0 : nc = OMP_CLAUSE_CHAIN (c);
13502 0 : gcc_checking_assert (OMP_CLAUSE_DECL (nc)
13503 : == get_base_address (ovar));
13504 0 : ovar = OMP_CLAUSE_DECL (nc);
13505 : }
13506 : else
13507 : {
13508 36887 : tree x = build_sender_ref (c, ctx);
13509 36887 : tree v = ovar;
13510 36887 : if (in_reduction_clauses
13511 163 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13512 37050 : && OMP_CLAUSE_MAP_IN_REDUCTION (c))
13513 : {
13514 104 : v = unshare_expr (v);
13515 104 : tree *p = &v;
13516 104 : while (handled_component_p (*p)
13517 : || TREE_CODE (*p) == INDIRECT_REF
13518 : || TREE_CODE (*p) == ADDR_EXPR
13519 : || TREE_CODE (*p) == MEM_REF
13520 256 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
13521 152 : p = &TREE_OPERAND (*p, 0);
13522 104 : tree d = *p;
13523 104 : if (is_variable_sized (d))
13524 : {
13525 16 : gcc_assert (DECL_HAS_VALUE_EXPR_P (d));
13526 16 : d = DECL_VALUE_EXPR (d);
13527 16 : gcc_assert (TREE_CODE (d) == INDIRECT_REF);
13528 16 : d = TREE_OPERAND (d, 0);
13529 16 : gcc_assert (DECL_P (d));
13530 : }
13531 104 : splay_tree_key key
13532 104 : = (splay_tree_key) &DECL_CONTEXT (d);
13533 104 : tree nd = (tree) splay_tree_lookup (ctx->field_map,
13534 104 : key)->value;
13535 104 : if (d == *p)
13536 88 : *p = nd;
13537 : else
13538 16 : *p = build_fold_indirect_ref (nd);
13539 : }
13540 36887 : v = build_fold_addr_expr_with_type (v, ptr_type_node);
13541 36887 : v = lower_omp_map_iterator_expr (v, c, stmt);
13542 36887 : gimplify_assign (x, v, &ilist);
13543 36887 : nc = NULL_TREE;
13544 : }
13545 : }
13546 : else
13547 : {
13548 47223 : if (DECL_SIZE (ovar)
13549 47223 : && !poly_int_tree_p (DECL_SIZE (ovar)))
13550 : {
13551 7 : tree ovar2 = DECL_VALUE_EXPR (ovar);
13552 7 : gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
13553 7 : ovar2 = TREE_OPERAND (ovar2, 0);
13554 7 : gcc_assert (DECL_P (ovar2));
13555 : ovar = ovar2;
13556 : }
13557 47223 : if (!maybe_lookup_field (c, ctx)
13558 51187 : && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13559 3964 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13560 3964 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)))
13561 3964 : continue;
13562 : }
13563 :
13564 80146 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
13565 80146 : if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
13566 6409 : talign = DECL_ALIGN_UNIT (ovar);
13567 :
13568 80146 : var = NULL_TREE;
13569 80146 : if (nc)
13570 : {
13571 43259 : if (in_reduction_clauses
13572 897 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13573 44156 : && OMP_CLAUSE_MAP_IN_REDUCTION (c))
13574 : {
13575 268 : tree d = ovar;
13576 268 : if (is_variable_sized (d))
13577 : {
13578 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (d));
13579 0 : d = DECL_VALUE_EXPR (d);
13580 0 : gcc_assert (TREE_CODE (d) == INDIRECT_REF);
13581 0 : d = TREE_OPERAND (d, 0);
13582 0 : gcc_assert (DECL_P (d));
13583 : }
13584 268 : splay_tree_key key
13585 268 : = (splay_tree_key) &DECL_CONTEXT (d);
13586 268 : tree nd = (tree) splay_tree_lookup (ctx->field_map,
13587 268 : key)->value;
13588 268 : if (d == ovar)
13589 : var = nd;
13590 : else
13591 0 : var = build_fold_indirect_ref (nd);
13592 : }
13593 : else
13594 42991 : var = lookup_decl_in_outer_ctx (ovar, ctx);
13595 : }
13596 43259 : if (nc
13597 43259 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13598 33295 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
13599 33088 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
13600 261 : && is_omp_target (stmt))
13601 : {
13602 237 : x = build_sender_ref (c, ctx);
13603 237 : gimplify_assign (x, build_fold_addr_expr (var), &ilist);
13604 : }
13605 79909 : else if (nc)
13606 : {
13607 43022 : x = build_sender_ref (nc, ctx);
13608 :
13609 43022 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13610 33058 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
13611 5184 : && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
13612 48206 : && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
13613 : {
13614 425 : gcc_assert (offloaded);
13615 425 : tree avar = build_fold_addr_expr (var);
13616 425 : if (!OMP_CLAUSE_ITERATORS (c))
13617 : {
13618 425 : tree tmp = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
13619 425 : mark_addressable (tmp);
13620 425 : gimplify_assign (tmp, avar, &ilist);
13621 425 : avar = tmp;
13622 : }
13623 425 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (x)));
13624 425 : avar = build_fold_addr_expr (avar);
13625 425 : avar = lower_omp_map_iterator_expr (avar, c, stmt);
13626 425 : gimplify_assign (x, avar, &ilist);
13627 : }
13628 42597 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13629 : {
13630 3896 : gcc_assert (is_gimple_omp_oacc (ctx->stmt));
13631 3896 : if (!omp_privatize_by_reference (var))
13632 : {
13633 3441 : if (is_gimple_reg (var)
13634 3441 : && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13635 2578 : suppress_warning (var);
13636 3441 : var = build_fold_addr_expr (var);
13637 : }
13638 : else
13639 455 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13640 3896 : gimplify_assign (x, var, &ilist);
13641 : }
13642 38701 : else if (is_gimple_reg (var))
13643 : {
13644 5285 : gcc_assert (offloaded);
13645 5285 : tree avar = create_tmp_var (TREE_TYPE (var));
13646 5285 : mark_addressable (avar);
13647 5285 : enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
13648 5285 : if (GOMP_MAP_COPY_TO_P (map_kind)
13649 : || map_kind == GOMP_MAP_POINTER
13650 475 : || map_kind == GOMP_MAP_TO_PSET
13651 2 : || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
13652 : {
13653 : /* If we need to initialize a temporary
13654 : with VAR because it is not addressable, and
13655 : the variable hasn't been initialized yet, then
13656 : we'll get a warning for the store to avar.
13657 : Don't warn in that case, the mapping might
13658 : be implicit. */
13659 5283 : suppress_warning (var, OPT_Wuninitialized);
13660 5283 : gimplify_assign (avar, var, &ilist);
13661 : }
13662 5285 : avar = build_fold_addr_expr (avar);
13663 5285 : gimplify_assign (x, avar, &ilist);
13664 5285 : if ((GOMP_MAP_COPY_FROM_P (map_kind)
13665 1486 : || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
13666 9084 : && !TYPE_READONLY (TREE_TYPE (var)))
13667 : {
13668 3799 : x = unshare_expr (x);
13669 3799 : x = build_simple_mem_ref (x);
13670 3799 : gimplify_assign (var, x, &olist);
13671 : }
13672 : }
13673 : else
13674 : {
13675 : /* While MAP is handled explicitly by the FE,
13676 : for 'target update', only the identified is passed. */
13677 33416 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM
13678 28292 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO)
13679 34360 : && (omp_is_allocatable_or_ptr (var)
13680 120 : && omp_check_optional_argument (var, false)))
13681 0 : var = build_fold_indirect_ref (var);
13682 33416 : else if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FROM
13683 28292 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TO)
13684 34360 : || (!omp_is_allocatable_or_ptr (var)
13685 5948 : && !omp_check_optional_argument (var, false)))
13686 33296 : var = build_fold_addr_expr (var);
13687 33416 : gimplify_assign (x, var, &ilist);
13688 : }
13689 : }
13690 80146 : s = NULL_TREE;
13691 80146 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13692 : {
13693 3896 : gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
13694 3896 : s = TREE_TYPE (ovar);
13695 3896 : if (TREE_CODE (s) == REFERENCE_TYPE
13696 3896 : || omp_check_optional_argument (ovar, false))
13697 449 : s = TREE_TYPE (s);
13698 3896 : s = TYPE_SIZE_UNIT (s);
13699 : }
13700 : else
13701 76250 : s = OMP_CLAUSE_SIZE (c);
13702 80146 : if (s == NULL_TREE)
13703 153 : s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
13704 80146 : s = fold_convert (size_type_node, s);
13705 80146 : s = lower_omp_map_iterator_size (s, c, stmt);
13706 80146 : purpose = size_int (map_idx++);
13707 80146 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
13708 80146 : if (TREE_CODE (s) != INTEGER_CST)
13709 16154 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13710 :
13711 80146 : unsigned HOST_WIDE_INT tkind, tkind_zero;
13712 80146 : switch (OMP_CLAUSE_CODE (c))
13713 : {
13714 68576 : case OMP_CLAUSE_MAP:
13715 68576 : tkind = OMP_CLAUSE_MAP_KIND (c);
13716 68576 : tkind_zero = tkind;
13717 68576 : if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
13718 5281 : switch (tkind)
13719 : {
13720 : case GOMP_MAP_ALLOC:
13721 : case GOMP_MAP_IF_PRESENT:
13722 : case GOMP_MAP_TO:
13723 : case GOMP_MAP_FROM:
13724 : case GOMP_MAP_TOFROM:
13725 : case GOMP_MAP_ALWAYS_TO:
13726 : case GOMP_MAP_ALWAYS_FROM:
13727 : case GOMP_MAP_ALWAYS_TOFROM:
13728 : case GOMP_MAP_ALWAYS_PRESENT_TO:
13729 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
13730 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
13731 : case GOMP_MAP_RELEASE:
13732 : case GOMP_MAP_FORCE_TO:
13733 : case GOMP_MAP_FORCE_FROM:
13734 : case GOMP_MAP_FORCE_TOFROM:
13735 : case GOMP_MAP_FORCE_PRESENT:
13736 68576 : tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
13737 : break;
13738 21 : case GOMP_MAP_DELETE:
13739 21 : tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
13740 : default:
13741 : break;
13742 : }
13743 68576 : if (tkind_zero != tkind)
13744 : {
13745 5281 : if (integer_zerop (s))
13746 : tkind = tkind_zero;
13747 4551 : else if (integer_nonzerop (s))
13748 68576 : tkind_zero = tkind;
13749 : }
13750 68576 : if (tkind_zero == tkind
13751 67115 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (c)
13752 68576 : && (((tkind & GOMP_MAP_FLAG_SPECIAL_BITS)
13753 5234 : & ~GOMP_MAP_IMPLICIT)
13754 : == 0))
13755 : {
13756 : /* If this is an implicit map, and the GOMP_MAP_IMPLICIT
13757 : bits are not interfered by other special bit encodings,
13758 : then turn the GOMP_IMPLICIT_BIT flag on for the runtime
13759 : to see. */
13760 5191 : tkind |= GOMP_MAP_IMPLICIT;
13761 5191 : tkind_zero = tkind;
13762 : }
13763 : break;
13764 3896 : case OMP_CLAUSE_FIRSTPRIVATE:
13765 3896 : gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
13766 : tkind = GOMP_MAP_TO;
13767 : tkind_zero = tkind;
13768 : break;
13769 1651 : case OMP_CLAUSE_TO:
13770 1651 : tkind
13771 1651 : = (OMP_CLAUSE_MOTION_PRESENT (c)
13772 1651 : ? GOMP_MAP_ALWAYS_PRESENT_TO : GOMP_MAP_TO);
13773 : tkind_zero = tkind;
13774 : break;
13775 6023 : case OMP_CLAUSE_FROM:
13776 6023 : tkind
13777 6023 : = (OMP_CLAUSE_MOTION_PRESENT (c)
13778 6023 : ? GOMP_MAP_ALWAYS_PRESENT_FROM : GOMP_MAP_FROM);
13779 : tkind_zero = tkind;
13780 : break;
13781 0 : default:
13782 0 : gcc_unreachable ();
13783 : }
13784 68576 : gcc_checking_assert (tkind
13785 : < (HOST_WIDE_INT_C (1U) << talign_shift));
13786 80146 : gcc_checking_assert (tkind_zero
13787 : < (HOST_WIDE_INT_C (1U) << talign_shift));
13788 80146 : talign = ceil_log2 (talign);
13789 80146 : tkind |= talign << talign_shift;
13790 80146 : tkind_zero |= talign << talign_shift;
13791 80146 : gcc_checking_assert (tkind
13792 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13793 80146 : gcc_checking_assert (tkind_zero
13794 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13795 80146 : if (tkind == tkind_zero)
13796 78685 : x = build_int_cstu (tkind_type, tkind);
13797 : else
13798 : {
13799 1461 : TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
13800 1461 : x = build3 (COND_EXPR, tkind_type,
13801 : fold_build2 (EQ_EXPR, boolean_type_node,
13802 : unshare_expr (s), size_zero_node),
13803 1461 : build_int_cstu (tkind_type, tkind_zero),
13804 1461 : build_int_cstu (tkind_type, tkind));
13805 : }
13806 80146 : CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
13807 80146 : if (nc && nc != c)
13808 0 : c = nc;
13809 : break;
13810 :
13811 15306 : case OMP_CLAUSE_FIRSTPRIVATE:
13812 15306 : omp_has_device_addr_descr:
13813 15306 : if (is_gimple_omp_oacc (ctx->stmt))
13814 3896 : goto oacc_firstprivate_map;
13815 11410 : ovar = OMP_CLAUSE_DECL (c);
13816 11410 : if (omp_privatize_by_reference (ovar))
13817 828 : talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13818 : else
13819 10582 : talign = DECL_ALIGN_UNIT (ovar);
13820 11410 : var = lookup_decl_in_outer_ctx (ovar, ctx);
13821 11410 : x = build_sender_ref (ovar, ctx);
13822 11410 : tkind = GOMP_MAP_FIRSTPRIVATE;
13823 11410 : type = TREE_TYPE (ovar);
13824 11410 : if (omp_privatize_by_reference (ovar))
13825 828 : type = TREE_TYPE (type);
13826 11410 : if ((INTEGRAL_TYPE_P (type)
13827 11004 : && TYPE_PRECISION (type) <= POINTER_SIZE)
13828 11420 : || TREE_CODE (type) == POINTER_TYPE)
13829 : {
13830 11149 : tkind = GOMP_MAP_FIRSTPRIVATE_INT;
13831 11149 : tree t = var;
13832 11149 : if (omp_privatize_by_reference (var))
13833 773 : t = build_simple_mem_ref (var);
13834 10376 : else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13835 9310 : suppress_warning (var);
13836 11149 : if (TREE_CODE (type) != POINTER_TYPE)
13837 10994 : t = fold_convert (pointer_sized_int_node, t);
13838 11149 : t = fold_convert (TREE_TYPE (x), t);
13839 11149 : gimplify_assign (x, t, &ilist);
13840 : }
13841 261 : else if (omp_privatize_by_reference (var))
13842 55 : gimplify_assign (x, var, &ilist);
13843 206 : else if (is_gimple_reg (var))
13844 : {
13845 51 : tree avar = create_tmp_var (TREE_TYPE (var));
13846 51 : mark_addressable (avar);
13847 51 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13848 44 : suppress_warning (var);
13849 51 : gimplify_assign (avar, var, &ilist);
13850 51 : avar = build_fold_addr_expr (avar);
13851 51 : gimplify_assign (x, avar, &ilist);
13852 : }
13853 : else
13854 : {
13855 155 : var = build_fold_addr_expr (var);
13856 155 : gimplify_assign (x, var, &ilist);
13857 : }
13858 261 : if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
13859 11149 : s = size_int (0);
13860 261 : else if (omp_privatize_by_reference (ovar))
13861 55 : s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
13862 : else
13863 206 : s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
13864 11410 : s = fold_convert (size_type_node, s);
13865 11410 : purpose = size_int (map_idx++);
13866 11410 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
13867 11410 : if (TREE_CODE (s) != INTEGER_CST)
13868 35 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13869 :
13870 11410 : gcc_checking_assert (tkind
13871 : < (HOST_WIDE_INT_C (1U) << talign_shift));
13872 11410 : talign = ceil_log2 (talign);
13873 11410 : tkind |= talign << talign_shift;
13874 11410 : gcc_checking_assert (tkind
13875 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
13876 11410 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13877 : build_int_cstu (tkind_type, tkind));
13878 : /* Fortran array descriptors: firstprivate of data + attach. */
13879 11410 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
13880 11391 : && lang_hooks.decls.omp_array_data (ovar, true)
13881 11441 : && lang_hooks.decls.omp_array_data_privatize (ovar))
13882 : {
13883 23 : tree not_null_lb, null_lb, after_lb;
13884 23 : tree var1, var2, size1, size2;
13885 23 : tree present = omp_check_optional_argument (ovar, true);
13886 23 : if (present)
13887 : {
13888 1 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
13889 1 : not_null_lb = create_artificial_label (clause_loc);
13890 1 : null_lb = create_artificial_label (clause_loc);
13891 1 : after_lb = create_artificial_label (clause_loc);
13892 1 : gimple_seq seq = NULL;
13893 1 : present = force_gimple_operand (present, &seq, true,
13894 : NULL_TREE);
13895 1 : gimple_seq_add_seq (&ilist, seq);
13896 1 : gimple_seq_add_stmt (&ilist,
13897 1 : gimple_build_cond_from_tree (present,
13898 : not_null_lb, null_lb));
13899 1 : gimple_seq_add_stmt (&ilist,
13900 1 : gimple_build_label (not_null_lb));
13901 : }
13902 23 : var1 = lang_hooks.decls.omp_array_data (var, false);
13903 23 : size1 = lang_hooks.decls.omp_array_size (var, &ilist);
13904 23 : var2 = build_fold_addr_expr (x);
13905 23 : if (!POINTER_TYPE_P (TREE_TYPE (var)))
13906 0 : var = build_fold_addr_expr (var);
13907 23 : size2 = fold_build2 (POINTER_DIFF_EXPR, ssizetype,
13908 : build_fold_addr_expr (var1), var);
13909 23 : size2 = fold_convert (sizetype, size2);
13910 23 : if (present)
13911 : {
13912 1 : tree tmp = create_tmp_var (TREE_TYPE (var1));
13913 1 : gimplify_assign (tmp, var1, &ilist);
13914 1 : var1 = tmp;
13915 1 : tmp = create_tmp_var (TREE_TYPE (var2));
13916 1 : gimplify_assign (tmp, var2, &ilist);
13917 1 : var2 = tmp;
13918 1 : tmp = create_tmp_var (TREE_TYPE (size1));
13919 1 : gimplify_assign (tmp, size1, &ilist);
13920 1 : size1 = tmp;
13921 1 : tmp = create_tmp_var (TREE_TYPE (size2));
13922 1 : gimplify_assign (tmp, size2, &ilist);
13923 1 : size2 = tmp;
13924 1 : gimple_seq_add_stmt (&ilist, gimple_build_goto (after_lb));
13925 1 : gimple_seq_add_stmt (&ilist, gimple_build_label (null_lb));
13926 1 : gimplify_assign (var1, null_pointer_node, &ilist);
13927 1 : gimplify_assign (var2, null_pointer_node, &ilist);
13928 1 : gimplify_assign (size1, size_zero_node, &ilist);
13929 1 : gimplify_assign (size2, size_zero_node, &ilist);
13930 1 : gimple_seq_add_stmt (&ilist, gimple_build_label (after_lb));
13931 : }
13932 23 : x = build_sender_ref ((splay_tree_key) &DECL_NAME (ovar), ctx);
13933 23 : gimplify_assign (x, var1, &ilist);
13934 23 : tkind = GOMP_MAP_FIRSTPRIVATE;
13935 23 : talign = DECL_ALIGN_UNIT (ovar);
13936 23 : talign = ceil_log2 (talign);
13937 23 : tkind |= talign << talign_shift;
13938 23 : gcc_checking_assert (tkind
13939 : <= tree_to_uhwi (
13940 : TYPE_MAX_VALUE (tkind_type)));
13941 23 : purpose = size_int (map_idx++);
13942 23 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, size1);
13943 23 : if (TREE_CODE (size1) != INTEGER_CST)
13944 23 : TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
13945 23 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13946 : build_int_cstu (tkind_type, tkind));
13947 23 : x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar), ctx);
13948 23 : gimplify_assign (x, var2, &ilist);
13949 23 : tkind = GOMP_MAP_ATTACH;
13950 23 : purpose = size_int (map_idx++);
13951 23 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, size2);
13952 23 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
13953 : build_int_cstu (tkind_type, tkind));
13954 : }
13955 : break;
13956 :
13957 2430 : case OMP_CLAUSE_USE_DEVICE_PTR:
13958 2430 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13959 2430 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13960 2430 : case OMP_CLAUSE_IS_DEVICE_PTR:
13961 2430 : ovar = OMP_CLAUSE_DECL (c);
13962 2430 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
13963 : {
13964 235 : if (lang_hooks.decls.omp_array_data (ovar, true))
13965 19 : goto omp_has_device_addr_descr;
13966 233 : while (TREE_CODE (ovar) == INDIRECT_REF
13967 233 : || TREE_CODE (ovar) == ARRAY_REF)
13968 17 : ovar = TREE_OPERAND (ovar, 0);
13969 : }
13970 2411 : var = lookup_decl_in_outer_ctx (ovar, ctx);
13971 :
13972 2411 : if (lang_hooks.decls.omp_array_data (ovar, true))
13973 : {
13974 601 : tkind = ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
13975 601 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13976 601 : ? GOMP_MAP_USE_DEVICE_PTR : GOMP_MAP_FIRSTPRIVATE_INT);
13977 601 : x = build_sender_ref ((splay_tree_key) &DECL_NAME (ovar), ctx);
13978 : }
13979 1810 : else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
13980 1810 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
13981 : {
13982 1453 : tkind = GOMP_MAP_USE_DEVICE_PTR;
13983 1453 : x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar), ctx);
13984 : }
13985 : else
13986 : {
13987 357 : tkind = GOMP_MAP_FIRSTPRIVATE_INT;
13988 357 : x = build_sender_ref (ovar, ctx);
13989 : }
13990 :
13991 2411 : if (is_gimple_omp_oacc (ctx->stmt))
13992 : {
13993 147 : gcc_assert (tkind == GOMP_MAP_USE_DEVICE_PTR);
13994 :
13995 147 : if (OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c))
13996 57 : tkind = GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT;
13997 : }
13998 :
13999 2411 : type = TREE_TYPE (ovar);
14000 2411 : if (lang_hooks.decls.omp_array_data (ovar, true))
14001 601 : var = lang_hooks.decls.omp_array_data (var, false);
14002 1810 : else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
14003 542 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
14004 1484 : && !omp_privatize_by_reference (ovar)
14005 512 : && !omp_is_allocatable_or_ptr (ovar))
14006 3247 : || TREE_CODE (type) == ARRAY_TYPE)
14007 401 : var = build_fold_addr_expr (var);
14008 : else
14009 : {
14010 1409 : if (omp_privatize_by_reference (ovar)
14011 370 : || omp_check_optional_argument (ovar, false)
14012 1779 : || omp_is_allocatable_or_ptr (ovar))
14013 : {
14014 1212 : type = TREE_TYPE (type);
14015 1212 : if (POINTER_TYPE_P (type)
14016 1212 : && TREE_CODE (type) != ARRAY_TYPE
14017 1571 : && ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
14018 36 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
14019 28 : && !omp_is_allocatable_or_ptr (ovar))
14020 337 : || (omp_privatize_by_reference (ovar)
14021 337 : && omp_is_allocatable_or_ptr (ovar))))
14022 357 : var = build_simple_mem_ref (var);
14023 1212 : var = fold_convert (TREE_TYPE (x), var);
14024 : }
14025 : }
14026 2411 : tree present;
14027 2411 : present = omp_check_optional_argument (ovar, true);
14028 2411 : if (present)
14029 : {
14030 878 : tree null_label = create_artificial_label (UNKNOWN_LOCATION);
14031 878 : tree notnull_label = create_artificial_label (UNKNOWN_LOCATION);
14032 878 : tree opt_arg_label = create_artificial_label (UNKNOWN_LOCATION);
14033 878 : tree new_x = unshare_expr (x);
14034 878 : gimplify_expr (&present, &ilist, NULL, is_gimple_val,
14035 : fb_rvalue);
14036 878 : gcond *cond = gimple_build_cond_from_tree (present,
14037 : notnull_label,
14038 : null_label);
14039 878 : gimple_seq_add_stmt (&ilist, cond);
14040 878 : gimple_seq_add_stmt (&ilist, gimple_build_label (null_label));
14041 878 : gimplify_assign (new_x, null_pointer_node, &ilist);
14042 878 : gimple_seq_add_stmt (&ilist, gimple_build_goto (opt_arg_label));
14043 878 : gimple_seq_add_stmt (&ilist,
14044 878 : gimple_build_label (notnull_label));
14045 878 : gimplify_assign (x, var, &ilist);
14046 878 : gimple_seq_add_stmt (&ilist,
14047 878 : gimple_build_label (opt_arg_label));
14048 : }
14049 : else
14050 1533 : gimplify_assign (x, var, &ilist);
14051 2411 : s = size_int (0);
14052 2411 : purpose = size_int (map_idx++);
14053 2411 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
14054 2411 : gcc_checking_assert (tkind
14055 : < (HOST_WIDE_INT_C (1U) << talign_shift));
14056 2411 : gcc_checking_assert (tkind
14057 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14058 2411 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
14059 : build_int_cstu (tkind_type, tkind));
14060 2411 : break;
14061 :
14062 86 : case OMP_CLAUSE_USES_ALLOCATORS:
14063 86 : tree allocator = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
14064 86 : tree memspace = OMP_CLAUSE_USES_ALLOCATORS_MEMSPACE (c);
14065 86 : tree traits = OMP_CLAUSE_USES_ALLOCATORS_TRAITS (c);
14066 :
14067 86 : tree ntraits, traits_var;
14068 86 : if (traits == NULL_TREE)
14069 : {
14070 29 : ntraits = integer_zero_node;
14071 29 : traits_var = null_pointer_node;
14072 : }
14073 : else
14074 : {
14075 57 : location_t loc = OMP_CLAUSE_LOCATION (c);
14076 57 : ntraits = array_type_nelts_top (TREE_TYPE (traits));
14077 57 : traits_var = build_fold_addr_expr_loc (loc, traits);
14078 : }
14079 :
14080 86 : if (memspace == NULL_TREE)
14081 61 : memspace = build_int_cst (pointer_sized_int_node, 0);
14082 : else
14083 25 : memspace = fold_convert (pointer_sized_int_node, memspace);
14084 :
14085 86 : tree arr_type
14086 86 : = build_array_type_nelts (pointer_sized_int_node, 3);
14087 86 : tree uses_allocators_descr
14088 86 : = create_tmp_var (arr_type, "uses_allocator_descr");
14089 86 : tree ua_descr[3];
14090 344 : for (int i = 0; i < 3; i++)
14091 258 : ua_descr[i] = build4 (ARRAY_REF, pointer_sized_int_node,
14092 : uses_allocators_descr,
14093 258 : build_int_cst (size_type_node, i),
14094 : NULL_TREE, NULL_TREE);
14095 86 : gimplify_assign (ua_descr[0],
14096 : fold_convert (pointer_sized_int_node, memspace),
14097 : &ilist);
14098 86 : gimplify_assign (ua_descr[1],
14099 : fold_convert (pointer_sized_int_node, ntraits),
14100 : &ilist);
14101 86 : gimplify_assign (ua_descr[2],
14102 : fold_convert (pointer_sized_int_node, traits_var),
14103 : &ilist);
14104 :
14105 86 : x = build_sender_ref (allocator, ctx);
14106 86 : tree ptr = build_fold_addr_expr (uses_allocators_descr);
14107 86 : gimplify_assign (x, fold_convert (TREE_TYPE (x), ptr), &ilist);
14108 :
14109 86 : s = size_int (0);
14110 86 : purpose = size_int (map_idx++);
14111 86 : CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
14112 86 : tkind = GOMP_MAP_USES_ALLOCATORS;
14113 86 : gcc_checking_assert (tkind
14114 : < (HOST_WIDE_INT_C (1U) << talign_shift));
14115 86 : talign = TYPE_ALIGN_UNIT (pointer_sized_int_node);
14116 86 : talign = ceil_log2 (talign);
14117 86 : tkind |= talign << talign_shift;
14118 86 : gcc_checking_assert (tkind
14119 : <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14120 86 : CONSTRUCTOR_APPEND_ELT (vkind, purpose,
14121 : build_int_cstu (tkind_type, tkind));
14122 86 : break;
14123 : }
14124 :
14125 32279 : gcc_assert (map_idx == map_cnt);
14126 :
14127 32279 : if (!deep_map_cnt)
14128 : {
14129 32135 : DECL_INITIAL (TREE_VEC_ELT (t, 1))
14130 32135 : = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
14131 32135 : DECL_INITIAL (TREE_VEC_ELT (t, 2))
14132 64270 : = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
14133 : }
14134 96837 : for (int i = 1; i <= 2; i++)
14135 64558 : if (deep_map_cnt || !TREE_STATIC (TREE_VEC_ELT (t, i)))
14136 : {
14137 9657 : tree tmp = TREE_VEC_ELT (t, i);
14138 9657 : if (deep_map_cnt)
14139 : {
14140 288 : const char *prefix = (i == 1 ? ".omp_data_sizes0"
14141 : : ".omp_data_kinds0");
14142 144 : tree type = (i == 1) ? size_type_node : tkind_type;
14143 288 : type = build_array_type_nelts (type, map_cnt);
14144 288 : tree var = create_tmp_var (type, prefix);
14145 288 : DECL_NAMELESS (var) = 1;
14146 288 : TREE_ADDRESSABLE (var) = 1;
14147 288 : TREE_STATIC (var) = TREE_STATIC (tmp);
14148 288 : DECL_INITIAL (var) = build_constructor (type, i == 1
14149 : ? vsize : vkind);
14150 288 : tmp = var;
14151 288 : TREE_STATIC (TREE_VEC_ELT (t, i)) = 0;
14152 : }
14153 :
14154 9657 : gimple_seq initlist = NULL;
14155 9657 : force_gimple_operand (build1 (DECL_EXPR, void_type_node, tmp),
14156 : &initlist, true, NULL_TREE);
14157 9657 : gimple_seq_add_seq (&ilist, initlist);
14158 :
14159 9657 : if (deep_map_cnt)
14160 : {
14161 288 : tree tmp2;
14162 288 : tree call = builtin_decl_explicit (BUILT_IN_MEMCPY);
14163 288 : tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
14164 576 : call = build_call_expr_loc (input_location, call, 3,
14165 288 : TREE_VEC_ELT (t, i),
14166 : build_fold_addr_expr (tmp), tmp2);
14167 288 : gimplify_and_add (call, &ilist);
14168 : }
14169 :
14170 9657 : if (!TREE_STATIC (tmp))
14171 : {
14172 9439 : tree clobber = build_clobber (TREE_TYPE (tmp));
14173 9439 : gimple_seq_add_stmt (&olist,
14174 9439 : gimple_build_assign (tmp, clobber));
14175 : }
14176 9657 : if (deep_map_cnt)
14177 : {
14178 288 : tmp = TREE_VEC_ELT (t, i);
14179 288 : tree call = builtin_decl_explicit (BUILT_IN_FREE);
14180 288 : call = build_call_expr_loc (input_location, call, 1, tmp);
14181 288 : gimplify_and_add (call, &olist);
14182 288 : tree clobber = build_clobber (TREE_TYPE (tmp));
14183 288 : gimple_seq_add_stmt (&olist,
14184 288 : gimple_build_assign (tmp, clobber));
14185 : }
14186 : }
14187 54901 : else if (omp_maybe_offloaded_ctx (ctx->outer))
14188 : {
14189 3296 : tree id = get_identifier ("omp declare target");
14190 3296 : tree decl = TREE_VEC_ELT (t, i);
14191 3296 : DECL_ATTRIBUTES (decl)
14192 3296 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
14193 3296 : varpool_node *node = varpool_node::get (decl);
14194 3296 : if (node)
14195 : {
14196 0 : node->offloadable = 1;
14197 0 : if (ENABLE_OFFLOADING)
14198 : {
14199 : g->have_offload = true;
14200 : vec_safe_push (offload_vars, t);
14201 : }
14202 : }
14203 : }
14204 :
14205 32279 : if (deep_map_cnt)
14206 : {
14207 144 : tree call = builtin_decl_explicit (BUILT_IN_FREE);
14208 144 : call = build_call_expr_loc (input_location, call, 1,
14209 144 : TREE_VEC_ELT (t, 0));
14210 144 : gimplify_and_add (call, &olist);
14211 :
14212 144 : gimplify_expr (&TREE_VEC_ELT (t, 1), &ilist, NULL, is_gimple_val,
14213 : fb_rvalue);
14214 : }
14215 :
14216 32279 : tree clobber = build_clobber (TREE_TYPE (ctx->sender_decl));
14217 32279 : gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14218 : clobber));
14219 : }
14220 :
14221 : /* Once all the expansions are done, sequence all the different
14222 : fragments inside gimple_omp_body. */
14223 :
14224 37170 : new_body = NULL;
14225 :
14226 37170 : if (offloaded
14227 21210 : && ctx->record_type)
14228 : {
14229 16556 : t = ctx->sender_decl;
14230 16556 : if (!deep_map_cnt)
14231 16449 : t = build_fold_addr_expr_loc (loc, t);
14232 : /* fixup_child_record_type might have changed receiver_decl's type. */
14233 16556 : t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
14234 16556 : if (!AGGREGATE_TYPE_P (TREE_TYPE (ctx->sender_decl)))
14235 107 : gimplify_assign (ctx->receiver_decl, t, &new_body);
14236 : else
14237 16449 : gimple_seq_add_stmt (&new_body,
14238 16449 : gimple_build_assign (ctx->receiver_decl, t));
14239 : }
14240 37170 : gimple_seq_add_seq (&new_body, fplist);
14241 :
14242 37170 : if (offloaded || data_region)
14243 : {
14244 141173 : tree prev = NULL_TREE;
14245 : bool by_ref;
14246 141173 : for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14247 115942 : switch (OMP_CLAUSE_CODE (c))
14248 : {
14249 : tree var, x, new_var, *allocate_ptr;
14250 : default:
14251 : break;
14252 15306 : case OMP_CLAUSE_FIRSTPRIVATE:
14253 15306 : omp_firstprivatize_data_region:
14254 15306 : if (is_gimple_omp_oacc (ctx->stmt))
14255 : break;
14256 11410 : var = OMP_CLAUSE_DECL (c);
14257 11410 : new_var = lookup_decl (var, ctx);
14258 11410 : allocate_ptr = alloc_map.get (new_var);
14259 11410 : by_ref = omp_privatize_by_reference (var);
14260 11410 : if (allocate_ptr)
14261 : {
14262 65 : if (is_variable_sized (var, by_ref))
14263 : /* Handle this in the next pass when the size is
14264 : available. */
14265 : break;
14266 :
14267 50 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14268 50 : gcc_assert (allocate_seq);
14269 50 : gimple_seq_add_seq (&new_body, *allocate_seq);
14270 :
14271 50 : if (by_ref)
14272 : {
14273 4 : x = fold_convert (TREE_TYPE (new_var), *allocate_ptr);
14274 4 : gimplify_assign (new_var, x, &new_body);
14275 4 : new_var = build_fold_indirect_ref (new_var);
14276 : }
14277 : else
14278 46 : new_var = build_simple_mem_ref (*allocate_ptr);
14279 : }
14280 11395 : if (by_ref || is_gimple_reg_type (TREE_TYPE (var)))
14281 : {
14282 11254 : tree type;
14283 11254 : type = TREE_TYPE (var);
14284 11254 : if (by_ref)
14285 815 : type = TREE_TYPE (type);
14286 11254 : if ((INTEGRAL_TYPE_P (type)
14287 11004 : && TYPE_PRECISION (type) <= POINTER_SIZE)
14288 11264 : || TREE_CODE (type) == POINTER_TYPE)
14289 : {
14290 11149 : x = build_receiver_ref (var, false, ctx);
14291 11149 : if (TREE_CODE (type) != POINTER_TYPE)
14292 10994 : x = fold_convert (pointer_sized_int_node, x);
14293 11149 : x = fold_convert (type, x);
14294 11149 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14295 : fb_rvalue);
14296 11149 : if (by_ref && !allocate_ptr)
14297 : {
14298 772 : tree v = create_tmp_var_raw (type, get_name (var));
14299 772 : gimple_add_tmp_var (v);
14300 772 : TREE_ADDRESSABLE (v) = 1;
14301 772 : gimple_seq_add_stmt (&new_body,
14302 772 : gimple_build_assign (v, x));
14303 772 : x = build_fold_addr_expr (v);
14304 : }
14305 11149 : gimplify_assign (new_var, x, &new_body);
14306 : }
14307 : else
14308 : {
14309 105 : x = build_receiver_ref (var, allocate_ptr || !by_ref, ctx);
14310 105 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14311 : fb_rvalue);
14312 105 : gimplify_assign (new_var, x, &new_body);
14313 : }
14314 : }
14315 141 : else if (is_variable_sized (var))
14316 : {
14317 4 : tree pvar = DECL_VALUE_EXPR (var);
14318 4 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14319 4 : pvar = TREE_OPERAND (pvar, 0);
14320 4 : gcc_assert (DECL_P (pvar));
14321 4 : tree new_var = lookup_decl (pvar, ctx);
14322 4 : x = build_receiver_ref (var, false, ctx);
14323 4 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14324 4 : gimple_seq_add_stmt (&new_body,
14325 4 : gimple_build_assign (new_var, x));
14326 : }
14327 137 : else if (allocate_ptr)
14328 : {
14329 19 : x = build_receiver_ref (var, true, ctx);
14330 19 : new_var = unshare_expr (new_var);
14331 19 : x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
14332 19 : gimplify_and_add (x, &new_body);
14333 : }
14334 : break;
14335 228 : case OMP_CLAUSE_PRIVATE:
14336 228 : if (is_gimple_omp_oacc (ctx->stmt))
14337 : break;
14338 148 : var = OMP_CLAUSE_DECL (c);
14339 148 : new_var = lookup_decl (var, ctx);
14340 148 : allocate_ptr = alloc_map.get (new_var);
14341 148 : by_ref = omp_privatize_by_reference (var);
14342 148 : if (allocate_ptr)
14343 : {
14344 57 : if (is_variable_sized (var, by_ref))
14345 : /* Handle this in the next pass when the size is
14346 : available. */
14347 : break;
14348 :
14349 45 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14350 45 : gcc_assert (allocate_seq);
14351 45 : gimple_seq_add_seq (&new_body, *allocate_seq);
14352 :
14353 45 : if (!by_ref)
14354 44 : new_var = build_simple_mem_ref (*allocate_ptr);
14355 : }
14356 135 : if (by_ref)
14357 : {
14358 12 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14359 12 : if (!allocate_ptr)
14360 : {
14361 11 : x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
14362 11 : if (TREE_CONSTANT (x))
14363 : {
14364 3 : x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
14365 : get_name (var));
14366 3 : gimple_add_tmp_var (x);
14367 3 : TREE_ADDRESSABLE (x) = 1;
14368 3 : x = build_fold_addr_expr_loc (clause_loc, x);
14369 : }
14370 : else
14371 : break;
14372 :
14373 3 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
14374 3 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14375 : fb_rvalue);
14376 : }
14377 : else
14378 1 : x = *allocate_ptr;
14379 :
14380 4 : gimple_seq_add_stmt (&new_body,
14381 4 : gimple_build_assign (new_var, x));
14382 : }
14383 : break;
14384 2430 : case OMP_CLAUSE_USE_DEVICE_PTR:
14385 2430 : case OMP_CLAUSE_USE_DEVICE_ADDR:
14386 2430 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14387 2430 : case OMP_CLAUSE_IS_DEVICE_PTR:
14388 2430 : gimple_seq assign_body;
14389 2430 : bool is_array_data;
14390 2430 : bool do_optional_check;
14391 2430 : assign_body = NULL;
14392 2430 : do_optional_check = false;
14393 2430 : var = OMP_CLAUSE_DECL (c);
14394 2430 : is_array_data = lang_hooks.decls.omp_array_data (var, true) != NULL;
14395 2430 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR && is_array_data)
14396 19 : goto omp_firstprivatize_data_region;
14397 :
14398 2411 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR
14399 2411 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
14400 4108 : x = build_sender_ref (is_array_data
14401 601 : ? (splay_tree_key) &DECL_NAME (var)
14402 1453 : : (splay_tree_key) &DECL_UID (var), ctx);
14403 : else
14404 : {
14405 357 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
14406 : {
14407 233 : while (TREE_CODE (var) == INDIRECT_REF
14408 233 : || TREE_CODE (var) == ARRAY_REF)
14409 17 : var = TREE_OPERAND (var, 0);
14410 : }
14411 357 : x = build_receiver_ref (var, false, ctx);
14412 : }
14413 :
14414 2411 : if (is_array_data)
14415 : {
14416 601 : bool is_ref = omp_privatize_by_reference (var);
14417 601 : do_optional_check = true;
14418 : /* First, we copy the descriptor data from the host; then
14419 : we update its data to point to the target address. */
14420 601 : new_var = lookup_decl (var, ctx);
14421 601 : new_var = DECL_VALUE_EXPR (new_var);
14422 601 : tree v = new_var;
14423 601 : tree v2 = var;
14424 601 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR
14425 601 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR)
14426 601 : v2 = maybe_lookup_decl_in_outer_ctx (var, ctx);
14427 :
14428 601 : if (is_ref)
14429 : {
14430 396 : v2 = build_fold_indirect_ref (v2);
14431 396 : v = create_tmp_var_raw (TREE_TYPE (v2), get_name (var));
14432 396 : gimple_add_tmp_var (v);
14433 396 : TREE_ADDRESSABLE (v) = 1;
14434 396 : gimplify_assign (v, v2, &assign_body);
14435 396 : tree rhs = build_fold_addr_expr (v);
14436 396 : gimple_seq_add_stmt (&assign_body,
14437 396 : gimple_build_assign (new_var, rhs));
14438 : }
14439 : else
14440 205 : gimplify_assign (new_var, v2, &assign_body);
14441 :
14442 601 : v2 = lang_hooks.decls.omp_array_data (unshare_expr (v), false);
14443 601 : gcc_assert (v2);
14444 601 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14445 1202 : gimple_seq_add_stmt (&assign_body,
14446 601 : gimple_build_assign (v2, x));
14447 : }
14448 1810 : else if (is_variable_sized (var))
14449 : {
14450 12 : tree pvar = DECL_VALUE_EXPR (var);
14451 12 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14452 12 : pvar = TREE_OPERAND (pvar, 0);
14453 12 : gcc_assert (DECL_P (pvar));
14454 12 : new_var = lookup_decl (pvar, ctx);
14455 12 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14456 24 : gimple_seq_add_stmt (&assign_body,
14457 12 : gimple_build_assign (new_var, x));
14458 : }
14459 1798 : else if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_ADDR
14460 536 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
14461 1476 : && !omp_privatize_by_reference (var)
14462 504 : && !omp_is_allocatable_or_ptr (var))
14463 3231 : || TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
14464 : {
14465 389 : new_var = lookup_decl (var, ctx);
14466 389 : new_var = DECL_VALUE_EXPR (new_var);
14467 389 : gcc_assert (TREE_CODE (new_var) == MEM_REF);
14468 389 : new_var = TREE_OPERAND (new_var, 0);
14469 389 : gcc_assert (DECL_P (new_var));
14470 389 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14471 778 : gimple_seq_add_stmt (&assign_body,
14472 389 : gimple_build_assign (new_var, x));
14473 : }
14474 : else
14475 : {
14476 1409 : tree type = TREE_TYPE (var);
14477 1409 : new_var = lookup_decl (var, ctx);
14478 1409 : if (omp_privatize_by_reference (var))
14479 : {
14480 1039 : type = TREE_TYPE (type);
14481 1039 : if (POINTER_TYPE_P (type)
14482 1039 : && TREE_CODE (type) != ARRAY_TYPE
14483 1398 : && ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_USE_DEVICE_ADDR
14484 36 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR)
14485 331 : || (omp_privatize_by_reference (var)
14486 331 : && omp_is_allocatable_or_ptr (var))))
14487 : {
14488 357 : tree v = create_tmp_var_raw (type, get_name (var));
14489 357 : gimple_add_tmp_var (v);
14490 357 : TREE_ADDRESSABLE (v) = 1;
14491 357 : x = fold_convert (type, x);
14492 357 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val,
14493 : fb_rvalue);
14494 357 : gimple_seq_add_stmt (&assign_body,
14495 357 : gimple_build_assign (v, x));
14496 357 : x = build_fold_addr_expr (v);
14497 357 : do_optional_check = true;
14498 : }
14499 : }
14500 1409 : new_var = DECL_VALUE_EXPR (new_var);
14501 1409 : x = fold_convert (TREE_TYPE (new_var), x);
14502 1409 : gimplify_expr (&x, &assign_body, NULL, is_gimple_val, fb_rvalue);
14503 1409 : gimple_seq_add_stmt (&assign_body,
14504 1409 : gimple_build_assign (new_var, x));
14505 : }
14506 2411 : tree present;
14507 1002 : present = ((do_optional_check
14508 958 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_HAS_DEVICE_ADDR
14509 952 : && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IS_DEVICE_PTR)
14510 2342 : ? omp_check_optional_argument (OMP_CLAUSE_DECL (c), true)
14511 : : NULL_TREE);
14512 2411 : if (present)
14513 : {
14514 480 : tree null_label = create_artificial_label (UNKNOWN_LOCATION);
14515 480 : tree notnull_label = create_artificial_label (UNKNOWN_LOCATION);
14516 480 : tree opt_arg_label = create_artificial_label (UNKNOWN_LOCATION);
14517 480 : glabel *null_glabel = gimple_build_label (null_label);
14518 480 : glabel *notnull_glabel = gimple_build_label (notnull_label);
14519 480 : ggoto *opt_arg_ggoto = gimple_build_goto (opt_arg_label);
14520 480 : gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14521 : fb_rvalue);
14522 480 : gimplify_expr (&present, &new_body, NULL, is_gimple_val,
14523 : fb_rvalue);
14524 480 : gcond *cond = gimple_build_cond_from_tree (present,
14525 : notnull_label,
14526 : null_label);
14527 480 : gimple_seq_add_stmt (&new_body, cond);
14528 480 : gimple_seq_add_stmt (&new_body, null_glabel);
14529 480 : gimplify_assign (new_var, null_pointer_node, &new_body);
14530 480 : gimple_seq_add_stmt (&new_body, opt_arg_ggoto);
14531 480 : gimple_seq_add_stmt (&new_body, notnull_glabel);
14532 480 : gimple_seq_add_seq (&new_body, assign_body);
14533 480 : gimple_seq_add_stmt (&new_body,
14534 480 : gimple_build_label (opt_arg_label));
14535 : }
14536 : else
14537 1931 : gimple_seq_add_seq (&new_body, assign_body);
14538 : break;
14539 : }
14540 : /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
14541 : so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
14542 : are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
14543 : or references to VLAs. */
14544 141173 : for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14545 115942 : switch (OMP_CLAUSE_CODE (c))
14546 : {
14547 : tree var, new_var, *allocate_ptr;
14548 : default:
14549 100675 : break;
14550 63539 : case OMP_CLAUSE_MAP:
14551 63539 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
14552 63539 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
14553 : {
14554 3669 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14555 3669 : poly_int64 offset = 0;
14556 3669 : gcc_assert (prev);
14557 3669 : var = OMP_CLAUSE_DECL (c);
14558 3669 : if (DECL_P (var)
14559 3669 : && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
14560 1125 : && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
14561 : ctx))
14562 3767 : && varpool_node::get_create (var)->offloadable)
14563 : break;
14564 3667 : if (TREE_CODE (var) == INDIRECT_REF
14565 3667 : && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
14566 0 : var = TREE_OPERAND (var, 0);
14567 3667 : if (TREE_CODE (var) == COMPONENT_REF)
14568 : {
14569 0 : var = get_addr_base_and_unit_offset (var, &offset);
14570 0 : gcc_assert (var != NULL_TREE && DECL_P (var));
14571 : }
14572 3667 : else if (DECL_SIZE (var)
14573 3667 : && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
14574 : {
14575 710 : tree var2 = DECL_VALUE_EXPR (var);
14576 710 : gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
14577 710 : var2 = TREE_OPERAND (var2, 0);
14578 710 : gcc_assert (DECL_P (var2));
14579 : var = var2;
14580 : }
14581 3667 : tree new_var = lookup_decl (var, ctx), x;
14582 3667 : tree type = TREE_TYPE (new_var);
14583 3667 : bool is_ref;
14584 3667 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
14585 3667 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14586 : == COMPONENT_REF))
14587 : {
14588 0 : type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
14589 0 : is_ref = true;
14590 0 : new_var = build2 (MEM_REF, type,
14591 : build_fold_addr_expr (new_var),
14592 : build_int_cst (build_pointer_type (type),
14593 : offset));
14594 : }
14595 3667 : else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
14596 : {
14597 0 : type = TREE_TYPE (OMP_CLAUSE_DECL (c));
14598 0 : is_ref = TREE_CODE (type) == REFERENCE_TYPE;
14599 0 : new_var = build2 (MEM_REF, type,
14600 : build_fold_addr_expr (new_var),
14601 : build_int_cst (build_pointer_type (type),
14602 : offset));
14603 : }
14604 : else
14605 3667 : is_ref = omp_privatize_by_reference (var);
14606 3667 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
14607 : is_ref = false;
14608 6705 : bool ref_to_array = false;
14609 6705 : bool ref_to_ptr = false;
14610 3238 : if (is_ref)
14611 : {
14612 200 : type = TREE_TYPE (type);
14613 200 : if (TREE_CODE (type) == ARRAY_TYPE)
14614 : {
14615 194 : type = build_pointer_type (type);
14616 194 : ref_to_array = true;
14617 : }
14618 : }
14619 3467 : else if (TREE_CODE (type) == ARRAY_TYPE)
14620 : {
14621 413 : tree decl2 = DECL_VALUE_EXPR (new_var);
14622 413 : gcc_assert (TREE_CODE (decl2) == MEM_REF);
14623 413 : decl2 = TREE_OPERAND (decl2, 0);
14624 413 : gcc_assert (DECL_P (decl2));
14625 413 : new_var = decl2;
14626 413 : type = TREE_TYPE (new_var);
14627 : }
14628 3054 : else if (TREE_CODE (type) == REFERENCE_TYPE
14629 3054 : && TREE_CODE (TREE_TYPE (type)) == POINTER_TYPE)
14630 : {
14631 156 : type = TREE_TYPE (type);
14632 156 : ref_to_ptr = true;
14633 : }
14634 3667 : x = build_receiver_ref (prev, false, ctx);
14635 3667 : x = fold_convert_loc (clause_loc, type, x);
14636 3667 : if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
14637 : {
14638 762 : tree bias = OMP_CLAUSE_SIZE (c);
14639 762 : if (DECL_P (bias))
14640 364 : bias = lookup_decl (bias, ctx);
14641 762 : bias = fold_convert_loc (clause_loc, sizetype, bias);
14642 762 : bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
14643 : bias);
14644 762 : x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
14645 762 : TREE_TYPE (x), x, bias);
14646 : }
14647 3667 : if (ref_to_array)
14648 194 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
14649 3667 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14650 3667 : if ((is_ref && !ref_to_array)
14651 3661 : || ref_to_ptr)
14652 : {
14653 162 : tree t = create_tmp_var_raw (type, get_name (var));
14654 162 : gimple_add_tmp_var (t);
14655 162 : TREE_ADDRESSABLE (t) = 1;
14656 162 : gimple_seq_add_stmt (&new_body,
14657 162 : gimple_build_assign (t, x));
14658 162 : x = build_fold_addr_expr_loc (clause_loc, t);
14659 : }
14660 3667 : gimple_seq_add_stmt (&new_body,
14661 3667 : gimple_build_assign (new_var, x));
14662 3667 : prev = NULL_TREE;
14663 : }
14664 59870 : else if (OMP_CLAUSE_CHAIN (c)
14665 43260 : && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
14666 : == OMP_CLAUSE_MAP
14667 97696 : && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
14668 : == GOMP_MAP_FIRSTPRIVATE_POINTER
14669 34586 : || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
14670 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
14671 : prev = c;
14672 : break;
14673 228 : case OMP_CLAUSE_PRIVATE:
14674 228 : var = OMP_CLAUSE_DECL (c);
14675 228 : by_ref = omp_privatize_by_reference (var);
14676 228 : new_var = lookup_decl (var, ctx);
14677 228 : allocate_ptr = alloc_map.get (new_var);
14678 228 : if (is_variable_sized (var, by_ref)
14679 228 : || (!allocate_ptr && by_ref && !is_gimple_omp_oacc (ctx->stmt)))
14680 : {
14681 24 : if (allocate_ptr)
14682 : {
14683 12 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14684 12 : gcc_assert (allocate_seq);
14685 12 : gimple_seq_add_seq (&new_body, *allocate_seq);
14686 : }
14687 24 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14688 24 : tree pvar = var;
14689 24 : if (!by_ref)
14690 : {
14691 3 : pvar = DECL_VALUE_EXPR (var);
14692 3 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14693 3 : pvar = TREE_OPERAND (pvar, 0);
14694 : }
14695 24 : gcc_assert (DECL_P (pvar));
14696 24 : tree new_pvar = lookup_decl (pvar, ctx);
14697 24 : tree x;
14698 24 : if (!allocate_ptr)
14699 : {
14700 12 : tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
14701 12 : tree ty = TREE_TYPE (new_var);
14702 12 : if (by_ref)
14703 11 : ty = TREE_TYPE (ty);
14704 12 : x = TYPE_SIZE_UNIT (ty);
14705 12 : if (TREE_CONSTANT (x))
14706 : break;
14707 9 : tree al = size_int (TYPE_ALIGN (ty));
14708 9 : x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
14709 9 : x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
14710 : }
14711 : else
14712 12 : x = *allocate_ptr;
14713 21 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14714 21 : gimple_seq_add_stmt (&new_body,
14715 21 : gimple_build_assign (new_pvar, x));
14716 : }
14717 : break;
14718 15287 : case OMP_CLAUSE_FIRSTPRIVATE:
14719 15287 : var = OMP_CLAUSE_DECL (c);
14720 15287 : by_ref = omp_privatize_by_reference (var);
14721 15287 : if (is_variable_sized (var, by_ref))
14722 : {
14723 35 : tree new_var = lookup_decl (var, ctx);
14724 35 : tree *allocate_ptr = alloc_map.get (new_var);
14725 35 : if (!allocate_ptr)
14726 : break;
14727 15 : gimple_seq *allocate_seq = alloc_seq_map.get (new_var);
14728 15 : gcc_assert (allocate_seq);
14729 15 : gimple_seq_add_seq (&new_body, *allocate_seq);
14730 :
14731 15 : location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14732 15 : tree pvar = var;
14733 15 : if (!by_ref)
14734 : {
14735 2 : pvar = DECL_VALUE_EXPR (var);
14736 2 : gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14737 2 : pvar = TREE_OPERAND (pvar, 0);
14738 : }
14739 15 : gcc_assert (DECL_P (pvar));
14740 15 : tree new_pvar = lookup_decl (pvar, ctx);
14741 15 : tree x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar),
14742 15 : *allocate_ptr);
14743 15 : gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14744 15 : gimple_seq_add_stmt (&new_body,
14745 15 : gimple_build_assign (new_pvar, x));
14746 :
14747 15 : x = build_receiver_ref (var, true, ctx);
14748 15 : new_var = unshare_expr (new_var);
14749 15 : if (by_ref)
14750 13 : new_var = build_fold_indirect_ref (new_var);
14751 15 : x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
14752 15 : gimplify_and_add (x, &new_body);
14753 : }
14754 : }
14755 :
14756 25231 : gimple_seq fork_seq = NULL;
14757 25231 : gimple_seq join_seq = NULL;
14758 :
14759 25231 : if (offloaded && is_gimple_omp_oacc (ctx->stmt))
14760 : {
14761 : /* If there are reductions on the offloaded region itself, treat
14762 : them as a dummy GANG loop. */
14763 9395 : tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
14764 :
14765 9395 : gcall *private_marker = lower_oacc_private_marker (ctx);
14766 :
14767 9395 : if (private_marker)
14768 30 : gimple_call_set_arg (private_marker, 2, level);
14769 :
14770 9395 : lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
14771 : false, NULL, private_marker, NULL, &fork_seq,
14772 : &join_seq, ctx);
14773 : }
14774 :
14775 25231 : gimple_seq_add_seq (&new_body, fork_seq);
14776 25231 : gimple_seq_add_seq (&new_body, tgt_body);
14777 25231 : gimple_seq_add_seq (&new_body, join_seq);
14778 25231 : gimple_seq_add_seq (&new_body, alloc_dlist);
14779 :
14780 25231 : if (offloaded)
14781 : {
14782 21210 : new_body = maybe_catch_exception (new_body);
14783 21210 : gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14784 : }
14785 25231 : gimple_omp_set_body (stmt, new_body);
14786 : }
14787 :
14788 37170 : gsi_insert_seq_before (gsi_p, gimple_omp_target_iterator_loops (stmt),
14789 : GSI_SAME_STMT);
14790 37170 : gimple_omp_target_set_iterator_loops (stmt, NULL);
14791 58380 : bind = gimple_build_bind (NULL, NULL,
14792 21210 : tgt_bind ? gimple_bind_block (tgt_bind)
14793 : : NULL_TREE);
14794 73948 : gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14795 37170 : gimple_bind_add_seq (bind, ilist);
14796 37170 : gimple_bind_add_stmt (bind, stmt);
14797 37170 : gimple_bind_add_seq (bind, olist);
14798 :
14799 37170 : pop_gimplify_context (NULL);
14800 :
14801 37170 : if (dep_bind)
14802 : {
14803 392 : gimple_bind_add_seq (dep_bind, dep_ilist);
14804 392 : gimple_bind_add_stmt (dep_bind, bind);
14805 392 : gimple_bind_add_seq (dep_bind, dep_olist);
14806 392 : pop_gimplify_context (dep_bind);
14807 : }
14808 37170 : }
14809 :
14810 : /* Generate code to implement the action-clauses (destroy, init, use) of an
14811 : OpenMP interop construct. */
14812 :
14813 : static void
14814 492 : lower_omp_interop_action_clauses (gimple_seq *seq, vec<tree> &objs,
14815 : vec<tree> *interop_types = NULL,
14816 : vec<tree> *prefer_types = NULL)
14817 : {
14818 492 : if (objs.length () == 0)
14819 229 : return;
14820 :
14821 263 : enum omp_clause_code action = OMP_CLAUSE_CODE (objs[0]);
14822 263 : if (action == OMP_CLAUSE_INIT)
14823 402 : gcc_checking_assert (objs.length () == interop_types->length ()
14824 : && objs.length () == prefer_types->length ());
14825 : else
14826 129 : gcc_assert (prefer_types == NULL && interop_types == NULL);
14827 :
14828 263 : tree ret_objs = NULL_TREE, ret_interop_types = NULL_TREE,
14829 263 : ret_prefer_types = NULL_TREE;
14830 :
14831 : /* Build an array of interop objects. */
14832 :
14833 263 : tree type_obj_pref = build_array_type_nelts (ptr_type_node, objs.length ());
14834 263 : ret_objs = create_tmp_var (type_obj_pref, "interopobjs");
14835 :
14836 263 : bool have_pref_type = false;
14837 263 : if (action == OMP_CLAUSE_INIT)
14838 : {
14839 592 : for (tree pref_type : prefer_types)
14840 260 : if (pref_type != NULL_TREE)
14841 : {
14842 : have_pref_type = true;
14843 : break;
14844 : }
14845 134 : tree type_tgtsync
14846 134 : = build_array_type_nelts (integer_type_node, objs.length ());
14847 134 : ret_interop_types = create_tmp_var (type_tgtsync, "tgt_tgtsync");
14848 134 : if (have_pref_type)
14849 70 : ret_prefer_types = create_tmp_var (type_obj_pref, "pref_type");
14850 : else
14851 : {
14852 64 : ret_prefer_types = null_pointer_node;
14853 64 : prefer_types->truncate (0);
14854 : }
14855 : }
14856 :
14857 856 : for (size_t i = 0; !objs.is_empty (); i++)
14858 : {
14859 593 : tree offset = build_int_cst (integer_type_node, i);
14860 593 : tree init = build4 (ARRAY_REF, ptr_type_node, ret_objs, offset, NULL_TREE,
14861 : NULL_TREE);
14862 593 : tree obj = OMP_CLAUSE_DECL (objs.pop ());
14863 593 : if (TREE_CODE (TREE_TYPE (obj)) == REFERENCE_TYPE)
14864 6 : obj = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (obj)), obj);
14865 593 : if (action != OMP_CLAUSE_USE
14866 593 : && TREE_CODE (TREE_TYPE (obj)) != POINTER_TYPE)
14867 : /* For modifying actions, we need a pointer. */
14868 483 : obj = build_fold_addr_expr (obj);
14869 110 : else if (action == OMP_CLAUSE_USE
14870 110 : && TREE_CODE (TREE_TYPE (obj)) == POINTER_TYPE)
14871 : /* For use action, we need the value. */
14872 2 : obj = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (obj)), obj);
14873 593 : init = build2 (MODIFY_EXPR, ptr_type_node, init,
14874 : fold_convert (ptr_type_node, obj));
14875 593 : gimplify_and_add (init, seq);
14876 :
14877 593 : if (action == OMP_CLAUSE_INIT)
14878 : {
14879 384 : init = build4 (ARRAY_REF, integer_type_node, ret_interop_types,
14880 : offset, NULL_TREE, NULL_TREE);
14881 384 : init = build2 (MODIFY_EXPR, integer_type_node, init,
14882 384 : interop_types->pop ());
14883 384 : gimplify_and_add (init, seq);
14884 :
14885 384 : if (have_pref_type)
14886 : {
14887 194 : tree prefer_type = prefer_types->pop ();
14888 194 : tree pref = (prefer_type == NULL_TREE
14889 194 : ? null_pointer_node
14890 194 : : build_fold_addr_expr (prefer_type));
14891 194 : init = build4 (ARRAY_REF, ptr_type_node, ret_prefer_types, offset,
14892 : NULL_TREE, NULL_TREE);
14893 194 : init = build2 (MODIFY_EXPR, ptr_type_node, init, pref);
14894 194 : gimplify_and_add (init, seq);
14895 : }
14896 : }
14897 : }
14898 263 : if (action == OMP_CLAUSE_INIT)
14899 : {
14900 134 : if (have_pref_type)
14901 70 : ret_prefer_types = build_fold_addr_expr (ret_prefer_types);
14902 134 : ret_interop_types = build_fold_addr_expr (ret_interop_types);
14903 : }
14904 263 : ret_objs = build_fold_addr_expr (ret_objs);
14905 :
14906 660 : gcc_assert (objs.is_empty ()
14907 : && (!interop_types || interop_types->is_empty ())
14908 : && (!prefer_types || prefer_types->is_empty ()));
14909 :
14910 263 : objs.safe_push (ret_objs);
14911 263 : if (action == OMP_CLAUSE_INIT)
14912 : {
14913 134 : interop_types->safe_push (ret_interop_types);
14914 134 : prefer_types->safe_push (ret_prefer_types);
14915 : }
14916 : }
14917 :
14918 : /* Lower code for an OpenMP interop directive. */
14919 :
14920 : static void
14921 164 : lower_omp_interop (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14922 : {
14923 164 : push_gimplify_context ();
14924 :
14925 164 : tree block = make_node (BLOCK);
14926 164 : gbind *bind = gimple_build_bind (NULL, NULL, block);
14927 164 : gimple_seq bind_body = NULL;
14928 :
14929 : /* Emit call to GOMP_interop:
14930 : void
14931 : GOMP_interop (int device_num, int n_init, omp_interop_t **init,
14932 : const void *target_targetsync, const void *prefer_type,
14933 : int n_use, omp_interop_t *use, int n_destroy,
14934 : omp_interop_t **destroy, unsigned int flags,
14935 : void **depend) */
14936 :
14937 164 : tree flags = NULL_TREE;
14938 164 : tree depend = null_pointer_node;
14939 164 : tree device_num = NULL_TREE;
14940 :
14941 164 : auto_vec<tree> init_objs, use_objs, destroy_objs, prefer_type,
14942 164 : target_targetsync;
14943 164 : gimple_seq dep_ilist = NULL, dep_olist = NULL;
14944 164 : tree clauses = gimple_omp_interop_clauses (gsi_stmt (*gsi_p));
14945 868 : for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14946 : {
14947 704 : switch (OMP_CLAUSE_CODE (c))
14948 : {
14949 384 : case OMP_CLAUSE_INIT:
14950 384 : {
14951 384 : init_objs.safe_push (c);
14952 384 : int target_targetsync_bits = 0;
14953 384 : if (OMP_CLAUSE_INIT_TARGET (c))
14954 229 : target_targetsync_bits |= GOMP_INTEROP_TARGET;
14955 384 : if (OMP_CLAUSE_INIT_TARGETSYNC (c))
14956 204 : target_targetsync_bits |= GOMP_INTEROP_TARGETSYNC;
14957 384 : tree t = build_int_cst (integer_type_node, target_targetsync_bits);
14958 384 : target_targetsync.safe_push (t);
14959 384 : prefer_type.safe_push (OMP_CLAUSE_INIT_PREFER_TYPE (c));
14960 : }
14961 384 : break;
14962 106 : case OMP_CLAUSE_USE:
14963 106 : use_objs.safe_push (c);
14964 106 : break;
14965 103 : case OMP_CLAUSE_DESTROY:
14966 103 : destroy_objs.safe_push (c);
14967 103 : break;
14968 50 : case OMP_CLAUSE_NOWAIT:
14969 50 : flags = build_int_cst (integer_type_node, GOMP_INTEROP_FLAG_NOWAIT);
14970 50 : break;
14971 35 : case OMP_CLAUSE_DEPEND:
14972 35 : {
14973 35 : tree *cp = gimple_omp_interop_clauses_ptr (gsi_stmt (*gsi_p));
14974 35 : lower_depend_clauses (cp, &dep_ilist, &dep_olist);
14975 35 : depend = OMP_CLAUSE_DECL (*cp);
14976 : }
14977 35 : break;
14978 26 : case OMP_CLAUSE_DEVICE:
14979 26 : device_num = OMP_CLAUSE_DEVICE_ID (c);
14980 26 : break;
14981 0 : default:
14982 0 : gcc_unreachable ();
14983 : }
14984 : }
14985 :
14986 164 : if (flags == NULL_TREE)
14987 114 : flags = build_int_cst (integer_type_node, 0);
14988 :
14989 164 : if (device_num == NULL_TREE)
14990 138 : device_num = build_int_cst (integer_type_node, GOMP_DEVICE_DEFAULT_OMP_61);
14991 :
14992 298 : tree n_init = build_int_cst (integer_type_node, init_objs.length ());
14993 234 : tree n_use = build_int_cst (integer_type_node, use_objs.length ());
14994 223 : tree n_destroy = build_int_cst (integer_type_node, destroy_objs.length ());
14995 :
14996 164 : lower_omp_interop_action_clauses (&bind_body, init_objs, &target_targetsync,
14997 : &prefer_type);
14998 164 : lower_omp_interop_action_clauses (&bind_body, use_objs);
14999 164 : lower_omp_interop_action_clauses (&bind_body, destroy_objs);
15000 :
15001 164 : gimple_seq_add_seq (&bind_body, dep_ilist);
15002 164 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
15003 298 : tree init_arg = init_objs.length () ? init_objs.pop () : null_pointer_node;
15004 164 : tree target_targetsync_arg = target_targetsync.length ()
15005 134 : ? target_targetsync.pop ()
15006 164 : : null_pointer_node;
15007 164 : tree prefer_type_arg
15008 298 : = prefer_type.length () ? prefer_type.pop () : null_pointer_node;
15009 234 : tree use_arg = use_objs.length () ? use_objs.pop () : null_pointer_node;
15010 164 : tree destroy_arg
15011 223 : = destroy_objs.length () ? destroy_objs.pop () : null_pointer_node;
15012 164 : gcall *call
15013 164 : = gimple_build_call (fn, 11, device_num, n_init, init_arg,
15014 : target_targetsync_arg, prefer_type_arg, n_use, use_arg,
15015 : n_destroy, destroy_arg, flags, depend);
15016 164 : gimple_seq_add_stmt (&bind_body, call);
15017 164 : gimple_seq_add_seq (&bind_body, dep_olist);
15018 :
15019 164 : gsi_replace (gsi_p, bind, true);
15020 164 : gimple_bind_set_body (bind, bind_body);
15021 164 : pop_gimplify_context (bind);
15022 164 : gimple_bind_append_vars (bind, ctx->block_vars);
15023 164 : BLOCK_VARS (block) = ctx->block_vars;
15024 164 : }
15025 :
15026 : /* Expand code for an OpenMP teams directive. */
15027 :
15028 : static void
15029 5924 : lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15030 : {
15031 5924 : gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
15032 5924 : push_gimplify_context ();
15033 :
15034 5924 : tree block = make_node (BLOCK);
15035 5924 : gbind *bind = gimple_build_bind (NULL, NULL, block);
15036 5924 : gsi_replace (gsi_p, bind, true);
15037 5924 : gimple_seq bind_body = NULL;
15038 5924 : gimple_seq dlist = NULL;
15039 5924 : gimple_seq olist = NULL;
15040 :
15041 5924 : tree num_teams = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
15042 5924 : OMP_CLAUSE_NUM_TEAMS);
15043 5924 : tree num_teams_lower = NULL_TREE;
15044 5924 : if (num_teams == NULL_TREE)
15045 5300 : num_teams = build_int_cst (unsigned_type_node, 0);
15046 : else
15047 : {
15048 624 : num_teams_lower = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (num_teams);
15049 624 : if (num_teams_lower)
15050 : {
15051 136 : num_teams_lower = fold_convert (unsigned_type_node, num_teams_lower);
15052 136 : gimplify_expr (&num_teams_lower, &bind_body, NULL, is_gimple_val,
15053 : fb_rvalue);
15054 : }
15055 624 : num_teams = OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (num_teams);
15056 : // FIXME: Handle dim(x), cf. omp-expand.cc's get_target_arguments. */
15057 624 : if (TREE_CODE (num_teams) == TREE_LIST && TREE_CHAIN (num_teams))
15058 : {
15059 14 : num_teams_lower = TREE_VALUE (num_teams);
15060 14 : num_teams = TREE_VALUE (TREE_CHAIN (num_teams));
15061 : }
15062 610 : else if (TREE_CODE (num_teams) == TREE_LIST)
15063 80 : num_teams = TREE_VALUE (num_teams);
15064 624 : num_teams = fold_convert (unsigned_type_node, num_teams);
15065 624 : gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
15066 : }
15067 5924 : if (num_teams_lower == NULL_TREE)
15068 5774 : num_teams_lower = num_teams;
15069 5924 : tree thread_limit = omp_find_clause (gimple_omp_teams_clauses (teams_stmt),
15070 5924 : OMP_CLAUSE_THREAD_LIMIT);
15071 5924 : if (thread_limit == NULL_TREE)
15072 5446 : thread_limit = build_int_cst (unsigned_type_node, 0);
15073 : else
15074 : {
15075 478 : thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
15076 : // FIXME: Handle dim(x), cf. omp-expand.cc's get_target_arguments. */
15077 478 : if (TREE_CODE (thread_limit) == TREE_LIST)
15078 66 : thread_limit = TREE_VALUE (thread_limit);
15079 478 : thread_limit = fold_convert (unsigned_type_node, thread_limit);
15080 478 : gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
15081 : fb_rvalue);
15082 : }
15083 5924 : location_t loc = gimple_location (teams_stmt);
15084 5924 : tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS4);
15085 5924 : tree rettype = TREE_TYPE (TREE_TYPE (decl));
15086 5924 : tree first = create_tmp_var (rettype);
15087 5924 : gimple_seq_add_stmt (&bind_body,
15088 5924 : gimple_build_assign (first, build_one_cst (rettype)));
15089 5924 : tree llabel = create_artificial_label (loc);
15090 5924 : gimple_seq_add_stmt (&bind_body, gimple_build_label (llabel));
15091 5924 : gimple *call
15092 5924 : = gimple_build_call (decl, 4, num_teams_lower, num_teams, thread_limit,
15093 : first);
15094 5924 : gimple_set_location (call, loc);
15095 5924 : tree temp = create_tmp_var (rettype);
15096 5924 : gimple_call_set_lhs (call, temp);
15097 5924 : gimple_seq_add_stmt (&bind_body, call);
15098 :
15099 5924 : tree tlabel = create_artificial_label (loc);
15100 5924 : tree flabel = create_artificial_label (loc);
15101 5924 : gimple *cond = gimple_build_cond (NE_EXPR, temp, build_zero_cst (rettype),
15102 : tlabel, flabel);
15103 5924 : gimple_seq_add_stmt (&bind_body, cond);
15104 5924 : gimple_seq_add_stmt (&bind_body, gimple_build_label (tlabel));
15105 5924 : gimple_seq_add_stmt (&bind_body,
15106 5924 : gimple_build_assign (first, build_zero_cst (rettype)));
15107 :
15108 5924 : lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
15109 : &bind_body, &dlist, ctx, NULL);
15110 5924 : lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
15111 5924 : lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist,
15112 : NULL, ctx);
15113 5924 : gimple_seq_add_stmt (&bind_body, teams_stmt);
15114 :
15115 5924 : gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
15116 5924 : gimple_omp_set_body (teams_stmt, NULL);
15117 5924 : gimple_seq_add_seq (&bind_body, olist);
15118 5924 : gimple_seq_add_seq (&bind_body, dlist);
15119 5924 : gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
15120 5924 : gimple_seq_add_stmt (&bind_body, gimple_build_goto (llabel));
15121 5924 : gimple_seq_add_stmt (&bind_body, gimple_build_label (flabel));
15122 5924 : gimple_bind_set_body (bind, bind_body);
15123 :
15124 5924 : pop_gimplify_context (bind);
15125 :
15126 5924 : gimple_bind_append_vars (bind, ctx->block_vars);
15127 5924 : BLOCK_VARS (block) = ctx->block_vars;
15128 5924 : if (BLOCK_VARS (block))
15129 689 : TREE_USED (block) = 1;
15130 5924 : }
15131 :
15132 : /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
15133 : regimplified. If DATA is non-NULL, lower_omp_1 is outside
15134 : of OMP context, but with make_addressable_vars set. */
15135 :
15136 : static tree
15137 3213477 : lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
15138 : void *data)
15139 : {
15140 3213477 : tree t = *tp;
15141 :
15142 : /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
15143 3213477 : if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
15144 1495904 : && data == NULL
15145 1435454 : && DECL_HAS_VALUE_EXPR_P (t))
15146 : return t;
15147 :
15148 3107587 : if (make_addressable_vars
15149 423128 : && DECL_P (t)
15150 3312910 : && bitmap_bit_p (make_addressable_vars, DECL_UID (t)))
15151 : return t;
15152 :
15153 : /* If a global variable has been privatized, TREE_CONSTANT on
15154 : ADDR_EXPR might be wrong. */
15155 3104998 : if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
15156 109115 : recompute_tree_invariant_for_addr_expr (t);
15157 :
15158 3104998 : *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
15159 3104998 : return NULL_TREE;
15160 : }
15161 :
15162 : /* Data to be communicated between lower_omp_regimplify_operands and
15163 : lower_omp_regimplify_operands_p. */
15164 :
15165 : struct lower_omp_regimplify_operands_data
15166 : {
15167 : omp_context *ctx;
15168 : vec<tree> *decls;
15169 : };
15170 :
15171 : /* Helper function for lower_omp_regimplify_operands. Find
15172 : omp_member_access_dummy_var vars and adjust temporarily their
15173 : DECL_VALUE_EXPRs if needed. */
15174 :
15175 : static tree
15176 427063 : lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
15177 : void *data)
15178 : {
15179 427063 : tree t = omp_member_access_dummy_var (*tp);
15180 427063 : if (t)
15181 : {
15182 9 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15183 9 : lower_omp_regimplify_operands_data *ldata
15184 : = (lower_omp_regimplify_operands_data *) wi->info;
15185 9 : tree o = maybe_lookup_decl (t, ldata->ctx);
15186 9 : if (o == NULL_TREE)
15187 5 : o = maybe_lookup_decl_in_outer_ctx (t, ldata->ctx);
15188 9 : if (o != t)
15189 : {
15190 9 : ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
15191 9 : ldata->decls->safe_push (*tp);
15192 9 : tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
15193 9 : SET_DECL_VALUE_EXPR (*tp, v);
15194 : }
15195 : }
15196 427063 : *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
15197 427063 : return NULL_TREE;
15198 : }
15199 :
15200 : /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
15201 : of omp_member_access_dummy_var vars during regimplification. */
15202 :
15203 : static void
15204 108324 : lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
15205 : gimple_stmt_iterator *gsi_p)
15206 : {
15207 108324 : auto_vec<tree, 10> decls;
15208 108324 : if (ctx)
15209 : {
15210 105802 : struct walk_stmt_info wi;
15211 105802 : memset (&wi, '\0', sizeof (wi));
15212 105802 : struct lower_omp_regimplify_operands_data data;
15213 105802 : data.ctx = ctx;
15214 105802 : data.decls = &decls;
15215 105802 : wi.info = &data;
15216 105802 : walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
15217 : }
15218 108324 : gimple_regimplify_operands (stmt, gsi_p);
15219 324981 : while (!decls.is_empty ())
15220 : {
15221 9 : tree t = decls.pop ();
15222 9 : tree v = decls.pop ();
15223 9 : SET_DECL_VALUE_EXPR (t, v);
15224 : }
15225 108324 : }
15226 :
15227 : static void
15228 2508935 : lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15229 : {
15230 2508935 : gimple *stmt = gsi_stmt (*gsi_p);
15231 2508935 : struct walk_stmt_info wi;
15232 2508935 : gcall *call_stmt;
15233 :
15234 2508935 : if (gimple_has_location (stmt))
15235 2060726 : input_location = gimple_location (stmt);
15236 :
15237 2508935 : if (make_addressable_vars)
15238 154214 : memset (&wi, '\0', sizeof (wi));
15239 :
15240 : /* If we have issued syntax errors, avoid doing any heavy lifting.
15241 : Just replace the OMP directives with a NOP to avoid
15242 : confusing RTL expansion. */
15243 2508935 : if (seen_error () && is_gimple_omp (stmt))
15244 : {
15245 11363 : gsi_replace (gsi_p, gimple_build_nop (), true);
15246 11363 : return;
15247 : }
15248 :
15249 2497572 : switch (gimple_code (stmt))
15250 : {
15251 156229 : case GIMPLE_COND:
15252 156229 : {
15253 156229 : gcond *cond_stmt = as_a <gcond *> (stmt);
15254 88795 : if ((ctx || make_addressable_vars)
15255 159837 : && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
15256 : lower_omp_regimplify_p,
15257 : ctx ? NULL : &wi, NULL)
15258 136529 : || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
15259 : lower_omp_regimplify_p,
15260 : ctx ? NULL : &wi, NULL)))
15261 1247 : lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
15262 : }
15263 : break;
15264 20 : case GIMPLE_CATCH:
15265 20 : lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
15266 20 : break;
15267 0 : case GIMPLE_EH_FILTER:
15268 0 : lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
15269 0 : break;
15270 25948 : case GIMPLE_TRY:
15271 25948 : lower_omp (gimple_try_eval_ptr (stmt), ctx);
15272 25943 : lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
15273 25943 : break;
15274 0 : case GIMPLE_ASSUME:
15275 0 : lower_omp (gimple_assume_body_ptr (stmt), ctx);
15276 0 : break;
15277 5 : case GIMPLE_TRANSACTION:
15278 5 : lower_omp (gimple_transaction_body_ptr (as_a <gtransaction *> (stmt)),
15279 : ctx);
15280 5 : break;
15281 168492 : case GIMPLE_BIND:
15282 168492 : if (ctx && is_gimple_omp_oacc (ctx->stmt))
15283 : {
15284 17785 : tree vars = gimple_bind_vars (as_a <gbind *> (stmt));
15285 17785 : oacc_privatization_scan_decl_chain (ctx, vars);
15286 : }
15287 168492 : lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
15288 168485 : maybe_remove_omp_member_access_dummy_vars (as_a <gbind *> (stmt));
15289 168485 : break;
15290 20036 : case GIMPLE_OMP_PARALLEL:
15291 20036 : case GIMPLE_OMP_TASK:
15292 20036 : ctx = maybe_lookup_ctx (stmt);
15293 20036 : gcc_assert (ctx);
15294 20036 : if (ctx->cancellable)
15295 135 : ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15296 20036 : lower_omp_taskreg (gsi_p, ctx);
15297 20036 : break;
15298 46966 : case GIMPLE_OMP_FOR:
15299 46966 : ctx = maybe_lookup_ctx (stmt);
15300 46966 : gcc_assert (ctx);
15301 46966 : if (ctx->cancellable)
15302 84 : ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15303 46966 : lower_omp_for (gsi_p, ctx);
15304 46966 : break;
15305 386 : case GIMPLE_OMP_SECTIONS:
15306 386 : ctx = maybe_lookup_ctx (stmt);
15307 386 : gcc_assert (ctx);
15308 386 : if (ctx->cancellable)
15309 19 : ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15310 386 : lower_omp_sections (gsi_p, ctx);
15311 386 : break;
15312 161 : case GIMPLE_OMP_SCOPE:
15313 161 : ctx = maybe_lookup_ctx (stmt);
15314 161 : gcc_assert (ctx);
15315 161 : lower_omp_scope (gsi_p, ctx);
15316 161 : break;
15317 659 : case GIMPLE_OMP_DISPATCH:
15318 659 : ctx = maybe_lookup_ctx (stmt);
15319 659 : gcc_assert (ctx);
15320 659 : lower_omp_dispatch (gsi_p, ctx);
15321 659 : break;
15322 164 : case GIMPLE_OMP_INTEROP:
15323 164 : ctx = maybe_lookup_ctx (stmt);
15324 164 : gcc_assert (ctx);
15325 164 : lower_omp_interop (gsi_p, ctx);
15326 164 : break;
15327 1127 : case GIMPLE_OMP_SINGLE:
15328 1127 : ctx = maybe_lookup_ctx (stmt);
15329 1127 : gcc_assert (ctx);
15330 1127 : lower_omp_single (gsi_p, ctx);
15331 1127 : break;
15332 658 : case GIMPLE_OMP_STRUCTURED_BLOCK:
15333 : /* We have already done error checking at this point, so these nodes
15334 : can be completely removed and replaced with their body. */
15335 658 : ctx = maybe_lookup_ctx (stmt);
15336 658 : gcc_assert (ctx);
15337 658 : lower_omp (gimple_omp_body_ptr (stmt), ctx);
15338 658 : gsi_replace_with_seq (gsi_p, gimple_omp_body (stmt), true);
15339 658 : break;
15340 1118 : case GIMPLE_OMP_MASTER:
15341 1118 : case GIMPLE_OMP_MASKED:
15342 1118 : ctx = maybe_lookup_ctx (stmt);
15343 1118 : gcc_assert (ctx);
15344 1118 : lower_omp_master (gsi_p, ctx);
15345 1118 : break;
15346 536 : case GIMPLE_OMP_TASKGROUP:
15347 536 : ctx = maybe_lookup_ctx (stmt);
15348 536 : gcc_assert (ctx);
15349 536 : lower_omp_taskgroup (gsi_p, ctx);
15350 536 : break;
15351 1124 : case GIMPLE_OMP_ORDERED:
15352 1124 : ctx = maybe_lookup_ctx (stmt);
15353 1124 : gcc_assert (ctx);
15354 1124 : lower_omp_ordered (gsi_p, ctx);
15355 1124 : break;
15356 1276 : case GIMPLE_OMP_SCAN:
15357 1276 : ctx = maybe_lookup_ctx (stmt);
15358 1276 : gcc_assert (ctx);
15359 1276 : lower_omp_scan (gsi_p, ctx);
15360 1276 : break;
15361 311 : case GIMPLE_OMP_CRITICAL:
15362 311 : ctx = maybe_lookup_ctx (stmt);
15363 311 : gcc_assert (ctx);
15364 311 : lower_omp_critical (gsi_p, ctx);
15365 311 : break;
15366 2516 : case GIMPLE_OMP_ATOMIC_LOAD:
15367 85 : if ((ctx || make_addressable_vars)
15368 2516 : && walk_tree (gimple_omp_atomic_load_rhs_ptr (
15369 : as_a <gomp_atomic_load *> (stmt)),
15370 : lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
15371 1425 : lower_omp_regimplify_operands (ctx, stmt, gsi_p);
15372 : break;
15373 37170 : case GIMPLE_OMP_TARGET:
15374 37170 : ctx = maybe_lookup_ctx (stmt);
15375 37170 : gcc_assert (ctx);
15376 37170 : lower_omp_target (gsi_p, ctx);
15377 37170 : break;
15378 8458 : case GIMPLE_OMP_TEAMS:
15379 8458 : ctx = maybe_lookup_ctx (stmt);
15380 8458 : gcc_assert (ctx);
15381 8458 : if (gimple_omp_teams_host (as_a <gomp_teams *> (stmt)))
15382 2534 : lower_omp_taskreg (gsi_p, ctx);
15383 : else
15384 5924 : lower_omp_teams (gsi_p, ctx);
15385 : break;
15386 135012 : case GIMPLE_CALL:
15387 135012 : tree fndecl;
15388 135012 : call_stmt = as_a <gcall *> (stmt);
15389 135012 : fndecl = gimple_call_fndecl (call_stmt);
15390 135012 : if (fndecl
15391 135012 : && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
15392 38723 : switch (DECL_FUNCTION_CODE (fndecl))
15393 : {
15394 727 : case BUILT_IN_GOMP_BARRIER:
15395 727 : if (ctx == NULL)
15396 : break;
15397 : /* FALLTHRU */
15398 1037 : case BUILT_IN_GOMP_CANCEL:
15399 1037 : case BUILT_IN_GOMP_CANCELLATION_POINT:
15400 1037 : omp_context *cctx;
15401 1037 : cctx = ctx;
15402 1037 : if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
15403 43 : cctx = cctx->outer;
15404 1037 : gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
15405 1037 : if (!cctx->cancellable)
15406 : {
15407 679 : if (DECL_FUNCTION_CODE (fndecl)
15408 : == BUILT_IN_GOMP_CANCELLATION_POINT)
15409 : {
15410 0 : stmt = gimple_build_nop ();
15411 0 : gsi_replace (gsi_p, stmt, false);
15412 : }
15413 : break;
15414 : }
15415 358 : if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
15416 : {
15417 14 : fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
15418 14 : gimple_call_set_fndecl (call_stmt, fndecl);
15419 14 : gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
15420 : }
15421 358 : tree lhs;
15422 358 : lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
15423 358 : gimple_call_set_lhs (call_stmt, lhs);
15424 358 : tree fallthru_label;
15425 358 : fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
15426 358 : gimple *g;
15427 358 : g = gimple_build_label (fallthru_label);
15428 358 : gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15429 358 : g = gimple_build_cond (NE_EXPR, lhs,
15430 358 : fold_convert (TREE_TYPE (lhs),
15431 : boolean_false_node),
15432 : cctx->cancel_label, fallthru_label);
15433 358 : gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15434 358 : break;
15435 : default:
15436 : break;
15437 : }
15438 134977 : goto regimplify;
15439 :
15440 : case GIMPLE_ASSIGN:
15441 1455192 : for (omp_context *up = ctx; up; up = up->outer)
15442 : {
15443 685264 : if (gimple_code (up->stmt) == GIMPLE_OMP_ORDERED
15444 : || gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL
15445 : || gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP
15446 : || gimple_code (up->stmt) == GIMPLE_OMP_SCOPE
15447 : || gimple_code (up->stmt) == GIMPLE_OMP_SECTION
15448 : || gimple_code (up->stmt) == GIMPLE_OMP_SCAN
15449 : || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
15450 229998 : && (gimple_omp_target_kind (up->stmt)
15451 : == GF_OMP_TARGET_KIND_DATA)))
15452 90715 : continue;
15453 594549 : else if (!up->lastprivate_conditional_map)
15454 : break;
15455 4204 : tree lhs = get_base_address (gimple_assign_lhs (stmt));
15456 4204 : if (TREE_CODE (lhs) == MEM_REF
15457 26 : && DECL_P (TREE_OPERAND (lhs, 0))
15458 4227 : && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs,
15459 : 0))) == REFERENCE_TYPE)
15460 19 : lhs = TREE_OPERAND (lhs, 0);
15461 4204 : if (DECL_P (lhs))
15462 3161 : if (tree *v = up->lastprivate_conditional_map->get (lhs))
15463 : {
15464 382 : tree clauses;
15465 382 : if (up->combined_into_simd_safelen1)
15466 : {
15467 54 : up = up->outer;
15468 54 : if (gimple_code (up->stmt) == GIMPLE_OMP_SCAN)
15469 3 : up = up->outer;
15470 : }
15471 382 : if (gimple_code (up->stmt) == GIMPLE_OMP_FOR)
15472 298 : clauses = gimple_omp_for_clauses (up->stmt);
15473 : else
15474 84 : clauses = gimple_omp_sections_clauses (up->stmt);
15475 382 : tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
15476 382 : if (!OMP_CLAUSE__CONDTEMP__ITER (c))
15477 348 : c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
15478 : OMP_CLAUSE__CONDTEMP_);
15479 382 : gcc_assert (OMP_CLAUSE__CONDTEMP__ITER (c));
15480 382 : gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
15481 382 : gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15482 : }
15483 : }
15484 : /* FALLTHRU */
15485 :
15486 2024212 : default:
15487 2024212 : regimplify:
15488 1066597 : if ((ctx || make_addressable_vars)
15489 2100063 : && walk_gimple_op (stmt, lower_omp_regimplify_p,
15490 : ctx ? NULL : &wi))
15491 : {
15492 : /* Just remove clobbers, this should happen only if we have
15493 : "privatized" local addressable variables in SIMD regions,
15494 : the clobber isn't needed in that case and gimplifying address
15495 : of the ARRAY_REF into a pointer and creating MEM_REF based
15496 : clobber would create worse code than we get with the clobber
15497 : dropped. */
15498 105807 : if (gimple_clobber_p (stmt))
15499 : {
15500 155 : gsi_replace (gsi_p, gimple_build_nop (), true);
15501 155 : break;
15502 : }
15503 105652 : lower_omp_regimplify_operands (ctx, stmt, gsi_p);
15504 : }
15505 : break;
15506 : }
15507 : }
15508 :
15509 : static void
15510 411539 : lower_omp (gimple_seq *body, omp_context *ctx)
15511 : {
15512 411539 : location_t saved_location = input_location;
15513 411539 : gimple_stmt_iterator gsi;
15514 3283722 : for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
15515 2508935 : lower_omp_1 (&gsi, ctx);
15516 : /* During gimplification, we haven't folded statements inside offloading
15517 : or taskreg regions (gimplify.cc:maybe_fold_stmt); do that now. */
15518 411523 : if (target_nesting_level || taskreg_nesting_level)
15519 656970 : for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
15520 443691 : fold_stmt (&gsi);
15521 411523 : input_location = saved_location;
15522 411523 : }
15523 :
15524 : /* Main entry point. */
15525 :
15526 : static unsigned int
15527 2973071 : execute_lower_omp (void)
15528 : {
15529 2973071 : gimple_seq body;
15530 2973071 : int i;
15531 2973071 : omp_context *ctx;
15532 :
15533 : /* This pass always runs, to provide PROP_gimple_lomp.
15534 : But often, there is nothing to do. */
15535 2973071 : if (flag_openacc == 0 && flag_openmp == 0
15536 2918136 : && flag_openmp_simd == 0)
15537 : return 0;
15538 :
15539 57192 : all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
15540 : delete_omp_context);
15541 :
15542 57192 : body = gimple_body (current_function_decl);
15543 :
15544 57192 : scan_omp (&body, NULL);
15545 57192 : gcc_assert (taskreg_nesting_level == 0);
15546 83327 : FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
15547 26135 : finish_taskreg_scan (ctx);
15548 57192 : taskreg_contexts.release ();
15549 :
15550 57192 : if (all_contexts->root)
15551 : {
15552 25857 : if (make_addressable_vars)
15553 622 : push_gimplify_context ();
15554 25857 : lower_omp (&body, NULL);
15555 25853 : if (make_addressable_vars)
15556 622 : pop_gimplify_context (NULL);
15557 : }
15558 :
15559 57188 : if (all_contexts)
15560 : {
15561 57188 : splay_tree_delete (all_contexts);
15562 57188 : all_contexts = NULL;
15563 : }
15564 57188 : BITMAP_FREE (make_addressable_vars);
15565 57188 : BITMAP_FREE (global_nonaddressable_vars);
15566 :
15567 : /* If current function is a method, remove artificial dummy VAR_DECL created
15568 : for non-static data member privatization, they aren't needed for
15569 : debuginfo nor anything else, have been already replaced everywhere in the
15570 : IL and cause problems with LTO. */
15571 57188 : if (DECL_ARGUMENTS (current_function_decl)
15572 32615 : && DECL_ARTIFICIAL (DECL_ARGUMENTS (current_function_decl))
15573 66740 : && (TREE_CODE (TREE_TYPE (DECL_ARGUMENTS (current_function_decl)))
15574 : == POINTER_TYPE))
15575 8990 : remove_member_access_dummy_vars (DECL_INITIAL (current_function_decl));
15576 :
15577 58164 : for (auto task_stmt : task_cpyfns)
15578 504 : finalize_task_copyfn (task_stmt);
15579 57188 : task_cpyfns.release ();
15580 57188 : return 0;
15581 : }
15582 :
15583 : namespace {
15584 :
15585 : const pass_data pass_data_lower_omp =
15586 : {
15587 : GIMPLE_PASS, /* type */
15588 : "omplower", /* name */
15589 : OPTGROUP_OMP, /* optinfo_flags */
15590 : TV_NONE, /* tv_id */
15591 : PROP_gimple_any, /* properties_required */
15592 : PROP_gimple_lomp | PROP_gimple_lomp_dev, /* properties_provided */
15593 : 0, /* properties_destroyed */
15594 : 0, /* todo_flags_start */
15595 : 0, /* todo_flags_finish */
15596 : };
15597 :
15598 : class pass_lower_omp : public gimple_opt_pass
15599 : {
15600 : public:
15601 293828 : pass_lower_omp (gcc::context *ctxt)
15602 587656 : : gimple_opt_pass (pass_data_lower_omp, ctxt)
15603 : {}
15604 :
15605 : /* opt_pass methods: */
15606 2973071 : unsigned int execute (function *) final override
15607 : {
15608 2973071 : return execute_lower_omp ();
15609 : }
15610 :
15611 : }; // class pass_lower_omp
15612 :
15613 : } // anon namespace
15614 :
15615 : gimple_opt_pass *
15616 293828 : make_pass_lower_omp (gcc::context *ctxt)
15617 : {
15618 293828 : return new pass_lower_omp (ctxt);
15619 : }
15620 :
15621 : /* The following is a utility to diagnose structured block violations.
15622 : It is not part of the "omplower" pass, as that's invoked too late. It
15623 : should be invoked by the respective front ends after gimplification. */
15624 :
15625 : static splay_tree all_labels;
15626 :
15627 : /* Check for mismatched contexts and generate an error if needed. Return
15628 : true if an error is detected. */
15629 :
15630 : static bool
15631 562345 : diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
15632 : gimple *branch_ctx, gimple *label_ctx)
15633 : {
15634 562345 : gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
15635 562345 : gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
15636 :
15637 562345 : if (label_ctx == branch_ctx)
15638 : return false;
15639 :
15640 180 : const char* kind = NULL;
15641 :
15642 180 : if (flag_openacc)
15643 : {
15644 7 : if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
15645 16 : || (label_ctx && is_gimple_omp_oacc (label_ctx)))
15646 : {
15647 : gcc_checking_assert (kind == NULL);
15648 : kind = "OpenACC";
15649 : }
15650 : }
15651 : if (kind == NULL)
15652 : {
15653 164 : gcc_checking_assert (flag_openmp || flag_openmp_simd);
15654 : kind = "OpenMP";
15655 : }
15656 :
15657 : /* Previously we kept track of the label's entire context in diagnose_sb_[12]
15658 : so we could traverse it and issue a correct "exit" or "enter" error
15659 : message upon a structured block violation.
15660 :
15661 : We built the context by building a list with tree_cons'ing, but there is
15662 : no easy counterpart in gimple tuples. It seems like far too much work
15663 : for issuing exit/enter error messages. If someone really misses the
15664 : distinct error message... patches welcome. */
15665 :
15666 : #if 0
15667 : /* Try to avoid confusing the user by producing and error message
15668 : with correct "exit" or "enter" verbiage. We prefer "exit"
15669 : unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
15670 : if (branch_ctx == NULL)
15671 : exit_p = false;
15672 : else
15673 : {
15674 : while (label_ctx)
15675 : {
15676 : if (TREE_VALUE (label_ctx) == branch_ctx)
15677 : {
15678 : exit_p = false;
15679 : break;
15680 : }
15681 : label_ctx = TREE_CHAIN (label_ctx);
15682 : }
15683 : }
15684 :
15685 : if (exit_p)
15686 : error ("invalid exit from %s structured block", kind);
15687 : else
15688 : error ("invalid entry to %s structured block", kind);
15689 : #endif
15690 :
15691 : /* If it's obvious we have an invalid entry, be specific about the error. */
15692 180 : if (branch_ctx == NULL)
15693 53 : error ("invalid entry to %s structured block", kind);
15694 : else
15695 : {
15696 : /* Otherwise, be vague and lazy, but efficient. */
15697 127 : error ("invalid branch to/from %s structured block", kind);
15698 : }
15699 :
15700 180 : gsi_replace (gsi_p, gimple_build_nop (), false);
15701 180 : return true;
15702 : }
15703 :
15704 : /* Pass 1: Create a minimal tree of structured blocks, and record
15705 : where each label is found. */
15706 :
15707 : static tree
15708 3355310 : diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
15709 : struct walk_stmt_info *wi)
15710 : {
15711 3355310 : gimple *context = (gimple *) wi->info;
15712 3355310 : gimple *inner_context;
15713 3355310 : gimple *stmt = gsi_stmt (*gsi_p);
15714 :
15715 3355310 : *handled_ops_p = true;
15716 :
15717 3355310 : switch (gimple_code (stmt))
15718 : {
15719 320580 : WALK_SUBSTMTS;
15720 :
15721 83794 : case GIMPLE_OMP_PARALLEL:
15722 83794 : case GIMPLE_OMP_TASK:
15723 83794 : case GIMPLE_OMP_SCOPE:
15724 83794 : case GIMPLE_OMP_SECTIONS:
15725 83794 : case GIMPLE_OMP_SINGLE:
15726 83794 : case GIMPLE_OMP_SECTION:
15727 83794 : case GIMPLE_OMP_STRUCTURED_BLOCK:
15728 83794 : case GIMPLE_OMP_MASTER:
15729 83794 : case GIMPLE_OMP_MASKED:
15730 83794 : case GIMPLE_OMP_ORDERED:
15731 83794 : case GIMPLE_OMP_SCAN:
15732 83794 : case GIMPLE_OMP_CRITICAL:
15733 83794 : case GIMPLE_OMP_TARGET:
15734 83794 : case GIMPLE_OMP_TEAMS:
15735 83794 : case GIMPLE_OMP_TASKGROUP:
15736 : /* The minimal context here is just the current OMP construct. */
15737 83794 : inner_context = stmt;
15738 83794 : wi->info = inner_context;
15739 83794 : walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
15740 83794 : wi->info = context;
15741 83794 : break;
15742 :
15743 52836 : case GIMPLE_OMP_FOR:
15744 52836 : inner_context = stmt;
15745 52836 : wi->info = inner_context;
15746 : /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15747 : walk them. */
15748 52836 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15749 : diagnose_sb_1, NULL, wi);
15750 52836 : walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
15751 52836 : wi->info = context;
15752 52836 : break;
15753 :
15754 559445 : case GIMPLE_LABEL:
15755 1118890 : splay_tree_insert (all_labels,
15756 559445 : (splay_tree_key) gimple_label_label (
15757 559445 : as_a <glabel *> (stmt)),
15758 : (splay_tree_value) context);
15759 559445 : break;
15760 :
15761 : default:
15762 : break;
15763 : }
15764 :
15765 3355310 : return NULL_TREE;
15766 : }
15767 :
15768 : /* Pass 2: Check each branch and see if its context differs from that of
15769 : the destination label's context. */
15770 :
15771 : static tree
15772 3355310 : diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
15773 : struct walk_stmt_info *wi)
15774 : {
15775 3355310 : gimple *context = (gimple *) wi->info;
15776 3355310 : splay_tree_node n;
15777 3355310 : gimple *stmt = gsi_stmt (*gsi_p);
15778 :
15779 3355310 : *handled_ops_p = true;
15780 :
15781 3355310 : switch (gimple_code (stmt))
15782 : {
15783 320580 : WALK_SUBSTMTS;
15784 :
15785 83794 : case GIMPLE_OMP_PARALLEL:
15786 83794 : case GIMPLE_OMP_TASK:
15787 83794 : case GIMPLE_OMP_SCOPE:
15788 83794 : case GIMPLE_OMP_SECTIONS:
15789 83794 : case GIMPLE_OMP_SINGLE:
15790 83794 : case GIMPLE_OMP_SECTION:
15791 83794 : case GIMPLE_OMP_STRUCTURED_BLOCK:
15792 83794 : case GIMPLE_OMP_MASTER:
15793 83794 : case GIMPLE_OMP_MASKED:
15794 83794 : case GIMPLE_OMP_ORDERED:
15795 83794 : case GIMPLE_OMP_SCAN:
15796 83794 : case GIMPLE_OMP_CRITICAL:
15797 83794 : case GIMPLE_OMP_TARGET:
15798 83794 : case GIMPLE_OMP_TEAMS:
15799 83794 : case GIMPLE_OMP_TASKGROUP:
15800 83794 : wi->info = stmt;
15801 83794 : walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
15802 83794 : wi->info = context;
15803 83794 : break;
15804 :
15805 52836 : case GIMPLE_OMP_FOR:
15806 52836 : wi->info = stmt;
15807 : /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15808 : walk them. */
15809 52836 : walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
15810 : diagnose_sb_2, NULL, wi);
15811 52836 : walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
15812 52836 : wi->info = context;
15813 52836 : break;
15814 :
15815 207120 : case GIMPLE_COND:
15816 207120 : {
15817 207120 : gcond *cond_stmt = as_a <gcond *> (stmt);
15818 207120 : tree lab = gimple_cond_true_label (cond_stmt);
15819 207120 : if (lab)
15820 : {
15821 207120 : n = splay_tree_lookup (all_labels,
15822 : (splay_tree_key) lab);
15823 414240 : diagnose_sb_0 (gsi_p, context,
15824 207120 : n ? (gimple *) n->value : NULL);
15825 : }
15826 207120 : lab = gimple_cond_false_label (cond_stmt);
15827 207120 : if (lab)
15828 : {
15829 207120 : n = splay_tree_lookup (all_labels,
15830 : (splay_tree_key) lab);
15831 414240 : diagnose_sb_0 (gsi_p, context,
15832 207120 : n ? (gimple *) n->value : NULL);
15833 : }
15834 : }
15835 : break;
15836 :
15837 112173 : case GIMPLE_GOTO:
15838 112173 : {
15839 112173 : tree lab = gimple_goto_dest (stmt);
15840 112173 : if (TREE_CODE (lab) != LABEL_DECL)
15841 : break;
15842 :
15843 112173 : n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15844 112173 : diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
15845 : }
15846 112173 : break;
15847 :
15848 424 : case GIMPLE_SWITCH:
15849 424 : {
15850 424 : gswitch *switch_stmt = as_a <gswitch *> (stmt);
15851 424 : unsigned int i;
15852 1724 : for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
15853 : {
15854 1316 : tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
15855 1316 : n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15856 1316 : if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
15857 : break;
15858 : }
15859 : }
15860 : break;
15861 :
15862 742 : case GIMPLE_ASM:
15863 742 : {
15864 742 : gasm *asm_stmt = as_a <gasm *> (stmt);
15865 757 : for (unsigned i = 0; i < gimple_asm_nlabels (asm_stmt); ++i)
15866 : {
15867 21 : tree lab = TREE_VALUE (gimple_asm_label_op (asm_stmt, i));
15868 21 : n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15869 21 : if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
15870 : break;
15871 : }
15872 : }
15873 : break;
15874 :
15875 34595 : case GIMPLE_RETURN:
15876 34595 : diagnose_sb_0 (gsi_p, context, NULL);
15877 34595 : break;
15878 :
15879 : default:
15880 : break;
15881 : }
15882 :
15883 3355310 : return NULL_TREE;
15884 : }
15885 :
15886 : static unsigned int
15887 57201 : diagnose_omp_structured_block_errors (void)
15888 : {
15889 57201 : struct walk_stmt_info wi;
15890 57201 : gimple_seq body = gimple_body (current_function_decl);
15891 :
15892 57201 : all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
15893 :
15894 57201 : memset (&wi, 0, sizeof (wi));
15895 57201 : walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
15896 :
15897 57201 : memset (&wi, 0, sizeof (wi));
15898 57201 : wi.want_locations = true;
15899 57201 : walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
15900 :
15901 57201 : gimple_set_body (current_function_decl, body);
15902 :
15903 57201 : splay_tree_delete (all_labels);
15904 57201 : all_labels = NULL;
15905 :
15906 57201 : return 0;
15907 : }
15908 :
15909 : namespace {
15910 :
15911 : const pass_data pass_data_diagnose_omp_blocks =
15912 : {
15913 : GIMPLE_PASS, /* type */
15914 : "*diagnose_omp_blocks", /* name */
15915 : OPTGROUP_OMP, /* optinfo_flags */
15916 : TV_NONE, /* tv_id */
15917 : PROP_gimple_any, /* properties_required */
15918 : 0, /* properties_provided */
15919 : 0, /* properties_destroyed */
15920 : 0, /* todo_flags_start */
15921 : 0, /* todo_flags_finish */
15922 : };
15923 :
15924 : class pass_diagnose_omp_blocks : public gimple_opt_pass
15925 : {
15926 : public:
15927 293828 : pass_diagnose_omp_blocks (gcc::context *ctxt)
15928 587656 : : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
15929 : {}
15930 :
15931 : /* opt_pass methods: */
15932 2973085 : bool gate (function *) final override
15933 : {
15934 2973085 : return flag_openacc || flag_openmp || flag_openmp_simd;
15935 : }
15936 57201 : unsigned int execute (function *) final override
15937 : {
15938 57201 : return diagnose_omp_structured_block_errors ();
15939 : }
15940 :
15941 : }; // class pass_diagnose_omp_blocks
15942 :
15943 : } // anon namespace
15944 :
15945 : gimple_opt_pass *
15946 293828 : make_pass_diagnose_omp_blocks (gcc::context *ctxt)
15947 : {
15948 293828 : return new pass_diagnose_omp_blocks (ctxt);
15949 : }
15950 :
15951 :
15952 : #include "gt-omp-low.h"
|