Line data Source code
1 : /* Tree lowering pass. This pass converts the GENERIC functions-as-trees
2 : tree representation into the GIMPLE form.
3 : Copyright (C) 2002-2026 Free Software Foundation, Inc.
4 : Major work done by Sebastian Pop <s.pop@laposte.net>,
5 : Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
6 :
7 : This file is part of GCC.
8 :
9 : GCC is free software; you can redistribute it and/or modify it under
10 : the terms of the GNU General Public License as published by the Free
11 : Software Foundation; either version 3, or (at your option) any later
12 : version.
13 :
14 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 : for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GCC; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "config.h"
24 : #include "system.h"
25 : #include "coretypes.h"
26 : #include "backend.h"
27 : #include "target.h"
28 : #include "rtl.h"
29 : #include "tree.h"
30 : #include "memmodel.h"
31 : #include "tm_p.h"
32 : #include "gimple.h"
33 : #include "gimple-predict.h"
34 : #include "tree-pass.h" /* FIXME: only for PROP_gimple_any */
35 : #include "ssa.h"
36 : #include "cgraph.h"
37 : #include "tree-pretty-print.h"
38 : #include "diagnostic-core.h"
39 : #include "diagnostic.h" /* For errorcount. */
40 : #include "alias.h"
41 : #include "fold-const.h"
42 : #include "calls.h"
43 : #include "varasm.h"
44 : #include "stmt.h"
45 : #include "expr.h"
46 : #include "gimple-iterator.h"
47 : #include "gimple-fold.h"
48 : #include "tree-eh.h"
49 : #include "gimplify.h"
50 : #include "stor-layout.h"
51 : #include "print-tree.h"
52 : #include "tree-iterator.h"
53 : #include "tree-inline.h"
54 : #include "langhooks.h"
55 : #include "tree-cfg.h"
56 : #include "tree-ssa.h"
57 : #include "tree-hash-traits.h"
58 : #include "omp-general.h"
59 : #include "omp-low.h"
60 : #include "gimple-low.h"
61 : #include "gomp-constants.h"
62 : #include "splay-tree.h"
63 : #include "gimple-walk.h"
64 : #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
65 : #include "builtins.h"
66 : #include "stringpool.h"
67 : #include "attribs.h"
68 : #include "asan.h"
69 : #include "dbgcnt.h"
70 : #include "omp-offload.h"
71 : #include "context.h"
72 : #include "tree-nested.h"
73 : #include "gcc-urlifier.h"
74 : #include "insn-config.h"
75 : #include "recog.h"
76 : #include "output.h"
77 : #include "gimplify_reg_info.h"
78 : #include "tree-ssa-loop-niter.h" /* For simplify_replace_tree. */
79 :
80 : /* Identifier for a basic condition, mapping it to other basic conditions of
81 : its Boolean expression. Basic conditions given the same uid (in the same
82 : function) are parts of the same ANDIF/ORIF expression. Used for condition
83 : coverage. */
84 : static unsigned nextconduid = 1;
85 :
86 : /* Annotated gconds so that basic conditions in the same expression map to
87 : the same uid. This is used for condition coverage. */
88 : static hash_map <tree, unsigned> *cond_uids;
89 :
90 : /* Get a fresh identifier for a new condition expression. This is used for
91 : condition coverage. */
92 : static unsigned
93 5907276 : next_cond_uid ()
94 : {
95 5907276 : return nextconduid++;
96 : }
97 :
98 : /* Reset the condition uid to the value it should have when compiling a new
99 : function. 0 is already the default/untouched value, so start at non-zero.
100 : A valid and set id should always be > 0. This is used for condition
101 : coverage. */
102 : static void
103 3048501 : reset_cond_uid ()
104 : {
105 3048501 : nextconduid = 1;
106 0 : }
107 :
108 : /* Associate the condition STMT with the discriminator UID. STMTs that are
109 : broken down with ANDIF/ORIF from the same Boolean expression should be given
110 : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
111 : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
112 : for condition coverage. */
113 : static void
114 1230799 : tree_associate_condition_with_expr (tree stmt, unsigned uid)
115 : {
116 1230799 : if (!condition_coverage_flag)
117 : return;
118 :
119 542 : if (!cond_uids)
120 68 : cond_uids = new hash_map <tree, unsigned> ();
121 :
122 542 : cond_uids->put (stmt, uid);
123 : }
124 :
125 : /* Hash set of poisoned variables in a bind expr. */
126 : static hash_set<tree> *asan_poisoned_variables = NULL;
127 :
128 : /* Hash set of already-resolved calls to OpenMP "declare variant"
129 : functions. A call can resolve to the original function and
130 : we don't want to repeat the resolution multiple times. */
131 : static hash_set<tree> *omp_resolved_variant_calls = NULL;
132 :
133 : enum gimplify_omp_var_data
134 : {
135 : GOVD_SEEN = 0x000001,
136 : GOVD_EXPLICIT = 0x000002,
137 : GOVD_SHARED = 0x000004,
138 : GOVD_PRIVATE = 0x000008,
139 : GOVD_FIRSTPRIVATE = 0x000010,
140 : GOVD_LASTPRIVATE = 0x000020,
141 : GOVD_REDUCTION = 0x000040,
142 : GOVD_LOCAL = 0x00080,
143 : GOVD_MAP = 0x000100,
144 : GOVD_DEBUG_PRIVATE = 0x000200,
145 : GOVD_PRIVATE_OUTER_REF = 0x000400,
146 : GOVD_LINEAR = 0x000800,
147 : GOVD_ALIGNED = 0x001000,
148 :
149 : /* Flag for GOVD_MAP: don't copy back. */
150 : GOVD_MAP_TO_ONLY = 0x002000,
151 :
152 : /* Flag for GOVD_LINEAR or GOVD_LASTPRIVATE: no outer reference. */
153 : GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 0x004000,
154 :
155 : GOVD_MAP_0LEN_ARRAY = 0x008000,
156 :
157 : /* Flag for GOVD_MAP, if it is always, to or always, tofrom mapping. */
158 : GOVD_MAP_ALWAYS_TO = 0x010000,
159 :
160 : /* Flag for shared vars that are or might be stored to in the region. */
161 : GOVD_WRITTEN = 0x020000,
162 :
163 : /* Flag for GOVD_MAP, if it is a forced mapping. */
164 : GOVD_MAP_FORCE = 0x040000,
165 :
166 : /* Flag for GOVD_MAP: must be present already. */
167 : GOVD_MAP_FORCE_PRESENT = 0x080000,
168 :
169 : /* Flag for GOVD_MAP: only allocate. */
170 : GOVD_MAP_ALLOC_ONLY = 0x100000,
171 :
172 : /* Flag for GOVD_MAP: only copy back. */
173 : GOVD_MAP_FROM_ONLY = 0x200000,
174 :
175 : GOVD_NONTEMPORAL = 0x400000,
176 :
177 : /* Flag for GOVD_LASTPRIVATE: conditional modifier. */
178 : GOVD_LASTPRIVATE_CONDITIONAL = 0x800000,
179 :
180 : GOVD_CONDTEMP = 0x1000000,
181 :
182 : /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */
183 : GOVD_REDUCTION_INSCAN = 0x2000000,
184 :
185 : /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. */
186 : GOVD_FIRSTPRIVATE_IMPLICIT = 0x4000000,
187 :
188 : /* Flag to indicate this an allocator for the uses_allocators clause. */
189 : GOVD_USES_ALLOCATORS_ALLOCATOR = 0x8000000,
190 :
191 : GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
192 : | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
193 : | GOVD_LOCAL)
194 : };
195 :
196 :
197 : enum omp_region_type
198 : {
199 : ORT_WORKSHARE = 0x00,
200 : ORT_TASKGROUP = 0x01,
201 : ORT_DISPATCH = 0x02,
202 : ORT_SIMD = 0x04,
203 :
204 : ORT_PARALLEL = 0x08,
205 : ORT_COMBINED_PARALLEL = ORT_PARALLEL | 1,
206 :
207 : ORT_TASK = 0x10,
208 : ORT_UNTIED_TASK = ORT_TASK | 1,
209 : ORT_TASKLOOP = ORT_TASK | 2,
210 : ORT_UNTIED_TASKLOOP = ORT_UNTIED_TASK | 2,
211 :
212 : ORT_TEAMS = 0x20,
213 : ORT_COMBINED_TEAMS = ORT_TEAMS | 1,
214 : ORT_HOST_TEAMS = ORT_TEAMS | 2,
215 : ORT_COMBINED_HOST_TEAMS = ORT_COMBINED_TEAMS | 2,
216 :
217 : /* Data region. */
218 : ORT_TARGET_DATA = 0x40,
219 :
220 : /* Data region with offloading. */
221 : ORT_TARGET = 0x80,
222 : ORT_COMBINED_TARGET = ORT_TARGET | 1,
223 : ORT_IMPLICIT_TARGET = ORT_TARGET | 2,
224 :
225 : /* OpenACC variants. */
226 : ORT_ACC = 0x100, /* A generic OpenACC region. */
227 : ORT_ACC_DATA = ORT_ACC | ORT_TARGET_DATA, /* Data construct. */
228 : ORT_ACC_PARALLEL = ORT_ACC | ORT_TARGET, /* Parallel construct */
229 : ORT_ACC_KERNELS = ORT_ACC | ORT_TARGET | 2, /* Kernels construct. */
230 : ORT_ACC_SERIAL = ORT_ACC | ORT_TARGET | 4, /* Serial construct. */
231 : ORT_ACC_HOST_DATA = ORT_ACC | ORT_TARGET_DATA | 2, /* Host data. */
232 :
233 : /* Dummy OpenMP region, used to disable expansion of
234 : DECL_VALUE_EXPRs in taskloop pre body. */
235 : ORT_NONE = 0x200
236 : };
237 :
238 : /* Gimplify hashtable helper. */
239 :
240 : struct gimplify_hasher : free_ptr_hash <elt_t>
241 : {
242 : static inline hashval_t hash (const elt_t *);
243 : static inline bool equal (const elt_t *, const elt_t *);
244 : };
245 :
246 : struct gimplify_ctx
247 : {
248 : struct gimplify_ctx *prev_context;
249 :
250 : vec<gbind *> bind_expr_stack;
251 : tree temps;
252 : gimple_seq conditional_cleanups;
253 : tree exit_label;
254 : tree return_temp;
255 :
256 : vec<tree> case_labels;
257 : hash_set<tree> *live_switch_vars;
258 : /* The formal temporary table. Should this be persistent? */
259 : hash_table<gimplify_hasher> *temp_htab;
260 :
261 : int conditions;
262 : unsigned into_ssa : 1;
263 : unsigned allow_rhs_cond_expr : 1;
264 : unsigned in_cleanup_point_expr : 1;
265 : unsigned keep_stack : 1;
266 : unsigned save_stack : 1;
267 : unsigned in_switch_expr : 1;
268 : unsigned in_handler_expr : 1;
269 : };
270 :
271 : enum gimplify_defaultmap_kind
272 : {
273 : GDMK_SCALAR,
274 : GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only. */
275 : GDMK_AGGREGATE,
276 : GDMK_ALLOCATABLE,
277 : GDMK_POINTER
278 : };
279 :
280 : struct gimplify_omp_ctx
281 : {
282 : struct gimplify_omp_ctx *outer_context;
283 : splay_tree variables;
284 : hash_map<omp_name_type<tree>, tree> *implicit_mappers;
285 : hash_set<tree> *privatized_types;
286 : tree clauses;
287 : /* Iteration variables in an OMP_FOR. */
288 : vec<tree> loop_iter_var;
289 : location_t location;
290 : enum omp_clause_default_kind default_kind;
291 : enum omp_region_type region_type;
292 : enum tree_code code;
293 : bool combined_loop;
294 : bool distribute;
295 : bool target_firstprivatize_array_bases;
296 : bool add_safelen1;
297 : bool order_concurrent;
298 : bool has_depend;
299 : bool in_for_exprs;
300 : bool in_call_args;
301 : int defaultmap[5];
302 : };
303 :
304 : static struct gimplify_ctx *gimplify_ctxp;
305 : static struct gimplify_omp_ctx *gimplify_omp_ctxp;
306 : static bool in_omp_construct;
307 :
308 : /* Forward declaration. */
309 : static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
310 : static hash_map<tree, tree> *oacc_declare_returns;
311 : static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
312 : bool (*) (tree), fallback_t, bool);
313 : static void prepare_gimple_addressable (tree *, gimple_seq *);
314 :
315 : /* Shorter alias name for the above function for use in gimplify.cc
316 : only. */
317 :
318 : static inline void
319 95004446 : gimplify_seq_add_stmt (gimple_seq *seq_p, gimple *gs)
320 : {
321 95004446 : gimple_seq_add_stmt_without_update (seq_p, gs);
322 : }
323 :
324 : /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
325 : NULL, a new sequence is allocated. This function is
326 : similar to gimple_seq_add_seq, but does not scan the operands.
327 : During gimplification, we need to manipulate statement sequences
328 : before the def/use vectors have been constructed. */
329 :
330 : static void
331 9663626 : gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
332 : {
333 9663626 : gimple_stmt_iterator si;
334 :
335 9663626 : if (src == NULL)
336 4114743 : return;
337 :
338 5548883 : si = gsi_last (*dst_p);
339 5548883 : gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
340 : }
341 :
342 :
343 : /* Pointer to a list of allocated gimplify_ctx structs to be used for pushing
344 : and popping gimplify contexts. */
345 :
346 : static struct gimplify_ctx *ctx_pool = NULL;
347 :
348 : /* Return a gimplify context struct from the pool. */
349 :
350 : static inline struct gimplify_ctx *
351 9219160 : ctx_alloc (void)
352 : {
353 9219160 : struct gimplify_ctx * c = ctx_pool;
354 :
355 9219160 : if (c)
356 8948516 : ctx_pool = c->prev_context;
357 : else
358 270644 : c = XNEW (struct gimplify_ctx);
359 :
360 9219160 : memset (c, '\0', sizeof (*c));
361 9219160 : return c;
362 : }
363 :
364 : /* Put gimplify context C back into the pool. */
365 :
366 : static inline void
367 9219156 : ctx_free (struct gimplify_ctx *c)
368 : {
369 9219156 : c->prev_context = ctx_pool;
370 9219156 : ctx_pool = c;
371 : }
372 :
373 : /* Free allocated ctx stack memory. */
374 :
375 : void
376 237831 : free_gimplify_stack (void)
377 : {
378 237831 : struct gimplify_ctx *c;
379 :
380 478284 : while ((c = ctx_pool))
381 : {
382 240453 : ctx_pool = c->prev_context;
383 240453 : free (c);
384 : }
385 237831 : }
386 :
387 :
388 : /* Set up a context for the gimplifier. */
389 :
390 : void
391 9219160 : push_gimplify_context (bool in_ssa, bool rhs_cond_ok)
392 : {
393 9219160 : struct gimplify_ctx *c = ctx_alloc ();
394 :
395 9219160 : c->prev_context = gimplify_ctxp;
396 9219160 : gimplify_ctxp = c;
397 9219160 : gimplify_ctxp->into_ssa = in_ssa;
398 9219160 : gimplify_ctxp->allow_rhs_cond_expr = rhs_cond_ok;
399 9219160 : }
400 :
401 : /* Tear down a context for the gimplifier. If BODY is non-null, then
402 : put the temporaries into the outer BIND_EXPR. Otherwise, put them
403 : in the local_decls.
404 :
405 : BODY is not a sequence, but the first tuple in a sequence. */
406 :
407 : void
408 9219156 : pop_gimplify_context (gimple *body)
409 : {
410 9219156 : struct gimplify_ctx *c = gimplify_ctxp;
411 :
412 9219156 : gcc_assert (c
413 : && (!c->bind_expr_stack.exists ()
414 : || c->bind_expr_stack.is_empty ()));
415 9219156 : c->bind_expr_stack.release ();
416 9219156 : gimplify_ctxp = c->prev_context;
417 :
418 9219156 : if (body)
419 3173833 : declare_vars (c->temps, body, false);
420 : else
421 6045323 : record_vars (c->temps);
422 :
423 9219156 : delete c->temp_htab;
424 9219156 : c->temp_htab = NULL;
425 9219156 : ctx_free (c);
426 9219156 : }
427 :
428 : /* Push a GIMPLE_BIND tuple onto the stack of bindings. */
429 :
430 : static void
431 6094339 : gimple_push_bind_expr (gbind *bind_stmt)
432 : {
433 6094339 : gimplify_ctxp->bind_expr_stack.reserve (8);
434 6094339 : gimplify_ctxp->bind_expr_stack.safe_push (bind_stmt);
435 6094339 : }
436 :
437 : /* Pop the first element off the stack of bindings. */
438 :
439 : static void
440 6094339 : gimple_pop_bind_expr (void)
441 : {
442 0 : gimplify_ctxp->bind_expr_stack.pop ();
443 0 : }
444 :
445 : /* Return the first element of the stack of bindings. */
446 :
447 : gbind *
448 0 : gimple_current_bind_expr (void)
449 : {
450 0 : return gimplify_ctxp->bind_expr_stack.last ();
451 : }
452 :
453 : /* Return the stack of bindings created during gimplification. */
454 :
455 : vec<gbind *>
456 369 : gimple_bind_expr_stack (void)
457 : {
458 369 : return gimplify_ctxp->bind_expr_stack;
459 : }
460 :
461 : /* Return true iff there is a COND_EXPR between us and the innermost
462 : CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
463 :
464 : static bool
465 2995127 : gimple_conditional_context (void)
466 : {
467 2995127 : return gimplify_ctxp->conditions > 0;
468 : }
469 :
470 : /* Note that we've entered a COND_EXPR. */
471 :
472 : static void
473 5907723 : gimple_push_condition (void)
474 : {
475 : #ifdef ENABLE_GIMPLE_CHECKING
476 5907723 : if (gimplify_ctxp->conditions == 0)
477 3886229 : gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
478 : #endif
479 5907723 : ++(gimplify_ctxp->conditions);
480 5907723 : }
481 :
482 : /* Note that we've left a COND_EXPR. If we're back at unconditional scope
483 : now, add any conditional cleanups we've seen to the prequeue. */
484 :
485 : static void
486 5907723 : gimple_pop_condition (gimple_seq *pre_p)
487 : {
488 5907723 : int conds = --(gimplify_ctxp->conditions);
489 :
490 5907723 : gcc_assert (conds >= 0);
491 5907723 : if (conds == 0)
492 : {
493 3886229 : gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
494 3886229 : gimplify_ctxp->conditional_cleanups = NULL;
495 : }
496 5907723 : }
497 :
498 : /* A stable comparison routine for use with splay trees and DECLs. */
499 :
500 : static int
501 18356602 : splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
502 : {
503 18356602 : tree a = (tree) xa;
504 18356602 : tree b = (tree) xb;
505 :
506 18356602 : return DECL_UID (a) - DECL_UID (b);
507 : }
508 :
509 : /* Create a new omp construct that deals with variable remapping. */
510 :
511 : static struct gimplify_omp_ctx *
512 141369 : new_omp_context (enum omp_region_type region_type)
513 : {
514 141369 : struct gimplify_omp_ctx *c;
515 :
516 141369 : c = XCNEW (struct gimplify_omp_ctx);
517 141369 : c->outer_context = gimplify_omp_ctxp;
518 141369 : c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
519 141369 : c->implicit_mappers = new hash_map<omp_name_type<tree>, tree>;
520 141369 : c->privatized_types = new hash_set<tree>;
521 141369 : c->location = input_location;
522 141369 : c->region_type = region_type;
523 141369 : if ((region_type & ORT_TASK) == 0)
524 : c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
525 : else
526 6304 : c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
527 141369 : c->defaultmap[GDMK_SCALAR] = GOVD_MAP;
528 141369 : c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP;
529 141369 : c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP;
530 141369 : c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP;
531 141369 : c->defaultmap[GDMK_POINTER] = GOVD_MAP;
532 :
533 141369 : return c;
534 : }
535 :
536 : /* Destroy an omp construct that deals with variable remapping. */
537 :
538 : static void
539 140810 : delete_omp_context (struct gimplify_omp_ctx *c)
540 : {
541 140810 : splay_tree_delete (c->variables);
542 281620 : delete c->privatized_types;
543 281620 : delete c->implicit_mappers;
544 140810 : c->loop_iter_var.release ();
545 140810 : XDELETE (c);
546 140810 : }
547 :
548 : static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
549 : static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
550 :
551 : /* Both gimplify the statement T and append it to *SEQ_P. This function
552 : behaves exactly as gimplify_stmt, but you don't have to pass T as a
553 : reference. */
554 :
555 : void
556 39039817 : gimplify_and_add (tree t, gimple_seq *seq_p)
557 : {
558 39039817 : gimplify_stmt (&t, seq_p);
559 39039817 : }
560 :
561 : /* Gimplify statement T into sequence *SEQ_P, and return the first
562 : tuple in the sequence of generated tuples for this statement.
563 : Return NULL if gimplifying T produced no tuples. */
564 :
565 : static gimple *
566 106178 : gimplify_and_return_first (tree t, gimple_seq *seq_p)
567 : {
568 106178 : gimple_stmt_iterator last = gsi_last (*seq_p);
569 :
570 106178 : gimplify_and_add (t, seq_p);
571 :
572 106178 : if (!gsi_end_p (last))
573 : {
574 4881 : gsi_next (&last);
575 4881 : return gsi_stmt (last);
576 : }
577 : else
578 101297 : return gimple_seq_first_stmt (*seq_p);
579 : }
580 :
581 : /* Returns true iff T is a valid RHS for an assignment to an un-renamed
582 : LHS, or for a call argument. */
583 :
584 : static bool
585 238207 : is_gimple_mem_rhs (tree t)
586 : {
587 : /* If we're dealing with a renamable type, either source or dest must be
588 : a renamed variable. */
589 238207 : if (is_gimple_reg_type (TREE_TYPE (t)))
590 234833 : return is_gimple_val (t);
591 : else
592 3374 : return is_gimple_val (t) || is_gimple_lvalue (t);
593 : }
594 :
595 : /* Return true if T is a CALL_EXPR or an expression that can be
596 : assigned to a temporary. Note that this predicate should only be
597 : used during gimplification. See the rationale for this in
598 : gimplify_modify_expr. */
599 :
600 : static bool
601 100039886 : is_gimple_reg_rhs_or_call (tree t)
602 : {
603 73466002 : return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
604 100039886 : || TREE_CODE (t) == CALL_EXPR);
605 : }
606 :
607 : /* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
608 : this predicate should only be used during gimplification. See the
609 : rationale for this in gimplify_modify_expr. */
610 :
611 : static bool
612 14652402 : is_gimple_mem_rhs_or_call (tree t)
613 : {
614 : /* If we're dealing with a renamable type, either source or dest must be
615 : a renamed variable. */
616 14652402 : if (is_gimple_reg_type (TREE_TYPE (t)))
617 11142316 : return is_gimple_val (t);
618 : else
619 3510086 : return (is_gimple_val (t)
620 1775517 : || is_gimple_lvalue (t)
621 1246494 : || (TREE_CODE (t) == CONSTRUCTOR && CONSTRUCTOR_NELTS (t) == 0)
622 4756188 : || TREE_CODE (t) == CALL_EXPR);
623 : }
624 :
625 : /* Create a temporary with a name derived from VAL. Subroutine of
626 : lookup_tmp_var; nobody else should call this function. */
627 :
628 : static inline tree
629 2198533 : create_tmp_from_val (tree val)
630 : {
631 : /* Drop all qualifiers and address-space information from the value type. */
632 2198533 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
633 2198533 : tree var = create_tmp_var (type, get_name (val));
634 2198533 : return var;
635 : }
636 :
637 : /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
638 : an existing expression temporary. If NOT_GIMPLE_REG, mark it as such. */
639 :
640 : static tree
641 2437942 : lookup_tmp_var (tree val, bool is_formal, bool not_gimple_reg)
642 : {
643 2437942 : tree ret;
644 :
645 : /* We cannot mark a formal temporary with DECL_NOT_GIMPLE_REG_P. */
646 2437942 : gcc_assert (!is_formal || !not_gimple_reg);
647 :
648 : /* If not optimizing, never really reuse a temporary. local-alloc
649 : won't allocate any variable that is used in more than one basic
650 : block, which means it will go into memory, causing much extra
651 : work in reload and final and poorer code generation, outweighing
652 : the extra memory allocation here. */
653 2437942 : if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
654 : {
655 1108296 : ret = create_tmp_from_val (val);
656 1108296 : DECL_NOT_GIMPLE_REG_P (ret) = not_gimple_reg;
657 : }
658 : else
659 : {
660 1329646 : elt_t elt, *elt_p;
661 1329646 : elt_t **slot;
662 :
663 1329646 : elt.val = val;
664 1329646 : if (!gimplify_ctxp->temp_htab)
665 420578 : gimplify_ctxp->temp_htab = new hash_table<gimplify_hasher> (1000);
666 1329646 : slot = gimplify_ctxp->temp_htab->find_slot (&elt, INSERT);
667 1329646 : if (*slot == NULL)
668 : {
669 1090237 : elt_p = XNEW (elt_t);
670 1090237 : elt_p->val = val;
671 1090237 : elt_p->temp = ret = create_tmp_from_val (val);
672 1090237 : *slot = elt_p;
673 : }
674 : else
675 : {
676 239409 : elt_p = *slot;
677 239409 : ret = elt_p->temp;
678 : }
679 : }
680 :
681 2437942 : return ret;
682 : }
683 :
684 : /* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
685 :
686 : static tree
687 27114493 : internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
688 : bool is_formal, bool allow_ssa, bool not_gimple_reg)
689 : {
690 27114493 : tree t, mod;
691 :
692 : /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
693 : can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
694 27114493 : gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
695 : fb_rvalue);
696 :
697 27114493 : if (allow_ssa
698 26844247 : && gimplify_ctxp->into_ssa
699 52482604 : && is_gimple_reg_type (TREE_TYPE (val)))
700 : {
701 24676552 : t = make_ssa_name (TYPE_MAIN_VARIANT (TREE_TYPE (val)));
702 24676552 : if (! gimple_in_ssa_p (cfun))
703 : {
704 21291508 : const char *name = get_name (val);
705 21291508 : if (name)
706 6849024 : SET_SSA_NAME_VAR_OR_IDENTIFIER (t, create_tmp_var_name (name));
707 : }
708 : }
709 : else
710 2437941 : t = lookup_tmp_var (val, is_formal, not_gimple_reg);
711 :
712 27114493 : mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
713 :
714 27114493 : SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location));
715 :
716 : /* gimplify_modify_expr might want to reduce this further. */
717 27114493 : gimplify_and_add (mod, pre_p);
718 27114493 : ggc_free (mod);
719 :
720 : /* If we failed to gimplify VAL then we can end up with the temporary
721 : SSA name not having a definition. In this case return a decl. */
722 27114493 : if (TREE_CODE (t) == SSA_NAME && ! SSA_NAME_DEF_STMT (t))
723 1 : return lookup_tmp_var (val, is_formal, not_gimple_reg);
724 :
725 : return t;
726 : }
727 :
728 : /* Return a formal temporary variable initialized with VAL. PRE_P is as
729 : in gimplify_expr. Only use this function if:
730 :
731 : 1) The value of the unfactored expression represented by VAL will not
732 : change between the initialization and use of the temporary, and
733 : 2) The temporary will not be otherwise modified.
734 :
735 : For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
736 : and #2 means it is inappropriate for && temps.
737 :
738 : For other cases, use get_initialized_tmp_var instead. */
739 :
740 : tree
741 26612546 : get_formal_tmp_var (tree val, gimple_seq *pre_p)
742 : {
743 26612546 : return internal_get_tmp_var (val, pre_p, NULL, true, true, false);
744 : }
745 :
746 : /* Return a temporary variable initialized with VAL. PRE_P and POST_P
747 : are as in gimplify_expr. */
748 :
749 : tree
750 489814 : get_initialized_tmp_var (tree val, gimple_seq *pre_p,
751 : gimple_seq *post_p /* = NULL */,
752 : bool allow_ssa /* = true */)
753 : {
754 489814 : return internal_get_tmp_var (val, pre_p, post_p, false, allow_ssa, false);
755 : }
756 :
757 : /* Declare all the variables in VARS in SCOPE. If DEBUG_INFO is true,
758 : generate debug info for them; otherwise don't. */
759 :
760 : void
761 3182098 : declare_vars (tree vars, gimple *gs, bool debug_info)
762 : {
763 3182098 : tree last = vars;
764 3182098 : if (last)
765 : {
766 2000914 : tree temps, block;
767 :
768 2000914 : gbind *scope = as_a <gbind *> (gs);
769 :
770 2000914 : temps = nreverse (last);
771 :
772 2000914 : block = gimple_bind_block (scope);
773 2000914 : gcc_assert (!block || TREE_CODE (block) == BLOCK);
774 2000914 : if (!block || !debug_info)
775 : {
776 1997064 : DECL_CHAIN (last) = gimple_bind_vars (scope);
777 1997064 : gimple_bind_set_vars (scope, temps);
778 : }
779 : else
780 : {
781 : /* We need to attach the nodes both to the BIND_EXPR and to its
782 : associated BLOCK for debugging purposes. The key point here
783 : is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
784 : is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
785 3850 : if (BLOCK_VARS (block))
786 3657 : BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
787 : else
788 : {
789 193 : gimple_bind_set_vars (scope,
790 : chainon (gimple_bind_vars (scope), temps));
791 193 : BLOCK_VARS (block) = temps;
792 : }
793 : }
794 : }
795 3182098 : }
796 :
797 : /* For VAR a VAR_DECL of variable size, try to find a constant upper bound
798 : for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
799 : no such upper bound can be obtained. */
800 :
801 : static void
802 0 : force_constant_size (tree var)
803 : {
804 : /* The only attempt we make is by querying the maximum size of objects
805 : of the variable's type. */
806 :
807 0 : HOST_WIDE_INT max_size;
808 :
809 0 : gcc_assert (VAR_P (var));
810 :
811 0 : max_size = max_int_size_in_bytes (TREE_TYPE (var));
812 :
813 0 : gcc_assert (max_size >= 0);
814 :
815 0 : DECL_SIZE_UNIT (var)
816 0 : = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
817 0 : DECL_SIZE (var)
818 0 : = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
819 0 : }
820 :
821 : /* Push the temporary variable TMP into the current binding. */
822 :
823 : void
824 29813 : gimple_add_tmp_var_fn (struct function *fn, tree tmp)
825 : {
826 29813 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
827 :
828 : /* Later processing assumes that the object size is constant, which might
829 : not be true at this point. Force the use of a constant upper bound in
830 : this case. */
831 29813 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
832 0 : force_constant_size (tmp);
833 :
834 29813 : DECL_CONTEXT (tmp) = fn->decl;
835 29813 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
836 :
837 29813 : record_vars_into (tmp, fn->decl);
838 29813 : }
839 :
840 : /* Push the temporary variable TMP into the current binding. */
841 :
842 : void
843 16835704 : gimple_add_tmp_var (tree tmp)
844 : {
845 16835704 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
846 :
847 : /* Later processing assumes that the object size is constant, which might
848 : not be true at this point. Force the use of a constant upper bound in
849 : this case. */
850 16835704 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
851 0 : force_constant_size (tmp);
852 :
853 16835704 : DECL_CONTEXT (tmp) = current_function_decl;
854 16835704 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
855 :
856 16835704 : if (gimplify_ctxp)
857 : {
858 5857939 : DECL_CHAIN (tmp) = gimplify_ctxp->temps;
859 5857939 : gimplify_ctxp->temps = tmp;
860 :
861 : /* Mark temporaries local within the nearest enclosing parallel. */
862 5857939 : if (gimplify_omp_ctxp)
863 : {
864 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
865 554529 : int flag = GOVD_LOCAL | GOVD_SEEN;
866 : while (ctx
867 554529 : && (ctx->region_type == ORT_WORKSHARE
868 : || ctx->region_type == ORT_TASKGROUP
869 406630 : || ctx->region_type == ORT_SIMD
870 356214 : || ctx->region_type == ORT_ACC))
871 : {
872 204967 : if (ctx->region_type == ORT_SIMD
873 50416 : && TREE_ADDRESSABLE (tmp)
874 95 : && !TREE_STATIC (tmp))
875 : {
876 95 : if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST)
877 0 : ctx->add_safelen1 = true;
878 95 : else if (ctx->in_for_exprs)
879 : flag = GOVD_PRIVATE;
880 : else
881 : flag = GOVD_PRIVATE | GOVD_SEEN;
882 : break;
883 : }
884 204872 : ctx = ctx->outer_context;
885 : }
886 349562 : if (ctx)
887 322270 : omp_add_variable (ctx, tmp, flag);
888 : }
889 : }
890 10977765 : else if (cfun)
891 10977765 : record_vars (tmp);
892 : else
893 : {
894 0 : gimple_seq body_seq;
895 :
896 : /* This case is for nested functions. We need to expose the locals
897 : they create. */
898 0 : body_seq = gimple_body (current_function_decl);
899 0 : declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
900 : }
901 16835704 : }
902 :
903 : /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
904 : any nested functions. */
905 :
906 : static void
907 3075893 : unshare_body (tree fndecl)
908 : {
909 3075893 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
910 : /* If the language requires deep unsharing, we need a pointer set to make
911 : sure we don't repeatedly unshare subtrees of unshareable nodes. */
912 3075893 : hash_set<tree> *visited
913 3075893 : = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
914 :
915 3075893 : copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
916 3075893 : copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
917 3075893 : copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
918 :
919 3080069 : delete visited;
920 :
921 3075893 : if (cgn)
922 6197168 : for (cgn = first_nested_function (cgn); cgn;
923 26888 : cgn = next_nested_function (cgn))
924 26888 : unshare_body (cgn->decl);
925 3075893 : }
926 :
927 : /* Callback for walk_tree to unmark the visited trees rooted at *TP.
928 : Subtrees are walked until the first unvisited node is encountered. */
929 :
930 : static tree
931 289189224 : unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
932 : {
933 289189224 : tree t = *tp;
934 :
935 : /* If this node has been visited, unmark it and keep looking. */
936 289189224 : if (TREE_VISITED (t))
937 203453267 : TREE_VISITED (t) = 0;
938 :
939 : /* Otherwise, don't look any deeper. */
940 : else
941 85735957 : *walk_subtrees = 0;
942 :
943 289189224 : return NULL_TREE;
944 : }
945 :
946 : /* Unmark the visited trees rooted at *TP. */
947 :
948 : static inline void
949 9227679 : unmark_visited (tree *tp)
950 : {
951 9227679 : walk_tree (tp, unmark_visited_r, NULL, NULL);
952 9227679 : }
953 :
954 : /* Likewise, but mark all trees as not visited. */
955 :
956 : static void
957 3075893 : unvisit_body (tree fndecl)
958 : {
959 3075893 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
960 :
961 3075893 : unmark_visited (&DECL_SAVED_TREE (fndecl));
962 3075893 : unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
963 3075893 : unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
964 :
965 3075893 : if (cgn)
966 6170280 : for (cgn = first_nested_function (cgn);
967 3098584 : cgn; cgn = next_nested_function (cgn))
968 26888 : unvisit_body (cgn->decl);
969 3075893 : }
970 :
971 : /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
972 : one, OR_ELSE otherwise. The location of a STATEMENT_LISTs
973 : comprising at least one DEBUG_BEGIN_STMT followed by exactly one
974 : EXPR is the location of the EXPR. */
975 :
976 : static location_t
977 1187112 : rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
978 : {
979 1187112 : if (!expr)
980 : return or_else;
981 :
982 1187112 : if (EXPR_HAS_LOCATION (expr))
983 823031 : return EXPR_LOCATION (expr);
984 :
985 364081 : if (TREE_CODE (expr) != STATEMENT_LIST)
986 : return or_else;
987 :
988 0 : tree_stmt_iterator i = tsi_start (expr);
989 :
990 0 : bool found = false;
991 0 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
992 : {
993 0 : found = true;
994 0 : tsi_next (&i);
995 : }
996 :
997 0 : if (!found || !tsi_one_before_end_p (i))
998 : return or_else;
999 :
1000 0 : return rexpr_location (tsi_stmt (i), or_else);
1001 : }
1002 :
1003 : /* Return TRUE iff EXPR (maybe recursively) has a location; see
1004 : rexpr_location for the potential recursion. */
1005 :
1006 : static inline bool
1007 518529 : rexpr_has_location (tree expr)
1008 : {
1009 308243 : return rexpr_location (expr) != UNKNOWN_LOCATION;
1010 : }
1011 :
1012 :
1013 : /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
1014 : contain statements and have a value. Assign its value to a temporary
1015 : and give it void_type_node. Return the temporary, or NULL_TREE if
1016 : WRAPPER was already void. */
1017 :
1018 : tree
1019 20936816 : voidify_wrapper_expr (tree wrapper, tree temp)
1020 : {
1021 20936816 : tree type = TREE_TYPE (wrapper);
1022 20936816 : if (type && !VOID_TYPE_P (type))
1023 : {
1024 : tree *p;
1025 :
1026 : /* Set p to point to the body of the wrapper. Loop until we find
1027 : something that isn't a wrapper. */
1028 814782 : for (p = &wrapper; p && *p; )
1029 : {
1030 814782 : switch (TREE_CODE (*p))
1031 : {
1032 3148 : case BIND_EXPR:
1033 3148 : TREE_SIDE_EFFECTS (*p) = 1;
1034 3148 : TREE_TYPE (*p) = void_type_node;
1035 : /* For a BIND_EXPR, the body is operand 1. */
1036 3148 : p = &BIND_EXPR_BODY (*p);
1037 3148 : break;
1038 :
1039 377426 : case CLEANUP_POINT_EXPR:
1040 377426 : case TRY_FINALLY_EXPR:
1041 377426 : case TRY_CATCH_EXPR:
1042 377426 : TREE_SIDE_EFFECTS (*p) = 1;
1043 377426 : TREE_TYPE (*p) = void_type_node;
1044 377426 : p = &TREE_OPERAND (*p, 0);
1045 377426 : break;
1046 :
1047 17983 : case STATEMENT_LIST:
1048 17983 : {
1049 17983 : tree_stmt_iterator i = tsi_last (*p);
1050 17983 : TREE_SIDE_EFFECTS (*p) = 1;
1051 17983 : TREE_TYPE (*p) = void_type_node;
1052 17983 : p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
1053 : }
1054 17983 : break;
1055 :
1056 : case COMPOUND_EXPR:
1057 : /* Advance to the last statement. Set all container types to
1058 : void. */
1059 65307 : for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
1060 : {
1061 32661 : TREE_SIDE_EFFECTS (*p) = 1;
1062 32661 : TREE_TYPE (*p) = void_type_node;
1063 : }
1064 : break;
1065 :
1066 76 : case TRANSACTION_EXPR:
1067 76 : TREE_SIDE_EFFECTS (*p) = 1;
1068 76 : TREE_TYPE (*p) = void_type_node;
1069 76 : p = &TRANSACTION_EXPR_BODY (*p);
1070 76 : break;
1071 :
1072 383503 : default:
1073 : /* Assume that any tree upon which voidify_wrapper_expr is
1074 : directly called is a wrapper, and that its body is op0. */
1075 383503 : if (p == &wrapper)
1076 : {
1077 33 : TREE_SIDE_EFFECTS (*p) = 1;
1078 33 : TREE_TYPE (*p) = void_type_node;
1079 33 : p = &TREE_OPERAND (*p, 0);
1080 33 : break;
1081 : }
1082 383470 : goto out;
1083 : }
1084 : }
1085 :
1086 0 : out:
1087 383470 : if (p == NULL || IS_EMPTY_STMT (*p))
1088 : temp = NULL_TREE;
1089 383470 : else if (temp)
1090 : {
1091 : /* The wrapper is on the RHS of an assignment that we're pushing
1092 : down. */
1093 1994 : gcc_assert (TREE_CODE (temp) == INIT_EXPR
1094 : || TREE_CODE (temp) == MODIFY_EXPR);
1095 1994 : TREE_OPERAND (temp, 1) = *p;
1096 1994 : *p = temp;
1097 : }
1098 : else
1099 : {
1100 381476 : temp = create_tmp_var (type, "retval");
1101 381476 : *p = build2 (INIT_EXPR, type, temp, *p);
1102 : }
1103 :
1104 : return temp;
1105 : }
1106 :
1107 : return NULL_TREE;
1108 : }
1109 :
1110 : /* Prepare calls to builtins to SAVE and RESTORE the stack as well as
1111 : a temporary through which they communicate. */
1112 :
1113 : static void
1114 7923 : build_stack_save_restore (gcall **save, gcall **restore)
1115 : {
1116 7923 : tree tmp_var;
1117 :
1118 15846 : *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
1119 7923 : tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
1120 7923 : gimple_call_set_lhs (*save, tmp_var);
1121 :
1122 7923 : *restore
1123 7923 : = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1124 : 1, tmp_var);
1125 7923 : }
1126 :
1127 : /* Generate IFN_ASAN_MARK call that poisons shadow memory of the DECL
1128 : variable. */
1129 :
1130 : static tree
1131 472 : build_asan_poison_call_expr (tree decl)
1132 : {
1133 : /* Do not poison variables that have size equal to zero. */
1134 472 : tree unit_size = DECL_SIZE_UNIT (decl);
1135 472 : if (zerop (unit_size))
1136 : return NULL_TREE;
1137 :
1138 472 : tree base = build_fold_addr_expr (decl);
1139 :
1140 472 : return build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_ASAN_MARK,
1141 : void_type_node, 3,
1142 : build_int_cst (integer_type_node,
1143 : ASAN_MARK_POISON),
1144 : base, unit_size);
1145 : }
1146 :
1147 : /* Generate IFN_ASAN_MARK call that would poison or unpoison, depending
1148 : on POISON flag, shadow memory of a DECL variable. The call will be
1149 : put on location identified by IT iterator, where BEFORE flag drives
1150 : position where the stmt will be put. */
1151 :
1152 : static void
1153 5103 : asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
1154 : bool before)
1155 : {
1156 5103 : tree unit_size = DECL_SIZE_UNIT (decl);
1157 5103 : tree base = build_fold_addr_expr (decl);
1158 :
1159 : /* Do not poison variables that have size equal to zero. */
1160 5103 : if (zerop (unit_size))
1161 5103 : return;
1162 :
1163 : /* It's necessary to have all stack variables aligned to ASAN granularity
1164 : bytes. */
1165 5089 : gcc_assert (!hwassist_sanitize_p () || hwassist_sanitize_stack_p ());
1166 5089 : unsigned shadow_granularity
1167 5089 : = (hwassist_sanitize_p ()
1168 5089 : ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY);
1169 5089 : if (DECL_ALIGN_UNIT (decl) <= shadow_granularity)
1170 4887 : SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity);
1171 :
1172 5089 : HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON;
1173 :
1174 5089 : gimple *g
1175 5089 : = gimple_build_call_internal (IFN_ASAN_MARK, 3,
1176 5089 : build_int_cst (integer_type_node, flags),
1177 : base, unit_size);
1178 :
1179 5089 : if (before)
1180 2660 : gsi_insert_before (it, g, GSI_NEW_STMT);
1181 : else
1182 2429 : gsi_insert_after (it, g, GSI_NEW_STMT);
1183 : }
1184 :
1185 : /* Generate IFN_ASAN_MARK internal call that depending on POISON flag
1186 : either poisons or unpoisons a DECL. Created statement is appended
1187 : to SEQ_P gimple sequence. */
1188 :
1189 : static void
1190 4631 : asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
1191 : {
1192 4631 : gimple_stmt_iterator it = gsi_last (*seq_p);
1193 4631 : bool before = false;
1194 :
1195 4631 : if (gsi_end_p (it))
1196 2451 : before = true;
1197 :
1198 4631 : asan_poison_variable (decl, poison, &it, before);
1199 4631 : }
1200 :
1201 : /* Sort pair of VAR_DECLs A and B by DECL_UID. */
1202 :
1203 : static int
1204 135 : sort_by_decl_uid (const void *a, const void *b)
1205 : {
1206 135 : const tree *t1 = (const tree *)a;
1207 135 : const tree *t2 = (const tree *)b;
1208 :
1209 135 : int uid1 = DECL_UID (*t1);
1210 135 : int uid2 = DECL_UID (*t2);
1211 :
1212 135 : if (uid1 < uid2)
1213 : return -1;
1214 53 : else if (uid1 > uid2)
1215 : return 1;
1216 : else
1217 0 : return 0;
1218 : }
1219 :
1220 : /* Generate IFN_ASAN_MARK internal call for all VARIABLES
1221 : depending on POISON flag. Created statement is appended
1222 : to SEQ_P gimple sequence. */
1223 :
1224 : static void
1225 1046096 : asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p)
1226 : {
1227 1046096 : unsigned c = variables->elements ();
1228 1046096 : if (c == 0)
1229 1045822 : return;
1230 :
1231 274 : auto_vec<tree> sorted_variables (c);
1232 :
1233 274 : for (hash_set<tree>::iterator it = variables->begin ();
1234 569 : it != variables->end (); ++it)
1235 295 : sorted_variables.safe_push (*it);
1236 :
1237 274 : sorted_variables.qsort (sort_by_decl_uid);
1238 :
1239 274 : unsigned i;
1240 274 : tree var;
1241 843 : FOR_EACH_VEC_ELT (sorted_variables, i, var)
1242 : {
1243 295 : asan_poison_variable (var, poison, seq_p);
1244 :
1245 : /* Add use_after_scope_memory attribute for the variable in order
1246 : to prevent re-written into SSA. */
1247 295 : if (!lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
1248 295 : DECL_ATTRIBUTES (var)))
1249 97 : DECL_ATTRIBUTES (var)
1250 194 : = tree_cons (get_identifier (ASAN_USE_AFTER_SCOPE_ATTRIBUTE),
1251 : integer_one_node,
1252 97 : DECL_ATTRIBUTES (var));
1253 : }
1254 274 : }
1255 :
1256 : /* Gimplify a BIND_EXPR. Just voidify and recurse. */
1257 :
1258 : static enum gimplify_status
1259 6092087 : gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
1260 : {
1261 6092087 : tree bind_expr = *expr_p;
1262 6092087 : bool old_keep_stack = gimplify_ctxp->keep_stack;
1263 6092087 : bool old_save_stack = gimplify_ctxp->save_stack;
1264 6092087 : tree t;
1265 6092087 : gbind *bind_stmt;
1266 6092087 : gimple_seq body, cleanup;
1267 6092087 : gcall *stack_save;
1268 6092087 : location_t start_locus = 0, end_locus = 0;
1269 6092087 : tree ret_clauses = NULL;
1270 :
1271 6092087 : tree temp = voidify_wrapper_expr (bind_expr, NULL);
1272 :
1273 : /* Mark variables seen in this bind expr. */
1274 13099237 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1275 : {
1276 7007150 : if (VAR_P (t))
1277 : {
1278 6337413 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1279 6337413 : tree attr;
1280 :
1281 6337413 : if (flag_openmp
1282 259563 : && !is_global_var (t)
1283 250624 : && !TREE_STATIC (t)
1284 250624 : && DECL_CONTEXT (t) == current_function_decl
1285 250624 : && TREE_USED (t)
1286 6586420 : && (attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1287 : != NULL_TREE)
1288 : {
1289 76 : gcc_assert (!DECL_HAS_VALUE_EXPR_P (t));
1290 76 : tree alloc = TREE_PURPOSE (TREE_VALUE (attr));
1291 76 : tree align = TREE_VALUE (TREE_VALUE (attr));
1292 : /* Allocate directives that appear in a target region must specify
1293 : an allocator clause unless a requires directive with the
1294 : dynamic_allocators clause is present in the same compilation
1295 : unit. */
1296 76 : bool missing_dyn_alloc = false;
1297 76 : if ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1298 : {
1299 : /* This comes too early for omp_discover_declare_target...,
1300 : but should at least catch the most common cases. */
1301 70 : missing_dyn_alloc
1302 70 : = (alloc == NULL_TREE
1303 70 : && cgraph_node::get (current_function_decl)->offloadable);
1304 70 : for (struct gimplify_omp_ctx *ctx2 = ctx;
1305 74 : ctx2 && !missing_dyn_alloc; ctx2 = ctx2->outer_context)
1306 13 : if (ctx2->code == OMP_TARGET)
1307 : {
1308 9 : if (alloc == NULL_TREE)
1309 : missing_dyn_alloc = true;
1310 7 : else if (TREE_CODE (alloc) != INTEGER_CST)
1311 : {
1312 2 : tree alloc2 = alloc;
1313 2 : if (TREE_CODE (alloc2) == MEM_REF
1314 2 : || TREE_CODE (alloc2) == INDIRECT_REF)
1315 0 : alloc2 = TREE_OPERAND (alloc2, 0);
1316 2 : tree c2;
1317 2 : for (c2 = ctx2->clauses; c2;
1318 0 : c2 = OMP_CLAUSE_CHAIN (c2))
1319 1 : if (OMP_CLAUSE_CODE (c2)
1320 : == OMP_CLAUSE_USES_ALLOCATORS)
1321 : {
1322 1 : tree t2
1323 1 : = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c2);
1324 1 : if (operand_equal_p (alloc2, t2))
1325 : break;
1326 : }
1327 2 : if (c2 == NULL_TREE)
1328 1 : error_at (EXPR_LOC_OR_LOC (
1329 : alloc, DECL_SOURCE_LOCATION (t)),
1330 : "%qE in %<allocator%> clause inside a "
1331 : "target region must be specified in an "
1332 : "%<uses_allocators%> clause on the "
1333 : "%<target%> directive", alloc2);
1334 : }
1335 : break;
1336 : }
1337 : }
1338 68 : if (missing_dyn_alloc)
1339 4 : error_at (DECL_SOURCE_LOCATION (t),
1340 : "%<allocate%> directive for %qD inside a target "
1341 : "region must specify an %<allocator%> clause", t);
1342 : /* Skip for omp_default_mem_alloc (= 1),
1343 : unless align is present. For C/C++, there should be always a
1344 : statement list following if TREE_USED, except for, e.g., using
1345 : this decl in a static_assert; in that case, only a single
1346 : DECL_EXPR remains, which can be skipped here. */
1347 72 : else if (!errorcount
1348 55 : && (align != NULL_TREE
1349 55 : || alloc == NULL_TREE
1350 10 : || !integer_onep (alloc))
1351 125 : && (lang_GNU_Fortran ()
1352 25 : || (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1353 : != DECL_EXPR)))
1354 : {
1355 : /* Fortran might already use a pointer type internally;
1356 : use that pointer except for type(C_ptr) and type(C_funptr);
1357 : note that normal proc pointers are rejected. */
1358 53 : tree type = TREE_TYPE (t);
1359 53 : tree tmp, v;
1360 53 : if (lang_GNU_Fortran ()
1361 28 : && POINTER_TYPE_P (type)
1362 8 : && TREE_TYPE (type) != void_type_node
1363 59 : && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
1364 : {
1365 6 : type = TREE_TYPE (type);
1366 6 : v = t;
1367 : }
1368 : else
1369 : {
1370 47 : tmp = build_pointer_type (type);
1371 47 : v = create_tmp_var (tmp, get_name (t));
1372 47 : DECL_IGNORED_P (v) = 0;
1373 47 : DECL_ATTRIBUTES (v)
1374 47 : = tree_cons (get_identifier ("omp allocate var"),
1375 : build_tree_list (NULL_TREE, t),
1376 : remove_attribute ("omp allocate",
1377 47 : DECL_ATTRIBUTES (t)));
1378 47 : tmp = build_fold_indirect_ref (v);
1379 47 : TREE_THIS_NOTRAP (tmp) = 1;
1380 47 : SET_DECL_VALUE_EXPR (t, tmp);
1381 47 : DECL_HAS_VALUE_EXPR_P (t) = 1;
1382 : }
1383 53 : tree sz = TYPE_SIZE_UNIT (type);
1384 : /* The size to use in Fortran might not match TYPE_SIZE_UNIT;
1385 : hence, for some decls, a size variable is saved in the
1386 : attributes; use it, if available. */
1387 53 : if (TREE_CHAIN (TREE_VALUE (attr))
1388 28 : && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))
1389 59 : && TREE_PURPOSE (
1390 : TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))))
1391 : {
1392 6 : sz = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1393 6 : sz = TREE_PURPOSE (sz);
1394 : }
1395 53 : if (alloc == NULL_TREE)
1396 36 : alloc = build_zero_cst (ptr_type_node);
1397 53 : if (align == NULL_TREE)
1398 42 : align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (t));
1399 : else
1400 11 : align = build_int_cst (size_type_node,
1401 11 : MAX (tree_to_uhwi (align),
1402 : DECL_ALIGN_UNIT (t)));
1403 53 : location_t loc = DECL_SOURCE_LOCATION (t);
1404 53 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
1405 53 : tmp = build_call_expr_loc (loc, tmp, 3, align, sz, alloc);
1406 53 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1407 53 : fold_convert (TREE_TYPE (v), tmp));
1408 53 : gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE);
1409 : /* Ensure that either TREE_CHAIN (TREE_VALUE (attr) is set
1410 : and GOMP_FREE added here or that DECL_HAS_VALUE_EXPR_P (t)
1411 : is set, using in a condition much further below. */
1412 59 : gcc_assert (DECL_HAS_VALUE_EXPR_P (t)
1413 : || TREE_CHAIN (TREE_VALUE (attr)));
1414 53 : if (TREE_CHAIN (TREE_VALUE (attr)))
1415 : {
1416 : /* Fortran is special as it does not have properly nest
1417 : declarations in blocks. And as there is no
1418 : initializer, there is also no expression to look for.
1419 : Hence, the FE makes the statement list of the
1420 : try-finally block available. We can put the GOMP_alloc
1421 : at the top, unless an allocator or size expression
1422 : requires to put it afterward; note that the size is
1423 : always later in generated code; for strings, no
1424 : size expr but still an expr might be available.
1425 : As LTO does not handle a statement list, 'sl' has
1426 : to be removed; done so by removing the attribute. */
1427 28 : DECL_ATTRIBUTES (t)
1428 28 : = remove_attribute ("omp allocate",
1429 28 : DECL_ATTRIBUTES (t));
1430 28 : tree sl = TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)));
1431 28 : tree_stmt_iterator e = tsi_start (sl);
1432 28 : tree needle = NULL_TREE;
1433 28 : if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1434 : {
1435 6 : needle = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1436 6 : needle = (TREE_VALUE (needle) ? TREE_VALUE (needle)
1437 : : sz);
1438 : }
1439 22 : else if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1440 : needle = sz;
1441 22 : else if (DECL_P (alloc) && DECL_ARTIFICIAL (alloc))
1442 : needle = alloc;
1443 :
1444 10 : if (needle != NULL_TREE)
1445 : {
1446 49 : while (!tsi_end_p (e))
1447 : {
1448 49 : if (*e == needle
1449 49 : || (TREE_CODE (*e) == MODIFY_EXPR
1450 49 : && TREE_OPERAND (*e, 0) == needle))
1451 : break;
1452 39 : ++e;
1453 : }
1454 10 : gcc_assert (!tsi_end_p (e));
1455 : }
1456 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1457 :
1458 : /* As the cleanup is in BIND_EXPR_BODY, GOMP_free is added
1459 : here; for C/C++ it will be added in the 'cleanup'
1460 : section after gimplification. But Fortran already has
1461 : a try-finally block. */
1462 28 : sl = TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)));
1463 28 : e = tsi_last (sl);
1464 28 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1465 28 : tmp = build_call_expr_loc (EXPR_LOCATION (*e), tmp, 2, v,
1466 : build_zero_cst (ptr_type_node));
1467 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1468 28 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1469 28 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1470 28 : fold_convert (TREE_TYPE (v), tmp));
1471 28 : ++e;
1472 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1473 : }
1474 : else
1475 : {
1476 25 : gcc_assert (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1477 : == STATEMENT_LIST);
1478 25 : tree_stmt_iterator e;
1479 25 : e = tsi_start (BIND_EXPR_BODY (bind_expr));
1480 113 : while (!tsi_end_p (e))
1481 : {
1482 88 : if ((TREE_CODE (*e) == DECL_EXPR
1483 58 : && TREE_OPERAND (*e, 0) == t)
1484 121 : || (TREE_CODE (*e) == CLEANUP_POINT_EXPR
1485 0 : && (TREE_CODE (TREE_OPERAND (*e, 0))
1486 : == DECL_EXPR)
1487 0 : && (TREE_OPERAND (TREE_OPERAND (*e, 0), 0)
1488 : == t)))
1489 : break;
1490 63 : ++e;
1491 : }
1492 25 : gcc_assert (!tsi_end_p (e));
1493 25 : tsi_link_before (&e, tmp, TSI_SAME_STMT);
1494 : }
1495 : }
1496 : }
1497 :
1498 : /* Mark variable as local. */
1499 6337413 : if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t))
1500 : {
1501 100890 : if (! DECL_SEEN_IN_BIND_EXPR_P (t)
1502 100890 : || splay_tree_lookup (ctx->variables,
1503 : (splay_tree_key) t) == NULL)
1504 : {
1505 100890 : int flag = GOVD_LOCAL;
1506 100890 : if (ctx->region_type == ORT_SIMD
1507 4376 : && TREE_ADDRESSABLE (t)
1508 81 : && !TREE_STATIC (t))
1509 : {
1510 69 : if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST)
1511 2 : ctx->add_safelen1 = true;
1512 : else
1513 : flag = GOVD_PRIVATE;
1514 : }
1515 100890 : omp_add_variable (ctx, t, flag | GOVD_SEEN);
1516 : }
1517 : /* Static locals inside of target construct or offloaded
1518 : routines need to be "omp declare target". */
1519 100890 : if (TREE_STATIC (t))
1520 1399 : for (; ctx; ctx = ctx->outer_context)
1521 1214 : if ((ctx->region_type & ORT_TARGET) != 0)
1522 : {
1523 970 : if (!lookup_attribute ("omp declare target",
1524 970 : DECL_ATTRIBUTES (t)))
1525 : {
1526 958 : tree id = get_identifier ("omp declare target");
1527 958 : DECL_ATTRIBUTES (t)
1528 958 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
1529 958 : varpool_node *node = varpool_node::get (t);
1530 958 : if (node)
1531 : {
1532 33 : node->offloadable = 1;
1533 33 : if (ENABLE_OFFLOADING && !DECL_EXTERNAL (t))
1534 : {
1535 : g->have_offload = true;
1536 : if (!in_lto_p)
1537 : vec_safe_push (offload_vars, t);
1538 : }
1539 : }
1540 : }
1541 : break;
1542 : }
1543 : }
1544 :
1545 6337413 : DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
1546 :
1547 6337413 : if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
1548 1089 : cfun->has_local_explicit_reg_vars = true;
1549 : }
1550 : }
1551 :
1552 12184174 : bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
1553 6092087 : BIND_EXPR_BLOCK (bind_expr));
1554 6092087 : gimple_push_bind_expr (bind_stmt);
1555 :
1556 6092087 : gimplify_ctxp->keep_stack = false;
1557 6092087 : gimplify_ctxp->save_stack = false;
1558 :
1559 : /* Gimplify the body into the GIMPLE_BIND tuple's body. */
1560 6092087 : body = NULL;
1561 6092087 : gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
1562 6092087 : gimple_bind_set_body (bind_stmt, body);
1563 :
1564 : /* Source location wise, the cleanup code (stack_restore and clobbers)
1565 : belongs to the end of the block, so propagate what we have. The
1566 : stack_save operation belongs to the beginning of block, which we can
1567 : infer from the bind_expr directly if the block has no explicit
1568 : assignment. */
1569 6092087 : if (BIND_EXPR_BLOCK (bind_expr))
1570 : {
1571 5960427 : end_locus = BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1572 5960427 : start_locus = BLOCK_SOURCE_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1573 : }
1574 5960427 : if (start_locus == 0)
1575 6092087 : start_locus = EXPR_LOCATION (bind_expr);
1576 :
1577 6092087 : cleanup = NULL;
1578 6092087 : stack_save = NULL;
1579 :
1580 : /* Add clobbers for all variables that go out of scope. */
1581 13099237 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1582 : {
1583 7007150 : if (VAR_P (t)
1584 6337413 : && !is_global_var (t)
1585 13120555 : && DECL_CONTEXT (t) == current_function_decl)
1586 : {
1587 6113405 : if (flag_openmp
1588 250587 : && DECL_HAS_VALUE_EXPR_P (t)
1589 1086 : && TREE_USED (t)
1590 6114474 : && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1591 : {
1592 : /* For Fortran, TREE_CHAIN (TREE_VALUE (attr)) is set, which
1593 : causes that the GOMP_free call is already added above;
1594 : and "omp allocate" is removed from DECL_ATTRIBUTES. */
1595 25 : tree v = TREE_OPERAND (DECL_VALUE_EXPR (t), 0);
1596 25 : tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1597 25 : tmp = build_call_expr_loc (end_locus, tmp, 2, v,
1598 : build_zero_cst (ptr_type_node));
1599 25 : gimplify_and_add (tmp, &cleanup);
1600 25 : gimple *clobber_stmt;
1601 25 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1602 25 : clobber_stmt = gimple_build_assign (v, tmp);
1603 25 : gimple_set_location (clobber_stmt, end_locus);
1604 25 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1605 : }
1606 6113405 : if (!DECL_HARD_REGISTER (t)
1607 6112316 : && !TREE_THIS_VOLATILE (t)
1608 6072519 : && !DECL_HAS_VALUE_EXPR_P (t)
1609 : /* Only care for variables that have to be in memory. Others
1610 : will be rewritten into SSA names, hence moved to the
1611 : top-level. */
1612 5944820 : && !is_gimple_reg (t)
1613 7401244 : && flag_stack_reuse != SR_NONE)
1614 : {
1615 1284046 : tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_STORAGE_END);
1616 1284046 : gimple *clobber_stmt;
1617 1284046 : clobber_stmt = gimple_build_assign (t, clobber);
1618 1284046 : gimple_set_location (clobber_stmt, end_locus);
1619 1284046 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1620 : }
1621 :
1622 6113405 : if (flag_openacc && oacc_declare_returns != NULL)
1623 : {
1624 207 : tree key = t;
1625 207 : if (DECL_HAS_VALUE_EXPR_P (key))
1626 : {
1627 8 : key = DECL_VALUE_EXPR (key);
1628 8 : if (INDIRECT_REF_P (key))
1629 8 : key = TREE_OPERAND (key, 0);
1630 : }
1631 207 : tree *c = oacc_declare_returns->get (key);
1632 207 : if (c != NULL)
1633 : {
1634 116 : if (ret_clauses)
1635 64 : OMP_CLAUSE_CHAIN (*c) = ret_clauses;
1636 :
1637 116 : ret_clauses = unshare_expr (*c);
1638 :
1639 116 : oacc_declare_returns->remove (key);
1640 :
1641 116 : if (oacc_declare_returns->is_empty ())
1642 : {
1643 40 : delete oacc_declare_returns;
1644 40 : oacc_declare_returns = NULL;
1645 : }
1646 : }
1647 : }
1648 : }
1649 :
1650 7007150 : if (asan_poisoned_variables != NULL
1651 7007150 : && asan_poisoned_variables->contains (t))
1652 : {
1653 2168 : asan_poisoned_variables->remove (t);
1654 2168 : asan_poison_variable (t, true, &cleanup);
1655 : }
1656 :
1657 7007150 : if (gimplify_ctxp->live_switch_vars != NULL
1658 7007150 : && gimplify_ctxp->live_switch_vars->contains (t))
1659 55 : gimplify_ctxp->live_switch_vars->remove (t);
1660 : }
1661 :
1662 : /* If the code both contains VLAs and calls alloca, then we cannot reclaim
1663 : the stack space allocated to the VLAs. */
1664 6092087 : if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack)
1665 : {
1666 7923 : gcall *stack_restore;
1667 :
1668 : /* Save stack on entry and restore it on exit. Add a try_finally
1669 : block to achieve this. */
1670 7923 : build_stack_save_restore (&stack_save, &stack_restore);
1671 :
1672 7923 : gimple_set_location (stack_save, start_locus);
1673 7923 : gimple_set_location (stack_restore, end_locus);
1674 :
1675 7923 : gimplify_seq_add_stmt (&cleanup, stack_restore);
1676 : }
1677 :
1678 6092087 : if (ret_clauses)
1679 : {
1680 52 : gomp_target *stmt;
1681 52 : gimple_stmt_iterator si = gsi_start (cleanup);
1682 :
1683 52 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
1684 : ret_clauses);
1685 52 : gsi_insert_seq_before_without_update (&si, stmt, GSI_NEW_STMT);
1686 : }
1687 :
1688 6092087 : if (cleanup)
1689 : {
1690 793129 : gtry *gs;
1691 793129 : gimple_seq new_body;
1692 :
1693 793129 : new_body = NULL;
1694 793129 : gs = gimple_build_try (gimple_bind_body (bind_stmt), cleanup,
1695 : GIMPLE_TRY_FINALLY);
1696 :
1697 793129 : if (stack_save)
1698 7923 : gimplify_seq_add_stmt (&new_body, stack_save);
1699 793129 : gimplify_seq_add_stmt (&new_body, gs);
1700 793129 : gimple_bind_set_body (bind_stmt, new_body);
1701 : }
1702 :
1703 : /* keep_stack propagates all the way up to the outermost BIND_EXPR. */
1704 6092087 : if (!gimplify_ctxp->keep_stack)
1705 6076894 : gimplify_ctxp->keep_stack = old_keep_stack;
1706 6092087 : gimplify_ctxp->save_stack = old_save_stack;
1707 :
1708 6092087 : gimple_pop_bind_expr ();
1709 :
1710 6092087 : gimplify_seq_add_stmt (pre_p, bind_stmt);
1711 :
1712 6092087 : if (temp)
1713 : {
1714 1709 : *expr_p = temp;
1715 1709 : return GS_OK;
1716 : }
1717 :
1718 : *expr_p = NULL_TREE;
1719 : return GS_ALL_DONE;
1720 : }
1721 :
1722 : /* Maybe add early return predict statement to PRE_P sequence. */
1723 :
1724 : static void
1725 2320397 : maybe_add_early_return_predict_stmt (gimple_seq *pre_p)
1726 : {
1727 : /* If we are not in a conditional context, add PREDICT statement. */
1728 2320397 : if (gimple_conditional_context ())
1729 : {
1730 450626 : gimple *predict = gimple_build_predict (PRED_TREE_EARLY_RETURN,
1731 : NOT_TAKEN);
1732 450626 : gimplify_seq_add_stmt (pre_p, predict);
1733 : }
1734 2320397 : }
1735 :
1736 : /* Gimplify a RETURN_EXPR. If the expression to be returned is not a
1737 : GIMPLE value, it is assigned to a new temporary and the statement is
1738 : re-written to return the temporary.
1739 :
1740 : PRE_P points to the sequence where side effects that must happen before
1741 : STMT should be stored. */
1742 :
1743 : static enum gimplify_status
1744 2320406 : gimplify_return_expr (tree stmt, gimple_seq *pre_p)
1745 : {
1746 2320406 : greturn *ret;
1747 2320406 : tree ret_expr = TREE_OPERAND (stmt, 0);
1748 2320406 : tree result_decl, result;
1749 :
1750 2320406 : if (ret_expr == error_mark_node)
1751 : return GS_ERROR;
1752 :
1753 2320397 : if (!ret_expr
1754 2229053 : || TREE_CODE (ret_expr) == RESULT_DECL)
1755 : {
1756 107275 : maybe_add_early_return_predict_stmt (pre_p);
1757 107275 : greturn *ret = gimple_build_return (ret_expr);
1758 107275 : copy_warning (ret, stmt);
1759 107275 : gimplify_seq_add_stmt (pre_p, ret);
1760 107275 : return GS_ALL_DONE;
1761 : }
1762 :
1763 2213122 : if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
1764 : result_decl = NULL_TREE;
1765 2212799 : else if (TREE_CODE (ret_expr) == COMPOUND_EXPR)
1766 : {
1767 : /* Used in C++ for handling EH cleanup of the return value if a local
1768 : cleanup throws. Assume the front-end knows what it's doing. */
1769 5302 : result_decl = DECL_RESULT (current_function_decl);
1770 : /* But crash if we end up trying to modify ret_expr below. */
1771 5302 : ret_expr = NULL_TREE;
1772 : }
1773 : else
1774 : {
1775 2207497 : result_decl = TREE_OPERAND (ret_expr, 0);
1776 :
1777 : /* See through a return by reference. */
1778 2207497 : if (INDIRECT_REF_P (result_decl))
1779 43994 : result_decl = TREE_OPERAND (result_decl, 0);
1780 :
1781 2207497 : gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
1782 : || TREE_CODE (ret_expr) == INIT_EXPR)
1783 : && TREE_CODE (result_decl) == RESULT_DECL);
1784 : }
1785 :
1786 : /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
1787 : Recall that aggregate_value_p is FALSE for any aggregate type that is
1788 : returned in registers. If we're returning values in registers, then
1789 : we don't want to extend the lifetime of the RESULT_DECL, particularly
1790 : across another call. In addition, for those aggregates for which
1791 : hard_function_value generates a PARALLEL, we'll die during normal
1792 : expansion of structure assignments; there's special code in expand_return
1793 : to handle this case that does not exist in expand_expr. */
1794 5302 : if (!result_decl)
1795 : result = NULL_TREE;
1796 2212799 : else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
1797 : {
1798 182804 : if (!poly_int_tree_p (DECL_SIZE (result_decl)))
1799 : {
1800 48 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
1801 0 : gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
1802 : /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
1803 : should be effectively allocated by the caller, i.e. all calls to
1804 : this function must be subject to the Return Slot Optimization. */
1805 48 : gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
1806 48 : gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
1807 : }
1808 : result = result_decl;
1809 : }
1810 2029995 : else if (gimplify_ctxp->return_temp)
1811 : result = gimplify_ctxp->return_temp;
1812 : else
1813 : {
1814 1528609 : result = create_tmp_reg (TREE_TYPE (result_decl));
1815 :
1816 : /* ??? With complex control flow (usually involving abnormal edges),
1817 : we can wind up warning about an uninitialized value for this. Due
1818 : to how this variable is constructed and initialized, this is never
1819 : true. Give up and never warn. */
1820 1528609 : suppress_warning (result, OPT_Wuninitialized);
1821 :
1822 1528609 : gimplify_ctxp->return_temp = result;
1823 : }
1824 :
1825 : /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
1826 : Then gimplify the whole thing. */
1827 2213122 : if (result != result_decl)
1828 2029995 : TREE_OPERAND (ret_expr, 0) = result;
1829 :
1830 2213122 : gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
1831 :
1832 2213122 : maybe_add_early_return_predict_stmt (pre_p);
1833 2213122 : ret = gimple_build_return (result);
1834 2213122 : copy_warning (ret, stmt);
1835 2213122 : gimplify_seq_add_stmt (pre_p, ret);
1836 :
1837 2213122 : return GS_ALL_DONE;
1838 : }
1839 :
1840 : /* Gimplify a variable-length array DECL. */
1841 :
1842 : static void
1843 9034 : gimplify_vla_decl (tree decl, gimple_seq *seq_p)
1844 : {
1845 : /* This is a variable-sized decl. Simplify its size and mark it
1846 : for deferred expansion. */
1847 9034 : tree t, addr, ptr_type;
1848 :
1849 9034 : gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
1850 9034 : gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
1851 :
1852 : /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */
1853 9034 : if (DECL_HAS_VALUE_EXPR_P (decl))
1854 : return;
1855 :
1856 : /* All occurrences of this decl in final gimplified code will be
1857 : replaced by indirection. Setting DECL_VALUE_EXPR does two
1858 : things: First, it lets the rest of the gimplifier know what
1859 : replacement to use. Second, it lets the debug info know
1860 : where to find the value. */
1861 9029 : ptr_type = build_pointer_type (TREE_TYPE (decl));
1862 9029 : addr = create_tmp_var (ptr_type, get_name (decl));
1863 9029 : DECL_IGNORED_P (addr) = 0;
1864 9029 : t = build_fold_indirect_ref (addr);
1865 9029 : TREE_THIS_NOTRAP (t) = 1;
1866 9029 : SET_DECL_VALUE_EXPR (decl, t);
1867 9029 : DECL_HAS_VALUE_EXPR_P (decl) = 1;
1868 :
1869 9029 : t = build_alloca_call_expr (DECL_SIZE_UNIT (decl), DECL_ALIGN (decl),
1870 9029 : max_int_size_in_bytes (TREE_TYPE (decl)));
1871 : /* The call has been built for a variable-sized object. */
1872 9029 : CALL_ALLOCA_FOR_VAR_P (t) = 1;
1873 9029 : t = fold_convert (ptr_type, t);
1874 9029 : t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
1875 :
1876 9029 : gimplify_and_add (t, seq_p);
1877 :
1878 : /* Record the dynamic allocation associated with DECL if requested. */
1879 9029 : if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
1880 0 : record_dynamic_alloc (decl);
1881 : }
1882 :
1883 : /* A helper function to be called via walk_tree. Mark all labels under *TP
1884 : as being forced. To be called for DECL_INITIAL of static variables. */
1885 :
1886 : static tree
1887 863713 : force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1888 : {
1889 863713 : if (TYPE_P (*tp))
1890 0 : *walk_subtrees = 0;
1891 863713 : if (TREE_CODE (*tp) == LABEL_DECL)
1892 : {
1893 986 : FORCED_LABEL (*tp) = 1;
1894 986 : cfun->has_forced_label_in_static = 1;
1895 : }
1896 :
1897 863713 : return NULL_TREE;
1898 : }
1899 :
1900 : /* Generate an initialization to automatic variable DECL based on INIT_TYPE.
1901 : Build a call to internal const function DEFERRED_INIT:
1902 : 1st argument: SIZE of the DECL;
1903 : 2nd argument: INIT_TYPE;
1904 : 3rd argument: NAME of the DECL;
1905 :
1906 : as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL). */
1907 :
1908 : static void
1909 158359 : gimple_add_init_for_auto_var (tree decl,
1910 : enum auto_init_type init_type,
1911 : gimple_seq *seq_p)
1912 : {
1913 158359 : gcc_assert (auto_var_p (decl));
1914 158359 : gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
1915 :
1916 158359 : const location_t loc = DECL_SOURCE_LOCATION (decl);
1917 158359 : tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
1918 158359 : tree init_type_node = build_int_cst (integer_type_node, (int) init_type);
1919 158359 : tree decl_name;
1920 :
1921 158359 : if (DECL_NAME (decl))
1922 90591 : decl_name = build_string_literal (DECL_NAME (decl));
1923 : else
1924 : {
1925 67768 : char decl_name_anonymous[3 + (HOST_BITS_PER_INT + 2) / 3];
1926 67768 : sprintf (decl_name_anonymous, "D.%u", DECL_UID (decl));
1927 67768 : decl_name = build_string_literal (decl_name_anonymous);
1928 : }
1929 :
1930 158359 : tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT,
1931 158359 : TREE_TYPE (decl), 3,
1932 : decl_size, init_type_node,
1933 : decl_name);
1934 :
1935 158359 : gimplify_assign (decl, call, seq_p);
1936 158359 : }
1937 :
1938 : /* Generate padding initialization for automatic variable DECL.
1939 : C guarantees that brace-init with fewer initializers than members
1940 : aggregate will initialize the rest of the aggregate as-if it were
1941 : static initialization. In turn static initialization guarantees
1942 : that padding is initialized to zero. So, we always initialize paddings
1943 : to zeroes regardless INIT_TYPE.
1944 : To do the padding initialization, we insert a call to
1945 : __builtin_clear_padding (&decl, 0, for_auto_init = true).
1946 : Note, we add an additional dummy argument for __builtin_clear_padding,
1947 : 'for_auto_init' to distinguish whether this call is for automatic
1948 : variable initialization or not.
1949 : */
1950 : static void
1951 116 : gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
1952 : gimple_seq *seq_p)
1953 : {
1954 116 : tree addr_of_decl = NULL_TREE;
1955 116 : tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
1956 :
1957 116 : if (is_vla)
1958 : {
1959 : /* The temporary address variable for this vla should be
1960 : created in gimplify_vla_decl. */
1961 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
1962 0 : gcc_assert (INDIRECT_REF_P (DECL_VALUE_EXPR (decl)));
1963 0 : addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
1964 : }
1965 : else
1966 : {
1967 116 : mark_addressable (decl);
1968 116 : addr_of_decl = build_fold_addr_expr (decl);
1969 : }
1970 :
1971 116 : gimple *call = gimple_build_call (fn, 2, addr_of_decl,
1972 116 : build_one_cst (TREE_TYPE (addr_of_decl)));
1973 116 : gimplify_seq_add_stmt (seq_p, call);
1974 116 : }
1975 :
1976 : /* Return true if the DECL need to be automatically initialized by the
1977 : compiler. */
1978 : static bool
1979 4363821 : var_needs_auto_init_p (tree decl)
1980 : {
1981 4363821 : if (auto_var_p (decl)
1982 4264702 : && (TREE_CODE (decl) != VAR_DECL || !DECL_HARD_REGISTER (decl))
1983 4263994 : && flag_auto_var_init > AUTO_INIT_UNINITIALIZED
1984 354648 : && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
1985 354640 : && !lookup_attribute ("indeterminate", DECL_ATTRIBUTES (decl))
1986 354631 : && !OPAQUE_TYPE_P (TREE_TYPE (decl))
1987 4718452 : && !is_empty_type (TREE_TYPE (decl)))
1988 327058 : return true;
1989 : return false;
1990 : }
1991 :
1992 : /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
1993 : and initialization explicit. */
1994 :
1995 : static enum gimplify_status
1996 6639478 : gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
1997 : {
1998 6639478 : tree stmt = *stmt_p;
1999 6639478 : tree decl = DECL_EXPR_DECL (stmt);
2000 :
2001 6639478 : *stmt_p = NULL_TREE;
2002 :
2003 6639478 : if (TREE_TYPE (decl) == error_mark_node)
2004 : return GS_ERROR;
2005 :
2006 6639391 : if ((TREE_CODE (decl) == TYPE_DECL
2007 6595559 : || VAR_P (decl))
2008 13231864 : && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
2009 : {
2010 717198 : gimplify_type_sizes (TREE_TYPE (decl), seq_p);
2011 717198 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
2012 23806 : gimplify_type_sizes (TREE_TYPE (TREE_TYPE (decl)), seq_p);
2013 : }
2014 :
2015 : /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
2016 : in case its size expressions contain problematic nodes like CALL_EXPR. */
2017 6639391 : if (TREE_CODE (decl) == TYPE_DECL
2018 43832 : && DECL_ORIGINAL_TYPE (decl)
2019 6644712 : && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
2020 : {
2021 0 : gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
2022 0 : if (TREE_CODE (DECL_ORIGINAL_TYPE (decl)) == REFERENCE_TYPE)
2023 0 : gimplify_type_sizes (TREE_TYPE (DECL_ORIGINAL_TYPE (decl)), seq_p);
2024 : }
2025 :
2026 6639391 : if (VAR_P (decl) && !DECL_EXTERNAL (decl))
2027 : {
2028 6592473 : tree init = DECL_INITIAL (decl);
2029 6592473 : bool is_vla = false;
2030 : /* Check whether a decl has FE created VALUE_EXPR here BEFORE
2031 : gimplify_vla_decl creates VALUE_EXPR for a vla decl.
2032 : If the decl has VALUE_EXPR that was created by FE (usually
2033 : C++FE), it's a proxy variable, and FE already initialized
2034 : the VALUE_EXPR of it, we should not initialize it anymore. */
2035 6592473 : bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
2036 :
2037 6592473 : poly_uint64 size;
2038 6592473 : if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
2039 6592473 : || (!TREE_STATIC (decl)
2040 6465320 : && flag_stack_check == GENERIC_STACK_CHECK
2041 234 : && maybe_gt (size,
2042 : (unsigned HOST_WIDE_INT) STACK_CHECK_MAX_VAR_SIZE)))
2043 : {
2044 8907 : gimplify_vla_decl (decl, seq_p);
2045 8907 : is_vla = true;
2046 : }
2047 :
2048 6592473 : if (asan_poisoned_variables
2049 5247 : && !is_vla
2050 5061 : && TREE_ADDRESSABLE (decl)
2051 2463 : && !TREE_STATIC (decl)
2052 2253 : && !DECL_HAS_VALUE_EXPR_P (decl)
2053 2176 : && DECL_ALIGN (decl) <= MAX_SUPPORTED_STACK_ALIGNMENT
2054 2176 : && dbg_cnt (asan_use_after_scope)
2055 2176 : && !gimplify_omp_ctxp
2056 : /* GNAT introduces temporaries to hold return values of calls in
2057 : initializers of variables defined in other units, so the
2058 : declaration of the variable is discarded completely. We do not
2059 : want to issue poison calls for such dropped variables. */
2060 6594641 : && (DECL_SEEN_IN_BIND_EXPR_P (decl)
2061 0 : || (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)))
2062 : {
2063 2168 : asan_poisoned_variables->add (decl);
2064 2168 : asan_poison_variable (decl, false, seq_p);
2065 2168 : if (!DECL_ARTIFICIAL (decl) && gimplify_ctxp->live_switch_vars)
2066 55 : gimplify_ctxp->live_switch_vars->add (decl);
2067 : }
2068 :
2069 : /* Some front ends do not explicitly declare all anonymous
2070 : artificial variables. We compensate here by declaring the
2071 : variables, though it would be better if the front ends would
2072 : explicitly declare them. */
2073 6592473 : if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
2074 6592473 : && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
2075 17190 : gimple_add_tmp_var (decl);
2076 :
2077 6592473 : if (init && init != error_mark_node)
2078 : {
2079 3752319 : if (!TREE_STATIC (decl))
2080 : {
2081 3722312 : DECL_INITIAL (decl) = NULL_TREE;
2082 3722312 : init = build2 (INIT_EXPR, void_type_node, decl, init);
2083 3722312 : gimplify_and_add (init, seq_p);
2084 3722312 : ggc_free (init);
2085 : /* Clear TREE_READONLY if we really have an initialization. */
2086 3722312 : if (!DECL_INITIAL (decl)
2087 3722312 : && !omp_privatize_by_reference (decl))
2088 3699323 : TREE_READONLY (decl) = 0;
2089 : }
2090 : else
2091 : /* We must still examine initializers for static variables
2092 : as they may contain a label address. */
2093 30007 : walk_tree (&init, force_labels_r, NULL, NULL);
2094 : }
2095 : /* When there is no explicit initializer, if the user requested,
2096 : We should insert an artificial initializer for this automatic
2097 : variable. */
2098 2840154 : else if (var_needs_auto_init_p (decl)
2099 2840154 : && !decl_had_value_expr_p)
2100 : {
2101 98751 : gimple_add_init_for_auto_var (decl,
2102 : flag_auto_var_init,
2103 : seq_p);
2104 : /* The expanding of a call to the above .DEFERRED_INIT will apply
2105 : block initialization to the whole space covered by this variable.
2106 : As a result, all the paddings will be initialized to zeroes
2107 : for zero initialization and 0xFE byte-repeatable patterns for
2108 : pattern initialization.
2109 : In order to make the paddings as zeroes for pattern init, We
2110 : should add a call to __builtin_clear_padding to clear the
2111 : paddings to zero in compatible with CLANG.
2112 : We cannot insert this call if the variable is a gimple register
2113 : since __builtin_clear_padding will take the address of the
2114 : variable. As a result, if a long double/_Complex long double
2115 : variable will spilled into stack later, its padding is 0XFE. */
2116 98751 : if ((flag_auto_var_init & ~AUTO_INIT_CXX26) == AUTO_INIT_PATTERN
2117 186 : && !is_gimple_reg (decl)
2118 98849 : && clear_padding_type_may_have_padding_p (TREE_TYPE (decl)))
2119 75 : gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
2120 : }
2121 : }
2122 :
2123 : return GS_ALL_DONE;
2124 : }
2125 :
2126 : /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
2127 : and replacing the LOOP_EXPR with goto, but if the loop contains an
2128 : EXIT_EXPR, we need to append a label for it to jump to. */
2129 :
2130 : static enum gimplify_status
2131 207479 : gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
2132 : {
2133 207479 : tree saved_label = gimplify_ctxp->exit_label;
2134 207479 : tree start_label = create_artificial_label (UNKNOWN_LOCATION);
2135 :
2136 207479 : gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
2137 :
2138 207479 : gimplify_ctxp->exit_label = NULL_TREE;
2139 :
2140 207479 : gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
2141 :
2142 207479 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
2143 :
2144 207479 : if (gimplify_ctxp->exit_label)
2145 6402 : gimplify_seq_add_stmt (pre_p,
2146 3201 : gimple_build_label (gimplify_ctxp->exit_label));
2147 :
2148 207479 : gimplify_ctxp->exit_label = saved_label;
2149 :
2150 207479 : *expr_p = NULL;
2151 207479 : return GS_ALL_DONE;
2152 : }
2153 :
2154 : /* Gimplify a statement list onto a sequence. These may be created either
2155 : by an enlightened front-end, or by shortcut_cond_expr. */
2156 :
2157 : static enum gimplify_status
2158 8719235 : gimplify_statement_list (tree *expr_p, gimple_seq *pre_p)
2159 : {
2160 8719235 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
2161 :
2162 8719235 : tree_stmt_iterator i = tsi_start (*expr_p);
2163 :
2164 56125929 : while (!tsi_end_p (i))
2165 : {
2166 38687459 : gimplify_stmt (tsi_stmt_ptr (i), pre_p);
2167 38687459 : tsi_delink (&i);
2168 : }
2169 :
2170 8719235 : if (temp)
2171 : {
2172 14835 : *expr_p = temp;
2173 14835 : return GS_OK;
2174 : }
2175 :
2176 : return GS_ALL_DONE;
2177 : }
2178 :
2179 :
2180 : /* Emit warning for the unreachable statement STMT if needed.
2181 : Return the gimple itself when the warning is emitted, otherwise
2182 : return NULL. */
2183 : static gimple *
2184 181 : emit_warn_switch_unreachable (gimple *stmt)
2185 : {
2186 181 : if (gimple_code (stmt) == GIMPLE_GOTO
2187 50 : && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL
2188 231 : && DECL_ARTIFICIAL (gimple_goto_dest (stmt)))
2189 : /* Don't warn for compiler-generated gotos. These occur
2190 : in Duff's devices, for example. */
2191 : return NULL;
2192 : else
2193 131 : warning_at (gimple_location (stmt), OPT_Wswitch_unreachable,
2194 : "statement will never be executed");
2195 131 : return stmt;
2196 : }
2197 :
2198 : /* Callback for walk_gimple_seq. */
2199 :
2200 : static tree
2201 50897 : warn_switch_unreachable_and_auto_init_r (gimple_stmt_iterator *gsi_p,
2202 : bool *handled_ops_p,
2203 : struct walk_stmt_info *wi)
2204 : {
2205 50897 : gimple *stmt = gsi_stmt (*gsi_p);
2206 50897 : bool unreachable_issued = wi->info != NULL;
2207 :
2208 50897 : *handled_ops_p = true;
2209 50897 : switch (gimple_code (stmt))
2210 : {
2211 446 : case GIMPLE_TRY:
2212 : /* A compiler-generated cleanup or a user-written try block.
2213 : If it's empty, don't dive into it--that would result in
2214 : worse location info. */
2215 446 : if (gimple_try_eval (stmt) == NULL)
2216 : {
2217 3 : if (warn_switch_unreachable && !unreachable_issued)
2218 3 : wi->info = emit_warn_switch_unreachable (stmt);
2219 :
2220 : /* Stop when auto var init warning is not on. */
2221 3 : if (!warn_trivial_auto_var_init)
2222 3 : return integer_zero_node;
2223 : }
2224 : /* Fall through. */
2225 2679 : case GIMPLE_BIND:
2226 2679 : case GIMPLE_CATCH:
2227 2679 : case GIMPLE_EH_FILTER:
2228 2679 : case GIMPLE_TRANSACTION:
2229 : /* Walk the sub-statements. */
2230 2679 : *handled_ops_p = false;
2231 2679 : break;
2232 :
2233 : case GIMPLE_DEBUG:
2234 : /* Ignore these. We may generate them before declarations that
2235 : are never executed. If there's something to warn about,
2236 : there will be non-debug stmts too, and we'll catch those. */
2237 : break;
2238 :
2239 60 : case GIMPLE_ASSIGN:
2240 : /* See comment below in the GIMPLE_CALL case. */
2241 60 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2242 20 : && gimple_assign_single_p (stmt)
2243 79 : && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
2244 : {
2245 6 : gimple *g = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
2246 6 : if (gimple_call_internal_p (g, IFN_DEFERRED_INIT))
2247 : break;
2248 : }
2249 54 : goto do_default;
2250 :
2251 46753 : case GIMPLE_LABEL:
2252 : /* Stop till the first Label. */
2253 46753 : return integer_zero_node;
2254 62 : case GIMPLE_CALL:
2255 62 : if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2256 : {
2257 8 : *handled_ops_p = false;
2258 8 : break;
2259 : }
2260 : /* Don't warn for compiler-generated initializations for
2261 : -ftrivial-auto-var-init for -Wswitch-unreachable. Though
2262 : do warn for -Wtrivial-auto-var-init.
2263 : There are 3 cases:
2264 : case 1: a call to .DEFERRED_INIT;
2265 : case 2: a call to __builtin_clear_padding with the 2nd argument is
2266 : present and non-zero;
2267 : case 3: a gimple assign store right after the call to .DEFERRED_INIT
2268 : that has the LHS of .DEFERRED_INIT as the RHS as following:
2269 : _1 = .DEFERRED_INIT (4, 2, &"i1"[0]);
2270 : i1 = _1.
2271 : case 3 is handled above in the GIMPLE_ASSIGN case. */
2272 54 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2273 54 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2274 : {
2275 33 : if (warn_trivial_auto_var_init)
2276 : {
2277 : /* Get the variable name from the 3rd argument of call. */
2278 12 : tree var_name = gimple_call_arg (stmt, 2);
2279 12 : var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0);
2280 12 : const char *var_name_str = TREE_STRING_POINTER (var_name);
2281 :
2282 12 : warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init,
2283 : "%qs cannot be initialized with "
2284 : "%<-ftrivial-auto-var_init%>", var_name_str);
2285 : }
2286 : break;
2287 : }
2288 21 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2289 7 : && gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
2290 24 : && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
2291 : break;
2292 : /* Fall through. */
2293 178 : default:
2294 178 : do_default:
2295 : /* check the first "real" statement (not a decl/lexical scope/...), issue
2296 : warning if needed. */
2297 178 : if (warn_switch_unreachable && !unreachable_issued)
2298 178 : wi->info = emit_warn_switch_unreachable (stmt);
2299 : /* Stop when auto var init warning is not on. */
2300 178 : if (!warn_trivial_auto_var_init)
2301 178 : return integer_zero_node;
2302 : break;
2303 : }
2304 : return NULL_TREE;
2305 : }
2306 :
2307 :
2308 : /* Possibly warn about unreachable statements between switch's controlling
2309 : expression and the first case. Also warn about -ftrivial-auto-var-init
2310 : cannot initialize the auto variable under such situation.
2311 : SEQ is the body of a switch expression. */
2312 :
2313 : static void
2314 50872 : maybe_warn_switch_unreachable_and_auto_init (gimple_seq seq)
2315 : {
2316 60 : if ((!warn_switch_unreachable && !warn_trivial_auto_var_init)
2317 : /* This warning doesn't play well with Fortran when optimizations
2318 : are on. */
2319 50812 : || lang_GNU_Fortran ()
2320 97980 : || seq == NULL)
2321 3935 : return;
2322 :
2323 46937 : struct walk_stmt_info wi;
2324 :
2325 46937 : memset (&wi, 0, sizeof (wi));
2326 46937 : walk_gimple_seq (seq, warn_switch_unreachable_and_auto_init_r, NULL, &wi);
2327 : }
2328 :
2329 :
2330 : /* A label entry that pairs label and a location. */
2331 : struct label_entry
2332 : {
2333 : tree label;
2334 : location_t loc;
2335 : };
2336 :
2337 : /* Find LABEL in vector of label entries VEC. */
2338 :
2339 : static struct label_entry *
2340 12352 : find_label_entry (const auto_vec<struct label_entry> *vec, tree label)
2341 : {
2342 12352 : unsigned int i;
2343 12352 : struct label_entry *l;
2344 :
2345 23634 : FOR_EACH_VEC_ELT (*vec, i, l)
2346 20270 : if (l->label == label)
2347 : return l;
2348 : return NULL;
2349 : }
2350 :
2351 : /* Return true if LABEL, a LABEL_DECL, represents a case label
2352 : in a vector of labels CASES. */
2353 :
2354 : static bool
2355 16478 : case_label_p (const vec<tree> *cases, tree label)
2356 : {
2357 16478 : unsigned int i;
2358 16478 : tree l;
2359 :
2360 165417 : FOR_EACH_VEC_ELT (*cases, i, l)
2361 165083 : if (CASE_LABEL (l) == label)
2362 : return true;
2363 : return false;
2364 : }
2365 :
2366 : /* Find the last nondebug statement in a scope STMT. */
2367 :
2368 : static gimple *
2369 2257 : last_stmt_in_scope (gimple *stmt)
2370 : {
2371 4196 : if (!stmt)
2372 : return NULL;
2373 :
2374 6834 : auto last_stmt_in_seq = [] (gimple_seq s)
2375 : {
2376 2649 : gimple_seq_node n;
2377 5289 : for (n = gimple_seq_last (s);
2378 2654 : n && (is_gimple_debug (n)
2379 2641 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2380 109 : && gimple_call_internal_p (n, IFN_DEFERRED_INIT)));
2381 5 : n = n->prev)
2382 7 : if (n == s)
2383 : return (gimple *) NULL;
2384 : return (gimple *) n;
2385 : };
2386 :
2387 4185 : switch (gimple_code (stmt))
2388 : {
2389 1391 : case GIMPLE_BIND:
2390 1391 : {
2391 1391 : gbind *bind = as_a <gbind *> (stmt);
2392 1391 : stmt = last_stmt_in_seq (gimple_bind_body (bind));
2393 1391 : return last_stmt_in_scope (stmt);
2394 : }
2395 :
2396 710 : case GIMPLE_TRY:
2397 710 : {
2398 710 : gtry *try_stmt = as_a <gtry *> (stmt);
2399 710 : stmt = last_stmt_in_seq (gimple_try_eval (try_stmt));
2400 710 : gimple *last_eval = last_stmt_in_scope (stmt);
2401 710 : if (gimple_stmt_may_fallthru (last_eval)
2402 567 : && (last_eval == NULL
2403 564 : || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH))
2404 1270 : && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
2405 : {
2406 548 : stmt = last_stmt_in_seq (gimple_try_cleanup (try_stmt));
2407 548 : return last_stmt_in_scope (stmt);
2408 : }
2409 : else
2410 : return last_eval;
2411 : }
2412 :
2413 0 : case GIMPLE_DEBUG:
2414 0 : gcc_unreachable ();
2415 :
2416 : default:
2417 : return stmt;
2418 : }
2419 : }
2420 :
2421 : /* Collect labels that may fall through into LABELS and return the statement
2422 : preceding another case label, or a user-defined label. Store a location
2423 : useful to give warnings at *PREVLOC (usually the location of the returned
2424 : statement or of its surrounding scope). */
2425 :
2426 : static gimple *
2427 21093 : collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
2428 : auto_vec <struct label_entry> *labels,
2429 : location_t *prevloc)
2430 : {
2431 21093 : gimple *prev = NULL;
2432 :
2433 21093 : *prevloc = UNKNOWN_LOCATION;
2434 102348 : do
2435 : {
2436 102348 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND)
2437 : {
2438 : /* Recognize the special GIMPLE_BIND added by gimplify_switch_expr,
2439 : which starts on a GIMPLE_SWITCH and ends with a break label.
2440 : Handle that as a single statement that can fall through. */
2441 1452 : gbind *bind = as_a <gbind *> (gsi_stmt (*gsi_p));
2442 1452 : gimple *first = gimple_seq_first_stmt (gimple_bind_body (bind));
2443 1452 : gimple *last = gimple_seq_last_stmt (gimple_bind_body (bind));
2444 1446 : if (last
2445 1446 : && gimple_code (first) == GIMPLE_SWITCH
2446 1548 : && gimple_code (last) == GIMPLE_LABEL)
2447 : {
2448 102 : tree label = gimple_label_label (as_a <glabel *> (last));
2449 102 : if (SWITCH_BREAK_LABEL_P (label))
2450 : {
2451 102 : prev = bind;
2452 102 : gsi_next (gsi_p);
2453 102 : continue;
2454 : }
2455 : }
2456 : }
2457 102246 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
2458 102246 : || gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
2459 : {
2460 : /* Nested scope. Only look at the last statement of
2461 : the innermost scope. */
2462 1547 : location_t bind_loc = gimple_location (gsi_stmt (*gsi_p));
2463 1547 : gimple *last = last_stmt_in_scope (gsi_stmt (*gsi_p));
2464 1547 : if (last)
2465 : {
2466 1539 : prev = last;
2467 : /* It might be a label without a location. Use the
2468 : location of the scope then. */
2469 1539 : if (!gimple_has_location (prev))
2470 671 : *prevloc = bind_loc;
2471 : }
2472 1547 : gsi_next (gsi_p);
2473 1547 : continue;
2474 1547 : }
2475 :
2476 : /* Ifs are tricky. */
2477 100699 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
2478 : {
2479 7268 : gcond *cond_stmt = as_a <gcond *> (gsi_stmt (*gsi_p));
2480 7268 : tree false_lab = gimple_cond_false_label (cond_stmt);
2481 7268 : location_t if_loc = gimple_location (cond_stmt);
2482 :
2483 : /* If we have e.g.
2484 : if (i > 1) goto <D.2259>; else goto D;
2485 : we can't do much with the else-branch. */
2486 7268 : if (!DECL_ARTIFICIAL (false_lab))
2487 : break;
2488 :
2489 : /* Go on until the false label, then one step back. */
2490 55328 : for (; !gsi_end_p (*gsi_p); gsi_next (gsi_p))
2491 : {
2492 55328 : gimple *stmt = gsi_stmt (*gsi_p);
2493 55328 : if (gimple_code (stmt) == GIMPLE_LABEL
2494 55328 : && gimple_label_label (as_a <glabel *> (stmt)) == false_lab)
2495 : break;
2496 : }
2497 :
2498 : /* Not found? Oops. */
2499 7268 : if (gsi_end_p (*gsi_p))
2500 : break;
2501 :
2502 : /* A dead label can't fall through. */
2503 7268 : if (!UNUSED_LABEL_P (false_lab))
2504 : {
2505 7221 : struct label_entry l = { false_lab, if_loc };
2506 7221 : labels->safe_push (l);
2507 : }
2508 :
2509 : /* Go to the last statement of the then branch. */
2510 7268 : gsi_prev (gsi_p);
2511 :
2512 : /* if (i != 0) goto <D.1759>; else goto <D.1760>;
2513 : <D.1759>:
2514 : <stmt>;
2515 : goto <D.1761>;
2516 : <D.1760>:
2517 : */
2518 7268 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2519 7268 : && !gimple_has_location (gsi_stmt (*gsi_p)))
2520 : {
2521 : /* Look at the statement before, it might be
2522 : attribute fallthrough, in which case don't warn. */
2523 1626 : gsi_prev (gsi_p);
2524 1626 : bool fallthru_before_dest
2525 1626 : = gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
2526 1626 : gsi_next (gsi_p);
2527 1626 : tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
2528 1626 : if (!fallthru_before_dest)
2529 : {
2530 1569 : struct label_entry l = { goto_dest, if_loc };
2531 1569 : labels->safe_push (l);
2532 : }
2533 : }
2534 : /* This case is about
2535 : if (1 != 0) goto <D.2022>; else goto <D.2023>;
2536 : <D.2022>:
2537 : n = n + 1; // #1
2538 : <D.2023>: // #2
2539 : <D.1988>: // #3
2540 : where #2 is UNUSED_LABEL_P and we want to warn about #1 falling
2541 : through to #3. So set PREV to #1. */
2542 5642 : else if (UNUSED_LABEL_P (false_lab))
2543 47 : prev = gsi_stmt (*gsi_p);
2544 :
2545 : /* And move back. */
2546 7268 : gsi_next (gsi_p);
2547 : }
2548 :
2549 100699 : tree lab;
2550 : /* Remember the last statement. Skip labels that are of no interest
2551 : to us. */
2552 100699 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2553 : {
2554 12134 : tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (*gsi_p)));
2555 12134 : if (find_label_entry (labels, label))
2556 8790 : prev = gsi_stmt (*gsi_p);
2557 : }
2558 88565 : else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
2559 : ;
2560 88565 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2561 88565 : && gimple_call_internal_p (gsi_stmt (*gsi_p),
2562 : IFN_DEFERRED_INIT))
2563 : ;
2564 88559 : else if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_PREDICT)
2565 : ;
2566 87331 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2567 2382 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2568 348 : && (lab = gimple_goto_dest (gsi_stmt (*gsi_p)))
2569 348 : && TREE_CODE (lab) == LABEL_DECL
2570 87678 : && VACUOUS_INIT_LABEL_P (lab))
2571 : ;
2572 87331 : else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
2573 67015 : prev = gsi_stmt (*gsi_p);
2574 100699 : gsi_next (gsi_p);
2575 : }
2576 102348 : while (!gsi_end_p (*gsi_p)
2577 : /* Stop if we find a case or a user-defined label. */
2578 200609 : && (gimple_code (gsi_stmt (*gsi_p)) != GIMPLE_LABEL
2579 21872 : || !gimple_has_location (gsi_stmt (*gsi_p))));
2580 :
2581 21093 : if (prev && gimple_has_location (prev))
2582 20640 : *prevloc = gimple_location (prev);
2583 21093 : return prev;
2584 : }
2585 :
2586 : /* Return true if the switch fallthrough warning should occur. LABEL is
2587 : the label statement that we're falling through to. */
2588 :
2589 : static bool
2590 16999 : should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
2591 : {
2592 16999 : gimple_stmt_iterator gsi = *gsi_p;
2593 :
2594 : /* Don't warn if the label is marked with a "falls through" comment. */
2595 16999 : if (FALLTHROUGH_LABEL_P (label))
2596 : return false;
2597 :
2598 : /* Don't warn for non-case labels followed by a statement:
2599 : case 0:
2600 : foo ();
2601 : label:
2602 : bar ();
2603 : as these are likely intentional. */
2604 16219 : if (!case_label_p (&gimplify_ctxp->case_labels, label))
2605 : {
2606 : tree l;
2607 334 : while (!gsi_end_p (gsi)
2608 334 : && ((gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2609 259 : && (l
2610 259 : = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi))))
2611 259 : && !case_label_p (&gimplify_ctxp->case_labels, l))
2612 153 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2613 31 : && gimple_call_internal_p (gsi_stmt (gsi),
2614 : IFN_DEFERRED_INIT))))
2615 173 : gsi_next_nondebug (&gsi);
2616 161 : if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
2617 : return false;
2618 : }
2619 :
2620 : /* Don't warn for terminated branches, i.e. when the subsequent case labels
2621 : immediately breaks. */
2622 16144 : gsi = *gsi_p;
2623 :
2624 : /* Skip all immediately following labels. */
2625 35963 : while (!gsi_end_p (gsi)
2626 35963 : && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2627 16293 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT
2628 16084 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2629 775 : && gimple_call_internal_p (gsi_stmt (gsi),
2630 : IFN_DEFERRED_INIT))))
2631 19819 : gsi_next_nondebug (&gsi);
2632 :
2633 : /* { ... something; default:; } */
2634 16144 : if (gsi_end_p (gsi)
2635 : /* { ... something; default: break; } or
2636 : { ... something; default: goto L; } */
2637 16078 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
2638 : /* { ... something; default: return; } */
2639 31123 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
2640 1192 : return false;
2641 :
2642 : return true;
2643 : }
2644 :
2645 : /* Callback for walk_gimple_seq. */
2646 :
2647 : static tree
2648 22101 : warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2649 : struct walk_stmt_info *)
2650 : {
2651 22101 : gimple *stmt = gsi_stmt (*gsi_p);
2652 :
2653 22101 : *handled_ops_p = true;
2654 22101 : switch (gimple_code (stmt))
2655 : {
2656 299 : case GIMPLE_TRY:
2657 299 : case GIMPLE_BIND:
2658 299 : case GIMPLE_CATCH:
2659 299 : case GIMPLE_EH_FILTER:
2660 299 : case GIMPLE_TRANSACTION:
2661 : /* Walk the sub-statements. */
2662 299 : *handled_ops_p = false;
2663 299 : break;
2664 :
2665 : /* Find a sequence of form:
2666 :
2667 : GIMPLE_LABEL
2668 : [...]
2669 : <may fallthru stmt>
2670 : GIMPLE_LABEL
2671 :
2672 : and possibly warn. */
2673 : case GIMPLE_LABEL:
2674 : {
2675 : /* Found a label. Skip all immediately following labels. */
2676 49612 : while (!gsi_end_p (*gsi_p)
2677 49612 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2678 28285 : gsi_next_nondebug (gsi_p);
2679 :
2680 : /* There might be no more statements. */
2681 21327 : if (gsi_end_p (*gsi_p))
2682 4321 : return integer_zero_node;
2683 :
2684 : /* Vector of labels that fall through. */
2685 21093 : auto_vec <struct label_entry> labels;
2686 21093 : location_t prevloc;
2687 21093 : gimple *prev = collect_fallthrough_labels (gsi_p, &labels, &prevloc);
2688 :
2689 : /* There might be no more statements. */
2690 21093 : if (gsi_end_p (*gsi_p))
2691 4087 : return integer_zero_node;
2692 :
2693 17006 : gimple *next = gsi_stmt (*gsi_p);
2694 17006 : tree label;
2695 : /* If what follows is a label, then we may have a fallthrough. */
2696 17006 : if (gimple_code (next) == GIMPLE_LABEL
2697 17006 : && gimple_has_location (next)
2698 17006 : && (label = gimple_label_label (as_a <glabel *> (next)))
2699 34012 : && prev != NULL)
2700 : {
2701 16999 : struct label_entry *l;
2702 16999 : bool warned_p = false;
2703 16999 : auto_diagnostic_group d;
2704 16999 : if (!should_warn_for_implicit_fallthrough (gsi_p, label))
2705 : /* Quiet. */;
2706 14952 : else if (gimple_code (prev) == GIMPLE_LABEL
2707 218 : && (label = gimple_label_label (as_a <glabel *> (prev)))
2708 15170 : && (l = find_label_entry (&labels, label)))
2709 198 : warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough_,
2710 : "this statement may fall through");
2711 14754 : else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH)
2712 : /* Try to be clever and don't warn when the statement
2713 : can't actually fall through. */
2714 14174 : && gimple_stmt_may_fallthru (prev)
2715 15055 : && prevloc != UNKNOWN_LOCATION)
2716 301 : warned_p = warning_at (prevloc,
2717 301 : OPT_Wimplicit_fallthrough_,
2718 : "this statement may fall through");
2719 499 : if (warned_p)
2720 499 : inform (gimple_location (next), "here");
2721 :
2722 : /* Mark this label as processed so as to prevent multiple
2723 : warnings in nested switches. */
2724 16999 : FALLTHROUGH_LABEL_P (label) = true;
2725 :
2726 : /* So that next warn_implicit_fallthrough_r will start looking for
2727 : a new sequence starting with this label. */
2728 16999 : gsi_prev (gsi_p);
2729 16999 : }
2730 4087 : }
2731 17006 : break;
2732 : default:
2733 : break;
2734 : }
2735 : return NULL_TREE;
2736 : }
2737 :
2738 : /* Warn when a switch case falls through. */
2739 :
2740 : static void
2741 50872 : maybe_warn_implicit_fallthrough (gimple_seq seq)
2742 : {
2743 50872 : if (!warn_implicit_fallthrough)
2744 46692 : return;
2745 :
2746 : /* This warning is meant for C/C++/ObjC/ObjC++ only. */
2747 4180 : if (!(lang_GNU_C ()
2748 1232 : || lang_GNU_CXX ()
2749 0 : || lang_GNU_OBJC ()))
2750 : return;
2751 :
2752 4180 : struct walk_stmt_info wi;
2753 4180 : memset (&wi, 0, sizeof (wi));
2754 4180 : walk_gimple_seq (seq, warn_implicit_fallthrough_r, NULL, &wi);
2755 : }
2756 :
2757 : /* Callback for walk_gimple_seq. */
2758 :
2759 : static tree
2760 3291845 : expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2761 : struct walk_stmt_info *wi)
2762 : {
2763 3291845 : gimple *stmt = gsi_stmt (*gsi_p);
2764 :
2765 3291845 : *handled_ops_p = true;
2766 3291845 : switch (gimple_code (stmt))
2767 : {
2768 148843 : case GIMPLE_TRY:
2769 148843 : case GIMPLE_BIND:
2770 148843 : case GIMPLE_CATCH:
2771 148843 : case GIMPLE_EH_FILTER:
2772 148843 : case GIMPLE_TRANSACTION:
2773 : /* Walk the sub-statements. */
2774 148843 : *handled_ops_p = false;
2775 148843 : break;
2776 259783 : case GIMPLE_CALL:
2777 259783 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2778 259783 : if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
2779 : {
2780 3962 : location_t loc = gimple_location (stmt);
2781 3962 : gsi_remove (gsi_p, true);
2782 3962 : wi->removed_stmt = true;
2783 :
2784 : /* nothrow flag is added by genericize_c_loop to mark fallthrough
2785 : statement at the end of some loop's body. Those should be
2786 : always diagnosed, either because they indeed don't precede
2787 : a case label or default label, or because the next statement
2788 : is not within the same iteration statement. */
2789 3962 : if ((stmt->subcode & GF_CALL_NOTHROW) != 0)
2790 : {
2791 12 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2792 : "a case label or default label");
2793 12 : break;
2794 : }
2795 :
2796 3950 : if (gsi_end_p (*gsi_p))
2797 : {
2798 32 : static_cast<location_t *>(wi->info)[0] = BUILTINS_LOCATION;
2799 32 : static_cast<location_t *>(wi->info)[1] = loc;
2800 32 : break;
2801 : }
2802 :
2803 3918 : bool found = false;
2804 :
2805 3918 : gimple_stmt_iterator gsi2 = *gsi_p;
2806 3918 : stmt = gsi_stmt (gsi2);
2807 3918 : tree lab;
2808 3918 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2809 1704 : && gimple_code (stmt) == GIMPLE_GOTO
2810 20 : && (lab = gimple_goto_dest (stmt))
2811 20 : && TREE_CODE (lab) == LABEL_DECL
2812 3938 : && VACUOUS_INIT_LABEL_P (lab))
2813 : {
2814 : /* Handle for C++ artificial -ftrivial-auto-var-init=
2815 : sequences. Those look like:
2816 : goto lab1;
2817 : lab2:;
2818 : v1 = .DEFERRED_INIT (...);
2819 : v2 = .DEFERRED_INIT (...);
2820 : lab3:;
2821 : v3 = .DEFERRED_INIT (...);
2822 : lab1:;
2823 : In this case, a case/default label can be either in between
2824 : the GIMPLE_GOTO and the corresponding GIMPLE_LABEL, if jumps
2825 : from the switch condition to the case/default label cross
2826 : vacuous initialization of some variables, or after the
2827 : corresponding GIMPLE_LABEL, if those jumps don't cross
2828 : any such initialization but there is an adjacent named label
2829 : which crosses such initialization. So, for the purpose of
2830 : this function, just ignore the goto but until reaching the
2831 : corresponding GIMPLE_LABEL allow also .DEFERRED_INIT
2832 : calls. */
2833 5 : gsi_next (&gsi2);
2834 : }
2835 3913 : else if (gimple_code (stmt) == GIMPLE_GOTO
2836 3913 : && !gimple_has_location (stmt))
2837 : {
2838 : /* Go on until the artificial label. */
2839 57 : tree goto_dest = gimple_goto_dest (stmt);
2840 414 : for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
2841 : {
2842 357 : if (gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL
2843 357 : && gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)))
2844 : == goto_dest)
2845 : break;
2846 : }
2847 :
2848 : /* Not found? Stop. */
2849 57 : if (gsi_end_p (gsi2))
2850 : break;
2851 :
2852 : /* Look one past it. */
2853 57 : gsi_next (&gsi2);
2854 : }
2855 :
2856 : /* We're looking for a case label or default label here. */
2857 4016 : while (!gsi_end_p (gsi2))
2858 : {
2859 4016 : stmt = gsi_stmt (gsi2);
2860 4016 : if (gimple_code (stmt) == GIMPLE_LABEL)
2861 : {
2862 3973 : tree label = gimple_label_label (as_a <glabel *> (stmt));
2863 3973 : if (gimple_has_location (stmt) && DECL_ARTIFICIAL (label))
2864 : {
2865 : found = true;
2866 : break;
2867 : }
2868 : }
2869 43 : else if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2870 : ;
2871 43 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2872 43 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2873 : ;
2874 43 : else if (!is_gimple_debug (stmt))
2875 : /* Anything else is not expected. */
2876 : break;
2877 98 : gsi_next (&gsi2);
2878 : }
2879 3918 : if (!found)
2880 23 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2881 : "a case label or default label");
2882 : }
2883 : break;
2884 2883219 : default:
2885 2883219 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2886 2883219 : break;
2887 : }
2888 3291845 : return NULL_TREE;
2889 : }
2890 :
2891 : /* Expand all FALLTHROUGH () calls in SEQ. */
2892 :
2893 : static void
2894 49043 : expand_FALLTHROUGH (gimple_seq *seq_p)
2895 : {
2896 49043 : auto_urlify_attributes sentinel;
2897 :
2898 49043 : struct walk_stmt_info wi;
2899 49043 : location_t loc[2];
2900 49043 : memset (&wi, 0, sizeof (wi));
2901 49043 : loc[0] = UNKNOWN_LOCATION;
2902 49043 : loc[1] = UNKNOWN_LOCATION;
2903 49043 : wi.info = (void *) &loc[0];
2904 49043 : walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
2905 49043 : if (loc[0] != UNKNOWN_LOCATION)
2906 : /* We've found [[fallthrough]]; at the end of a switch, which the C++
2907 : standard says is ill-formed; see [dcl.attr.fallthrough]. */
2908 8 : pedwarn (loc[1], 0, "attribute %<fallthrough%> not preceding "
2909 : "a case label or default label");
2910 49043 : }
2911 :
2912 :
2913 : /* Gimplify a SWITCH_EXPR, and collect the vector of labels it can
2914 : branch to. */
2915 :
2916 : static enum gimplify_status
2917 50872 : gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
2918 : {
2919 50872 : tree switch_expr = *expr_p;
2920 50872 : gimple_seq switch_body_seq = NULL;
2921 50872 : enum gimplify_status ret;
2922 50872 : tree index_type = TREE_TYPE (switch_expr);
2923 50872 : if (index_type == NULL_TREE)
2924 11450 : index_type = TREE_TYPE (SWITCH_COND (switch_expr));
2925 :
2926 50872 : ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
2927 : fb_rvalue);
2928 50872 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
2929 : return ret;
2930 :
2931 50872 : if (SWITCH_BODY (switch_expr))
2932 : {
2933 50872 : vec<tree> labels;
2934 50872 : vec<tree> saved_labels;
2935 50872 : hash_set<tree> *saved_live_switch_vars = NULL;
2936 50872 : tree default_case = NULL_TREE;
2937 50872 : gswitch *switch_stmt;
2938 :
2939 : /* Save old labels, get new ones from body, then restore the old
2940 : labels. Save all the things from the switch body to append after. */
2941 50872 : saved_labels = gimplify_ctxp->case_labels;
2942 50872 : gimplify_ctxp->case_labels.create (8);
2943 :
2944 : /* Do not create live_switch_vars if SWITCH_BODY is not a BIND_EXPR. */
2945 50872 : saved_live_switch_vars = gimplify_ctxp->live_switch_vars;
2946 50872 : tree_code body_type = TREE_CODE (SWITCH_BODY (switch_expr));
2947 50872 : if (body_type == BIND_EXPR || body_type == STATEMENT_LIST)
2948 50588 : gimplify_ctxp->live_switch_vars = new hash_set<tree> (4);
2949 : else
2950 284 : gimplify_ctxp->live_switch_vars = NULL;
2951 :
2952 50872 : bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
2953 50872 : gimplify_ctxp->in_switch_expr = true;
2954 :
2955 50872 : gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
2956 :
2957 50872 : gimplify_ctxp->in_switch_expr = old_in_switch_expr;
2958 50872 : maybe_warn_switch_unreachable_and_auto_init (switch_body_seq);
2959 50872 : maybe_warn_implicit_fallthrough (switch_body_seq);
2960 : /* Only do this for the outermost GIMPLE_SWITCH. */
2961 50872 : if (!gimplify_ctxp->in_switch_expr)
2962 49043 : expand_FALLTHROUGH (&switch_body_seq);
2963 :
2964 50872 : labels = gimplify_ctxp->case_labels;
2965 50872 : gimplify_ctxp->case_labels = saved_labels;
2966 :
2967 50872 : if (gimplify_ctxp->live_switch_vars)
2968 : {
2969 50588 : gcc_assert (gimplify_ctxp->live_switch_vars->is_empty ());
2970 50588 : delete gimplify_ctxp->live_switch_vars;
2971 : }
2972 50872 : gimplify_ctxp->live_switch_vars = saved_live_switch_vars;
2973 :
2974 50872 : preprocess_case_label_vec_for_gimple (labels, index_type,
2975 : &default_case);
2976 :
2977 50872 : bool add_bind = false;
2978 50872 : if (!default_case)
2979 : {
2980 15033 : glabel *new_default;
2981 :
2982 15033 : default_case
2983 15033 : = build_case_label (NULL_TREE, NULL_TREE,
2984 : create_artificial_label (UNKNOWN_LOCATION));
2985 15033 : if (old_in_switch_expr)
2986 : {
2987 1083 : SWITCH_BREAK_LABEL_P (CASE_LABEL (default_case)) = 1;
2988 1083 : add_bind = true;
2989 : }
2990 15033 : new_default = gimple_build_label (CASE_LABEL (default_case));
2991 15033 : gimplify_seq_add_stmt (&switch_body_seq, new_default);
2992 : }
2993 35839 : else if (old_in_switch_expr)
2994 : {
2995 746 : gimple *last = gimple_seq_last_stmt (switch_body_seq);
2996 746 : if (last && gimple_code (last) == GIMPLE_LABEL)
2997 : {
2998 481 : tree label = gimple_label_label (as_a <glabel *> (last));
2999 481 : if (SWITCH_BREAK_LABEL_P (label))
3000 50872 : add_bind = true;
3001 : }
3002 : }
3003 :
3004 50872 : switch_stmt = gimple_build_switch (SWITCH_COND (switch_expr),
3005 : default_case, labels);
3006 50872 : gimple_set_location (switch_stmt, EXPR_LOCATION (switch_expr));
3007 : /* For the benefit of -Wimplicit-fallthrough, if switch_body_seq
3008 : ends with a GIMPLE_LABEL holding SWITCH_BREAK_LABEL_P LABEL_DECL,
3009 : wrap the GIMPLE_SWITCH up to that GIMPLE_LABEL into a GIMPLE_BIND,
3010 : so that we can easily find the start and end of the switch
3011 : statement. */
3012 50872 : if (add_bind)
3013 : {
3014 1563 : gimple_seq bind_body = NULL;
3015 1563 : gimplify_seq_add_stmt (&bind_body, switch_stmt);
3016 1563 : gimple_seq_add_seq (&bind_body, switch_body_seq);
3017 1563 : gbind *bind = gimple_build_bind (NULL_TREE, bind_body, NULL_TREE);
3018 1563 : gimple_set_location (bind, EXPR_LOCATION (switch_expr));
3019 1563 : gimplify_seq_add_stmt (pre_p, bind);
3020 : }
3021 : else
3022 : {
3023 49309 : gimplify_seq_add_stmt (pre_p, switch_stmt);
3024 49309 : gimplify_seq_add_seq (pre_p, switch_body_seq);
3025 : }
3026 50872 : labels.release ();
3027 : }
3028 : else
3029 0 : gcc_unreachable ();
3030 :
3031 50872 : return GS_ALL_DONE;
3032 : }
3033 :
3034 : /* Gimplify the LABEL_EXPR pointed to by EXPR_P. */
3035 :
3036 : static enum gimplify_status
3037 2617976 : gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
3038 : {
3039 2617976 : gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
3040 : == current_function_decl);
3041 :
3042 2617976 : tree label = LABEL_EXPR_LABEL (*expr_p);
3043 2617976 : glabel *label_stmt = gimple_build_label (label);
3044 2617976 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3045 2617976 : gimplify_seq_add_stmt (pre_p, label_stmt);
3046 :
3047 2617976 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3048 21 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3049 : NOT_TAKEN));
3050 2617955 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3051 11 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3052 : TAKEN));
3053 :
3054 2617976 : return GS_ALL_DONE;
3055 : }
3056 :
3057 : /* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
3058 :
3059 : static enum gimplify_status
3060 1045379 : gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
3061 : {
3062 1045379 : struct gimplify_ctx *ctxp;
3063 1045379 : glabel *label_stmt;
3064 :
3065 : /* Invalid programs can play Duff's Device type games with, for example,
3066 : #pragma omp parallel. At least in the C front end, we don't
3067 : detect such invalid branches until after gimplification, in the
3068 : diagnose_omp_blocks pass. */
3069 1045389 : for (ctxp = gimplify_ctxp; ; ctxp = ctxp->prev_context)
3070 1045389 : if (ctxp->case_labels.exists ())
3071 : break;
3072 :
3073 1045379 : tree label = CASE_LABEL (*expr_p);
3074 1045379 : label_stmt = gimple_build_label (label);
3075 1045379 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3076 1045379 : ctxp->case_labels.safe_push (*expr_p);
3077 1045379 : gimplify_seq_add_stmt (pre_p, label_stmt);
3078 :
3079 1045379 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3080 16 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3081 : NOT_TAKEN));
3082 1045363 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3083 20 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3084 : TAKEN));
3085 :
3086 1045379 : return GS_ALL_DONE;
3087 : }
3088 :
3089 : /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first
3090 : if necessary. */
3091 :
3092 : tree
3093 1807717 : build_and_jump (tree *label_p)
3094 : {
3095 1807717 : if (label_p == NULL)
3096 : /* If there's nowhere to jump, just fall through. */
3097 : return NULL_TREE;
3098 :
3099 1225447 : if (*label_p == NULL_TREE)
3100 : {
3101 702348 : tree label = create_artificial_label (UNKNOWN_LOCATION);
3102 702348 : *label_p = label;
3103 : }
3104 :
3105 1225447 : return build1 (GOTO_EXPR, void_type_node, *label_p);
3106 : }
3107 :
3108 : /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
3109 : This also involves building a label to jump to and communicating it to
3110 : gimplify_loop_expr through gimplify_ctxp->exit_label. */
3111 :
3112 : static enum gimplify_status
3113 3207 : gimplify_exit_expr (tree *expr_p)
3114 : {
3115 3207 : tree cond = TREE_OPERAND (*expr_p, 0);
3116 3207 : tree expr;
3117 :
3118 3207 : expr = build_and_jump (&gimplify_ctxp->exit_label);
3119 3207 : expr = build3 (COND_EXPR, void_type_node, cond, expr, NULL_TREE);
3120 3207 : *expr_p = expr;
3121 :
3122 3207 : return GS_OK;
3123 : }
3124 :
3125 : /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is
3126 : different from its canonical type, wrap the whole thing inside a
3127 : NOP_EXPR and force the type of the COMPONENT_REF to be the canonical
3128 : type.
3129 :
3130 : The canonical type of a COMPONENT_REF is the type of the field being
3131 : referenced--unless the field is a bit-field which can be read directly
3132 : in a smaller mode, in which case the canonical type is the
3133 : sign-appropriate type corresponding to that mode. */
3134 :
3135 : static void
3136 19108266 : canonicalize_component_ref (tree *expr_p)
3137 : {
3138 19108266 : tree expr = *expr_p;
3139 19108266 : tree type;
3140 :
3141 19108266 : gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
3142 :
3143 19108266 : if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
3144 7653063 : type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
3145 : else
3146 11455203 : type = TREE_TYPE (TREE_OPERAND (expr, 1));
3147 :
3148 : /* One could argue that all the stuff below is not necessary for
3149 : the non-bitfield case and declare it a FE error if type
3150 : adjustment would be needed. */
3151 19108266 : if (TREE_TYPE (expr) != type)
3152 : {
3153 : #ifdef ENABLE_TYPES_CHECKING
3154 821060 : tree old_type = TREE_TYPE (expr);
3155 : #endif
3156 821060 : int type_quals;
3157 :
3158 : /* We need to preserve qualifiers and propagate them from
3159 : operand 0. */
3160 821060 : type_quals = TYPE_QUALS (type)
3161 821060 : | TYPE_QUALS (TREE_TYPE (TREE_OPERAND (expr, 0)));
3162 821060 : if (TYPE_QUALS (type) != type_quals)
3163 820803 : type = build_qualified_type (TYPE_MAIN_VARIANT (type), type_quals);
3164 :
3165 : /* Set the type of the COMPONENT_REF to the underlying type. */
3166 821060 : TREE_TYPE (expr) = type;
3167 :
3168 : #ifdef ENABLE_TYPES_CHECKING
3169 : /* It is now a FE error, if the conversion from the canonical
3170 : type to the original expression type is not useless. */
3171 821060 : gcc_assert (useless_type_conversion_p (old_type, type));
3172 : #endif
3173 : }
3174 19108266 : }
3175 :
3176 : /* If a NOP conversion is changing a pointer to array of foo to a pointer
3177 : to foo, embed that change in the ADDR_EXPR by converting
3178 : T array[U];
3179 : (T *)&array
3180 : ==>
3181 : &array[L]
3182 : where L is the lower bound. For simplicity, only do this for constant
3183 : lower bound.
3184 : The constraint is that the type of &array[L] is trivially convertible
3185 : to T *. */
3186 :
3187 : static void
3188 565737 : canonicalize_addr_expr (tree *expr_p)
3189 : {
3190 565737 : tree expr = *expr_p;
3191 565737 : tree addr_expr = TREE_OPERAND (expr, 0);
3192 565737 : tree datype, ddatype, pddatype;
3193 :
3194 : /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
3195 1131128 : if (!POINTER_TYPE_P (TREE_TYPE (expr))
3196 565737 : || TREE_CODE (addr_expr) != ADDR_EXPR)
3197 : return;
3198 :
3199 : /* The addr_expr type should be a pointer to an array. */
3200 346 : datype = TREE_TYPE (TREE_TYPE (addr_expr));
3201 346 : if (TREE_CODE (datype) != ARRAY_TYPE)
3202 : return;
3203 :
3204 : /* The pointer to element type shall be trivially convertible to
3205 : the expression pointer type. */
3206 28 : ddatype = TREE_TYPE (datype);
3207 28 : pddatype = build_pointer_type (ddatype);
3208 28 : if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
3209 : pddatype))
3210 : return;
3211 :
3212 : /* The lower bound and element sizes must be constant. */
3213 0 : if (!TYPE_SIZE_UNIT (ddatype)
3214 0 : || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
3215 0 : || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
3216 0 : || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
3217 : return;
3218 :
3219 : /* All checks succeeded. Build a new node to merge the cast. */
3220 0 : *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
3221 0 : TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
3222 : NULL_TREE, NULL_TREE);
3223 0 : *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
3224 :
3225 : /* We can have stripped a required restrict qualifier above. */
3226 0 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
3227 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
3228 : }
3229 :
3230 : /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
3231 : underneath as appropriate. */
3232 :
3233 : static enum gimplify_status
3234 13268342 : gimplify_conversion (tree *expr_p)
3235 : {
3236 13268342 : location_t loc = EXPR_LOCATION (*expr_p);
3237 13268342 : gcc_assert (CONVERT_EXPR_P (*expr_p));
3238 :
3239 : /* Then strip away all but the outermost conversion. */
3240 13268342 : STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
3241 :
3242 : /* And remove the outermost conversion if it's useless. */
3243 13268342 : if (tree_ssa_useless_type_conversion (*expr_p))
3244 0 : *expr_p = TREE_OPERAND (*expr_p, 0);
3245 :
3246 : /* If we still have a conversion at the toplevel,
3247 : then canonicalize some constructs. */
3248 13268342 : if (CONVERT_EXPR_P (*expr_p))
3249 : {
3250 13268342 : tree sub = TREE_OPERAND (*expr_p, 0);
3251 :
3252 : /* If a NOP conversion is changing the type of a COMPONENT_REF
3253 : expression, then canonicalize its type now in order to expose more
3254 : redundant conversions. */
3255 13268342 : if (TREE_CODE (sub) == COMPONENT_REF)
3256 277497 : canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0));
3257 :
3258 : /* If a NOP conversion is changing a pointer to array of foo
3259 : to a pointer to foo, embed that change in the ADDR_EXPR. */
3260 12990845 : else if (TREE_CODE (sub) == ADDR_EXPR)
3261 565737 : canonicalize_addr_expr (expr_p);
3262 : }
3263 :
3264 : /* If we have a conversion to a non-register type force the
3265 : use of a VIEW_CONVERT_EXPR instead. */
3266 13268342 : if (CONVERT_EXPR_P (*expr_p) && !is_gimple_reg_type (TREE_TYPE (*expr_p)))
3267 90 : *expr_p = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p),
3268 90 : TREE_OPERAND (*expr_p, 0));
3269 :
3270 : /* Canonicalize CONVERT_EXPR to NOP_EXPR. */
3271 13268342 : if (TREE_CODE (*expr_p) == CONVERT_EXPR)
3272 233882 : TREE_SET_CODE (*expr_p, NOP_EXPR);
3273 :
3274 13268342 : return GS_OK;
3275 : }
3276 :
3277 : /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
3278 : DECL_VALUE_EXPR, and it's worth re-examining things. */
3279 :
3280 : static enum gimplify_status
3281 130635419 : gimplify_var_or_parm_decl (tree *expr_p)
3282 : {
3283 130635419 : tree decl = *expr_p;
3284 :
3285 : /* ??? If this is a local variable, and it has not been seen in any
3286 : outer BIND_EXPR, then it's probably the result of a duplicate
3287 : declaration, for which we've already issued an error. It would
3288 : be really nice if the front end wouldn't leak these at all.
3289 : Currently the only known culprit is C++ destructors, as seen
3290 : in g++.old-deja/g++.jason/binding.C.
3291 : Another possible culpit are size expressions for variably modified
3292 : types which are lost in the FE or not gimplified correctly. */
3293 130635419 : if (VAR_P (decl)
3294 101534234 : && !DECL_SEEN_IN_BIND_EXPR_P (decl)
3295 17312919 : && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
3296 130695515 : && decl_function_context (decl) == current_function_decl)
3297 : {
3298 77 : gcc_assert (seen_error ());
3299 : return GS_ERROR;
3300 : }
3301 :
3302 : /* When within an OMP context, notice uses of variables. */
3303 130635342 : if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
3304 : return GS_ALL_DONE;
3305 :
3306 : /* If the decl is an alias for another expression, substitute it now. */
3307 130629522 : if (DECL_HAS_VALUE_EXPR_P (decl))
3308 : {
3309 462288 : *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
3310 462288 : return GS_OK;
3311 : }
3312 :
3313 : return GS_ALL_DONE;
3314 : }
3315 :
3316 : /* Recalculate the value of the TREE_SIDE_EFFECTS flag for T. */
3317 :
3318 : static void
3319 113589841 : recalculate_side_effects (tree t)
3320 : {
3321 113589841 : enum tree_code code = TREE_CODE (t);
3322 113589841 : int len = TREE_OPERAND_LENGTH (t);
3323 113589841 : int i;
3324 :
3325 113589841 : switch (TREE_CODE_CLASS (code))
3326 : {
3327 674165 : case tcc_expression:
3328 674165 : switch (code)
3329 : {
3330 : case INIT_EXPR:
3331 : case MODIFY_EXPR:
3332 : case VA_ARG_EXPR:
3333 : case PREDECREMENT_EXPR:
3334 : case PREINCREMENT_EXPR:
3335 : case POSTDECREMENT_EXPR:
3336 : case POSTINCREMENT_EXPR:
3337 : /* All of these have side-effects, no matter what their
3338 : operands are. */
3339 : return;
3340 :
3341 : default:
3342 : break;
3343 : }
3344 : /* Fall through. */
3345 :
3346 113589837 : case tcc_comparison: /* a comparison expression */
3347 113589837 : case tcc_unary: /* a unary arithmetic expression */
3348 113589837 : case tcc_binary: /* a binary arithmetic expression */
3349 113589837 : case tcc_reference: /* a reference */
3350 113589837 : case tcc_vl_exp: /* a function call */
3351 113589837 : TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
3352 369976083 : for (i = 0; i < len; ++i)
3353 : {
3354 256386246 : tree op = TREE_OPERAND (t, i);
3355 256386246 : if (op && TREE_SIDE_EFFECTS (op))
3356 1305206 : TREE_SIDE_EFFECTS (t) = 1;
3357 : }
3358 : break;
3359 :
3360 : case tcc_constant:
3361 : /* No side-effects. */
3362 : return;
3363 :
3364 : case tcc_declaration:
3365 : /* These can have side-effects if TREE_THIS_VOLATILE,
3366 : but those should be set elsewhere, not in
3367 : recalculate_side_effects. Can be triggered e.g. if
3368 : a comparison is folded into one of its operands. */
3369 : return;
3370 :
3371 2 : default:
3372 2 : if (code == SSA_NAME)
3373 : /* No side-effects. */
3374 : return;
3375 0 : gcc_unreachable ();
3376 : }
3377 : }
3378 :
3379 : /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
3380 : node *EXPR_P.
3381 :
3382 : compound_lval
3383 : : min_lval '[' val ']'
3384 : | min_lval '.' ID
3385 : | compound_lval '[' val ']'
3386 : | compound_lval '.' ID
3387 :
3388 : This is not part of the original SIMPLE definition, which separates
3389 : array and member references, but it seems reasonable to handle them
3390 : together. Also, this way we don't run into problems with union
3391 : aliasing; gcc requires that for accesses through a union to alias, the
3392 : union reference must be explicit, which was not always the case when we
3393 : were splitting up array and member refs.
3394 :
3395 : PRE_P points to the sequence where side effects that must happen before
3396 : *EXPR_P should be stored.
3397 :
3398 : POST_P points to the sequence where side effects that must happen after
3399 : *EXPR_P should be stored. */
3400 :
3401 : static enum gimplify_status
3402 30901455 : gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3403 : fallback_t fallback)
3404 : {
3405 30901455 : tree *p;
3406 30901455 : enum gimplify_status ret = GS_ALL_DONE, tret;
3407 30901455 : int i;
3408 30901455 : location_t loc = EXPR_LOCATION (*expr_p);
3409 30901455 : tree expr = *expr_p;
3410 :
3411 : /* Create a stack of the subexpressions so later we can walk them in
3412 : order from inner to outer. */
3413 30901455 : auto_vec<tree, 10> expr_stack;
3414 :
3415 : /* We can handle anything that get_inner_reference can deal with. */
3416 74550668 : for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
3417 : {
3418 43715330 : restart:
3419 : /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
3420 74616785 : if (TREE_CODE (*p) == INDIRECT_REF)
3421 4101599 : *p = fold_indirect_ref_loc (loc, *p);
3422 :
3423 74616785 : if (handled_component_p (*p))
3424 : ;
3425 : /* Expand DECL_VALUE_EXPR now. In some cases that may expose
3426 : additional COMPONENT_REFs. */
3427 13705662 : else if ((VAR_P (*p) || TREE_CODE (*p) == PARM_DECL)
3428 32419201 : && gimplify_var_or_parm_decl (p) == GS_OK)
3429 66117 : goto restart;
3430 : else
3431 : break;
3432 :
3433 43649213 : expr_stack.safe_push (*p);
3434 : }
3435 :
3436 30901455 : gcc_assert (expr_stack.length ());
3437 :
3438 : /* Now EXPR_STACK is a stack of pointers to all the refs we've
3439 : walked through and P points to the innermost expression.
3440 :
3441 : Java requires that we elaborated nodes in source order. That
3442 : means we must gimplify the inner expression followed by each of
3443 : the indices, in order. But we can't gimplify the inner
3444 : expression until we deal with any variable bounds, sizes, or
3445 : positions in order to deal with PLACEHOLDER_EXPRs.
3446 :
3447 : The base expression may contain a statement expression that
3448 : has declarations used in size expressions, so has to be
3449 : gimplified before gimplifying the size expressions.
3450 :
3451 : So we do this in three steps. First we deal with variable
3452 : bounds, sizes, and positions, then we gimplify the base and
3453 : ensure it is memory if needed, then we deal with the annotations
3454 : for any variables in the components and any indices, from left
3455 : to right. */
3456 :
3457 30901455 : bool need_non_reg = false;
3458 74550665 : for (i = expr_stack.length () - 1; i >= 0; i--)
3459 : {
3460 43649213 : tree t = expr_stack[i];
3461 :
3462 43649213 : if (error_operand_p (TREE_OPERAND (t, 0)))
3463 : return GS_ERROR;
3464 :
3465 43649210 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3466 : {
3467 : /* Deal with the low bound and element type size and put them into
3468 : the ARRAY_REF. If these values are set, they have already been
3469 : gimplified. */
3470 9090779 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3471 : {
3472 9026473 : tree low = unshare_expr (array_ref_low_bound (t));
3473 9026473 : if (!is_gimple_min_invariant (low))
3474 : {
3475 0 : TREE_OPERAND (t, 2) = low;
3476 : }
3477 : }
3478 :
3479 9090779 : if (TREE_OPERAND (t, 3) == NULL_TREE)
3480 : {
3481 9076724 : tree elmt_size = array_ref_element_size (t);
3482 9076724 : if (!is_gimple_min_invariant (elmt_size))
3483 : {
3484 8781 : elmt_size = unshare_expr (elmt_size);
3485 8781 : tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
3486 8781 : tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
3487 :
3488 : /* Divide the element size by the alignment of the element
3489 : type (above). */
3490 8781 : elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR,
3491 : elmt_size, factor);
3492 :
3493 8781 : TREE_OPERAND (t, 3) = elmt_size;
3494 : }
3495 : }
3496 : need_non_reg = true;
3497 : }
3498 34558431 : else if (TREE_CODE (t) == COMPONENT_REF)
3499 : {
3500 : /* Set the field offset into T and gimplify it. */
3501 33245142 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3502 : {
3503 33244763 : tree offset = component_ref_field_offset (t);
3504 33244763 : if (!is_gimple_min_invariant (offset))
3505 : {
3506 287 : offset = unshare_expr (offset);
3507 287 : tree field = TREE_OPERAND (t, 1);
3508 287 : tree factor
3509 287 : = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
3510 :
3511 : /* Divide the offset by its alignment. */
3512 287 : offset = size_binop_loc (loc, EXACT_DIV_EXPR,
3513 : offset, factor);
3514 :
3515 287 : TREE_OPERAND (t, 2) = offset;
3516 : }
3517 : }
3518 : need_non_reg = true;
3519 : }
3520 1313289 : else if (!is_gimple_reg_type (TREE_TYPE (t)))
3521 : /* When the result of an operation, in particular a VIEW_CONVERT_EXPR
3522 : is a non-register type then require the base object to be a
3523 : non-register as well. */
3524 42619989 : need_non_reg = true;
3525 : }
3526 :
3527 : /* Step 2 is to gimplify the base expression. Make sure lvalue is set
3528 : so as to match the min_lval predicate. Failure to do so may result
3529 : in the creation of large aggregate temporaries. */
3530 30901452 : tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
3531 : fallback | fb_lvalue);
3532 30901452 : ret = MIN (ret, tret);
3533 30901452 : if (ret == GS_ERROR)
3534 : return GS_ERROR;
3535 :
3536 : /* Step 2a: if we have component references we do not support on
3537 : registers then make sure the base isn't a register. Of course
3538 : we can only do so if an rvalue is OK. */
3539 30901452 : if (need_non_reg && (fallback & fb_rvalue))
3540 23042598 : prepare_gimple_addressable (p, pre_p);
3541 :
3542 :
3543 : /* Step 3: gimplify size expressions and the indices and operands of
3544 : ARRAY_REF. During this loop we also remove any useless conversions.
3545 : If we operate on a register also make sure to properly gimplify
3546 : to individual operations. */
3547 :
3548 30901452 : bool reg_operations = is_gimple_reg (*p);
3549 105452114 : for (; expr_stack.length () > 0; )
3550 : {
3551 43649210 : tree t = expr_stack.pop ();
3552 :
3553 43649210 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3554 : {
3555 9090779 : gcc_assert (!reg_operations);
3556 :
3557 : /* Gimplify the low bound and element type size. */
3558 9090779 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3559 : is_gimple_reg, fb_rvalue);
3560 9090779 : ret = MIN (ret, tret);
3561 :
3562 9090779 : tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
3563 : is_gimple_reg, fb_rvalue);
3564 9090779 : ret = MIN (ret, tret);
3565 :
3566 : /* Gimplify the dimension. */
3567 9090779 : tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
3568 : is_gimple_val, fb_rvalue);
3569 9090779 : ret = MIN (ret, tret);
3570 : }
3571 34558431 : else if (TREE_CODE (t) == COMPONENT_REF)
3572 : {
3573 33245142 : gcc_assert (!reg_operations);
3574 :
3575 33245142 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3576 : is_gimple_reg, fb_rvalue);
3577 33245142 : ret = MIN (ret, tret);
3578 : }
3579 1313289 : else if (reg_operations)
3580 : {
3581 910330 : tret = gimplify_expr (&TREE_OPERAND (t, 0), pre_p, post_p,
3582 : is_gimple_val, fb_rvalue);
3583 1313289 : ret = MIN (ret, tret);
3584 : }
3585 :
3586 43649210 : STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
3587 :
3588 : /* The innermost expression P may have originally had
3589 : TREE_SIDE_EFFECTS set which would have caused all the outer
3590 : expressions in *EXPR_P leading to P to also have had
3591 : TREE_SIDE_EFFECTS set. */
3592 43649210 : recalculate_side_effects (t);
3593 : }
3594 :
3595 : /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */
3596 30901452 : if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
3597 : {
3598 18830769 : canonicalize_component_ref (expr_p);
3599 : }
3600 :
3601 30901452 : expr_stack.release ();
3602 :
3603 30901452 : gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
3604 :
3605 : return ret;
3606 30901455 : }
3607 :
3608 : /* Gimplify the self modifying expression pointed to by EXPR_P
3609 : (++, --, +=, -=).
3610 :
3611 : PRE_P points to the list where side effects that must happen before
3612 : *EXPR_P should be stored.
3613 :
3614 : POST_P points to the list where side effects that must happen after
3615 : *EXPR_P should be stored.
3616 :
3617 : WANT_VALUE is nonzero iff we want to use the value of this expression
3618 : in another expression.
3619 :
3620 : ARITH_TYPE is the type the computation should be performed in. */
3621 :
3622 : enum gimplify_status
3623 1153529 : gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3624 : bool want_value, tree arith_type)
3625 : {
3626 1153529 : enum tree_code code;
3627 1153529 : tree lhs, lvalue, rhs, t1;
3628 1153529 : gimple_seq post = NULL, *orig_post_p = post_p;
3629 1153529 : bool postfix;
3630 1153529 : enum tree_code arith_code;
3631 1153529 : enum gimplify_status ret;
3632 1153529 : location_t loc = EXPR_LOCATION (*expr_p);
3633 :
3634 1153529 : code = TREE_CODE (*expr_p);
3635 :
3636 1153529 : gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
3637 : || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
3638 :
3639 : /* Prefix or postfix? */
3640 1153529 : if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
3641 : /* Faster to treat as prefix if result is not used. */
3642 : postfix = want_value;
3643 : else
3644 : postfix = false;
3645 :
3646 : /* For postfix, make sure the inner expression's post side effects
3647 : are executed after side effects from this expression. */
3648 410986 : if (postfix)
3649 1153529 : post_p = &post;
3650 :
3651 : /* Add or subtract? */
3652 1153529 : if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
3653 : arith_code = PLUS_EXPR;
3654 : else
3655 46130 : arith_code = MINUS_EXPR;
3656 :
3657 : /* Gimplify the LHS into a GIMPLE lvalue. */
3658 1153529 : lvalue = TREE_OPERAND (*expr_p, 0);
3659 1153529 : ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
3660 1153529 : if (ret == GS_ERROR)
3661 : return ret;
3662 :
3663 : /* Extract the operands to the arithmetic operation. */
3664 1153526 : lhs = lvalue;
3665 1153526 : rhs = TREE_OPERAND (*expr_p, 1);
3666 :
3667 : /* For postfix operator, we evaluate the LHS to an rvalue and then use
3668 : that as the result value and in the postqueue operation. */
3669 1153526 : if (postfix)
3670 : {
3671 189173 : ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
3672 189173 : if (ret == GS_ERROR)
3673 : return ret;
3674 :
3675 189173 : lhs = get_initialized_tmp_var (lhs, pre_p);
3676 : }
3677 :
3678 : /* For POINTERs increment, use POINTER_PLUS_EXPR. */
3679 1153526 : if (POINTER_TYPE_P (TREE_TYPE (lhs)))
3680 : {
3681 238862 : rhs = convert_to_ptrofftype_loc (loc, rhs);
3682 238862 : if (arith_code == MINUS_EXPR)
3683 10281 : rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
3684 238862 : t1 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
3685 : }
3686 : else
3687 914664 : t1 = fold_convert (TREE_TYPE (*expr_p),
3688 : fold_build2 (arith_code, arith_type,
3689 : fold_convert (arith_type, lhs),
3690 : fold_convert (arith_type, rhs)));
3691 :
3692 1153526 : if (postfix)
3693 : {
3694 189173 : gimplify_assign (lvalue, t1, pre_p);
3695 189173 : gimplify_seq_add_seq (orig_post_p, post);
3696 189173 : *expr_p = lhs;
3697 189173 : return GS_ALL_DONE;
3698 : }
3699 : else
3700 : {
3701 964353 : *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
3702 964353 : return GS_OK;
3703 : }
3704 : }
3705 :
3706 : /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
3707 :
3708 : static void
3709 83977124 : maybe_with_size_expr (tree *expr_p)
3710 : {
3711 83977124 : tree expr = *expr_p;
3712 83977124 : tree type = TREE_TYPE (expr);
3713 83977124 : tree size;
3714 :
3715 : /* If we've already wrapped this or the type is error_mark_node, we can't do
3716 : anything. */
3717 83977124 : if (TREE_CODE (expr) == WITH_SIZE_EXPR
3718 83976999 : || type == error_mark_node)
3719 : return;
3720 :
3721 : /* If the size isn't known or is a constant, we have nothing to do. */
3722 83976851 : size = TYPE_SIZE_UNIT (type);
3723 83976851 : if (!size || poly_int_tree_p (size))
3724 : return;
3725 :
3726 : /* Otherwise, make a WITH_SIZE_EXPR. */
3727 1698 : size = unshare_expr (size);
3728 1698 : size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
3729 1698 : *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
3730 : }
3731 :
3732 : /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P
3733 : Store any side-effects in PRE_P. CALL_LOCATION is the location of
3734 : the CALL_EXPR. If ALLOW_SSA is set the actual parameter may be
3735 : gimplified to an SSA name. */
3736 :
3737 : enum gimplify_status
3738 35209664 : gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
3739 : bool allow_ssa)
3740 : {
3741 35209664 : bool (*test) (tree);
3742 35209664 : fallback_t fb;
3743 :
3744 : /* In general, we allow lvalues for function arguments to avoid
3745 : extra overhead of copying large aggregates out of even larger
3746 : aggregates into temporaries only to copy the temporaries to
3747 : the argument list. Make optimizers happy by pulling out to
3748 : temporaries those types that fit in registers. */
3749 35209664 : if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
3750 : test = is_gimple_val, fb = fb_rvalue;
3751 : else
3752 : {
3753 1615204 : test = is_gimple_lvalue, fb = fb_either;
3754 : /* Also strip a TARGET_EXPR that would force an extra copy. */
3755 1615204 : if (TREE_CODE (*arg_p) == TARGET_EXPR)
3756 : {
3757 335668 : tree init = TARGET_EXPR_INITIAL (*arg_p);
3758 335668 : if (init
3759 335665 : && !VOID_TYPE_P (TREE_TYPE (init))
3760 : /* Currently, due to c++/116015, it is not desirable to
3761 : strip a TARGET_EXPR whose initializer is a {}. The
3762 : problem is that if we do elide it, we also have to
3763 : replace all the occurrences of the slot temporary in the
3764 : initializer with the temporary created for the argument.
3765 : But we do not have that temporary yet so the replacement
3766 : would be quite awkward and it might be needed to resort
3767 : back to a PLACEHOLDER_EXPR. Note that stripping the
3768 : TARGET_EXPR wouldn't help anyway, as gimplify_expr would
3769 : just allocate a temporary to store the CONSTRUCTOR into.
3770 : (FIXME PR116375.)
3771 :
3772 : See convert_for_arg_passing for the C++ code that marks
3773 : the TARGET_EXPR as eliding or not. */
3774 629082 : && TREE_CODE (init) != CONSTRUCTOR)
3775 254574 : *arg_p = init;
3776 : }
3777 : }
3778 :
3779 : /* If this is a variable sized type, we must remember the size. */
3780 35209664 : maybe_with_size_expr (arg_p);
3781 :
3782 : /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */
3783 : /* Make sure arguments have the same location as the function call
3784 : itself. */
3785 35209664 : protected_set_expr_location (*arg_p, call_location);
3786 :
3787 : /* There is a sequence point before a function call. Side effects in
3788 : the argument list must occur before the actual call. So, when
3789 : gimplifying arguments, force gimplify_expr to use an internal
3790 : post queue which is then appended to the end of PRE_P. */
3791 35209664 : return gimplify_expr (arg_p, pre_p, NULL, test, fb, allow_ssa);
3792 : }
3793 :
3794 : /* Don't fold inside offloading or taskreg regions: it can break code by
3795 : adding decl references that weren't in the source. We'll do it during
3796 : omplower pass instead. */
3797 :
3798 : static bool
3799 60623209 : maybe_fold_stmt (gimple_stmt_iterator *gsi)
3800 : {
3801 60623209 : struct gimplify_omp_ctx *ctx;
3802 61152161 : for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
3803 1201063 : if ((ctx->region_type & (ORT_TARGET | ORT_PARALLEL | ORT_TASK)) != 0)
3804 : return false;
3805 533971 : else if ((ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
3806 : return false;
3807 : /* Delay folding of builtins until the IL is in consistent state
3808 : so the diagnostic machinery can do a better job. */
3809 59951098 : if (gimple_call_builtin_p (gsi_stmt (*gsi)))
3810 : return false;
3811 57541304 : return fold_stmt (gsi);
3812 : }
3813 :
3814 : static tree
3815 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
3816 : tree construct_context);
3817 :
3818 :
3819 : /* Helper function for calls to omp_dynamic_cond: find the current
3820 : enclosing block in the gimplification context. */
3821 : static tree
3822 369 : find_supercontext (void)
3823 : {
3824 369 : vec<gbind *>stack = gimple_bind_expr_stack ();
3825 706 : for (int i = stack.length () - 1; i >= 0; i++)
3826 : {
3827 337 : gbind *b = stack[i];
3828 337 : if (b->block)
3829 : return b->block;
3830 : }
3831 : return NULL_TREE;
3832 : }
3833 :
3834 : /* OpenMP: Handle the append_args and adjust_args clauses of
3835 : declare_variant for EXPR, which is a CALL_EXPR whose CALL_EXPR_FN
3836 : is the variant, within a dispatch construct with clauses DISPATCH_CLAUSES.
3837 : WANT_VALUE and POINTERIZE are as for expand_variant_call_expr.
3838 :
3839 : 'append_args' causes interop objects are added after the last regular
3840 : (nonhidden, nonvariadic) arguments of the variant function.
3841 : 'adjust_args' with need_device_{addr,ptr} converts the pointer target of
3842 : a pointer from a host to a device address. This uses either the default
3843 : device or the passed device number, which then sets the default device
3844 : address. */
3845 : static tree
3846 471 : modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
3847 : bool want_value, bool pointerize)
3848 : {
3849 471 : location_t loc = EXPR_LOCATION (expr);
3850 471 : tree fndecl = get_callee_fndecl (expr);
3851 :
3852 : /* Skip processing if we don't get the expected call form. */
3853 471 : if (!fndecl)
3854 : return expr;
3855 :
3856 471 : tree init_code = NULL_TREE;
3857 471 : tree cleanup = NULL_TREE;
3858 471 : tree clobbers = NULL_TREE;
3859 471 : int nargs = call_expr_nargs (expr);
3860 471 : tree dispatch_device_num = NULL_TREE;
3861 471 : tree dispatch_interop = NULL_TREE;
3862 471 : tree dispatch_append_args = NULL_TREE;
3863 471 : int nfirst_args = 0;
3864 471 : tree dispatch_adjust_args_list
3865 471 : = lookup_attribute ("omp declare variant variant args",
3866 471 : DECL_ATTRIBUTES (fndecl));
3867 :
3868 471 : if (dispatch_adjust_args_list)
3869 : {
3870 389 : dispatch_adjust_args_list = TREE_VALUE (dispatch_adjust_args_list);
3871 389 : dispatch_append_args = TREE_CHAIN (dispatch_adjust_args_list);
3872 389 : if (TREE_PURPOSE (dispatch_adjust_args_list) == NULL_TREE
3873 389 : && TREE_VALUE (dispatch_adjust_args_list) == NULL_TREE)
3874 : dispatch_adjust_args_list = NULL_TREE;
3875 : }
3876 389 : if (dispatch_append_args)
3877 : {
3878 245 : nfirst_args = tree_to_shwi (TREE_PURPOSE (dispatch_append_args));
3879 245 : dispatch_append_args = TREE_VALUE (dispatch_append_args);
3880 : }
3881 471 : dispatch_device_num = omp_find_clause (dispatch_clauses, OMP_CLAUSE_DEVICE);
3882 471 : if (dispatch_device_num)
3883 287 : dispatch_device_num = OMP_CLAUSE_DEVICE_ID (dispatch_device_num);
3884 471 : dispatch_interop = omp_find_clause (dispatch_clauses, OMP_CLAUSE_INTEROP);
3885 471 : int nappend = 0, ninterop = 0;
3886 1351 : for (tree t = dispatch_append_args; t; t = TREE_CHAIN (t))
3887 409 : nappend++;
3888 :
3889 : /* FIXME: error checking should be taken out of this function and
3890 : handled before any attempt at filtering or resolution happens.
3891 : Otherwise whether or not diagnostics appear is determined by
3892 : GCC internals, how good the front ends are at constant-folding,
3893 : the split between early/late resolution, etc instead of the code
3894 : as written by the user. */
3895 471 : if (dispatch_interop)
3896 861 : for (tree t = dispatch_interop; t; t = TREE_CHAIN (t))
3897 605 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3898 409 : ninterop++;
3899 471 : if (dispatch_interop && !dispatch_device_num)
3900 : {
3901 7 : gcc_checking_assert (ninterop > 1);
3902 7 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3903 : "the %<device%> clause must be present if the %<interop%> "
3904 : "clause has more than one list item");
3905 : }
3906 471 : if (nappend < ninterop)
3907 : {
3908 48 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3909 : "number of list items in %<interop%> clause (%d) "
3910 : "exceeds the number of %<append_args%> items (%d) for "
3911 : "%<declare variant%> candidate %qD", ninterop, nappend, fndecl);
3912 88 : inform (dispatch_append_args
3913 8 : ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args))
3914 40 : : DECL_SOURCE_LOCATION (fndecl),
3915 : "%<declare variant%> candidate %qD declared here", fndecl);
3916 48 : ninterop = nappend;
3917 : }
3918 471 : if (dispatch_append_args)
3919 : {
3920 245 : tree *buffer = XALLOCAVEC (tree, nargs + nappend);
3921 245 : tree arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
3922 : /* Copy the first arguments; insert then the interop objects,
3923 : and then copy the rest (nargs - nfirst_args) args. */
3924 245 : int i;
3925 679 : for (i = 0; i < nfirst_args; i++)
3926 : {
3927 434 : arg = TREE_CHAIN (arg);
3928 434 : buffer[i] = CALL_EXPR_ARG (expr, i);
3929 : }
3930 : int j = ninterop;
3931 583 : for (tree t = dispatch_interop; t && j > 0; t = TREE_CHAIN (t))
3932 338 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3933 338 : buffer[i + --j] = OMP_CLAUSE_DECL (t);
3934 245 : gcc_checking_assert (j == 0);
3935 :
3936 : /* Do we need to create additional interop objects? */
3937 245 : if (ninterop < nappend)
3938 : {
3939 56 : if (dispatch_device_num == NULL_TREE)
3940 : /* Not remapping device number. */
3941 22 : dispatch_device_num = build_int_cst (integer_type_node,
3942 : GOMP_DEVICE_DEFAULT_OMP_61);
3943 56 : int nnew = nappend - ninterop;
3944 56 : tree nobjs = build_int_cst (integer_type_node, nnew);
3945 56 : tree a, t;
3946 :
3947 : /* Skip to the append_args clause for the first constructed
3948 : interop argument. */
3949 56 : tree apparg = dispatch_append_args;
3950 83 : for (j = 0; j < ninterop; j++)
3951 27 : apparg = TREE_CHAIN (apparg);
3952 :
3953 : /* omp_interop_t *objs[n]; */
3954 56 : tree objtype = build_pointer_type (pointer_sized_int_node);
3955 56 : t = build_array_type_nelts (objtype, nnew);
3956 56 : tree objs = create_tmp_var (t, "interopobjs");
3957 :
3958 : /* int target_tgtsync[n]; */
3959 56 : t = build_array_type_nelts (integer_type_node, nnew);
3960 56 : tree target_tgtsync = create_tmp_var (t, "tgt_tgtsync");
3961 :
3962 : /* Scan first to determine if we need a prefer_type array. */
3963 56 : tree prefer_type = NULL_TREE;
3964 56 : tree prefer_type_type = NULL_TREE;
3965 141 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3966 64 : if (TREE_VALUE (a) != NULL_TREE)
3967 : {
3968 : /* const char *prefer_type[n]; */
3969 35 : t = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
3970 35 : prefer_type_type = build_pointer_type (t);
3971 35 : t = build_array_type_nelts (prefer_type_type, nnew);
3972 35 : prefer_type = create_tmp_var (t, "pref_type");
3973 35 : break;
3974 : }
3975 :
3976 : /* Initialize the arrays, generating temp vars and clobbers for
3977 : the interop objects. (The constructed array holding the
3978 : pointers to these objects shouldn't need clobbering as there's
3979 : no reason for GOMP_interop to modify its contents.) */
3980 127 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3981 : {
3982 : /* The allocated temporaries for the interop objects
3983 : have type omp_interop_t, which is an integer type that
3984 : can encode a pointer. */
3985 71 : tree objvar = create_tmp_var (pointer_sized_int_node, "interop");
3986 71 : buffer[i + j] = objvar;
3987 71 : TREE_ADDRESSABLE (objvar) = 1;
3988 : /* Generate a clobber for the temporary for when we're done
3989 : with it. */
3990 71 : tree c = build_clobber (pointer_sized_int_node,
3991 : CLOBBER_OBJECT_END);
3992 71 : c = build2 (MODIFY_EXPR, pointer_sized_int_node, objvar, c);
3993 71 : if (clobbers)
3994 15 : clobbers = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
3995 : c, clobbers);
3996 : else
3997 : clobbers = c;
3998 :
3999 : /* objs[offset] = &objvar; */
4000 71 : tree offset = build_int_cst (integer_type_node, j - ninterop);
4001 71 : tree init = build4 (ARRAY_REF, objtype, objs, offset,
4002 : NULL_TREE, NULL_TREE);
4003 71 : init = build2 (MODIFY_EXPR, objtype, init,
4004 : build_fold_addr_expr (objvar));
4005 71 : if (init_code)
4006 15 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4007 : init_code, init);
4008 : else
4009 : init_code = init;
4010 :
4011 : /* target_tgtsync[offset] = tgt;
4012 : (Don't blame me, I didn't design the encoding of this
4013 : info into the dispatch interop clause data structure,
4014 : but the runtime wants a bit mask.) */
4015 71 : tree tree_tgt = TREE_OPERAND (TREE_PURPOSE (a), 0);
4016 71 : int tgt = 0;
4017 71 : if (TREE_PURPOSE (tree_tgt) == boolean_true_node)
4018 42 : tgt |= GOMP_INTEROP_TARGET;
4019 71 : if (TREE_VALUE (tree_tgt) == boolean_true_node)
4020 36 : tgt |= GOMP_INTEROP_TARGETSYNC;
4021 71 : init = build4 (ARRAY_REF, integer_type_node,
4022 : target_tgtsync, offset, NULL_TREE, NULL_TREE);
4023 71 : init = build2 (MODIFY_EXPR, integer_type_node, init,
4024 71 : build_int_cst (integer_type_node, tgt));
4025 71 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4026 : init_code, init);
4027 :
4028 71 : if (prefer_type)
4029 : {
4030 45 : tree pref = TREE_VALUE (a);
4031 45 : if (pref == NULL_TREE)
4032 6 : pref = null_pointer_node;
4033 : else
4034 39 : pref = build_fold_addr_expr (pref);
4035 45 : init = build4 (ARRAY_REF, prefer_type_type, prefer_type,
4036 : offset, NULL_TREE, NULL_TREE);
4037 45 : init = build2 (MODIFY_EXPR, prefer_type_type, init,
4038 : pref);
4039 45 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4040 : init_code, init);
4041 : }
4042 : }
4043 :
4044 56 : objs = build_fold_addr_expr (objs);
4045 56 : target_tgtsync = build_fold_addr_expr (target_tgtsync);
4046 56 : prefer_type = prefer_type ? build_fold_addr_expr (prefer_type)
4047 : : null_pointer_node;
4048 56 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
4049 56 : tree create
4050 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4051 : nobjs, objs, target_tgtsync, prefer_type,
4052 : integer_zero_node, null_pointer_node,
4053 : integer_zero_node, null_pointer_node,
4054 : integer_zero_node, null_pointer_node);
4055 56 : if (init_code)
4056 56 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (create),
4057 : init_code, create);
4058 : else
4059 : init_code = create;
4060 :
4061 56 : cleanup
4062 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4063 : integer_zero_node, null_pointer_node,
4064 : null_pointer_node, null_pointer_node,
4065 : integer_zero_node, null_pointer_node,
4066 : nobjs, objs,
4067 : integer_zero_node, null_pointer_node);
4068 56 : if (clobbers)
4069 56 : cleanup = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
4070 : cleanup, clobbers);
4071 : }
4072 :
4073 654 : for (j = 0; j < nappend; j++)
4074 : {
4075 : /* Fortran permits by-reference or by-value for the dummy arg
4076 : and by-value, by-reference, ptr by-reference as actual
4077 : argument. Handle this. */
4078 409 : tree obj = buffer[i + j]; // interop object
4079 409 : tree a2 = TREE_VALUE (arg); // parameter type
4080 766 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4081 436 : && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (obj))))
4082 : {
4083 32 : tree t = TREE_TYPE (TREE_TYPE (obj));
4084 32 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (t)));
4085 32 : obj = fold_build1 (INDIRECT_REF, t, obj);
4086 : }
4087 750 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4088 420 : && INTEGRAL_TYPE_P (a2))
4089 : {
4090 43 : tree t = TREE_TYPE (TREE_TYPE (obj));
4091 43 : gcc_checking_assert (INTEGRAL_TYPE_P (t));
4092 43 : obj = fold_build1 (INDIRECT_REF, t, obj);
4093 : }
4094 497 : else if (INTEGRAL_TYPE_P (TREE_TYPE (obj))
4095 461 : && POINTER_TYPE_P (a2))
4096 : {
4097 18 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4098 18 : obj = build_fold_addr_expr (obj);
4099 : }
4100 348 : else if (!INTEGRAL_TYPE_P (a2)
4101 348 : || !INTEGRAL_TYPE_P (TREE_TYPE (obj)))
4102 : {
4103 36 : tree t = TREE_TYPE (obj);
4104 36 : gcc_checking_assert (POINTER_TYPE_P (t)
4105 : && POINTER_TYPE_P (a2)
4106 : && INTEGRAL_TYPE_P (TREE_TYPE (t))
4107 : && INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4108 : }
4109 409 : buffer[i + j] = obj;
4110 409 : arg = TREE_CHAIN (arg);
4111 : }
4112 245 : i += nappend;
4113 534 : for (j = nfirst_args; j < nargs; j++)
4114 289 : buffer[i++] = CALL_EXPR_ARG (expr, j);
4115 245 : nargs += nappend;
4116 245 : tree call = expr;
4117 490 : expr = build_call_array_loc (EXPR_LOCATION (expr), TREE_TYPE (call),
4118 245 : CALL_EXPR_FN (call), nargs, buffer);
4119 :
4120 : /* Copy all CALL_EXPR flags. */
4121 245 : CALL_EXPR_STATIC_CHAIN (expr) = CALL_EXPR_STATIC_CHAIN (call);
4122 245 : CALL_EXPR_TAILCALL (expr) = CALL_EXPR_TAILCALL (call);
4123 245 : CALL_EXPR_RETURN_SLOT_OPT (expr)
4124 245 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4125 245 : CALL_FROM_THUNK_P (expr) = CALL_FROM_THUNK_P (call);
4126 245 : SET_EXPR_LOCATION (expr, EXPR_LOCATION (call));
4127 245 : CALL_EXPR_VA_ARG_PACK (expr) = CALL_EXPR_VA_ARG_PACK (call);
4128 : }
4129 :
4130 : /* Nothing to do for adjust_args? */
4131 471 : if (!dispatch_adjust_args_list || !TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
4132 260 : goto add_cleanup;
4133 :
4134 : /* Handle adjust_args. */
4135 966 : for (int i = 0; i < nargs; i++)
4136 : {
4137 755 : tree *arg_p = &CALL_EXPR_ARG (expr, i);
4138 :
4139 : /* Nothing to do if arg is constant null pointer. */
4140 755 : if (integer_zerop (*arg_p))
4141 6 : continue;
4142 :
4143 : bool need_device_ptr = false;
4144 : bool need_device_addr = false;
4145 2247 : for (int need_addr = 0; need_addr <= 1; need_addr++)
4146 2301 : for (tree arg = (need_addr
4147 1498 : ? TREE_VALUE (dispatch_adjust_args_list)
4148 1498 : : TREE_PURPOSE (dispatch_adjust_args_list));
4149 2301 : arg != NULL; arg = TREE_CHAIN (arg))
4150 : {
4151 1152 : if (TREE_VALUE (arg)
4152 1152 : && TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST
4153 2304 : && wi::eq_p (i, wi::to_wide (TREE_VALUE (arg))))
4154 : {
4155 349 : if (need_addr)
4156 : need_device_addr = true;
4157 : else
4158 349 : need_device_ptr = true;
4159 : break;
4160 : }
4161 : }
4162 :
4163 749 : if (need_device_ptr || need_device_addr)
4164 : {
4165 740 : bool is_device_ptr = false;
4166 740 : bool has_device_addr = false;
4167 :
4168 740 : for (tree c = dispatch_clauses; c; c = TREE_CHAIN (c))
4169 : {
4170 454 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
4171 454 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
4172 : {
4173 164 : tree decl1 = DECL_NAME (OMP_CLAUSE_DECL (c));
4174 164 : tree decl2 = tree_strip_nop_conversions (*arg_p);
4175 164 : if (TREE_CODE (decl2) == ADDR_EXPR)
4176 19 : decl2 = TREE_OPERAND (decl2, 0);
4177 164 : if (VAR_P (decl2) || TREE_CODE (decl2) == PARM_DECL)
4178 : {
4179 140 : decl2 = DECL_NAME (decl2);
4180 140 : if (decl1 == decl2
4181 203 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
4182 : {
4183 58 : if (need_device_addr)
4184 0 : warning_at (OMP_CLAUSE_LOCATION (c),
4185 0 : OPT_Wopenmp,
4186 : "%<is_device_ptr%> for %qD does"
4187 : " not imply %<has_device_addr%> "
4188 : "required for %<need_device_addr%>",
4189 0 : OMP_CLAUSE_DECL (c));
4190 : is_device_ptr = true;
4191 : break;
4192 : }
4193 82 : else if (decl1 == decl2)
4194 : {
4195 5 : if (need_device_ptr)
4196 10 : warning_at (OMP_CLAUSE_LOCATION (c),
4197 5 : OPT_Wopenmp,
4198 : "%<has_device_addr%> for %qD does"
4199 : " not imply %<is_device_ptr%> "
4200 : "required for %<need_device_ptr%>",
4201 5 : OMP_CLAUSE_DECL (c));
4202 : has_device_addr = true;
4203 : break;
4204 : }
4205 : }
4206 : }
4207 : }
4208 :
4209 349 : if ((need_device_ptr && !is_device_ptr)
4210 58 : || (need_device_addr && !has_device_addr))
4211 : {
4212 291 : if (dispatch_device_num == NULL_TREE)
4213 : {
4214 : // device_num = omp_get_default_device ()
4215 105 : tree fn
4216 105 : = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
4217 105 : tree call = build_call_expr (fn, 0);
4218 105 : dispatch_device_num = create_tmp_var_raw (TREE_TYPE (call));
4219 105 : tree init
4220 105 : = build4 (TARGET_EXPR, TREE_TYPE (call),
4221 : dispatch_device_num, call, NULL_TREE, NULL_TREE);
4222 105 : if (init_code)
4223 0 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4224 : init_code, init);
4225 : else
4226 : init_code = init;
4227 : }
4228 :
4229 : // We want to emit the following statement:
4230 : // mapped_arg = omp_get_mapped_ptr (arg,
4231 : // device_num)
4232 : // but arg has to be the actual pointer, not a
4233 : // reference or a conversion expression.
4234 291 : tree actual_ptr
4235 291 : = ((TREE_CODE (*arg_p) == ADDR_EXPR)
4236 291 : ? TREE_OPERAND (*arg_p, 0)
4237 38 : : *arg_p);
4238 291 : if (TREE_CODE (actual_ptr) == NOP_EXPR
4239 291 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (actual_ptr, 0)))
4240 : == REFERENCE_TYPE))
4241 : {
4242 6 : actual_ptr = TREE_OPERAND (actual_ptr, 0);
4243 6 : actual_ptr = build1 (INDIRECT_REF,
4244 6 : TREE_TYPE (actual_ptr),
4245 : actual_ptr);
4246 : }
4247 291 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_MAPPED_PTR);
4248 291 : tree mapped_arg = build_call_expr_loc (loc, fn, 2, actual_ptr,
4249 : dispatch_device_num);
4250 :
4251 291 : if (TREE_CODE (*arg_p) == ADDR_EXPR
4252 291 : || (TREE_CODE (TREE_TYPE (actual_ptr)) == REFERENCE_TYPE))
4253 47 : mapped_arg = build_fold_addr_expr (mapped_arg);
4254 244 : else if (TREE_CODE (*arg_p) == NOP_EXPR)
4255 35 : mapped_arg = build1 (NOP_EXPR, TREE_TYPE (*arg_p),
4256 : mapped_arg);
4257 291 : *arg_p = mapped_arg;
4258 : }
4259 : }
4260 : }
4261 :
4262 471 : add_cleanup:
4263 471 : if (cleanup)
4264 : {
4265 56 : tree result = NULL_TREE;
4266 56 : if (want_value && pointerize)
4267 : {
4268 0 : tree tmp = create_tmp_var (build_pointer_type (TREE_TYPE (expr)),
4269 : "cleanuptmp");
4270 0 : result = build_simple_mem_ref (tmp);
4271 0 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp,
4272 : build_fold_addr_expr (expr));
4273 : }
4274 56 : else if (want_value)
4275 : {
4276 18 : tree tmp = create_tmp_var (TREE_TYPE (expr), "cleanuptmp");
4277 18 : result = tmp;
4278 18 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp, expr);
4279 : }
4280 56 : if (init_code)
4281 56 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4282 56 : expr = build2 (TRY_FINALLY_EXPR, void_type_node, expr, cleanup);
4283 :
4284 56 : if (result)
4285 18 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (result), expr, result);
4286 : }
4287 415 : else if (init_code)
4288 105 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4289 :
4290 : return expr;
4291 : }
4292 :
4293 : /* Helper function for gimplify_call_expr: handle "declare variant"
4294 : resolution and expansion of the CALL_EXPR EXPR. WANT_VALUE is true
4295 : if the result value of the call is needed; POINTERIZE is true if it
4296 : also needs to be pointerized. If OMP_DISPATCH_P is true, apply
4297 : associated transformations using DISPATCH_CLAUSES.
4298 : This function may return either the original call or some other
4299 : expression such as a conditional to select one of multiple calls.
4300 :
4301 : FIXME: this function is written to be independent of gimplifier internals
4302 : so that it could be moved to omp-general.cc and invoked from the
4303 : front ends instead, per PR115076. */
4304 :
4305 : static tree
4306 1355 : expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
4307 : bool omp_dispatch_p, tree dispatch_clauses)
4308 : {
4309 : /* If we've already processed this call, stop now. This can happen
4310 : if the variant call resolves to the original function, or to
4311 : a dynamic conditional that includes the default call to the original
4312 : function. */
4313 1355 : gcc_assert (omp_resolved_variant_calls != NULL);
4314 1355 : if (omp_resolved_variant_calls->contains (expr))
4315 131 : return expr;
4316 :
4317 1224 : tree fndecl = get_callee_fndecl (expr);
4318 1224 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (expr));
4319 1224 : location_t loc = EXPR_LOCATION (expr);
4320 1224 : tree construct_context = omp_get_construct_context ();
4321 1224 : vec<struct omp_variant> all_candidates
4322 1224 : = omp_declare_variant_candidates (fndecl, construct_context);
4323 1224 : gcc_assert (!all_candidates.is_empty ());
4324 1224 : vec<struct omp_variant> candidates
4325 1224 : = omp_get_dynamic_candidates (all_candidates, construct_context);
4326 :
4327 : /* If the variant call could be resolved now, build a nest of COND_EXPRs
4328 : if there are dynamic candidates, and/or a new CALL_EXPR for each
4329 : candidate call. */
4330 1224 : if (!candidates.is_empty ())
4331 : {
4332 1212 : int n = candidates.length ();
4333 1212 : tree tail = NULL_TREE;
4334 :
4335 2462 : for (int i = n - 1; i >= 0; i--)
4336 : {
4337 1250 : if (tail)
4338 38 : gcc_assert (candidates[i].dynamic_selector);
4339 : else
4340 1212 : gcc_assert (!candidates[i].dynamic_selector);
4341 1250 : if (candidates[i].alternative == fndecl)
4342 : {
4343 : /* We should only get the original function back as the
4344 : default. */
4345 284 : gcc_assert (!tail);
4346 284 : omp_resolved_variant_calls->add (expr);
4347 284 : tail = expr;
4348 : }
4349 : else
4350 : {
4351 : /* For the final static selector, we can re-use the old
4352 : CALL_EXPR and just replace the function, unless it may
4353 : need dispatch argument modification. Otherwise,
4354 : make a copy of it. */
4355 966 : tree thiscall = (tail || omp_dispatch_p
4356 966 : ? unshare_expr (expr) : expr);
4357 966 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype,
4358 966 : candidates[i].alternative);
4359 966 : if (omp_dispatch_p)
4360 471 : thiscall = modify_call_for_omp_dispatch (thiscall,
4361 : dispatch_clauses,
4362 : want_value,
4363 : pointerize);
4364 966 : if (!tail)
4365 : tail = thiscall;
4366 : else
4367 76 : tail = build3 (COND_EXPR, TREE_TYPE (expr),
4368 38 : omp_dynamic_cond (candidates[i].selector,
4369 : find_supercontext ()),
4370 : thiscall, tail);
4371 : }
4372 : }
4373 : return tail;
4374 : }
4375 :
4376 : /* If we couldn't resolve the variant call now, expand it into a loop using
4377 : a switch and OMP_NEXT_VARIANT for dispatch. The ompdevlow pass will
4378 : handle OMP_NEXT_VARIANT expansion. */
4379 : else
4380 : {
4381 : /* If we need a usable return value, we need a temporary
4382 : and an assignment in each alternative. This logic was borrowed
4383 : from gimplify_cond_expr. */
4384 12 : tree type = TREE_TYPE (expr);
4385 12 : tree tmp = NULL_TREE, result = NULL_TREE;
4386 :
4387 12 : if (want_value)
4388 : {
4389 12 : if (pointerize)
4390 : {
4391 0 : type = build_pointer_type (type);
4392 0 : tmp = create_tmp_var (type, "iftmp");
4393 0 : result = build_simple_mem_ref_loc (loc, tmp);
4394 : }
4395 : else
4396 : {
4397 12 : tmp = create_tmp_var (type, "iftmp");
4398 12 : result = tmp;
4399 : }
4400 : }
4401 :
4402 : /* Preprocess the all_candidates array so that the alternative field of
4403 : each element holds the actual function call expression and possible
4404 : assignment, instead of just the decl for the variant function. */
4405 60 : for (unsigned int i = 0; i < all_candidates.length (); i++)
4406 : {
4407 48 : tree decl = all_candidates[i].alternative;
4408 48 : tree thiscall;
4409 :
4410 : /* We need to turn the decl from the candidate into a function
4411 : call and possible assignment, and stuff that in
4412 : the directive seq of the gomp_variant. */
4413 48 : if (decl == fndecl)
4414 : {
4415 12 : thiscall = expr;
4416 12 : omp_resolved_variant_calls->add (expr);
4417 : }
4418 : else
4419 : {
4420 36 : thiscall = unshare_expr (expr);
4421 36 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype, decl);
4422 36 : if (omp_dispatch_p)
4423 0 : thiscall = modify_call_for_omp_dispatch (thiscall,
4424 : dispatch_clauses,
4425 : want_value,
4426 : pointerize);
4427 : }
4428 48 : if (pointerize)
4429 0 : thiscall = build_fold_addr_expr_loc (loc, thiscall);
4430 48 : if (want_value)
4431 48 : thiscall = build2 (INIT_EXPR, type, tmp, thiscall);
4432 48 : all_candidates[i].alternative = thiscall;
4433 : }
4434 :
4435 12 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
4436 12 : tree expansion = expand_late_variant_directive (all_candidates,
4437 : construct_context);
4438 12 : if (result)
4439 12 : expansion = build2 (COMPOUND_EXPR, TREE_TYPE (result),
4440 : expansion, result);
4441 : return expansion;
4442 : }
4443 : }
4444 :
4445 : /* Wrapper around expand_variant_call_expr to interface with gimplifier
4446 : state. EXPR and OMP_DISPATCH_P are as for expand_variant_call_expr,
4447 : FALLBACK is used to compute the WANT_VALUE and POINTERIZE arguments. */
4448 : static tree
4449 1355 : gimplify_variant_call_expr (tree expr, fallback_t fallback,
4450 : bool omp_dispatch_p)
4451 : {
4452 1355 : tree type = TREE_TYPE (expr);
4453 1355 : bool want_value = (fallback != fb_none && !VOID_TYPE_P (type));
4454 673 : bool pointerize = false;
4455 : /* If the result value must be an lvalue or the result type must
4456 : live in memory, then we have to pointerize it if we need a temporary. */
4457 673 : if (want_value
4458 673 : && ((!(fallback & fb_rvalue) && (fallback & fb_lvalue))
4459 673 : || TREE_ADDRESSABLE (type)))
4460 0 : pointerize = true;
4461 :
4462 1867 : return expand_variant_call_expr (expr, want_value, pointerize,
4463 : omp_dispatch_p,
4464 : (omp_dispatch_p
4465 512 : ? gimplify_omp_ctxp->clauses
4466 1355 : : NULL_TREE));
4467 : }
4468 :
4469 :
4470 : /* Helper function for gimplify_call_expr, called via walk_tree.
4471 : Find used user labels. */
4472 :
4473 : static tree
4474 766 : find_used_user_labels (tree *tp, int *, void *)
4475 : {
4476 766 : if (TREE_CODE (*tp) == LABEL_EXPR
4477 15 : && !DECL_ARTIFICIAL (LABEL_EXPR_LABEL (*tp))
4478 15 : && DECL_NAME (LABEL_EXPR_LABEL (*tp))
4479 781 : && TREE_USED (LABEL_EXPR_LABEL (*tp)))
4480 15 : return *tp;
4481 : return NULL_TREE;
4482 : }
4483 :
4484 :
4485 : /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
4486 : WANT_VALUE is true if the result of the call is desired. */
4487 :
4488 : static enum gimplify_status
4489 17554339 : gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
4490 : {
4491 17554339 : bool want_value = (fallback != fb_none);
4492 17554339 : tree fndecl, parms, p, fnptrtype;
4493 17554339 : enum gimplify_status ret;
4494 17554339 : int i, nargs;
4495 17554339 : gcall *call;
4496 17554339 : bool builtin_va_start_p = false, omp_dispatch_p = false;
4497 17554339 : location_t loc = EXPR_LOCATION (*expr_p);
4498 :
4499 17554339 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4500 :
4501 : /* For reliable diagnostics during inlining, it is necessary that
4502 : every call_expr be annotated with file and line. */
4503 17554339 : if (! EXPR_HAS_LOCATION (*expr_p))
4504 526642 : SET_EXPR_LOCATION (*expr_p, input_location);
4505 :
4506 : /* Gimplify internal functions created in the FEs. */
4507 17554339 : if (CALL_EXPR_FN (*expr_p) == NULL_TREE)
4508 : {
4509 605680 : enum internal_fn ifn = CALL_EXPR_IFN (*expr_p);
4510 605680 : if (ifn == IFN_GOMP_DISPATCH)
4511 : {
4512 884 : gcc_assert (flag_openmp
4513 : && gimplify_omp_ctxp
4514 : && gimplify_omp_ctxp->code == OMP_DISPATCH);
4515 884 : *expr_p = CALL_EXPR_ARG (*expr_p, 0);
4516 884 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4517 884 : if (! EXPR_HAS_LOCATION (*expr_p))
4518 94 : SET_EXPR_LOCATION (*expr_p, input_location);
4519 : omp_dispatch_p = true;
4520 : }
4521 : else
4522 : {
4523 604796 : if (want_value)
4524 : return GS_ALL_DONE;
4525 :
4526 21173 : nargs = call_expr_nargs (*expr_p);
4527 21173 : auto_vec<tree> vargs (nargs);
4528 :
4529 21173 : if (ifn == IFN_ASSUME)
4530 : {
4531 533 : if (simple_condition_p (CALL_EXPR_ARG (*expr_p, 0)))
4532 : {
4533 : /* If the [[assume (cond)]]; condition is simple
4534 : enough and can be evaluated unconditionally
4535 : without side-effects, expand it as
4536 : if (!cond) __builtin_unreachable (); */
4537 311 : tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
4538 311 : *expr_p
4539 622 : = build3 (COND_EXPR, void_type_node,
4540 311 : CALL_EXPR_ARG (*expr_p, 0), void_node,
4541 311 : build_call_expr_loc (EXPR_LOCATION (*expr_p),
4542 : fndecl, 0));
4543 311 : return GS_OK;
4544 : }
4545 : /* If not optimizing, ignore the assumptions unless there
4546 : are used user labels in it. */
4547 222 : if ((!optimize
4548 98 : && !walk_tree_without_duplicates (&CALL_EXPR_ARG (*expr_p,
4549 : 0),
4550 : find_used_user_labels,
4551 : NULL))
4552 237 : || seen_error ())
4553 : {
4554 94 : *expr_p = NULL_TREE;
4555 94 : return GS_ALL_DONE;
4556 : }
4557 : /* Temporarily, until gimple lowering, transform
4558 : .ASSUME (cond);
4559 : into:
4560 : [[assume (guard)]]
4561 : {
4562 : guard = cond;
4563 : }
4564 : such that gimple lowering can outline the condition into
4565 : a separate function easily. */
4566 128 : tree guard = create_tmp_var (boolean_type_node);
4567 128 : *expr_p = build2 (MODIFY_EXPR, void_type_node, guard,
4568 128 : gimple_boolify (CALL_EXPR_ARG (*expr_p, 0)));
4569 128 : *expr_p = build3 (BIND_EXPR, void_type_node, NULL, *expr_p, NULL);
4570 128 : push_gimplify_context ();
4571 128 : gimple_seq body = NULL;
4572 128 : gimple *g = gimplify_and_return_first (*expr_p, &body);
4573 128 : pop_gimplify_context (g);
4574 128 : g = gimple_build_assume (guard, body);
4575 128 : gimple_set_location (g, loc);
4576 128 : gimplify_seq_add_stmt (pre_p, g);
4577 128 : *expr_p = NULL_TREE;
4578 128 : return GS_ALL_DONE;
4579 : }
4580 20640 : else if (ifn == IFN_UBSAN_BOUNDS
4581 20640 : && nargs == 3
4582 20640 : && integer_onep (CALL_EXPR_ARG (*expr_p, 0)))
4583 : {
4584 : /* If first argument is one, add TYPE_MAX_VALUE (TYPE_DOMAIN (t))
4585 : to 3rd argument and change first argument to 0. This is
4586 : done by ubsan_instrument_bounds so that we can use the
4587 : max value from gimplify_type_sizes here instead of original
4588 : expression for VLAs. */
4589 406 : tree type = TREE_TYPE (CALL_EXPR_ARG (*expr_p, 0));
4590 406 : CALL_EXPR_ARG (*expr_p, 0) = build_int_cst (type, 0);
4591 406 : gcc_assert (TREE_CODE (type) == POINTER_TYPE);
4592 406 : type = TREE_TYPE (type);
4593 406 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4594 406 : tree maxv = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4595 406 : gcc_assert (maxv);
4596 406 : tree arg3 = CALL_EXPR_ARG (*expr_p, 2);
4597 406 : CALL_EXPR_ARG (*expr_p, 2)
4598 812 : = fold_build2 (PLUS_EXPR, TREE_TYPE (arg3), maxv, arg3);
4599 : }
4600 :
4601 46429 : for (i = 0; i < nargs; i++)
4602 : {
4603 25789 : gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
4604 25789 : EXPR_LOCATION (*expr_p));
4605 25789 : vargs.quick_push (CALL_EXPR_ARG (*expr_p, i));
4606 : }
4607 :
4608 20640 : gcall *call = gimple_build_call_internal_vec (ifn, vargs);
4609 20640 : gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p));
4610 20640 : gimplify_seq_add_stmt (pre_p, call);
4611 20640 : return GS_ALL_DONE;
4612 21173 : }
4613 : }
4614 :
4615 : /* This may be a call to a builtin function.
4616 :
4617 : Builtin function calls may be transformed into different
4618 : (and more efficient) builtin function calls under certain
4619 : circumstances. Unfortunately, gimplification can muck things
4620 : up enough that the builtin expanders are not aware that certain
4621 : transformations are still valid.
4622 :
4623 : So we attempt transformation/gimplification of the call before
4624 : we gimplify the CALL_EXPR. At this time we do not manage to
4625 : transform all calls in the same manner as the expanders do, but
4626 : we do transform most of them. */
4627 16949543 : fndecl = get_callee_fndecl (*expr_p);
4628 16949543 : if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
4629 3986749 : switch (DECL_FUNCTION_CODE (fndecl))
4630 : {
4631 94654 : CASE_BUILT_IN_ALLOCA:
4632 : /* If the call has been built for a variable-sized object, then we
4633 : want to restore the stack level when the enclosing BIND_EXPR is
4634 : exited to reclaim the allocated space; otherwise, we precisely
4635 : need to do the opposite and preserve the latest stack level. */
4636 94654 : if (CALL_ALLOCA_FOR_VAR_P (*expr_p))
4637 9029 : gimplify_ctxp->save_stack = true;
4638 : else
4639 85625 : gimplify_ctxp->keep_stack = true;
4640 : break;
4641 :
4642 20897 : case BUILT_IN_VA_START:
4643 20897 : {
4644 20897 : builtin_va_start_p = true;
4645 20897 : if (call_expr_nargs (*expr_p) < 2)
4646 : {
4647 1 : error ("too few arguments to function %<va_start%>");
4648 1 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4649 1 : return GS_OK;
4650 : }
4651 :
4652 20896 : if (fold_builtin_next_arg (*expr_p, true))
4653 : {
4654 8 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4655 8 : return GS_OK;
4656 : }
4657 : break;
4658 : }
4659 :
4660 30 : case BUILT_IN_EH_RETURN:
4661 30 : cfun->calls_eh_return = true;
4662 30 : break;
4663 :
4664 1036 : case BUILT_IN_CLEAR_PADDING:
4665 1036 : if (call_expr_nargs (*expr_p) == 1)
4666 : {
4667 : /* Remember the original type of the argument in an internal
4668 : dummy second argument, as in GIMPLE pointer conversions are
4669 : useless. Also mark this call as not for automatic
4670 : initialization in the internal dummy third argument. */
4671 518 : p = CALL_EXPR_ARG (*expr_p, 0);
4672 518 : *expr_p
4673 518 : = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
4674 518 : build_zero_cst (TREE_TYPE (p)));
4675 518 : return GS_OK;
4676 : }
4677 : break;
4678 :
4679 : default:
4680 : ;
4681 : }
4682 16949016 : if (fndecl && fndecl_built_in_p (fndecl))
4683 : {
4684 4226995 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4685 4226995 : if (new_tree && new_tree != *expr_p)
4686 : {
4687 : /* There was a transformation of this call which computes the
4688 : same value, but in a more efficient way. Return and try
4689 : again. */
4690 773 : *expr_p = new_tree;
4691 773 : return GS_OK;
4692 : }
4693 : }
4694 :
4695 : /* Remember the original function pointer type. */
4696 16948243 : fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
4697 :
4698 : /* Handle "declare variant" resolution and arglist processing. */
4699 16948243 : if (flag_openmp
4700 391398 : && fndecl
4701 390717 : && cfun
4702 390717 : && (cfun->curr_properties & PROP_gimple_any) == 0
4703 251530 : && !omp_has_novariants ()
4704 17199661 : && lookup_attribute ("omp declare variant base",
4705 251418 : DECL_ATTRIBUTES (fndecl)))
4706 : {
4707 1355 : tree orig = *expr_p;
4708 1355 : *expr_p = gimplify_variant_call_expr (*expr_p, fallback,
4709 : omp_dispatch_p);
4710 :
4711 : /* This may resolve to the same call, or the call expr with just
4712 : the function replaced, in which case we should just continue to
4713 : gimplify it normally. Otherwise, if we get something else back,
4714 : stop here and re-gimplify the whole replacement expr. */
4715 1355 : if (*expr_p != orig)
4716 : return GS_OK;
4717 : }
4718 :
4719 : /* There is a sequence point before the call, so any side effects in
4720 : the calling expression must occur before the actual call. Force
4721 : gimplify_expr to use an internal post queue. */
4722 16947754 : ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
4723 : is_gimple_call_addr, fb_rvalue);
4724 :
4725 16947754 : if (ret == GS_ERROR)
4726 : return GS_ERROR;
4727 :
4728 16947752 : nargs = call_expr_nargs (*expr_p);
4729 :
4730 : /* Get argument types for verification. */
4731 16947752 : fndecl = get_callee_fndecl (*expr_p);
4732 16947752 : parms = NULL_TREE;
4733 16947752 : if (fndecl)
4734 16723084 : parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
4735 : else
4736 224668 : parms = TYPE_ARG_TYPES (TREE_TYPE (fnptrtype));
4737 :
4738 33670836 : if (fndecl && DECL_ARGUMENTS (fndecl))
4739 : p = DECL_ARGUMENTS (fndecl);
4740 7408637 : else if (parms)
4741 : p = parms;
4742 : else
4743 : p = NULL_TREE;
4744 45108722 : for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
4745 : ;
4746 :
4747 : /* If the last argument is __builtin_va_arg_pack () and it is not
4748 : passed as a named argument, decrease the number of CALL_EXPR
4749 : arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */
4750 16947752 : if (!p
4751 16947752 : && i < nargs
4752 16947752 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR)
4753 : {
4754 5960 : tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1);
4755 5960 : tree last_arg_fndecl = get_callee_fndecl (last_arg);
4756 :
4757 5960 : if (last_arg_fndecl
4758 5960 : && fndecl_built_in_p (last_arg_fndecl, BUILT_IN_VA_ARG_PACK))
4759 : {
4760 132 : tree call = *expr_p;
4761 :
4762 132 : --nargs;
4763 264 : *expr_p = build_call_array_loc (loc, TREE_TYPE (call),
4764 132 : CALL_EXPR_FN (call),
4765 132 : nargs, CALL_EXPR_ARGP (call));
4766 :
4767 : /* Copy all CALL_EXPR flags, location and block, except
4768 : CALL_EXPR_VA_ARG_PACK flag. */
4769 132 : CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call);
4770 132 : CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call);
4771 132 : CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
4772 132 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4773 132 : CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
4774 132 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
4775 :
4776 : /* Set CALL_EXPR_VA_ARG_PACK. */
4777 132 : CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
4778 : }
4779 : }
4780 :
4781 : /* If the call returns twice then after building the CFG the call
4782 : argument computations will no longer dominate the call because
4783 : we add an abnormal incoming edge to the call. So do not use SSA
4784 : vars there. */
4785 16947752 : bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE;
4786 :
4787 :
4788 : /* Gimplify the function arguments. */
4789 16947752 : if (nargs > 0)
4790 : {
4791 14834300 : for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
4792 44468486 : PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
4793 29634186 : PUSH_ARGS_REVERSED ? i-- : i++)
4794 : {
4795 29634186 : enum gimplify_status t;
4796 :
4797 : /* Avoid gimplifying the second argument to va_start, which needs to
4798 : be the plain PARM_DECL. */
4799 29634186 : if ((i != 1) || !builtin_va_start_p)
4800 : {
4801 29613298 : tree *arg_p = &CALL_EXPR_ARG (*expr_p, i);
4802 :
4803 29613298 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4804 6687 : gimplify_omp_ctxp->in_call_args = true;
4805 29613298 : t = gimplify_arg (arg_p, pre_p, EXPR_LOCATION (*expr_p),
4806 : !returns_twice);
4807 29613298 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4808 6687 : gimplify_omp_ctxp->in_call_args = false;
4809 :
4810 29613298 : if (t == GS_ERROR)
4811 29634186 : ret = GS_ERROR;
4812 : }
4813 : }
4814 : }
4815 :
4816 : /* Gimplify the static chain. */
4817 16947752 : if (CALL_EXPR_STATIC_CHAIN (*expr_p))
4818 : {
4819 28853 : if (fndecl && !DECL_STATIC_CHAIN (fndecl))
4820 3 : CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL;
4821 : else
4822 : {
4823 28174 : enum gimplify_status t;
4824 28174 : t = gimplify_arg (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p,
4825 28174 : EXPR_LOCATION (*expr_p), ! returns_twice);
4826 28174 : if (t == GS_ERROR)
4827 16947752 : ret = GS_ERROR;
4828 : }
4829 : }
4830 :
4831 : /* Verify the function result. */
4832 16947752 : if (want_value && fndecl
4833 16947752 : && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
4834 : {
4835 0 : error_at (loc, "using result of function returning %<void%>");
4836 0 : ret = GS_ERROR;
4837 : }
4838 :
4839 : /* Try this again in case gimplification exposed something. */
4840 16947752 : if (ret != GS_ERROR)
4841 : {
4842 16947602 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4843 :
4844 16947602 : if (new_tree && new_tree != *expr_p)
4845 : {
4846 : /* There was a transformation of this call which computes the
4847 : same value, but in a more efficient way. Return and try
4848 : again. */
4849 11459 : *expr_p = new_tree;
4850 11459 : return GS_OK;
4851 : }
4852 : }
4853 : else
4854 : {
4855 150 : *expr_p = error_mark_node;
4856 150 : return GS_ERROR;
4857 : }
4858 :
4859 : /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
4860 : decl. This allows us to eliminate redundant or useless
4861 : calls to "const" functions. */
4862 16936143 : if (TREE_CODE (*expr_p) == CALL_EXPR)
4863 : {
4864 16936143 : int flags = call_expr_flags (*expr_p);
4865 16936143 : if (flags & (ECF_CONST | ECF_PURE)
4866 : /* An infinite loop is considered a side effect. */
4867 2459888 : && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
4868 2049205 : TREE_SIDE_EFFECTS (*expr_p) = 0;
4869 : }
4870 :
4871 : /* If the value is not needed by the caller, emit a new GIMPLE_CALL
4872 : and clear *EXPR_P. Otherwise, leave *EXPR_P in its gimplified
4873 : form and delegate the creation of a GIMPLE_CALL to
4874 : gimplify_modify_expr. This is always possible because when
4875 : WANT_VALUE is true, the caller wants the result of this call into
4876 : a temporary, which means that we will emit an INIT_EXPR in
4877 : internal_get_tmp_var which will then be handled by
4878 : gimplify_modify_expr. */
4879 16936143 : if (!want_value)
4880 : {
4881 : /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
4882 : have to do is replicate it as a GIMPLE_CALL tuple. */
4883 6452016 : gimple_stmt_iterator gsi;
4884 6452016 : call = gimple_build_call_from_tree (*expr_p, fnptrtype);
4885 6452016 : notice_special_calls (call);
4886 6452016 : gimplify_seq_add_stmt (pre_p, call);
4887 6452016 : gsi = gsi_last (*pre_p);
4888 6452016 : maybe_fold_stmt (&gsi);
4889 6452016 : *expr_p = NULL_TREE;
4890 : }
4891 : else
4892 : /* Remember the original function type. */
4893 10484127 : CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
4894 10484127 : CALL_EXPR_FN (*expr_p));
4895 :
4896 : return ret;
4897 : }
4898 :
4899 : /* Handle shortcut semantics in the predicate operand of a COND_EXPR by
4900 : rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs.
4901 :
4902 : TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the
4903 : condition is true or false, respectively. If null, we should generate
4904 : our own to skip over the evaluation of this specific expression.
4905 :
4906 : LOCUS is the source location of the COND_EXPR.
4907 :
4908 : The condition_uid is a discriminator tag for condition coverage used to map
4909 : conditions to its corresponding full Boolean function.
4910 :
4911 : This function is the tree equivalent of do_jump.
4912 :
4913 : shortcut_cond_r should only be called by shortcut_cond_expr. */
4914 :
4915 : static tree
4916 1333094 : shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
4917 : location_t locus, unsigned condition_uid)
4918 : {
4919 1333094 : tree local_label = NULL_TREE;
4920 1333094 : tree t, expr = NULL;
4921 :
4922 : /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
4923 : retain the shortcut semantics. Just insert the gotos here;
4924 : shortcut_cond_expr will append the real blocks later. */
4925 1333094 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
4926 : {
4927 125615 : location_t new_locus;
4928 :
4929 : /* Turn if (a && b) into
4930 :
4931 : if (a); else goto no;
4932 : if (b) goto yes; else goto no;
4933 : (no:) */
4934 :
4935 125615 : if (false_label_p == NULL)
4936 3999 : false_label_p = &local_label;
4937 :
4938 : /* Keep the original source location on the first 'if'. */
4939 125615 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus,
4940 : condition_uid);
4941 125615 : append_to_statement_list (t, &expr);
4942 :
4943 : /* Set the source location of the && on the second 'if'. */
4944 125615 : new_locus = rexpr_location (pred, locus);
4945 125615 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4946 : new_locus, condition_uid);
4947 125615 : append_to_statement_list (t, &expr);
4948 : }
4949 1207479 : else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
4950 : {
4951 384942 : location_t new_locus;
4952 :
4953 : /* Turn if (a || b) into
4954 :
4955 : if (a) goto yes;
4956 : if (b) goto yes; else goto no;
4957 : (yes:) */
4958 :
4959 384942 : if (true_label_p == NULL)
4960 230716 : true_label_p = &local_label;
4961 :
4962 : /* Keep the original source location on the first 'if'. */
4963 384942 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus,
4964 : condition_uid);
4965 384942 : append_to_statement_list (t, &expr);
4966 :
4967 : /* Set the source location of the || on the second 'if'. */
4968 384942 : new_locus = rexpr_location (pred, locus);
4969 384942 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4970 : new_locus, condition_uid);
4971 384942 : append_to_statement_list (t, &expr);
4972 : }
4973 822537 : else if (TREE_CODE (pred) == COND_EXPR
4974 852 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
4975 823389 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
4976 : {
4977 846 : location_t new_locus;
4978 :
4979 : /* As long as we're messing with gotos, turn if (a ? b : c) into
4980 : if (a)
4981 : if (b) goto yes; else goto no;
4982 : else
4983 : if (c) goto yes; else goto no;
4984 :
4985 : Don't do this if one of the arms has void type, which can happen
4986 : in C++ when the arm is throw. */
4987 :
4988 : /* Keep the original source location on the first 'if'. Set the source
4989 : location of the ? on the second 'if'. */
4990 846 : new_locus = rexpr_location (pred, locus);
4991 1692 : expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
4992 846 : shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
4993 : false_label_p, locus, condition_uid),
4994 846 : shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
4995 : false_label_p, new_locus,
4996 : condition_uid));
4997 846 : tree_associate_condition_with_expr (expr, condition_uid);
4998 : }
4999 : else
5000 : {
5001 821691 : expr = build3 (COND_EXPR, void_type_node, pred,
5002 : build_and_jump (true_label_p),
5003 : build_and_jump (false_label_p));
5004 821691 : SET_EXPR_LOCATION (expr, locus);
5005 821691 : tree_associate_condition_with_expr (expr, condition_uid);
5006 : }
5007 :
5008 1333094 : if (local_label)
5009 : {
5010 234715 : t = build1 (LABEL_EXPR, void_type_node, local_label);
5011 234715 : append_to_statement_list (t, &expr);
5012 : }
5013 :
5014 1333094 : return expr;
5015 : }
5016 :
5017 : /* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip
5018 : any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
5019 : statement, if it is the last one. Otherwise, return NULL. */
5020 :
5021 : static tree
5022 11725246 : find_goto (tree expr)
5023 : {
5024 12056315 : if (!expr)
5025 : return NULL_TREE;
5026 :
5027 10091939 : if (TREE_CODE (expr) == GOTO_EXPR)
5028 : return expr;
5029 :
5030 8054264 : if (TREE_CODE (expr) != STATEMENT_LIST)
5031 : return NULL_TREE;
5032 :
5033 1051456 : tree_stmt_iterator i = tsi_start (expr);
5034 :
5035 1414009 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
5036 362553 : tsi_next (&i);
5037 :
5038 1051456 : if (!tsi_one_before_end_p (i))
5039 : return NULL_TREE;
5040 :
5041 331069 : return find_goto (tsi_stmt (i));
5042 : }
5043 :
5044 : /* Same as find_goto, except that it returns NULL if the destination
5045 : is not a LABEL_DECL. */
5046 :
5047 : static inline tree
5048 11725246 : find_goto_label (tree expr)
5049 : {
5050 11725246 : tree dest = find_goto (expr);
5051 13762921 : if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
5052 2037564 : return dest;
5053 : return NULL_TREE;
5054 : }
5055 :
5056 :
5057 : /* Given a multi-term condition (ANDIF, ORIF), walk the predicate PRED and tag
5058 : every basic condition with CONDITION_UID. Two basic conditions share the
5059 : CONDITION_UID discriminator when they belong to the same predicate, which is
5060 : used by the condition coverage. Doing this as an explicit step makes for a
5061 : simpler implementation than weaving it into the splitting code as the
5062 : splitting code eventually calls the entry point gimplfiy_expr which makes
5063 : bookkeeping complicated. */
5064 : static void
5065 576366 : tag_shortcut_cond (tree pred, unsigned condition_uid)
5066 : {
5067 615667 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR
5068 615667 : || TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5069 : {
5070 565194 : tree fst = TREE_OPERAND (pred, 0);
5071 565194 : tree lst = TREE_OPERAND (pred, 1);
5072 :
5073 565194 : if (TREE_CODE (fst) == TRUTH_ANDIF_EXPR
5074 565194 : || TREE_CODE (fst) == TRUTH_ORIF_EXPR)
5075 168793 : tag_shortcut_cond (fst, condition_uid);
5076 396401 : else if (TREE_CODE (fst) == COND_EXPR)
5077 244 : tree_associate_condition_with_expr (fst, condition_uid);
5078 :
5079 565194 : if (TREE_CODE (lst) == TRUTH_ANDIF_EXPR
5080 565194 : || TREE_CODE (lst) == TRUTH_ORIF_EXPR)
5081 : tag_shortcut_cond (lst, condition_uid);
5082 525893 : else if (TREE_CODE (lst) == COND_EXPR)
5083 445 : tree_associate_condition_with_expr (lst, condition_uid);
5084 : }
5085 576366 : }
5086 :
5087 : /* Given a conditional expression EXPR with short-circuit boolean
5088 : predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
5089 : predicate apart into the equivalent sequence of conditionals. CONDITION_UID
5090 : is a the tag/discriminator for this EXPR - all basic conditions in the
5091 : expression will be given the same CONDITION_UID. */
5092 : static tree
5093 407573 : shortcut_cond_expr (tree expr, unsigned condition_uid)
5094 : {
5095 407573 : tree pred = TREE_OPERAND (expr, 0);
5096 407573 : tree then_ = TREE_OPERAND (expr, 1);
5097 407573 : tree else_ = TREE_OPERAND (expr, 2);
5098 407573 : tree true_label, false_label, end_label, t;
5099 407573 : tree *true_label_p;
5100 407573 : tree *false_label_p;
5101 407573 : bool emit_end, emit_false, jump_over_else;
5102 407573 : bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
5103 407573 : bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
5104 :
5105 407573 : tag_shortcut_cond (pred, condition_uid);
5106 :
5107 : /* First do simple transformations. */
5108 407573 : if (!else_se)
5109 : {
5110 : /* If there is no 'else', turn
5111 : if (a && b) then c
5112 : into
5113 : if (a) if (b) then c. */
5114 293137 : while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
5115 : {
5116 : /* Keep the original source location on the first 'if'. */
5117 51388 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5118 51388 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5119 : /* Set the source location of the && on the second 'if'. */
5120 51388 : if (rexpr_has_location (pred))
5121 50364 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5122 51388 : then_ = shortcut_cond_expr (expr, condition_uid);
5123 51388 : then_se = then_ && TREE_SIDE_EFFECTS (then_);
5124 51388 : pred = TREE_OPERAND (pred, 0);
5125 51388 : expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
5126 51388 : SET_EXPR_LOCATION (expr, locus);
5127 : }
5128 : }
5129 :
5130 407573 : if (!then_se)
5131 : {
5132 : /* If there is no 'then', turn
5133 : if (a || b); else d
5134 : into
5135 : if (a); else if (b); else d. */
5136 25589 : while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5137 : {
5138 : /* Keep the original source location on the first 'if'. */
5139 797 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5140 797 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5141 : /* Set the source location of the || on the second 'if'. */
5142 797 : if (rexpr_has_location (pred))
5143 796 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5144 797 : else_ = shortcut_cond_expr (expr, condition_uid);
5145 797 : else_se = else_ && TREE_SIDE_EFFECTS (else_);
5146 797 : pred = TREE_OPERAND (pred, 0);
5147 797 : expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
5148 797 : SET_EXPR_LOCATION (expr, locus);
5149 : }
5150 : }
5151 :
5152 : /* The expr tree should also have the expression id set. */
5153 407573 : tree_associate_condition_with_expr (expr, condition_uid);
5154 :
5155 : /* If we're done, great. */
5156 407573 : if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR
5157 407573 : && TREE_CODE (pred) != TRUTH_ORIF_EXPR)
5158 97285 : return expr;
5159 :
5160 : /* Otherwise we need to mess with gotos. Change
5161 : if (a) c; else d;
5162 : to
5163 : if (a); else goto no;
5164 : c; goto end;
5165 : no: d; end:
5166 : and recursively gimplify the condition. */
5167 :
5168 310288 : true_label = false_label = end_label = NULL_TREE;
5169 :
5170 : /* If our arms just jump somewhere, hijack those labels so we don't
5171 : generate jumps to jumps. */
5172 :
5173 310288 : if (tree then_goto = find_goto_label (then_))
5174 : {
5175 4630 : true_label = GOTO_DESTINATION (then_goto);
5176 4630 : then_ = NULL;
5177 4630 : then_se = false;
5178 : }
5179 :
5180 310288 : if (tree else_goto = find_goto_label (else_))
5181 : {
5182 4223 : false_label = GOTO_DESTINATION (else_goto);
5183 4223 : else_ = NULL;
5184 4223 : else_se = false;
5185 : }
5186 :
5187 : /* If we aren't hijacking a label for the 'then' branch, it falls through. */
5188 310288 : if (true_label)
5189 : true_label_p = &true_label;
5190 : else
5191 305658 : true_label_p = NULL;
5192 :
5193 : /* The 'else' branch also needs a label if it contains interesting code. */
5194 310288 : if (false_label || else_se)
5195 : false_label_p = &false_label;
5196 : else
5197 : false_label_p = NULL;
5198 :
5199 : /* If there was nothing else in our arms, just forward the label(s). */
5200 149658 : if (!then_se && !else_se)
5201 8590 : return shortcut_cond_r (pred, true_label_p, false_label_p,
5202 12885 : EXPR_LOC_OR_LOC (expr, input_location), condition_uid);
5203 :
5204 : /* If our last subexpression already has a terminal label, reuse it. */
5205 305993 : if (else_se)
5206 160630 : t = expr_last (else_);
5207 145363 : else if (then_se)
5208 145363 : t = expr_last (then_);
5209 : else
5210 : t = NULL;
5211 305993 : if (t && TREE_CODE (t) == LABEL_EXPR)
5212 1013 : end_label = LABEL_EXPR_LABEL (t);
5213 :
5214 : /* If we don't care about jumping to the 'else' branch, jump to the end
5215 : if the condition is false. */
5216 305993 : if (!false_label_p)
5217 145121 : false_label_p = &end_label;
5218 :
5219 : /* We only want to emit these labels if we aren't hijacking them. */
5220 305993 : emit_end = (end_label == NULL_TREE);
5221 305993 : emit_false = (false_label == NULL_TREE);
5222 :
5223 : /* We only emit the jump over the else clause if we have to--if the
5224 : then clause may fall through. Otherwise we can wind up with a
5225 : useless jump and a useless label at the end of gimplified code,
5226 : which will cause us to think that this conditional as a whole
5227 : falls through even if it doesn't. If we then inline a function
5228 : which ends with such a condition, that can cause us to issue an
5229 : inappropriate warning about control reaching the end of a
5230 : non-void function. */
5231 305993 : jump_over_else = block_may_fallthru (then_);
5232 :
5233 611355 : pred = shortcut_cond_r (pred, true_label_p, false_label_p,
5234 611355 : EXPR_LOC_OR_LOC (expr, input_location),
5235 : condition_uid);
5236 :
5237 305993 : expr = NULL;
5238 305993 : append_to_statement_list (pred, &expr);
5239 :
5240 305993 : append_to_statement_list (then_, &expr);
5241 305993 : if (else_se)
5242 : {
5243 160630 : if (jump_over_else)
5244 : {
5245 158101 : tree last = expr_last (expr);
5246 158101 : t = build_and_jump (&end_label);
5247 158101 : if (rexpr_has_location (last))
5248 37938 : SET_EXPR_LOCATION (t, rexpr_location (last));
5249 158101 : append_to_statement_list (t, &expr);
5250 : }
5251 160630 : if (emit_false)
5252 : {
5253 160630 : t = build1 (LABEL_EXPR, void_type_node, false_label);
5254 160630 : append_to_statement_list (t, &expr);
5255 : }
5256 160630 : append_to_statement_list (else_, &expr);
5257 : }
5258 305993 : if (emit_end && end_label)
5259 : {
5260 302214 : t = build1 (LABEL_EXPR, void_type_node, end_label);
5261 302214 : append_to_statement_list (t, &expr);
5262 : }
5263 :
5264 305993 : return expr;
5265 : }
5266 :
5267 : /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */
5268 :
5269 : tree
5270 17071426 : gimple_boolify (tree expr)
5271 : {
5272 17071426 : tree type = TREE_TYPE (expr);
5273 17071426 : location_t loc = EXPR_LOCATION (expr);
5274 :
5275 17071426 : if (TREE_CODE (expr) == NE_EXPR
5276 5800563 : && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
5277 18029446 : && integer_zerop (TREE_OPERAND (expr, 1)))
5278 : {
5279 498466 : tree call = TREE_OPERAND (expr, 0);
5280 498466 : tree fn = get_callee_fndecl (call);
5281 :
5282 : /* For __builtin_expect ((long) (x), y) recurse into x as well
5283 : if x is truth_value_p. */
5284 498466 : if (fn
5285 497483 : && fndecl_built_in_p (fn, BUILT_IN_EXPECT)
5286 638440 : && call_expr_nargs (call) == 2)
5287 : {
5288 139974 : tree arg = CALL_EXPR_ARG (call, 0);
5289 139974 : if (arg)
5290 : {
5291 139974 : if (TREE_CODE (arg) == NOP_EXPR
5292 139974 : && TREE_TYPE (arg) == TREE_TYPE (call))
5293 66019 : arg = TREE_OPERAND (arg, 0);
5294 139974 : if (truth_value_p (TREE_CODE (arg)))
5295 : {
5296 116431 : arg = gimple_boolify (arg);
5297 116431 : CALL_EXPR_ARG (call, 0)
5298 232862 : = fold_convert_loc (loc, TREE_TYPE (call), arg);
5299 : }
5300 : }
5301 : }
5302 : }
5303 :
5304 17071426 : switch (TREE_CODE (expr))
5305 : {
5306 1400419 : case TRUTH_AND_EXPR:
5307 1400419 : case TRUTH_OR_EXPR:
5308 1400419 : case TRUTH_XOR_EXPR:
5309 1400419 : case TRUTH_ANDIF_EXPR:
5310 1400419 : case TRUTH_ORIF_EXPR:
5311 : /* Also boolify the arguments of truth exprs. */
5312 1400419 : TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
5313 : /* FALLTHRU */
5314 :
5315 1834593 : case TRUTH_NOT_EXPR:
5316 1834593 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5317 :
5318 : /* These expressions always produce boolean results. */
5319 1834593 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5320 309200 : TREE_TYPE (expr) = boolean_type_node;
5321 : return expr;
5322 :
5323 5500 : case ANNOTATE_EXPR:
5324 5500 : switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)))
5325 : {
5326 5500 : case annot_expr_ivdep_kind:
5327 5500 : case annot_expr_unroll_kind:
5328 5500 : case annot_expr_no_vector_kind:
5329 5500 : case annot_expr_vector_kind:
5330 5500 : case annot_expr_parallel_kind:
5331 5500 : case annot_expr_maybe_infinite_kind:
5332 5500 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5333 5500 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5334 3399 : TREE_TYPE (expr) = boolean_type_node;
5335 : return expr;
5336 0 : default:
5337 0 : gcc_unreachable ();
5338 : }
5339 :
5340 15231333 : default:
5341 15231333 : if (COMPARISON_CLASS_P (expr))
5342 : {
5343 : /* These expressions always produce boolean results. */
5344 13324108 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5345 1607011 : TREE_TYPE (expr) = boolean_type_node;
5346 : return expr;
5347 : }
5348 : /* Other expressions that get here must have boolean values, but
5349 : might need to be converted to the appropriate mode. */
5350 1907225 : if (TREE_CODE (type) == BOOLEAN_TYPE)
5351 : return expr;
5352 204635 : return fold_convert_loc (loc, boolean_type_node, expr);
5353 : }
5354 : }
5355 :
5356 : /* Given a conditional expression *EXPR_P without side effects, gimplify
5357 : its operands. New statements are inserted to PRE_P. */
5358 :
5359 : static enum gimplify_status
5360 45819 : gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
5361 : {
5362 45819 : tree expr = *expr_p, cond;
5363 45819 : enum gimplify_status ret, tret;
5364 45819 : enum tree_code code;
5365 :
5366 45819 : cond = gimple_boolify (COND_EXPR_COND (expr));
5367 :
5368 : /* We need to handle && and || specially, as their gimplification
5369 : creates pure cond_expr, thus leading to an infinite cycle otherwise. */
5370 45819 : code = TREE_CODE (cond);
5371 45819 : if (code == TRUTH_ANDIF_EXPR)
5372 39 : TREE_SET_CODE (cond, TRUTH_AND_EXPR);
5373 45780 : else if (code == TRUTH_ORIF_EXPR)
5374 4607 : TREE_SET_CODE (cond, TRUTH_OR_EXPR);
5375 45819 : ret = gimplify_expr (&cond, pre_p, NULL, is_gimple_val, fb_rvalue);
5376 45819 : COND_EXPR_COND (*expr_p) = cond;
5377 :
5378 45819 : tret = gimplify_expr (&COND_EXPR_THEN (expr), pre_p, NULL,
5379 : is_gimple_val, fb_rvalue);
5380 45819 : ret = MIN (ret, tret);
5381 45819 : tret = gimplify_expr (&COND_EXPR_ELSE (expr), pre_p, NULL,
5382 : is_gimple_val, fb_rvalue);
5383 :
5384 45819 : return MIN (ret, tret);
5385 : }
5386 :
5387 : /* Return true if evaluating EXPR could trap.
5388 : EXPR is GENERIC, while tree_could_trap_p can be called
5389 : only on GIMPLE. */
5390 :
5391 : bool
5392 16774763 : generic_expr_could_trap_p (tree expr)
5393 : {
5394 16774763 : unsigned i, n;
5395 :
5396 16774763 : if (!expr || is_gimple_val (expr))
5397 : return false;
5398 :
5399 9350362 : if (!EXPR_P (expr) || tree_could_trap_p (expr))
5400 : return true;
5401 :
5402 6868856 : n = TREE_OPERAND_LENGTH (expr);
5403 16420028 : for (i = 0; i < n; i++)
5404 11895680 : if (generic_expr_could_trap_p (TREE_OPERAND (expr, i)))
5405 : return true;
5406 :
5407 : return false;
5408 : }
5409 :
5410 : /* Associate the condition STMT with the discriminator UID. STMTs that are
5411 : broken down with ANDIF/ORIF from the same Boolean expression should be given
5412 : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
5413 : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
5414 : for condition coverage. */
5415 : static void
5416 5552335 : gimple_associate_condition_with_expr (struct function *fn, gcond *stmt,
5417 : unsigned uid)
5418 : {
5419 5552335 : if (!condition_coverage_flag)
5420 : return;
5421 :
5422 657 : if (!fn->cond_uids)
5423 144 : fn->cond_uids = new hash_map <gcond*, unsigned> ();
5424 :
5425 657 : fn->cond_uids->put (stmt, uid);
5426 : }
5427 :
5428 : /* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
5429 : into
5430 :
5431 : if (p) if (p)
5432 : t1 = a; a;
5433 : else or else
5434 : t1 = b; b;
5435 : t1;
5436 :
5437 : The second form is used when *EXPR_P is of type void.
5438 :
5439 : PRE_P points to the list where side effects that must happen before
5440 : *EXPR_P should be stored. */
5441 :
5442 : static enum gimplify_status
5443 6329445 : gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
5444 : {
5445 6329445 : tree expr = *expr_p;
5446 6329445 : tree type = TREE_TYPE (expr);
5447 6329445 : location_t loc = EXPR_LOCATION (expr);
5448 6329445 : tree tmp, arm1, arm2;
5449 6329445 : enum gimplify_status ret;
5450 6329445 : tree label_true, label_false, label_cont;
5451 6329445 : bool have_then_clause_p, have_else_clause_p;
5452 6329445 : gcond *cond_stmt;
5453 6329445 : enum tree_code pred_code;
5454 6329445 : gimple_seq seq = NULL;
5455 :
5456 : /* If this COND_EXPR has a value, copy the values into a temporary within
5457 : the arms. */
5458 6329445 : if (!VOID_TYPE_P (type))
5459 : {
5460 420940 : tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
5461 420940 : tree result;
5462 :
5463 : /* If either an rvalue is ok or we do not require an lvalue, create the
5464 : temporary. But we cannot do that if the type is addressable. */
5465 420940 : if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
5466 420933 : && !TREE_ADDRESSABLE (type))
5467 : {
5468 420933 : if (gimplify_ctxp->allow_rhs_cond_expr
5469 : /* If either branch has side effects or could trap, it can't be
5470 : evaluated unconditionally. */
5471 45819 : && !TREE_SIDE_EFFECTS (then_)
5472 45819 : && !generic_expr_could_trap_p (then_)
5473 45819 : && !TREE_SIDE_EFFECTS (else_)
5474 466752 : && !generic_expr_could_trap_p (else_))
5475 45819 : return gimplify_pure_cond_expr (expr_p, pre_p);
5476 :
5477 375114 : tmp = create_tmp_var (type, "iftmp");
5478 375114 : result = tmp;
5479 : }
5480 :
5481 : /* Otherwise, only create and copy references to the values. */
5482 : else
5483 : {
5484 7 : type = build_pointer_type (type);
5485 :
5486 7 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5487 7 : then_ = build_fold_addr_expr_loc (loc, then_);
5488 :
5489 7 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5490 7 : else_ = build_fold_addr_expr_loc (loc, else_);
5491 :
5492 7 : expr
5493 7 : = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
5494 :
5495 7 : tmp = create_tmp_var (type, "iftmp");
5496 7 : result = build_simple_mem_ref_loc (loc, tmp);
5497 : }
5498 :
5499 : /* Build the new then clause, `tmp = then_;'. But don't build the
5500 : assignment if the value is void; in C++ it can be if it's a throw. */
5501 375121 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5502 293545 : TREE_OPERAND (expr, 1) = build2 (INIT_EXPR, type, tmp, then_);
5503 :
5504 : /* Similarly, build the new else clause, `tmp = else_;'. */
5505 375121 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5506 364449 : TREE_OPERAND (expr, 2) = build2 (INIT_EXPR, type, tmp, else_);
5507 :
5508 375121 : TREE_TYPE (expr) = void_type_node;
5509 375121 : recalculate_side_effects (expr);
5510 :
5511 : /* Move the COND_EXPR to the prequeue. */
5512 375121 : gimplify_stmt (&expr, pre_p);
5513 :
5514 375121 : *expr_p = result;
5515 375121 : return GS_ALL_DONE;
5516 : }
5517 :
5518 : /* Remove any COMPOUND_EXPR so the following cases will be caught. */
5519 5923268 : STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
5520 5908505 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
5521 81105 : gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
5522 :
5523 : /* Make sure the condition has BOOLEAN_TYPE. */
5524 5908505 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5525 :
5526 : /* Break apart && and || conditions. */
5527 5908505 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
5528 5908505 : || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
5529 : {
5530 355388 : expr = shortcut_cond_expr (expr, next_cond_uid ());
5531 :
5532 355388 : if (expr != *expr_p)
5533 : {
5534 355388 : *expr_p = expr;
5535 :
5536 : /* We can't rely on gimplify_expr to re-gimplify the expanded
5537 : form properly, as cleanups might cause the target labels to be
5538 : wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to
5539 : set up a conditional context. */
5540 355388 : gimple_push_condition ();
5541 355388 : gimplify_stmt (expr_p, &seq);
5542 355388 : gimple_pop_condition (pre_p);
5543 355388 : gimple_seq_add_seq (pre_p, seq);
5544 :
5545 355388 : return GS_ALL_DONE;
5546 : }
5547 : }
5548 :
5549 : /* Now do the normal gimplification. */
5550 :
5551 : /* Gimplify condition. */
5552 5553117 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
5553 : is_gimple_condexpr_for_cond, fb_rvalue);
5554 5553117 : if (ret == GS_ERROR)
5555 : return GS_ERROR;
5556 5552335 : gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
5557 :
5558 5552335 : gimple_push_condition ();
5559 :
5560 5552335 : have_then_clause_p = have_else_clause_p = false;
5561 5552335 : label_true = find_goto_label (TREE_OPERAND (expr, 1));
5562 5552335 : if (label_true
5563 1293241 : && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
5564 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5565 : have different locations, otherwise we end up with incorrect
5566 : location information on the branches. */
5567 6845576 : && (optimize
5568 231179 : || !EXPR_HAS_LOCATION (expr)
5569 204270 : || !rexpr_has_location (label_true)
5570 67970 : || EXPR_LOCATION (expr) == rexpr_location (label_true)))
5571 : {
5572 1292066 : have_then_clause_p = true;
5573 1292066 : label_true = GOTO_DESTINATION (label_true);
5574 : }
5575 : else
5576 4260269 : label_true = create_artificial_label (UNKNOWN_LOCATION);
5577 5552335 : label_false = find_goto_label (TREE_OPERAND (expr, 2));
5578 5552335 : if (label_false
5579 735470 : && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
5580 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5581 : have different locations, otherwise we end up with incorrect
5582 : location information on the branches. */
5583 6287805 : && (optimize
5584 104855 : || !EXPR_HAS_LOCATION (expr)
5585 103973 : || !rexpr_has_location (label_false)
5586 112 : || EXPR_LOCATION (expr) == rexpr_location (label_false)))
5587 : {
5588 735370 : have_else_clause_p = true;
5589 735370 : label_false = GOTO_DESTINATION (label_false);
5590 : }
5591 : else
5592 4816965 : label_false = create_artificial_label (UNKNOWN_LOCATION);
5593 :
5594 5552335 : unsigned cond_uid = 0;
5595 5552335 : if (cond_uids)
5596 467 : if (unsigned *v = cond_uids->get (expr))
5597 447 : cond_uid = *v;
5598 447 : if (cond_uid == 0)
5599 5551888 : cond_uid = next_cond_uid ();
5600 :
5601 5552335 : gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
5602 : &arm2);
5603 5552335 : cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
5604 : label_false);
5605 5552335 : gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
5606 5552335 : gimple_associate_condition_with_expr (cfun, cond_stmt, cond_uid);
5607 5552335 : copy_warning (cond_stmt, COND_EXPR_COND (expr));
5608 5552335 : gimplify_seq_add_stmt (&seq, cond_stmt);
5609 5552335 : gimple_stmt_iterator gsi = gsi_last (seq);
5610 5552335 : maybe_fold_stmt (&gsi);
5611 :
5612 5552335 : label_cont = NULL_TREE;
5613 5552335 : if (!have_then_clause_p)
5614 : {
5615 : /* For if (...) {} else { code; } put label_true after
5616 : the else block. */
5617 4260269 : if (TREE_OPERAND (expr, 1) == NULL_TREE
5618 202681 : && !have_else_clause_p
5619 4261039 : && TREE_OPERAND (expr, 2) != NULL_TREE)
5620 : {
5621 : /* For if (0) {} else { code; } tell -Wimplicit-fallthrough
5622 : handling that label_cont == label_true can be only reached
5623 : through fallthrough from { code; }. */
5624 770 : if (integer_zerop (COND_EXPR_COND (expr)))
5625 0 : UNUSED_LABEL_P (label_true) = 1;
5626 : label_cont = label_true;
5627 : }
5628 : else
5629 : {
5630 4259499 : bool then_side_effects
5631 4259499 : = (TREE_OPERAND (expr, 1)
5632 4259499 : && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)));
5633 4259499 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
5634 4259499 : have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
5635 : /* For if (...) { code; } else {} or
5636 : if (...) { code; } else goto label; or
5637 : if (...) { code; return; } else { ... }
5638 : label_cont isn't needed. */
5639 4259499 : if (!have_else_clause_p
5640 4056442 : && TREE_OPERAND (expr, 2) != NULL_TREE
5641 7088709 : && gimple_seq_may_fallthru (seq))
5642 : {
5643 1965030 : gimple *g;
5644 1965030 : label_cont = create_artificial_label (UNKNOWN_LOCATION);
5645 :
5646 : /* For if (0) { non-side-effect-code } else { code }
5647 : tell -Wimplicit-fallthrough handling that label_cont can
5648 : be only reached through fallthrough from { code }. */
5649 1965030 : if (integer_zerop (COND_EXPR_COND (expr)))
5650 : {
5651 76487 : UNUSED_LABEL_P (label_true) = 1;
5652 76487 : if (!then_side_effects)
5653 12376 : UNUSED_LABEL_P (label_cont) = 1;
5654 : }
5655 :
5656 1965030 : g = gimple_build_goto (label_cont);
5657 :
5658 : /* GIMPLE_COND's are very low level; they have embedded
5659 : gotos. This particular embedded goto should not be marked
5660 : with the location of the original COND_EXPR, as it would
5661 : correspond to the COND_EXPR's condition, not the ELSE or the
5662 : THEN arms. To avoid marking it with the wrong location, flag
5663 : it as "no location". */
5664 1965030 : gimple_set_do_not_emit_location (g);
5665 :
5666 1965030 : gimplify_seq_add_stmt (&seq, g);
5667 : }
5668 : }
5669 : }
5670 5552335 : if (!have_else_clause_p)
5671 : {
5672 : /* For if (1) { code } or if (1) { code } else { non-side-effect-code }
5673 : tell -Wimplicit-fallthrough handling that label_false can be only
5674 : reached through fallthrough from { code }. */
5675 4816965 : if (integer_nonzerop (COND_EXPR_COND (expr))
5676 4816965 : && (TREE_OPERAND (expr, 2) == NULL_TREE
5677 56892 : || !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2))))
5678 7864 : UNUSED_LABEL_P (label_false) = 1;
5679 4816965 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_false));
5680 4816965 : have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq);
5681 : }
5682 5552335 : if (label_cont)
5683 1965800 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_cont));
5684 :
5685 5552335 : gimple_pop_condition (pre_p);
5686 5552335 : gimple_seq_add_seq (pre_p, seq);
5687 :
5688 5552335 : if (ret == GS_ERROR)
5689 : ; /* Do nothing. */
5690 5552335 : else if (have_then_clause_p || have_else_clause_p)
5691 : ret = GS_ALL_DONE;
5692 : else
5693 : {
5694 : /* Both arms are empty; replace the COND_EXPR with its predicate. */
5695 2958 : expr = TREE_OPERAND (expr, 0);
5696 2958 : gimplify_stmt (&expr, pre_p);
5697 : }
5698 :
5699 5552335 : *expr_p = NULL;
5700 5552335 : return ret;
5701 : }
5702 :
5703 : /* Prepare the node pointed to by EXPR_P, an is_gimple_addressable expression,
5704 : to be marked addressable.
5705 :
5706 : We cannot rely on such an expression being directly markable if a temporary
5707 : has been created by the gimplification. In this case, we create another
5708 : temporary and initialize it with a copy, which will become a store after we
5709 : mark it addressable. This can happen if the front-end passed us something
5710 : that it could not mark addressable yet, like a Fortran pass-by-reference
5711 : parameter (int) floatvar. */
5712 :
5713 : static void
5714 57401282 : prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
5715 : {
5716 63021817 : while (handled_component_p (*expr_p))
5717 5620535 : expr_p = &TREE_OPERAND (*expr_p, 0);
5718 :
5719 : /* Do not allow an SSA name as the temporary. */
5720 57401282 : if (is_gimple_reg (*expr_p))
5721 12133 : *expr_p = internal_get_tmp_var (*expr_p, seq_p, NULL, false, false, true);
5722 57401282 : }
5723 :
5724 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5725 : a call to __builtin_memcpy. */
5726 :
5727 : static enum gimplify_status
5728 1106 : gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
5729 : gimple_seq *seq_p)
5730 : {
5731 1106 : tree t, to, to_ptr, from, from_ptr;
5732 1106 : gcall *gs;
5733 1106 : location_t loc = EXPR_LOCATION (*expr_p);
5734 :
5735 1106 : to = TREE_OPERAND (*expr_p, 0);
5736 1106 : from = TREE_OPERAND (*expr_p, 1);
5737 1106 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to)))
5738 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))));
5739 :
5740 : /* Mark the RHS addressable. Beware that it may not be possible to do so
5741 : directly if a temporary has been created by the gimplification. */
5742 1106 : prepare_gimple_addressable (&from, seq_p);
5743 :
5744 1106 : mark_addressable (from);
5745 1106 : from_ptr = build_fold_addr_expr_loc (loc, from);
5746 1106 : gimplify_arg (&from_ptr, seq_p, loc);
5747 :
5748 1106 : mark_addressable (to);
5749 1106 : to_ptr = build_fold_addr_expr_loc (loc, to);
5750 1106 : gimplify_arg (&to_ptr, seq_p, loc);
5751 :
5752 1106 : t = builtin_decl_implicit (BUILT_IN_MEMCPY);
5753 :
5754 1106 : gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
5755 1106 : gimple_call_set_alloca_for_var (gs, true);
5756 :
5757 1106 : if (want_value)
5758 : {
5759 : /* tmp = memcpy() */
5760 8 : t = create_tmp_var (TREE_TYPE (to_ptr));
5761 8 : gimple_call_set_lhs (gs, t);
5762 8 : gimplify_seq_add_stmt (seq_p, gs);
5763 :
5764 8 : *expr_p = build_simple_mem_ref (t);
5765 8 : return GS_ALL_DONE;
5766 : }
5767 :
5768 1098 : gimplify_seq_add_stmt (seq_p, gs);
5769 1098 : *expr_p = NULL;
5770 1098 : return GS_ALL_DONE;
5771 : }
5772 :
5773 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5774 : a call to __builtin_memset. In this case we know that the RHS is
5775 : a CONSTRUCTOR with an empty element list. */
5776 :
5777 : static enum gimplify_status
5778 84 : gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
5779 : gimple_seq *seq_p)
5780 : {
5781 84 : tree t, from, to, to_ptr;
5782 84 : gcall *gs;
5783 84 : location_t loc = EXPR_LOCATION (*expr_p);
5784 :
5785 : /* Assert our assumptions, to abort instead of producing wrong code
5786 : silently if they are not met. Beware that the RHS CONSTRUCTOR might
5787 : not be immediately exposed. */
5788 84 : from = TREE_OPERAND (*expr_p, 1);
5789 84 : if (TREE_CODE (from) == WITH_SIZE_EXPR)
5790 84 : from = TREE_OPERAND (from, 0);
5791 :
5792 84 : gcc_assert (TREE_CODE (from) == CONSTRUCTOR
5793 : && vec_safe_is_empty (CONSTRUCTOR_ELTS (from)));
5794 :
5795 : /* Now proceed. */
5796 84 : to = TREE_OPERAND (*expr_p, 0);
5797 84 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to))));
5798 :
5799 84 : to_ptr = build_fold_addr_expr_loc (loc, to);
5800 84 : gimplify_arg (&to_ptr, seq_p, loc);
5801 84 : t = builtin_decl_implicit (BUILT_IN_MEMSET);
5802 :
5803 84 : gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
5804 :
5805 84 : if (want_value)
5806 : {
5807 : /* tmp = memset() */
5808 0 : t = create_tmp_var (TREE_TYPE (to_ptr));
5809 0 : gimple_call_set_lhs (gs, t);
5810 0 : gimplify_seq_add_stmt (seq_p, gs);
5811 :
5812 0 : *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
5813 0 : return GS_ALL_DONE;
5814 : }
5815 :
5816 84 : gimplify_seq_add_stmt (seq_p, gs);
5817 84 : *expr_p = NULL;
5818 84 : return GS_ALL_DONE;
5819 : }
5820 :
5821 : /* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
5822 : determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
5823 : assignment. Return non-null if we detect a potential overlap. */
5824 :
5825 : struct gimplify_init_ctor_preeval_data
5826 : {
5827 : /* The base decl of the lhs object. May be NULL, in which case we
5828 : have to assume the lhs is indirect. */
5829 : tree lhs_base_decl;
5830 :
5831 : /* The alias set of the lhs object. */
5832 : alias_set_type lhs_alias_set;
5833 : };
5834 :
5835 : static tree
5836 116410 : gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
5837 : {
5838 116410 : struct gimplify_init_ctor_preeval_data *data
5839 : = (struct gimplify_init_ctor_preeval_data *) xdata;
5840 116410 : tree t = *tp;
5841 :
5842 : /* If we find the base object, obviously we have overlap. */
5843 116410 : if (data->lhs_base_decl == t)
5844 : return t;
5845 :
5846 : /* If the constructor component is indirect, determine if we have a
5847 : potential overlap with the lhs. The only bits of information we
5848 : have to go on at this point are addressability and alias sets. */
5849 116409 : if ((INDIRECT_REF_P (t)
5850 116409 : || TREE_CODE (t) == MEM_REF)
5851 651 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5852 116925 : && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
5853 : return t;
5854 :
5855 : /* If the constructor component is a call, determine if it can hide a
5856 : potential overlap with the lhs through an INDIRECT_REF like above.
5857 : ??? Ugh - this is completely broken. In fact this whole analysis
5858 : doesn't look conservative. */
5859 115893 : if (TREE_CODE (t) == CALL_EXPR)
5860 : {
5861 0 : tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
5862 :
5863 0 : for (type = TYPE_ARG_TYPES (fntype); type; type = TREE_CHAIN (type))
5864 0 : if (POINTER_TYPE_P (TREE_VALUE (type))
5865 0 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5866 0 : && alias_sets_conflict_p (data->lhs_alias_set,
5867 : get_alias_set
5868 0 : (TREE_TYPE (TREE_VALUE (type)))))
5869 : return t;
5870 : }
5871 :
5872 115893 : if (IS_TYPE_OR_DECL_P (t))
5873 10968 : *walk_subtrees = 0;
5874 : return NULL;
5875 : }
5876 :
5877 : /* A subroutine of gimplify_init_constructor. Pre-evaluate EXPR,
5878 : force values that overlap with the lhs (as described by *DATA)
5879 : into temporaries. */
5880 :
5881 : static void
5882 418193 : gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
5883 : struct gimplify_init_ctor_preeval_data *data)
5884 : {
5885 418193 : enum gimplify_status one;
5886 :
5887 : /* If the value is constant, then there's nothing to pre-evaluate. */
5888 418193 : if (TREE_CONSTANT (*expr_p))
5889 : {
5890 : /* Ensure it does not have side effects, it might contain a reference to
5891 : the object we're initializing. */
5892 199982 : gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
5893 : return;
5894 : }
5895 :
5896 : /* If the type has non-trivial constructors, we can't pre-evaluate. */
5897 218211 : if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
5898 : return;
5899 :
5900 : /* Recurse for nested constructors. */
5901 218211 : if (TREE_CODE (*expr_p) == CONSTRUCTOR)
5902 : {
5903 73929 : unsigned HOST_WIDE_INT ix;
5904 73929 : constructor_elt *ce;
5905 73929 : vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (*expr_p);
5906 :
5907 272066 : FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
5908 198137 : gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
5909 :
5910 : return;
5911 : }
5912 :
5913 : /* If this is a variable sized type, we must remember the size. */
5914 144282 : maybe_with_size_expr (expr_p);
5915 :
5916 : /* Gimplify the constructor element to something appropriate for the rhs
5917 : of a MODIFY_EXPR. Given that we know the LHS is an aggregate, we know
5918 : the gimplifier will consider this a store to memory. Doing this
5919 : gimplification now means that we won't have to deal with complicated
5920 : language-specific trees, nor trees like SAVE_EXPR that can induce
5921 : exponential search behavior. */
5922 144282 : one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
5923 144282 : if (one == GS_ERROR)
5924 : {
5925 0 : *expr_p = NULL;
5926 0 : return;
5927 : }
5928 :
5929 : /* If we gimplified to a bare decl, we can be sure that it doesn't overlap
5930 : with the lhs, since "a = { .x=a }" doesn't make sense. This will
5931 : always be true for all scalars, since is_gimple_mem_rhs insists on a
5932 : temporary variable for them. */
5933 144282 : if (DECL_P (*expr_p))
5934 : return;
5935 :
5936 : /* If this is of variable size, we have no choice but to assume it doesn't
5937 : overlap since we can't make a temporary for it. */
5938 104846 : if (TREE_CODE (TYPE_SIZE (TREE_TYPE (*expr_p))) != INTEGER_CST)
5939 : return;
5940 :
5941 : /* Otherwise, we must search for overlap ... */
5942 104846 : if (!walk_tree (expr_p, gimplify_init_ctor_preeval_1, data, NULL))
5943 : return;
5944 :
5945 : /* ... and if found, force the value into a temporary. */
5946 517 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
5947 : }
5948 :
5949 : /* A subroutine of gimplify_init_ctor_eval. Create a loop for
5950 : a RANGE_EXPR in a CONSTRUCTOR for an array.
5951 :
5952 : var = lower;
5953 : loop_entry:
5954 : object[var] = value;
5955 : if (var == upper)
5956 : goto loop_exit;
5957 : var = var + 1;
5958 : goto loop_entry;
5959 : loop_exit:
5960 :
5961 : We increment var _after_ the loop exit check because we might otherwise
5962 : fail if upper == TYPE_MAX_VALUE (type for upper).
5963 :
5964 : Note that we never have to deal with SAVE_EXPRs here, because this has
5965 : already been taken care of for us, in gimplify_init_ctor_preeval(). */
5966 :
5967 : static void gimplify_init_ctor_eval (tree, vec<constructor_elt, va_gc> *,
5968 : gimple_seq *, bool);
5969 :
5970 : static void
5971 579 : gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
5972 : tree value, tree array_elt_type,
5973 : gimple_seq *pre_p, bool cleared)
5974 : {
5975 579 : tree loop_entry_label, loop_exit_label, fall_thru_label;
5976 579 : tree var, var_type, cref, tmp;
5977 :
5978 579 : loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
5979 579 : loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
5980 579 : fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
5981 :
5982 : /* Create and initialize the index variable. */
5983 579 : var_type = TREE_TYPE (upper);
5984 579 : var = create_tmp_var (var_type);
5985 579 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
5986 :
5987 : /* Add the loop entry label. */
5988 579 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
5989 :
5990 : /* Build the reference. */
5991 579 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
5992 : var, NULL_TREE, NULL_TREE);
5993 :
5994 : /* If we are a constructor, just call gimplify_init_ctor_eval to do
5995 : the store. Otherwise just assign value to the reference. */
5996 :
5997 579 : if (TREE_CODE (value) == CONSTRUCTOR)
5998 : /* NB we might have to call ourself recursively through
5999 : gimplify_init_ctor_eval if the value is a constructor. */
6000 129 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
6001 : pre_p, cleared);
6002 : else
6003 : {
6004 450 : if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue)
6005 : != GS_ERROR)
6006 450 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
6007 : }
6008 :
6009 : /* We exit the loop when the index var is equal to the upper bound. */
6010 1158 : gimplify_seq_add_stmt (pre_p,
6011 579 : gimple_build_cond (EQ_EXPR, var, upper,
6012 : loop_exit_label, fall_thru_label));
6013 :
6014 579 : gimplify_seq_add_stmt (pre_p, gimple_build_label (fall_thru_label));
6015 :
6016 : /* Otherwise, increment the index var... */
6017 579 : tmp = build2 (PLUS_EXPR, var_type, var,
6018 : fold_convert (var_type, integer_one_node));
6019 579 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
6020 :
6021 : /* ...and jump back to the loop entry. */
6022 579 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
6023 :
6024 : /* Add the loop exit label. */
6025 579 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
6026 579 : }
6027 :
6028 : /* A subroutine of gimplify_init_constructor. Generate individual
6029 : MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the
6030 : assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the
6031 : CONSTRUCTOR. CLEARED is true if the entire LHS object has been
6032 : zeroed first. */
6033 :
6034 : static void
6035 1274527 : gimplify_init_ctor_eval (tree object, vec<constructor_elt, va_gc> *elts,
6036 : gimple_seq *pre_p, bool cleared)
6037 : {
6038 1274527 : tree array_elt_type = NULL;
6039 1274527 : unsigned HOST_WIDE_INT ix;
6040 1274527 : tree purpose, value;
6041 :
6042 1274527 : if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
6043 142377 : array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
6044 :
6045 4708648 : FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
6046 : {
6047 3434121 : tree cref;
6048 :
6049 : /* NULL values are created above for gimplification errors. */
6050 3434121 : if (value == NULL)
6051 327849 : continue;
6052 :
6053 3434121 : if (cleared && initializer_zerop (value))
6054 327104 : continue;
6055 :
6056 : /* ??? Here's to hoping the front end fills in all of the indices,
6057 : so we don't have to figure out what's missing ourselves. */
6058 3107017 : gcc_assert (purpose);
6059 :
6060 : /* Skip zero-sized fields, unless value has side-effects. This can
6061 : happen with calls to functions returning a empty type, which
6062 : we shouldn't discard. As a number of downstream passes don't
6063 : expect sets of empty type fields, we rely on the gimplification of
6064 : the MODIFY_EXPR we make below to drop the assignment statement. */
6065 3107017 : if (!TREE_SIDE_EFFECTS (value)
6066 2812563 : && TREE_CODE (purpose) == FIELD_DECL
6067 5446286 : && is_empty_type (TREE_TYPE (purpose)))
6068 166 : continue;
6069 :
6070 : /* If we have a RANGE_EXPR, we have to build a loop to assign the
6071 : whole range. */
6072 3106851 : if (TREE_CODE (purpose) == RANGE_EXPR)
6073 : {
6074 595 : tree lower = TREE_OPERAND (purpose, 0);
6075 595 : tree upper = TREE_OPERAND (purpose, 1);
6076 :
6077 : /* If the lower bound is equal to upper, just treat it as if
6078 : upper was the index. */
6079 595 : if (simple_cst_equal (lower, upper))
6080 : purpose = upper;
6081 : else
6082 : {
6083 579 : gimplify_init_ctor_eval_range (object, lower, upper, value,
6084 : array_elt_type, pre_p, cleared);
6085 579 : continue;
6086 : }
6087 : }
6088 :
6089 3106272 : if (array_elt_type)
6090 : {
6091 : /* Do not use bitsizetype for ARRAY_REF indices. */
6092 563537 : if (TYPE_DOMAIN (TREE_TYPE (object)))
6093 563537 : purpose
6094 563537 : = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
6095 : purpose);
6096 563537 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
6097 : purpose, NULL_TREE, NULL_TREE);
6098 : }
6099 : else
6100 : {
6101 2542735 : gcc_assert (TREE_CODE (purpose) == FIELD_DECL);
6102 2542735 : cref = build3 (COMPONENT_REF, TREE_TYPE (purpose),
6103 : unshare_expr (object), purpose, NULL_TREE);
6104 : }
6105 :
6106 3106272 : if (TREE_CODE (value) == CONSTRUCTOR
6107 3106272 : && TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE)
6108 302915 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
6109 : pre_p, cleared);
6110 2803357 : else if (TREE_CODE (value) == RAW_DATA_CST)
6111 : {
6112 43 : if (RAW_DATA_LENGTH (value) <= 32)
6113 : {
6114 13 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value);
6115 : ++i)
6116 12 : if (!cleared || RAW_DATA_POINTER (value)[i])
6117 : {
6118 12 : if (i)
6119 : {
6120 11 : tree p
6121 11 : = fold_build2 (PLUS_EXPR, TREE_TYPE (purpose),
6122 : purpose,
6123 : build_int_cst (TREE_TYPE (purpose),
6124 : i));
6125 11 : cref = build4 (ARRAY_REF, array_elt_type,
6126 : unshare_expr (object), p, NULL_TREE,
6127 : NULL_TREE);
6128 : }
6129 12 : tree init
6130 12 : = build2 (INIT_EXPR, TREE_TYPE (cref), cref,
6131 12 : build_int_cst (TREE_TYPE (value),
6132 12 : RAW_DATA_UCHAR_ELT (value, i)));
6133 12 : gimplify_and_add (init, pre_p);
6134 12 : ggc_free (init);
6135 : }
6136 : }
6137 : else
6138 : {
6139 42 : tree rtype = build_array_type_nelts (TREE_TYPE (value),
6140 42 : RAW_DATA_LENGTH (value));
6141 42 : tree rctor = build_constructor_single (rtype, bitsize_zero_node,
6142 : value);
6143 42 : tree addr = build_fold_addr_expr (cref);
6144 42 : cref = build2 (MEM_REF, rtype, addr,
6145 : build_int_cst (ptr_type_node, 0));
6146 42 : rctor = tree_output_constant_def (rctor);
6147 42 : if (!useless_type_conversion_p (rtype, TREE_TYPE (rctor)))
6148 4 : rctor = build1 (VIEW_CONVERT_EXPR, rtype, rctor);
6149 42 : if (gimplify_expr (&cref, pre_p, NULL, is_gimple_lvalue,
6150 : fb_lvalue) != GS_ERROR)
6151 84 : gimplify_seq_add_stmt (pre_p,
6152 42 : gimple_build_assign (cref, rctor));
6153 : }
6154 : }
6155 : else
6156 : {
6157 2803314 : tree init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
6158 2803314 : gimplify_and_add (init, pre_p);
6159 2803314 : ggc_free (init);
6160 : }
6161 : }
6162 1274527 : }
6163 :
6164 : /* Return the appropriate RHS predicate for this LHS. */
6165 :
6166 : gimple_predicate
6167 49838234 : rhs_predicate_for (tree lhs)
6168 : {
6169 49838234 : if (is_gimple_reg (lhs))
6170 : return is_gimple_reg_rhs_or_call;
6171 : else
6172 11747990 : return is_gimple_mem_rhs_or_call;
6173 : }
6174 :
6175 : /* Return the initial guess for an appropriate RHS predicate for this LHS,
6176 : before the LHS has been gimplified. */
6177 :
6178 : static gimple_predicate
6179 48623094 : initial_rhs_predicate_for (tree lhs)
6180 : {
6181 48623094 : if (is_gimple_reg_type (TREE_TYPE (lhs)))
6182 : return is_gimple_reg_rhs_or_call;
6183 : else
6184 2462897 : return is_gimple_mem_rhs_or_call;
6185 : }
6186 :
6187 : /* Gimplify a C99 compound literal expression. This just means adding
6188 : the DECL_EXPR before the current statement and using its anonymous
6189 : decl instead. */
6190 :
6191 : static enum gimplify_status
6192 37242 : gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
6193 : bool (*gimple_test_f) (tree),
6194 : fallback_t fallback)
6195 : {
6196 37242 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
6197 37242 : tree decl = DECL_EXPR_DECL (decl_s);
6198 37242 : tree init = DECL_INITIAL (decl);
6199 : /* Mark the decl as addressable if the compound literal
6200 : expression is addressable now, otherwise it is marked too late
6201 : after we gimplify the initialization expression. */
6202 37242 : if (TREE_ADDRESSABLE (*expr_p))
6203 549 : TREE_ADDRESSABLE (decl) = 1;
6204 : /* Otherwise, if we don't need an lvalue and have a literal directly
6205 : substitute it. Check if it matches the gimple predicate, as
6206 : otherwise we'd generate a new temporary, and we can as well just
6207 : use the decl we already have. */
6208 36693 : else if (!TREE_ADDRESSABLE (decl)
6209 36693 : && !TREE_THIS_VOLATILE (decl)
6210 36688 : && init
6211 36680 : && (fallback & fb_lvalue) == 0
6212 73208 : && gimple_test_f (init))
6213 : {
6214 35423 : *expr_p = init;
6215 35423 : return GS_OK;
6216 : }
6217 :
6218 : /* If the decl is not addressable, then it is being used in some
6219 : expression or on the right hand side of a statement, and it can
6220 : be put into a readonly data section. */
6221 1819 : if (!TREE_ADDRESSABLE (decl) && (fallback & fb_lvalue) == 0)
6222 1097 : TREE_READONLY (decl) = 1;
6223 :
6224 : /* This decl isn't mentioned in the enclosing block, so add it to the
6225 : list of temps. FIXME it seems a bit of a kludge to say that
6226 : anonymous artificial vars aren't pushed, but everything else is. */
6227 1819 : if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
6228 2 : gimple_add_tmp_var (decl);
6229 :
6230 1819 : gimplify_and_add (decl_s, pre_p);
6231 1819 : *expr_p = decl;
6232 1819 : return GS_OK;
6233 : }
6234 :
6235 : /* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
6236 : return a new CONSTRUCTOR if something changed. */
6237 :
6238 : static tree
6239 1900202 : optimize_compound_literals_in_ctor (tree orig_ctor)
6240 : {
6241 1900202 : tree ctor = orig_ctor;
6242 1900202 : vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
6243 1900202 : unsigned int idx, num = vec_safe_length (elts);
6244 :
6245 6297029 : for (idx = 0; idx < num; idx++)
6246 : {
6247 4396827 : tree value = (*elts)[idx].value;
6248 4396827 : tree newval = value;
6249 4396827 : if (TREE_CODE (value) == CONSTRUCTOR)
6250 546074 : newval = optimize_compound_literals_in_ctor (value);
6251 3850753 : else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
6252 : {
6253 103 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
6254 103 : tree decl = DECL_EXPR_DECL (decl_s);
6255 103 : tree init = DECL_INITIAL (decl);
6256 :
6257 103 : if (!TREE_ADDRESSABLE (value)
6258 103 : && !TREE_ADDRESSABLE (decl)
6259 103 : && init
6260 103 : && TREE_CODE (init) == CONSTRUCTOR)
6261 52 : newval = optimize_compound_literals_in_ctor (init);
6262 : }
6263 4396827 : if (newval == value)
6264 4396767 : continue;
6265 :
6266 60 : if (ctor == orig_ctor)
6267 : {
6268 49 : ctor = copy_node (orig_ctor);
6269 98 : CONSTRUCTOR_ELTS (ctor) = vec_safe_copy (elts);
6270 49 : elts = CONSTRUCTOR_ELTS (ctor);
6271 : }
6272 60 : (*elts)[idx].value = newval;
6273 : }
6274 1900202 : return ctor;
6275 : }
6276 :
6277 : /* A subroutine of gimplify_modify_expr. Break out elements of a
6278 : CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
6279 :
6280 : Note that we still need to clear any elements that don't have explicit
6281 : initializers, so if not all elements are initialized we keep the
6282 : original MODIFY_EXPR, we just remove all of the constructor elements.
6283 :
6284 : If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
6285 : GS_ERROR if we would have to create a temporary when gimplifying
6286 : this constructor. Otherwise, return GS_OK.
6287 :
6288 : If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
6289 :
6290 : static enum gimplify_status
6291 1354076 : gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
6292 : bool want_value, bool notify_temp_creation)
6293 : {
6294 1354076 : tree object, ctor, type;
6295 1354076 : enum gimplify_status ret;
6296 1354076 : vec<constructor_elt, va_gc> *elts;
6297 1354076 : bool cleared = false;
6298 1354076 : bool is_empty_ctor = false;
6299 1354076 : bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR);
6300 :
6301 1354076 : gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
6302 :
6303 1354076 : if (!notify_temp_creation)
6304 : {
6305 1345401 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
6306 : is_gimple_lvalue, fb_lvalue);
6307 1345401 : if (ret == GS_ERROR)
6308 : return ret;
6309 : }
6310 :
6311 1354076 : object = TREE_OPERAND (*expr_p, 0);
6312 1354076 : ctor = TREE_OPERAND (*expr_p, 1)
6313 1354076 : = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
6314 1354076 : type = TREE_TYPE (ctor);
6315 1354076 : elts = CONSTRUCTOR_ELTS (ctor);
6316 1354076 : ret = GS_ALL_DONE;
6317 :
6318 1354076 : switch (TREE_CODE (type))
6319 : {
6320 1345374 : case RECORD_TYPE:
6321 1345374 : case UNION_TYPE:
6322 1345374 : case QUAL_UNION_TYPE:
6323 1345374 : case ARRAY_TYPE:
6324 1345374 : {
6325 : /* Use readonly data for initializers of this or smaller size
6326 : regardless of the num_nonzero_elements / num_unique_nonzero_elements
6327 : ratio. */
6328 1345374 : const HOST_WIDE_INT min_unique_size = 64;
6329 : /* If num_nonzero_elements / num_unique_nonzero_elements ratio
6330 : is smaller than this, use readonly data. */
6331 1345374 : const int unique_nonzero_ratio = 8;
6332 : /* True if a single access of the object must be ensured. This is the
6333 : case if the target is volatile, the type is non-addressable and more
6334 : than one field need to be assigned. */
6335 1345374 : const bool ensure_single_access
6336 1345374 : = TREE_THIS_VOLATILE (object)
6337 259 : && !TREE_ADDRESSABLE (type)
6338 1345579 : && vec_safe_length (elts) > 1;
6339 1345374 : struct gimplify_init_ctor_preeval_data preeval_data;
6340 1345374 : HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
6341 1345374 : HOST_WIDE_INT num_unique_nonzero_elements;
6342 1345374 : ctor_completeness complete_p;
6343 1345374 : bool valid_const_initializer;
6344 :
6345 : /* Aggregate types must lower constructors to initialization of
6346 : individual elements. The exception is that a CONSTRUCTOR node
6347 : with no elements indicates zero-initialization of the whole. */
6348 1345374 : if (vec_safe_is_empty (elts))
6349 : {
6350 339451 : if (notify_temp_creation)
6351 10211 : return GS_OK;
6352 :
6353 : /* The var will be initialized and so appear on lhs of
6354 : assignment, it can't be TREE_READONLY anymore. */
6355 339403 : if (VAR_P (object))
6356 189260 : TREE_READONLY (object) = 0;
6357 :
6358 : is_empty_ctor = true;
6359 343368 : break;
6360 : }
6361 :
6362 : /* Fetch information about the constructor to direct later processing.
6363 : We might want to make static versions of it in various cases, and
6364 : can only do so if it known to be a valid constant initializer. */
6365 1005923 : valid_const_initializer
6366 1005923 : = categorize_ctor_elements (ctor, &num_nonzero_elements,
6367 : &num_unique_nonzero_elements,
6368 : &num_ctor_elements, &complete_p);
6369 :
6370 : /* If a const aggregate variable is being initialized, then it
6371 : should never be a lose to promote the variable to be static. */
6372 1005923 : if (valid_const_initializer
6373 623496 : && num_nonzero_elements > 1
6374 456010 : && TREE_READONLY (object)
6375 7682 : && VAR_P (object)
6376 7305 : && !DECL_REGISTER (object)
6377 7298 : && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)
6378 5147 : || DECL_MERGEABLE (object))
6379 : /* For ctors that have many repeated nonzero elements
6380 : represented through RANGE_EXPRs, prefer initializing
6381 : those through runtime loops over copies of large amounts
6382 : of data from readonly data section. */
6383 1005923 : && (num_unique_nonzero_elements
6384 3965 : > num_nonzero_elements / unique_nonzero_ratio
6385 0 : || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
6386 : <= (unsigned HOST_WIDE_INT) min_unique_size)))
6387 : {
6388 3965 : if (notify_temp_creation)
6389 : return GS_ERROR;
6390 :
6391 3965 : DECL_INITIAL (object) = ctor;
6392 3965 : TREE_STATIC (object) = 1;
6393 3965 : if (!DECL_NAME (object) || DECL_NAMELESS (object))
6394 2999 : DECL_NAME (object) = create_tmp_var_name ("C");
6395 3965 : walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL);
6396 :
6397 : /* ??? C++ doesn't automatically append a .<number> to the
6398 : assembler name, and even when it does, it looks at FE private
6399 : data structures to figure out what that number should be,
6400 : which are not set for this variable. I suppose this is
6401 : important for local statics for inline functions, which aren't
6402 : "local" in the object file sense. So in order to get a unique
6403 : TU-local symbol, we must invoke the lhd version now. */
6404 3965 : lhd_set_decl_assembler_name (object);
6405 :
6406 3965 : *expr_p = NULL_TREE;
6407 3965 : break;
6408 : }
6409 :
6410 : /* The var will be initialized and so appear on lhs of
6411 : assignment, it can't be TREE_READONLY anymore. */
6412 1001958 : if (VAR_P (object) && !notify_temp_creation)
6413 790299 : TREE_READONLY (object) = 0;
6414 :
6415 : /* If there are "lots" of initialized elements, even discounting
6416 : those that are not address constants (and thus *must* be
6417 : computed at runtime), then partition the constructor into
6418 : constant and non-constant parts. Block copy the constant
6419 : parts in, then generate code for the non-constant parts. */
6420 : /* TODO. There's code in cp/typeck.cc to do this. */
6421 :
6422 1001958 : if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
6423 : /* store_constructor will ignore the clearing of variable-sized
6424 : objects. Initializers for such objects must explicitly set
6425 : every field that needs to be set. */
6426 : cleared = false;
6427 1001938 : else if (complete_p.sparse)
6428 : /* If the constructor isn't complete, clear the whole object
6429 : beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
6430 :
6431 : ??? This ought not to be needed. For any element not present
6432 : in the initializer, we should simply set them to zero. Except
6433 : we'd need to *find* the elements that are not present, and that
6434 : requires trickery to avoid quadratic compile-time behavior in
6435 : large cases or excessive memory use in small cases. */
6436 192427 : cleared = !CONSTRUCTOR_NO_CLEARING (ctor);
6437 809511 : else if (num_ctor_elements - num_nonzero_elements
6438 809511 : > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
6439 809511 : && num_nonzero_elements < num_ctor_elements / 4)
6440 : /* If there are "lots" of zeros, it's more efficient to clear
6441 : the memory and then set the nonzero elements. */
6442 : cleared = true;
6443 808486 : else if (ensure_single_access && num_nonzero_elements == 0)
6444 : /* If a single access to the target must be ensured and all elements
6445 : are zero, then it's optimal to clear whatever their number. */
6446 : cleared = true;
6447 : /* If the object is small enough to go in registers, and it's
6448 : not required to be constructed in memory, clear it first.
6449 : That will avoid wasting cycles preserving any padding bits
6450 : that might be there, and if there aren't any, the compiler
6451 : is smart enough to optimize the clearing out. */
6452 808477 : else if ((complete_p.sparse || complete_p.padded_union
6453 807989 : || complete_p.padded_non_union)
6454 14988 : && !TREE_ADDRESSABLE (ctor)
6455 14974 : && !TREE_THIS_VOLATILE (object)
6456 14971 : && (TYPE_MODE (type) != BLKmode || TYPE_NO_FORCE_BLK (type))
6457 815741 : && optimize)
6458 : cleared = true;
6459 : else
6460 : cleared = false;
6461 :
6462 : /* If there are "lots" of initialized elements, and all of them
6463 : are valid address constants, then the entire initializer can
6464 : be dropped to memory, and then memcpy'd out. Don't do this
6465 : for sparse arrays, though, as it's more efficient to follow
6466 : the standard CONSTRUCTOR behavior of memset followed by
6467 : individual element initialization. Also don't do this for small
6468 : all-zero initializers (which aren't big enough to merit
6469 : clearing), and don't try to make bitwise copies of
6470 : TREE_ADDRESSABLE types. */
6471 1001958 : if (valid_const_initializer
6472 619531 : && !complete_p.sparse
6473 442210 : && !(cleared || num_nonzero_elements == 0)
6474 345059 : && !TREE_ADDRESSABLE (type))
6475 : {
6476 343176 : HOST_WIDE_INT size = int_size_in_bytes (type);
6477 343176 : unsigned int align;
6478 :
6479 : /* ??? We can still get unbounded array types, at least
6480 : from the C++ front end. This seems wrong, but attempt
6481 : to work around it for now. */
6482 343176 : if (size < 0)
6483 : {
6484 9 : size = int_size_in_bytes (TREE_TYPE (object));
6485 9 : if (size >= 0)
6486 0 : TREE_TYPE (ctor) = type = TREE_TYPE (object);
6487 : }
6488 :
6489 : /* Find the maximum alignment we can assume for the object. */
6490 : /* ??? Make use of DECL_OFFSET_ALIGN. */
6491 343176 : if (DECL_P (object))
6492 328820 : align = DECL_ALIGN (object);
6493 : else
6494 14356 : align = TYPE_ALIGN (type);
6495 :
6496 : /* Do a block move either if the size is so small as to make
6497 : each individual move a sub-unit move on average, or if it
6498 : is so large as to make individual moves inefficient. */
6499 343176 : if (size > 0
6500 343167 : && num_nonzero_elements > 1
6501 : /* For ctors that have many repeated nonzero elements
6502 : represented through RANGE_EXPRs, prefer initializing
6503 : those through runtime loops over copies of large amounts
6504 : of data from readonly data section. */
6505 303779 : && (num_unique_nonzero_elements
6506 303779 : > num_nonzero_elements / unique_nonzero_ratio
6507 56 : || size <= min_unique_size)
6508 646899 : && (size < num_nonzero_elements
6509 303617 : || !can_move_by_pieces (size, align)))
6510 : {
6511 2746 : if (notify_temp_creation)
6512 : return GS_ERROR;
6513 :
6514 1375 : walk_tree (&ctor, force_labels_r, NULL, NULL);
6515 1375 : ctor = tree_output_constant_def (ctor);
6516 1375 : if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
6517 0 : ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
6518 1375 : TREE_OPERAND (*expr_p, 1) = ctor;
6519 :
6520 : /* This is no longer an assignment of a CONSTRUCTOR, but
6521 : we still may have processing to do on the LHS. So
6522 : pretend we didn't do anything here to let that happen. */
6523 1375 : return GS_UNHANDLED;
6524 : }
6525 : }
6526 :
6527 994339 : if (!cleared)
6528 : {
6529 799244 : if (complete_p.padded_non_union
6530 7927 : && warn_zero_init_padding_bits >= ZERO_INIT_PADDING_BITS_ALL)
6531 12 : warning (OPT_Wzero_init_padding_bits_,
6532 : "padding might not be initialized to zero; "
6533 : "if code relies on it being zero, consider "
6534 : "using %<-fzero-init-padding-bits=all%>");
6535 799232 : else if (complete_p.padded_union
6536 120 : && warn_zero_init_padding_bits
6537 : >= ZERO_INIT_PADDING_BITS_UNIONS)
6538 14 : warning (OPT_Wzero_init_padding_bits_,
6539 : "padding might not be initialized to zero; "
6540 : "if code relies on it being zero, consider "
6541 : "using %<-fzero-init-padding-bits=unions%> "
6542 : "or %<-fzero-init-padding-bits=all%>");
6543 : }
6544 :
6545 : /* If a single access to the target must be ensured and there are
6546 : nonzero elements or the zero elements are not assigned en masse,
6547 : initialize the target from a temporary. */
6548 999212 : if (ensure_single_access && (num_nonzero_elements > 0 || !cleared))
6549 : {
6550 167 : if (notify_temp_creation)
6551 : return GS_ERROR;
6552 :
6553 161 : tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type));
6554 161 : TREE_OPERAND (*expr_p, 0) = temp;
6555 161 : *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
6556 : *expr_p,
6557 : build2 (MODIFY_EXPR, void_type_node,
6558 : object, temp));
6559 161 : return GS_OK;
6560 : }
6561 :
6562 999045 : if (notify_temp_creation)
6563 : return GS_OK;
6564 :
6565 : /* If there are nonzero elements and if needed, pre-evaluate to capture
6566 : elements overlapping with the lhs into temporaries. We must do this
6567 : before clearing to fetch the values before they are zeroed-out. */
6568 991795 : if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
6569 : {
6570 220056 : preeval_data.lhs_base_decl = get_base_address (object);
6571 220056 : if (!DECL_P (preeval_data.lhs_base_decl))
6572 41350 : preeval_data.lhs_base_decl = NULL;
6573 220056 : preeval_data.lhs_alias_set = get_alias_set (object);
6574 :
6575 220056 : gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
6576 : pre_p, post_p, &preeval_data);
6577 : }
6578 :
6579 991795 : bool ctor_has_side_effects_p
6580 991795 : = TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1));
6581 :
6582 991795 : if (cleared)
6583 : {
6584 : /* Zap the CONSTRUCTOR element list, which simplifies this case.
6585 : Note that we still have to gimplify, in order to handle the
6586 : case of variable sized types. Avoid shared tree structures. */
6587 199723 : CONSTRUCTOR_ELTS (ctor) = NULL;
6588 199723 : TREE_SIDE_EFFECTS (ctor) = 0;
6589 199723 : object = unshare_expr (object);
6590 199723 : gimplify_stmt (expr_p, pre_p);
6591 : }
6592 :
6593 : /* If we have not block cleared the object, or if there are nonzero
6594 : elements in the constructor, or if the constructor has side effects,
6595 : add assignments to the individual scalar fields of the object. */
6596 199723 : if (!cleared
6597 199723 : || num_nonzero_elements > 0
6598 20708 : || ctor_has_side_effects_p)
6599 971483 : gimplify_init_ctor_eval (object, elts, pre_p, cleared);
6600 :
6601 991795 : *expr_p = NULL_TREE;
6602 : }
6603 991795 : break;
6604 :
6605 0 : case COMPLEX_TYPE:
6606 0 : {
6607 0 : tree r, i;
6608 :
6609 0 : if (notify_temp_creation)
6610 : return GS_OK;
6611 :
6612 : /* Extract the real and imaginary parts out of the ctor. */
6613 0 : gcc_assert (elts->length () == 2);
6614 0 : r = (*elts)[0].value;
6615 0 : i = (*elts)[1].value;
6616 0 : if (r == NULL || i == NULL)
6617 : {
6618 0 : tree zero = build_zero_cst (TREE_TYPE (type));
6619 0 : if (r == NULL)
6620 0 : r = zero;
6621 0 : if (i == NULL)
6622 0 : i = zero;
6623 : }
6624 :
6625 : /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to
6626 : represent creation of a complex value. */
6627 0 : if (TREE_CONSTANT (r) && TREE_CONSTANT (i))
6628 : {
6629 0 : ctor = build_complex (type, r, i);
6630 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6631 : }
6632 : else
6633 : {
6634 0 : ctor = build2 (COMPLEX_EXPR, type, r, i);
6635 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6636 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1),
6637 : pre_p,
6638 : post_p,
6639 0 : rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
6640 : fb_rvalue);
6641 : }
6642 : }
6643 : break;
6644 :
6645 8702 : case VECTOR_TYPE:
6646 8702 : {
6647 8702 : unsigned HOST_WIDE_INT ix;
6648 8702 : constructor_elt *ce;
6649 :
6650 8702 : if (notify_temp_creation)
6651 1354076 : return GS_OK;
6652 :
6653 : /* Vector types use CONSTRUCTOR all the way through gimple
6654 : compilation as a general initializer. */
6655 75894 : FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
6656 : {
6657 67192 : enum gimplify_status tret;
6658 67192 : tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
6659 : fb_rvalue);
6660 67192 : if (tret == GS_ERROR)
6661 : ret = GS_ERROR;
6662 67191 : else if (TREE_STATIC (ctor)
6663 67224 : && !initializer_constant_valid_p (ce->value,
6664 33 : TREE_TYPE (ce->value)))
6665 33 : TREE_STATIC (ctor) = 0;
6666 : }
6667 8702 : recompute_constructor_flags (ctor);
6668 :
6669 : /* Go ahead and simplify constant constructors to VECTOR_CST. */
6670 8702 : if (TREE_CONSTANT (ctor))
6671 : {
6672 2705 : bool constant_p = true;
6673 : tree value;
6674 :
6675 : /* Even when ctor is constant, it might contain non-*_CST
6676 : elements, such as addresses or trapping values like
6677 : 1.0/0.0 - 1.0/0.0. Such expressions don't belong
6678 : in VECTOR_CST nodes. */
6679 2705 : FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
6680 2483 : if (!CONSTANT_CLASS_P (value))
6681 : {
6682 : constant_p = false;
6683 : break;
6684 : }
6685 :
6686 222 : if (constant_p)
6687 : {
6688 222 : TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts);
6689 222 : break;
6690 : }
6691 : }
6692 :
6693 8480 : if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
6694 944 : TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
6695 : }
6696 : break;
6697 :
6698 0 : default:
6699 : /* So how did we get a CONSTRUCTOR for a scalar type? */
6700 0 : gcc_unreachable ();
6701 : }
6702 :
6703 1343865 : if (ret == GS_ERROR)
6704 : return GS_ERROR;
6705 : /* If we have gimplified both sides of the initializer but have
6706 : not emitted an assignment, do so now. */
6707 1343864 : if (*expr_p
6708 : /* If the type is an empty type, we don't need to emit the
6709 : assignment. */
6710 1343864 : && !is_empty_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
6711 : {
6712 344030 : tree lhs = TREE_OPERAND (*expr_p, 0);
6713 344030 : tree rhs = TREE_OPERAND (*expr_p, 1);
6714 344030 : if (want_value && object == lhs)
6715 12 : lhs = unshare_expr (lhs);
6716 344030 : gassign *init = gimple_build_assign (lhs, rhs);
6717 344030 : gimplify_seq_add_stmt (pre_p, init);
6718 : }
6719 1343864 : if (want_value)
6720 : {
6721 : *expr_p = object;
6722 1343864 : ret = GS_OK;
6723 : }
6724 : else
6725 : {
6726 1343845 : *expr_p = NULL;
6727 1343845 : ret = GS_ALL_DONE;
6728 : }
6729 :
6730 : /* If the user requests to initialize automatic variables, we
6731 : should initialize paddings inside the variable. Add a call to
6732 : __builtin_clear_pading (&object, 0, for_auto_init = true) to
6733 : initialize paddings of object always to zero regardless of
6734 : INIT_TYPE. Note, we will not insert this call if the aggregate
6735 : variable has be completely cleared already or it's initialized
6736 : with an empty constructor. We cannot insert this call if the
6737 : variable is a gimple register since __builtin_clear_padding will take
6738 : the address of the variable. As a result, if a long double/_Complex long
6739 : double variable will be spilled into stack later, its padding cannot
6740 : be cleared with __builtin_clear_padding. We should clear its padding
6741 : when it is spilled into memory. */
6742 1343864 : if (is_init_expr
6743 955790 : && !is_gimple_reg (object)
6744 950356 : && clear_padding_type_may_have_padding_p (type)
6745 905119 : && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
6746 229881 : || !AGGREGATE_TYPE_P (type))
6747 675238 : && var_needs_auto_init_p (object)
6748 1379585 : && flag_auto_var_init != AUTO_INIT_CXX26)
6749 41 : gimple_add_padding_init_for_auto_var (object, false, pre_p);
6750 :
6751 : return ret;
6752 : }
6753 :
6754 : /* Given a pointer value OP0, return a simplified version of an
6755 : indirection through OP0, or NULL_TREE if no simplification is
6756 : possible. This may only be applied to a rhs of an expression.
6757 : Note that the resulting type may be different from the type pointed
6758 : to in the sense that it is still compatible from the langhooks
6759 : point of view. */
6760 :
6761 : static tree
6762 533116 : gimple_fold_indirect_ref_rhs (tree t)
6763 : {
6764 0 : return gimple_fold_indirect_ref (t);
6765 : }
6766 :
6767 : /* Subroutine of gimplify_modify_expr to do simplifications of
6768 : MODIFY_EXPRs based on the code of the RHS. We loop for as long as
6769 : something changes. */
6770 :
6771 : static enum gimplify_status
6772 99328693 : gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
6773 : gimple_seq *pre_p, gimple_seq *post_p,
6774 : bool want_value)
6775 : {
6776 99328693 : enum gimplify_status ret = GS_UNHANDLED;
6777 99985823 : bool changed;
6778 :
6779 98487572 : do
6780 : {
6781 99985823 : changed = false;
6782 99985823 : switch (TREE_CODE (*from_p))
6783 : {
6784 12031594 : case VAR_DECL:
6785 : /* If we're assigning from a read-only variable initialized with
6786 : a constructor and not volatile, do the direct assignment from
6787 : the constructor, but only if the target is not volatile either
6788 : since this latter assignment might end up being done on a per
6789 : field basis. However, if the target is volatile and the type
6790 : is aggregate and non-addressable, gimplify_init_constructor
6791 : knows that it needs to ensure a single access to the target
6792 : and it will return GS_OK only in this case. */
6793 12031594 : if (TREE_READONLY (*from_p)
6794 95412 : && DECL_INITIAL (*from_p)
6795 61554 : && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR
6796 8675 : && !TREE_THIS_VOLATILE (*from_p)
6797 12040269 : && (!TREE_THIS_VOLATILE (*to_p)
6798 6 : || (AGGREGATE_TYPE_P (TREE_TYPE (*to_p))
6799 6 : && !TREE_ADDRESSABLE (TREE_TYPE (*to_p)))))
6800 : {
6801 8675 : tree old_from = *from_p;
6802 8675 : enum gimplify_status subret;
6803 :
6804 : /* Move the constructor into the RHS. */
6805 8675 : *from_p = unshare_expr (DECL_INITIAL (*from_p));
6806 :
6807 : /* Let's see if gimplify_init_constructor will need to put
6808 : it in memory. */
6809 8675 : subret = gimplify_init_constructor (expr_p, NULL, NULL,
6810 : false, true);
6811 8675 : if (subret == GS_ERROR)
6812 : {
6813 : /* If so, revert the change. */
6814 1377 : *from_p = old_from;
6815 : }
6816 : else
6817 : {
6818 : ret = GS_OK;
6819 : changed = true;
6820 : }
6821 : }
6822 : break;
6823 541348 : case INDIRECT_REF:
6824 541348 : if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
6825 : /* If we have code like
6826 :
6827 : *(const A*)(A*)&x
6828 :
6829 : where the type of "x" is a (possibly cv-qualified variant
6830 : of "A"), treat the entire expression as identical to "x".
6831 : This kind of code arises in C++ when an object is bound
6832 : to a const reference, and if "x" is a TARGET_EXPR we want
6833 : to take advantage of the optimization below. But not if
6834 : the type is TREE_ADDRESSABLE; then C++17 says that the
6835 : TARGET_EXPR needs to be a temporary. */
6836 1066232 : if (tree t
6837 533116 : = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)))
6838 : {
6839 130795 : bool volatile_p = TREE_THIS_VOLATILE (*from_p);
6840 130795 : if (TREE_THIS_VOLATILE (t) != volatile_p)
6841 : {
6842 5 : if (DECL_P (t))
6843 0 : t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
6844 : build_fold_addr_expr (t));
6845 5 : if (REFERENCE_CLASS_P (t))
6846 5 : TREE_THIS_VOLATILE (t) = volatile_p;
6847 : }
6848 130795 : *from_p = t;
6849 130795 : ret = GS_OK;
6850 130795 : changed = true;
6851 : }
6852 : break;
6853 :
6854 199969 : case TARGET_EXPR:
6855 199969 : {
6856 : /* If we are initializing something from a TARGET_EXPR, strip the
6857 : TARGET_EXPR and initialize it directly, if possible. This can't
6858 : be done if the initializer is void, since that implies that the
6859 : temporary is set in some non-trivial way.
6860 :
6861 : ??? What about code that pulls out the temp and uses it
6862 : elsewhere? I think that such code never uses the TARGET_EXPR as
6863 : an initializer. If I'm wrong, we'll die because the temp won't
6864 : have any RTL. In that case, I guess we'll need to replace
6865 : references somehow. */
6866 199969 : tree init = TARGET_EXPR_INITIAL (*from_p);
6867 :
6868 199969 : if (init
6869 199253 : && (TREE_CODE (*expr_p) != MODIFY_EXPR
6870 52058 : || !TARGET_EXPR_NO_ELIDE (*from_p))
6871 399004 : && !VOID_TYPE_P (TREE_TYPE (init)))
6872 : {
6873 183379 : *from_p = init;
6874 183379 : ret = GS_OK;
6875 183379 : changed = true;
6876 : }
6877 : }
6878 : break;
6879 :
6880 335295 : case COMPOUND_EXPR:
6881 : /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
6882 : caught. */
6883 335295 : gimplify_compound_expr (from_p, pre_p, true);
6884 335295 : ret = GS_OK;
6885 335295 : changed = true;
6886 335295 : break;
6887 :
6888 1366225 : case CONSTRUCTOR:
6889 : /* If we already made some changes, let the front end have a
6890 : crack at this before we break it down. */
6891 1366225 : if (ret != GS_UNHANDLED)
6892 : break;
6893 :
6894 : /* If we're initializing from a CONSTRUCTOR, break this into
6895 : individual MODIFY_EXPRs. */
6896 1345401 : ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
6897 : false);
6898 1345401 : return ret;
6899 :
6900 227627 : case COND_EXPR:
6901 : /* If we're assigning to a non-register type, push the assignment
6902 : down into the branches. This is mandatory for ADDRESSABLE types,
6903 : since we cannot generate temporaries for such, but it saves a
6904 : copy in other cases as well.
6905 : Also avoid an extra temporary and copy when assigning to
6906 : a register. */
6907 227627 : if (!is_gimple_reg_type (TREE_TYPE (*from_p))
6908 227627 : || (is_gimple_reg (*to_p) && !gimplify_ctxp->allow_rhs_cond_expr))
6909 : {
6910 : /* This code should mirror the code in gimplify_cond_expr. */
6911 145900 : enum tree_code code = TREE_CODE (*expr_p);
6912 145900 : tree cond = *from_p;
6913 145900 : tree result = *to_p;
6914 :
6915 145900 : ret = gimplify_expr (&result, pre_p, post_p,
6916 : is_gimple_lvalue, fb_lvalue);
6917 145900 : if (ret != GS_ERROR)
6918 145900 : ret = GS_OK;
6919 :
6920 : /* If we are going to write RESULT more than once, clear
6921 : TREE_READONLY flag, otherwise we might incorrectly promote
6922 : the variable to static const and initialize it at compile
6923 : time in one of the branches. */
6924 145900 : if (VAR_P (result)
6925 144878 : && TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node
6926 281705 : && TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6927 135704 : TREE_READONLY (result) = 0;
6928 145900 : if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
6929 136691 : TREE_OPERAND (cond, 1)
6930 273382 : = build2 (code, void_type_node, result,
6931 136691 : TREE_OPERAND (cond, 1));
6932 145900 : if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6933 145799 : TREE_OPERAND (cond, 2)
6934 291598 : = build2 (code, void_type_node, unshare_expr (result),
6935 145799 : TREE_OPERAND (cond, 2));
6936 :
6937 145900 : TREE_TYPE (cond) = void_type_node;
6938 145900 : recalculate_side_effects (cond);
6939 :
6940 145900 : if (want_value)
6941 : {
6942 68 : gimplify_and_add (cond, pre_p);
6943 68 : *expr_p = unshare_expr (result);
6944 : }
6945 : else
6946 : *expr_p = cond;
6947 145900 : return ret;
6948 : }
6949 : break;
6950 :
6951 10373877 : case CALL_EXPR:
6952 : /* For calls that return in memory, give *to_p as the CALL_EXPR's
6953 : return slot so that we don't generate a temporary. */
6954 10373877 : if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
6955 10373877 : && aggregate_value_p (*from_p, *from_p))
6956 : {
6957 253727 : bool use_target;
6958 :
6959 253727 : if (!(rhs_predicate_for (*to_p))(*from_p))
6960 : /* If we need a temporary, *to_p isn't accurate. */
6961 : use_target = false;
6962 : /* It's OK to use the return slot directly unless it's an NRV. */
6963 252906 : else if (TREE_CODE (*to_p) == RESULT_DECL
6964 6779 : && DECL_NAME (*to_p) == NULL_TREE
6965 259541 : && needs_to_live_in_memory (*to_p))
6966 : use_target = true;
6967 246271 : else if (is_gimple_reg_type (TREE_TYPE (*to_p))
6968 246271 : || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
6969 : /* Don't force regs into memory. */
6970 : use_target = false;
6971 231713 : else if (TREE_CODE (*expr_p) == INIT_EXPR)
6972 : /* It's OK to use the target directly if it's being
6973 : initialized. */
6974 : use_target = true;
6975 14653 : else if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p)))
6976 : != INTEGER_CST)
6977 : /* Always use the target and thus RSO for variable-sized types.
6978 : GIMPLE cannot deal with a variable-sized assignment
6979 : embedded in a call statement. */
6980 : use_target = true;
6981 14625 : else if (TREE_CODE (*to_p) != SSA_NAME
6982 14625 : && (!is_gimple_variable (*to_p)
6983 11288 : || needs_to_live_in_memory (*to_p)))
6984 : /* Don't use the original target if it's already addressable;
6985 : if its address escapes, and the called function uses the
6986 : NRV optimization, a conforming program could see *to_p
6987 : change before the called function returns; see c++/19317.
6988 : When optimizing, the return_slot pass marks more functions
6989 : as safe after we have escape info. */
6990 : use_target = false;
6991 : else
6992 : use_target = true;
6993 :
6994 : if (use_target)
6995 : {
6996 225914 : CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
6997 225914 : mark_addressable (*to_p);
6998 : }
6999 : }
7000 : break;
7001 :
7002 1560 : case WITH_SIZE_EXPR:
7003 : /* Likewise for calls that return an aggregate of non-constant size,
7004 : since we would not be able to generate a temporary at all. */
7005 1560 : if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
7006 : {
7007 350 : *from_p = TREE_OPERAND (*from_p, 0);
7008 : /* We don't change ret in this case because the
7009 : WITH_SIZE_EXPR might have been added in
7010 : gimplify_modify_expr, so returning GS_OK would lead to an
7011 : infinite loop. */
7012 350 : changed = true;
7013 : }
7014 : break;
7015 :
7016 : /* If we're initializing from a container, push the initialization
7017 : inside it. */
7018 1994 : case CLEANUP_POINT_EXPR:
7019 1994 : case BIND_EXPR:
7020 1994 : case STATEMENT_LIST:
7021 1994 : {
7022 1994 : tree wrap = *from_p;
7023 1994 : tree t;
7024 :
7025 1994 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
7026 : fb_lvalue);
7027 1994 : if (ret != GS_ERROR)
7028 1994 : ret = GS_OK;
7029 :
7030 1994 : t = voidify_wrapper_expr (wrap, *expr_p);
7031 1994 : gcc_assert (t == *expr_p);
7032 :
7033 1994 : if (want_value)
7034 : {
7035 6 : gimplify_and_add (wrap, pre_p);
7036 6 : *expr_p = unshare_expr (*to_p);
7037 : }
7038 : else
7039 1988 : *expr_p = wrap;
7040 : return GS_OK;
7041 : }
7042 :
7043 9841463 : case NOP_EXPR:
7044 : /* Pull out compound literal expressions from a NOP_EXPR.
7045 : Those are created in the C FE to drop qualifiers during
7046 : lvalue conversion. */
7047 9841463 : if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR)
7048 9841463 : && tree_ssa_useless_type_conversion (*from_p))
7049 : {
7050 13 : *from_p = TREE_OPERAND (*from_p, 0);
7051 13 : ret = GS_OK;
7052 13 : changed = true;
7053 : }
7054 : break;
7055 :
7056 4956 : case COMPOUND_LITERAL_EXPR:
7057 4956 : {
7058 4956 : tree complit = TREE_OPERAND (*expr_p, 1);
7059 4956 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
7060 4956 : tree decl = DECL_EXPR_DECL (decl_s);
7061 4956 : tree init = DECL_INITIAL (decl);
7062 :
7063 : /* struct T x = (struct T) { 0, 1, 2 } can be optimized
7064 : into struct T x = { 0, 1, 2 } if the address of the
7065 : compound literal has never been taken. */
7066 4956 : if (!TREE_ADDRESSABLE (complit)
7067 4956 : && !TREE_ADDRESSABLE (decl)
7068 4956 : && init)
7069 : {
7070 4956 : *expr_p = copy_node (*expr_p);
7071 4956 : TREE_OPERAND (*expr_p, 1) = init;
7072 4956 : return GS_OK;
7073 : }
7074 : }
7075 :
7076 : default:
7077 : break;
7078 : }
7079 : }
7080 : while (changed);
7081 :
7082 : return ret;
7083 : }
7084 :
7085 :
7086 : /* Return true if T looks like a valid GIMPLE statement. */
7087 :
7088 : static bool
7089 19697441 : is_gimple_stmt (tree t)
7090 : {
7091 19697441 : const enum tree_code code = TREE_CODE (t);
7092 :
7093 19697441 : switch (code)
7094 : {
7095 1775837 : case NOP_EXPR:
7096 : /* The only valid NOP_EXPR is the empty statement. */
7097 1775837 : return IS_EMPTY_STMT (t);
7098 :
7099 0 : case BIND_EXPR:
7100 0 : case COND_EXPR:
7101 : /* These are only valid if they're void. */
7102 0 : return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
7103 :
7104 : case SWITCH_EXPR:
7105 : case GOTO_EXPR:
7106 : case RETURN_EXPR:
7107 : case LABEL_EXPR:
7108 : case CASE_LABEL_EXPR:
7109 : case TRY_CATCH_EXPR:
7110 : case TRY_FINALLY_EXPR:
7111 : case EH_FILTER_EXPR:
7112 : case CATCH_EXPR:
7113 : case ASM_EXPR:
7114 : case STATEMENT_LIST:
7115 : case OACC_PARALLEL:
7116 : case OACC_KERNELS:
7117 : case OACC_SERIAL:
7118 : case OACC_DATA:
7119 : case OACC_HOST_DATA:
7120 : case OACC_DECLARE:
7121 : case OACC_UPDATE:
7122 : case OACC_ENTER_DATA:
7123 : case OACC_EXIT_DATA:
7124 : case OACC_CACHE:
7125 : case OMP_PARALLEL:
7126 : case OMP_FOR:
7127 : case OMP_SIMD:
7128 : case OMP_DISTRIBUTE:
7129 : case OMP_LOOP:
7130 : case OMP_TILE:
7131 : case OMP_UNROLL:
7132 : case OACC_LOOP:
7133 : case OMP_SCAN:
7134 : case OMP_SCOPE:
7135 : case OMP_DISPATCH:
7136 : case OMP_SECTIONS:
7137 : case OMP_SECTION:
7138 : case OMP_STRUCTURED_BLOCK:
7139 : case OMP_SINGLE:
7140 : case OMP_MASTER:
7141 : case OMP_MASKED:
7142 : case OMP_TASKGROUP:
7143 : case OMP_ORDERED:
7144 : case OMP_CRITICAL:
7145 : case OMP_METADIRECTIVE:
7146 : case OMP_TASK:
7147 : case OMP_TARGET:
7148 : case OMP_TARGET_DATA:
7149 : case OMP_TARGET_UPDATE:
7150 : case OMP_TARGET_ENTER_DATA:
7151 : case OMP_TARGET_EXIT_DATA:
7152 : case OMP_TASKLOOP:
7153 : case OMP_TEAMS:
7154 : /* These are always void. */
7155 : return true;
7156 :
7157 : case CALL_EXPR:
7158 : case MODIFY_EXPR:
7159 : case PREDICT_EXPR:
7160 : /* These are valid regardless of their type. */
7161 : return true;
7162 :
7163 : default:
7164 : return false;
7165 : }
7166 : }
7167 :
7168 :
7169 : /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
7170 : a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
7171 :
7172 : IMPORTANT NOTE: This promotion is performed by introducing a load of the
7173 : other, unmodified part of the complex object just before the total store.
7174 : As a consequence, if the object is still uninitialized, an undefined value
7175 : will be loaded into a register, which may result in a spurious exception
7176 : if the register is floating-point and the value happens to be a signaling
7177 : NaN for example. Then the fully-fledged complex operations lowering pass
7178 : followed by a DCE pass are necessary in order to fix things up. */
7179 :
7180 : static enum gimplify_status
7181 1942 : gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
7182 : bool want_value)
7183 : {
7184 1942 : enum tree_code code, ocode;
7185 1942 : tree lhs, rhs, new_rhs, other, realpart, imagpart;
7186 :
7187 1942 : lhs = TREE_OPERAND (*expr_p, 0);
7188 1942 : rhs = TREE_OPERAND (*expr_p, 1);
7189 1942 : code = TREE_CODE (lhs);
7190 1942 : lhs = TREE_OPERAND (lhs, 0);
7191 :
7192 1942 : ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
7193 1942 : other = build1 (ocode, TREE_TYPE (rhs), lhs);
7194 1942 : suppress_warning (other);
7195 1942 : other = get_formal_tmp_var (other, pre_p);
7196 :
7197 1942 : realpart = code == REALPART_EXPR ? rhs : other;
7198 957 : imagpart = code == REALPART_EXPR ? other : rhs;
7199 :
7200 1942 : if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
7201 0 : new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
7202 : else
7203 1942 : new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
7204 :
7205 1942 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
7206 1942 : *expr_p = (want_value) ? rhs : NULL_TREE;
7207 :
7208 1942 : return GS_ALL_DONE;
7209 : }
7210 :
7211 : /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
7212 :
7213 : modify_expr
7214 : : varname '=' rhs
7215 : | '*' ID '=' rhs
7216 :
7217 : PRE_P points to the list where side effects that must happen before
7218 : *EXPR_P should be stored.
7219 :
7220 : POST_P points to the list where side effects that must happen after
7221 : *EXPR_P should be stored.
7222 :
7223 : WANT_VALUE is nonzero iff we want to use the value of this expression
7224 : in another expression. */
7225 :
7226 : static enum gimplify_status
7227 51338796 : gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
7228 : bool want_value)
7229 : {
7230 51338796 : tree *from_p = &TREE_OPERAND (*expr_p, 1);
7231 51338796 : tree *to_p = &TREE_OPERAND (*expr_p, 0);
7232 51338796 : enum gimplify_status ret = GS_UNHANDLED;
7233 51338796 : gimple *assign;
7234 51338796 : location_t loc = EXPR_LOCATION (*expr_p);
7235 51338796 : gimple_stmt_iterator gsi;
7236 :
7237 51338796 : if (error_operand_p (*from_p) || error_operand_p (*to_p))
7238 : return GS_ERROR;
7239 :
7240 51338768 : gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
7241 : || TREE_CODE (*expr_p) == INIT_EXPR);
7242 :
7243 : /* Trying to simplify a clobber using normal logic doesn't work,
7244 : so handle it here. */
7245 51338768 : if (TREE_CLOBBER_P (*from_p))
7246 : {
7247 632860 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7248 632860 : if (ret == GS_ERROR)
7249 : return ret;
7250 632860 : gcc_assert (!want_value);
7251 632860 : if (!VAR_P (*to_p) && TREE_CODE (*to_p) != MEM_REF)
7252 : {
7253 208 : tree addr = get_initialized_tmp_var (build_fold_addr_expr (*to_p),
7254 : pre_p, post_p);
7255 208 : *to_p = build_simple_mem_ref_loc (EXPR_LOCATION (*to_p), addr);
7256 : }
7257 632860 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
7258 632860 : *expr_p = NULL;
7259 632860 : return GS_ALL_DONE;
7260 : }
7261 :
7262 : /* Convert initialization from an empty variable-size CONSTRUCTOR to
7263 : memset. */
7264 50705908 : if (TREE_TYPE (*from_p) != error_mark_node
7265 50705908 : && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
7266 50705908 : && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
7267 1593 : && TREE_CODE (*from_p) == CONSTRUCTOR
7268 50706012 : && CONSTRUCTOR_NELTS (*from_p) == 0)
7269 : {
7270 84 : maybe_with_size_expr (from_p);
7271 84 : gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
7272 84 : return gimplify_modify_expr_to_memset (expr_p,
7273 84 : TREE_OPERAND (*from_p, 1),
7274 84 : want_value, pre_p);
7275 : }
7276 :
7277 : /* Insert pointer conversions required by the middle-end that are not
7278 : required by the frontend. This fixes middle-end type checking for
7279 : for example gcc.dg/redecl-6.c. */
7280 50705824 : if (POINTER_TYPE_P (TREE_TYPE (*to_p)))
7281 : {
7282 13789318 : STRIP_USELESS_TYPE_CONVERSION (*from_p);
7283 13789318 : if (!useless_type_conversion_p (TREE_TYPE (*to_p), TREE_TYPE (*from_p)))
7284 754 : *from_p = fold_convert_loc (loc, TREE_TYPE (*to_p), *from_p);
7285 : }
7286 :
7287 : /* See if any simplifications can be done based on what the RHS is. */
7288 50705824 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7289 : want_value);
7290 50705824 : if (ret != GS_UNHANDLED)
7291 : return ret;
7292 :
7293 : /* For empty types only gimplify the left hand side and right hand
7294 : side as statements and throw away the assignment. Do this after
7295 : gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable
7296 : types properly. */
7297 48625153 : if (is_empty_type (TREE_TYPE (*from_p))
7298 13733 : && !want_value
7299 : /* Don't do this for calls that return addressable types, expand_call
7300 : relies on those having a lhs. */
7301 48638879 : && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
7302 11667 : && TREE_CODE (*from_p) == CALL_EXPR))
7303 : {
7304 2059 : suppress_warning (*from_p, OPT_Wunused_result);
7305 2059 : gimplify_stmt (from_p, pre_p);
7306 2059 : gimplify_stmt (to_p, pre_p);
7307 2059 : *expr_p = NULL_TREE;
7308 2059 : return GS_ALL_DONE;
7309 : }
7310 :
7311 : /* If the value being copied is of variable width, compute the length
7312 : of the copy into a WITH_SIZE_EXPR. Note that we need to do this
7313 : before gimplifying any of the operands so that we can resolve any
7314 : PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
7315 : the size of the expression to be copied, not of the destination, so
7316 : that is what we must do here. */
7317 48623094 : maybe_with_size_expr (from_p);
7318 :
7319 : /* As a special case, we have to temporarily allow for assignments
7320 : with a CALL_EXPR on the RHS. Since in GIMPLE a function call is
7321 : a toplevel statement, when gimplifying the GENERIC expression
7322 : MODIFY_EXPR <a, CALL_EXPR <foo>>, we cannot create the tuple
7323 : GIMPLE_ASSIGN <a, GIMPLE_CALL <foo>>.
7324 :
7325 : Instead, we need to create the tuple GIMPLE_CALL <a, foo>. To
7326 : prevent gimplify_expr from trying to create a new temporary for
7327 : foo's LHS, we tell it that it should only gimplify until it
7328 : reaches the CALL_EXPR. On return from gimplify_expr, the newly
7329 : created GIMPLE_CALL <foo> will be the last statement in *PRE_P
7330 : and all we need to do here is set 'a' to be its LHS. */
7331 :
7332 : /* Gimplify the RHS first for C++17 and bug 71104. */
7333 48623094 : gimple_predicate initial_pred = initial_rhs_predicate_for (*to_p);
7334 48623094 : ret = gimplify_expr (from_p, pre_p, post_p, initial_pred, fb_rvalue);
7335 48623094 : if (ret == GS_ERROR)
7336 : return ret;
7337 :
7338 : /* Then gimplify the LHS. */
7339 : /* If we gimplified the RHS to a CALL_EXPR and that call may return
7340 : twice we have to make sure to gimplify into non-SSA as otherwise
7341 : the abnormal edge added later will make those defs not dominate
7342 : their uses.
7343 : ??? Technically this applies only to the registers used in the
7344 : resulting non-register *TO_P. */
7345 48622944 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
7346 48622944 : if (saved_into_ssa
7347 46228697 : && TREE_CODE (*from_p) == CALL_EXPR
7348 53910203 : && call_expr_flags (*from_p) & ECF_RETURNS_TWICE)
7349 1539 : gimplify_ctxp->into_ssa = false;
7350 48622944 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7351 48622944 : gimplify_ctxp->into_ssa = saved_into_ssa;
7352 48622944 : if (ret == GS_ERROR)
7353 : return ret;
7354 :
7355 : /* Now that the LHS is gimplified, re-gimplify the RHS if our initial
7356 : guess for the predicate was wrong. */
7357 48622869 : gimple_predicate final_pred = rhs_predicate_for (*to_p);
7358 48622869 : if (final_pred != initial_pred)
7359 : {
7360 8258957 : ret = gimplify_expr (from_p, pre_p, post_p, final_pred, fb_rvalue);
7361 8258957 : if (ret == GS_ERROR)
7362 : return ret;
7363 : }
7364 :
7365 : /* In case of va_arg internal fn wrapped in a WITH_SIZE_EXPR, add the type
7366 : size as argument to the call. */
7367 48622869 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7368 : {
7369 1457 : tree call = TREE_OPERAND (*from_p, 0);
7370 1457 : tree vlasize = TREE_OPERAND (*from_p, 1);
7371 :
7372 1457 : if (TREE_CODE (call) == CALL_EXPR
7373 1457 : && CALL_EXPR_IFN (call) == IFN_VA_ARG)
7374 : {
7375 95 : int nargs = call_expr_nargs (call);
7376 95 : tree type = TREE_TYPE (call);
7377 95 : tree ap = CALL_EXPR_ARG (call, 0);
7378 95 : tree tag = CALL_EXPR_ARG (call, 1);
7379 95 : tree aptag = CALL_EXPR_ARG (call, 2);
7380 95 : tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
7381 : IFN_VA_ARG, type,
7382 : nargs + 1, ap, tag,
7383 : aptag, vlasize);
7384 95 : TREE_OPERAND (*from_p, 0) = newcall;
7385 : }
7386 : }
7387 :
7388 : /* Now see if the above changed *from_p to something we handle specially. */
7389 48622869 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7390 : want_value);
7391 48622869 : if (ret != GS_UNHANDLED)
7392 : return ret;
7393 :
7394 : /* If we've got a variable sized assignment between two lvalues (i.e. does
7395 : not involve a call), then we can make things a bit more straightforward
7396 : by converting the assignment to memcpy or memset. */
7397 48621906 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7398 : {
7399 1107 : tree from = TREE_OPERAND (*from_p, 0);
7400 1107 : tree size = TREE_OPERAND (*from_p, 1);
7401 :
7402 1107 : if (TREE_CODE (from) == CONSTRUCTOR)
7403 0 : return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
7404 1107 : else if (is_gimple_addressable (from)
7405 1107 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (*to_p)))
7406 2213 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))))
7407 : {
7408 1106 : *from_p = from;
7409 1106 : return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
7410 1106 : pre_p);
7411 : }
7412 : }
7413 :
7414 : /* Transform partial stores to non-addressable complex variables into
7415 : total stores. This allows us to use real instead of virtual operands
7416 : for these variables, which improves optimization. */
7417 48620800 : if ((TREE_CODE (*to_p) == REALPART_EXPR
7418 48620800 : || TREE_CODE (*to_p) == IMAGPART_EXPR)
7419 48620800 : && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
7420 1942 : return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
7421 :
7422 : /* Try to alleviate the effects of the gimplification creating artificial
7423 : temporaries (see for example is_gimple_reg_rhs) on the debug info, but
7424 : make sure not to create DECL_DEBUG_EXPR links across functions. */
7425 48618858 : if (!gimplify_ctxp->into_ssa
7426 2393321 : && VAR_P (*from_p)
7427 472395 : && DECL_IGNORED_P (*from_p)
7428 351314 : && DECL_P (*to_p)
7429 138578 : && !DECL_IGNORED_P (*to_p)
7430 38239 : && decl_function_context (*to_p) == current_function_decl
7431 48651517 : && decl_function_context (*from_p) == current_function_decl)
7432 : {
7433 32654 : if (!DECL_NAME (*from_p) && DECL_NAME (*to_p))
7434 27363 : DECL_NAME (*from_p)
7435 54726 : = create_tmp_var_name (IDENTIFIER_POINTER (DECL_NAME (*to_p)));
7436 32654 : DECL_HAS_DEBUG_EXPR_P (*from_p) = 1;
7437 32654 : SET_DECL_DEBUG_EXPR (*from_p, *to_p);
7438 : }
7439 :
7440 48618858 : if (want_value && TREE_THIS_VOLATILE (*to_p))
7441 522 : *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
7442 :
7443 48618858 : if (TREE_CODE (*from_p) == CALL_EXPR)
7444 : {
7445 : /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
7446 : instead of a GIMPLE_ASSIGN. */
7447 4964589 : gcall *call_stmt;
7448 4964589 : if (CALL_EXPR_FN (*from_p) == NULL_TREE)
7449 : {
7450 : /* Gimplify internal functions created in the FEs. */
7451 344234 : int nargs = call_expr_nargs (*from_p), i;
7452 344234 : enum internal_fn ifn = CALL_EXPR_IFN (*from_p);
7453 344234 : auto_vec<tree> vargs (nargs);
7454 :
7455 1732502 : for (i = 0; i < nargs; i++)
7456 : {
7457 1044034 : gimplify_arg (&CALL_EXPR_ARG (*from_p, i), pre_p,
7458 1044034 : EXPR_LOCATION (*from_p));
7459 1044034 : vargs.quick_push (CALL_EXPR_ARG (*from_p, i));
7460 : }
7461 344234 : call_stmt = gimple_build_call_internal_vec (ifn, vargs);
7462 344234 : gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p));
7463 688468 : gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p));
7464 344234 : }
7465 : else
7466 : {
7467 4620355 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
7468 4620355 : CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
7469 4620355 : STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
7470 4620355 : tree fndecl = get_callee_fndecl (*from_p);
7471 4620355 : if (fndecl
7472 4504565 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
7473 4759272 : && call_expr_nargs (*from_p) == 3)
7474 67925 : call_stmt = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3,
7475 67925 : CALL_EXPR_ARG (*from_p, 0),
7476 67925 : CALL_EXPR_ARG (*from_p, 1),
7477 67925 : CALL_EXPR_ARG (*from_p, 2));
7478 : else
7479 : {
7480 4552430 : call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
7481 : }
7482 : }
7483 4964589 : notice_special_calls (call_stmt);
7484 4964589 : if (!gimple_call_noreturn_p (call_stmt) || !should_remove_lhs_p (*to_p))
7485 4964345 : gimple_call_set_lhs (call_stmt, *to_p);
7486 244 : else if (TREE_CODE (*to_p) == SSA_NAME)
7487 : /* The above is somewhat premature, avoid ICEing later for a
7488 : SSA name w/o a definition. We may have uses in the GIMPLE IL.
7489 : ??? This doesn't make it a default-def. */
7490 137 : SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop ();
7491 :
7492 : assign = call_stmt;
7493 : }
7494 : else
7495 : {
7496 43654269 : assign = gimple_build_assign (*to_p, *from_p);
7497 43654269 : gimple_set_location (assign, EXPR_LOCATION (*expr_p));
7498 43654269 : if (COMPARISON_CLASS_P (*from_p))
7499 1258396 : copy_warning (assign, *from_p);
7500 : }
7501 :
7502 48618858 : if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
7503 : {
7504 : /* We should have got an SSA name from the start. */
7505 35983286 : gcc_assert (TREE_CODE (*to_p) == SSA_NAME
7506 : || ! gimple_in_ssa_p (cfun));
7507 : }
7508 :
7509 48618858 : gimplify_seq_add_stmt (pre_p, assign);
7510 48618858 : gsi = gsi_last (*pre_p);
7511 48618858 : maybe_fold_stmt (&gsi);
7512 :
7513 48618858 : if (want_value)
7514 : {
7515 696031 : *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
7516 696031 : return GS_OK;
7517 : }
7518 : else
7519 47922827 : *expr_p = NULL;
7520 :
7521 47922827 : return GS_ALL_DONE;
7522 : }
7523 :
7524 : /* Gimplify a comparison between two variable-sized objects. Do this
7525 : with a call to BUILT_IN_MEMCMP. */
7526 :
7527 : static enum gimplify_status
7528 0 : gimplify_variable_sized_compare (tree *expr_p)
7529 : {
7530 0 : location_t loc = EXPR_LOCATION (*expr_p);
7531 0 : tree op0 = TREE_OPERAND (*expr_p, 0);
7532 0 : tree op1 = TREE_OPERAND (*expr_p, 1);
7533 0 : tree t, arg, dest, src, expr;
7534 :
7535 0 : arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
7536 0 : arg = unshare_expr (arg);
7537 0 : arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
7538 0 : src = build_fold_addr_expr_loc (loc, op1);
7539 0 : dest = build_fold_addr_expr_loc (loc, op0);
7540 0 : t = builtin_decl_implicit (BUILT_IN_MEMCMP);
7541 0 : t = build_call_expr_loc (loc, t, 3, dest, src, arg);
7542 :
7543 0 : expr
7544 0 : = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
7545 0 : SET_EXPR_LOCATION (expr, loc);
7546 0 : *expr_p = expr;
7547 :
7548 0 : return GS_OK;
7549 : }
7550 :
7551 : /* Gimplify a comparison between two aggregate objects of integral scalar
7552 : mode as a comparison between the bitwise equivalent scalar values. */
7553 :
7554 : static enum gimplify_status
7555 16 : gimplify_scalar_mode_aggregate_compare (tree *expr_p)
7556 : {
7557 16 : const location_t loc = EXPR_LOCATION (*expr_p);
7558 16 : const enum tree_code code = TREE_CODE (*expr_p);
7559 16 : tree op0 = TREE_OPERAND (*expr_p, 0);
7560 16 : tree op1 = TREE_OPERAND (*expr_p, 1);
7561 16 : tree type = TREE_TYPE (op0);
7562 16 : tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
7563 :
7564 16 : op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
7565 16 : op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
7566 :
7567 : /* We need to perform ordering comparisons in memory order like memcmp and,
7568 : therefore, may need to byte-swap operands for little-endian targets. */
7569 16 : if (code != EQ_EXPR && code != NE_EXPR)
7570 : {
7571 0 : gcc_assert (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN);
7572 0 : gcc_assert (TREE_CODE (scalar_type) == INTEGER_TYPE);
7573 0 : tree fndecl;
7574 :
7575 0 : if (BYTES_BIG_ENDIAN)
7576 : fndecl = NULL_TREE;
7577 : else
7578 0 : switch (int_size_in_bytes (scalar_type))
7579 : {
7580 : case 1:
7581 : fndecl = NULL_TREE;
7582 : break;
7583 0 : case 2:
7584 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP16);
7585 : break;
7586 0 : case 4:
7587 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP32);
7588 : break;
7589 0 : case 8:
7590 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP64);
7591 : break;
7592 0 : case 16:
7593 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP128);
7594 : break;
7595 0 : default:
7596 0 : gcc_unreachable ();
7597 : }
7598 :
7599 0 : if (fndecl)
7600 : {
7601 0 : op0 = build_call_expr_loc (loc, fndecl, 1, op0);
7602 0 : op1 = build_call_expr_loc (loc, fndecl, 1, op1);
7603 : }
7604 : }
7605 :
7606 16 : *expr_p = fold_build2_loc (loc, code, TREE_TYPE (*expr_p), op0, op1);
7607 :
7608 16 : return GS_OK;
7609 : }
7610 :
7611 : /* Gimplify an expression sequence. This function gimplifies each
7612 : expression and rewrites the original expression with the last
7613 : expression of the sequence in GIMPLE form.
7614 :
7615 : PRE_P points to the list where the side effects for all the
7616 : expressions in the sequence will be emitted.
7617 :
7618 : WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
7619 :
7620 : static enum gimplify_status
7621 1134828 : gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
7622 : {
7623 1134828 : tree t = *expr_p;
7624 :
7625 1227188 : do
7626 : {
7627 1227188 : tree *sub_p = &TREE_OPERAND (t, 0);
7628 :
7629 1227188 : if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
7630 215151 : gimplify_compound_expr (sub_p, pre_p, false);
7631 : else
7632 1012037 : gimplify_stmt (sub_p, pre_p);
7633 :
7634 1227188 : t = TREE_OPERAND (t, 1);
7635 : }
7636 1227188 : while (TREE_CODE (t) == COMPOUND_EXPR);
7637 :
7638 1134828 : *expr_p = t;
7639 1134828 : if (want_value)
7640 : return GS_OK;
7641 : else
7642 : {
7643 631993 : gimplify_stmt (expr_p, pre_p);
7644 631993 : return GS_ALL_DONE;
7645 : }
7646 : }
7647 :
7648 : /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
7649 : gimplify. After gimplification, EXPR_P will point to a new temporary
7650 : that holds the original value of the SAVE_EXPR node.
7651 :
7652 : PRE_P points to the list where side effects that must happen before
7653 : *EXPR_P should be stored. */
7654 :
7655 : static enum gimplify_status
7656 444592 : gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7657 : {
7658 444592 : enum gimplify_status ret = GS_ALL_DONE;
7659 444592 : tree val;
7660 :
7661 444592 : gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
7662 444592 : val = TREE_OPERAND (*expr_p, 0);
7663 :
7664 444592 : if (val && TREE_TYPE (val) == error_mark_node)
7665 : return GS_ERROR;
7666 :
7667 : /* If the SAVE_EXPR has not been resolved, then evaluate it once. */
7668 444590 : if (!SAVE_EXPR_RESOLVED_P (*expr_p))
7669 : {
7670 : /* The operand may be a void-valued expression. It is
7671 : being executed only for its side-effects. */
7672 170893 : if (TREE_TYPE (val) == void_type_node)
7673 : {
7674 751 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7675 : is_gimple_stmt, fb_none);
7676 751 : val = NULL;
7677 : }
7678 : else
7679 : /* The temporary may not be an SSA name as later abnormal and EH
7680 : control flow may invalidate use/def domination. When in SSA
7681 : form then assume there are no such issues and SAVE_EXPRs only
7682 : appear via GENERIC foldings. */
7683 340284 : val = get_initialized_tmp_var (val, pre_p, post_p,
7684 : gimple_in_ssa_p (cfun));
7685 :
7686 170893 : TREE_OPERAND (*expr_p, 0) = val;
7687 170893 : SAVE_EXPR_RESOLVED_P (*expr_p) = 1;
7688 : }
7689 :
7690 444590 : *expr_p = val;
7691 :
7692 444590 : return ret;
7693 : }
7694 :
7695 : /* Rewrite the ADDR_EXPR node pointed to by EXPR_P
7696 :
7697 : unary_expr
7698 : : ...
7699 : | '&' varname
7700 : ...
7701 :
7702 : PRE_P points to the list where side effects that must happen before
7703 : *EXPR_P should be stored.
7704 :
7705 : POST_P points to the list where side effects that must happen after
7706 : *EXPR_P should be stored. */
7707 :
7708 : static enum gimplify_status
7709 34440966 : gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7710 : {
7711 34440966 : tree expr = *expr_p;
7712 34440966 : tree op0 = TREE_OPERAND (expr, 0);
7713 34440966 : enum gimplify_status ret;
7714 34440966 : location_t loc = EXPR_LOCATION (*expr_p);
7715 :
7716 34440966 : switch (TREE_CODE (op0))
7717 : {
7718 100847 : case INDIRECT_REF:
7719 100847 : do_indirect_ref:
7720 : /* Check if we are dealing with an expression of the form '&*ptr'.
7721 : While the front end folds away '&*ptr' into 'ptr', these
7722 : expressions may be generated internally by the compiler (e.g.,
7723 : builtins like __builtin_va_end). */
7724 : /* Caution: the silent array decomposition semantics we allow for
7725 : ADDR_EXPR means we can't always discard the pair. */
7726 : /* Gimplification of the ADDR_EXPR operand may drop
7727 : cv-qualification conversions, so make sure we add them if
7728 : needed. */
7729 100847 : {
7730 100847 : tree op00 = TREE_OPERAND (op0, 0);
7731 100847 : tree t_expr = TREE_TYPE (expr);
7732 100847 : tree t_op00 = TREE_TYPE (op00);
7733 :
7734 100847 : if (!useless_type_conversion_p (t_expr, t_op00))
7735 0 : op00 = fold_convert_loc (loc, TREE_TYPE (expr), op00);
7736 100847 : *expr_p = op00;
7737 100847 : ret = GS_OK;
7738 : }
7739 100847 : break;
7740 :
7741 0 : case VIEW_CONVERT_EXPR:
7742 : /* Take the address of our operand and then convert it to the type of
7743 : this ADDR_EXPR.
7744 :
7745 : ??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
7746 : all clear. The impact of this transformation is even less clear. */
7747 :
7748 : /* If the operand is a useless conversion, look through it. Doing so
7749 : guarantees that the ADDR_EXPR and its operand will remain of the
7750 : same type. */
7751 0 : if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
7752 0 : op0 = TREE_OPERAND (op0, 0);
7753 :
7754 0 : *expr_p = fold_convert_loc (loc, TREE_TYPE (expr),
7755 : build_fold_addr_expr_loc (loc,
7756 0 : TREE_OPERAND (op0, 0)));
7757 0 : ret = GS_OK;
7758 0 : break;
7759 :
7760 66224 : case MEM_REF:
7761 66224 : if (integer_zerop (TREE_OPERAND (op0, 1)))
7762 37980 : goto do_indirect_ref;
7763 :
7764 : /* fall through */
7765 :
7766 34357565 : default:
7767 : /* If we see a call to a declared builtin or see its address
7768 : being taken (we can unify those cases here) then we can mark
7769 : the builtin for implicit generation by GCC. */
7770 34357565 : if (TREE_CODE (op0) == FUNCTION_DECL
7771 17085496 : && fndecl_built_in_p (op0, BUILT_IN_NORMAL)
7772 38343793 : && builtin_decl_declared_p (DECL_FUNCTION_CODE (op0)))
7773 1300853 : set_builtin_decl_implicit_p (DECL_FUNCTION_CODE (op0), true);
7774 :
7775 : /* We use fb_either here because the C frontend sometimes takes
7776 : the address of a call that returns a struct; see
7777 : gcc.dg/c99-array-lval-1.c. The gimplifier will correctly make
7778 : the implied temporary explicit. */
7779 :
7780 : /* Make the operand addressable. */
7781 34357565 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
7782 : is_gimple_addressable, fb_either);
7783 34357565 : if (ret == GS_ERROR)
7784 : break;
7785 :
7786 : /* Then mark it. Beware that it may not be possible to do so directly
7787 : if a temporary has been created by the gimplification. */
7788 34357561 : prepare_gimple_addressable (&TREE_OPERAND (expr, 0), pre_p);
7789 :
7790 34357561 : op0 = TREE_OPERAND (expr, 0);
7791 :
7792 : /* For various reasons, the gimplification of the expression
7793 : may have made a new INDIRECT_REF. */
7794 34357561 : if (INDIRECT_REF_P (op0)
7795 34357561 : || (TREE_CODE (op0) == MEM_REF
7796 45690 : && integer_zerop (TREE_OPERAND (op0, 1))))
7797 17446 : goto do_indirect_ref;
7798 :
7799 34340115 : mark_addressable (TREE_OPERAND (expr, 0));
7800 :
7801 : /* The FEs may end up building ADDR_EXPRs early on a decl with
7802 : an incomplete type. Re-build ADDR_EXPRs in canonical form
7803 : here. */
7804 34340115 : if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
7805 153404 : *expr_p = build_fold_addr_expr (op0);
7806 :
7807 : /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */
7808 34340115 : if (TREE_CODE (*expr_p) == ADDR_EXPR)
7809 34340115 : recompute_tree_invariant_for_addr_expr (*expr_p);
7810 :
7811 : /* If we re-built the ADDR_EXPR add a conversion to the original type
7812 : if required. */
7813 34340115 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
7814 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
7815 :
7816 : break;
7817 : }
7818 :
7819 34440966 : return ret;
7820 : }
7821 :
7822 : /* Return the number of times character C occurs in string S. */
7823 :
7824 : static int
7825 94940 : num_occurrences (int c, const char *s)
7826 : {
7827 94940 : int n = 0;
7828 257441 : while (*s)
7829 162501 : n += (*s++ == c);
7830 94940 : return n;
7831 : }
7832 :
7833 : /* A subroutine of gimplify_asm_expr. Check that all operands have
7834 : the same number of alternatives. Return -1 if this is violated. Otherwise
7835 : return the number of alternatives. */
7836 :
7837 : static int
7838 166200 : num_alternatives (const_tree link)
7839 : {
7840 166200 : if (link == nullptr)
7841 : return 0;
7842 :
7843 48799 : const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7844 48799 : int num = num_occurrences (',', constraint);
7845 :
7846 48799 : if (num + 1 > MAX_RECOG_ALTERNATIVES)
7847 : return -1;
7848 :
7849 94940 : for (link = TREE_CHAIN (link); link; link = TREE_CHAIN (link))
7850 : {
7851 46141 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7852 92282 : if (num_occurrences (',', constraint) != num)
7853 : return -1;
7854 : }
7855 48799 : return num + 1;
7856 : }
7857 :
7858 : /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple
7859 : value; output operands should be a gimple lvalue. */
7860 :
7861 : static enum gimplify_status
7862 83100 : gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7863 : {
7864 83100 : tree expr;
7865 83100 : int noutputs;
7866 83100 : const char **oconstraints;
7867 83100 : int i;
7868 83100 : tree link;
7869 83100 : const char *constraint;
7870 83100 : bool allows_mem, allows_reg, is_inout;
7871 83100 : enum gimplify_status ret, tret;
7872 83100 : gasm *stmt;
7873 83100 : vec<tree, va_gc> *inputs;
7874 83100 : vec<tree, va_gc> *outputs;
7875 83100 : vec<tree, va_gc> *clobbers;
7876 83100 : vec<tree, va_gc> *labels;
7877 83100 : tree link_next;
7878 :
7879 83100 : expr = *expr_p;
7880 83100 : noutputs = list_length (ASM_OUTPUTS (expr));
7881 83100 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
7882 :
7883 83100 : inputs = NULL;
7884 83100 : outputs = NULL;
7885 83100 : clobbers = NULL;
7886 83100 : labels = NULL;
7887 :
7888 83100 : int num_alternatives_out = num_alternatives (ASM_OUTPUTS (expr));
7889 83100 : int num_alternatives_in = num_alternatives (ASM_INPUTS (expr));
7890 83100 : if (num_alternatives_out == -1 || num_alternatives_in == -1
7891 83100 : || (num_alternatives_out > 0 && num_alternatives_in > 0
7892 17276 : && num_alternatives_out != num_alternatives_in))
7893 : {
7894 0 : error ("operand constraints for %<asm%> differ "
7895 : "in number of alternatives");
7896 0 : return GS_ERROR;
7897 : }
7898 83100 : int num_alternatives = MAX (num_alternatives_out, num_alternatives_in);
7899 :
7900 83100 : gimplify_reg_info reg_info (num_alternatives, noutputs);
7901 :
7902 83100 : link_next = NULL_TREE;
7903 163440 : for (link = ASM_CLOBBERS (expr); link; link = link_next)
7904 : {
7905 : /* The clobber entry could also be an error marker. */
7906 80340 : if (TREE_CODE (TREE_VALUE (link)) == STRING_CST)
7907 : {
7908 80317 : const char *regname= TREE_STRING_POINTER (TREE_VALUE (link));
7909 80317 : int regno = decode_reg_name (regname);
7910 80317 : if (regno >= 0)
7911 41263 : reg_info.set_clobbered (regno);
7912 : }
7913 80340 : link_next = TREE_CHAIN (link);
7914 80340 : TREE_CHAIN (link) = NULL_TREE;
7915 80340 : vec_safe_push (clobbers, link);
7916 : }
7917 :
7918 83100 : ret = GS_ALL_DONE;
7919 83100 : link_next = NULL_TREE;
7920 144340 : for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
7921 : {
7922 61273 : bool ok;
7923 61273 : size_t constraint_len;
7924 :
7925 61273 : if (error_operand_p (TREE_VALUE (link)))
7926 : return GS_ERROR;
7927 61252 : link_next = TREE_CHAIN (link);
7928 :
7929 122504 : oconstraints[i]
7930 61252 : = constraint
7931 61252 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7932 61252 : constraint_len = strlen (constraint);
7933 61252 : if (constraint_len == 0)
7934 0 : continue;
7935 :
7936 61252 : reg_info.operand = TREE_VALUE (link);
7937 61252 : ok = parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
7938 : &allows_reg, &is_inout, ®_info);
7939 61252 : if (!ok)
7940 : {
7941 11 : ret = GS_ERROR;
7942 11 : is_inout = false;
7943 : }
7944 :
7945 : /* If we can't make copies, we can only accept memory.
7946 : Similarly for VLAs. */
7947 61252 : tree outtype = TREE_TYPE (TREE_VALUE (link));
7948 61252 : if (TREE_ADDRESSABLE (outtype)
7949 61229 : || !COMPLETE_TYPE_P (outtype)
7950 122440 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (outtype)))
7951 : {
7952 288 : if (allows_mem)
7953 276 : allows_reg = 0;
7954 : else
7955 : {
7956 12 : error ("impossible constraint in %<asm%>");
7957 12 : error ("non-memory output %d must stay in memory", i);
7958 12 : return GS_ERROR;
7959 : }
7960 : }
7961 :
7962 61240 : if (!allows_reg && allows_mem)
7963 2079 : mark_addressable (TREE_VALUE (link));
7964 :
7965 61240 : tree orig = TREE_VALUE (link);
7966 113760 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
7967 : is_inout ? is_gimple_min_lval : is_gimple_lvalue,
7968 : fb_lvalue | fb_mayfail);
7969 61240 : if (tret == GS_ERROR)
7970 : {
7971 0 : if (orig != error_mark_node)
7972 0 : error ("invalid lvalue in %<asm%> output %d", i);
7973 : ret = tret;
7974 : }
7975 :
7976 : /* If the gimplified operand is a register we do not allow memory. */
7977 61240 : if (allows_reg
7978 59158 : && allows_mem
7979 67435 : && (is_gimple_reg (TREE_VALUE (link))
7980 267 : || (handled_component_p (TREE_VALUE (link))
7981 36 : && is_gimple_reg (TREE_OPERAND (TREE_VALUE (link), 0)))))
7982 5929 : allows_mem = 0;
7983 :
7984 : /* If the constraint does not allow memory make sure we gimplify
7985 : it to a register if it is not already but its base is. This
7986 : happens for complex and vector components. */
7987 61240 : if (!allows_mem)
7988 : {
7989 58895 : tree op = TREE_VALUE (link);
7990 58895 : if (! is_gimple_val (op)
7991 21375 : && is_gimple_reg_type (TREE_TYPE (op))
7992 80269 : && is_gimple_reg (get_base_address (op)))
7993 : {
7994 19 : tree tem = create_tmp_reg (TREE_TYPE (op));
7995 19 : tree ass;
7996 19 : if (is_inout)
7997 : {
7998 7 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem),
7999 : tem, unshare_expr (op));
8000 7 : gimplify_and_add (ass, pre_p);
8001 : }
8002 19 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem), op, tem);
8003 19 : gimplify_and_add (ass, post_p);
8004 :
8005 19 : TREE_VALUE (link) = tem;
8006 19 : tret = GS_OK;
8007 : }
8008 : }
8009 :
8010 61240 : vec_safe_push (outputs, link);
8011 61240 : TREE_CHAIN (link) = NULL_TREE;
8012 :
8013 61240 : if (is_inout)
8014 : {
8015 : /* An input/output operand. To give the optimizers more
8016 : flexibility, split it into separate input and output
8017 : operands. */
8018 8720 : tree input;
8019 : /* Buffer big enough to format a 32-bit UINT_MAX into. */
8020 8720 : char buf[11];
8021 :
8022 : /* Turn the in/out constraint into an output constraint. */
8023 8720 : char *p = xstrdup (constraint);
8024 8720 : p[0] = '=';
8025 8720 : TREE_PURPOSE (link) = unshare_expr (TREE_PURPOSE (link));
8026 8720 : TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
8027 :
8028 : /* And add a matching input constraint. */
8029 8720 : if (allows_reg)
8030 : {
8031 8219 : sprintf (buf, "%u", i);
8032 :
8033 : /* If there are multiple alternatives in the constraint,
8034 : handle each of them individually. Those that allow register
8035 : will be replaced with operand number, the others will stay
8036 : unchanged. */
8037 8219 : if (strchr (p, ',') != NULL)
8038 : {
8039 100 : size_t len = 0, buflen = strlen (buf);
8040 100 : char *beg, *end, *str, *dst;
8041 :
8042 100 : for (beg = p + 1;;)
8043 : {
8044 200 : end = strchr (beg, ',');
8045 200 : if (end == NULL)
8046 100 : end = strchr (beg, '\0');
8047 200 : if ((size_t) (end - beg) < buflen)
8048 28 : len += buflen + 1;
8049 : else
8050 172 : len += end - beg + 1;
8051 200 : if (*end)
8052 100 : beg = end + 1;
8053 : else
8054 : break;
8055 : }
8056 :
8057 100 : str = (char *) alloca (len);
8058 100 : for (beg = p + 1, dst = str;;)
8059 : {
8060 200 : const char *tem;
8061 200 : bool mem_p, reg_p, inout_p;
8062 :
8063 200 : end = strchr (beg, ',');
8064 200 : if (end)
8065 100 : *end = '\0';
8066 200 : beg[-1] = '=';
8067 200 : tem = beg - 1;
8068 200 : parse_output_constraint (&tem, i, 0, 0, &mem_p, ®_p,
8069 : &inout_p, nullptr);
8070 200 : if (dst != str)
8071 100 : *dst++ = ',';
8072 200 : if (reg_p)
8073 : {
8074 115 : memcpy (dst, buf, buflen);
8075 115 : dst += buflen;
8076 : }
8077 : else
8078 : {
8079 85 : if (end)
8080 0 : len = end - beg;
8081 : else
8082 85 : len = strlen (beg);
8083 85 : memcpy (dst, beg, len);
8084 85 : dst += len;
8085 : }
8086 200 : if (end)
8087 100 : beg = end + 1;
8088 : else
8089 : break;
8090 100 : }
8091 100 : *dst = '\0';
8092 100 : input = build_string (dst - str, str);
8093 : }
8094 : else
8095 8119 : input = build_string (strlen (buf), buf);
8096 : }
8097 : else
8098 501 : input = build_string (constraint_len - 1, constraint + 1);
8099 :
8100 8720 : free (p);
8101 :
8102 8720 : input = build_tree_list (build_tree_list (NULL_TREE, input),
8103 8720 : unshare_expr (TREE_VALUE (link)));
8104 8720 : ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
8105 : }
8106 : }
8107 :
8108 : /* After all output operands have been gimplified, verify that each output
8109 : operand is used at most once in case of hard register constraints. Thus,
8110 : error out in cases like
8111 : asm ("" : "={0}" (x), "={1}" (x));
8112 : or even for
8113 : asm ("" : "=r" (x), "={1}" (x));
8114 :
8115 : FIXME: Ideally we would also error out for cases like
8116 : int x;
8117 : asm ("" : "=r" (x), "=r" (x));
8118 : However, since code like that was previously accepted, erroring out now might
8119 : break existing code. On the other hand, we already error out for register
8120 : asm like
8121 : register int x asm ("0");
8122 : asm ("" : "=r" (x), "=r" (x));
8123 : Thus, maybe it wouldn't be too bad to also error out in the former
8124 : non-register-asm case.
8125 : */
8126 144303 : for (unsigned i = 0; i < vec_safe_length (outputs); ++i)
8127 : {
8128 61238 : tree link = (*outputs)[i];
8129 61238 : tree op1 = TREE_VALUE (link);
8130 61238 : const char *constraint
8131 61238 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8132 61238 : if (strchr (constraint, '{') != nullptr)
8133 61378 : for (unsigned j = 0; j < vec_safe_length (outputs); ++j)
8134 : {
8135 142 : if (i == j)
8136 95 : continue;
8137 47 : tree link2 = (*outputs)[j];
8138 47 : tree op2 = TREE_VALUE (link2);
8139 47 : if (op1 == op2)
8140 : {
8141 2 : error ("multiple outputs to lvalue %qE", op2);
8142 2 : return GS_ERROR;
8143 : }
8144 : }
8145 : }
8146 :
8147 83065 : link_next = NULL_TREE;
8148 83065 : int input_num = 0;
8149 125390 : for (link = ASM_INPUTS (expr); link; ++input_num, ++i, link = link_next)
8150 : {
8151 42383 : if (error_operand_p (TREE_VALUE (link)))
8152 : return GS_ERROR;
8153 42334 : link_next = TREE_CHAIN (link);
8154 42334 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8155 42334 : reg_info.operand = TREE_VALUE (link);
8156 42334 : bool ok = parse_input_constraint (&constraint, input_num, 0, noutputs, 0,
8157 : oconstraints, &allows_mem, &allows_reg,
8158 : ®_info);
8159 42334 : if (!ok)
8160 : {
8161 30 : ret = GS_ERROR;
8162 30 : is_inout = false;
8163 : }
8164 :
8165 : /* If we can't make copies, we can only accept memory. */
8166 42334 : tree intype = TREE_TYPE (TREE_VALUE (link));
8167 42334 : if (TREE_ADDRESSABLE (intype)
8168 42308 : || !COMPLETE_TYPE_P (intype)
8169 84587 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (intype)))
8170 : {
8171 297 : if (allows_mem)
8172 288 : allows_reg = 0;
8173 : else
8174 : {
8175 9 : error ("impossible constraint in %<asm%>");
8176 9 : error ("non-memory input %d must stay in memory", i);
8177 9 : return GS_ERROR;
8178 : }
8179 : }
8180 :
8181 : /* If the operand is a memory input, it should be an lvalue. */
8182 42325 : if (!allows_reg && allows_mem)
8183 : {
8184 2392 : tree inputv = TREE_VALUE (link);
8185 2392 : STRIP_NOPS (inputv);
8186 2392 : if (TREE_CODE (inputv) == PREDECREMENT_EXPR
8187 : || TREE_CODE (inputv) == PREINCREMENT_EXPR
8188 : || TREE_CODE (inputv) == POSTDECREMENT_EXPR
8189 2392 : || TREE_CODE (inputv) == POSTINCREMENT_EXPR
8190 2380 : || TREE_CODE (inputv) == MODIFY_EXPR
8191 4770 : || VOID_TYPE_P (TREE_TYPE (inputv)))
8192 38 : TREE_VALUE (link) = error_mark_node;
8193 2392 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8194 : is_gimple_lvalue, fb_lvalue | fb_mayfail);
8195 2392 : if (tret != GS_ERROR)
8196 : {
8197 : /* Unlike output operands, memory inputs are not guaranteed
8198 : to be lvalues by the FE, and while the expressions are
8199 : marked addressable there, if it is e.g. a statement
8200 : expression, temporaries in it might not end up being
8201 : addressable. They might be already used in the IL and thus
8202 : it is too late to make them addressable now though. */
8203 2346 : tree x = TREE_VALUE (link);
8204 2488 : while (handled_component_p (x))
8205 142 : x = TREE_OPERAND (x, 0);
8206 2346 : if (TREE_CODE (x) == MEM_REF
8207 2346 : && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
8208 0 : x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
8209 2346 : if ((VAR_P (x)
8210 : || TREE_CODE (x) == PARM_DECL
8211 : || TREE_CODE (x) == RESULT_DECL)
8212 1489 : && !TREE_ADDRESSABLE (x)
8213 23 : && is_gimple_reg (x))
8214 : {
8215 17 : warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link),
8216 17 : input_location), 0,
8217 : "memory input %d is not directly addressable",
8218 : i);
8219 17 : prepare_gimple_addressable (&TREE_VALUE (link), pre_p);
8220 : }
8221 : }
8222 2392 : mark_addressable (TREE_VALUE (link));
8223 2392 : if (tret == GS_ERROR)
8224 : {
8225 46 : if (inputv != error_mark_node)
8226 46 : error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
8227 : "memory input %d is not directly addressable", i);
8228 : ret = tret;
8229 : }
8230 : }
8231 : else
8232 : {
8233 39933 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8234 : is_gimple_asm_val, fb_rvalue);
8235 39933 : if (tret == GS_ERROR)
8236 46 : ret = tret;
8237 : }
8238 :
8239 42325 : TREE_CHAIN (link) = NULL_TREE;
8240 42325 : vec_safe_push (inputs, link);
8241 : }
8242 :
8243 83007 : link_next = NULL_TREE;
8244 83954 : for (link = ASM_LABELS (expr); link; link = link_next)
8245 : {
8246 947 : link_next = TREE_CHAIN (link);
8247 947 : TREE_CHAIN (link) = NULL_TREE;
8248 947 : vec_safe_push (labels, link);
8249 : }
8250 :
8251 : /* Do not add ASMs with errors to the gimple IL stream. */
8252 83007 : if (ret != GS_ERROR)
8253 : {
8254 82924 : stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
8255 : inputs, outputs, clobbers, labels);
8256 :
8257 : /* asm is volatile if it was marked by the user as volatile or
8258 : there are no outputs or this is an asm goto. */
8259 90438 : gimple_asm_set_volatile (stmt,
8260 82924 : ASM_VOLATILE_P (expr)
8261 7528 : || noutputs == 0
8262 : || labels);
8263 82924 : gimple_asm_set_basic (stmt, ASM_BASIC_P (expr));
8264 82924 : gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
8265 :
8266 82924 : gimplify_seq_add_stmt (pre_p, stmt);
8267 : }
8268 :
8269 : return ret;
8270 83100 : }
8271 :
8272 : /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding
8273 : GIMPLE_WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
8274 : gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we
8275 : return to this function.
8276 :
8277 : FIXME should we complexify the prequeue handling instead? Or use flags
8278 : for all the cleanups and let the optimizer tighten them up? The current
8279 : code seems pretty fragile; it will break on a cleanup within any
8280 : non-conditional nesting. But any such nesting would be broken, anyway;
8281 : we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
8282 : and continues out of it. We can do that at the RTL level, though, so
8283 : having an optimizer to tighten up try/finally regions would be a Good
8284 : Thing. */
8285 :
8286 : static enum gimplify_status
8287 5531759 : gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
8288 : {
8289 5531759 : gimple_stmt_iterator iter;
8290 5531759 : gimple_seq body_sequence = NULL;
8291 :
8292 5531759 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
8293 :
8294 : /* We only care about the number of conditions between the innermost
8295 : CLEANUP_POINT_EXPR and the cleanup. So save and reset the count and
8296 : any cleanups collected outside the CLEANUP_POINT_EXPR. */
8297 5531759 : int old_conds = gimplify_ctxp->conditions;
8298 5531759 : gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
8299 5531759 : bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
8300 5531759 : gimplify_ctxp->conditions = 0;
8301 5531759 : gimplify_ctxp->conditional_cleanups = NULL;
8302 5531759 : gimplify_ctxp->in_cleanup_point_expr = true;
8303 :
8304 5531759 : gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
8305 :
8306 5531759 : gimplify_ctxp->conditions = old_conds;
8307 5531759 : gimplify_ctxp->conditional_cleanups = old_cleanups;
8308 5531759 : gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
8309 :
8310 28601269 : for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
8311 : {
8312 17584542 : gimple *wce = gsi_stmt (iter);
8313 :
8314 17584542 : if (gimple_code (wce) == GIMPLE_WITH_CLEANUP_EXPR)
8315 : {
8316 674730 : if (gsi_one_before_end_p (iter))
8317 : {
8318 : /* Note that gsi_insert_seq_before and gsi_remove do not
8319 : scan operands, unlike some other sequence mutators. */
8320 3118 : if (!gimple_wce_cleanup_eh_only (wce))
8321 3118 : gsi_insert_seq_before_without_update (&iter,
8322 : gimple_wce_cleanup (wce),
8323 : GSI_SAME_STMT);
8324 3118 : gsi_remove (&iter, true);
8325 3118 : break;
8326 : }
8327 : else
8328 : {
8329 671612 : gtry *gtry;
8330 671612 : gimple_seq seq;
8331 671612 : enum gimple_try_flags kind;
8332 :
8333 671612 : if (gimple_wce_cleanup_eh_only (wce))
8334 : kind = GIMPLE_TRY_CATCH;
8335 : else
8336 654177 : kind = GIMPLE_TRY_FINALLY;
8337 671612 : seq = gsi_split_seq_after (iter);
8338 :
8339 671612 : gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
8340 : /* Do not use gsi_replace here, as it may scan operands.
8341 : We want to do a simple structural modification only. */
8342 671612 : gsi_set_stmt (&iter, gtry);
8343 1343224 : iter = gsi_start (gtry->eval);
8344 : }
8345 : }
8346 : else
8347 16909812 : gsi_next (&iter);
8348 : }
8349 :
8350 5531759 : gimplify_seq_add_seq (pre_p, body_sequence);
8351 5531759 : if (temp)
8352 : {
8353 : *expr_p = temp;
8354 : return GS_OK;
8355 : }
8356 : else
8357 : {
8358 5166936 : *expr_p = NULL;
8359 5166936 : return GS_ALL_DONE;
8360 : }
8361 : }
8362 :
8363 : /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
8364 : is the cleanup action required. EH_ONLY is true if the cleanup should
8365 : only be executed if an exception is thrown, not on normal exit.
8366 : If FORCE_UNCOND is true perform the cleanup unconditionally; this is
8367 : only valid for clobbers. */
8368 :
8369 : static void
8370 679871 : gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
8371 : bool force_uncond = false)
8372 : {
8373 679871 : gimple *wce;
8374 679871 : gimple_seq cleanup_stmts = NULL;
8375 :
8376 : /* Errors can result in improperly nested cleanups. Which results in
8377 : confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
8378 679871 : if (seen_error ())
8379 5141 : return;
8380 :
8381 674730 : if (gimple_conditional_context ())
8382 : {
8383 : /* If we're in a conditional context, this is more complex. We only
8384 : want to run the cleanup if we actually ran the initialization that
8385 : necessitates it, but we want to run it after the end of the
8386 : conditional context. So we wrap the try/finally around the
8387 : condition and use a flag to determine whether or not to actually
8388 : run the destructor. Thus
8389 :
8390 : test ? f(A()) : 0
8391 :
8392 : becomes (approximately)
8393 :
8394 : flag = 0;
8395 : try {
8396 : if (test) { A::A(temp); flag = 1; val = f(temp); }
8397 : else { val = 0; }
8398 : } finally {
8399 : if (flag) A::~A(temp);
8400 : }
8401 : val
8402 : */
8403 16154 : if (force_uncond)
8404 : {
8405 15284 : gimplify_stmt (&cleanup, &cleanup_stmts);
8406 15284 : wce = gimple_build_wce (cleanup_stmts);
8407 15284 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8408 : }
8409 : else
8410 : {
8411 870 : tree flag = create_tmp_var (boolean_type_node, "cleanup");
8412 870 : gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
8413 870 : gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
8414 :
8415 870 : cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
8416 870 : gimplify_stmt (&cleanup, &cleanup_stmts);
8417 870 : wce = gimple_build_wce (cleanup_stmts);
8418 870 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8419 :
8420 870 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
8421 870 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8422 870 : gimplify_seq_add_stmt (pre_p, ftrue);
8423 :
8424 : /* Because of this manipulation, and the EH edges that jump
8425 : threading cannot redirect, the temporary (VAR) will appear
8426 : to be used uninitialized. Don't warn. */
8427 870 : suppress_warning (var, OPT_Wuninitialized);
8428 : }
8429 : }
8430 : else
8431 : {
8432 658576 : gimplify_stmt (&cleanup, &cleanup_stmts);
8433 658576 : wce = gimple_build_wce (cleanup_stmts);
8434 658576 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8435 658576 : gimplify_seq_add_stmt (pre_p, wce);
8436 : }
8437 : }
8438 :
8439 : /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
8440 :
8441 : static enum gimplify_status
8442 882656 : gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
8443 : {
8444 882656 : tree targ = *expr_p;
8445 882656 : tree temp = TARGET_EXPR_SLOT (targ);
8446 882656 : tree init = TARGET_EXPR_INITIAL (targ);
8447 882656 : enum gimplify_status ret;
8448 :
8449 882656 : bool unpoison_empty_seq = false;
8450 882656 : gimple_stmt_iterator unpoison_it;
8451 :
8452 882656 : if (init)
8453 : {
8454 848429 : gimple_seq init_pre_p = NULL;
8455 848429 : bool is_vla = false;
8456 :
8457 : /* TARGET_EXPR temps aren't part of the enclosing block, so add it
8458 : to the temps list. Handle also variable length TARGET_EXPRs. */
8459 848429 : if (!poly_int_tree_p (DECL_SIZE (temp)))
8460 : {
8461 44 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
8462 1 : gimplify_type_sizes (TREE_TYPE (temp), &init_pre_p);
8463 : /* FIXME: this is correct only when the size of the type does
8464 : not depend on expressions evaluated in init. */
8465 44 : gimplify_vla_decl (temp, &init_pre_p);
8466 44 : is_vla = true;
8467 : }
8468 : else
8469 : {
8470 : /* Save location where we need to place unpoisoning. It's possible
8471 : that a variable will be converted to needs_to_live_in_memory. */
8472 848385 : unpoison_it = gsi_last (*pre_p);
8473 848385 : unpoison_empty_seq = gsi_end_p (unpoison_it);
8474 :
8475 848385 : gimple_add_tmp_var (temp);
8476 : }
8477 :
8478 848429 : if (var_needs_auto_init_p (temp) && VOID_TYPE_P (TREE_TYPE (init)))
8479 : {
8480 59608 : gimple_add_init_for_auto_var (temp, flag_auto_var_init, &init_pre_p);
8481 59608 : if ((flag_auto_var_init & ~AUTO_INIT_CXX26) == AUTO_INIT_PATTERN
8482 0 : && !is_gimple_reg (temp)
8483 59608 : && clear_padding_type_may_have_padding_p (TREE_TYPE (temp)))
8484 0 : gimple_add_padding_init_for_auto_var (temp, is_vla, &init_pre_p);
8485 : }
8486 :
8487 : /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
8488 : expression is supposed to initialize the slot. */
8489 848429 : if (VOID_TYPE_P (TREE_TYPE (init)))
8490 301007 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8491 : fb_none);
8492 : else
8493 : {
8494 547422 : tree init_expr = build2 (INIT_EXPR, void_type_node, temp, init);
8495 547422 : init = init_expr;
8496 547422 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8497 : fb_none);
8498 547422 : init = NULL;
8499 547422 : ggc_free (init_expr);
8500 : }
8501 848429 : if (ret == GS_ERROR)
8502 : {
8503 : /* PR c++/28266 Make sure this is expanded only once. */
8504 10 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8505 10 : return GS_ERROR;
8506 : }
8507 :
8508 848419 : if (init)
8509 0 : gimplify_and_add (init, &init_pre_p);
8510 :
8511 : /* Add a clobber for the temporary going out of scope, like
8512 : gimplify_bind_expr. But only if we did not promote the
8513 : temporary to static storage. */
8514 848419 : if (gimplify_ctxp->in_cleanup_point_expr
8515 704186 : && !TREE_STATIC (temp)
8516 1551055 : && needs_to_live_in_memory (temp))
8517 : {
8518 515597 : if (flag_stack_reuse == SR_ALL)
8519 : {
8520 515117 : tree clobber = build_clobber (TREE_TYPE (temp),
8521 : CLOBBER_STORAGE_END);
8522 515117 : clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
8523 515117 : gimple_push_cleanup (temp, clobber, false, pre_p, true);
8524 : }
8525 515597 : if (asan_poisoned_variables
8526 480 : && DECL_ALIGN (temp) <= MAX_SUPPORTED_STACK_ALIGNMENT
8527 480 : && !TREE_STATIC (temp)
8528 480 : && dbg_cnt (asan_use_after_scope)
8529 516077 : && !gimplify_omp_ctxp)
8530 : {
8531 472 : tree asan_cleanup = build_asan_poison_call_expr (temp);
8532 472 : if (asan_cleanup)
8533 : {
8534 472 : if (unpoison_empty_seq)
8535 217 : unpoison_it = gsi_start (*pre_p);
8536 :
8537 472 : asan_poison_variable (temp, false, &unpoison_it,
8538 : unpoison_empty_seq);
8539 472 : gimple_push_cleanup (temp, asan_cleanup, false, pre_p);
8540 : }
8541 : }
8542 : }
8543 :
8544 848419 : gimple_seq_add_seq (pre_p, init_pre_p);
8545 :
8546 : /* If needed, push the cleanup for the temp. */
8547 848419 : if (TARGET_EXPR_CLEANUP (targ))
8548 164282 : gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
8549 164282 : CLEANUP_EH_ONLY (targ), pre_p);
8550 :
8551 : /* Only expand this once. */
8552 848419 : TREE_OPERAND (targ, 3) = init;
8553 848419 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8554 : }
8555 : else
8556 : /* We should have expanded this before. */
8557 34227 : gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
8558 :
8559 882646 : *expr_p = temp;
8560 882646 : return GS_OK;
8561 : }
8562 :
8563 : /* Gimplification of expression trees. */
8564 :
8565 : /* Gimplify an expression which appears at statement context. The
8566 : corresponding GIMPLE statements are added to *SEQ_P. If *SEQ_P is
8567 : NULL, a new sequence is allocated.
8568 :
8569 : Return true if we actually added a statement to the queue. */
8570 :
8571 : bool
8572 104784023 : gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
8573 : {
8574 104784023 : gimple_seq_node last;
8575 :
8576 104784023 : last = gimple_seq_last (*seq_p);
8577 104784023 : gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
8578 104784023 : return last != gimple_seq_last (*seq_p);
8579 : }
8580 :
8581 : /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
8582 : to CTX. If entries already exist, force them to be some flavor of private.
8583 : If there is no enclosing parallel, do nothing. */
8584 :
8585 : void
8586 126226 : omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
8587 : {
8588 126226 : splay_tree_node n;
8589 :
8590 126226 : if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE)
8591 : return;
8592 :
8593 36987 : do
8594 : {
8595 36987 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8596 36987 : if (n != NULL)
8597 : {
8598 4302 : if (n->value & GOVD_SHARED)
8599 183 : n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
8600 4119 : else if (n->value & GOVD_MAP)
8601 58 : n->value |= GOVD_MAP_TO_ONLY;
8602 : else
8603 : return;
8604 : }
8605 32685 : else if ((ctx->region_type & ORT_TARGET) != 0)
8606 : {
8607 7027 : if (ctx->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
8608 4268 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8609 : else
8610 2759 : omp_add_variable (ctx, decl, GOVD_MAP | GOVD_MAP_TO_ONLY);
8611 : }
8612 25658 : else if (ctx->region_type != ORT_WORKSHARE
8613 : && ctx->region_type != ORT_TASKGROUP
8614 23829 : && ctx->region_type != ORT_SIMD
8615 23205 : && ctx->region_type != ORT_ACC
8616 23088 : && !(ctx->region_type & ORT_TARGET_DATA))
8617 14507 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8618 :
8619 32926 : ctx = ctx->outer_context;
8620 : }
8621 32926 : while (ctx);
8622 : }
8623 :
8624 : /* Similarly for each of the type sizes of TYPE. */
8625 :
8626 : static void
8627 40253 : omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
8628 : {
8629 40253 : if (type == NULL || type == error_mark_node)
8630 : return;
8631 40249 : type = TYPE_MAIN_VARIANT (type);
8632 :
8633 40249 : if (ctx->privatized_types->add (type))
8634 : return;
8635 :
8636 31315 : switch (TREE_CODE (type))
8637 : {
8638 13592 : case INTEGER_TYPE:
8639 13592 : case ENUMERAL_TYPE:
8640 13592 : case BOOLEAN_TYPE:
8641 13592 : case REAL_TYPE:
8642 13592 : case FIXED_POINT_TYPE:
8643 13592 : omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
8644 13592 : omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
8645 13592 : break;
8646 :
8647 5418 : case ARRAY_TYPE:
8648 5418 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8649 5418 : omp_firstprivatize_type_sizes (ctx, TYPE_DOMAIN (type));
8650 5418 : break;
8651 :
8652 2502 : case RECORD_TYPE:
8653 2502 : case UNION_TYPE:
8654 2502 : case QUAL_UNION_TYPE:
8655 2502 : {
8656 2502 : tree field;
8657 26645 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
8658 24143 : if (TREE_CODE (field) == FIELD_DECL)
8659 : {
8660 8997 : omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
8661 8997 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (field));
8662 : }
8663 : }
8664 : break;
8665 :
8666 9153 : case POINTER_TYPE:
8667 9153 : case REFERENCE_TYPE:
8668 9153 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8669 9153 : break;
8670 :
8671 : default:
8672 : break;
8673 : }
8674 :
8675 31315 : omp_firstprivatize_variable (ctx, TYPE_SIZE (type));
8676 31315 : omp_firstprivatize_variable (ctx, TYPE_SIZE_UNIT (type));
8677 31315 : lang_hooks.types.omp_firstprivatize_type_sizes (ctx, type);
8678 : }
8679 :
8680 : /* Add an entry for DECL in the OMP context CTX with FLAGS. */
8681 :
8682 : static void
8683 717971 : omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
8684 : {
8685 717971 : splay_tree_node n;
8686 717971 : unsigned int nflags;
8687 717971 : tree t;
8688 :
8689 717971 : if (error_operand_p (decl) || ctx->region_type == ORT_NONE)
8690 : return;
8691 :
8692 : /* Never elide decls whose type has TREE_ADDRESSABLE set. This means
8693 : there are constructors involved somewhere. Exception is a shared clause,
8694 : there is nothing privatized in that case. */
8695 717823 : if ((flags & GOVD_SHARED) == 0
8696 717823 : && (TREE_ADDRESSABLE (TREE_TYPE (decl))
8697 657298 : || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
8698 7758 : flags |= GOVD_SEEN;
8699 :
8700 717823 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8701 717823 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
8702 : {
8703 : /* We shouldn't be re-adding the decl with the same data
8704 : sharing class. */
8705 828 : gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
8706 828 : nflags = n->value | flags;
8707 : /* The only combination of data sharing classes we should see is
8708 : FIRSTPRIVATE and LASTPRIVATE. However, OpenACC permits
8709 : reduction variables to be used in data sharing clauses. */
8710 828 : gcc_assert ((ctx->region_type & ORT_ACC) != 0
8711 : || ((nflags & GOVD_DATA_SHARE_CLASS)
8712 : == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE))
8713 : || (flags & GOVD_DATA_SHARE_CLASS) == 0);
8714 828 : n->value = nflags;
8715 828 : return;
8716 : }
8717 :
8718 : /* When adding a variable-sized variable, we have to handle all sorts
8719 : of additional bits of data: the pointer replacement variable, and
8720 : the parameters of the type. */
8721 716995 : if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl)))
8722 : {
8723 : /* Add the pointer replacement variable as PRIVATE if the variable
8724 : replacement is private, else FIRSTPRIVATE since we'll need the
8725 : address of the original variable either for SHARED, or for the
8726 : copy into or out of the context. */
8727 1330 : if (!(flags & GOVD_LOCAL) && ctx->region_type != ORT_TASKGROUP)
8728 : {
8729 1238 : if (flags & GOVD_MAP)
8730 : nflags = GOVD_MAP | GOVD_MAP_TO_ONLY | GOVD_EXPLICIT;
8731 531 : else if (flags & GOVD_PRIVATE)
8732 : nflags = GOVD_PRIVATE;
8733 441 : else if (((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
8734 50 : && (flags & GOVD_FIRSTPRIVATE))
8735 431 : || (ctx->region_type == ORT_TARGET_DATA
8736 6 : && (flags & GOVD_DATA_SHARE_CLASS) == 0))
8737 : nflags = GOVD_PRIVATE | GOVD_EXPLICIT;
8738 : else
8739 1238 : nflags = GOVD_FIRSTPRIVATE;
8740 1238 : nflags |= flags & GOVD_SEEN;
8741 1238 : t = DECL_VALUE_EXPR (decl);
8742 1238 : gcc_assert (INDIRECT_REF_P (t));
8743 1238 : t = TREE_OPERAND (t, 0);
8744 1238 : gcc_assert (DECL_P (t));
8745 1238 : omp_add_variable (ctx, t, nflags);
8746 : }
8747 :
8748 : /* Add all of the variable and type parameters (which should have
8749 : been gimplified to a formal temporary) as FIRSTPRIVATE. */
8750 1330 : omp_firstprivatize_variable (ctx, DECL_SIZE_UNIT (decl));
8751 1330 : omp_firstprivatize_variable (ctx, DECL_SIZE (decl));
8752 1330 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8753 :
8754 : /* The variable-sized variable itself is never SHARED, only some form
8755 : of PRIVATE. The sharing would take place via the pointer variable
8756 : which we remapped above. */
8757 1330 : if (flags & GOVD_SHARED)
8758 284 : flags = GOVD_SHARED | GOVD_DEBUG_PRIVATE
8759 284 : | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
8760 :
8761 : /* We're going to make use of the TYPE_SIZE_UNIT at least in the
8762 : alloca statement we generate for the variable, so make sure it
8763 : is available. This isn't automatically needed for the SHARED
8764 : case, since we won't be allocating local storage then.
8765 : For local variables TYPE_SIZE_UNIT might not be gimplified yet,
8766 : in this case omp_notice_variable will be called later
8767 : on when it is gimplified. */
8768 1046 : else if (! (flags & (GOVD_LOCAL | GOVD_MAP))
8769 1046 : && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
8770 275 : omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
8771 : }
8772 715665 : else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
8773 715665 : && omp_privatize_by_reference (decl))
8774 : {
8775 9937 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8776 :
8777 : /* Similar to the direct variable sized case above, we'll need the
8778 : size of references being privatized. */
8779 9937 : if ((flags & GOVD_SHARED) == 0)
8780 : {
8781 6217 : t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
8782 6217 : if (t && DECL_P (t))
8783 1398 : omp_notice_variable (ctx, t, true);
8784 : }
8785 : }
8786 :
8787 716995 : if (n != NULL)
8788 1870 : n->value |= flags;
8789 : else
8790 715125 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
8791 :
8792 : /* For reductions clauses in OpenACC loop directives, by default create a
8793 : copy clause on the enclosing parallel construct for carrying back the
8794 : results. */
8795 716995 : if (ctx->region_type == ORT_ACC && (flags & GOVD_REDUCTION))
8796 : {
8797 4716 : struct gimplify_omp_ctx *outer_ctx = ctx->outer_context;
8798 6454 : while (outer_ctx)
8799 : {
8800 5788 : n = splay_tree_lookup (outer_ctx->variables, (splay_tree_key)decl);
8801 5788 : if (n != NULL)
8802 : {
8803 : /* Ignore local variables and explicitly declared clauses. */
8804 3990 : if (n->value & (GOVD_LOCAL | GOVD_EXPLICIT))
8805 : break;
8806 443 : else if (outer_ctx->region_type == ORT_ACC_KERNELS)
8807 : {
8808 : /* According to the OpenACC spec, such a reduction variable
8809 : should already have a copy map on a kernels construct,
8810 : verify that here. */
8811 143 : gcc_assert (!(n->value & GOVD_FIRSTPRIVATE)
8812 : && (n->value & GOVD_MAP));
8813 : }
8814 300 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8815 : {
8816 : /* Remove firstprivate and make it a copy map. */
8817 150 : n->value &= ~GOVD_FIRSTPRIVATE;
8818 150 : n->value |= GOVD_MAP;
8819 : }
8820 : }
8821 1798 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8822 : {
8823 503 : splay_tree_insert (outer_ctx->variables, (splay_tree_key)decl,
8824 : GOVD_MAP | GOVD_SEEN);
8825 503 : break;
8826 : }
8827 1738 : outer_ctx = outer_ctx->outer_context;
8828 : }
8829 : }
8830 : }
8831 :
8832 : /* Notice a threadprivate variable DECL used in OMP context CTX.
8833 : This just prints out diagnostics about threadprivate variable uses
8834 : in untied tasks. If DECL2 is non-NULL, prevent this warning
8835 : on that variable. */
8836 :
8837 : static bool
8838 14183 : omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
8839 : tree decl2)
8840 : {
8841 14183 : splay_tree_node n;
8842 14183 : struct gimplify_omp_ctx *octx;
8843 :
8844 28798 : for (octx = ctx; octx; octx = octx->outer_context)
8845 14615 : if ((octx->region_type & ORT_TARGET) != 0
8846 14615 : || octx->order_concurrent)
8847 : {
8848 112 : n = splay_tree_lookup (octx->variables, (splay_tree_key)decl);
8849 112 : if (n == NULL)
8850 : {
8851 20 : if (octx->order_concurrent)
8852 : {
8853 20 : error ("threadprivate variable %qE used in a region with"
8854 20 : " %<order(concurrent)%> clause", DECL_NAME (decl));
8855 20 : inform (octx->location, "enclosing region");
8856 : }
8857 : else
8858 : {
8859 0 : error ("threadprivate variable %qE used in target region",
8860 0 : DECL_NAME (decl));
8861 0 : inform (octx->location, "enclosing target region");
8862 : }
8863 20 : splay_tree_insert (octx->variables, (splay_tree_key)decl, 0);
8864 : }
8865 112 : if (decl2)
8866 0 : splay_tree_insert (octx->variables, (splay_tree_key)decl2, 0);
8867 : }
8868 :
8869 14183 : if (ctx->region_type != ORT_UNTIED_TASK)
8870 : return false;
8871 37 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8872 37 : if (n == NULL)
8873 : {
8874 6 : error ("threadprivate variable %qE used in untied task",
8875 6 : DECL_NAME (decl));
8876 6 : inform (ctx->location, "enclosing task");
8877 6 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
8878 : }
8879 37 : if (decl2)
8880 4 : splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
8881 : return false;
8882 : }
8883 :
8884 : /* Return true if global var DECL is device resident. */
8885 :
8886 : static bool
8887 642 : device_resident_p (tree decl)
8888 : {
8889 642 : tree attr = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (decl));
8890 :
8891 642 : if (!attr)
8892 : return false;
8893 :
8894 0 : for (tree t = TREE_VALUE (attr); t; t = TREE_PURPOSE (t))
8895 : {
8896 0 : tree c = TREE_VALUE (t);
8897 0 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DEVICE_RESIDENT)
8898 : return true;
8899 : }
8900 :
8901 : return false;
8902 : }
8903 :
8904 : /* Return true if DECL has an ACC DECLARE attribute. */
8905 :
8906 : static bool
8907 9101 : is_oacc_declared (tree decl)
8908 : {
8909 9101 : tree t = TREE_CODE (decl) == MEM_REF ? TREE_OPERAND (decl, 0) : decl;
8910 9101 : tree declared = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (t));
8911 9101 : return declared != NULL_TREE;
8912 : }
8913 :
8914 : /* Determine outer default flags for DECL mentioned in an OMP region
8915 : but not declared in an enclosing clause.
8916 :
8917 : ??? Some compiler-generated variables (like SAVE_EXPRs) could be
8918 : remapped firstprivate instead of shared. To some extent this is
8919 : addressed in omp_firstprivatize_type_sizes, but not
8920 : effectively. */
8921 :
8922 : static unsigned
8923 48030 : omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
8924 : bool in_code, unsigned flags)
8925 : {
8926 48030 : enum omp_clause_default_kind default_kind = ctx->default_kind;
8927 48030 : enum omp_clause_default_kind kind;
8928 :
8929 48030 : kind = lang_hooks.decls.omp_predetermined_sharing (decl);
8930 48030 : if (ctx->region_type & ORT_TASK)
8931 : {
8932 3994 : tree detach_clause = omp_find_clause (ctx->clauses, OMP_CLAUSE_DETACH);
8933 :
8934 : /* The event-handle specified by a detach clause should always be firstprivate,
8935 : regardless of the current default. */
8936 4206 : if (detach_clause && OMP_CLAUSE_DECL (detach_clause) == decl)
8937 : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
8938 : }
8939 48030 : if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
8940 : default_kind = kind;
8941 45213 : else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
8942 : default_kind = OMP_CLAUSE_DEFAULT_SHARED;
8943 : /* For C/C++ default({,first}private), variables with static storage duration
8944 : declared in a namespace or global scope and referenced in construct
8945 : must be explicitly specified, i.e. acts as default(none). */
8946 45212 : else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
8947 45212 : || default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
8948 371 : && VAR_P (decl)
8949 328 : && is_global_var (decl)
8950 184 : && (DECL_FILE_SCOPE_P (decl)
8951 104 : || (DECL_CONTEXT (decl)
8952 104 : && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
8953 45340 : && !lang_GNU_Fortran ())
8954 : default_kind = OMP_CLAUSE_DEFAULT_NONE;
8955 :
8956 47901 : switch (default_kind)
8957 : {
8958 267 : case OMP_CLAUSE_DEFAULT_NONE:
8959 267 : {
8960 267 : const char *rtype;
8961 :
8962 267 : if (ctx->region_type & ORT_PARALLEL)
8963 : rtype = "parallel";
8964 108 : else if ((ctx->region_type & ORT_TASKLOOP) == ORT_TASKLOOP)
8965 : rtype = "taskloop";
8966 72 : else if (ctx->region_type & ORT_TASK)
8967 : rtype = "task";
8968 36 : else if (ctx->region_type & ORT_TEAMS)
8969 : rtype = "teams";
8970 : else
8971 0 : gcc_unreachable ();
8972 :
8973 267 : error ("%qE not specified in enclosing %qs",
8974 267 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)), rtype);
8975 267 : inform (ctx->location, "enclosing %qs", rtype);
8976 : }
8977 : /* FALLTHRU */
8978 44373 : case OMP_CLAUSE_DEFAULT_SHARED:
8979 44373 : flags |= GOVD_SHARED;
8980 44373 : break;
8981 155 : case OMP_CLAUSE_DEFAULT_PRIVATE:
8982 155 : flags |= GOVD_PRIVATE;
8983 155 : break;
8984 280 : case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
8985 280 : flags |= GOVD_FIRSTPRIVATE;
8986 280 : break;
8987 3222 : case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
8988 : /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */
8989 3222 : gcc_assert ((ctx->region_type & ORT_TASK) != 0);
8990 3222 : if (struct gimplify_omp_ctx *octx = ctx->outer_context)
8991 : {
8992 2164 : omp_notice_variable (octx, decl, in_code);
8993 5158 : for (; octx; octx = octx->outer_context)
8994 : {
8995 2938 : splay_tree_node n2;
8996 :
8997 2938 : n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
8998 2938 : if ((octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)) != 0
8999 5 : && (n2 == NULL || (n2->value & GOVD_DATA_SHARE_CLASS) == 0))
9000 5 : continue;
9001 2933 : if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
9002 : {
9003 898 : flags |= GOVD_FIRSTPRIVATE;
9004 898 : goto found_outer;
9005 : }
9006 2035 : if ((octx->region_type & (ORT_PARALLEL | ORT_TEAMS)) != 0)
9007 : {
9008 1210 : flags |= GOVD_SHARED;
9009 1210 : goto found_outer;
9010 : }
9011 : }
9012 : }
9013 :
9014 1114 : if (TREE_CODE (decl) == PARM_DECL
9015 1114 : || (!is_global_var (decl)
9016 294 : && DECL_CONTEXT (decl) == current_function_decl))
9017 734 : flags |= GOVD_FIRSTPRIVATE;
9018 : else
9019 380 : flags |= GOVD_SHARED;
9020 48030 : found_outer:
9021 : break;
9022 :
9023 0 : default:
9024 0 : gcc_unreachable ();
9025 : }
9026 :
9027 48030 : return flags;
9028 : }
9029 :
9030 : /* Return string name for types of OpenACC constructs from ORT_* values. */
9031 :
9032 : static const char *
9033 570 : oacc_region_type_name (enum omp_region_type region_type)
9034 : {
9035 570 : switch (region_type)
9036 : {
9037 : case ORT_ACC_DATA:
9038 : return "data";
9039 140 : case ORT_ACC_PARALLEL:
9040 140 : return "parallel";
9041 140 : case ORT_ACC_KERNELS:
9042 140 : return "kernels";
9043 140 : case ORT_ACC_SERIAL:
9044 140 : return "serial";
9045 0 : default:
9046 0 : gcc_unreachable ();
9047 : }
9048 : }
9049 :
9050 : /* Determine outer default flags for DECL mentioned in an OACC region
9051 : but not declared in an enclosing clause. */
9052 :
9053 : static unsigned
9054 8839 : oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
9055 : {
9056 8839 : struct gimplify_omp_ctx *ctx_default = ctx;
9057 : /* If no 'default' clause appears on this compute construct... */
9058 8839 : if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED)
9059 : {
9060 : /* ..., see if one appears on a lexically containing 'data'
9061 : construct. */
9062 9618 : while ((ctx_default = ctx_default->outer_context))
9063 : {
9064 1534 : if (ctx_default->region_type == ORT_ACC_DATA
9065 1534 : && ctx_default->default_kind != OMP_CLAUSE_DEFAULT_SHARED)
9066 : break;
9067 : }
9068 : /* If not, reset. */
9069 8260 : if (!ctx_default)
9070 8663 : ctx_default = ctx;
9071 : }
9072 :
9073 8839 : bool on_device = false;
9074 8839 : bool is_private = false;
9075 8839 : bool declared = is_oacc_declared (decl);
9076 8839 : tree type = TREE_TYPE (decl);
9077 :
9078 8839 : if (omp_privatize_by_reference (decl))
9079 338 : type = TREE_TYPE (type);
9080 :
9081 : /* For Fortran COMMON blocks, only used variables in those blocks are
9082 : transferred and remapped. The block itself will have a private clause to
9083 : avoid transferring the data twice.
9084 : The hook evaluates to false by default. For a variable in Fortran's COMMON
9085 : or EQUIVALENCE block, returns 'true' (as we have shared=false) - as only
9086 : the variables in such a COMMON/EQUIVALENCE block shall be privatized not
9087 : the whole block. For C++ and Fortran, it can also be true under certain
9088 : other conditions, if DECL_HAS_VALUE_EXPR. */
9089 8839 : if (RECORD_OR_UNION_TYPE_P (type))
9090 983 : is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false);
9091 :
9092 8839 : if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0
9093 8839 : && is_global_var (decl)
9094 642 : && device_resident_p (decl)
9095 8839 : && !is_private)
9096 : {
9097 0 : on_device = true;
9098 0 : flags |= GOVD_MAP_TO_ONLY;
9099 : }
9100 :
9101 8839 : switch (ctx->region_type)
9102 : {
9103 1460 : case ORT_ACC_KERNELS:
9104 1460 : if (is_private)
9105 0 : flags |= GOVD_FIRSTPRIVATE;
9106 1460 : else if (AGGREGATE_TYPE_P (type))
9107 : {
9108 : /* Aggregates default to 'present_or_copy', or 'present'. */
9109 415 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9110 397 : flags |= GOVD_MAP;
9111 : else
9112 18 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9113 : }
9114 : else
9115 : /* Scalars default to 'copy'. */
9116 1045 : flags |= GOVD_MAP | GOVD_MAP_FORCE;
9117 :
9118 : break;
9119 :
9120 7379 : case ORT_ACC_PARALLEL:
9121 7379 : case ORT_ACC_SERIAL:
9122 7379 : if (is_private)
9123 0 : flags |= GOVD_FIRSTPRIVATE;
9124 7379 : else if (on_device || declared)
9125 17 : flags |= GOVD_MAP;
9126 7362 : else if (AGGREGATE_TYPE_P (type))
9127 : {
9128 : /* Aggregates default to 'present_or_copy', or 'present'. */
9129 3697 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9130 3431 : flags |= GOVD_MAP;
9131 : else
9132 266 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9133 : }
9134 : else
9135 : /* Scalars default to 'firstprivate'. */
9136 3665 : flags |= GOVD_FIRSTPRIVATE;
9137 :
9138 : break;
9139 :
9140 0 : default:
9141 0 : gcc_unreachable ();
9142 : }
9143 :
9144 8839 : if (DECL_ARTIFICIAL (decl))
9145 : ; /* We can get compiler-generated decls, and should not complain
9146 : about them. */
9147 8528 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_NONE)
9148 : {
9149 420 : error ("%qE not specified in enclosing OpenACC %qs construct",
9150 210 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)),
9151 : oacc_region_type_name (ctx->region_type));
9152 210 : if (ctx_default != ctx)
9153 150 : inform (ctx->location, "enclosing OpenACC %qs construct and",
9154 : oacc_region_type_name (ctx->region_type));
9155 210 : inform (ctx_default->location,
9156 : "enclosing OpenACC %qs construct with %qs clause",
9157 : oacc_region_type_name (ctx_default->region_type),
9158 : "default(none)");
9159 : }
9160 8318 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_PRESENT)
9161 : ; /* Handled above. */
9162 : else
9163 7785 : gcc_checking_assert (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED);
9164 :
9165 8839 : return flags;
9166 : }
9167 :
9168 : /* Record the fact that DECL was used within the OMP context CTX.
9169 : IN_CODE is true when real code uses DECL, and false when we should
9170 : merely emit default(none) errors. Return true if DECL is going to
9171 : be remapped and thus DECL shouldn't be gimplified into its
9172 : DECL_VALUE_EXPR (if any). */
9173 :
9174 : static bool
9175 3916722 : omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
9176 : {
9177 3916722 : splay_tree_node n;
9178 3916722 : unsigned flags = in_code ? GOVD_SEEN : 0;
9179 3916722 : bool ret = false, shared;
9180 :
9181 3916722 : if (error_operand_p (decl))
9182 : return false;
9183 :
9184 3916722 : if (DECL_ARTIFICIAL (decl))
9185 : {
9186 2236488 : tree attr = lookup_attribute ("omp allocate var", DECL_ATTRIBUTES (decl));
9187 2236488 : if (attr)
9188 531 : decl = TREE_VALUE (TREE_VALUE (attr));
9189 : }
9190 :
9191 3916722 : if (ctx->region_type == ORT_NONE)
9192 248 : return lang_hooks.decls.omp_disregard_value_expr (decl, false);
9193 :
9194 3916474 : if (is_global_var (decl))
9195 : {
9196 : /* Threadprivate variables are predetermined. */
9197 502590 : if (DECL_THREAD_LOCAL_P (decl))
9198 13565 : return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
9199 :
9200 489025 : if (DECL_HAS_VALUE_EXPR_P (decl))
9201 : {
9202 4380 : if (ctx->region_type & ORT_ACC)
9203 : /* For OpenACC, defer expansion of value to avoid transferring
9204 : privatized common block data instead of im-/explicitly
9205 : transferred variables which are in common blocks. */
9206 : ;
9207 : else
9208 : {
9209 2104 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
9210 :
9211 2104 : if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
9212 618 : return omp_notice_threadprivate_variable (ctx, decl, value);
9213 : }
9214 : }
9215 :
9216 488407 : if (gimplify_omp_ctxp->outer_context == NULL
9217 114470 : && VAR_P (decl)
9218 602877 : && oacc_get_fn_attrib (current_function_decl))
9219 : {
9220 765 : location_t loc = DECL_SOURCE_LOCATION (decl);
9221 :
9222 765 : if (lookup_attribute ("omp declare target link",
9223 765 : DECL_ATTRIBUTES (decl)))
9224 : {
9225 48 : error_at (loc,
9226 : "%qE with %<link%> clause used in %<routine%> function",
9227 24 : DECL_NAME (decl));
9228 24 : return false;
9229 : }
9230 741 : else if (!lookup_attribute ("omp declare target",
9231 741 : DECL_ATTRIBUTES (decl)))
9232 : {
9233 132 : error_at (loc,
9234 : "%qE requires a %<declare%> directive for use "
9235 66 : "in a %<routine%> function", DECL_NAME (decl));
9236 66 : return false;
9237 : }
9238 : }
9239 : }
9240 :
9241 3902201 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9242 3902201 : if ((ctx->region_type & ORT_TARGET) != 0)
9243 : {
9244 852995 : if (n == NULL)
9245 : {
9246 45110 : unsigned nflags = flags;
9247 45110 : if ((ctx->region_type & ORT_ACC) == 0)
9248 : {
9249 34156 : bool is_declare_target = false;
9250 34156 : if (is_global_var (decl)
9251 34156 : && varpool_node::get_create (decl)->offloadable)
9252 : {
9253 7054 : struct gimplify_omp_ctx *octx;
9254 7054 : for (octx = ctx->outer_context;
9255 7062 : octx; octx = octx->outer_context)
9256 : {
9257 9 : n = splay_tree_lookup (octx->variables,
9258 : (splay_tree_key)decl);
9259 9 : if (n
9260 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED
9261 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
9262 : break;
9263 : }
9264 7054 : is_declare_target = octx == NULL;
9265 : }
9266 7054 : if (!is_declare_target)
9267 : {
9268 27103 : int gdmk;
9269 27103 : enum omp_clause_defaultmap_kind kind;
9270 27103 : if (lang_hooks.decls.omp_allocatable_p (decl))
9271 : gdmk = GDMK_ALLOCATABLE;
9272 26754 : else if (lang_hooks.decls.omp_scalar_target_p (decl))
9273 : gdmk = GDMK_SCALAR_TARGET;
9274 26679 : else if (lang_hooks.decls.omp_scalar_p (decl, false))
9275 : gdmk = GDMK_SCALAR;
9276 11183 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
9277 11183 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
9278 3105 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
9279 : == POINTER_TYPE)))
9280 : gdmk = GDMK_POINTER;
9281 : else
9282 : gdmk = GDMK_AGGREGATE;
9283 27103 : kind = lang_hooks.decls.omp_predetermined_mapping (decl);
9284 27103 : if (kind != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
9285 : {
9286 1096 : if (kind == OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE)
9287 101 : nflags |= GOVD_FIRSTPRIVATE;
9288 995 : else if (kind == OMP_CLAUSE_DEFAULTMAP_TO)
9289 995 : nflags |= GOVD_MAP | GOVD_MAP_TO_ONLY;
9290 : else
9291 0 : gcc_unreachable ();
9292 : }
9293 26007 : else if (ctx->defaultmap[gdmk] == 0)
9294 : {
9295 75 : tree d = lang_hooks.decls.omp_report_decl (decl);
9296 75 : error ("%qE not specified in enclosing %<target%>",
9297 75 : DECL_NAME (d));
9298 75 : inform (ctx->location, "enclosing %<target%>");
9299 : }
9300 25932 : else if (ctx->defaultmap[gdmk]
9301 25932 : & (GOVD_MAP_0LEN_ARRAY | GOVD_FIRSTPRIVATE))
9302 9136 : nflags |= ctx->defaultmap[gdmk];
9303 16796 : else if (ctx->defaultmap[gdmk] & GOVD_MAP_FORCE_PRESENT)
9304 : {
9305 42 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9306 42 : nflags |= ctx->defaultmap[gdmk] | GOVD_MAP_ALLOC_ONLY;
9307 : }
9308 : else
9309 : {
9310 16754 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9311 16754 : nflags |= ctx->defaultmap[gdmk] & ~GOVD_MAP;
9312 : }
9313 : }
9314 : }
9315 :
9316 45110 : struct gimplify_omp_ctx *octx = ctx->outer_context;
9317 45110 : if ((ctx->region_type & ORT_ACC) && octx)
9318 : {
9319 : /* Look in outer OpenACC contexts, to see if there's a
9320 : data attribute for this variable. */
9321 3535 : omp_notice_variable (octx, decl, in_code);
9322 :
9323 8842 : for (; octx; octx = octx->outer_context)
9324 : {
9325 3883 : if (!(octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)))
9326 : break;
9327 3883 : splay_tree_node n2
9328 3883 : = splay_tree_lookup (octx->variables,
9329 : (splay_tree_key) decl);
9330 3883 : if (n2)
9331 : {
9332 2111 : if (octx->region_type == ORT_ACC_HOST_DATA)
9333 4 : error ("variable %qE declared in enclosing "
9334 4 : "%<host_data%> region", DECL_NAME (decl));
9335 2111 : nflags |= GOVD_MAP;
9336 2111 : if (octx->region_type == ORT_ACC_DATA
9337 2107 : && (n2->value & GOVD_MAP_0LEN_ARRAY))
9338 288 : nflags |= GOVD_MAP_0LEN_ARRAY;
9339 2111 : goto found_outer;
9340 : }
9341 : }
9342 : }
9343 :
9344 42999 : if ((nflags & ~(GOVD_MAP_TO_ONLY | GOVD_MAP_FROM_ONLY
9345 : | GOVD_MAP_ALLOC_ONLY)) == flags)
9346 : {
9347 32725 : tree type = TREE_TYPE (decl);
9348 32725 : location_t loc = DECL_SOURCE_LOCATION (decl);
9349 :
9350 32725 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases
9351 32725 : && omp_privatize_by_reference (decl))
9352 28 : type = TREE_TYPE (type);
9353 :
9354 32725 : if (!verify_type_context (loc, TCTX_OMP_MAP_IMP_REF, type))
9355 : /* Check if TYPE can appear in a target region.
9356 : verify_type_context has already issued an error if it
9357 : can't. */
9358 0 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9359 32725 : else if (!omp_mappable_type (type))
9360 : {
9361 8 : error ("%qD referenced in target region does not have "
9362 : "a mappable type", decl);
9363 8 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9364 : }
9365 : else
9366 : {
9367 32717 : if ((ctx->region_type & ORT_ACC) != 0)
9368 8839 : nflags = oacc_default_clause (ctx, decl, flags);
9369 : else
9370 23878 : nflags |= GOVD_MAP;
9371 : }
9372 : }
9373 10274 : found_outer:
9374 45110 : omp_add_variable (ctx, decl, nflags);
9375 45110 : if (ctx->region_type & ORT_ACC)
9376 : /* For OpenACC, as remarked above, defer expansion. */
9377 : shared = false;
9378 : else
9379 34156 : shared = (nflags & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9380 45110 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9381 : }
9382 : else
9383 : {
9384 807885 : if (ctx->region_type & ORT_ACC)
9385 : /* For OpenACC, as remarked above, defer expansion. */
9386 : shared = false;
9387 : else
9388 511460 : shared = ((n->value | flags)
9389 511460 : & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9390 807885 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9391 : /* If nothing changed, there's nothing left to do. */
9392 807885 : if ((n->value & flags) == flags)
9393 : return ret;
9394 16656 : flags |= n->value;
9395 16656 : n->value = flags;
9396 : }
9397 61766 : goto do_outer;
9398 : }
9399 :
9400 3049206 : if (n == NULL)
9401 : {
9402 1183679 : if (ctx->region_type == ORT_WORKSHARE
9403 : || ctx->region_type == ORT_TASKGROUP
9404 561941 : || ctx->region_type == ORT_SIMD
9405 288998 : || ctx->region_type == ORT_ACC
9406 92745 : || (ctx->region_type & ORT_TARGET_DATA) != 0)
9407 1135649 : goto do_outer;
9408 :
9409 48030 : flags = omp_default_clause (ctx, decl, in_code, flags);
9410 :
9411 48030 : if ((flags & GOVD_PRIVATE)
9412 48030 : && lang_hooks.decls.omp_private_outer_ref (decl))
9413 6 : flags |= GOVD_PRIVATE_OUTER_REF;
9414 :
9415 48030 : omp_add_variable (ctx, decl, flags);
9416 :
9417 48030 : shared = (flags & GOVD_SHARED) != 0;
9418 48030 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9419 48030 : goto do_outer;
9420 : }
9421 :
9422 : /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd
9423 : lb, b or incr expressions, those shouldn't be turned into simd arrays. */
9424 1865527 : if (ctx->region_type == ORT_SIMD
9425 151440 : && ctx->in_for_exprs
9426 70 : && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT))
9427 : == GOVD_PRIVATE))
9428 1865527 : flags &= ~GOVD_SEEN;
9429 :
9430 1865527 : if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
9431 31919 : && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
9432 1897407 : && DECL_SIZE (decl))
9433 : {
9434 31879 : tree size;
9435 31879 : if (!poly_int_tree_p (DECL_SIZE (decl)))
9436 : {
9437 148 : splay_tree_node n2;
9438 148 : tree t = DECL_VALUE_EXPR (decl);
9439 148 : gcc_assert (INDIRECT_REF_P (t));
9440 148 : t = TREE_OPERAND (t, 0);
9441 148 : gcc_assert (DECL_P (t));
9442 148 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
9443 148 : n2->value |= GOVD_SEEN;
9444 : }
9445 31731 : else if (omp_privatize_by_reference (decl)
9446 4193 : && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
9447 35887 : && !poly_int_tree_p (size))
9448 : {
9449 1337 : splay_tree_node n2;
9450 1337 : gcc_assert (DECL_P (size));
9451 1337 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size);
9452 1337 : if (n2)
9453 629 : omp_notice_variable (ctx, size, true);
9454 : }
9455 : }
9456 :
9457 1865527 : if (ctx->region_type & ORT_ACC)
9458 : /* For OpenACC, as remarked above, defer expansion. */
9459 : shared = false;
9460 : else
9461 1683592 : shared = ((flags | n->value) & GOVD_SHARED) != 0;
9462 1865527 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9463 :
9464 : /* If nothing changed, there's nothing left to do. */
9465 1865527 : if ((n->value & flags) == flags)
9466 : return ret;
9467 31880 : flags |= n->value;
9468 31880 : n->value = flags;
9469 :
9470 1277325 : do_outer:
9471 : /* If the variable is private in the current context, then we don't
9472 : need to propagate anything to an outer context. */
9473 1277325 : if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF))
9474 : return ret;
9475 1266919 : if ((flags & (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9476 : == (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9477 : return ret;
9478 1266859 : if ((flags & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
9479 : | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9480 : == (GOVD_LASTPRIVATE | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9481 : return ret;
9482 1266859 : if (ctx->outer_context
9483 1266859 : && omp_notice_variable (ctx->outer_context, decl, in_code))
9484 2151 : return true;
9485 : return ret;
9486 : }
9487 :
9488 : /* Verify that DECL is private within CTX. If there's specific information
9489 : to the contrary in the innermost scope, generate an error. */
9490 :
9491 : static bool
9492 50339 : omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd)
9493 : {
9494 96124 : splay_tree_node n;
9495 :
9496 96124 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9497 96124 : if (n != NULL)
9498 : {
9499 17992 : if (n->value & GOVD_SHARED)
9500 : {
9501 407 : if (ctx == gimplify_omp_ctxp)
9502 : {
9503 0 : if (simd)
9504 0 : error ("iteration variable %qE is predetermined linear",
9505 0 : DECL_NAME (decl));
9506 : else
9507 0 : error ("iteration variable %qE should be private",
9508 0 : DECL_NAME (decl));
9509 0 : n->value = GOVD_PRIVATE;
9510 0 : return true;
9511 : }
9512 : else
9513 : return false;
9514 : }
9515 17585 : else if ((n->value & GOVD_EXPLICIT) != 0
9516 9735 : && (ctx == gimplify_omp_ctxp
9517 340 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9518 220 : && gimplify_omp_ctxp->outer_context == ctx)))
9519 : {
9520 9615 : if ((n->value & GOVD_FIRSTPRIVATE) != 0)
9521 4 : error ("iteration variable %qE should not be firstprivate",
9522 4 : DECL_NAME (decl));
9523 9611 : else if ((n->value & GOVD_REDUCTION) != 0)
9524 8 : error ("iteration variable %qE should not be reduction",
9525 8 : DECL_NAME (decl));
9526 9603 : else if (simd != 1 && (n->value & GOVD_LINEAR) != 0)
9527 58 : error ("iteration variable %qE should not be linear",
9528 58 : DECL_NAME (decl));
9529 : }
9530 17585 : return (ctx == gimplify_omp_ctxp
9531 17585 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9532 2618 : && gimplify_omp_ctxp->outer_context == ctx));
9533 : }
9534 :
9535 78132 : if (ctx->region_type != ORT_WORKSHARE
9536 : && ctx->region_type != ORT_TASKGROUP
9537 49558 : && ctx->region_type != ORT_SIMD
9538 36229 : && ctx->region_type != ORT_ACC)
9539 : return false;
9540 54076 : else if (ctx->outer_context)
9541 : return omp_is_private (ctx->outer_context, decl, simd);
9542 : return false;
9543 : }
9544 :
9545 : /* Return true if DECL is private within a parallel region
9546 : that binds to the current construct's context or in parallel
9547 : region's REDUCTION clause. */
9548 :
9549 : static bool
9550 11608 : omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
9551 : {
9552 11680 : splay_tree_node n;
9553 :
9554 11680 : do
9555 : {
9556 11680 : ctx = ctx->outer_context;
9557 11680 : if (ctx == NULL)
9558 : {
9559 2786 : if (is_global_var (decl))
9560 : return false;
9561 :
9562 : /* References might be private, but might be shared too,
9563 : when checking for copyprivate, assume they might be
9564 : private, otherwise assume they might be shared. */
9565 1292 : if (copyprivate)
9566 : return true;
9567 :
9568 1246 : if (omp_privatize_by_reference (decl))
9569 : return false;
9570 :
9571 : /* Treat C++ privatized non-static data members outside
9572 : of the privatization the same. */
9573 1200 : if (omp_member_access_dummy_var (decl))
9574 : return false;
9575 :
9576 1144 : return true;
9577 : }
9578 :
9579 8894 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
9580 :
9581 8894 : if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
9582 1291 : && (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0))
9583 : {
9584 242 : if ((ctx->region_type & ORT_TARGET_DATA) != 0
9585 238 : || n == NULL
9586 230 : || (n->value & GOVD_MAP) == 0)
9587 12 : continue;
9588 : return false;
9589 : }
9590 :
9591 7603 : if (n != NULL)
9592 : {
9593 5397 : if ((n->value & GOVD_LOCAL) != 0
9594 5397 : && omp_member_access_dummy_var (decl))
9595 : return false;
9596 5358 : return (n->value & GOVD_SHARED) == 0;
9597 : }
9598 :
9599 3255 : if (ctx->region_type == ORT_WORKSHARE
9600 : || ctx->region_type == ORT_TASKGROUP
9601 3199 : || ctx->region_type == ORT_SIMD
9602 3195 : || ctx->region_type == ORT_ACC)
9603 60 : continue;
9604 :
9605 : break;
9606 : }
9607 : while (1);
9608 : return false;
9609 : }
9610 :
9611 : /* Callback for walk_tree to find a DECL_EXPR for the given DECL. */
9612 :
9613 : static tree
9614 3148 : find_decl_expr (tree *tp, int *walk_subtrees, void *data)
9615 : {
9616 3148 : tree t = *tp;
9617 :
9618 : /* If this node has been visited, unmark it and keep looking. */
9619 3148 : if (TREE_CODE (t) == DECL_EXPR && DECL_EXPR_DECL (t) == (tree) data)
9620 : return t;
9621 :
9622 2724 : if (IS_TYPE_OR_DECL_P (t))
9623 452 : *walk_subtrees = 0;
9624 : return NULL_TREE;
9625 : }
9626 :
9627 :
9628 : /* Gimplify the affinity clause but effectively ignore it.
9629 : Generate:
9630 : var = begin;
9631 : if ((step > 1) ? var <= end : var > end)
9632 : locatator_var_expr; */
9633 :
9634 : static void
9635 510 : gimplify_omp_affinity (tree *list_p, gimple_seq *pre_p)
9636 : {
9637 510 : tree last_iter = NULL_TREE;
9638 510 : tree last_bind = NULL_TREE;
9639 510 : tree label = NULL_TREE;
9640 510 : tree *last_body = NULL;
9641 1287 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9642 777 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
9643 : {
9644 777 : tree t = OMP_CLAUSE_DECL (c);
9645 777 : if (OMP_ITERATOR_DECL_P (t))
9646 : {
9647 389 : if (TREE_VALUE (t) == null_pointer_node)
9648 201 : continue;
9649 188 : if (TREE_PURPOSE (t) != last_iter)
9650 : {
9651 127 : if (last_bind)
9652 : {
9653 9 : append_to_statement_list (label, last_body);
9654 9 : gimplify_and_add (last_bind, pre_p);
9655 9 : last_bind = NULL_TREE;
9656 : }
9657 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9658 : {
9659 147 : if (gimplify_expr (&OMP_ITERATOR_BEGIN (it), pre_p, NULL,
9660 : is_gimple_val, fb_rvalue) == GS_ERROR
9661 147 : || gimplify_expr (&OMP_ITERATOR_END (it), pre_p, NULL,
9662 : is_gimple_val, fb_rvalue) == GS_ERROR
9663 147 : || gimplify_expr (&OMP_ITERATOR_STEP (it), pre_p, NULL,
9664 : is_gimple_val, fb_rvalue) == GS_ERROR
9665 294 : || (gimplify_expr (&OMP_ITERATOR_ORIG_STEP (it), pre_p,
9666 : NULL, is_gimple_val, fb_rvalue)
9667 : == GS_ERROR))
9668 0 : return;
9669 : }
9670 127 : last_iter = TREE_PURPOSE (t);
9671 127 : tree block = OMP_ITERATOR_BLOCK (TREE_PURPOSE (t));
9672 127 : last_bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
9673 : NULL, block);
9674 127 : last_body = &BIND_EXPR_BODY (last_bind);
9675 127 : tree cond = NULL_TREE;
9676 127 : location_t loc = OMP_CLAUSE_LOCATION (c);
9677 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9678 : {
9679 147 : tree var = OMP_ITERATOR_VAR (it);
9680 147 : tree begin = OMP_ITERATOR_BEGIN (it);
9681 147 : tree end = OMP_ITERATOR_END (it);
9682 147 : tree step = OMP_ITERATOR_STEP (it);
9683 147 : loc = DECL_SOURCE_LOCATION (var);
9684 147 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
9685 : var, begin);
9686 147 : append_to_statement_list_force (tem, last_body);
9687 :
9688 147 : tree cond1 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9689 147 : step, build_zero_cst (TREE_TYPE (step)));
9690 147 : tree cond2 = fold_build2_loc (loc, LE_EXPR, boolean_type_node,
9691 : var, end);
9692 147 : tree cond3 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9693 : var, end);
9694 147 : cond1 = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
9695 : cond1, cond2, cond3);
9696 147 : if (cond)
9697 20 : cond = fold_build2_loc (loc, TRUTH_AND_EXPR,
9698 : boolean_type_node, cond, cond1);
9699 : else
9700 : cond = cond1;
9701 : }
9702 127 : tree cont_label = create_artificial_label (loc);
9703 127 : label = build1 (LABEL_EXPR, void_type_node, cont_label);
9704 127 : tree tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9705 : void_node,
9706 : build_and_jump (&cont_label));
9707 127 : append_to_statement_list_force (tem, last_body);
9708 : }
9709 188 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
9710 : {
9711 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t), 0),
9712 : last_body);
9713 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
9714 : }
9715 188 : if (error_operand_p (TREE_VALUE (t)))
9716 : return;
9717 188 : append_to_statement_list_force (TREE_VALUE (t), last_body);
9718 188 : TREE_VALUE (t) = null_pointer_node;
9719 : }
9720 : else
9721 : {
9722 388 : if (last_bind)
9723 : {
9724 9 : append_to_statement_list (label, last_body);
9725 9 : gimplify_and_add (last_bind, pre_p);
9726 9 : last_bind = NULL_TREE;
9727 : }
9728 388 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
9729 : {
9730 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
9731 : NULL, is_gimple_val, fb_rvalue);
9732 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
9733 : }
9734 388 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
9735 : return;
9736 388 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
9737 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
9738 : return;
9739 388 : gimplify_and_add (OMP_CLAUSE_DECL (c), pre_p);
9740 : }
9741 : }
9742 510 : if (last_bind)
9743 : {
9744 109 : append_to_statement_list (label, last_body);
9745 109 : gimplify_and_add (last_bind, pre_p);
9746 : }
9747 : return;
9748 : }
9749 :
9750 : /* Returns a tree expression containing the total iteration count of the
9751 : OpenMP iterator IT. */
9752 :
9753 : static tree
9754 391 : compute_omp_iterator_count (tree it, gimple_seq *pre_p)
9755 : {
9756 391 : tree tcnt = size_one_node;
9757 861 : for (; it; it = TREE_CHAIN (it))
9758 : {
9759 470 : if (gimplify_expr (&OMP_ITERATOR_BEGIN (it), pre_p, NULL,
9760 : is_gimple_val, fb_rvalue) == GS_ERROR
9761 470 : || gimplify_expr (&OMP_ITERATOR_END (it), pre_p, NULL,
9762 : is_gimple_val, fb_rvalue) == GS_ERROR
9763 470 : || gimplify_expr (&OMP_ITERATOR_STEP (it), pre_p, NULL,
9764 : is_gimple_val, fb_rvalue) == GS_ERROR
9765 940 : || (gimplify_expr (&OMP_ITERATOR_ORIG_STEP (it), pre_p, NULL,
9766 : is_gimple_val, fb_rvalue) == GS_ERROR))
9767 0 : return NULL_TREE;
9768 470 : tree var = OMP_ITERATOR_VAR (it);
9769 470 : tree begin = OMP_ITERATOR_BEGIN (it);
9770 470 : tree end = OMP_ITERATOR_END (it);
9771 470 : tree step = OMP_ITERATOR_STEP (it);
9772 470 : tree orig_step = OMP_ITERATOR_ORIG_STEP (it);
9773 470 : tree type = TREE_TYPE (var);
9774 470 : tree stype = TREE_TYPE (step);
9775 470 : location_t loc = DECL_SOURCE_LOCATION (var);
9776 470 : tree endmbegin;
9777 : /* Compute count for this iterator as
9778 : orig_step > 0
9779 : ? (begin < end ? (end - begin + (step - 1)) / step : 0)
9780 : : (begin > end ? (end - begin + (step + 1)) / step : 0)
9781 : and compute product of those for the entire clause. */
9782 470 : if (POINTER_TYPE_P (type))
9783 42 : endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR, stype, end, begin);
9784 : else
9785 428 : endmbegin = fold_build2_loc (loc, MINUS_EXPR, type, end, begin);
9786 : /* Account for iteration stopping on the end value in Fortran rather
9787 : than before it. */
9788 470 : tree stepm1 = step;
9789 470 : tree stepp1 = step;
9790 470 : if (!lang_GNU_Fortran ())
9791 : {
9792 372 : stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype, step,
9793 : build_int_cst (stype, 1));
9794 372 : stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
9795 : build_int_cst (stype, 1));
9796 : }
9797 470 : tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
9798 : unshare_expr (endmbegin), stepm1);
9799 470 : pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, pos, step);
9800 470 : tree neg = fold_build2_loc (loc, PLUS_EXPR, stype, endmbegin, stepp1);
9801 470 : if (TYPE_UNSIGNED (stype))
9802 : {
9803 31 : neg = fold_build1_loc (loc, NEGATE_EXPR, stype, neg);
9804 31 : step = fold_build1_loc (loc, NEGATE_EXPR, stype, step);
9805 : }
9806 470 : neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, neg, step);
9807 470 : step = NULL_TREE;
9808 470 : tree_code cmp_op = lang_GNU_Fortran () ? LE_EXPR : LT_EXPR;
9809 470 : tree cond = fold_build2_loc (loc, cmp_op, boolean_type_node, begin, end);
9810 470 : pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
9811 : build_int_cst (stype, 0));
9812 470 : cond = fold_build2_loc (loc, cmp_op, boolean_type_node, end, begin);
9813 470 : neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
9814 : build_int_cst (stype, 0));
9815 470 : tree osteptype = TREE_TYPE (orig_step);
9816 470 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9817 : build_int_cst (osteptype, 0));
9818 470 : tree cnt = fold_build3_loc (loc, COND_EXPR, stype, cond, pos, neg);
9819 470 : cnt = fold_convert_loc (loc, sizetype, cnt);
9820 470 : if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
9821 : fb_rvalue) == GS_ERROR)
9822 : return NULL_TREE;
9823 470 : tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
9824 : }
9825 391 : if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
9826 : return NULL_TREE;
9827 :
9828 391 : return tcnt;
9829 : }
9830 :
9831 : /* Build loops iterating over the space defined by the OpenMP iterator IT.
9832 : Returns a pointer to the BIND_EXPR_BODY in the innermost loop body.
9833 : LAST_BIND is set to point to the BIND_EXPR containing the whole loop. */
9834 :
9835 : static tree *
9836 391 : build_omp_iterator_loop (tree it, gimple_seq *pre_p, tree *last_bind)
9837 : {
9838 391 : if (*last_bind)
9839 31 : gimplify_and_add (*last_bind, pre_p);
9840 391 : tree block = OMP_ITERATOR_BLOCK (it);
9841 476 : tree block_stmts = lang_GNU_Fortran () ? BLOCK_SUBBLOCKS (block) : NULL_TREE;
9842 391 : *last_bind = build3 (BIND_EXPR, void_type_node,
9843 391 : BLOCK_VARS (block), NULL, block);
9844 391 : TREE_SIDE_EFFECTS (*last_bind) = 1;
9845 391 : tree *p = &BIND_EXPR_BODY (*last_bind);
9846 1252 : for (; it; it = TREE_CHAIN (it))
9847 : {
9848 470 : tree var = OMP_ITERATOR_VAR (it);
9849 470 : tree begin = OMP_ITERATOR_BEGIN (it);
9850 470 : tree end = OMP_ITERATOR_END (it);
9851 470 : tree step = OMP_ITERATOR_STEP (it);
9852 470 : tree orig_step = OMP_ITERATOR_ORIG_STEP (it);
9853 470 : block = OMP_ITERATOR_BLOCK (it);
9854 470 : tree type = TREE_TYPE (var);
9855 470 : location_t loc = DECL_SOURCE_LOCATION (var);
9856 : /* Emit:
9857 : var = begin;
9858 : goto cond_label;
9859 : beg_label:
9860 : ...
9861 : var = var + step;
9862 : cond_label:
9863 : if (orig_step > 0) {
9864 : if (var < end) goto beg_label; // <= for Fortran
9865 : } else {
9866 : if (var > end) goto beg_label; // >= for Fortran
9867 : }
9868 : for each iterator, with inner iterators added to
9869 : the ... above. */
9870 470 : tree beg_label = create_artificial_label (loc);
9871 470 : tree cond_label = NULL_TREE;
9872 470 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, begin);
9873 470 : append_to_statement_list_force (tem, p);
9874 470 : tem = build_and_jump (&cond_label);
9875 470 : append_to_statement_list_force (tem, p);
9876 470 : tem = build1 (LABEL_EXPR, void_type_node, beg_label);
9877 470 : append_to_statement_list (tem, p);
9878 470 : tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
9879 : NULL_TREE, NULL_TREE);
9880 470 : TREE_SIDE_EFFECTS (bind) = 1;
9881 470 : SET_EXPR_LOCATION (bind, loc);
9882 470 : append_to_statement_list_force (bind, p);
9883 470 : if (POINTER_TYPE_P (type))
9884 42 : tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
9885 : var, fold_convert_loc (loc, sizetype, step));
9886 : else
9887 428 : tem = build2_loc (loc, PLUS_EXPR, type, var, step);
9888 470 : tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, tem);
9889 470 : append_to_statement_list_force (tem, p);
9890 470 : tem = build1 (LABEL_EXPR, void_type_node, cond_label);
9891 470 : append_to_statement_list (tem, p);
9892 842 : tree cond = fold_build2_loc (loc, lang_GNU_Fortran () ? LE_EXPR : LT_EXPR,
9893 : boolean_type_node, var, end);
9894 470 : tree pos = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9895 : build_and_jump (&beg_label), void_node);
9896 842 : cond = fold_build2_loc (loc, lang_GNU_Fortran () ? GE_EXPR : GT_EXPR,
9897 : boolean_type_node, var, end);
9898 470 : tree neg = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9899 : build_and_jump (&beg_label), void_node);
9900 470 : tree osteptype = TREE_TYPE (orig_step);
9901 470 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9902 : build_int_cst (osteptype, 0));
9903 470 : tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, pos, neg);
9904 470 : append_to_statement_list_force (tem, p);
9905 470 : p = &BIND_EXPR_BODY (bind);
9906 : /* The Fortran front-end stashes statements into the BLOCK_SUBBLOCKS
9907 : of the last element of the first iterator. These should go into the
9908 : body of the innermost loop. */
9909 470 : if (!TREE_CHAIN (it))
9910 391 : append_to_statement_list_force (block_stmts, p);
9911 : }
9912 :
9913 391 : return p;
9914 : }
9915 :
9916 :
9917 : /* Callback for walk_tree to find a VAR_DECL (stored in DATA) in the
9918 : tree TP. */
9919 :
9920 : static tree
9921 3900 : find_var_decl (tree *tp, int *, void *data)
9922 : {
9923 3900 : if (*tp == (tree) data)
9924 369 : return *tp;
9925 :
9926 : return NULL_TREE;
9927 : }
9928 :
9929 : /* Returns an element-by-element copy of OMP iterator tree IT. If
9930 : EXPAND is true, force the result to be an expanded iterator; otherwise
9931 : it makes the copy the same size as IT. */
9932 : static tree
9933 337 : copy_omp_iterator (tree it, bool expand = false)
9934 : {
9935 337 : int elem_count = TREE_VEC_LENGTH (it);
9936 337 : tree new_it =
9937 337 : (expand ? make_expanded_omp_iterator () : make_tree_vec (elem_count));
9938 2359 : for (int i = 0; i < TREE_VEC_LENGTH (it); i++)
9939 2022 : TREE_VEC_ELT (new_it, i) = TREE_VEC_ELT (it, i);
9940 337 : return new_it;
9941 : }
9942 :
9943 : /* Helper function for walk_tree in remap_omp_iterator_var. */
9944 :
9945 : static tree
9946 1063 : remap_omp_iterator_var_1 (tree *tp, int *, void *data)
9947 : {
9948 1063 : tree old_var = ((tree *) data)[0];
9949 1063 : tree new_var = ((tree *) data)[1];
9950 :
9951 1063 : if (*tp == old_var)
9952 106 : *tp = new_var;
9953 1063 : return NULL_TREE;
9954 : }
9955 :
9956 : /* Replace instances of OLD_VAR in TP with NEW_VAR. */
9957 :
9958 : static void
9959 212 : remap_omp_iterator_var (tree *tp, tree old_var, tree new_var)
9960 : {
9961 212 : tree vars[2] = { old_var, new_var };
9962 212 : walk_tree (tp, remap_omp_iterator_var_1, vars, NULL);
9963 212 : }
9964 :
9965 : /* Scan through all clauses using OpenMP iterators in LIST_P. If any
9966 : clauses have iterators with variables that are not used by the clause
9967 : decl or size, issue a warning and replace the iterator with a copy with
9968 : the unused variables removed. */
9969 :
9970 : static void
9971 27824 : remove_unused_omp_iterator_vars (tree *list_p)
9972 : {
9973 27824 : auto_vec< vec<tree> > iter_vars;
9974 27824 : auto_vec<tree> new_iterators;
9975 :
9976 81122 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9977 : {
9978 53298 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
9979 53234 : continue;
9980 288 : auto_vec<tree> vars;
9981 288 : bool need_new_iterators = false;
9982 734 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
9983 : {
9984 446 : tree var = OMP_ITERATOR_VAR (it);
9985 446 : tree t = walk_tree (&OMP_CLAUSE_DECL (c), find_var_decl, var, NULL);
9986 446 : if (t == NULL_TREE)
9987 143 : t = walk_tree (&OMP_CLAUSE_SIZE (c), find_var_decl, var, NULL);
9988 143 : if (t == NULL_TREE)
9989 : need_new_iterators = true;
9990 : else
9991 369 : vars.safe_push (var);
9992 : }
9993 288 : if (!need_new_iterators)
9994 211 : continue;
9995 77 : if (vars.is_empty ())
9996 : {
9997 : /* No iteration variables are used in the clause - remove the
9998 : iterator from the clause. */
9999 13 : OMP_CLAUSE_ITERATORS (c) = NULL_TREE;
10000 13 : continue;
10001 : }
10002 :
10003 : /* If a new iterator has been created for the current set of used
10004 : iterator variables, then use that as the iterator. Otherwise,
10005 : create a new iterator for the current iterator variable set. */
10006 : unsigned i;
10007 106 : for (i = 0; i < iter_vars.length (); i++)
10008 : {
10009 124 : if (vars.length () != iter_vars[i].length ())
10010 0 : continue;
10011 : bool identical_p = true;
10012 150 : for (unsigned j = 0; j < vars.length () && identical_p; j++)
10013 88 : identical_p = vars[j] == iter_vars[i][j];
10014 :
10015 62 : if (identical_p)
10016 : break;
10017 : }
10018 64 : if (i < iter_vars.length ())
10019 20 : OMP_CLAUSE_ITERATORS (c) = new_iterators[i];
10020 : else
10021 : {
10022 44 : tree new_iters = NULL_TREE;
10023 44 : tree *new_iters_p = &new_iters;
10024 44 : tree new_vars = NULL_TREE;
10025 44 : tree *new_vars_p = &new_vars;
10026 44 : i = 0;
10027 140 : for (tree it = OMP_CLAUSE_ITERATORS (c); it && i < vars.length();
10028 96 : it = TREE_CHAIN (it))
10029 : {
10030 96 : tree var = OMP_ITERATOR_VAR (it);
10031 96 : if (var == vars[i])
10032 : {
10033 74 : *new_iters_p = copy_omp_iterator (it);
10034 74 : *new_vars_p = build_decl (OMP_CLAUSE_LOCATION (c), VAR_DECL,
10035 74 : DECL_NAME (var), TREE_TYPE (var));
10036 74 : DECL_ARTIFICIAL (*new_vars_p) = 1;
10037 74 : DECL_CONTEXT (*new_vars_p) = DECL_CONTEXT (var);
10038 74 : OMP_ITERATOR_VAR (*new_iters_p) = *new_vars_p;
10039 74 : new_iters_p = &TREE_CHAIN (*new_iters_p);
10040 74 : new_vars_p = &DECL_CHAIN (*new_vars_p);
10041 74 : i++;
10042 : }
10043 : }
10044 44 : tree old_block = OMP_ITERATOR_BLOCK (OMP_CLAUSE_ITERATORS (c));
10045 44 : tree new_block = make_node (BLOCK);
10046 44 : BLOCK_VARS (new_block) = new_vars;
10047 44 : if (BLOCK_SUBBLOCKS (old_block))
10048 : {
10049 4 : BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block);
10050 4 : BLOCK_SUBBLOCKS (old_block) = NULL_TREE;
10051 : }
10052 44 : OMP_ITERATOR_BLOCK (new_iters) = new_block;
10053 44 : new_iterators.safe_push (new_iters);
10054 44 : iter_vars.safe_push (vars.copy ());
10055 44 : OMP_CLAUSE_ITERATORS (c) = new_iters;
10056 : }
10057 :
10058 : /* Remap clause to use the new variables. */
10059 64 : i = 0;
10060 170 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
10061 : {
10062 106 : tree old_var = vars[i++];
10063 106 : tree new_var = OMP_ITERATOR_VAR (it);
10064 106 : remap_omp_iterator_var (&OMP_CLAUSE_DECL (c), old_var, new_var);
10065 106 : remap_omp_iterator_var (&OMP_CLAUSE_SIZE (c), old_var, new_var);
10066 : }
10067 288 : }
10068 :
10069 27868 : for (unsigned i = 0; i < iter_vars.length (); i++)
10070 44 : iter_vars[i].release ();
10071 27824 : }
10072 :
10073 272 : struct iterator_loop_info_t
10074 : {
10075 : tree bind;
10076 : tree count;
10077 : tree index;
10078 : tree body_label;
10079 : auto_vec<tree> clauses;
10080 : };
10081 :
10082 : typedef hash_map<tree, iterator_loop_info_t> iterator_loop_info_map_t;
10083 :
10084 : /* Builds a loop to expand any OpenMP iterators in the clauses in LIST_P,
10085 : reusing any previously built loops if they use the same set of iterators.
10086 : Generated Gimple statements are placed into LOOPS_SEQ_P. The clause
10087 : iterators are updated with information on how and where to insert code into
10088 : the loop body. */
10089 :
10090 : static void
10091 27824 : build_omp_iterators_loops (tree *list_p, gimple_seq *loops_seq_p)
10092 : {
10093 27824 : iterator_loop_info_map_t loops;
10094 :
10095 81122 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10096 : {
10097 53298 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10098 53035 : continue;
10099 :
10100 275 : bool built_p;
10101 275 : iterator_loop_info_t &loop
10102 275 : = loops.get_or_insert (OMP_CLAUSE_ITERATORS (c), &built_p);
10103 :
10104 275 : if (!built_p)
10105 : {
10106 136 : loop.count = compute_omp_iterator_count (OMP_CLAUSE_ITERATORS (c),
10107 : loops_seq_p);
10108 136 : if (!loop.count)
10109 0 : continue;
10110 136 : if (integer_zerop (loop.count))
10111 8 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
10112 : "iteration count is zero");
10113 :
10114 136 : loop.bind = NULL_TREE;
10115 136 : tree *body = build_omp_iterator_loop (OMP_CLAUSE_ITERATORS (c),
10116 : loops_seq_p, &loop.bind);
10117 :
10118 136 : loop.index = create_tmp_var (sizetype);
10119 136 : SET_EXPR_LOCATION (loop.bind, OMP_CLAUSE_LOCATION (c));
10120 :
10121 : /* BEFORE LOOP: */
10122 : /* idx = -1; */
10123 : /* This should be initialized to before the individual elements,
10124 : as idx is pre-incremented in the loop body. */
10125 136 : gimple *assign = gimple_build_assign (loop.index, size_int (-1));
10126 136 : gimple_seq_add_stmt (loops_seq_p, assign);
10127 :
10128 : /* IN LOOP BODY: */
10129 : /* Create a label so we can find this point later. */
10130 136 : loop.body_label = create_artificial_label (OMP_CLAUSE_LOCATION (c));
10131 136 : tree tem = build1 (LABEL_EXPR, void_type_node, loop.body_label);
10132 136 : append_to_statement_list_force (tem, body);
10133 :
10134 : /* idx += 2; */
10135 136 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10136 : void_type_node, loop.index,
10137 : size_binop (PLUS_EXPR, loop.index, size_int (2)));
10138 136 : append_to_statement_list_force (tem, body);
10139 : }
10140 :
10141 : /* Create array to hold expanded values. */
10142 275 : tree last_count_2 = size_binop (MULT_EXPR, loop.count, size_int (2));
10143 275 : tree arr_length = size_binop (PLUS_EXPR, last_count_2, size_int (1));
10144 275 : tree elems = NULL_TREE;
10145 275 : if (TREE_CONSTANT (arr_length))
10146 : {
10147 263 : tree type = build_array_type (ptr_type_node,
10148 : build_index_type (arr_length));
10149 263 : elems = create_tmp_var_raw (type, "omp_iter_data");
10150 263 : TREE_ADDRESSABLE (elems) = 1;
10151 263 : gimple_add_tmp_var (elems);
10152 : }
10153 : else
10154 : {
10155 : /* Handle dynamic sizes. */
10156 12 : sorry ("dynamic iterator sizes not implemented yet");
10157 12 : OMP_CLAUSE_ITERATORS (c) = NULL_TREE;
10158 12 : continue;
10159 : }
10160 :
10161 : /* BEFORE LOOP: */
10162 : /* elems[0] = count; */
10163 263 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, size_int (0),
10164 : NULL_TREE, NULL_TREE);
10165 263 : tree tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10166 : void_type_node, lhs, loop.count);
10167 263 : gimplify_and_add (tem, loops_seq_p);
10168 :
10169 : /* Make a copy of the iterator with extra info at the end. */
10170 263 : tree new_iterator = copy_omp_iterator (OMP_CLAUSE_ITERATORS (c), true);
10171 263 : OMP_ITERATOR_LABEL (new_iterator) = loop.body_label;
10172 263 : OMP_ITERATOR_INDEX (new_iterator) = loop.index;
10173 263 : OMP_ITERATOR_ELEMS (new_iterator) = elems;
10174 263 : TREE_CHAIN (new_iterator) = TREE_CHAIN (OMP_CLAUSE_ITERATORS (c));
10175 263 : OMP_CLAUSE_ITERATORS (c) = new_iterator;
10176 :
10177 263 : loop.clauses.safe_push (c);
10178 : }
10179 :
10180 : /* Now gimplify and add all the loops that were built. */
10181 27960 : for (hash_map<tree, iterator_loop_info_t>::iterator it = loops.begin ();
10182 55784 : it != loops.end (); ++it)
10183 136 : gimplify_and_add ((*it).second.bind, loops_seq_p);
10184 27824 : }
10185 :
10186 : /* Helper function for enter_omp_iterator_loop_context. */
10187 :
10188 : static gimple_seq *
10189 2950 : enter_omp_iterator_loop_context_1 (tree iterator, gimple_seq *loops_seq_p)
10190 : {
10191 : /* Drill into the nested bind expressions to get to the loop body. */
10192 2950 : for (gimple_stmt_iterator gsi = gsi_start (*loops_seq_p);
10193 19569 : !gsi_end_p (gsi); gsi_next (&gsi))
10194 : {
10195 18965 : gimple *stmt = gsi_stmt (gsi);
10196 :
10197 18965 : switch (gimple_code (stmt))
10198 : {
10199 2252 : case GIMPLE_BIND:
10200 2252 : {
10201 2252 : gbind *bind_stmt = as_a<gbind *> (stmt);
10202 2252 : gimple_push_bind_expr (bind_stmt);
10203 2252 : gimple_seq *bind_body_p = gimple_bind_body_ptr (bind_stmt);
10204 2252 : gimple_seq *seq =
10205 2252 : enter_omp_iterator_loop_context_1 (iterator, bind_body_p);
10206 2252 : if (seq)
10207 : return seq;
10208 604 : gimple_pop_bind_expr ();
10209 : }
10210 604 : break;
10211 3 : case GIMPLE_TRY:
10212 3 : {
10213 3 : gimple_seq *try_eval_p = gimple_try_eval_ptr (stmt);
10214 3 : gimple_seq *seq =
10215 3 : enter_omp_iterator_loop_context_1 (iterator, try_eval_p);
10216 3 : if (seq)
10217 : return seq;
10218 : }
10219 : break;
10220 2994 : case GIMPLE_LABEL:
10221 2994 : {
10222 2994 : glabel *label_stmt = as_a<glabel *> (stmt);
10223 2994 : tree label = gimple_label_label (label_stmt);
10224 2994 : if (label == OMP_ITERATOR_LABEL (iterator))
10225 : return loops_seq_p;
10226 : }
10227 : break;
10228 : default:
10229 : break;
10230 : }
10231 : }
10232 :
10233 : return NULL;
10234 : }
10235 :
10236 : /* Enter the Gimplification context in LOOPS_SEQ_P for the iterator loop
10237 : associated with OpenMP clause C. Returns the gimple_seq for the loop body
10238 : if C has OpenMP iterators, or ALT_SEQ_P if not. */
10239 :
10240 : static gimple_seq *
10241 65274 : enter_omp_iterator_loop_context (tree c, gimple_seq *loops_seq_p,
10242 : gimple_seq *alt_seq_p)
10243 : {
10244 65274 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10245 : return alt_seq_p;
10246 :
10247 695 : push_gimplify_context ();
10248 :
10249 695 : gimple_seq *seq = enter_omp_iterator_loop_context_1 (OMP_CLAUSE_ITERATORS (c),
10250 : loops_seq_p);
10251 695 : gcc_assert (seq);
10252 : return seq;
10253 : }
10254 :
10255 : /* Enter the Gimplification context in STMT for the iterator loop associated
10256 : with OpenMP clause C. Returns the gimple_seq for the loop body if C has
10257 : OpenMP iterators, or ALT_SEQ_P if not. */
10258 :
10259 : gimple_seq *
10260 434 : enter_omp_iterator_loop_context (tree c, gomp_target *stmt,
10261 : gimple_seq *alt_seq_p)
10262 : {
10263 434 : gimple_seq *loops_seq_p = gimple_omp_target_iterator_loops_ptr (stmt);
10264 434 : return enter_omp_iterator_loop_context (c, loops_seq_p, alt_seq_p);
10265 : }
10266 :
10267 : /* Exit the Gimplification context for the OpenMP clause C. */
10268 :
10269 : void
10270 65364 : exit_omp_iterator_loop_context (tree c)
10271 : {
10272 65364 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10273 : return;
10274 2343 : while (!gimplify_ctxp->bind_expr_stack.is_empty ())
10275 1648 : gimple_pop_bind_expr ();
10276 695 : pop_gimplify_context (NULL);
10277 : }
10278 :
10279 : /* If *LIST_P contains any OpenMP depend clauses with iterators,
10280 : lower all the depend clauses by populating corresponding depend
10281 : array. Returns 0 if there are no such depend clauses, or
10282 : 2 if all depend clauses should be removed, 1 otherwise. */
10283 :
10284 : static int
10285 1905 : gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
10286 : {
10287 1905 : tree c;
10288 1905 : gimple *g;
10289 1905 : size_t n[5] = { 0, 0, 0, 0, 0 };
10290 1905 : bool unused[5];
10291 1905 : tree counts[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
10292 1905 : tree last_iter = NULL_TREE, last_count = NULL_TREE;
10293 1905 : size_t i, j;
10294 1905 : location_t first_loc = UNKNOWN_LOCATION;
10295 :
10296 6250 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10297 4345 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10298 : {
10299 2207 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10300 : {
10301 : case OMP_CLAUSE_DEPEND_IN:
10302 : i = 2;
10303 : break;
10304 : case OMP_CLAUSE_DEPEND_OUT:
10305 : case OMP_CLAUSE_DEPEND_INOUT:
10306 : i = 0;
10307 : break;
10308 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10309 : i = 1;
10310 : break;
10311 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10312 : i = 3;
10313 : break;
10314 : case OMP_CLAUSE_DEPEND_INOUTSET:
10315 : i = 4;
10316 : break;
10317 0 : default:
10318 0 : gcc_unreachable ();
10319 : }
10320 2207 : tree t = OMP_CLAUSE_DECL (c);
10321 2207 : if (first_loc == UNKNOWN_LOCATION)
10322 1905 : first_loc = OMP_CLAUSE_LOCATION (c);
10323 2207 : if (OMP_ITERATOR_DECL_P (t))
10324 : {
10325 302 : if (TREE_PURPOSE (t) != last_iter)
10326 : {
10327 255 : tree tcnt = compute_omp_iterator_count (TREE_PURPOSE (t),
10328 : pre_p);
10329 255 : if (!tcnt)
10330 : return 2;
10331 255 : last_iter = TREE_PURPOSE (t);
10332 255 : last_count = tcnt;
10333 : }
10334 302 : if (counts[i] == NULL_TREE)
10335 248 : counts[i] = last_count;
10336 : else
10337 54 : counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
10338 : PLUS_EXPR, counts[i], last_count);
10339 : }
10340 : else
10341 1905 : n[i]++;
10342 : }
10343 10620 : for (i = 0; i < 5; i++)
10344 8925 : if (counts[i])
10345 : break;
10346 1905 : if (i == 5)
10347 : return 0;
10348 :
10349 210 : tree total = size_zero_node;
10350 1260 : for (i = 0; i < 5; i++)
10351 : {
10352 1050 : unused[i] = counts[i] == NULL_TREE && n[i] == 0;
10353 1050 : if (counts[i] == NULL_TREE)
10354 802 : counts[i] = size_zero_node;
10355 1050 : if (n[i])
10356 44 : counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
10357 1050 : if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
10358 : fb_rvalue) == GS_ERROR)
10359 : return 2;
10360 1050 : total = size_binop (PLUS_EXPR, total, counts[i]);
10361 : }
10362 :
10363 210 : if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
10364 : == GS_ERROR)
10365 : return 2;
10366 210 : bool is_old = unused[1] && unused[3] && unused[4];
10367 210 : tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
10368 : size_int (is_old ? 1 : 4));
10369 210 : if (!unused[4])
10370 3 : totalpx = size_binop (PLUS_EXPR, totalpx,
10371 : size_binop (MULT_EXPR, counts[4], size_int (2)));
10372 210 : tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
10373 210 : tree array = create_tmp_var_raw (type);
10374 210 : TREE_ADDRESSABLE (array) = 1;
10375 210 : if (!poly_int_tree_p (totalpx))
10376 : {
10377 83 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
10378 83 : gimplify_type_sizes (TREE_TYPE (array), pre_p);
10379 83 : if (gimplify_omp_ctxp)
10380 : {
10381 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
10382 : while (ctx
10383 22 : && (ctx->region_type == ORT_WORKSHARE
10384 : || ctx->region_type == ORT_TASKGROUP
10385 22 : || ctx->region_type == ORT_SIMD
10386 22 : || ctx->region_type == ORT_ACC))
10387 0 : ctx = ctx->outer_context;
10388 22 : if (ctx)
10389 22 : omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
10390 : }
10391 83 : gimplify_vla_decl (array, pre_p);
10392 : }
10393 : else
10394 127 : gimple_add_tmp_var (array);
10395 210 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
10396 : NULL_TREE);
10397 210 : tree tem;
10398 210 : if (!is_old)
10399 : {
10400 31 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10401 : build_int_cst (ptr_type_node, 0));
10402 31 : gimplify_and_add (tem, pre_p);
10403 31 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
10404 : NULL_TREE);
10405 : }
10406 210 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10407 : fold_convert (ptr_type_node, total));
10408 210 : gimplify_and_add (tem, pre_p);
10409 816 : for (i = 1; i < (is_old ? 2 : 4); i++)
10410 : {
10411 272 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
10412 : NULL_TREE, NULL_TREE);
10413 272 : tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
10414 272 : gimplify_and_add (tem, pre_p);
10415 : }
10416 :
10417 : tree cnts[6];
10418 740 : for (j = 5; j; j--)
10419 740 : if (!unused[j - 1])
10420 : break;
10421 1260 : for (i = 0; i < 5; i++)
10422 : {
10423 1050 : if (i && (i >= j || unused[i - 1]))
10424 : {
10425 790 : cnts[i] = cnts[i - 1];
10426 790 : continue;
10427 : }
10428 260 : cnts[i] = create_tmp_var (sizetype);
10429 260 : if (i == 0)
10430 241 : g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
10431 : else
10432 : {
10433 50 : tree t;
10434 50 : if (is_old)
10435 38 : t = size_binop (PLUS_EXPR, counts[0], size_int (2));
10436 : else
10437 12 : t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
10438 50 : if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
10439 : == GS_ERROR)
10440 0 : return 2;
10441 50 : g = gimple_build_assign (cnts[i], t);
10442 : }
10443 260 : gimple_seq_add_stmt (pre_p, g);
10444 : }
10445 210 : if (unused[4])
10446 207 : cnts[5] = NULL_TREE;
10447 : else
10448 : {
10449 3 : tree t = size_binop (PLUS_EXPR, total, size_int (5));
10450 3 : cnts[5] = create_tmp_var (sizetype);
10451 3 : g = gimple_build_assign (cnts[i], t);
10452 3 : gimple_seq_add_stmt (pre_p, g);
10453 : }
10454 :
10455 210 : last_iter = NULL_TREE;
10456 210 : tree last_bind = NULL_TREE;
10457 210 : tree *last_body = NULL;
10458 573 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10459 363 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10460 : {
10461 348 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10462 : {
10463 : case OMP_CLAUSE_DEPEND_IN:
10464 : i = 2;
10465 : break;
10466 : case OMP_CLAUSE_DEPEND_OUT:
10467 : case OMP_CLAUSE_DEPEND_INOUT:
10468 : i = 0;
10469 : break;
10470 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10471 : i = 1;
10472 : break;
10473 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10474 : i = 3;
10475 : break;
10476 : case OMP_CLAUSE_DEPEND_INOUTSET:
10477 : i = 4;
10478 : break;
10479 0 : default:
10480 0 : gcc_unreachable ();
10481 : }
10482 348 : tree t = OMP_CLAUSE_DECL (c);
10483 348 : if (OMP_ITERATOR_DECL_P (t))
10484 : {
10485 302 : if (TREE_PURPOSE (t) != last_iter)
10486 : {
10487 255 : last_body = build_omp_iterator_loop (TREE_PURPOSE (t), pre_p,
10488 : &last_bind);
10489 255 : SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
10490 : }
10491 302 : last_iter = TREE_PURPOSE (t);
10492 302 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
10493 : {
10494 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
10495 : 0), last_body);
10496 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
10497 : }
10498 302 : if (error_operand_p (TREE_VALUE (t)))
10499 : return 2;
10500 302 : if (TREE_VALUE (t) != null_pointer_node)
10501 296 : TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
10502 302 : if (i == 4)
10503 : {
10504 3 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10505 : NULL_TREE, NULL_TREE);
10506 3 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10507 : NULL_TREE, NULL_TREE);
10508 3 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10509 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10510 : void_type_node, r, r2);
10511 3 : append_to_statement_list_force (tem, last_body);
10512 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10513 : void_type_node, cnts[i],
10514 : size_binop (PLUS_EXPR, cnts[i],
10515 : size_int (1)));
10516 3 : append_to_statement_list_force (tem, last_body);
10517 3 : i = 5;
10518 : }
10519 302 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10520 : NULL_TREE, NULL_TREE);
10521 604 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10522 302 : void_type_node, r, TREE_VALUE (t));
10523 302 : append_to_statement_list_force (tem, last_body);
10524 302 : if (i == 5)
10525 : {
10526 3 : r = build4 (ARRAY_REF, ptr_type_node, array,
10527 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10528 : NULL_TREE, NULL_TREE);
10529 3 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10530 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10531 : void_type_node, r, tem);
10532 3 : append_to_statement_list_force (tem, last_body);
10533 : }
10534 302 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10535 : void_type_node, cnts[i],
10536 302 : size_binop (PLUS_EXPR, cnts[i],
10537 : size_int (1 + (i == 5))));
10538 302 : append_to_statement_list_force (tem, last_body);
10539 302 : TREE_VALUE (t) = null_pointer_node;
10540 : }
10541 : else
10542 : {
10543 46 : if (last_bind)
10544 : {
10545 18 : gimplify_and_add (last_bind, pre_p);
10546 18 : last_bind = NULL_TREE;
10547 : }
10548 46 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
10549 : {
10550 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
10551 : NULL, is_gimple_val, fb_rvalue);
10552 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
10553 : }
10554 46 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
10555 : return 2;
10556 46 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
10557 46 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
10558 46 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
10559 : is_gimple_val, fb_rvalue) == GS_ERROR)
10560 : return 2;
10561 46 : if (i == 4)
10562 : {
10563 0 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10564 : NULL_TREE, NULL_TREE);
10565 0 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10566 : NULL_TREE, NULL_TREE);
10567 0 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10568 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, r2);
10569 0 : gimplify_and_add (tem, pre_p);
10570 0 : g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR,
10571 : cnts[i],
10572 : size_int (1)));
10573 0 : gimple_seq_add_stmt (pre_p, g);
10574 0 : i = 5;
10575 : }
10576 46 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10577 : NULL_TREE, NULL_TREE);
10578 46 : tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
10579 46 : gimplify_and_add (tem, pre_p);
10580 46 : if (i == 5)
10581 : {
10582 0 : r = build4 (ARRAY_REF, ptr_type_node, array,
10583 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10584 : NULL_TREE, NULL_TREE);
10585 0 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10586 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, tem);
10587 0 : append_to_statement_list_force (tem, last_body);
10588 0 : gimplify_and_add (tem, pre_p);
10589 : }
10590 46 : g = gimple_build_assign (cnts[i],
10591 46 : size_binop (PLUS_EXPR, cnts[i],
10592 : size_int (1 + (i == 5))));
10593 46 : gimple_seq_add_stmt (pre_p, g);
10594 : }
10595 : }
10596 210 : if (last_bind)
10597 206 : gimplify_and_add (last_bind, pre_p);
10598 210 : tree cond = boolean_false_node;
10599 210 : if (is_old)
10600 : {
10601 179 : if (!unused[0])
10602 92 : cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
10603 : size_binop_loc (first_loc, PLUS_EXPR, counts[0],
10604 : size_int (2)));
10605 179 : if (!unused[2])
10606 125 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10607 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10608 : cnts[2],
10609 : size_binop_loc (first_loc, PLUS_EXPR,
10610 : totalpx,
10611 : size_int (1))));
10612 : }
10613 : else
10614 : {
10615 31 : tree prev = size_int (5);
10616 186 : for (i = 0; i < 5; i++)
10617 : {
10618 155 : if (unused[i])
10619 112 : continue;
10620 43 : prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
10621 43 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10622 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10623 : cnts[i], unshare_expr (prev)));
10624 : }
10625 : }
10626 210 : tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
10627 : build_call_expr_loc (first_loc,
10628 : builtin_decl_explicit (BUILT_IN_TRAP),
10629 : 0), void_node);
10630 210 : gimplify_and_add (tem, pre_p);
10631 210 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10632 210 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
10633 210 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10634 210 : OMP_CLAUSE_CHAIN (c) = *list_p;
10635 210 : *list_p = c;
10636 210 : return 1;
10637 : }
10638 :
10639 : /* True if mapping node C maps, or unmaps, a (Fortran) array descriptor. */
10640 :
10641 : static bool
10642 126114 : omp_map_clause_descriptor_p (tree c)
10643 : {
10644 126114 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
10645 : return false;
10646 :
10647 126110 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)
10648 : return true;
10649 :
10650 82892 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
10651 74854 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE)
10652 83374 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (c))
10653 6135 : return true;
10654 :
10655 : return false;
10656 : }
10657 :
10658 : /* For a set of mappings describing an array section pointed to by a struct
10659 : (or derived type, etc.) component, create an "alloc" or "release" node to
10660 : insert into a list following a GOMP_MAP_STRUCT node. For some types of
10661 : mapping (e.g. Fortran arrays with descriptors), an additional mapping may
10662 : be created that is inserted into the list of mapping nodes attached to the
10663 : directive being processed -- not part of the sorted list of nodes after
10664 : GOMP_MAP_STRUCT.
10665 :
10666 : CODE is the code of the directive being processed. GRP_START and GRP_END
10667 : are the first and last of two or three nodes representing this array section
10668 : mapping (e.g. a data movement node like GOMP_MAP_{TO,FROM}, optionally a
10669 : GOMP_MAP_TO_PSET, and finally a GOMP_MAP_ALWAYS_POINTER). EXTRA_NODE is
10670 : filled with the additional node described above, if needed.
10671 :
10672 : This function does not add the new nodes to any lists itself. It is the
10673 : responsibility of the caller to do that. */
10674 :
10675 : static tree
10676 1729 : build_omp_struct_comp_nodes (enum tree_code code, tree grp_start, tree grp_end,
10677 : tree *extra_node)
10678 : {
10679 1524 : enum gomp_map_kind mkind
10680 1729 : = (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
10681 1729 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
10682 :
10683 1729 : gcc_assert (grp_start != grp_end);
10684 :
10685 1729 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10686 1729 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
10687 1729 : OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (grp_end));
10688 1729 : OMP_CLAUSE_CHAIN (c2) = NULL_TREE;
10689 1729 : tree grp_mid = NULL_TREE;
10690 1729 : if (OMP_CLAUSE_CHAIN (grp_start) != grp_end)
10691 197 : grp_mid = OMP_CLAUSE_CHAIN (grp_start);
10692 :
10693 197 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
10694 0 : OMP_CLAUSE_SIZE (c2) = OMP_CLAUSE_SIZE (grp_mid);
10695 : else
10696 1729 : OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node);
10697 :
10698 1729 : if (grp_mid
10699 197 : && OMP_CLAUSE_CODE (grp_mid) == OMP_CLAUSE_MAP
10700 1926 : && OMP_CLAUSE_MAP_KIND (grp_mid) == GOMP_MAP_ALWAYS_POINTER)
10701 : {
10702 0 : tree c3
10703 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10704 0 : OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
10705 0 : OMP_CLAUSE_DECL (c3) = unshare_expr (OMP_CLAUSE_DECL (grp_mid));
10706 0 : OMP_CLAUSE_SIZE (c3) = TYPE_SIZE_UNIT (ptr_type_node);
10707 0 : OMP_CLAUSE_CHAIN (c3) = NULL_TREE;
10708 :
10709 0 : *extra_node = c3;
10710 : }
10711 : else
10712 1729 : *extra_node = NULL_TREE;
10713 :
10714 1729 : return c2;
10715 : }
10716 :
10717 : /* Strip ARRAY_REFS or an indirect ref off BASE, find the containing object,
10718 : and set *BITPOSP and *POFFSETP to the bit offset of the access.
10719 : If BASE_REF is non-NULL and the containing object is a reference, set
10720 : *BASE_REF to that reference before dereferencing the object.
10721 : If BASE_REF is NULL, check that the containing object is a COMPONENT_REF or
10722 : has array type, else return NULL. */
10723 :
10724 : static tree
10725 7741 : extract_base_bit_offset (tree base, poly_int64 *bitposp,
10726 : poly_offset_int *poffsetp,
10727 : bool *variable_offset,
10728 : tree iterator)
10729 : {
10730 7741 : tree offset;
10731 7741 : poly_int64 bitsize, bitpos;
10732 7741 : machine_mode mode;
10733 7741 : int unsignedp, reversep, volatilep = 0;
10734 7741 : poly_offset_int poffset;
10735 :
10736 7741 : STRIP_NOPS (base);
10737 :
10738 7741 : if (iterator)
10739 : {
10740 : /* Replace any iterator variables with the lower bound of the iterator.
10741 : This will give us the nominal offset and bit position of the first
10742 : element, which is all we should need to lay out the mappings. The
10743 : actual locations of the iterated mappings are elsewhere. */
10744 : tree it;
10745 72 : for (it = iterator; it; it = TREE_CHAIN (it))
10746 39 : base = simplify_replace_tree (base, OMP_ITERATOR_VAR (it),
10747 39 : OMP_ITERATOR_BEGIN (it));
10748 : }
10749 :
10750 7741 : base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
10751 : &unsignedp, &reversep, &volatilep);
10752 :
10753 7741 : STRIP_NOPS (base);
10754 :
10755 7741 : if (offset && poly_int_tree_p (offset))
10756 : {
10757 0 : poffset = wi::to_poly_offset (offset);
10758 0 : *variable_offset = false;
10759 : }
10760 : else
10761 : {
10762 7741 : poffset = 0;
10763 7741 : *variable_offset = (offset != NULL_TREE);
10764 : }
10765 :
10766 7741 : if (maybe_ne (bitpos, 0))
10767 5627 : poffset += bits_to_bytes_round_down (bitpos);
10768 :
10769 7741 : *bitposp = bitpos;
10770 7741 : *poffsetp = poffset;
10771 :
10772 7741 : return base;
10773 : }
10774 :
10775 : /* Used for topological sorting of mapping groups. UNVISITED means we haven't
10776 : started processing the group yet. The TEMPORARY mark is used when we first
10777 : encounter a group on a depth-first traversal, and the PERMANENT mark is used
10778 : when we have processed all the group's children (i.e. all the base pointers
10779 : referred to by the group's mapping nodes, recursively). */
10780 :
10781 : enum omp_tsort_mark {
10782 : UNVISITED,
10783 : TEMPORARY,
10784 : PERMANENT
10785 : };
10786 :
10787 : /* Hash for trees based on operand_equal_p. Like tree_operand_hash
10788 : but ignores side effects in the equality comparisons. */
10789 :
10790 : struct tree_operand_hash_no_se : tree_operand_hash
10791 : {
10792 : static inline bool equal (const value_type &,
10793 : const compare_type &);
10794 : };
10795 :
10796 : inline bool
10797 415812 : tree_operand_hash_no_se::equal (const value_type &t1,
10798 : const compare_type &t2)
10799 : {
10800 415812 : return operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS);
10801 : }
10802 :
10803 : /* A group of OMP_CLAUSE_MAP nodes that correspond to a single "map"
10804 : clause. */
10805 :
10806 : struct omp_mapping_group {
10807 : tree *grp_start;
10808 : tree grp_end;
10809 : omp_tsort_mark mark;
10810 : /* If we've removed the group but need to reindex, mark the group as
10811 : deleted. */
10812 : bool deleted;
10813 : /* The group points to an already-created "GOMP_MAP_STRUCT
10814 : GOMP_MAP_ATTACH_DETACH" pair. */
10815 : bool reprocess_struct;
10816 : /* The group should use "zero-length" allocations for pointers that are not
10817 : mapped "to" on the same directive. */
10818 : bool fragile;
10819 : struct omp_mapping_group *sibling;
10820 : struct omp_mapping_group *next;
10821 : };
10822 :
10823 : DEBUG_FUNCTION void
10824 0 : debug_mapping_group (omp_mapping_group *grp)
10825 : {
10826 0 : tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end);
10827 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = NULL;
10828 0 : debug_generic_expr (*grp->grp_start);
10829 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = tmp;
10830 0 : }
10831 :
10832 : /* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there
10833 : isn't one. */
10834 :
10835 : static tree
10836 36672 : omp_get_base_pointer (tree expr)
10837 : {
10838 36672 : while (TREE_CODE (expr) == ARRAY_REF
10839 44009 : || TREE_CODE (expr) == COMPONENT_REF)
10840 7337 : expr = TREE_OPERAND (expr, 0);
10841 :
10842 36672 : if (INDIRECT_REF_P (expr)
10843 36672 : || (TREE_CODE (expr) == MEM_REF
10844 1 : && integer_zerop (TREE_OPERAND (expr, 1))))
10845 : {
10846 10598 : expr = TREE_OPERAND (expr, 0);
10847 10635 : while (TREE_CODE (expr) == COMPOUND_EXPR)
10848 37 : expr = TREE_OPERAND (expr, 1);
10849 10598 : if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
10850 841 : expr = TREE_OPERAND (expr, 0);
10851 10598 : if (TREE_CODE (expr) == SAVE_EXPR)
10852 31 : expr = TREE_OPERAND (expr, 0);
10853 10598 : STRIP_NOPS (expr);
10854 10598 : return expr;
10855 : }
10856 :
10857 : return NULL_TREE;
10858 : }
10859 :
10860 : /* An attach or detach operation depends directly on the address being
10861 : attached/detached. Return that address, or none if there are no
10862 : attachments/detachments. */
10863 :
10864 : static tree
10865 16998 : omp_get_attachment (omp_mapping_group *grp)
10866 : {
10867 16998 : tree node = *grp->grp_start;
10868 :
10869 16998 : switch (OMP_CLAUSE_MAP_KIND (node))
10870 : {
10871 14038 : case GOMP_MAP_TO:
10872 14038 : case GOMP_MAP_FROM:
10873 14038 : case GOMP_MAP_TOFROM:
10874 14038 : case GOMP_MAP_ALWAYS_FROM:
10875 14038 : case GOMP_MAP_ALWAYS_TO:
10876 14038 : case GOMP_MAP_ALWAYS_TOFROM:
10877 14038 : case GOMP_MAP_FORCE_FROM:
10878 14038 : case GOMP_MAP_FORCE_TO:
10879 14038 : case GOMP_MAP_FORCE_TOFROM:
10880 14038 : case GOMP_MAP_FORCE_PRESENT:
10881 14038 : case GOMP_MAP_PRESENT_ALLOC:
10882 14038 : case GOMP_MAP_PRESENT_FROM:
10883 14038 : case GOMP_MAP_PRESENT_TO:
10884 14038 : case GOMP_MAP_PRESENT_TOFROM:
10885 14038 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
10886 14038 : case GOMP_MAP_ALWAYS_PRESENT_TO:
10887 14038 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
10888 14038 : case GOMP_MAP_ALLOC:
10889 14038 : case GOMP_MAP_RELEASE:
10890 14038 : case GOMP_MAP_DELETE:
10891 14038 : case GOMP_MAP_FORCE_ALLOC:
10892 14038 : if (node == grp->grp_end)
10893 : return NULL_TREE;
10894 :
10895 6645 : node = OMP_CLAUSE_CHAIN (node);
10896 6645 : if (node && omp_map_clause_descriptor_p (node))
10897 : {
10898 1038 : gcc_assert (node != grp->grp_end);
10899 1038 : node = OMP_CLAUSE_CHAIN (node);
10900 : }
10901 6645 : if (node)
10902 6645 : switch (OMP_CLAUSE_MAP_KIND (node))
10903 : {
10904 : case GOMP_MAP_POINTER:
10905 : case GOMP_MAP_ALWAYS_POINTER:
10906 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
10907 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
10908 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
10909 : case GOMP_MAP_USES_ALLOCATORS:
10910 : return NULL_TREE;
10911 :
10912 2559 : case GOMP_MAP_ATTACH_DETACH:
10913 2559 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10914 2559 : case GOMP_MAP_DETACH:
10915 2559 : return OMP_CLAUSE_DECL (node);
10916 :
10917 0 : default:
10918 0 : internal_error ("unexpected mapping node");
10919 : }
10920 0 : return error_mark_node;
10921 :
10922 0 : case GOMP_MAP_TO_PSET:
10923 0 : gcc_assert (node != grp->grp_end);
10924 0 : node = OMP_CLAUSE_CHAIN (node);
10925 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
10926 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
10927 0 : return OMP_CLAUSE_DECL (node);
10928 : else
10929 0 : internal_error ("unexpected mapping node");
10930 : return error_mark_node;
10931 :
10932 541 : case GOMP_MAP_ATTACH:
10933 541 : case GOMP_MAP_DETACH:
10934 541 : node = OMP_CLAUSE_CHAIN (node);
10935 541 : if (!node || *grp->grp_start == grp->grp_end)
10936 541 : return OMP_CLAUSE_DECL (*grp->grp_start);
10937 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
10938 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
10939 0 : return OMP_CLAUSE_DECL (*grp->grp_start);
10940 : else
10941 0 : internal_error ("unexpected mapping node");
10942 : return error_mark_node;
10943 :
10944 : case GOMP_MAP_STRUCT:
10945 : case GOMP_MAP_STRUCT_UNORD:
10946 : case GOMP_MAP_FORCE_DEVICEPTR:
10947 : case GOMP_MAP_DEVICE_RESIDENT:
10948 : case GOMP_MAP_LINK:
10949 : case GOMP_MAP_IF_PRESENT:
10950 : case GOMP_MAP_FIRSTPRIVATE:
10951 : case GOMP_MAP_FIRSTPRIVATE_INT:
10952 : case GOMP_MAP_USE_DEVICE_PTR:
10953 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10954 : case GOMP_MAP_USES_ALLOCATORS:
10955 : return NULL_TREE;
10956 :
10957 0 : default:
10958 0 : internal_error ("unexpected mapping node");
10959 : }
10960 :
10961 : return error_mark_node;
10962 : }
10963 :
10964 : /* Given a pointer START_P to the start of a group of related (e.g. pointer)
10965 : mappings, return the chain pointer to the end of that group in the list. */
10966 :
10967 : static tree *
10968 111880 : omp_group_last (tree *start_p)
10969 : {
10970 111880 : tree c = *start_p, nc, *grp_last_p = start_p;
10971 :
10972 111880 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
10973 :
10974 111880 : nc = OMP_CLAUSE_CHAIN (c);
10975 :
10976 195017 : if (!nc || OMP_CLAUSE_CODE (nc) != OMP_CLAUSE_MAP)
10977 : return grp_last_p;
10978 :
10979 70900 : switch (OMP_CLAUSE_MAP_KIND (c))
10980 : {
10981 : default:
10982 : while (nc
10983 113904 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
10984 239227 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
10985 106726 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
10986 96033 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH
10987 83206 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
10988 57118 : || (OMP_CLAUSE_MAP_KIND (nc)
10989 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
10990 57102 : || (OMP_CLAUSE_MAP_KIND (nc)
10991 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)
10992 56735 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH
10993 56680 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER
10994 54768 : || omp_map_clause_descriptor_p (nc)))
10995 : {
10996 67059 : tree nc2 = OMP_CLAUSE_CHAIN (nc);
10997 67059 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH)
10998 : {
10999 : /* In the specific case we're doing "exit data" on an array
11000 : slice of a reference-to-pointer struct component, we will see
11001 : DETACH followed by ATTACH_DETACH here. We want to treat that
11002 : as a single group. In other cases DETACH might represent a
11003 : stand-alone "detach" clause, so we don't want to consider
11004 : that part of the group. */
11005 55 : if (nc2
11006 16 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
11007 71 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH)
11008 0 : goto consume_two_nodes;
11009 : else
11010 : break;
11011 : }
11012 67004 : if (nc2
11013 49076 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
11014 42563 : && (OMP_CLAUSE_MAP_KIND (nc)
11015 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
11016 67020 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH)
11017 : {
11018 16 : consume_two_nodes:
11019 16 : grp_last_p = &OMP_CLAUSE_CHAIN (nc);
11020 16 : c = nc2;
11021 16 : nc = OMP_CLAUSE_CHAIN (nc2);
11022 : }
11023 : else
11024 : {
11025 66988 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11026 66988 : c = nc;
11027 66988 : nc = nc2;
11028 : }
11029 : }
11030 : break;
11031 :
11032 302 : case GOMP_MAP_ATTACH:
11033 302 : case GOMP_MAP_DETACH:
11034 : /* This is a weird artifact of how directives are parsed: bare attach or
11035 : detach clauses get a subsequent (meaningless) FIRSTPRIVATE_POINTER or
11036 : FIRSTPRIVATE_REFERENCE node. FIXME. */
11037 302 : if (nc
11038 302 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11039 302 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11040 302 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER))
11041 0 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11042 : break;
11043 :
11044 39 : case GOMP_MAP_TO_PSET:
11045 39 : if (OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11046 39 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH
11047 12 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH))
11048 39 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11049 : break;
11050 :
11051 5727 : case GOMP_MAP_STRUCT:
11052 5727 : case GOMP_MAP_STRUCT_UNORD:
11053 5727 : {
11054 5727 : unsigned HOST_WIDE_INT num_mappings
11055 5727 : = tree_to_uhwi (OMP_CLAUSE_SIZE (c));
11056 5727 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
11057 5389 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11058 10634 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH)
11059 1134 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11060 14397 : for (unsigned i = 0; i < num_mappings; i++)
11061 8670 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11062 : }
11063 : break;
11064 : }
11065 :
11066 : return grp_last_p;
11067 : }
11068 :
11069 : /* Walk through LIST_P, and return a list of groups of mappings found (e.g.
11070 : OMP_CLAUSE_MAP with GOMP_MAP_{TO/FROM/TOFROM} followed by one or two
11071 : associated GOMP_MAP_POINTER mappings). Return a vector of omp_mapping_group
11072 : if we have more than one such group, else return NULL. */
11073 :
11074 : static void
11075 90093 : omp_gather_mapping_groups_1 (tree *list_p, vec<omp_mapping_group> *groups,
11076 : tree gather_sentinel)
11077 : {
11078 90093 : for (tree *cp = list_p;
11079 269321 : *cp && *cp != gather_sentinel;
11080 179228 : cp = &OMP_CLAUSE_CHAIN (*cp))
11081 : {
11082 179228 : if (OMP_CLAUSE_CODE (*cp) != OMP_CLAUSE_MAP)
11083 99219 : continue;
11084 :
11085 80009 : tree *grp_last_p = omp_group_last (cp);
11086 80009 : omp_mapping_group grp;
11087 :
11088 80009 : grp.grp_start = cp;
11089 80009 : grp.grp_end = *grp_last_p;
11090 80009 : grp.mark = UNVISITED;
11091 80009 : grp.sibling = NULL;
11092 80009 : grp.deleted = false;
11093 80009 : grp.reprocess_struct = false;
11094 80009 : grp.fragile = false;
11095 80009 : grp.next = NULL;
11096 80009 : groups->safe_push (grp);
11097 :
11098 80009 : cp = grp_last_p;
11099 : }
11100 90093 : }
11101 :
11102 : static vec<omp_mapping_group> *
11103 89775 : omp_gather_mapping_groups (tree *list_p)
11104 : {
11105 89775 : vec<omp_mapping_group> *groups = new vec<omp_mapping_group> ();
11106 :
11107 89775 : omp_gather_mapping_groups_1 (list_p, groups, NULL_TREE);
11108 :
11109 89775 : if (groups->length () > 0)
11110 : return groups;
11111 : else
11112 : {
11113 44730 : delete groups;
11114 44730 : return NULL;
11115 : }
11116 : }
11117 :
11118 : /* A pointer mapping group GRP may define a block of memory starting at some
11119 : base address, and maybe also define a firstprivate pointer or firstprivate
11120 : reference that points to that block. The return value is a node containing
11121 : the former, and the *FIRSTPRIVATE pointer is set if we have the latter.
11122 : If we define several base pointers, i.e. for a GOMP_MAP_STRUCT mapping,
11123 : return the number of consecutive chained nodes in CHAINED. */
11124 :
11125 : static tree
11126 80403 : omp_group_base (omp_mapping_group *grp, unsigned int *chained,
11127 : tree *firstprivate)
11128 : {
11129 80403 : tree node = *grp->grp_start;
11130 :
11131 80403 : *firstprivate = NULL_TREE;
11132 80403 : *chained = 1;
11133 :
11134 80403 : switch (OMP_CLAUSE_MAP_KIND (node))
11135 : {
11136 76205 : case GOMP_MAP_TO:
11137 76205 : case GOMP_MAP_FROM:
11138 76205 : case GOMP_MAP_TOFROM:
11139 76205 : case GOMP_MAP_ALWAYS_FROM:
11140 76205 : case GOMP_MAP_ALWAYS_TO:
11141 76205 : case GOMP_MAP_ALWAYS_TOFROM:
11142 76205 : case GOMP_MAP_FORCE_FROM:
11143 76205 : case GOMP_MAP_FORCE_TO:
11144 76205 : case GOMP_MAP_FORCE_TOFROM:
11145 76205 : case GOMP_MAP_FORCE_PRESENT:
11146 76205 : case GOMP_MAP_PRESENT_ALLOC:
11147 76205 : case GOMP_MAP_PRESENT_FROM:
11148 76205 : case GOMP_MAP_PRESENT_TO:
11149 76205 : case GOMP_MAP_PRESENT_TOFROM:
11150 76205 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
11151 76205 : case GOMP_MAP_ALWAYS_PRESENT_TO:
11152 76205 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
11153 76205 : case GOMP_MAP_ALLOC:
11154 76205 : case GOMP_MAP_RELEASE:
11155 76205 : case GOMP_MAP_DELETE:
11156 76205 : case GOMP_MAP_FORCE_ALLOC:
11157 76205 : case GOMP_MAP_IF_PRESENT:
11158 76205 : if (node == grp->grp_end)
11159 : return node;
11160 :
11161 34852 : node = OMP_CLAUSE_CHAIN (node);
11162 34852 : if (!node)
11163 0 : internal_error ("unexpected mapping node");
11164 34852 : if (omp_map_clause_descriptor_p (node))
11165 : {
11166 10754 : if (node == grp->grp_end)
11167 0 : return *grp->grp_start;
11168 10754 : node = OMP_CLAUSE_CHAIN (node);
11169 : }
11170 34852 : switch (OMP_CLAUSE_MAP_KIND (node))
11171 : {
11172 23539 : case GOMP_MAP_POINTER:
11173 23539 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11174 23539 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11175 23539 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11176 23539 : *firstprivate = OMP_CLAUSE_DECL (node);
11177 23539 : return *grp->grp_start;
11178 :
11179 11313 : case GOMP_MAP_ALWAYS_POINTER:
11180 11313 : case GOMP_MAP_ATTACH_DETACH:
11181 11313 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11182 11313 : case GOMP_MAP_DETACH:
11183 11313 : return *grp->grp_start;
11184 :
11185 0 : default:
11186 0 : internal_error ("unexpected mapping node");
11187 : }
11188 : return error_mark_node;
11189 :
11190 26 : case GOMP_MAP_TO_PSET:
11191 26 : gcc_assert (node != grp->grp_end);
11192 26 : node = OMP_CLAUSE_CHAIN (node);
11193 26 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
11194 26 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
11195 : return NULL_TREE;
11196 : else
11197 0 : internal_error ("unexpected mapping node");
11198 : return error_mark_node;
11199 :
11200 1109 : case GOMP_MAP_ATTACH:
11201 1109 : case GOMP_MAP_DETACH:
11202 1109 : node = OMP_CLAUSE_CHAIN (node);
11203 1109 : if (!node || *grp->grp_start == grp->grp_end)
11204 : return NULL_TREE;
11205 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11206 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11207 : {
11208 : /* We're mapping the base pointer itself in a bare attach or detach
11209 : node. This is a side effect of how parsing works, and the mapping
11210 : will be removed anyway (at least for enter/exit data directives).
11211 : We should ignore the mapping here. FIXME. */
11212 : return NULL_TREE;
11213 : }
11214 : else
11215 0 : internal_error ("unexpected mapping node");
11216 : return error_mark_node;
11217 :
11218 2779 : case GOMP_MAP_STRUCT:
11219 2779 : case GOMP_MAP_STRUCT_UNORD:
11220 2779 : {
11221 2779 : unsigned HOST_WIDE_INT num_mappings
11222 2779 : = tree_to_uhwi (OMP_CLAUSE_SIZE (node));
11223 2779 : node = OMP_CLAUSE_CHAIN (node);
11224 2779 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11225 2779 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11226 : {
11227 393 : *firstprivate = OMP_CLAUSE_DECL (node);
11228 393 : node = OMP_CLAUSE_CHAIN (node);
11229 : }
11230 2386 : else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH_DETACH)
11231 314 : node = OMP_CLAUSE_CHAIN (node);
11232 2779 : *chained = num_mappings;
11233 2779 : return node;
11234 : }
11235 :
11236 : case GOMP_MAP_FORCE_DEVICEPTR:
11237 : case GOMP_MAP_DEVICE_RESIDENT:
11238 : case GOMP_MAP_LINK:
11239 : case GOMP_MAP_FIRSTPRIVATE:
11240 : case GOMP_MAP_FIRSTPRIVATE_INT:
11241 : case GOMP_MAP_USE_DEVICE_PTR:
11242 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11243 : case GOMP_MAP_USES_ALLOCATORS:
11244 : return NULL_TREE;
11245 :
11246 0 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11247 0 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11248 0 : case GOMP_MAP_POINTER:
11249 0 : case GOMP_MAP_ALWAYS_POINTER:
11250 0 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11251 : /* These shouldn't appear by themselves. */
11252 0 : if (!seen_error ())
11253 0 : internal_error ("unexpected pointer mapping node");
11254 0 : return error_mark_node;
11255 :
11256 0 : default:
11257 0 : gcc_unreachable ();
11258 : }
11259 :
11260 : return error_mark_node;
11261 : }
11262 :
11263 : /* Given a vector of omp_mapping_groups, build a hash table so we can look up
11264 : nodes by tree_operand_hash_no_se. */
11265 :
11266 : static void
11267 45529 : omp_index_mapping_groups_1 (hash_map<tree_operand_hash_no_se,
11268 : omp_mapping_group *> *grpmap,
11269 : vec<omp_mapping_group> *groups,
11270 : tree reindex_sentinel)
11271 : {
11272 45529 : omp_mapping_group *grp;
11273 45529 : unsigned int i;
11274 45529 : bool reindexing = reindex_sentinel != NULL_TREE, above_hwm = false;
11275 :
11276 126386 : FOR_EACH_VEC_ELT (*groups, i, grp)
11277 : {
11278 80857 : if (reindexing && *grp->grp_start == reindex_sentinel)
11279 80857 : above_hwm = true;
11280 :
11281 80857 : if (reindexing && !above_hwm)
11282 56925 : continue;
11283 :
11284 80557 : if (grp->reprocess_struct)
11285 154 : continue;
11286 :
11287 80403 : tree fpp;
11288 80403 : unsigned int chained;
11289 80403 : tree node = omp_group_base (grp, &chained, &fpp);
11290 :
11291 80403 : if (node == error_mark_node || (!node && !fpp))
11292 1419 : continue;
11293 :
11294 : for (unsigned j = 0;
11295 159412 : node && j < chained;
11296 80428 : node = OMP_CLAUSE_CHAIN (node), j++)
11297 : {
11298 80428 : tree decl = OMP_CLAUSE_DECL (node);
11299 : /* Sometimes we see zero-offset MEM_REF instead of INDIRECT_REF,
11300 : meaning node-hash lookups don't work. This is a workaround for
11301 : that, but ideally we should just create the INDIRECT_REF at
11302 : source instead. FIXME. */
11303 80428 : if (TREE_CODE (decl) == MEM_REF
11304 80428 : && integer_zerop (TREE_OPERAND (decl, 1)))
11305 0 : decl = build_fold_indirect_ref (TREE_OPERAND (decl, 0));
11306 :
11307 80428 : omp_mapping_group **prev = grpmap->get (decl);
11308 :
11309 80428 : if (prev && *prev == grp)
11310 : /* Empty. */;
11311 80428 : else if (prev)
11312 : {
11313 : /* Mapping the same thing twice is normally diagnosed as an error,
11314 : but can happen under some circumstances, e.g. in pr99928-16.c,
11315 : the directive:
11316 :
11317 : #pragma omp target simd reduction(+:a[:3]) \
11318 : map(always, tofrom: a[:6])
11319 : ...
11320 :
11321 : will result in two "a[0]" mappings (of different sizes). */
11322 :
11323 326 : grp->sibling = (*prev)->sibling;
11324 326 : (*prev)->sibling = grp;
11325 : }
11326 : else
11327 80102 : grpmap->put (decl, grp);
11328 : }
11329 :
11330 78984 : if (!fpp)
11331 55052 : continue;
11332 :
11333 23932 : omp_mapping_group **prev = grpmap->get (fpp);
11334 23932 : if (prev && *prev != grp)
11335 : {
11336 12 : grp->sibling = (*prev)->sibling;
11337 12 : (*prev)->sibling = grp;
11338 : }
11339 : else
11340 23920 : grpmap->put (fpp, grp);
11341 : }
11342 45529 : }
11343 :
11344 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11345 45045 : omp_index_mapping_groups (vec<omp_mapping_group> *groups)
11346 : {
11347 45045 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11348 45045 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11349 :
11350 45045 : omp_index_mapping_groups_1 (grpmap, groups, NULL_TREE);
11351 :
11352 45045 : return grpmap;
11353 : }
11354 :
11355 : /* Rebuild group map from partially-processed clause list (during
11356 : omp_build_struct_sibling_lists). We have already processed nodes up until
11357 : a high-water mark (HWM). This is a bit tricky because the list is being
11358 : reordered as it is scanned, but we know:
11359 :
11360 : 1. The list after HWM has not been touched yet, so we can reindex it safely.
11361 :
11362 : 2. The list before and including HWM has been altered, but remains
11363 : well-formed throughout the sibling-list building operation.
11364 :
11365 : so, we can do the reindex operation in two parts, on the processed and
11366 : then the unprocessed halves of the list. */
11367 :
11368 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11369 318 : omp_reindex_mapping_groups (tree *list_p,
11370 : vec<omp_mapping_group> *groups,
11371 : vec<omp_mapping_group> *processed_groups,
11372 : tree sentinel)
11373 : {
11374 318 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11375 318 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11376 :
11377 318 : processed_groups->truncate (0);
11378 :
11379 318 : omp_gather_mapping_groups_1 (list_p, processed_groups, sentinel);
11380 318 : omp_index_mapping_groups_1 (grpmap, processed_groups, NULL_TREE);
11381 318 : if (sentinel)
11382 166 : omp_index_mapping_groups_1 (grpmap, groups, sentinel);
11383 :
11384 318 : return grpmap;
11385 : }
11386 :
11387 : /* Find the immediately-containing struct for a component ref (etc.)
11388 : expression EXPR. */
11389 :
11390 : static tree
11391 48181 : omp_containing_struct (tree expr)
11392 : {
11393 48181 : tree expr0 = expr;
11394 :
11395 48181 : STRIP_NOPS (expr);
11396 :
11397 : /* Note: don't strip NOPs unless we're also stripping off array refs or a
11398 : component ref. */
11399 48181 : if (TREE_CODE (expr) != ARRAY_REF && TREE_CODE (expr) != COMPONENT_REF)
11400 : return expr0;
11401 :
11402 27293 : while (TREE_CODE (expr) == ARRAY_REF)
11403 3706 : expr = TREE_OPERAND (expr, 0);
11404 :
11405 23587 : if (TREE_CODE (expr) == COMPONENT_REF)
11406 21106 : expr = TREE_OPERAND (expr, 0);
11407 :
11408 : return expr;
11409 : }
11410 :
11411 : /* Return TRUE if DECL describes a component that is part of a whole structure
11412 : that is mapped elsewhere in GRPMAP. *MAPPED_BY_GROUP is set to the group
11413 : that maps that structure, if present. */
11414 :
11415 : static bool
11416 25836 : omp_mapped_by_containing_struct (hash_map<tree_operand_hash_no_se,
11417 : omp_mapping_group *> *grpmap,
11418 : tree decl,
11419 : omp_mapping_group **mapped_by_group)
11420 : {
11421 25836 : tree wsdecl = NULL_TREE;
11422 :
11423 25836 : *mapped_by_group = NULL;
11424 :
11425 70526 : while (true)
11426 : {
11427 48181 : wsdecl = omp_containing_struct (decl);
11428 48181 : if (wsdecl == decl)
11429 : break;
11430 23587 : omp_mapping_group **wholestruct = grpmap->get (wsdecl);
11431 23587 : if (!wholestruct
11432 21015 : && TREE_CODE (wsdecl) == MEM_REF
11433 23588 : && integer_zerop (TREE_OPERAND (wsdecl, 1)))
11434 : {
11435 1 : tree deref = TREE_OPERAND (wsdecl, 0);
11436 1 : deref = build_fold_indirect_ref (deref);
11437 1 : wholestruct = grpmap->get (deref);
11438 : }
11439 23587 : if (wholestruct)
11440 : {
11441 : /* An intermediate descriptor should not match here because the
11442 : pointee is actually not mapped by this group -- it is just a
11443 : zero-length alloc. */
11444 2572 : tree desc = OMP_CLAUSE_CHAIN (*(*wholestruct)->grp_start);
11445 2572 : if (desc != NULL_TREE && omp_map_clause_descriptor_p (desc))
11446 1330 : goto next;
11447 1242 : *mapped_by_group = *wholestruct;
11448 1242 : return true;
11449 : }
11450 21015 : next:
11451 22345 : decl = wsdecl;
11452 22345 : }
11453 :
11454 : return false;
11455 : }
11456 :
11457 : /* Helper function for omp_tsort_mapping_groups. Returns TRUE on success, or
11458 : FALSE on error. */
11459 :
11460 : static bool
11461 20336 : omp_tsort_mapping_groups_1 (omp_mapping_group ***outlist,
11462 : vec<omp_mapping_group> *groups,
11463 : hash_map<tree_operand_hash_no_se,
11464 : omp_mapping_group *> *grpmap,
11465 : omp_mapping_group *grp)
11466 : {
11467 20336 : if (grp->mark == PERMANENT)
11468 : return true;
11469 16998 : if (grp->mark == TEMPORARY)
11470 : {
11471 0 : fprintf (stderr, "when processing group:\n");
11472 0 : debug_mapping_group (grp);
11473 0 : internal_error ("base pointer cycle detected");
11474 : return false;
11475 : }
11476 16998 : grp->mark = TEMPORARY;
11477 :
11478 16998 : tree attaches_to = omp_get_attachment (grp);
11479 :
11480 16998 : if (attaches_to)
11481 : {
11482 3100 : omp_mapping_group **basep = grpmap->get (attaches_to);
11483 :
11484 3100 : if (basep && *basep != grp)
11485 : {
11486 2924 : for (omp_mapping_group *w = *basep; w; w = w->sibling)
11487 1462 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11488 : return false;
11489 : }
11490 : }
11491 :
11492 16998 : tree decl = OMP_CLAUSE_DECL (*grp->grp_start);
11493 :
11494 23221 : while (decl)
11495 : {
11496 23221 : tree base = omp_get_base_pointer (decl);
11497 :
11498 23221 : if (!base)
11499 : break;
11500 :
11501 8986 : omp_mapping_group **innerp = grpmap->get (base);
11502 8986 : omp_mapping_group *wholestruct;
11503 :
11504 : /* We should treat whole-structure mappings as if all (pointer, in this
11505 : case) members are mapped as individual list items. Check if we have
11506 : such a whole-structure mapping, if we don't have an explicit reference
11507 : to the pointer member itself. */
11508 8986 : if (!innerp
11509 4172 : && TREE_CODE (base) == COMPONENT_REF
11510 11218 : && omp_mapped_by_containing_struct (grpmap, base, &wholestruct))
11511 : innerp = &wholestruct;
11512 :
11513 8986 : if (innerp && *innerp != grp)
11514 : {
11515 5538 : for (omp_mapping_group *w = *innerp; w; w = w->sibling)
11516 2775 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11517 0 : return false;
11518 : break;
11519 : }
11520 :
11521 6223 : decl = base;
11522 : }
11523 :
11524 16998 : grp->mark = PERMANENT;
11525 :
11526 : /* Emit grp to output list. */
11527 :
11528 16998 : **outlist = grp;
11529 16998 : *outlist = &grp->next;
11530 :
11531 16998 : return true;
11532 : }
11533 :
11534 : /* Topologically sort GROUPS, so that OMP 5.0-defined base pointers come
11535 : before mappings that use those pointers. This is an implementation of the
11536 : depth-first search algorithm, described e.g. at:
11537 :
11538 : https://en.wikipedia.org/wiki/Topological_sorting
11539 : */
11540 :
11541 : static omp_mapping_group *
11542 8640 : omp_tsort_mapping_groups (vec<omp_mapping_group> *groups,
11543 : hash_map<tree_operand_hash_no_se, omp_mapping_group *>
11544 : *grpmap,
11545 : bool enter_exit_data)
11546 : {
11547 8640 : omp_mapping_group *grp, *outlist = NULL, **cursor;
11548 8640 : unsigned int i;
11549 8640 : bool saw_runtime_implicit = false;
11550 :
11551 8640 : cursor = &outlist;
11552 :
11553 25638 : FOR_EACH_VEC_ELT (*groups, i, grp)
11554 : {
11555 16998 : if (grp->mark != PERMANENT)
11556 : {
11557 16123 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11558 : {
11559 683 : saw_runtime_implicit = true;
11560 683 : continue;
11561 : }
11562 15440 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11563 : return NULL;
11564 : }
11565 : }
11566 :
11567 8640 : if (!saw_runtime_implicit)
11568 8358 : return outlist;
11569 :
11570 1634 : FOR_EACH_VEC_ELT (*groups, i, grp)
11571 : {
11572 1352 : if (grp->mark != PERMANENT
11573 1352 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11574 : {
11575 : /* Clear the flag for enter/exit data because it is currently
11576 : meaningless for those operations in libgomp. */
11577 659 : if (enter_exit_data)
11578 446 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start) = 0;
11579 :
11580 659 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11581 : return NULL;
11582 : }
11583 : }
11584 :
11585 282 : return outlist;
11586 : }
11587 :
11588 : /* Split INLIST into three parts:
11589 :
11590 : - "present" alloc/to/from groups
11591 : - other to/from groups
11592 : - other alloc/release/delete groups
11593 :
11594 : These sub-lists are then concatenated together to form the final list.
11595 : Each sub-list retains the order of the original list.
11596 : Note that ATTACH nodes are later moved to the end of the list in
11597 : gimplify_adjust_omp_clauses, for target regions. */
11598 :
11599 : static omp_mapping_group *
11600 8640 : omp_segregate_mapping_groups (omp_mapping_group *inlist)
11601 : {
11602 8640 : omp_mapping_group *ard_groups = NULL, *tf_groups = NULL;
11603 8640 : omp_mapping_group *p_groups = NULL;
11604 8640 : omp_mapping_group **ard_tail = &ard_groups, **tf_tail = &tf_groups;
11605 8640 : omp_mapping_group **p_tail = &p_groups;
11606 :
11607 25638 : for (omp_mapping_group *w = inlist; w;)
11608 : {
11609 16998 : tree c = *w->grp_start;
11610 16998 : omp_mapping_group *next = w->next;
11611 :
11612 16998 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
11613 :
11614 16998 : switch (OMP_CLAUSE_MAP_KIND (c))
11615 : {
11616 1939 : case GOMP_MAP_ALLOC:
11617 1939 : case GOMP_MAP_RELEASE:
11618 1939 : case GOMP_MAP_DELETE:
11619 1939 : *ard_tail = w;
11620 1939 : w->next = NULL;
11621 1939 : ard_tail = &w->next;
11622 1939 : break;
11623 :
11624 : /* These map types are all semantically identical, so are moved into a
11625 : single group. They will each be changed into GOMP_MAP_FORCE_PRESENT
11626 : in gimplify_adjust_omp_clauses. */
11627 151 : case GOMP_MAP_PRESENT_ALLOC:
11628 151 : case GOMP_MAP_PRESENT_FROM:
11629 151 : case GOMP_MAP_PRESENT_TO:
11630 151 : case GOMP_MAP_PRESENT_TOFROM:
11631 151 : *p_tail = w;
11632 151 : w->next = NULL;
11633 151 : p_tail = &w->next;
11634 151 : break;
11635 :
11636 14908 : default:
11637 14908 : *tf_tail = w;
11638 14908 : w->next = NULL;
11639 14908 : tf_tail = &w->next;
11640 : }
11641 :
11642 16998 : w = next;
11643 : }
11644 :
11645 : /* Now splice the lists together... */
11646 8640 : *tf_tail = ard_groups;
11647 8640 : *p_tail = tf_groups;
11648 :
11649 8640 : return p_groups;
11650 : }
11651 :
11652 : /* Given a list LIST_P containing groups of mappings given by GROUPS, reorder
11653 : those groups based on the output list of omp_tsort_mapping_groups --
11654 : singly-linked, threaded through each element's NEXT pointer starting at
11655 : HEAD. Each list element appears exactly once in that linked list.
11656 :
11657 : Each element of GROUPS may correspond to one or several mapping nodes.
11658 : Node groups are kept together, and in the reordered list, the positions of
11659 : the original groups are reused for the positions of the reordered list.
11660 : Hence if we have e.g.
11661 :
11662 : {to ptr ptr} firstprivate {tofrom ptr} ...
11663 : ^ ^ ^
11664 : first group non-"map" second group
11665 :
11666 : and say the second group contains a base pointer for the first so must be
11667 : moved before it, the resulting list will contain:
11668 :
11669 : {tofrom ptr} firstprivate {to ptr ptr} ...
11670 : ^ prev. second group ^ prev. first group
11671 : */
11672 :
11673 : static tree *
11674 8640 : omp_reorder_mapping_groups (vec<omp_mapping_group> *groups,
11675 : omp_mapping_group *head,
11676 : tree *list_p)
11677 : {
11678 8640 : omp_mapping_group *grp;
11679 8640 : unsigned int i;
11680 8640 : unsigned numgroups = groups->length ();
11681 8640 : auto_vec<tree> old_heads (numgroups);
11682 8640 : auto_vec<tree *> old_headps (numgroups);
11683 8640 : auto_vec<tree> new_heads (numgroups);
11684 8640 : auto_vec<tree> old_succs (numgroups);
11685 8640 : bool map_at_start = (list_p == (*groups)[0].grp_start);
11686 :
11687 8640 : tree *new_grp_tail = NULL;
11688 :
11689 : /* Stash the start & end nodes of each mapping group before we start
11690 : modifying the list. */
11691 25638 : FOR_EACH_VEC_ELT (*groups, i, grp)
11692 : {
11693 16998 : old_headps.quick_push (grp->grp_start);
11694 16998 : old_heads.quick_push (*grp->grp_start);
11695 16998 : old_succs.quick_push (OMP_CLAUSE_CHAIN (grp->grp_end));
11696 : }
11697 :
11698 : /* And similarly, the heads of the groups in the order we want to rearrange
11699 : the list to. */
11700 25638 : for (omp_mapping_group *w = head; w; w = w->next)
11701 16998 : new_heads.quick_push (*w->grp_start);
11702 :
11703 25638 : FOR_EACH_VEC_ELT (*groups, i, grp)
11704 : {
11705 16998 : gcc_assert (head);
11706 :
11707 16998 : if (new_grp_tail && old_succs[i - 1] == old_heads[i])
11708 : {
11709 : /* a {b c d} {e f g} h i j (original)
11710 : -->
11711 : a {k l m} {e f g} h i j (inserted new group on last iter)
11712 : -->
11713 : a {k l m} {n o p} h i j (this time, chain last group to new one)
11714 : ^new_grp_tail
11715 : */
11716 7736 : *new_grp_tail = new_heads[i];
11717 : }
11718 9262 : else if (new_grp_tail)
11719 : {
11720 : /* a {b c d} e {f g h} i j k (original)
11721 : -->
11722 : a {l m n} e {f g h} i j k (gap after last iter's group)
11723 : -->
11724 : a {l m n} e {o p q} h i j (chain last group to old successor)
11725 : ^new_grp_tail
11726 : */
11727 622 : *new_grp_tail = old_succs[i - 1];
11728 622 : *old_headps[i] = new_heads[i];
11729 : }
11730 : else
11731 : {
11732 : /* The first inserted group -- point to new group, and leave end
11733 : open.
11734 : a {b c d} e f
11735 : -->
11736 : a {g h i...
11737 : */
11738 8640 : *grp->grp_start = new_heads[i];
11739 : }
11740 :
11741 16998 : new_grp_tail = &OMP_CLAUSE_CHAIN (head->grp_end);
11742 :
11743 16998 : head = head->next;
11744 : }
11745 :
11746 8640 : if (new_grp_tail)
11747 8640 : *new_grp_tail = old_succs[numgroups - 1];
11748 :
11749 8640 : gcc_assert (!head);
11750 :
11751 12098 : return map_at_start ? (*groups)[0].grp_start : list_p;
11752 8640 : }
11753 :
11754 : /* DECL is supposed to have lastprivate semantics in the outer contexts
11755 : of combined/composite constructs, starting with OCTX.
11756 : Add needed lastprivate, shared or map clause if no data sharing or
11757 : mapping clause are present. IMPLICIT_P is true if it is an implicit
11758 : clause (IV on simd), in which case the lastprivate will not be
11759 : copied to some constructs. */
11760 :
11761 : static void
11762 14658 : omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx,
11763 : tree decl, bool implicit_p)
11764 : {
11765 14658 : struct gimplify_omp_ctx *orig_octx = octx;
11766 26979 : for (; octx; octx = octx->outer_context)
11767 : {
11768 25901 : if ((octx->region_type == ORT_COMBINED_PARALLEL
11769 20865 : || (octx->region_type & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS)
11770 25332 : && splay_tree_lookup (octx->variables,
11771 : (splay_tree_key) decl) == NULL)
11772 : {
11773 3887 : omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN);
11774 3887 : continue;
11775 : }
11776 18375 : if ((octx->region_type & ORT_TASK) != 0
11777 575 : && octx->combined_loop
11778 18656 : && splay_tree_lookup (octx->variables,
11779 : (splay_tree_key) decl) == NULL)
11780 : {
11781 248 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11782 248 : continue;
11783 : }
11784 22711 : if (implicit_p
11785 13619 : && octx->region_type == ORT_WORKSHARE
11786 10405 : && octx->combined_loop
11787 10300 : && splay_tree_lookup (octx->variables,
11788 : (splay_tree_key) decl) == NULL
11789 10300 : && octx->outer_context
11790 8907 : && octx->outer_context->region_type == ORT_COMBINED_PARALLEL
11791 22718 : && splay_tree_lookup (octx->outer_context->variables,
11792 : (splay_tree_key) decl) == NULL)
11793 : {
11794 4832 : octx = octx->outer_context;
11795 4832 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11796 4832 : continue;
11797 : }
11798 5565 : if ((octx->region_type == ORT_WORKSHARE || octx->region_type == ORT_ACC)
11799 7482 : && octx->combined_loop
11800 7295 : && splay_tree_lookup (octx->variables,
11801 : (splay_tree_key) decl) == NULL
11802 19072 : && !omp_check_private (octx, decl, false))
11803 : {
11804 3354 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11805 3354 : continue;
11806 : }
11807 9693 : if (octx->region_type == ORT_COMBINED_TARGET)
11808 : {
11809 2008 : splay_tree_node n = splay_tree_lookup (octx->variables,
11810 : (splay_tree_key) decl);
11811 2008 : if (n == NULL)
11812 : {
11813 1986 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11814 1986 : octx = octx->outer_context;
11815 : }
11816 22 : else if (!implicit_p
11817 22 : && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT))
11818 : {
11819 12 : n->value &= ~(GOVD_FIRSTPRIVATE
11820 : | GOVD_FIRSTPRIVATE_IMPLICIT
11821 : | GOVD_EXPLICIT);
11822 12 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11823 12 : octx = octx->outer_context;
11824 : }
11825 : }
11826 : break;
11827 : }
11828 14658 : if (octx && (implicit_p || octx != orig_octx))
11829 4046 : omp_notice_variable (octx, decl, true);
11830 14658 : }
11831 :
11832 : /* We might have indexed several groups for DECL, e.g. a "TO" mapping and also
11833 : a "FIRSTPRIVATE" mapping. Return the one that isn't firstprivate, etc. */
11834 :
11835 : static omp_mapping_group *
11836 6008 : omp_get_nonfirstprivate_group (hash_map<tree_operand_hash_no_se,
11837 : omp_mapping_group *> *grpmap,
11838 : tree decl, bool allow_deleted = false)
11839 : {
11840 6008 : omp_mapping_group **to_group_p = grpmap->get (decl);
11841 :
11842 6008 : if (!to_group_p)
11843 : return NULL;
11844 :
11845 2475 : omp_mapping_group *to_group = *to_group_p;
11846 :
11847 3828 : for (; to_group; to_group = to_group->sibling)
11848 : {
11849 2512 : tree grp_end = to_group->grp_end;
11850 2512 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
11851 : {
11852 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11853 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11854 : break;
11855 :
11856 1161 : default:
11857 1161 : if (allow_deleted || !to_group->deleted)
11858 : return to_group;
11859 : }
11860 : }
11861 :
11862 : return NULL;
11863 : }
11864 :
11865 : /* Return TRUE if the directive (whose clauses are described by the hash table
11866 : of mapping groups, GRPMAP) maps DECL explicitly. If TO_SPECIFICALLY is
11867 : true, only count TO mappings. If ALLOW_DELETED is true, ignore the
11868 : "deleted" flag for groups. If CONTAINED_IN_STRUCT is true, also return
11869 : TRUE if DECL is mapped as a member of a whole-struct mapping. */
11870 :
11871 : static bool
11872 4450 : omp_directive_maps_explicitly (hash_map<tree_operand_hash_no_se,
11873 : omp_mapping_group *> *grpmap,
11874 : tree decl, omp_mapping_group **base_group,
11875 : bool to_specifically, bool allow_deleted,
11876 : bool contained_in_struct)
11877 : {
11878 4450 : omp_mapping_group *decl_group
11879 4450 : = omp_get_nonfirstprivate_group (grpmap, decl, allow_deleted);
11880 :
11881 4450 : *base_group = NULL;
11882 :
11883 4450 : if (decl_group)
11884 : {
11885 1042 : tree grp_first = *decl_group->grp_start;
11886 : /* We might be called during omp_build_struct_sibling_lists, when
11887 : GOMP_MAP_STRUCT might have been inserted at the start of the group.
11888 : Skip over that, and also possibly the node after it. */
11889 1042 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT
11890 1042 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT_UNORD)
11891 : {
11892 6 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11893 6 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_FIRSTPRIVATE_POINTER
11894 6 : || (OMP_CLAUSE_MAP_KIND (grp_first)
11895 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11896 12 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_ATTACH_DETACH)
11897 0 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11898 : }
11899 1042 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
11900 1042 : if (!to_specifically
11901 592 : || GOMP_MAP_COPY_TO_P (first_kind)
11902 382 : || first_kind == GOMP_MAP_ALLOC)
11903 : {
11904 960 : *base_group = decl_group;
11905 960 : return true;
11906 : }
11907 : }
11908 :
11909 3490 : if (contained_in_struct
11910 3490 : && omp_mapped_by_containing_struct (grpmap, decl, base_group))
11911 : return true;
11912 :
11913 : return false;
11914 : }
11915 :
11916 : /* If we have mappings INNER and OUTER, where INNER is a component access and
11917 : OUTER is a mapping of the whole containing struct, check that the mappings
11918 : are compatible. We'll be deleting the inner mapping, so we need to make
11919 : sure the outer mapping does (at least) the same transfers to/from the device
11920 : as the inner mapping. */
11921 :
11922 : bool
11923 172 : omp_check_mapping_compatibility (location_t loc,
11924 : omp_mapping_group *outer,
11925 : omp_mapping_group *inner)
11926 : {
11927 172 : tree first_outer = *outer->grp_start, first_inner = *inner->grp_start;
11928 :
11929 172 : gcc_assert (OMP_CLAUSE_CODE (first_outer) == OMP_CLAUSE_MAP);
11930 172 : gcc_assert (OMP_CLAUSE_CODE (first_inner) == OMP_CLAUSE_MAP);
11931 :
11932 172 : enum gomp_map_kind outer_kind = OMP_CLAUSE_MAP_KIND (first_outer);
11933 172 : enum gomp_map_kind inner_kind = OMP_CLAUSE_MAP_KIND (first_inner);
11934 :
11935 172 : if (outer_kind == inner_kind)
11936 : return true;
11937 :
11938 70 : switch (outer_kind)
11939 : {
11940 0 : case GOMP_MAP_ALWAYS_TO:
11941 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11942 0 : || inner_kind == GOMP_MAP_ALLOC
11943 0 : || inner_kind == GOMP_MAP_TO)
11944 : return true;
11945 : break;
11946 :
11947 0 : case GOMP_MAP_ALWAYS_FROM:
11948 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11949 0 : || inner_kind == GOMP_MAP_RELEASE
11950 : || inner_kind == GOMP_MAP_FROM)
11951 : return true;
11952 : break;
11953 :
11954 10 : case GOMP_MAP_TO:
11955 10 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11956 10 : || inner_kind == GOMP_MAP_ALLOC)
11957 : return true;
11958 : break;
11959 :
11960 8 : case GOMP_MAP_FROM:
11961 8 : if (inner_kind == GOMP_MAP_RELEASE
11962 8 : || inner_kind == GOMP_MAP_FORCE_PRESENT)
11963 : return true;
11964 : break;
11965 :
11966 32 : case GOMP_MAP_ALWAYS_TOFROM:
11967 32 : case GOMP_MAP_TOFROM:
11968 32 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11969 32 : || inner_kind == GOMP_MAP_ALLOC
11970 : || inner_kind == GOMP_MAP_TO
11971 24 : || inner_kind == GOMP_MAP_FROM
11972 12 : || inner_kind == GOMP_MAP_TOFROM)
11973 : return true;
11974 : break;
11975 :
11976 28 : default:
11977 28 : ;
11978 : }
11979 :
11980 84 : error_at (loc, "data movement for component %qE is not compatible with "
11981 28 : "movement for struct %qE", OMP_CLAUSE_DECL (first_inner),
11982 28 : OMP_CLAUSE_DECL (first_outer));
11983 :
11984 28 : return false;
11985 : }
11986 :
11987 : /* This function handles several cases where clauses on a mapping directive
11988 : can interact with each other.
11989 :
11990 : If we have a FIRSTPRIVATE_POINTER node and we're also mapping the pointer
11991 : on the same directive, change the mapping of the first node to
11992 : ATTACH_DETACH. We should have detected that this will happen already in
11993 : c-omp.cc:c_omp_adjust_map_clauses and marked the appropriate decl
11994 : as addressable. (If we didn't, bail out.)
11995 :
11996 : If we have a FIRSTPRIVATE_REFERENCE (for a reference to pointer) and we're
11997 : mapping the base pointer also, we may need to change the mapping type to
11998 : ATTACH_DETACH and synthesize an alloc node for the reference itself.
11999 :
12000 : If we have an ATTACH_DETACH node, this is an array section with a pointer
12001 : base. If we're mapping the base on the same directive too, we can drop its
12002 : mapping. However, if we have a reference to pointer, make other appropriate
12003 : adjustments to the mapping nodes instead.
12004 :
12005 : If we have an ATTACH_DETACH node with a Fortran pointer-set (array
12006 : descriptor) mapping for a derived-type component, and we're also mapping the
12007 : whole of the derived-type variable on another clause, the pointer-set
12008 : mapping is removed.
12009 :
12010 : If we have a component access but we're also mapping the whole of the
12011 : containing struct, drop the former access.
12012 :
12013 : If the expression is a component access, and we're also mapping a base
12014 : pointer used in that component access in the same expression, change the
12015 : mapping type of the latter to ALLOC (ready for processing by
12016 : omp_build_struct_sibling_lists). */
12017 :
12018 : void
12019 8640 : omp_resolve_clause_dependencies (enum tree_code code,
12020 : vec<omp_mapping_group> *groups,
12021 : hash_map<tree_operand_hash_no_se,
12022 : omp_mapping_group *> *grpmap)
12023 : {
12024 8640 : int i;
12025 8640 : omp_mapping_group *grp;
12026 8640 : bool repair_chain = false;
12027 :
12028 24574 : FOR_EACH_VEC_ELT (*groups, i, grp)
12029 : {
12030 15934 : tree grp_end = grp->grp_end;
12031 15934 : tree decl = OMP_CLAUSE_DECL (grp_end);
12032 :
12033 15934 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12034 :
12035 15934 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
12036 : {
12037 1242 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
12038 1242 : {
12039 1242 : omp_mapping_group *to_group
12040 1242 : = omp_get_nonfirstprivate_group (grpmap, decl);
12041 :
12042 1242 : if (!to_group || to_group == grp)
12043 1217 : continue;
12044 :
12045 25 : tree grp_first = *to_group->grp_start;
12046 25 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12047 :
12048 25 : if ((GOMP_MAP_COPY_TO_P (first_kind)
12049 7 : || first_kind == GOMP_MAP_ALLOC)
12050 50 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12051 : != GOMP_MAP_FIRSTPRIVATE_POINTER))
12052 : {
12053 25 : gcc_assert (TREE_ADDRESSABLE (OMP_CLAUSE_DECL (grp_end)));
12054 25 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12055 : }
12056 : }
12057 : break;
12058 :
12059 160 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
12060 160 : {
12061 160 : tree ptr = build_fold_indirect_ref (decl);
12062 :
12063 160 : omp_mapping_group *to_group
12064 160 : = omp_get_nonfirstprivate_group (grpmap, ptr);
12065 :
12066 160 : if (!to_group || to_group == grp)
12067 156 : continue;
12068 :
12069 4 : tree grp_first = *to_group->grp_start;
12070 4 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12071 :
12072 4 : if (GOMP_MAP_COPY_TO_P (first_kind)
12073 4 : || first_kind == GOMP_MAP_ALLOC)
12074 : {
12075 4 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12076 4 : OMP_CLAUSE_DECL (grp_end) = ptr;
12077 4 : if ((OMP_CLAUSE_CHAIN (*to_group->grp_start)
12078 4 : == to_group->grp_end)
12079 4 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12080 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
12081 : {
12082 0 : gcc_assert (TREE_ADDRESSABLE
12083 : (OMP_CLAUSE_DECL (to_group->grp_end)));
12084 0 : OMP_CLAUSE_SET_MAP_KIND (to_group->grp_end,
12085 : GOMP_MAP_ATTACH_DETACH);
12086 :
12087 0 : location_t loc = OMP_CLAUSE_LOCATION (to_group->grp_end);
12088 0 : tree alloc
12089 0 : = build_omp_clause (loc, OMP_CLAUSE_MAP);
12090 0 : OMP_CLAUSE_SET_MAP_KIND (alloc, GOMP_MAP_ALLOC);
12091 0 : tree tmp = build_fold_addr_expr (OMP_CLAUSE_DECL
12092 : (to_group->grp_end));
12093 0 : tree char_ptr_type = build_pointer_type (char_type_node);
12094 0 : OMP_CLAUSE_DECL (alloc)
12095 0 : = build2 (MEM_REF, char_type_node,
12096 : tmp,
12097 : build_int_cst (char_ptr_type, 0));
12098 0 : OMP_CLAUSE_SIZE (alloc) = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
12099 :
12100 0 : OMP_CLAUSE_CHAIN (alloc)
12101 0 : = OMP_CLAUSE_CHAIN (*to_group->grp_start);
12102 0 : OMP_CLAUSE_CHAIN (*to_group->grp_start) = alloc;
12103 : }
12104 : }
12105 : }
12106 : break;
12107 :
12108 : case GOMP_MAP_ATTACH_DETACH:
12109 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
12110 : {
12111 2626 : tree base_ptr, referenced_ptr_node = NULL_TREE;
12112 :
12113 2626 : while (TREE_CODE (decl) == ARRAY_REF)
12114 0 : decl = TREE_OPERAND (decl, 0);
12115 :
12116 2626 : if (TREE_CODE (decl) == INDIRECT_REF)
12117 13 : decl = TREE_OPERAND (decl, 0);
12118 :
12119 : /* Only component accesses. */
12120 2626 : if (DECL_P (decl))
12121 230 : continue;
12122 :
12123 : /* We want the pointer itself when checking if the base pointer is
12124 : mapped elsewhere in the same directive -- if we have a
12125 : reference to the pointer, don't use that. */
12126 :
12127 2396 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12128 2396 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12129 : {
12130 394 : referenced_ptr_node = OMP_CLAUSE_CHAIN (*grp->grp_start);
12131 394 : base_ptr = OMP_CLAUSE_DECL (referenced_ptr_node);
12132 : }
12133 : else
12134 : base_ptr = decl;
12135 :
12136 1978 : gomp_map_kind zlas_kind
12137 2396 : = (code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
12138 2396 : ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION;
12139 :
12140 2396 : if (TREE_CODE (TREE_TYPE (base_ptr)) == POINTER_TYPE)
12141 : {
12142 : /* If we map the base TO, and we're doing an attachment, we can
12143 : skip the TO mapping altogether and create an ALLOC mapping
12144 : instead, since the attachment will overwrite the device
12145 : pointer in that location immediately anyway. Otherwise,
12146 : change our mapping to
12147 : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION in case the
12148 : attachment target has not been copied to the device already
12149 : by some earlier directive. */
12150 :
12151 1972 : bool base_mapped_to = false;
12152 :
12153 1972 : omp_mapping_group *base_group;
12154 :
12155 1972 : if (omp_directive_maps_explicitly (grpmap, base_ptr,
12156 : &base_group, false, true,
12157 : false))
12158 : {
12159 450 : if (referenced_ptr_node)
12160 : {
12161 129 : base_mapped_to = true;
12162 129 : if ((OMP_CLAUSE_MAP_KIND (base_group->grp_end)
12163 : == GOMP_MAP_ATTACH_DETACH)
12164 129 : && (OMP_CLAUSE_CHAIN (*base_group->grp_start)
12165 : == base_group->grp_end))
12166 : {
12167 258 : OMP_CLAUSE_CHAIN (*base_group->grp_start)
12168 129 : = OMP_CLAUSE_CHAIN (base_group->grp_end);
12169 129 : base_group->grp_end = *base_group->grp_start;
12170 129 : repair_chain = true;
12171 : }
12172 : }
12173 : else
12174 : {
12175 321 : base_group->deleted = true;
12176 321 : OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end) = 1;
12177 : }
12178 : }
12179 :
12180 : /* We're dealing with a reference to a pointer, and we are
12181 : attaching both the reference and the pointer. We know the
12182 : reference itself is on the target, because we are going to
12183 : create an ALLOC node for it in accumulate_sibling_list. The
12184 : pointer might be on the target already or it might not, but
12185 : if it isn't then it's not an error, so use
12186 : GOMP_MAP_ATTACH_ZLAS for it. */
12187 1972 : if (!base_mapped_to && referenced_ptr_node)
12188 56 : OMP_CLAUSE_SET_MAP_KIND (referenced_ptr_node, zlas_kind);
12189 :
12190 1972 : omp_mapping_group *struct_group;
12191 1972 : tree desc;
12192 1972 : if ((desc = OMP_CLAUSE_CHAIN (*grp->grp_start))
12193 1972 : && omp_map_clause_descriptor_p (desc)
12194 3050 : && omp_mapped_by_containing_struct (grpmap, decl,
12195 : &struct_group))
12196 : /* If we have a pointer set but we're mapping (or unmapping)
12197 : the whole of the containing struct, we can remove the
12198 : pointer set mapping. */
12199 15 : OMP_CLAUSE_CHAIN (*grp->grp_start) = OMP_CLAUSE_CHAIN (desc);
12200 : }
12201 424 : else if (TREE_CODE (TREE_TYPE (base_ptr)) == REFERENCE_TYPE
12202 424 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (base_ptr)))
12203 : == ARRAY_TYPE)
12204 562 : && OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION
12205 : (*grp->grp_start))
12206 92 : OMP_CLAUSE_SET_MAP_KIND (grp->grp_end, zlas_kind);
12207 : }
12208 : break;
12209 :
12210 : case GOMP_MAP_ATTACH:
12211 : /* Ignore standalone attach here. */
12212 : break;
12213 :
12214 11839 : default:
12215 11839 : {
12216 11839 : omp_mapping_group *struct_group;
12217 11839 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12218 11839 : && *grp->grp_start == grp_end)
12219 : {
12220 94 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12221 : struct_group, grp);
12222 : /* Remove the whole of this mapping -- redundant. */
12223 94 : grp->deleted = true;
12224 : }
12225 :
12226 11839 : tree base = decl;
12227 13451 : while ((base = omp_get_base_pointer (base)))
12228 : {
12229 1612 : omp_mapping_group *base_group;
12230 :
12231 1612 : if (omp_directive_maps_explicitly (grpmap, base, &base_group,
12232 : true, true, false))
12233 : {
12234 343 : tree grp_first = *base_group->grp_start;
12235 343 : OMP_CLAUSE_SET_MAP_KIND (grp_first, GOMP_MAP_ALLOC);
12236 : }
12237 : }
12238 : }
12239 : }
12240 : }
12241 :
12242 8640 : if (repair_chain)
12243 : {
12244 : /* Group start pointers may have become detached from the
12245 : OMP_CLAUSE_CHAIN of previous groups if elements were removed from the
12246 : end of those groups. Fix that now. */
12247 : tree *new_next = NULL;
12248 716 : FOR_EACH_VEC_ELT (*groups, i, grp)
12249 : {
12250 587 : if (new_next)
12251 458 : grp->grp_start = new_next;
12252 :
12253 587 : new_next = &OMP_CLAUSE_CHAIN (grp->grp_end);
12254 : }
12255 : }
12256 8640 : }
12257 :
12258 : /* Similar to omp_resolve_clause_dependencies, but for OpenACC. The only
12259 : clause dependencies we handle for now are struct element mappings and
12260 : whole-struct mappings on the same directive, and duplicate clause
12261 : detection. */
12262 :
12263 : void
12264 9462 : oacc_resolve_clause_dependencies (vec<omp_mapping_group> *groups,
12265 : hash_map<tree_operand_hash_no_se,
12266 : omp_mapping_group *> *grpmap)
12267 : {
12268 9462 : int i;
12269 9462 : omp_mapping_group *grp;
12270 9462 : hash_set<tree_operand_hash> *seen_components = NULL;
12271 9462 : hash_set<tree_operand_hash> *shown_error = NULL;
12272 :
12273 24643 : FOR_EACH_VEC_ELT (*groups, i, grp)
12274 : {
12275 15181 : tree grp_end = grp->grp_end;
12276 15181 : tree decl = OMP_CLAUSE_DECL (grp_end);
12277 :
12278 15181 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12279 :
12280 15181 : if (DECL_P (grp_end))
12281 14664 : continue;
12282 :
12283 15181 : tree c = OMP_CLAUSE_DECL (*grp->grp_start);
12284 16806 : while (TREE_CODE (c) == ARRAY_REF)
12285 1625 : c = TREE_OPERAND (c, 0);
12286 15181 : if (TREE_CODE (c) != COMPONENT_REF)
12287 14664 : continue;
12288 517 : if (!seen_components)
12289 474 : seen_components = new hash_set<tree_operand_hash> ();
12290 517 : if (!shown_error)
12291 474 : shown_error = new hash_set<tree_operand_hash> ();
12292 517 : if (seen_components->contains (c)
12293 517 : && !shown_error->contains (c))
12294 : {
12295 10 : error_at (OMP_CLAUSE_LOCATION (grp_end),
12296 : "%qE appears more than once in map clauses",
12297 5 : OMP_CLAUSE_DECL (grp_end));
12298 5 : shown_error->add (c);
12299 : }
12300 : else
12301 512 : seen_components->add (c);
12302 :
12303 517 : omp_mapping_group *struct_group;
12304 517 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12305 517 : && *grp->grp_start == grp_end)
12306 : {
12307 78 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12308 : struct_group, grp);
12309 : /* Remove the whole of this mapping -- redundant. */
12310 78 : grp->deleted = true;
12311 : }
12312 : }
12313 :
12314 9462 : if (seen_components)
12315 474 : delete seen_components;
12316 9462 : if (shown_error)
12317 474 : delete shown_error;
12318 9462 : }
12319 :
12320 : /* Link node NEWNODE so it is pointed to by chain INSERT_AT. NEWNODE's chain
12321 : is linked to the previous node pointed to by INSERT_AT. */
12322 :
12323 : static tree *
12324 1135 : omp_siblist_insert_node_after (tree newnode, tree *insert_at)
12325 : {
12326 1135 : OMP_CLAUSE_CHAIN (newnode) = *insert_at;
12327 1135 : *insert_at = newnode;
12328 1135 : return &OMP_CLAUSE_CHAIN (newnode);
12329 : }
12330 :
12331 : /* Move NODE (which is currently pointed to by the chain OLD_POS) so it is
12332 : pointed to by chain MOVE_AFTER instead. */
12333 :
12334 : static void
12335 1320 : omp_siblist_move_node_after (tree node, tree *old_pos, tree *move_after)
12336 : {
12337 1320 : gcc_assert (node == *old_pos);
12338 1320 : *old_pos = OMP_CLAUSE_CHAIN (node);
12339 1320 : OMP_CLAUSE_CHAIN (node) = *move_after;
12340 1320 : *move_after = node;
12341 1320 : }
12342 :
12343 : /* Move nodes from FIRST_PTR (pointed to by previous node's chain) to
12344 : LAST_NODE to after MOVE_AFTER chain. Similar to below function, but no
12345 : new nodes are prepended to the list before splicing into the new position.
12346 : Return the position we should continue scanning the list at, or NULL to
12347 : stay where we were. */
12348 :
12349 : static tree *
12350 254 : omp_siblist_move_nodes_after (tree *first_ptr, tree last_node,
12351 : tree *move_after)
12352 : {
12353 254 : if (first_ptr == move_after)
12354 : return NULL;
12355 :
12356 243 : tree tmp = *first_ptr;
12357 243 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12358 243 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12359 243 : *move_after = tmp;
12360 :
12361 243 : return first_ptr;
12362 : }
12363 :
12364 : /* Concatenate two lists described by [FIRST_NEW, LAST_NEW_TAIL] and
12365 : [FIRST_PTR, LAST_NODE], and insert them in the OMP clause list after chain
12366 : pointer MOVE_AFTER.
12367 :
12368 : The latter list was previously part of the OMP clause list, and the former
12369 : (prepended) part is comprised of new nodes.
12370 :
12371 : We start with a list of nodes starting with a struct mapping node. We
12372 : rearrange the list so that new nodes starting from FIRST_NEW and whose last
12373 : node's chain is LAST_NEW_TAIL comes directly after MOVE_AFTER, followed by
12374 : the group of mapping nodes we are currently processing (from the chain
12375 : FIRST_PTR to LAST_NODE). The return value is the pointer to the next chain
12376 : we should continue processing from, or NULL to stay where we were.
12377 :
12378 : The transformation (in the case where MOVE_AFTER and FIRST_PTR are
12379 : different) is worked through below. Here we are processing LAST_NODE, and
12380 : FIRST_PTR points at the preceding mapping clause:
12381 :
12382 : #. mapping node chain
12383 : ---------------------------------------------------
12384 : A. struct_node [->B]
12385 : B. comp_1 [->C]
12386 : C. comp_2 [->D (move_after)]
12387 : D. map_to_3 [->E]
12388 : E. attach_3 [->F (first_ptr)]
12389 : F. map_to_4 [->G (continue_at)]
12390 : G. attach_4 (last_node) [->H]
12391 : H. ...
12392 :
12393 : *last_new_tail = *first_ptr;
12394 :
12395 : I. new_node (first_new) [->F (last_new_tail)]
12396 :
12397 : *first_ptr = OMP_CLAUSE_CHAIN (last_node)
12398 :
12399 : #. mapping node chain
12400 : ----------------------------------------------------
12401 : A. struct_node [->B]
12402 : B. comp_1 [->C]
12403 : C. comp_2 [->D (move_after)]
12404 : D. map_to_3 [->E]
12405 : E. attach_3 [->H (first_ptr)]
12406 : F. map_to_4 [->G (continue_at)]
12407 : G. attach_4 (last_node) [->H]
12408 : H. ...
12409 :
12410 : I. new_node (first_new) [->F (last_new_tail)]
12411 :
12412 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12413 :
12414 : #. mapping node chain
12415 : ---------------------------------------------------
12416 : A. struct_node [->B]
12417 : B. comp_1 [->C]
12418 : C. comp_2 [->D (move_after)]
12419 : D. map_to_3 [->E]
12420 : E. attach_3 [->H (continue_at)]
12421 : F. map_to_4 [->G]
12422 : G. attach_4 (last_node) [->D]
12423 : H. ...
12424 :
12425 : I. new_node (first_new) [->F (last_new_tail)]
12426 :
12427 : *move_after = first_new;
12428 :
12429 : #. mapping node chain
12430 : ---------------------------------------------------
12431 : A. struct_node [->B]
12432 : B. comp_1 [->C]
12433 : C. comp_2 [->I (move_after)]
12434 : D. map_to_3 [->E]
12435 : E. attach_3 [->H (continue_at)]
12436 : F. map_to_4 [->G]
12437 : G. attach_4 (last_node) [->D]
12438 : H. ...
12439 : I. new_node (first_new) [->F (last_new_tail)]
12440 :
12441 : or, in order:
12442 :
12443 : #. mapping node chain
12444 : ---------------------------------------------------
12445 : A. struct_node [->B]
12446 : B. comp_1 [->C]
12447 : C. comp_2 [->I (move_after)]
12448 : I. new_node (first_new) [->F (last_new_tail)]
12449 : F. map_to_4 [->G]
12450 : G. attach_4 (last_node) [->D]
12451 : D. map_to_3 [->E]
12452 : E. attach_3 [->H (continue_at)]
12453 : H. ...
12454 : */
12455 :
12456 : static tree *
12457 71 : omp_siblist_move_concat_nodes_after (tree first_new, tree *last_new_tail,
12458 : tree *first_ptr, tree last_node,
12459 : tree *move_after)
12460 : {
12461 71 : tree *continue_at = NULL;
12462 71 : *last_new_tail = *first_ptr;
12463 71 : if (first_ptr == move_after)
12464 12 : *move_after = first_new;
12465 : else
12466 : {
12467 59 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12468 59 : continue_at = first_ptr;
12469 59 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12470 59 : *move_after = first_new;
12471 : }
12472 71 : return continue_at;
12473 : }
12474 :
12475 : static omp_addr_token *
12476 11572 : omp_first_chained_access_token (vec<omp_addr_token *> &addr_tokens)
12477 : {
12478 11572 : using namespace omp_addr_tokenizer;
12479 11572 : int idx = addr_tokens.length () - 1;
12480 11572 : gcc_assert (idx >= 0);
12481 11572 : if (addr_tokens[idx]->type != ACCESS_METHOD)
12482 : return addr_tokens[idx];
12483 11603 : while (idx > 0 && addr_tokens[idx - 1]->type == ACCESS_METHOD)
12484 : idx--;
12485 11572 : return addr_tokens[idx];
12486 : }
12487 :
12488 : /* Mapping struct members causes an additional set of nodes to be created,
12489 : starting with GOMP_MAP_STRUCT followed by a number of mappings equal to the
12490 : number of members being mapped, in order of ascending position (address or
12491 : bitwise).
12492 :
12493 : We scan through the list of mapping clauses, calling this function for each
12494 : struct member mapping we find, and build up the list of mappings after the
12495 : initial GOMP_MAP_STRUCT node. For pointer members, these will be
12496 : newly-created ALLOC nodes. For non-pointer members, the existing mapping is
12497 : moved into place in the sorted list.
12498 :
12499 : struct {
12500 : int *a;
12501 : int *b;
12502 : int c;
12503 : int *d;
12504 : };
12505 :
12506 : #pragma (acc|omp directive) copy(struct.a[0:n], struct.b[0:n], struct.c,
12507 : struct.d[0:n])
12508 :
12509 : GOMP_MAP_STRUCT (4)
12510 : [GOMP_MAP_FIRSTPRIVATE_REFERENCE -- for refs to structs]
12511 : GOMP_MAP_ALLOC (struct.a)
12512 : GOMP_MAP_ALLOC (struct.b)
12513 : GOMP_MAP_TO (struct.c)
12514 : GOMP_MAP_ALLOC (struct.d)
12515 : ...
12516 :
12517 : In the case where we are mapping references to pointers, or in Fortran if
12518 : we are mapping an array with a descriptor, additional nodes may be created
12519 : after the struct node list also.
12520 :
12521 : The return code is either a pointer to the next node to process (if the
12522 : list has been rearranged), else NULL to continue with the next node in the
12523 : original list. */
12524 :
12525 : static tree *
12526 4767 : omp_accumulate_sibling_list (enum omp_region_type region_type,
12527 : enum tree_code code,
12528 : hash_map<tree_operand_hash, tree>
12529 : *&struct_map_to_clause,
12530 : hash_map<tree_operand_hash_no_se,
12531 : omp_mapping_group *> *group_map,
12532 : tree *grp_start_p, tree grp_end,
12533 : vec<omp_addr_token *> &addr_tokens, tree **inner,
12534 : bool *fragile_p, bool reprocessing_struct,
12535 : tree **added_tail)
12536 : {
12537 4767 : using namespace omp_addr_tokenizer;
12538 4767 : poly_offset_int coffset;
12539 4767 : poly_int64 cbitpos;
12540 4767 : tree ocd = OMP_CLAUSE_DECL (grp_end);
12541 4767 : bool openmp = !(region_type & ORT_ACC);
12542 4767 : bool target = (region_type & ORT_TARGET) != 0;
12543 4767 : tree *continue_at = NULL;
12544 :
12545 5080 : while (TREE_CODE (ocd) == ARRAY_REF)
12546 313 : ocd = TREE_OPERAND (ocd, 0);
12547 :
12548 4767 : if (*fragile_p)
12549 : {
12550 156 : omp_mapping_group *to_group
12551 156 : = omp_get_nonfirstprivate_group (group_map, ocd, true);
12552 :
12553 156 : if (to_group)
12554 : return NULL;
12555 : }
12556 :
12557 4679 : omp_addr_token *last_token = omp_first_chained_access_token (addr_tokens);
12558 4679 : if (last_token->type == ACCESS_METHOD)
12559 : {
12560 4679 : switch (last_token->u.access_kind)
12561 : {
12562 735 : case ACCESS_REF:
12563 735 : case ACCESS_REF_TO_POINTER:
12564 735 : case ACCESS_REF_TO_POINTER_OFFSET:
12565 735 : case ACCESS_INDEXED_REF_TO_ARRAY:
12566 : /* We may see either a bare reference or a dereferenced
12567 : "convert_from_reference"-like one here. Handle either way. */
12568 735 : if (TREE_CODE (ocd) == INDIRECT_REF)
12569 64 : ocd = TREE_OPERAND (ocd, 0);
12570 735 : gcc_assert (TREE_CODE (TREE_TYPE (ocd)) == REFERENCE_TYPE);
12571 : break;
12572 :
12573 : default:
12574 : ;
12575 : }
12576 : }
12577 :
12578 4679 : bool variable_offset;
12579 9358 : tree iterators = OMP_CLAUSE_HAS_ITERATORS (grp_end)
12580 4712 : ? OMP_CLAUSE_ITERATORS (grp_end) : NULL_TREE;
12581 4679 : tree base
12582 4679 : = extract_base_bit_offset (ocd, &cbitpos, &coffset, &variable_offset,
12583 4679 : iterators);
12584 :
12585 4679 : int base_token;
12586 23907 : for (base_token = addr_tokens.length () - 1; base_token >= 0; base_token--)
12587 : {
12588 19228 : if (addr_tokens[base_token]->type == ARRAY_BASE
12589 19228 : || addr_tokens[base_token]->type == STRUCTURE_BASE)
12590 : break;
12591 : }
12592 :
12593 : /* The two expressions in the assertion below aren't quite the same: if we
12594 : have 'struct_base_decl access_indexed_array' for something like
12595 : "myvar[2].x" then base will be "myvar" and addr_tokens[base_token]->expr
12596 : will be "myvar[2]" -- the actual base of the structure.
12597 : The former interpretation leads to a strange situation where we get
12598 : struct(myvar) alloc(myvar[2].ptr1)
12599 : That is, the array of structures is kind of treated as one big structure
12600 : for the purposes of gathering sibling lists, etc. */
12601 : /* gcc_assert (base == addr_tokens[base_token]->expr); */
12602 :
12603 4679 : bool attach_detach = ((OMP_CLAUSE_MAP_KIND (grp_end)
12604 : == GOMP_MAP_ATTACH_DETACH)
12605 4679 : || (OMP_CLAUSE_MAP_KIND (grp_end)
12606 4679 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
12607 4679 : bool has_descriptor = false;
12608 4679 : if (OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
12609 : {
12610 3139 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
12611 3139 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
12612 : has_descriptor = true;
12613 : }
12614 :
12615 4679 : if (!struct_map_to_clause || struct_map_to_clause->get (base) == NULL)
12616 : {
12617 3060 : enum gomp_map_kind str_kind = GOMP_MAP_STRUCT;
12618 :
12619 3060 : if (struct_map_to_clause == NULL)
12620 2497 : struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
12621 :
12622 3060 : if (variable_offset)
12623 274 : str_kind = GOMP_MAP_STRUCT_UNORD;
12624 :
12625 3060 : tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
12626 :
12627 3060 : OMP_CLAUSE_SET_MAP_KIND (l, str_kind);
12628 3060 : OMP_CLAUSE_DECL (l) = unshare_expr (base);
12629 3060 : OMP_CLAUSE_SIZE (l) = size_int (1);
12630 :
12631 3060 : struct_map_to_clause->put (base, l);
12632 :
12633 : /* On first iterating through the clause list, we insert the struct node
12634 : just before the component access node that triggers the initial
12635 : omp_accumulate_sibling_list call for a particular sibling list (and
12636 : it then forms the first entry in that list). When reprocessing
12637 : struct bases that are themselves component accesses, we insert the
12638 : struct node on an off-side list to avoid inserting the new
12639 : GOMP_MAP_STRUCT into the middle of the old one. */
12640 3060 : tree *insert_node_pos = reprocessing_struct ? *added_tail : grp_start_p;
12641 :
12642 3060 : if (has_descriptor)
12643 : {
12644 759 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
12645 759 : if (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
12646 187 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
12647 759 : tree sc = *insert_node_pos;
12648 759 : OMP_CLAUSE_CHAIN (l) = desc;
12649 759 : OMP_CLAUSE_CHAIN (*grp_start_p) = OMP_CLAUSE_CHAIN (desc);
12650 759 : OMP_CLAUSE_CHAIN (desc) = sc;
12651 759 : *insert_node_pos = l;
12652 : }
12653 2301 : else if (attach_detach)
12654 : {
12655 1396 : tree extra_node;
12656 1396 : tree alloc_node
12657 1396 : = build_omp_struct_comp_nodes (code, *grp_start_p, grp_end,
12658 : &extra_node);
12659 1396 : tree *tail;
12660 1396 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12661 :
12662 1396 : if (extra_node)
12663 : {
12664 0 : OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos;
12665 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
12666 0 : tail = &OMP_CLAUSE_CHAIN (extra_node);
12667 : }
12668 : else
12669 : {
12670 1396 : OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
12671 1396 : tail = &OMP_CLAUSE_CHAIN (alloc_node);
12672 : }
12673 :
12674 : /* For OpenMP semantics, we don't want to implicitly allocate
12675 : space for the pointer here for non-compute regions (e.g. "enter
12676 : data"). A FRAGILE_P node is only being created so that
12677 : omp-low.cc is able to rewrite the struct properly.
12678 : For references (to pointers), we want to actually allocate the
12679 : space for the reference itself in the sorted list following the
12680 : struct node.
12681 : For pointers, we want to allocate space if we had an explicit
12682 : mapping of the attachment point, but not otherwise. */
12683 1396 : if (*fragile_p
12684 1396 : || (openmp
12685 : && !target
12686 : && attach_detach
12687 234 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
12688 88 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
12689 : {
12690 133 : if (!lang_GNU_Fortran ())
12691 : /* In Fortran, pointers are dereferenced automatically, but may
12692 : be unassociated. So we still want to allocate space for the
12693 : pointer (as the base for an attach operation that should be
12694 : present in the same directive's clause list also). */
12695 103 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
12696 133 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
12697 : }
12698 :
12699 1396 : *insert_node_pos = l;
12700 :
12701 1396 : if (reprocessing_struct)
12702 : {
12703 : /* When reprocessing a struct node group used as the base of a
12704 : subcomponent access, if we have a reference-to-pointer base,
12705 : we will see:
12706 : struct(**ptr) attach(*ptr)
12707 : whereas for a non-reprocess-struct group, we see, e.g.:
12708 : tofrom(**ptr) attach(*ptr) attach(ptr)
12709 : and we create the "alloc" for the second "attach", i.e.
12710 : for the reference itself. When reprocessing a struct group we
12711 : thus change the pointer attachment into a reference attachment
12712 : by stripping the indirection. (The attachment of the
12713 : referenced pointer must happen elsewhere, either on the same
12714 : directive, or otherwise.) */
12715 180 : tree adecl = OMP_CLAUSE_DECL (alloc_node);
12716 :
12717 180 : if ((TREE_CODE (adecl) == INDIRECT_REF
12718 148 : || (TREE_CODE (adecl) == MEM_REF
12719 0 : && integer_zerop (TREE_OPERAND (adecl, 1))))
12720 32 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (adecl, 0)))
12721 : == REFERENCE_TYPE)
12722 212 : && (TREE_CODE (TREE_TYPE (TREE_TYPE
12723 : (TREE_OPERAND (adecl, 0)))) == POINTER_TYPE))
12724 32 : OMP_CLAUSE_DECL (alloc_node) = TREE_OPERAND (adecl, 0);
12725 :
12726 180 : *added_tail = tail;
12727 : }
12728 : }
12729 : else
12730 : {
12731 905 : gcc_assert (*grp_start_p == grp_end);
12732 905 : if (reprocessing_struct)
12733 : {
12734 : /* If we don't have an attach/detach node, this is a
12735 : "target data" directive or similar, not an offload region.
12736 : Synthesize an "alloc" node using just the initiating
12737 : GOMP_MAP_STRUCT decl. */
12738 16 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
12739 32 : || code == OACC_EXIT_DATA)
12740 32 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
12741 32 : tree alloc_node
12742 32 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12743 : OMP_CLAUSE_MAP);
12744 32 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
12745 32 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
12746 64 : OMP_CLAUSE_SIZE (alloc_node)
12747 32 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
12748 :
12749 32 : OMP_CLAUSE_CHAIN (alloc_node) = OMP_CLAUSE_CHAIN (l);
12750 32 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12751 32 : *insert_node_pos = l;
12752 32 : *added_tail = &OMP_CLAUSE_CHAIN (alloc_node);
12753 : }
12754 : else
12755 873 : grp_start_p = omp_siblist_insert_node_after (l, insert_node_pos);
12756 : }
12757 :
12758 3060 : unsigned last_access = base_token + 1;
12759 :
12760 3060 : while (last_access + 1 < addr_tokens.length ()
12761 3395 : && addr_tokens[last_access + 1]->type == ACCESS_METHOD)
12762 : last_access++;
12763 :
12764 3060 : if ((region_type & ORT_TARGET)
12765 3060 : && addr_tokens[base_token + 1]->type == ACCESS_METHOD)
12766 : {
12767 1708 : bool base_ref = false;
12768 1708 : access_method_kinds access_kind
12769 1708 : = addr_tokens[last_access]->u.access_kind;
12770 :
12771 1708 : switch (access_kind)
12772 : {
12773 : case ACCESS_DIRECT:
12774 : case ACCESS_INDEXED_ARRAY:
12775 1060 : return NULL;
12776 :
12777 403 : case ACCESS_REF:
12778 403 : case ACCESS_REF_TO_POINTER:
12779 403 : case ACCESS_REF_TO_POINTER_OFFSET:
12780 403 : case ACCESS_INDEXED_REF_TO_ARRAY:
12781 403 : base_ref = true;
12782 403 : break;
12783 :
12784 866 : default:
12785 866 : ;
12786 : }
12787 866 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12788 : OMP_CLAUSE_MAP);
12789 866 : enum gomp_map_kind mkind;
12790 866 : omp_mapping_group *decl_group;
12791 866 : tree use_base;
12792 866 : switch (access_kind)
12793 : {
12794 463 : case ACCESS_POINTER:
12795 463 : case ACCESS_POINTER_OFFSET:
12796 463 : use_base = addr_tokens[last_access]->expr;
12797 463 : break;
12798 198 : case ACCESS_REF_TO_POINTER:
12799 198 : case ACCESS_REF_TO_POINTER_OFFSET:
12800 198 : use_base
12801 198 : = build_fold_indirect_ref (addr_tokens[last_access]->expr);
12802 198 : break;
12803 205 : default:
12804 205 : use_base = addr_tokens[base_token]->expr;
12805 : }
12806 866 : bool mapped_to_p
12807 866 : = omp_directive_maps_explicitly (group_map, use_base, &decl_group,
12808 : true, false, true);
12809 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12810 866 : && DECL_P (addr_tokens[last_access]->expr)
12811 1372 : && !mapped_to_p)
12812 444 : mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
12813 : : GOMP_MAP_FIRSTPRIVATE_POINTER;
12814 : else
12815 : mkind = GOMP_MAP_ATTACH_DETACH;
12816 :
12817 866 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
12818 : /* If we have a reference to pointer base, we want to attach the
12819 : pointer here, not the reference. The reference attachment happens
12820 : elsewhere. */
12821 866 : bool ref_to_ptr
12822 866 : = (access_kind == ACCESS_REF_TO_POINTER
12823 866 : || access_kind == ACCESS_REF_TO_POINTER_OFFSET);
12824 866 : tree sdecl = addr_tokens[last_access]->expr;
12825 866 : tree sdecl_ptr = ref_to_ptr ? build_fold_indirect_ref (sdecl)
12826 : : sdecl;
12827 : /* For the FIRSTPRIVATE_REFERENCE after the struct node, we
12828 : want to use the reference itself for the decl, but we
12829 : still want to use the pointer to calculate the bias. */
12830 866 : OMP_CLAUSE_DECL (c2) = (mkind == GOMP_MAP_ATTACH_DETACH)
12831 866 : ? sdecl_ptr : sdecl;
12832 866 : sdecl = sdecl_ptr;
12833 866 : tree baddr = build_fold_addr_expr (base);
12834 866 : baddr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12835 : ptrdiff_type_node, baddr);
12836 866 : tree decladdr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12837 : ptrdiff_type_node, sdecl);
12838 866 : OMP_CLAUSE_SIZE (c2)
12839 866 : = fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR,
12840 : ptrdiff_type_node, baddr, decladdr);
12841 : /* Insert after struct node. */
12842 866 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
12843 866 : OMP_CLAUSE_CHAIN (l) = c2;
12844 :
12845 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12846 866 : && (addr_tokens[base_token]->u.structure_base_kind
12847 : == BASE_COMPONENT_EXPR)
12848 286 : && mkind == GOMP_MAP_ATTACH_DETACH
12849 1152 : && addr_tokens[last_access]->u.access_kind != ACCESS_REF)
12850 : {
12851 218 : *inner = insert_node_pos;
12852 218 : if (openmp)
12853 166 : *fragile_p = true;
12854 : return NULL;
12855 : }
12856 : }
12857 :
12858 2000 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12859 2000 : && (addr_tokens[base_token]->u.structure_base_kind
12860 : == BASE_COMPONENT_EXPR)
12861 2467 : && addr_tokens[last_access]->u.access_kind == ACCESS_REF)
12862 100 : *inner = insert_node_pos;
12863 :
12864 : return NULL;
12865 : }
12866 1619 : else if (struct_map_to_clause)
12867 : {
12868 1619 : tree *osc = struct_map_to_clause->get (base);
12869 1619 : tree *sc = NULL, *scp = NULL;
12870 :
12871 1619 : unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
12872 1619 : sc = &OMP_CLAUSE_CHAIN (*osc);
12873 : /* The struct mapping might be immediately followed by a
12874 : FIRSTPRIVATE_POINTER, FIRSTPRIVATE_REFERENCE or an ATTACH_DETACH --
12875 : if it's an indirect access or a reference, or if the structure base
12876 : is not a decl. The FIRSTPRIVATE_* nodes are removed in omp-low.cc
12877 : after they have been processed there, and ATTACH_DETACH nodes are
12878 : recomputed and moved out of the GOMP_MAP_STRUCT construct once
12879 : sibling list building is complete. */
12880 1619 : if (OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_POINTER
12881 1574 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
12882 3148 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_ATTACH_DETACH)
12883 201 : sc = &OMP_CLAUSE_CHAIN (*sc);
12884 4108 : for (i = 0; i < elems; i++, sc = &OMP_CLAUSE_CHAIN (*sc))
12885 3062 : if (attach_detach && sc == grp_start_p)
12886 : break;
12887 3062 : else if (TREE_CODE (OMP_CLAUSE_DECL (*sc)) != COMPONENT_REF
12888 182 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != INDIRECT_REF
12889 3244 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != ARRAY_REF)
12890 : break;
12891 : else
12892 : {
12893 3062 : tree sc_decl = OMP_CLAUSE_DECL (*sc);
12894 3062 : poly_offset_int offset;
12895 3062 : poly_int64 bitpos;
12896 :
12897 3062 : if (TREE_CODE (sc_decl) == ARRAY_REF)
12898 : {
12899 366 : while (TREE_CODE (sc_decl) == ARRAY_REF)
12900 184 : sc_decl = TREE_OPERAND (sc_decl, 0);
12901 182 : if (TREE_CODE (sc_decl) != COMPONENT_REF
12902 182 : || TREE_CODE (TREE_TYPE (sc_decl)) != ARRAY_TYPE)
12903 : break;
12904 : }
12905 2880 : else if (INDIRECT_REF_P (sc_decl)
12906 0 : && TREE_CODE (TREE_OPERAND (sc_decl, 0)) == COMPONENT_REF
12907 2880 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (sc_decl, 0)))
12908 : == REFERENCE_TYPE))
12909 0 : sc_decl = TREE_OPERAND (sc_decl, 0);
12910 :
12911 3062 : bool variable_offset2;
12912 3062 : tree iterators2 = OMP_CLAUSE_HAS_ITERATORS (*sc)
12913 3062 : ? OMP_CLAUSE_ITERATORS (*sc) : NULL_TREE;
12914 :
12915 3062 : tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset,
12916 : &variable_offset2,
12917 : iterators2);
12918 3062 : if (!base2 || !operand_equal_p (base2, base, 0))
12919 : break;
12920 3062 : if (scp)
12921 469 : continue;
12922 2842 : if (variable_offset2)
12923 : {
12924 341 : OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
12925 :
12926 341 : if (has_descriptor)
12927 : {
12928 : /* Sort mapped components by offset. This is needed for
12929 : libgomp to handle Fortran derived-type allocatable
12930 : components transparently. */
12931 :
12932 323 : poly_int64 bitsize;
12933 323 : tree offset, coffset;
12934 323 : machine_mode mode;
12935 323 : int unsignedp, reversep, volatilep;
12936 323 : tree inner_ref1
12937 323 : = get_inner_reference (sc_decl, &bitsize, &bitpos,
12938 : &offset, &mode, &unsignedp,
12939 : &reversep, &volatilep);
12940 323 : tree osc_decl = ocd;
12941 323 : STRIP_NOPS (osc_decl);
12942 323 : tree inner_ref2
12943 323 : = get_inner_reference (osc_decl, &bitsize, &bitpos,
12944 : &coffset, &mode, &unsignedp,
12945 : &reversep, &volatilep);
12946 323 : gcc_assert (operand_equal_p (inner_ref1, inner_ref2, 0));
12947 323 : tree offset_diff
12948 323 : = fold_binary_to_constant (MINUS_EXPR, size_type_node,
12949 : coffset, offset);
12950 572 : if (offset_diff == NULL_TREE
12951 323 : || TREE_INT_CST_ELT (offset_diff, 0) > 0)
12952 249 : continue;
12953 : else
12954 : break;
12955 : }
12956 : }
12957 2501 : else if ((region_type & ORT_ACC) != 0)
12958 : {
12959 : /* For OpenACC, allow (ignore) duplicate struct accesses in
12960 : the middle of a mapping clause, e.g. "mystruct->foo" in:
12961 : copy(mystruct->foo->bar) copy(mystruct->foo->qux). */
12962 223 : if (reprocessing_struct
12963 8 : && known_eq (coffset, offset)
12964 223 : && known_eq (cbitpos, bitpos))
12965 16 : return NULL;
12966 : }
12967 2278 : else if (known_eq (coffset, offset)
12968 2278 : && known_eq (cbitpos, bitpos))
12969 : {
12970 : /* Having two struct members at the same offset doesn't work,
12971 : so make sure we don't. (We're allowed to ignore this.
12972 : Should we report the error?) */
12973 : /*error_at (OMP_CLAUSE_LOCATION (grp_end),
12974 : "duplicate struct member %qE in map clauses",
12975 : OMP_CLAUSE_DECL (grp_end));*/
12976 : return NULL;
12977 : }
12978 2503 : if (maybe_lt (coffset, offset)
12979 4231 : || (known_eq (coffset, offset)
12980 20 : && maybe_lt (cbitpos, bitpos)))
12981 : {
12982 775 : if (attach_detach)
12983 : scp = sc;
12984 : else
12985 : break;
12986 : }
12987 : }
12988 :
12989 1603 : OMP_CLAUSE_SIZE (*osc)
12990 1603 : = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
12991 :
12992 1603 : if (reprocessing_struct)
12993 : {
12994 : /* If we're reprocessing a struct node, we don't want to do most of
12995 : the list manipulation below. We only need to handle the (pointer
12996 : or reference) attach/detach case. */
12997 8 : tree extra_node, alloc_node;
12998 8 : if (has_descriptor)
12999 0 : gcc_unreachable ();
13000 8 : else if (attach_detach)
13001 8 : alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
13002 : grp_end, &extra_node);
13003 : else
13004 : {
13005 : /* If we don't have an attach/detach node, this is a
13006 : "target data" directive or similar, not an offload region.
13007 : Synthesize an "alloc" node using just the initiating
13008 : GOMP_MAP_STRUCT decl. */
13009 0 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
13010 0 : || code == OACC_EXIT_DATA)
13011 0 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
13012 0 : alloc_node
13013 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
13014 : OMP_CLAUSE_MAP);
13015 0 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
13016 0 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
13017 0 : OMP_CLAUSE_SIZE (alloc_node)
13018 0 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
13019 : }
13020 :
13021 8 : if (scp)
13022 0 : omp_siblist_insert_node_after (alloc_node, scp);
13023 : else
13024 : {
13025 8 : tree *new_end = omp_siblist_insert_node_after (alloc_node, sc);
13026 8 : if (sc == *added_tail)
13027 8 : *added_tail = new_end;
13028 : }
13029 :
13030 8 : return NULL;
13031 : }
13032 :
13033 1595 : if (has_descriptor)
13034 : {
13035 538 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
13036 538 : if (code == OMP_TARGET_EXIT_DATA
13037 538 : || code == OACC_EXIT_DATA)
13038 105 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
13039 1076 : omp_siblist_move_node_after (desc,
13040 538 : &OMP_CLAUSE_CHAIN (*grp_start_p),
13041 : scp ? scp : sc);
13042 : }
13043 1057 : else if (attach_detach)
13044 : {
13045 325 : tree cl = NULL_TREE, extra_node;
13046 325 : tree alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
13047 : grp_end, &extra_node);
13048 325 : tree *tail_chain = NULL;
13049 :
13050 325 : if (*fragile_p
13051 325 : || (openmp
13052 : && !target
13053 : && attach_detach
13054 62 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
13055 23 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
13056 : {
13057 6 : if (!lang_GNU_Fortran ())
13058 6 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
13059 6 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
13060 : }
13061 :
13062 : /* Here, we have:
13063 :
13064 : grp_end : the last (or only) node in this group.
13065 : grp_start_p : pointer to the first node in a pointer mapping group
13066 : up to and including GRP_END.
13067 : sc : pointer to the chain for the end of the struct component
13068 : list.
13069 : scp : pointer to the chain for the sorted position at which we
13070 : should insert in the middle of the struct component list
13071 : (else NULL to insert at end).
13072 : alloc_node : the "alloc" node for the structure (pointer-type)
13073 : component. We insert at SCP (if present), else SC
13074 : (the end of the struct component list).
13075 : extra_node : a newly-synthesized node for an additional indirect
13076 : pointer mapping or a Fortran pointer set, if needed.
13077 : cl : first node to prepend before grp_start_p.
13078 : tail_chain : pointer to chain of last prepended node.
13079 :
13080 : The general idea is we move the nodes for this struct mapping
13081 : together: the alloc node goes into the sorted list directly after
13082 : the struct mapping, and any extra nodes (together with the nodes
13083 : mapping arrays pointed to by struct components) get moved after
13084 : that list. When SCP is NULL, we insert the nodes at SC, i.e. at
13085 : the end of the struct component mapping list. It's important that
13086 : the alloc_node comes first in that case because it's part of the
13087 : sorted component mapping list (but subsequent nodes are not!). */
13088 :
13089 325 : if (scp)
13090 254 : omp_siblist_insert_node_after (alloc_node, scp);
13091 :
13092 : /* Make [cl,tail_chain] a list of the alloc node (if we haven't
13093 : already inserted it) and the extra_node (if it is present). The
13094 : list can be empty if we added alloc_node above and there is no
13095 : extra node. */
13096 254 : if (scp && extra_node)
13097 : {
13098 0 : cl = extra_node;
13099 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13100 : }
13101 325 : else if (extra_node)
13102 : {
13103 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
13104 0 : cl = alloc_node;
13105 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13106 : }
13107 325 : else if (!scp)
13108 : {
13109 71 : cl = alloc_node;
13110 71 : tail_chain = &OMP_CLAUSE_CHAIN (alloc_node);
13111 : }
13112 :
13113 71 : continue_at
13114 71 : = cl ? omp_siblist_move_concat_nodes_after (cl, tail_chain,
13115 : grp_start_p, grp_end,
13116 : sc)
13117 254 : : omp_siblist_move_nodes_after (grp_start_p, grp_end, sc);
13118 : }
13119 732 : else if (*sc != grp_end)
13120 : {
13121 692 : gcc_assert (*grp_start_p == grp_end);
13122 :
13123 : /* We are moving the current node back to a previous struct node:
13124 : the node that used to point to the current node will now point to
13125 : the next node. */
13126 692 : continue_at = grp_start_p;
13127 : /* In the non-pointer case, the mapping clause itself is moved into
13128 : the correct position in the struct component list, which in this
13129 : case is just SC. */
13130 692 : omp_siblist_move_node_after (*grp_start_p, grp_start_p, sc);
13131 : }
13132 : }
13133 : return continue_at;
13134 : }
13135 :
13136 : /* Scan through GROUPS, and create sorted structure sibling lists without
13137 : gimplifying. */
13138 :
13139 : static bool
13140 18102 : omp_build_struct_sibling_lists (enum tree_code code,
13141 : enum omp_region_type region_type,
13142 : vec<omp_mapping_group> *groups,
13143 : hash_map<tree_operand_hash_no_se,
13144 : omp_mapping_group *> **grpmap,
13145 : tree *list_p)
13146 : {
13147 18102 : using namespace omp_addr_tokenizer;
13148 18102 : unsigned i;
13149 18102 : omp_mapping_group *grp;
13150 18102 : hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
13151 18102 : bool success = true;
13152 18102 : tree *new_next = NULL;
13153 36204 : tree *tail = &OMP_CLAUSE_CHAIN ((*groups)[groups->length () - 1].grp_end);
13154 18102 : tree added_nodes = NULL_TREE;
13155 18102 : tree *added_tail = &added_nodes;
13156 18102 : auto_vec<omp_mapping_group> pre_hwm_groups;
13157 :
13158 67637 : FOR_EACH_VEC_ELT (*groups, i, grp)
13159 : {
13160 31433 : tree c = grp->grp_end;
13161 31433 : tree decl = OMP_CLAUSE_DECL (c);
13162 31433 : tree grp_end = grp->grp_end;
13163 31433 : auto_vec<omp_addr_token *> addr_tokens;
13164 31433 : tree sentinel = OMP_CLAUSE_CHAIN (grp_end);
13165 :
13166 31433 : if (new_next && !grp->reprocess_struct)
13167 622 : grp->grp_start = new_next;
13168 :
13169 31433 : new_next = NULL;
13170 :
13171 31433 : tree *grp_start_p = grp->grp_start;
13172 :
13173 31433 : if (DECL_P (decl))
13174 21271 : continue;
13175 :
13176 : /* Skip groups we marked for deletion in
13177 : {omp,oacc}_resolve_clause_dependencies. */
13178 10162 : if (grp->deleted)
13179 462 : continue;
13180 :
13181 9700 : if (OMP_CLAUSE_CHAIN (*grp_start_p)
13182 9700 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
13183 : {
13184 : /* Don't process an array descriptor that isn't inside a derived type
13185 : as a struct (the GOMP_MAP_POINTER following will have the form
13186 : "var.data", but such mappings are handled specially). */
13187 6126 : tree grpmid = OMP_CLAUSE_CHAIN (*grp_start_p);
13188 6126 : if (omp_map_clause_descriptor_p (grpmid)
13189 10277 : && DECL_P (OMP_CLAUSE_DECL (grpmid)))
13190 2807 : continue;
13191 : }
13192 :
13193 7937 : tree expr = decl;
13194 :
13195 7937 : while (TREE_CODE (expr) == ARRAY_REF)
13196 1044 : expr = TREE_OPERAND (expr, 0);
13197 :
13198 6893 : if (!omp_parse_expr (addr_tokens, expr))
13199 0 : continue;
13200 :
13201 6893 : omp_addr_token *last_token
13202 6893 : = omp_first_chained_access_token (addr_tokens);
13203 :
13204 : /* A mapping of a reference to a pointer member that doesn't specify an
13205 : array section, etc., like this:
13206 : *mystruct.ref_to_ptr
13207 : should not be processed by the struct sibling-list handling code --
13208 : it just transfers the referenced pointer.
13209 :
13210 : In contrast, the quite similar-looking construct:
13211 : *mystruct.ptr
13212 : which is equivalent to e.g.
13213 : mystruct.ptr[0]
13214 : *does* trigger sibling-list processing.
13215 :
13216 : An exception for the former case is for "fragile" groups where the
13217 : reference itself is not handled otherwise; this is subject to special
13218 : handling in omp_accumulate_sibling_list also. */
13219 :
13220 6893 : if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
13221 3402 : && last_token->type == ACCESS_METHOD
13222 3402 : && last_token->u.access_kind == ACCESS_REF
13223 7175 : && !grp->fragile)
13224 217 : continue;
13225 :
13226 6676 : tree d = decl;
13227 6676 : if (TREE_CODE (d) == ARRAY_REF)
13228 : {
13229 2036 : while (TREE_CODE (d) == ARRAY_REF)
13230 1029 : d = TREE_OPERAND (d, 0);
13231 1007 : if (TREE_CODE (d) == COMPONENT_REF
13232 1007 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
13233 : decl = d;
13234 : }
13235 6676 : if (d == decl
13236 5982 : && INDIRECT_REF_P (decl)
13237 738 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
13238 105 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
13239 : == REFERENCE_TYPE)
13240 6773 : && (OMP_CLAUSE_MAP_KIND (c)
13241 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
13242 97 : decl = TREE_OPERAND (decl, 0);
13243 :
13244 6676 : STRIP_NOPS (decl);
13245 :
13246 6676 : if (TREE_CODE (decl) != COMPONENT_REF)
13247 1368 : continue;
13248 :
13249 : /* If we're mapping the whole struct in another node, skip adding this
13250 : node to a sibling list. */
13251 5308 : omp_mapping_group *wholestruct;
13252 5308 : if (omp_mapped_by_containing_struct (*grpmap, OMP_CLAUSE_DECL (c),
13253 : &wholestruct))
13254 : {
13255 178 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
13256 161 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
13257 178 : continue;
13258 : }
13259 :
13260 5130 : if (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
13261 5130 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
13262 5025 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
13263 : && code != OACC_UPDATE
13264 10088 : && code != OMP_TARGET_UPDATE)
13265 : {
13266 4767 : if (error_operand_p (decl))
13267 : {
13268 0 : success = false;
13269 0 : goto error_out;
13270 : }
13271 :
13272 4767 : tree stype = TREE_TYPE (decl);
13273 4767 : if (TREE_CODE (stype) == REFERENCE_TYPE)
13274 768 : stype = TREE_TYPE (stype);
13275 4767 : if (TYPE_SIZE_UNIT (stype) == NULL
13276 4767 : || TREE_CODE (TYPE_SIZE_UNIT (stype)) != INTEGER_CST)
13277 : {
13278 0 : error_at (OMP_CLAUSE_LOCATION (c),
13279 : "mapping field %qE of variable length "
13280 0 : "structure", OMP_CLAUSE_DECL (c));
13281 0 : success = false;
13282 0 : goto error_out;
13283 : }
13284 :
13285 4767 : tree *inner = NULL;
13286 4767 : bool fragile_p = grp->fragile;
13287 :
13288 4767 : new_next
13289 4767 : = omp_accumulate_sibling_list (region_type, code,
13290 : struct_map_to_clause, *grpmap,
13291 : grp_start_p, grp_end, addr_tokens,
13292 : &inner, &fragile_p,
13293 : grp->reprocess_struct, &added_tail);
13294 :
13295 4767 : if (inner)
13296 : {
13297 318 : omp_mapping_group newgrp;
13298 318 : newgrp.grp_start = inner;
13299 318 : if (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (*inner))
13300 : == GOMP_MAP_ATTACH_DETACH)
13301 286 : newgrp.grp_end = OMP_CLAUSE_CHAIN (*inner);
13302 : else
13303 : newgrp.grp_end = *inner;
13304 318 : newgrp.mark = UNVISITED;
13305 318 : newgrp.sibling = NULL;
13306 318 : newgrp.deleted = false;
13307 318 : newgrp.reprocess_struct = true;
13308 318 : newgrp.fragile = fragile_p;
13309 318 : newgrp.next = NULL;
13310 318 : groups->safe_push (newgrp);
13311 :
13312 : /* !!! Growing GROUPS might invalidate the pointers in the group
13313 : map. Rebuild it here. This is a bit inefficient, but
13314 : shouldn't happen very often. */
13315 636 : delete (*grpmap);
13316 318 : *grpmap
13317 318 : = omp_reindex_mapping_groups (list_p, groups, &pre_hwm_groups,
13318 : sentinel);
13319 : }
13320 : }
13321 31433 : }
13322 :
13323 : /* Delete groups marked for deletion above. At this point the order of the
13324 : groups may no longer correspond to the order of the underlying list,
13325 : which complicates this a little. First clear out OMP_CLAUSE_DECL for
13326 : deleted nodes... */
13327 :
13328 49535 : FOR_EACH_VEC_ELT (*groups, i, grp)
13329 31433 : if (grp->deleted)
13330 462 : for (tree d = *grp->grp_start;
13331 924 : d != OMP_CLAUSE_CHAIN (grp->grp_end);
13332 462 : d = OMP_CLAUSE_CHAIN (d))
13333 462 : OMP_CLAUSE_DECL (d) = NULL_TREE;
13334 :
13335 : /* ...then sweep through the list removing the now-empty nodes. */
13336 :
13337 : tail = list_p;
13338 96393 : while (*tail)
13339 : {
13340 78291 : if (OMP_CLAUSE_CODE (*tail) == OMP_CLAUSE_MAP
13341 78291 : && OMP_CLAUSE_DECL (*tail) == NULL_TREE)
13342 462 : *tail = OMP_CLAUSE_CHAIN (*tail);
13343 : else
13344 77829 : tail = &OMP_CLAUSE_CHAIN (*tail);
13345 : }
13346 :
13347 : /* Tack on the struct nodes added during nested struct reprocessing. */
13348 18102 : if (added_nodes)
13349 : {
13350 192 : *tail = added_nodes;
13351 192 : tail = added_tail;
13352 : }
13353 :
13354 : /* Find each attach node whose bias needs to be adjusted and move it to the
13355 : group containing its pointee, right after the struct node, so that it can
13356 : be picked up by the adjustment code further down in this function. */
13357 18102 : bool attach_bias_needs_adjustment;
13358 18102 : attach_bias_needs_adjustment = false;
13359 67637 : FOR_EACH_VEC_ELT_REVERSE (*groups, i, grp)
13360 : {
13361 31433 : tree c = *grp->grp_start;
13362 30494 : if (c != NULL && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13363 30479 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
13364 27406 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
13365 3353 : && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) == GOMP_MAP_TO_PSET
13366 560 : && OMP_CLAUSE_MAP_KIND (grp->grp_end) == GOMP_MAP_ATTACH_DETACH
13367 31993 : && OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end))
13368 : {
13369 90 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end) = 0;
13370 90 : attach_bias_needs_adjustment = true;
13371 90 : tree *cp;
13372 90 : for (cp = &OMP_CLAUSE_CHAIN (c); cp != NULL;
13373 206 : cp = &OMP_CLAUSE_CHAIN (*cp))
13374 296 : if (*cp == grp->grp_end)
13375 : {
13376 : c = *cp;
13377 : break;
13378 : }
13379 :
13380 90 : tree base = OMP_CLAUSE_DECL (c);
13381 90 : gcc_assert (TREE_CODE (base) == NOP_EXPR);
13382 90 : base = build_fold_indirect_ref (base);
13383 90 : tree *struct_node = struct_map_to_clause->get (base);
13384 90 : omp_siblist_move_node_after (c, cp, &OMP_CLAUSE_CHAIN (*struct_node));
13385 : }
13386 : }
13387 :
13388 : /* Now we have finished building the struct sibling lists, reprocess
13389 : newly-added "attach" nodes: we need the address of the first
13390 : mapped element of each struct sibling list for the bias of the attach
13391 : operation -- not necessarily the base address of the whole struct. */
13392 18102 : if (struct_map_to_clause)
13393 3060 : for (hash_map<tree_operand_hash, tree>::iterator iter
13394 2497 : = struct_map_to_clause->begin ();
13395 8054 : iter != struct_map_to_clause->end ();
13396 3060 : ++iter)
13397 : {
13398 3060 : tree struct_node = (*iter).second;
13399 3060 : gcc_assert (OMP_CLAUSE_CODE (struct_node) == OMP_CLAUSE_MAP);
13400 3060 : tree attach = OMP_CLAUSE_CHAIN (struct_node);
13401 :
13402 3060 : if (OMP_CLAUSE_CODE (attach) != OMP_CLAUSE_MAP
13403 3060 : || OMP_CLAUSE_MAP_KIND (attach) != GOMP_MAP_ATTACH_DETACH)
13404 2548 : continue;
13405 :
13406 512 : OMP_CLAUSE_SET_MAP_KIND (attach, GOMP_MAP_ATTACH);
13407 :
13408 : /* Sanity check: the standalone attach node will not work if we have
13409 : an "enter data" operation (because for those, variables need to be
13410 : mapped separately and attach nodes must be grouped together with the
13411 : base they attach to). We should only have created the
13412 : ATTACH_DETACH node either after GOMP_MAP_STRUCT for a target region
13413 : or for an intermediate descriptor that needs adjustment -- so this
13414 : should never be true. */
13415 512 : gcc_assert ((region_type & ORT_TARGET) != 0
13416 : || attach_bias_needs_adjustment);
13417 :
13418 : /* This is the first sorted node in the struct sibling list. Use it
13419 : to recalculate the correct bias to use.
13420 : (&first_node - attach_decl).
13421 : For GOMP_MAP_STRUCT_UNORD, we need e.g. the
13422 : min(min(min(first,second),third),fourth) element, because the
13423 : elements aren't in any particular order. */
13424 512 : tree lowest_addr;
13425 512 : if (OMP_CLAUSE_MAP_KIND (struct_node) == GOMP_MAP_STRUCT_UNORD)
13426 : {
13427 94 : tree first_node = OMP_CLAUSE_CHAIN (attach);
13428 94 : unsigned HOST_WIDE_INT num_mappings
13429 94 : = tree_to_uhwi (OMP_CLAUSE_SIZE (struct_node));
13430 94 : lowest_addr = OMP_CLAUSE_DECL (first_node);
13431 94 : lowest_addr = build_fold_addr_expr (lowest_addr);
13432 94 : lowest_addr = fold_convert (pointer_sized_int_node, lowest_addr);
13433 94 : tree next_node = OMP_CLAUSE_CHAIN (first_node);
13434 185 : while (num_mappings > 1)
13435 : {
13436 91 : tree tmp = OMP_CLAUSE_DECL (next_node);
13437 91 : tmp = build_fold_addr_expr (tmp);
13438 91 : tmp = fold_convert (pointer_sized_int_node, tmp);
13439 91 : lowest_addr = fold_build2 (MIN_EXPR, pointer_sized_int_node,
13440 : lowest_addr, tmp);
13441 91 : next_node = OMP_CLAUSE_CHAIN (next_node);
13442 91 : num_mappings--;
13443 : }
13444 94 : lowest_addr = fold_convert (ptrdiff_type_node, lowest_addr);
13445 : }
13446 : else
13447 : {
13448 418 : tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
13449 418 : first_node = build_fold_addr_expr (first_node);
13450 418 : lowest_addr = fold_convert (ptrdiff_type_node, first_node);
13451 : }
13452 512 : tree attach_decl = OMP_CLAUSE_DECL (attach);
13453 512 : attach_decl = fold_convert (ptrdiff_type_node, attach_decl);
13454 512 : OMP_CLAUSE_SIZE (attach)
13455 512 : = fold_build2 (MINUS_EXPR, ptrdiff_type_node, lowest_addr,
13456 : attach_decl);
13457 :
13458 : /* Remove GOMP_MAP_ATTACH node from after struct node. */
13459 512 : OMP_CLAUSE_CHAIN (struct_node) = OMP_CLAUSE_CHAIN (attach);
13460 : /* ...and re-insert it at the end of our clause list. */
13461 512 : *tail = attach;
13462 512 : OMP_CLAUSE_CHAIN (attach) = NULL_TREE;
13463 512 : tail = &OMP_CLAUSE_CHAIN (attach);
13464 : }
13465 :
13466 15605 : error_out:
13467 18102 : if (struct_map_to_clause)
13468 2497 : delete struct_map_to_clause;
13469 :
13470 18102 : return success;
13471 18102 : }
13472 :
13473 : struct instantiate_mapper_info
13474 : {
13475 : tree *mapper_clauses_p;
13476 : struct gimplify_omp_ctx *omp_ctx;
13477 : gimple_seq *pre_p;
13478 : };
13479 :
13480 : /* Helper function for omp_instantiate_mapper. */
13481 :
13482 : static tree
13483 1592 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
13484 : {
13485 1592 : copy_body_data *id = (copy_body_data *) data;
13486 :
13487 1592 : if (DECL_P (*tp))
13488 : {
13489 724 : tree replacement = remap_decl (*tp, id);
13490 724 : if (*tp != replacement)
13491 : {
13492 369 : *tp = unshare_expr (replacement);
13493 369 : *walk_subtrees = 0;
13494 : }
13495 : }
13496 :
13497 1592 : return NULL_TREE;
13498 : }
13499 :
13500 : /* A copy_decl implementation (for use with tree-inline.cc functions) that
13501 : only transform decls or SSA names that are part of a map we already
13502 : prepared. */
13503 :
13504 : static tree
13505 126 : omp_mapper_copy_decl (tree var, copy_body_data *cb)
13506 : {
13507 126 : tree *repl = cb->decl_map->get (var);
13508 :
13509 126 : if (repl)
13510 0 : return *repl;
13511 :
13512 126 : return var;
13513 : }
13514 :
13515 : static tree *
13516 90 : omp_instantiate_mapper (gimple_seq *pre_p,
13517 : hash_map<omp_name_type<tree>, tree> *implicit_mappers,
13518 : tree mapperfn, tree expr, enum gomp_map_kind outer_kind,
13519 : tree *mapper_clauses_p)
13520 : {
13521 90 : tree mapper_name = NULL_TREE;
13522 90 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapperfn);
13523 90 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
13524 :
13525 90 : tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
13526 90 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
13527 :
13528 : /* The "extraction map" is used to map the mapper variable in the "declare
13529 : mapper" directive, and also any temporary variables that have been created
13530 : as part of expanding the mapper function's body (which are expanded as a
13531 : "bind" expression in the pre_p sequence). */
13532 90 : hash_map<tree, tree> extraction_map;
13533 :
13534 90 : extraction_map.put (dummy_var, expr);
13535 90 : extraction_map.put (expr, expr);
13536 :
13537 : /* This copy_body_data is only used to remap the decls in the
13538 : OMP_DECLARE_MAPPER tree node expansion itself. All relevant decls should
13539 : already be in the current function. */
13540 90 : copy_body_data id;
13541 90 : memset (&id, 0, sizeof (id));
13542 90 : id.src_fn = current_function_decl;
13543 90 : id.dst_fn = current_function_decl;
13544 90 : id.src_cfun = cfun;
13545 90 : id.decl_map = &extraction_map;
13546 90 : id.copy_decl = omp_mapper_copy_decl;
13547 90 : id.transform_call_graph_edges = CB_CGE_DUPLICATE; // ???
13548 90 : id.transform_new_cfg = true; // ???
13549 :
13550 282 : for (; clause; clause = OMP_CLAUSE_CHAIN (clause))
13551 : {
13552 192 : enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (clause);
13553 192 : tree *nested_mapper_p = NULL;
13554 :
13555 192 : if (map_kind == GOMP_MAP_PUSH_MAPPER_NAME)
13556 : {
13557 0 : mapper_name = OMP_CLAUSE_DECL (clause);
13558 25 : continue;
13559 : }
13560 192 : else if (map_kind == GOMP_MAP_POP_MAPPER_NAME)
13561 : {
13562 0 : mapper_name = NULL_TREE;
13563 0 : continue;
13564 : }
13565 :
13566 192 : if (OMP_CLAUSE_HAS_ITERATORS (clause))
13567 : {
13568 2 : sorry_at (OMP_CLAUSE_LOCATION (clause),
13569 : "user-defined mapper that uses a %<map%> clause "
13570 : "with %<iterator%>");
13571 2 : continue;
13572 : }
13573 :
13574 190 : tree decl = OMP_CLAUSE_DECL (clause);
13575 190 : tree unshared, type;
13576 190 : bool nonunit_array_with_mapper = false;
13577 :
13578 190 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
13579 : {
13580 62 : location_t loc = OMP_CLAUSE_LOCATION (clause);
13581 62 : tree tmp = lang_hooks.decls.omp_map_array_section (loc, decl);
13582 62 : if (tmp == decl)
13583 : {
13584 48 : unshared = unshare_expr (clause);
13585 48 : nonunit_array_with_mapper = true;
13586 48 : type = TREE_TYPE (TREE_TYPE (decl));
13587 : }
13588 : else
13589 : {
13590 14 : unshared = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
13591 14 : OMP_CLAUSE_CODE (clause));
13592 14 : OMP_CLAUSE_DECL (unshared) = tmp;
13593 14 : OMP_CLAUSE_SIZE (unshared)
13594 28 : = DECL_P (tmp) ? DECL_SIZE_UNIT (tmp)
13595 14 : : TYPE_SIZE_UNIT (TREE_TYPE (tmp));
13596 14 : type = TREE_TYPE (tmp);
13597 : }
13598 : }
13599 : else
13600 : {
13601 128 : unshared = unshare_expr (clause);
13602 128 : type = TREE_TYPE (decl);
13603 : }
13604 :
13605 190 : walk_tree (&unshared, remap_mapper_decl_1, &id, NULL);
13606 :
13607 190 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
13608 28 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
13609 :
13610 190 : decl = OMP_CLAUSE_DECL (unshared);
13611 190 : type = TYPE_MAIN_VARIANT (type);
13612 :
13613 190 : nested_mapper_p = implicit_mappers->get ({ mapper_name, type });
13614 :
13615 190 : if (nested_mapper_p && *nested_mapper_p != mapperfn)
13616 : {
13617 23 : if (nonunit_array_with_mapper)
13618 : {
13619 8 : sorry ("user-defined mapper with non-unit length array section");
13620 8 : continue;
13621 : }
13622 :
13623 15 : if (map_kind == GOMP_MAP_UNSET)
13624 0 : map_kind = outer_kind;
13625 :
13626 15 : mapper_clauses_p
13627 15 : = omp_instantiate_mapper (pre_p, implicit_mappers,
13628 : *nested_mapper_p, decl, map_kind,
13629 : mapper_clauses_p);
13630 15 : continue;
13631 : }
13632 :
13633 167 : *mapper_clauses_p = unshared;
13634 167 : mapper_clauses_p = &OMP_CLAUSE_CHAIN (unshared);
13635 : }
13636 :
13637 90 : return mapper_clauses_p;
13638 90 : }
13639 :
13640 : static int
13641 138694 : omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
13642 : {
13643 138694 : tree decl = (tree) n->key;
13644 138694 : instantiate_mapper_info *im_info = (instantiate_mapper_info *) data;
13645 138694 : gimplify_omp_ctx *ctx = im_info->omp_ctx;
13646 138694 : tree *mapper_p = NULL;
13647 138694 : tree type = TREE_TYPE (decl);
13648 138694 : bool ref_p = false;
13649 138694 : unsigned flags = n->value;
13650 :
13651 138694 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
13652 : return 0;
13653 23771 : if ((flags & GOVD_SEEN) == 0)
13654 : return 0;
13655 : /* If we already have clauses pertaining to a struct variable, then we don't
13656 : want to implicitly invoke a user-defined mapper. */
13657 20237 : if ((flags & GOVD_EXPLICIT) != 0 && AGGREGATE_TYPE_P (TREE_TYPE (decl)))
13658 : return 0;
13659 :
13660 20237 : if (TREE_CODE (type) == REFERENCE_TYPE)
13661 : {
13662 905 : ref_p = true;
13663 905 : type = TREE_TYPE (type);
13664 : }
13665 :
13666 20237 : type = TYPE_MAIN_VARIANT (type);
13667 :
13668 20237 : if (DECL_P (decl) && type && AGGREGATE_TYPE_P (type))
13669 : {
13670 5319 : gcc_assert (ctx);
13671 5319 : mapper_p = ctx->implicit_mappers->get ({ NULL_TREE, type });
13672 : }
13673 :
13674 5319 : if (mapper_p)
13675 : {
13676 : /* If we have a reference, map the pointed-to object rather than the
13677 : reference itself. */
13678 75 : if (ref_p)
13679 2 : decl = build_fold_indirect_ref (decl);
13680 :
13681 75 : im_info->mapper_clauses_p
13682 75 : = omp_instantiate_mapper (im_info->pre_p, ctx->implicit_mappers,
13683 : *mapper_p, decl, GOMP_MAP_TOFROM,
13684 : im_info->mapper_clauses_p);
13685 : /* Make sure we don't map the same variable implicitly in
13686 : gimplify_adjust_omp_clauses_1 also. */
13687 75 : n->value |= GOVD_EXPLICIT;
13688 : }
13689 :
13690 : return 0;
13691 : }
13692 :
13693 : /* Scan the OMP clauses in *LIST_P, installing mappings into a new
13694 : and previous omp contexts. */
13695 :
13696 : static void
13697 131616 : gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
13698 : enum omp_region_type region_type,
13699 : enum tree_code code,
13700 : gimple_seq *loops_seq_p = NULL)
13701 : {
13702 131616 : using namespace omp_addr_tokenizer;
13703 131616 : struct gimplify_omp_ctx *ctx, *outer_ctx;
13704 131616 : tree c;
13705 131616 : tree *orig_list_p = list_p;
13706 131616 : int handled_depend_iterators = -1;
13707 131616 : int nowait = -1;
13708 :
13709 131616 : ctx = new_omp_context (region_type);
13710 131616 : ctx->code = code;
13711 131616 : outer_ctx = ctx->outer_context;
13712 131616 : if (code == OMP_TARGET)
13713 : {
13714 13567 : if (!lang_GNU_Fortran ())
13715 11189 : ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
13716 13567 : ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE;
13717 27134 : ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran ()
13718 13567 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
13719 : }
13720 131616 : if (!lang_GNU_Fortran ())
13721 100235 : switch (code)
13722 : {
13723 18692 : case OMP_TARGET:
13724 18692 : case OMP_TARGET_DATA:
13725 18692 : case OMP_TARGET_ENTER_DATA:
13726 18692 : case OMP_TARGET_EXIT_DATA:
13727 18692 : case OACC_DECLARE:
13728 18692 : case OACC_HOST_DATA:
13729 18692 : case OACC_PARALLEL:
13730 18692 : case OACC_KERNELS:
13731 18692 : ctx->target_firstprivatize_array_bases = true;
13732 : default:
13733 : break;
13734 : }
13735 :
13736 131616 : vec<omp_mapping_group> *groups = NULL;
13737 131616 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
13738 131616 : unsigned grpnum = 0;
13739 131616 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
13740 :
13741 131616 : if (code == OMP_TARGET
13742 131616 : || code == OMP_TARGET_DATA
13743 131616 : || code == OMP_TARGET_ENTER_DATA
13744 : || code == OMP_TARGET_EXIT_DATA
13745 : || code == OACC_DATA
13746 : || code == OACC_KERNELS
13747 : || code == OACC_PARALLEL
13748 : || code == OACC_SERIAL
13749 : || code == OACC_ENTER_DATA
13750 : || code == OACC_EXIT_DATA
13751 : || code == OACC_UPDATE
13752 : || code == OACC_DECLARE)
13753 : {
13754 34001 : if (!(region_type & ORT_ACC))
13755 17489 : *list_p = omp_remove_duplicate_maps (*list_p, false);
13756 34001 : groups = omp_gather_mapping_groups (list_p);
13757 :
13758 34001 : if (groups)
13759 18303 : grpmap = omp_index_mapping_groups (groups);
13760 : }
13761 :
13762 338183 : while ((c = *list_p) != NULL)
13763 : {
13764 206567 : bool remove = false;
13765 206567 : bool notice_outer = true;
13766 206567 : bool map_descriptor;
13767 206567 : const char *check_non_private = NULL;
13768 206567 : unsigned int flags;
13769 206567 : tree decl;
13770 206567 : auto_vec<omp_addr_token *, 10> addr_tokens;
13771 206567 : tree op = NULL_TREE;
13772 206567 : location_t loc = OMP_CLAUSE_LOCATION (c);
13773 :
13774 244157 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
13775 : {
13776 : grp_start_p = NULL;
13777 : grp_end = NULL_TREE;
13778 : }
13779 :
13780 206567 : if (code == OMP_TARGET
13781 : || code == OMP_TARGET_DATA
13782 : || code == OMP_TARGET_ENTER_DATA
13783 173648 : || code == OMP_TARGET_EXIT_DATA)
13784 : /* Do some target-specific type checks for map operands. */
13785 35352 : switch (OMP_CLAUSE_CODE (c))
13786 : {
13787 25831 : case OMP_CLAUSE_MAP:
13788 25831 : op = OMP_CLAUSE_OPERAND (c, 0);
13789 25831 : verify_type_context (loc, TCTX_OMP_MAP, TREE_TYPE (op));
13790 25831 : break;
13791 186 : case OMP_CLAUSE_PRIVATE:
13792 186 : op = OMP_CLAUSE_OPERAND (c, 0);
13793 186 : verify_type_context (loc, TCTX_OMP_PRIVATE, TREE_TYPE (op));
13794 186 : break;
13795 1376 : case OMP_CLAUSE_FIRSTPRIVATE:
13796 1376 : op = OMP_CLAUSE_OPERAND (c, 0);
13797 1376 : verify_type_context (loc, TCTX_OMP_FIRSTPRIVATE, TREE_TYPE (op));
13798 1376 : break;
13799 2923 : case OMP_CLAUSE_IS_DEVICE_PTR:
13800 2923 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13801 2923 : case OMP_CLAUSE_USE_DEVICE_PTR:
13802 2923 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13803 2923 : op = OMP_CLAUSE_OPERAND (c, 0);
13804 2923 : verify_type_context (loc, TCTX_OMP_DEVICE_ADDR, TREE_TYPE (op));
13805 2923 : break;
13806 : default:
13807 : break;
13808 : }
13809 :
13810 206567 : switch (OMP_CLAUSE_CODE (c))
13811 : {
13812 12255 : case OMP_CLAUSE_PRIVATE:
13813 12255 : flags = GOVD_PRIVATE | GOVD_EXPLICIT;
13814 12255 : if (lang_hooks.decls.omp_private_outer_ref (OMP_CLAUSE_DECL (c)))
13815 : {
13816 167 : flags |= GOVD_PRIVATE_OUTER_REF;
13817 167 : OMP_CLAUSE_PRIVATE_OUTER_REF (c) = 1;
13818 : }
13819 : else
13820 : notice_outer = false;
13821 12255 : goto do_add;
13822 5536 : case OMP_CLAUSE_SHARED:
13823 5536 : flags = GOVD_SHARED | GOVD_EXPLICIT;
13824 5536 : goto do_add;
13825 8059 : case OMP_CLAUSE_FIRSTPRIVATE:
13826 8059 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
13827 8059 : check_non_private = "firstprivate";
13828 8059 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13829 : {
13830 380 : gcc_assert (code == OMP_TARGET);
13831 : flags |= GOVD_FIRSTPRIVATE_IMPLICIT;
13832 : }
13833 8059 : goto do_add;
13834 7338 : case OMP_CLAUSE_LASTPRIVATE:
13835 7338 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13836 496 : switch (code)
13837 : {
13838 25 : case OMP_DISTRIBUTE:
13839 25 : error_at (OMP_CLAUSE_LOCATION (c),
13840 : "conditional %<lastprivate%> clause on "
13841 : "%qs construct", "distribute");
13842 25 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13843 25 : break;
13844 13 : case OMP_TASKLOOP:
13845 13 : error_at (OMP_CLAUSE_LOCATION (c),
13846 : "conditional %<lastprivate%> clause on "
13847 : "%qs construct", "taskloop");
13848 13 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13849 13 : break;
13850 : default:
13851 : break;
13852 : }
13853 7338 : flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
13854 7338 : if (code != OMP_LOOP)
13855 6987 : check_non_private = "lastprivate";
13856 7338 : decl = OMP_CLAUSE_DECL (c);
13857 7338 : if (error_operand_p (decl))
13858 0 : goto do_add;
13859 7338 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
13860 7338 : && !lang_hooks.decls.omp_scalar_p (decl, true))
13861 : {
13862 5 : error_at (OMP_CLAUSE_LOCATION (c),
13863 : "non-scalar variable %qD in conditional "
13864 : "%<lastprivate%> clause", decl);
13865 5 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13866 : }
13867 7338 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13868 453 : flags |= GOVD_LASTPRIVATE_CONDITIONAL;
13869 7338 : omp_lastprivate_for_combined_outer_constructs (outer_ctx, decl,
13870 : false);
13871 7338 : goto do_add;
13872 15384 : case OMP_CLAUSE_REDUCTION:
13873 15384 : if (OMP_CLAUSE_REDUCTION_TASK (c))
13874 : {
13875 603 : if (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
13876 : {
13877 416 : if (nowait == -1)
13878 301 : nowait = omp_find_clause (*list_p,
13879 301 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
13880 416 : if (nowait
13881 15 : && (outer_ctx == NULL
13882 0 : || outer_ctx->region_type != ORT_COMBINED_PARALLEL))
13883 : {
13884 15 : error_at (OMP_CLAUSE_LOCATION (c),
13885 : "%<task%> reduction modifier on a construct "
13886 : "with a %<nowait%> clause");
13887 15 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13888 : }
13889 : }
13890 187 : else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL)
13891 : {
13892 40 : error_at (OMP_CLAUSE_LOCATION (c),
13893 : "invalid %<task%> reduction modifier on construct "
13894 : "other than %<parallel%>, %qs, %<sections%> or "
13895 20 : "%<scope%>", lang_GNU_Fortran () ? "do" : "for");
13896 20 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13897 : }
13898 : }
13899 15384 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
13900 851 : switch (code)
13901 : {
13902 4 : case OMP_SECTIONS:
13903 4 : error_at (OMP_CLAUSE_LOCATION (c),
13904 : "%<inscan%> %<reduction%> clause on "
13905 : "%qs construct", "sections");
13906 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13907 4 : break;
13908 4 : case OMP_PARALLEL:
13909 4 : error_at (OMP_CLAUSE_LOCATION (c),
13910 : "%<inscan%> %<reduction%> clause on "
13911 : "%qs construct", "parallel");
13912 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13913 4 : break;
13914 4 : case OMP_TEAMS:
13915 4 : error_at (OMP_CLAUSE_LOCATION (c),
13916 : "%<inscan%> %<reduction%> clause on "
13917 : "%qs construct", "teams");
13918 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13919 4 : break;
13920 4 : case OMP_TASKLOOP:
13921 4 : error_at (OMP_CLAUSE_LOCATION (c),
13922 : "%<inscan%> %<reduction%> clause on "
13923 : "%qs construct", "taskloop");
13924 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13925 4 : break;
13926 4 : case OMP_SCOPE:
13927 4 : error_at (OMP_CLAUSE_LOCATION (c),
13928 : "%<inscan%> %<reduction%> clause on "
13929 : "%qs construct", "scope");
13930 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13931 4 : break;
13932 : default:
13933 : break;
13934 : }
13935 : /* FALLTHRU */
13936 17988 : case OMP_CLAUSE_IN_REDUCTION:
13937 17988 : case OMP_CLAUSE_TASK_REDUCTION:
13938 17988 : flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
13939 : /* OpenACC permits reductions on private variables. */
13940 17988 : if (!(region_type & ORT_ACC)
13941 : /* taskgroup is actually not a worksharing region. */
13942 12469 : && code != OMP_TASKGROUP)
13943 11939 : check_non_private = omp_clause_code_name[OMP_CLAUSE_CODE (c)];
13944 17988 : decl = OMP_CLAUSE_DECL (c);
13945 17988 : if (TREE_CODE (decl) == MEM_REF)
13946 : {
13947 2614 : tree type = TREE_TYPE (decl);
13948 2614 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
13949 2614 : gimplify_ctxp->into_ssa = false;
13950 2614 : if (gimplify_expr (&TYPE_MAX_VALUE (TYPE_DOMAIN (type)), pre_p,
13951 : NULL, is_gimple_val, fb_rvalue, false)
13952 : == GS_ERROR)
13953 : {
13954 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13955 0 : remove = true;
13956 0 : break;
13957 : }
13958 2614 : gimplify_ctxp->into_ssa = saved_into_ssa;
13959 2614 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
13960 2614 : if (DECL_P (v))
13961 : {
13962 571 : omp_firstprivatize_variable (ctx, v);
13963 571 : omp_notice_variable (ctx, v, true);
13964 : }
13965 2614 : decl = TREE_OPERAND (decl, 0);
13966 2614 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
13967 : {
13968 477 : gimplify_ctxp->into_ssa = false;
13969 477 : if (gimplify_expr (&TREE_OPERAND (decl, 1), pre_p,
13970 : NULL, is_gimple_val, fb_rvalue, false)
13971 : == GS_ERROR)
13972 : {
13973 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13974 0 : remove = true;
13975 0 : break;
13976 : }
13977 477 : gimplify_ctxp->into_ssa = saved_into_ssa;
13978 477 : v = TREE_OPERAND (decl, 1);
13979 477 : if (DECL_P (v))
13980 : {
13981 477 : omp_firstprivatize_variable (ctx, v);
13982 477 : omp_notice_variable (ctx, v, true);
13983 : }
13984 477 : decl = TREE_OPERAND (decl, 0);
13985 : }
13986 2614 : if (TREE_CODE (decl) == ADDR_EXPR
13987 1220 : || TREE_CODE (decl) == INDIRECT_REF)
13988 1510 : decl = TREE_OPERAND (decl, 0);
13989 : }
13990 17988 : goto do_add_decl;
13991 2688 : case OMP_CLAUSE_LINEAR:
13992 2688 : if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
13993 : is_gimple_val, fb_rvalue) == GS_ERROR)
13994 : {
13995 : remove = true;
13996 : break;
13997 : }
13998 : else
13999 : {
14000 2688 : if (code == OMP_SIMD
14001 2688 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14002 : {
14003 1154 : struct gimplify_omp_ctx *octx = outer_ctx;
14004 1154 : if (octx
14005 741 : && octx->region_type == ORT_WORKSHARE
14006 500 : && octx->combined_loop
14007 500 : && !octx->distribute)
14008 : {
14009 492 : if (octx->outer_context
14010 430 : && (octx->outer_context->region_type
14011 : == ORT_COMBINED_PARALLEL))
14012 393 : octx = octx->outer_context->outer_context;
14013 : else
14014 : octx = octx->outer_context;
14015 : }
14016 905 : if (octx
14017 316 : && octx->region_type == ORT_WORKSHARE
14018 16 : && octx->combined_loop
14019 16 : && octx->distribute)
14020 : {
14021 16 : error_at (OMP_CLAUSE_LOCATION (c),
14022 : "%<linear%> clause for variable other than "
14023 : "loop iterator specified on construct "
14024 : "combined with %<distribute%>");
14025 16 : remove = true;
14026 16 : break;
14027 : }
14028 : }
14029 : /* For combined #pragma omp parallel for simd, need to put
14030 : lastprivate and perhaps firstprivate too on the
14031 : parallel. Similarly for #pragma omp for simd. */
14032 : struct gimplify_omp_ctx *octx = outer_ctx;
14033 : bool taskloop_seen = false;
14034 : decl = NULL_TREE;
14035 3469 : do
14036 : {
14037 3469 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14038 3469 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14039 : break;
14040 3409 : decl = OMP_CLAUSE_DECL (c);
14041 3409 : if (error_operand_p (decl))
14042 : {
14043 : decl = NULL_TREE;
14044 : break;
14045 : }
14046 3409 : flags = GOVD_SEEN;
14047 3409 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14048 1672 : flags |= GOVD_FIRSTPRIVATE;
14049 3409 : if (!OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14050 3409 : flags |= GOVD_LASTPRIVATE;
14051 3409 : if (octx
14052 2519 : && octx->region_type == ORT_WORKSHARE
14053 1220 : && octx->combined_loop)
14054 : {
14055 1214 : if (octx->outer_context
14056 1042 : && (octx->outer_context->region_type
14057 : == ORT_COMBINED_PARALLEL))
14058 : octx = octx->outer_context;
14059 480 : else if (omp_check_private (octx, decl, false))
14060 : break;
14061 : }
14062 : else if (octx
14063 1305 : && (octx->region_type & ORT_TASK) != 0
14064 307 : && octx->combined_loop)
14065 : taskloop_seen = true;
14066 : else if (octx
14067 1002 : && octx->region_type == ORT_COMBINED_PARALLEL
14068 301 : && ((ctx->region_type == ORT_WORKSHARE
14069 201 : && octx == outer_ctx)
14070 100 : || taskloop_seen))
14071 : flags = GOVD_SEEN | GOVD_SHARED;
14072 : else if (octx
14073 701 : && ((octx->region_type & ORT_COMBINED_TEAMS)
14074 : == ORT_COMBINED_TEAMS))
14075 : flags = GOVD_SEEN | GOVD_SHARED;
14076 544 : else if (octx
14077 544 : && octx->region_type == ORT_COMBINED_TARGET)
14078 : {
14079 197 : if (flags & GOVD_LASTPRIVATE)
14080 197 : flags = GOVD_SEEN | GOVD_MAP;
14081 : }
14082 : else
14083 : break;
14084 2080 : splay_tree_node on
14085 2080 : = splay_tree_lookup (octx->variables,
14086 : (splay_tree_key) decl);
14087 2080 : if (on && (on->value & GOVD_DATA_SHARE_CLASS) != 0)
14088 : {
14089 : octx = NULL;
14090 : break;
14091 : }
14092 2076 : omp_add_variable (octx, decl, flags);
14093 2076 : if (octx->outer_context == NULL)
14094 : break;
14095 : octx = octx->outer_context;
14096 : }
14097 : while (1);
14098 2672 : if (octx
14099 2672 : && decl
14100 2672 : && (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14101 735 : || !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
14102 1718 : omp_notice_variable (octx, decl, true);
14103 : }
14104 2672 : flags = GOVD_LINEAR | GOVD_EXPLICIT;
14105 2672 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14106 2672 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14107 : {
14108 : notice_outer = false;
14109 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
14110 : }
14111 2672 : goto do_add;
14112 :
14113 51416 : case OMP_CLAUSE_MAP:
14114 51416 : if (!grp_start_p)
14115 : {
14116 31210 : grp_start_p = list_p;
14117 31210 : grp_end = (*groups)[grpnum].grp_end;
14118 31210 : grpnum++;
14119 : }
14120 51416 : decl = OMP_CLAUSE_DECL (c);
14121 :
14122 51416 : if (error_operand_p (decl))
14123 : {
14124 : remove = true;
14125 : break;
14126 : }
14127 :
14128 51416 : if (!omp_parse_expr (addr_tokens, decl))
14129 : {
14130 : remove = true;
14131 : break;
14132 : }
14133 :
14134 51416 : if (remove)
14135 : break;
14136 51416 : if (DECL_P (decl) && outer_ctx && (region_type & ORT_ACC))
14137 : {
14138 : struct gimplify_omp_ctx *octx;
14139 1167 : for (octx = outer_ctx; octx; octx = octx->outer_context)
14140 : {
14141 1167 : if (octx->region_type != ORT_ACC_HOST_DATA)
14142 : break;
14143 12 : splay_tree_node n2
14144 12 : = splay_tree_lookup (octx->variables,
14145 : (splay_tree_key) decl);
14146 12 : if (n2)
14147 4 : error_at (OMP_CLAUSE_LOCATION (c), "variable %qE "
14148 : "declared in enclosing %<host_data%> region",
14149 4 : DECL_NAME (decl));
14150 : }
14151 : }
14152 :
14153 51416 : map_descriptor = false;
14154 :
14155 : /* This condition checks if we're mapping an array descriptor that
14156 : isn't inside a derived type -- these have special handling, and
14157 : are not handled as structs in omp_build_struct_sibling_lists.
14158 : See that function for further details. */
14159 51416 : if (*grp_start_p != grp_end
14160 34234 : && OMP_CLAUSE_CHAIN (*grp_start_p)
14161 85650 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
14162 : {
14163 17096 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
14164 17096 : if (omp_map_clause_descriptor_p (grp_mid)
14165 32365 : && DECL_P (OMP_CLAUSE_DECL (grp_mid)))
14166 : map_descriptor = true;
14167 : }
14168 34320 : else if (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP
14169 34320 : && (OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_RELEASE
14170 33576 : || OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_DELETE)
14171 35242 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (grp_end))
14172 : map_descriptor = true;
14173 :
14174 : /* Adding the decl for a struct access: we haven't created
14175 : GOMP_MAP_STRUCT nodes yet, so this statement needs to predict
14176 : whether they will be created in gimplify_adjust_omp_clauses.
14177 : NOTE: Technically we should probably look through DECL_VALUE_EXPR
14178 : here because something that looks like a DECL_P may actually be a
14179 : struct access, e.g. variables in a lambda closure
14180 : (__closure->__foo) or class members (this->foo). Currently in both
14181 : those cases we map the whole of the containing object (directly in
14182 : the C++ FE) though, so struct nodes are not created. */
14183 51416 : if (c == grp_end
14184 31210 : && addr_tokens[0]->type == STRUCTURE_BASE
14185 8403 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14186 59819 : && !map_descriptor)
14187 : {
14188 5599 : gcc_assert (addr_tokens[1]->type == ACCESS_METHOD);
14189 : /* If we got to this struct via a chain of pointers, maybe we
14190 : want to map it implicitly instead. */
14191 5599 : if (omp_access_chain_p (addr_tokens, 1))
14192 : break;
14193 5438 : omp_mapping_group *wholestruct;
14194 5438 : if (!(region_type & ORT_ACC)
14195 9601 : && omp_mapped_by_containing_struct (grpmap,
14196 4163 : OMP_CLAUSE_DECL (c),
14197 : &wholestruct))
14198 : break;
14199 5201 : decl = addr_tokens[1]->expr;
14200 5201 : if (splay_tree_lookup (ctx->variables, (splay_tree_key) decl))
14201 : break;
14202 : /* Standalone attach or detach clauses for a struct element
14203 : should not inhibit implicit mapping of the whole struct. */
14204 2987 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
14205 2987 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
14206 : break;
14207 2837 : flags = GOVD_MAP | GOVD_EXPLICIT;
14208 :
14209 2837 : gcc_assert (addr_tokens[1]->u.access_kind != ACCESS_DIRECT
14210 : || TREE_ADDRESSABLE (decl));
14211 2837 : goto do_add_decl;
14212 : }
14213 :
14214 45817 : if (!DECL_P (decl))
14215 : {
14216 21135 : tree d = decl, *pd;
14217 21135 : if (TREE_CODE (d) == ARRAY_REF)
14218 : {
14219 5128 : while (TREE_CODE (d) == ARRAY_REF)
14220 2621 : d = TREE_OPERAND (d, 0);
14221 2507 : if (TREE_CODE (d) == COMPONENT_REF
14222 2507 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
14223 : decl = d;
14224 : }
14225 21135 : pd = &OMP_CLAUSE_DECL (c);
14226 21135 : if (d == decl
14227 18674 : && TREE_CODE (decl) == INDIRECT_REF
14228 13946 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
14229 1070 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
14230 : == REFERENCE_TYPE)
14231 21786 : && (OMP_CLAUSE_MAP_KIND (c)
14232 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
14233 : {
14234 647 : pd = &TREE_OPERAND (decl, 0);
14235 647 : decl = TREE_OPERAND (decl, 0);
14236 : }
14237 :
14238 21135 : if (addr_tokens[0]->type == STRUCTURE_BASE
14239 11440 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14240 11439 : && addr_tokens[1]->type == ACCESS_METHOD
14241 11439 : && (addr_tokens[1]->u.access_kind == ACCESS_POINTER
14242 10941 : || (addr_tokens[1]->u.access_kind
14243 : == ACCESS_POINTER_OFFSET))
14244 21715 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)))
14245 : {
14246 0 : tree base = addr_tokens[1]->expr;
14247 0 : splay_tree_node n
14248 0 : = splay_tree_lookup (ctx->variables,
14249 : (splay_tree_key) base);
14250 0 : n->value |= GOVD_SEEN;
14251 : }
14252 :
14253 21135 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
14254 : {
14255 : /* Don't gimplify *pd fully at this point, as the base
14256 : will need to be adjusted during omp lowering. */
14257 88 : auto_vec<tree, 10> expr_stack;
14258 88 : tree *p = pd;
14259 88 : while (handled_component_p (*p)
14260 : || TREE_CODE (*p) == INDIRECT_REF
14261 : || TREE_CODE (*p) == ADDR_EXPR
14262 : || TREE_CODE (*p) == MEM_REF
14263 224 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
14264 : {
14265 136 : expr_stack.safe_push (*p);
14266 136 : p = &TREE_OPERAND (*p, 0);
14267 : }
14268 312 : for (int i = expr_stack.length () - 1; i >= 0; i--)
14269 : {
14270 136 : tree t = expr_stack[i];
14271 136 : if (TREE_CODE (t) == ARRAY_REF
14272 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14273 : {
14274 56 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14275 : {
14276 56 : tree low = unshare_expr (array_ref_low_bound (t));
14277 56 : if (!is_gimple_min_invariant (low))
14278 : {
14279 0 : TREE_OPERAND (t, 2) = low;
14280 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14281 : pre_p, NULL,
14282 : is_gimple_reg,
14283 : fb_rvalue) == GS_ERROR)
14284 56 : remove = true;
14285 : }
14286 : }
14287 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14288 : NULL, is_gimple_reg,
14289 : fb_rvalue) == GS_ERROR)
14290 56 : remove = true;
14291 56 : if (TREE_OPERAND (t, 3) == NULL_TREE)
14292 : {
14293 56 : tree elmt_size = array_ref_element_size (t);
14294 56 : if (!is_gimple_min_invariant (elmt_size))
14295 : {
14296 0 : elmt_size = unshare_expr (elmt_size);
14297 0 : tree elmt_type
14298 0 : = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t,
14299 : 0)));
14300 0 : tree factor
14301 0 : = size_int (TYPE_ALIGN_UNIT (elmt_type));
14302 0 : elmt_size
14303 0 : = size_binop (EXACT_DIV_EXPR, elmt_size,
14304 : factor);
14305 0 : TREE_OPERAND (t, 3) = elmt_size;
14306 0 : if (gimplify_expr (&TREE_OPERAND (t, 3),
14307 : pre_p, NULL,
14308 : is_gimple_reg,
14309 : fb_rvalue) == GS_ERROR)
14310 0 : remove = true;
14311 : }
14312 : }
14313 0 : else if (gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
14314 : NULL, is_gimple_reg,
14315 : fb_rvalue) == GS_ERROR)
14316 0 : remove = true;
14317 : }
14318 80 : else if (TREE_CODE (t) == COMPONENT_REF)
14319 : {
14320 0 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14321 : {
14322 0 : tree offset = component_ref_field_offset (t);
14323 0 : if (!is_gimple_min_invariant (offset))
14324 : {
14325 0 : offset = unshare_expr (offset);
14326 0 : tree field = TREE_OPERAND (t, 1);
14327 0 : tree factor
14328 0 : = size_int (DECL_OFFSET_ALIGN (field)
14329 : / BITS_PER_UNIT);
14330 0 : offset = size_binop (EXACT_DIV_EXPR, offset,
14331 : factor);
14332 0 : TREE_OPERAND (t, 2) = offset;
14333 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14334 : pre_p, NULL,
14335 : is_gimple_reg,
14336 : fb_rvalue) == GS_ERROR)
14337 0 : remove = true;
14338 : }
14339 : }
14340 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14341 : NULL, is_gimple_reg,
14342 : fb_rvalue) == GS_ERROR)
14343 0 : remove = true;
14344 : }
14345 : }
14346 224 : for (; expr_stack.length () > 0; )
14347 : {
14348 136 : tree t = expr_stack.pop ();
14349 :
14350 136 : if (TREE_CODE (t) == ARRAY_REF
14351 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14352 : {
14353 56 : if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))
14354 56 : && gimplify_expr (&TREE_OPERAND (t, 1), pre_p,
14355 : NULL, is_gimple_val,
14356 : fb_rvalue) == GS_ERROR)
14357 : remove = true;
14358 : }
14359 : }
14360 88 : }
14361 : break;
14362 : }
14363 :
14364 24682 : if ((code == OMP_TARGET
14365 : || code == OMP_TARGET_DATA
14366 : || code == OMP_TARGET_ENTER_DATA
14367 14229 : || code == OMP_TARGET_EXIT_DATA)
14368 25324 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14369 : {
14370 : /* If we have attach/detach but the decl we have is a pointer to
14371 : pointer, we're probably mapping the "base level" array
14372 : implicitly. Make sure we don't add the decl as if we mapped
14373 : it explicitly. That is,
14374 :
14375 : int **arr;
14376 : [...]
14377 : #pragma omp target map(arr[a][b:c])
14378 :
14379 : should *not* map "arr" explicitly. That way we get a
14380 : zero-length "alloc" mapping for it, and assuming it's been
14381 : mapped by some previous directive, etc., things work as they
14382 : should. */
14383 :
14384 217 : tree basetype = TREE_TYPE (addr_tokens[0]->expr);
14385 :
14386 217 : if (TREE_CODE (basetype) == REFERENCE_TYPE)
14387 34 : basetype = TREE_TYPE (basetype);
14388 :
14389 217 : if (code == OMP_TARGET
14390 54 : && addr_tokens[0]->type == ARRAY_BASE
14391 54 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14392 54 : && TREE_CODE (basetype) == POINTER_TYPE
14393 271 : && TREE_CODE (TREE_TYPE (basetype)) == POINTER_TYPE)
14394 : break;
14395 : }
14396 :
14397 24660 : flags = GOVD_MAP | GOVD_EXPLICIT;
14398 24660 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
14399 24523 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM
14400 24015 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TO
14401 48645 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TOFROM)
14402 : flags |= GOVD_MAP_ALWAYS_TO;
14403 :
14404 24660 : goto do_add;
14405 :
14406 510 : case OMP_CLAUSE_AFFINITY:
14407 510 : gimplify_omp_affinity (list_p, pre_p);
14408 510 : remove = true;
14409 510 : break;
14410 8 : case OMP_CLAUSE_DOACROSS:
14411 8 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
14412 : {
14413 4 : tree deps = OMP_CLAUSE_DECL (c);
14414 8 : while (deps && TREE_CODE (deps) == TREE_LIST)
14415 : {
14416 4 : if (TREE_CODE (TREE_PURPOSE (deps)) == TRUNC_DIV_EXPR
14417 4 : && DECL_P (TREE_OPERAND (TREE_PURPOSE (deps), 1)))
14418 0 : gimplify_expr (&TREE_OPERAND (TREE_PURPOSE (deps), 1),
14419 : pre_p, NULL, is_gimple_val, fb_rvalue);
14420 4 : deps = TREE_CHAIN (deps);
14421 : }
14422 : }
14423 : else
14424 4 : gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
14425 : == OMP_CLAUSE_DOACROSS_SOURCE);
14426 : break;
14427 2207 : case OMP_CLAUSE_DEPEND:
14428 2207 : if (handled_depend_iterators == -1)
14429 1905 : handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
14430 2207 : if (handled_depend_iterators)
14431 : {
14432 348 : if (handled_depend_iterators == 2)
14433 0 : remove = true;
14434 : break;
14435 : }
14436 1859 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
14437 : {
14438 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
14439 : NULL, is_gimple_val, fb_rvalue);
14440 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
14441 : }
14442 1859 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
14443 : {
14444 : remove = true;
14445 : break;
14446 : }
14447 1859 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
14448 : {
14449 1828 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
14450 1828 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
14451 : is_gimple_val, fb_rvalue) == GS_ERROR)
14452 : {
14453 : remove = true;
14454 : break;
14455 : }
14456 : }
14457 1859 : if (code == OMP_TASK)
14458 1401 : ctx->has_depend = true;
14459 : break;
14460 :
14461 8383 : case OMP_CLAUSE_TO:
14462 8383 : case OMP_CLAUSE_FROM:
14463 8383 : case OMP_CLAUSE__CACHE_:
14464 8383 : decl = OMP_CLAUSE_DECL (c);
14465 8383 : if (error_operand_p (decl))
14466 : {
14467 : remove = true;
14468 : break;
14469 : }
14470 8383 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14471 7682 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
14472 800 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
14473 8383 : gimple_seq *seq_p;
14474 8383 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
14475 8383 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
14476 : is_gimple_val, fb_rvalue) == GS_ERROR)
14477 : {
14478 0 : remove = true;
14479 0 : exit_omp_iterator_loop_context (c);
14480 0 : break;
14481 : }
14482 8383 : if (!DECL_P (decl))
14483 : {
14484 2180 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
14485 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
14486 0 : remove = true;
14487 2180 : exit_omp_iterator_loop_context (c);
14488 2180 : break;
14489 : }
14490 6203 : exit_omp_iterator_loop_context (c);
14491 6203 : goto do_notice;
14492 :
14493 135 : case OMP_CLAUSE__MAPPER_BINDING_:
14494 135 : {
14495 135 : tree name = OMP_CLAUSE__MAPPER_BINDING__ID (c);
14496 135 : tree var = OMP_CLAUSE__MAPPER_BINDING__DECL (c);
14497 135 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (var));
14498 135 : tree fndecl = OMP_CLAUSE__MAPPER_BINDING__MAPPER (c);
14499 135 : ctx->implicit_mappers->put ({ name, type }, fndecl);
14500 135 : remove = true;
14501 135 : break;
14502 : }
14503 :
14504 2118 : case OMP_CLAUSE_USE_DEVICE_PTR:
14505 2118 : case OMP_CLAUSE_USE_DEVICE_ADDR:
14506 2118 : flags = GOVD_EXPLICIT;
14507 2118 : goto do_add;
14508 :
14509 558 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14510 558 : decl = OMP_CLAUSE_DECL (c);
14511 558 : while (TREE_CODE (decl) == INDIRECT_REF
14512 607 : || TREE_CODE (decl) == ARRAY_REF)
14513 49 : decl = TREE_OPERAND (decl, 0);
14514 558 : flags = GOVD_EXPLICIT;
14515 558 : goto do_add_decl;
14516 :
14517 500 : case OMP_CLAUSE_IS_DEVICE_PTR:
14518 500 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
14519 500 : goto do_add;
14520 :
14521 63328 : do_add:
14522 63328 : decl = OMP_CLAUSE_DECL (c);
14523 84711 : do_add_decl:
14524 84711 : if (error_operand_p (decl))
14525 : {
14526 : remove = true;
14527 : break;
14528 : }
14529 84703 : if (DECL_NAME (decl) == NULL_TREE && (flags & GOVD_SHARED) == 0)
14530 : {
14531 1755 : tree t = omp_member_access_dummy_var (decl);
14532 1755 : if (t)
14533 : {
14534 668 : tree v = DECL_VALUE_EXPR (decl);
14535 668 : DECL_NAME (decl) = DECL_NAME (TREE_OPERAND (v, 1));
14536 668 : if (outer_ctx)
14537 140 : omp_notice_variable (outer_ctx, t, true);
14538 : }
14539 : }
14540 84703 : if (code == OACC_DATA
14541 2402 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14542 87105 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14543 307 : flags |= GOVD_MAP_0LEN_ARRAY;
14544 84703 : omp_add_variable (ctx, decl, flags);
14545 84703 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14546 69319 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
14547 67245 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
14548 87307 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
14549 : {
14550 2106 : struct gimplify_omp_ctx *pctx
14551 2166 : = code == OMP_TARGET ? outer_ctx : ctx;
14552 2166 : if (pctx)
14553 2136 : omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
14554 : GOVD_LOCAL | GOVD_SEEN);
14555 2136 : if (pctx
14556 2136 : && OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
14557 632 : && walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
14558 : find_decl_expr,
14559 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14560 : NULL) == NULL_TREE)
14561 208 : omp_add_variable (pctx,
14562 208 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14563 : GOVD_LOCAL | GOVD_SEEN);
14564 2166 : gimplify_omp_ctxp = pctx;
14565 2166 : push_gimplify_context ();
14566 :
14567 2166 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
14568 2166 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
14569 :
14570 2166 : gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
14571 2166 : &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
14572 2166 : pop_gimplify_context
14573 2166 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)));
14574 2166 : push_gimplify_context ();
14575 4332 : gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
14576 2166 : &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
14577 2166 : pop_gimplify_context
14578 2166 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
14579 2166 : OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
14580 2166 : OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
14581 :
14582 2166 : gimplify_omp_ctxp = outer_ctx;
14583 : }
14584 82537 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
14585 82537 : && OMP_CLAUSE_LASTPRIVATE_STMT (c))
14586 : {
14587 303 : gimplify_omp_ctxp = ctx;
14588 303 : push_gimplify_context ();
14589 303 : if (TREE_CODE (OMP_CLAUSE_LASTPRIVATE_STMT (c)) != BIND_EXPR)
14590 : {
14591 303 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14592 : NULL, NULL);
14593 303 : TREE_SIDE_EFFECTS (bind) = 1;
14594 303 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LASTPRIVATE_STMT (c);
14595 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = bind;
14596 : }
14597 606 : gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c),
14598 303 : &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
14599 303 : pop_gimplify_context
14600 303 : (gimple_seq_first_stmt (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)));
14601 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL_TREE;
14602 :
14603 303 : gimplify_omp_ctxp = outer_ctx;
14604 : }
14605 82234 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14606 82234 : && OMP_CLAUSE_LINEAR_STMT (c))
14607 : {
14608 60 : gimplify_omp_ctxp = ctx;
14609 60 : push_gimplify_context ();
14610 60 : if (TREE_CODE (OMP_CLAUSE_LINEAR_STMT (c)) != BIND_EXPR)
14611 : {
14612 60 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14613 : NULL, NULL);
14614 60 : TREE_SIDE_EFFECTS (bind) = 1;
14615 60 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LINEAR_STMT (c);
14616 60 : OMP_CLAUSE_LINEAR_STMT (c) = bind;
14617 : }
14618 120 : gimplify_and_add (OMP_CLAUSE_LINEAR_STMT (c),
14619 60 : &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
14620 60 : pop_gimplify_context
14621 60 : (gimple_seq_first_stmt (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)));
14622 60 : OMP_CLAUSE_LINEAR_STMT (c) = NULL_TREE;
14623 :
14624 60 : gimplify_omp_ctxp = outer_ctx;
14625 : }
14626 84703 : if (notice_outer)
14627 72555 : goto do_notice;
14628 : break;
14629 :
14630 910 : case OMP_CLAUSE_COPYIN:
14631 910 : case OMP_CLAUSE_COPYPRIVATE:
14632 910 : decl = OMP_CLAUSE_DECL (c);
14633 910 : if (error_operand_p (decl))
14634 : {
14635 : remove = true;
14636 : break;
14637 : }
14638 910 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
14639 : && !remove
14640 910 : && !omp_check_private (ctx, decl, true))
14641 : {
14642 35 : remove = true;
14643 35 : if (is_global_var (decl))
14644 : {
14645 30 : if (DECL_THREAD_LOCAL_P (decl))
14646 : remove = false;
14647 10 : else if (DECL_HAS_VALUE_EXPR_P (decl))
14648 : {
14649 2 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
14650 :
14651 2 : if (value
14652 2 : && DECL_P (value)
14653 4 : && DECL_THREAD_LOCAL_P (value))
14654 : remove = false;
14655 : }
14656 : }
14657 : if (remove)
14658 13 : error_at (OMP_CLAUSE_LOCATION (c),
14659 : "copyprivate variable %qE is not threadprivate"
14660 13 : " or private in outer context", DECL_NAME (decl));
14661 : }
14662 79668 : do_notice:
14663 79668 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14664 64284 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
14665 56225 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
14666 30781 : && outer_ctx
14667 17632 : && ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
14668 16293 : || (region_type == ORT_WORKSHARE
14669 3909 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14670 1111 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
14671 928 : || code == OMP_LOOP)))
14672 81621 : && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
14673 857 : || (code == OMP_LOOP
14674 138 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14675 138 : && ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
14676 : == ORT_COMBINED_TEAMS))))
14677 : {
14678 1217 : splay_tree_node on
14679 1217 : = splay_tree_lookup (outer_ctx->variables,
14680 : (splay_tree_key)decl);
14681 1217 : if (on == NULL || (on->value & GOVD_DATA_SHARE_CLASS) == 0)
14682 : {
14683 899 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14684 713 : && TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14685 1011 : && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
14686 56 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
14687 0 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
14688 : == POINTER_TYPE))))
14689 56 : omp_firstprivatize_variable (outer_ctx, decl);
14690 : else
14691 : {
14692 843 : omp_add_variable (outer_ctx, decl,
14693 : GOVD_SEEN | GOVD_SHARED);
14694 843 : if (outer_ctx->outer_context)
14695 235 : omp_notice_variable (outer_ctx->outer_context, decl,
14696 : true);
14697 : }
14698 : }
14699 : }
14700 79060 : if (outer_ctx)
14701 29677 : omp_notice_variable (outer_ctx, decl, true);
14702 79668 : if (check_non_private
14703 26985 : && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
14704 4804 : && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
14705 1689 : || decl == OMP_CLAUSE_DECL (c)
14706 224 : || (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14707 224 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14708 : == ADDR_EXPR
14709 103 : || (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14710 : == POINTER_PLUS_EXPR
14711 22 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND
14712 : (OMP_CLAUSE_DECL (c), 0), 0))
14713 : == ADDR_EXPR)))))
14714 84384 : && omp_check_private (ctx, decl, false))
14715 : {
14716 58 : error ("%s variable %qE is private in outer context",
14717 29 : check_non_private, DECL_NAME (decl));
14718 29 : remove = true;
14719 : }
14720 : break;
14721 :
14722 190 : case OMP_CLAUSE_DETACH:
14723 190 : flags = GOVD_FIRSTPRIVATE | GOVD_SEEN;
14724 190 : goto do_add;
14725 :
14726 4114 : case OMP_CLAUSE_IF:
14727 4114 : if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK
14728 4114 : && OMP_CLAUSE_IF_MODIFIER (c) != code)
14729 : {
14730 : const char *p[2];
14731 168 : for (int i = 0; i < 2; i++)
14732 112 : switch (i ? OMP_CLAUSE_IF_MODIFIER (c) : code)
14733 : {
14734 8 : case VOID_CST: p[i] = "cancel"; break;
14735 24 : case OMP_PARALLEL: p[i] = "parallel"; break;
14736 4 : case OMP_SIMD: p[i] = "simd"; break;
14737 12 : case OMP_TASK: p[i] = "task"; break;
14738 12 : case OMP_TASKLOOP: p[i] = "taskloop"; break;
14739 8 : case OMP_TARGET_DATA: p[i] = "target data"; break;
14740 12 : case OMP_TARGET: p[i] = "target"; break;
14741 12 : case OMP_TARGET_UPDATE: p[i] = "target update"; break;
14742 8 : case OMP_TARGET_ENTER_DATA:
14743 8 : p[i] = "target enter data"; break;
14744 12 : case OMP_TARGET_EXIT_DATA: p[i] = "target exit data"; break;
14745 0 : default: gcc_unreachable ();
14746 : }
14747 56 : error_at (OMP_CLAUSE_LOCATION (c),
14748 : "expected %qs %<if%> clause modifier rather than %qs",
14749 : p[0], p[1]);
14750 56 : remove = true;
14751 : }
14752 : /* Fall through. */
14753 :
14754 4824 : case OMP_CLAUSE_SELF:
14755 4824 : case OMP_CLAUSE_FINAL:
14756 4824 : OMP_CLAUSE_OPERAND (c, 0)
14757 9648 : = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
14758 : /* Fall through. */
14759 :
14760 5753 : case OMP_CLAUSE_NUM_TEAMS:
14761 5753 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
14762 929 : && OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14763 5977 : && !is_gimple_min_invariant (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14764 : {
14765 194 : if (error_operand_p (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14766 : {
14767 : remove = true;
14768 : break;
14769 : }
14770 194 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14771 388 : = get_initialized_tmp_var (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c),
14772 : pre_p, NULL, true);
14773 : }
14774 : /* Fall through. */
14775 :
14776 21960 : case OMP_CLAUSE_SCHEDULE:
14777 21960 : case OMP_CLAUSE_NUM_THREADS:
14778 21960 : case OMP_CLAUSE_THREAD_LIMIT:
14779 21960 : case OMP_CLAUSE_DIST_SCHEDULE:
14780 21960 : case OMP_CLAUSE_DEVICE:
14781 21960 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14782 21960 : && OMP_CLAUSE_DEVICE_ANCESTOR (c))
14783 : {
14784 125 : if (code != OMP_TARGET)
14785 : {
14786 20 : error_at (OMP_CLAUSE_LOCATION (c),
14787 : "%<device%> clause with %<ancestor%> is only "
14788 : "allowed on %<target%> construct");
14789 20 : remove = true;
14790 20 : break;
14791 : }
14792 :
14793 105 : tree clauses = *orig_list_p;
14794 330 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
14795 236 : if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE
14796 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE
14797 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE
14798 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP
14799 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP
14800 : )
14801 : {
14802 11 : error_at (OMP_CLAUSE_LOCATION (c),
14803 : "with %<ancestor%>, only the %<device%>, "
14804 : "%<firstprivate%>, %<private%>, %<defaultmap%>, "
14805 : "and %<map%> clauses may appear on the "
14806 : "construct");
14807 11 : remove = true;
14808 11 : break;
14809 : }
14810 : }
14811 21835 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14812 21835 : && code == OMP_DISPATCH)
14813 : {
14814 272 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
14815 272 : gimplify_ctxp->into_ssa = false;
14816 272 : if (gimplify_expr (&OMP_CLAUSE_DEVICE_ID (c), pre_p, NULL,
14817 : is_gimple_val, fb_rvalue)
14818 : == GS_ERROR)
14819 : remove = true;
14820 272 : else if (DECL_P (OMP_CLAUSE_DEVICE_ID (c)))
14821 55 : omp_add_variable (ctx, OMP_CLAUSE_DEVICE_ID (c),
14822 : GOVD_SHARED | GOVD_SEEN);
14823 272 : gimplify_ctxp->into_ssa = saved_into_ssa;
14824 272 : break;
14825 : }
14826 : /* Fall through. */
14827 :
14828 31414 : case OMP_CLAUSE_PRIORITY:
14829 31414 : case OMP_CLAUSE_GRAINSIZE:
14830 31414 : case OMP_CLAUSE_NUM_TASKS:
14831 31414 : case OMP_CLAUSE_FILTER:
14832 31414 : case OMP_CLAUSE_HINT:
14833 31414 : case OMP_CLAUSE_ASYNC:
14834 31414 : case OMP_CLAUSE_WAIT:
14835 31414 : case OMP_CLAUSE_NUM_GANGS:
14836 31414 : case OMP_CLAUSE_NUM_WORKERS:
14837 31414 : case OMP_CLAUSE_VECTOR_LENGTH:
14838 31414 : case OMP_CLAUSE_WORKER:
14839 31414 : case OMP_CLAUSE_VECTOR:
14840 31414 : if (OMP_CLAUSE_OPERAND (c, 0)
14841 31414 : && TREE_CODE (OMP_CLAUSE_OPERAND (c, 0)) == TREE_LIST)
14842 : {
14843 2604 : for (tree t = OMP_CLAUSE_OPERAND (c, 0); t; t = TREE_CHAIN (t))
14844 1346 : if (!is_gimple_min_invariant (TREE_VALUE (t)))
14845 : {
14846 280 : if (error_operand_p (TREE_VALUE (t)))
14847 : {
14848 : remove = true;
14849 : break;
14850 : }
14851 560 : TREE_VALUE (t)
14852 280 : = get_initialized_tmp_var (TREE_VALUE (t), pre_p,
14853 : NULL, true);
14854 : }
14855 : }
14856 30156 : else if (OMP_CLAUSE_OPERAND (c, 0)
14857 30156 : && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0)))
14858 : {
14859 7503 : if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0)))
14860 : {
14861 : remove = true;
14862 : break;
14863 : }
14864 : /* All these clauses care about value, not a particular decl,
14865 : so try to force it into a SSA_NAME or fresh temporary. */
14866 7496 : OMP_CLAUSE_OPERAND (c, 0)
14867 14992 : = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0),
14868 : pre_p, NULL, true);
14869 : }
14870 : break;
14871 :
14872 2332 : case OMP_CLAUSE_GANG:
14873 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
14874 : is_gimple_val, fb_rvalue) == GS_ERROR)
14875 0 : remove = true;
14876 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL,
14877 : is_gimple_val, fb_rvalue) == GS_ERROR)
14878 0 : remove = true;
14879 : break;
14880 :
14881 13147 : case OMP_CLAUSE_NOWAIT:
14882 13147 : nowait = 1;
14883 13147 : break;
14884 :
14885 116 : case OMP_CLAUSE_USES_ALLOCATORS:
14886 116 : if (TREE_CODE (OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c))
14887 : != INTEGER_CST)
14888 : {
14889 112 : decl = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
14890 112 : omp_add_variable (ctx, decl,
14891 : GOVD_SEEN | GOVD_USES_ALLOCATORS_ALLOCATOR);
14892 : }
14893 : else
14894 : remove = true;
14895 : break;
14896 :
14897 : case OMP_CLAUSE_ORDERED:
14898 : case OMP_CLAUSE_UNTIED:
14899 : case OMP_CLAUSE_COLLAPSE:
14900 : case OMP_CLAUSE_TILE:
14901 : case OMP_CLAUSE_AUTO:
14902 : case OMP_CLAUSE_SEQ:
14903 : case OMP_CLAUSE_INDEPENDENT:
14904 : case OMP_CLAUSE_MERGEABLE:
14905 : case OMP_CLAUSE_MESSAGE:
14906 : case OMP_CLAUSE_PROC_BIND:
14907 : case OMP_CLAUSE_SAFELEN:
14908 : case OMP_CLAUSE_NOGROUP:
14909 : case OMP_CLAUSE_THREADS:
14910 : case OMP_CLAUSE_SIMD:
14911 : case OMP_CLAUSE_BIND:
14912 : case OMP_CLAUSE_IF_PRESENT:
14913 : case OMP_CLAUSE_FINALIZE:
14914 : case OMP_CLAUSE_INTEROP:
14915 : case OMP_CLAUSE_INIT:
14916 : case OMP_CLAUSE_USE:
14917 : case OMP_CLAUSE_DESTROY:
14918 : case OMP_CLAUSE_DEVICE_TYPE:
14919 : break;
14920 :
14921 672 : case OMP_CLAUSE_SIMDLEN:
14922 672 : if (OMP_CLAUSE_SIMDLEN_TYPE (c))
14923 : {
14924 30 : remove = true;
14925 30 : sorry_at (OMP_CLAUSE_LOCATION (c),
14926 : "%<simdlen%> clause with %<scaled%> modifier");
14927 : }
14928 : break;
14929 :
14930 56 : case OMP_CLAUSE_DYN_GROUPPRIVATE:
14931 56 : remove = true;
14932 56 : sorry_at (OMP_CLAUSE_LOCATION (c),"%<dyn_groupprivate%> clause");
14933 56 : break;
14934 :
14935 3976 : case OMP_CLAUSE_ORDER:
14936 3976 : ctx->order_concurrent = true;
14937 3976 : break;
14938 :
14939 1017 : case OMP_CLAUSE_DEFAULTMAP:
14940 1017 : enum gimplify_defaultmap_kind gdmkmin, gdmkmax;
14941 1017 : switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c))
14942 : {
14943 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
14944 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
14945 : gdmkmin = GDMK_SCALAR;
14946 : gdmkmax = GDMK_POINTER;
14947 : break;
14948 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
14949 : gdmkmin = GDMK_SCALAR;
14950 : gdmkmax = GDMK_SCALAR_TARGET;
14951 : break;
14952 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
14953 : gdmkmin = gdmkmax = GDMK_AGGREGATE;
14954 : break;
14955 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE:
14956 : gdmkmin = gdmkmax = GDMK_ALLOCATABLE;
14957 : break;
14958 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
14959 : gdmkmin = gdmkmax = GDMK_POINTER;
14960 : break;
14961 0 : default:
14962 0 : gcc_unreachable ();
14963 : }
14964 4513 : for (int gdmk = gdmkmin; gdmk <= gdmkmax; gdmk++)
14965 3496 : switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (c))
14966 : {
14967 91 : case OMP_CLAUSE_DEFAULTMAP_ALLOC:
14968 91 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_ALLOC_ONLY;
14969 91 : break;
14970 96 : case OMP_CLAUSE_DEFAULTMAP_TO:
14971 96 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_TO_ONLY;
14972 96 : break;
14973 28 : case OMP_CLAUSE_DEFAULTMAP_FROM:
14974 28 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FROM_ONLY;
14975 28 : break;
14976 671 : case OMP_CLAUSE_DEFAULTMAP_TOFROM:
14977 671 : ctx->defaultmap[gdmk] = GOVD_MAP;
14978 671 : break;
14979 380 : case OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE:
14980 380 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14981 380 : break;
14982 2129 : case OMP_CLAUSE_DEFAULTMAP_NONE:
14983 2129 : ctx->defaultmap[gdmk] = 0;
14984 2129 : break;
14985 45 : case OMP_CLAUSE_DEFAULTMAP_PRESENT:
14986 45 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
14987 45 : break;
14988 56 : case OMP_CLAUSE_DEFAULTMAP_DEFAULT:
14989 56 : switch (gdmk)
14990 : {
14991 11 : case GDMK_SCALAR:
14992 11 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14993 11 : break;
14994 11 : case GDMK_SCALAR_TARGET:
14995 11 : ctx->defaultmap[gdmk] = (lang_GNU_Fortran ()
14996 11 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
14997 11 : break;
14998 14 : case GDMK_AGGREGATE:
14999 14 : case GDMK_ALLOCATABLE:
15000 14 : ctx->defaultmap[gdmk] = GOVD_MAP;
15001 14 : break;
15002 20 : case GDMK_POINTER:
15003 20 : ctx->defaultmap[gdmk] = GOVD_MAP;
15004 20 : if (!lang_GNU_Fortran ())
15005 12 : ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY;
15006 : break;
15007 : default:
15008 : gcc_unreachable ();
15009 : }
15010 : break;
15011 0 : default:
15012 0 : gcc_unreachable ();
15013 : }
15014 : break;
15015 :
15016 824 : case OMP_CLAUSE_ALIGNED:
15017 824 : decl = OMP_CLAUSE_DECL (c);
15018 824 : if (error_operand_p (decl))
15019 : {
15020 : remove = true;
15021 : break;
15022 : }
15023 824 : if (gimplify_expr (&OMP_CLAUSE_ALIGNED_ALIGNMENT (c), pre_p, NULL,
15024 : is_gimple_val, fb_rvalue) == GS_ERROR)
15025 : {
15026 : remove = true;
15027 : break;
15028 : }
15029 824 : if (!is_global_var (decl)
15030 824 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
15031 592 : omp_add_variable (ctx, decl, GOVD_ALIGNED);
15032 : break;
15033 :
15034 489 : case OMP_CLAUSE_NONTEMPORAL:
15035 489 : decl = OMP_CLAUSE_DECL (c);
15036 489 : if (error_operand_p (decl))
15037 : {
15038 : remove = true;
15039 : break;
15040 : }
15041 489 : omp_add_variable (ctx, decl, GOVD_NONTEMPORAL);
15042 489 : break;
15043 :
15044 3691 : case OMP_CLAUSE_ALLOCATE:
15045 3691 : decl = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
15046 3691 : if (decl
15047 1722 : && TREE_CODE (decl) == INTEGER_CST
15048 3720 : && wi::eq_p (wi::to_widest (decl), GOMP_OMP_PREDEF_ALLOC_THREAD)
15049 3720 : && (code == OMP_TARGET || code == OMP_TASK || code == OMP_TASKLOOP))
15050 35 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
15051 : "allocator with access trait set to %<thread%> "
15052 : "results in undefined behavior for %qs directive",
15053 : code == OMP_TARGET ? "target"
15054 : : (code == OMP_TASK
15055 15 : ? "task" : "taskloop"));
15056 3691 : decl = OMP_CLAUSE_DECL (c);
15057 3691 : if (error_operand_p (decl))
15058 : {
15059 : remove = true;
15060 : break;
15061 : }
15062 3691 : if ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0
15063 3679 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
15064 5413 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST)
15065 : {
15066 521 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
15067 521 : tree clauses = NULL_TREE;
15068 :
15069 : /* Get clause list of the nearest enclosing target construct. */
15070 521 : if (ctx->code == OMP_TARGET)
15071 14 : clauses = *orig_list_p;
15072 : else
15073 : {
15074 507 : struct gimplify_omp_ctx *tctx = ctx->outer_context;
15075 826 : while (tctx && tctx->code != OMP_TARGET)
15076 319 : tctx = tctx->outer_context;
15077 507 : if (tctx)
15078 18 : clauses = tctx->clauses;
15079 : }
15080 :
15081 32 : if (clauses)
15082 : {
15083 30 : tree uc;
15084 30 : if (TREE_CODE (allocator) == MEM_REF
15085 30 : || TREE_CODE (allocator) == INDIRECT_REF)
15086 0 : allocator = TREE_OPERAND (allocator, 0);
15087 132 : for (uc = clauses; uc; uc = OMP_CLAUSE_CHAIN (uc))
15088 123 : if (OMP_CLAUSE_CODE (uc) == OMP_CLAUSE_USES_ALLOCATORS)
15089 : {
15090 29 : tree uc_allocator
15091 29 : = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (uc);
15092 29 : if (operand_equal_p (allocator, uc_allocator))
15093 : break;
15094 : }
15095 30 : if (uc == NULL_TREE)
15096 : {
15097 9 : error_at (OMP_CLAUSE_LOCATION (c), "allocator %qE "
15098 : "requires %<uses_allocators(%E)%> clause in "
15099 : "target region", allocator, allocator);
15100 9 : remove = true;
15101 9 : break;
15102 : }
15103 : }
15104 : }
15105 3682 : if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL,
15106 : is_gimple_val, fb_rvalue) == GS_ERROR)
15107 : {
15108 : remove = true;
15109 : break;
15110 : }
15111 3682 : else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
15112 3682 : || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
15113 : == INTEGER_CST))
15114 : ;
15115 512 : else if (code == OMP_TASKLOOP
15116 512 : || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
15117 66 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
15118 132 : = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
15119 : pre_p, NULL, false);
15120 : break;
15121 :
15122 4365 : case OMP_CLAUSE_DEFAULT:
15123 4365 : ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
15124 4365 : break;
15125 :
15126 652 : case OMP_CLAUSE_INCLUSIVE:
15127 652 : case OMP_CLAUSE_EXCLUSIVE:
15128 652 : decl = OMP_CLAUSE_DECL (c);
15129 652 : {
15130 652 : splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
15131 : (splay_tree_key) decl);
15132 652 : if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
15133 : {
15134 5 : error_at (OMP_CLAUSE_LOCATION (c),
15135 : "%qD specified in %qs clause but not in %<inscan%> "
15136 : "%<reduction%> clause on the containing construct",
15137 5 : decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
15138 5 : remove = true;
15139 : }
15140 : else
15141 : {
15142 647 : n->value |= GOVD_REDUCTION_INSCAN;
15143 647 : if (outer_ctx->region_type == ORT_SIMD
15144 528 : && outer_ctx->outer_context
15145 115 : && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
15146 : {
15147 115 : n = splay_tree_lookup (outer_ctx->outer_context->variables,
15148 : (splay_tree_key) decl);
15149 115 : if (n && (n->value & GOVD_REDUCTION) != 0)
15150 115 : n->value |= GOVD_REDUCTION_INSCAN;
15151 : }
15152 : }
15153 : }
15154 : break;
15155 :
15156 103 : case OMP_CLAUSE_NOVARIANTS:
15157 103 : OMP_CLAUSE_NOVARIANTS_EXPR (c)
15158 103 : = gimple_boolify (OMP_CLAUSE_NOVARIANTS_EXPR (c));
15159 103 : break;
15160 115 : case OMP_CLAUSE_NOCONTEXT:
15161 115 : OMP_CLAUSE_NOCONTEXT_EXPR (c)
15162 115 : = gimple_boolify (OMP_CLAUSE_NOCONTEXT_EXPR (c));
15163 115 : break;
15164 0 : case OMP_CLAUSE_NOHOST:
15165 0 : default:
15166 0 : gcc_unreachable ();
15167 : }
15168 :
15169 206567 : if (code == OACC_DATA
15170 5123 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15171 211378 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15172 4504 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15173 : remove = true;
15174 206260 : if (remove)
15175 1216 : *list_p = OMP_CLAUSE_CHAIN (c);
15176 : else
15177 205351 : list_p = &OMP_CLAUSE_CHAIN (c);
15178 206567 : }
15179 :
15180 131616 : if (groups)
15181 : {
15182 36606 : delete grpmap;
15183 18303 : delete groups;
15184 : }
15185 :
15186 131616 : ctx->clauses = *orig_list_p;
15187 131616 : gimplify_omp_ctxp = ctx;
15188 131616 : }
15189 :
15190 : /* Return true if DECL is a candidate for shared to firstprivate
15191 : optimization. We only consider non-addressable scalars, not
15192 : too big, and not references. */
15193 :
15194 : static bool
15195 406187 : omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
15196 : {
15197 406187 : if (TREE_ADDRESSABLE (decl))
15198 : return false;
15199 357011 : tree type = TREE_TYPE (decl);
15200 357011 : if (!is_gimple_reg_type (type)
15201 332192 : || TREE_CODE (type) == REFERENCE_TYPE
15202 684894 : || TREE_ADDRESSABLE (type))
15203 : return false;
15204 : /* Don't optimize too large decls, as each thread/task will have
15205 : its own. */
15206 327883 : HOST_WIDE_INT len = int_size_in_bytes (type);
15207 327883 : if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
15208 : return false;
15209 327866 : if (omp_privatize_by_reference (decl))
15210 1324 : return false;
15211 : return true;
15212 : }
15213 :
15214 : /* Helper function of omp_find_stores_op and gimplify_adjust_omp_clauses*.
15215 : For omp_shared_to_firstprivate_optimizable_decl_p decl mark it as
15216 : GOVD_WRITTEN in outer contexts. */
15217 :
15218 : static void
15219 304938 : omp_mark_stores (struct gimplify_omp_ctx *ctx, tree decl)
15220 : {
15221 467274 : for (; ctx; ctx = ctx->outer_context)
15222 : {
15223 450178 : splay_tree_node n = splay_tree_lookup (ctx->variables,
15224 : (splay_tree_key) decl);
15225 450178 : if (n == NULL)
15226 158755 : continue;
15227 291423 : else if (n->value & GOVD_SHARED)
15228 : {
15229 9171 : n->value |= GOVD_WRITTEN;
15230 9171 : return;
15231 : }
15232 282252 : else if (n->value & GOVD_DATA_SHARE_CLASS)
15233 : return;
15234 : }
15235 : }
15236 :
15237 : /* Helper callback for walk_gimple_seq to discover possible stores
15238 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15239 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15240 : for those. */
15241 :
15242 : static tree
15243 1131017 : omp_find_stores_op (tree *tp, int *walk_subtrees, void *data)
15244 : {
15245 1131017 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15246 :
15247 1131017 : *walk_subtrees = 0;
15248 1131017 : if (!wi->is_lhs)
15249 : return NULL_TREE;
15250 :
15251 322767 : tree op = *tp;
15252 401707 : do
15253 : {
15254 401707 : if (handled_component_p (op))
15255 78940 : op = TREE_OPERAND (op, 0);
15256 322767 : else if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
15257 322767 : && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
15258 0 : op = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
15259 : else
15260 : break;
15261 : }
15262 : while (1);
15263 322767 : if (!DECL_P (op) || !omp_shared_to_firstprivate_optimizable_decl_p (op))
15264 : return NULL_TREE;
15265 :
15266 264488 : omp_mark_stores (gimplify_omp_ctxp, op);
15267 264488 : return NULL_TREE;
15268 : }
15269 :
15270 : /* Helper callback for walk_gimple_seq to discover possible stores
15271 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15272 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15273 : for those. */
15274 :
15275 : static tree
15276 629103 : omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
15277 : bool *handled_ops_p,
15278 : struct walk_stmt_info *wi)
15279 : {
15280 629103 : gimple *stmt = gsi_stmt (*gsi_p);
15281 629103 : switch (gimple_code (stmt))
15282 : {
15283 : /* Don't recurse on OpenMP constructs for which
15284 : gimplify_adjust_omp_clauses already handled the bodies,
15285 : except handle gimple_omp_for_pre_body. */
15286 26823 : case GIMPLE_OMP_FOR:
15287 26823 : *handled_ops_p = true;
15288 26823 : if (gimple_omp_for_pre_body (stmt))
15289 1782 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15290 : omp_find_stores_stmt, omp_find_stores_op, wi);
15291 : break;
15292 8630 : case GIMPLE_OMP_PARALLEL:
15293 8630 : case GIMPLE_OMP_TASK:
15294 8630 : case GIMPLE_OMP_SECTIONS:
15295 8630 : case GIMPLE_OMP_SINGLE:
15296 8630 : case GIMPLE_OMP_SCOPE:
15297 8630 : case GIMPLE_OMP_TARGET:
15298 8630 : case GIMPLE_OMP_TEAMS:
15299 8630 : case GIMPLE_OMP_CRITICAL:
15300 8630 : *handled_ops_p = true;
15301 8630 : break;
15302 : default:
15303 : break;
15304 : }
15305 629103 : return NULL_TREE;
15306 : }
15307 :
15308 : struct gimplify_adjust_omp_clauses_data
15309 : {
15310 : tree *list_p;
15311 : gimple_seq *pre_p;
15312 : };
15313 :
15314 : /* For all variables that were not actually used within the context,
15315 : remove PRIVATE, SHARED, and FIRSTPRIVATE clauses. */
15316 :
15317 : static int
15318 678852 : gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
15319 : {
15320 678852 : tree *list_p = ((struct gimplify_adjust_omp_clauses_data *) data)->list_p;
15321 678852 : gimple_seq *pre_p
15322 : = ((struct gimplify_adjust_omp_clauses_data *) data)->pre_p;
15323 678852 : tree decl = (tree) n->key;
15324 678852 : unsigned flags = n->value;
15325 678852 : enum omp_clause_code code;
15326 678852 : tree clause;
15327 678852 : bool private_debug;
15328 :
15329 678852 : if (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
15330 132957 : && (flags & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
15331 : flags = GOVD_SHARED | GOVD_SEEN | GOVD_WRITTEN;
15332 678727 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
15333 : return 0;
15334 179161 : if ((flags & GOVD_SEEN) == 0)
15335 : return 0;
15336 158060 : if (flags & GOVD_DEBUG_PRIVATE)
15337 : {
15338 260 : gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_SHARED);
15339 : private_debug = true;
15340 : }
15341 157800 : else if (flags & GOVD_MAP)
15342 : private_debug = false;
15343 : else
15344 139599 : private_debug
15345 139599 : = lang_hooks.decls.omp_private_debug_clause (decl,
15346 139599 : !!(flags & GOVD_SHARED));
15347 139599 : if (private_debug)
15348 : code = OMP_CLAUSE_PRIVATE;
15349 157678 : else if (flags & GOVD_MAP)
15350 : {
15351 18201 : code = OMP_CLAUSE_MAP;
15352 18201 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15353 18201 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15354 : {
15355 2 : error ("%<_Atomic%> %qD in implicit %<map%> clause", decl);
15356 2 : return 0;
15357 : }
15358 18199 : if (VAR_P (decl)
15359 16257 : && DECL_IN_CONSTANT_POOL (decl)
15360 18200 : && !lookup_attribute ("omp declare target",
15361 1 : DECL_ATTRIBUTES (decl)))
15362 : {
15363 1 : tree id = get_identifier ("omp declare target");
15364 1 : DECL_ATTRIBUTES (decl)
15365 1 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
15366 1 : varpool_node *node = varpool_node::get (decl);
15367 1 : if (node)
15368 : {
15369 1 : node->offloadable = 1;
15370 1 : if (ENABLE_OFFLOADING)
15371 : g->have_offload = true;
15372 : }
15373 : }
15374 : }
15375 139477 : else if (flags & GOVD_SHARED)
15376 : {
15377 49193 : if (is_global_var (decl))
15378 : {
15379 16144 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15380 25331 : while (ctx != NULL)
15381 : {
15382 17604 : splay_tree_node on
15383 17604 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15384 17604 : if (on && (on->value & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
15385 : | GOVD_PRIVATE | GOVD_REDUCTION
15386 : | GOVD_LINEAR | GOVD_MAP)) != 0)
15387 : break;
15388 9187 : ctx = ctx->outer_context;
15389 : }
15390 16144 : if (ctx == NULL)
15391 : return 0;
15392 : }
15393 41466 : code = OMP_CLAUSE_SHARED;
15394 : /* Don't optimize shared into firstprivate for read-only vars
15395 : on tasks with depend clause, we shouldn't try to copy them
15396 : until the dependencies are satisfied. */
15397 41466 : if (gimplify_omp_ctxp->has_depend)
15398 350 : flags |= GOVD_WRITTEN;
15399 : }
15400 90284 : else if (flags & GOVD_PRIVATE)
15401 : code = OMP_CLAUSE_PRIVATE;
15402 31650 : else if (flags & GOVD_FIRSTPRIVATE)
15403 : {
15404 22132 : code = OMP_CLAUSE_FIRSTPRIVATE;
15405 22132 : if ((gimplify_omp_ctxp->region_type & ORT_TARGET)
15406 14037 : && (gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15407 32488 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15408 : {
15409 1 : error ("%<_Atomic%> %qD in implicit %<firstprivate%> clause on "
15410 : "%<target%> construct", decl);
15411 1 : return 0;
15412 : }
15413 : }
15414 9518 : else if (flags & GOVD_LASTPRIVATE)
15415 : code = OMP_CLAUSE_LASTPRIVATE;
15416 353 : else if (flags & (GOVD_ALIGNED | GOVD_NONTEMPORAL))
15417 : return 0;
15418 230 : else if (flags & GOVD_CONDTEMP)
15419 : {
15420 118 : code = OMP_CLAUSE__CONDTEMP_;
15421 118 : gimple_add_tmp_var (decl);
15422 : }
15423 112 : else if (flags & GOVD_USES_ALLOCATORS_ALLOCATOR)
15424 : return 0;
15425 : else
15426 0 : gcc_unreachable ();
15427 :
15428 140930 : if (((flags & GOVD_LASTPRIVATE)
15429 140240 : || (code == OMP_CLAUSE_SHARED && (flags & GOVD_WRITTEN)))
15430 156197 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15431 15253 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15432 :
15433 150095 : tree chain = *list_p;
15434 150095 : clause = build_omp_clause (input_location, code);
15435 150095 : OMP_CLAUSE_DECL (clause) = decl;
15436 150095 : OMP_CLAUSE_CHAIN (clause) = chain;
15437 150095 : if (private_debug)
15438 382 : OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
15439 149713 : else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
15440 6 : OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
15441 149707 : else if (code == OMP_CLAUSE_SHARED
15442 41466 : && (flags & GOVD_WRITTEN) == 0
15443 185071 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15444 21078 : OMP_CLAUSE_SHARED_READONLY (clause) = 1;
15445 128629 : else if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_EXPLICIT) == 0)
15446 22131 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clause) = 1;
15447 106498 : else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
15448 : {
15449 630 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
15450 630 : OMP_CLAUSE_DECL (nc) = decl;
15451 630 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
15452 630 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
15453 15 : OMP_CLAUSE_DECL (clause)
15454 30 : = build_fold_indirect_ref_loc (input_location, decl);
15455 630 : OMP_CLAUSE_DECL (clause)
15456 630 : = build2 (MEM_REF, char_type_node, OMP_CLAUSE_DECL (clause),
15457 : build_int_cst (build_pointer_type (char_type_node), 0));
15458 630 : OMP_CLAUSE_SIZE (clause) = size_zero_node;
15459 630 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15460 630 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
15461 630 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
15462 630 : tree dtype = TREE_TYPE (decl);
15463 630 : if (TREE_CODE (dtype) == REFERENCE_TYPE)
15464 15 : dtype = TREE_TYPE (dtype);
15465 : /* FIRSTPRIVATE_POINTER doesn't work well if we have a
15466 : multiply-indirected pointer. If we have a reference to a pointer to
15467 : a pointer, it's possible that this should really be
15468 : GOMP_MAP_FIRSTPRIVATE_REFERENCE -- but that also doesn't work at the
15469 : moment, so stick with this. (See PR113279 and testcases
15470 : baseptrs-{4,6}.C:ref2ptrptr_offset_decl_member_slice). */
15471 630 : if (TREE_CODE (dtype) == POINTER_TYPE
15472 630 : && TREE_CODE (TREE_TYPE (dtype)) == POINTER_TYPE)
15473 19 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15474 : else
15475 611 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15476 630 : OMP_CLAUSE_CHAIN (nc) = chain;
15477 630 : OMP_CLAUSE_CHAIN (clause) = nc;
15478 630 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15479 630 : gimplify_omp_ctxp = ctx->outer_context;
15480 630 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0),
15481 : pre_p, NULL, is_gimple_val, fb_rvalue);
15482 630 : gimplify_omp_ctxp = ctx;
15483 630 : }
15484 17569 : else if (code == OMP_CLAUSE_MAP)
15485 : {
15486 17569 : int kind;
15487 : /* Not all combinations of these GOVD_MAP flags are actually valid. */
15488 17569 : switch (flags & (GOVD_MAP_TO_ONLY
15489 : | GOVD_MAP_FORCE
15490 : | GOVD_MAP_FORCE_PRESENT
15491 : | GOVD_MAP_ALLOC_ONLY
15492 : | GOVD_MAP_FROM_ONLY))
15493 : {
15494 : case 0:
15495 : kind = GOMP_MAP_TOFROM;
15496 : break;
15497 1042 : case GOVD_MAP_FORCE:
15498 1042 : kind = GOMP_MAP_TOFROM | GOMP_MAP_FLAG_FORCE;
15499 1042 : break;
15500 1015 : case GOVD_MAP_TO_ONLY:
15501 1015 : kind = GOMP_MAP_TO;
15502 1015 : break;
15503 16 : case GOVD_MAP_FROM_ONLY:
15504 16 : kind = GOMP_MAP_FROM;
15505 16 : break;
15506 37 : case GOVD_MAP_ALLOC_ONLY:
15507 37 : kind = GOMP_MAP_ALLOC;
15508 37 : break;
15509 3 : case GOVD_MAP_TO_ONLY | GOVD_MAP_FORCE:
15510 3 : kind = GOMP_MAP_TO | GOMP_MAP_FLAG_FORCE;
15511 3 : break;
15512 : case GOVD_MAP_FORCE_PRESENT:
15513 326 : kind = GOMP_MAP_FORCE_PRESENT;
15514 : break;
15515 : case GOVD_MAP_FORCE_PRESENT | GOVD_MAP_ALLOC_ONLY:
15516 326 : kind = GOMP_MAP_FORCE_PRESENT;
15517 : break;
15518 0 : default:
15519 0 : gcc_unreachable ();
15520 : }
15521 17569 : OMP_CLAUSE_SET_MAP_KIND (clause, kind);
15522 : /* Setting of the implicit flag for the runtime is currently disabled for
15523 : OpenACC. */
15524 17569 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
15525 10035 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1;
15526 17569 : if (DECL_SIZE (decl)
15527 17569 : && !poly_int_tree_p (DECL_SIZE (decl)))
15528 : {
15529 535 : tree decl2 = DECL_VALUE_EXPR (decl);
15530 535 : gcc_assert (INDIRECT_REF_P (decl2));
15531 535 : decl2 = TREE_OPERAND (decl2, 0);
15532 535 : gcc_assert (DECL_P (decl2));
15533 535 : tree mem = build_simple_mem_ref (decl2);
15534 535 : OMP_CLAUSE_DECL (clause) = mem;
15535 535 : OMP_CLAUSE_SIZE (clause) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
15536 535 : if (gimplify_omp_ctxp->outer_context)
15537 : {
15538 446 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15539 446 : omp_notice_variable (ctx, decl2, true);
15540 446 : omp_notice_variable (ctx, OMP_CLAUSE_SIZE (clause), true);
15541 : }
15542 535 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15543 : OMP_CLAUSE_MAP);
15544 535 : OMP_CLAUSE_DECL (nc) = decl;
15545 535 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15546 535 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases)
15547 535 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15548 : else
15549 0 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15550 535 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15551 535 : OMP_CLAUSE_CHAIN (clause) = nc;
15552 : }
15553 17034 : else if (gimplify_omp_ctxp->target_firstprivatize_array_bases
15554 17034 : && omp_privatize_by_reference (decl))
15555 : {
15556 28 : OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl);
15557 28 : OMP_CLAUSE_SIZE (clause)
15558 28 : = unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))));
15559 28 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15560 28 : gimplify_omp_ctxp = ctx->outer_context;
15561 28 : gimplify_expr (&OMP_CLAUSE_SIZE (clause),
15562 : pre_p, NULL, is_gimple_val, fb_rvalue);
15563 28 : gimplify_omp_ctxp = ctx;
15564 28 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15565 : OMP_CLAUSE_MAP);
15566 28 : OMP_CLAUSE_DECL (nc) = decl;
15567 28 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15568 28 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
15569 28 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15570 28 : OMP_CLAUSE_CHAIN (clause) = nc;
15571 : }
15572 : else
15573 17006 : OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
15574 : }
15575 150095 : if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
15576 : {
15577 690 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
15578 690 : OMP_CLAUSE_DECL (nc) = decl;
15579 690 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
15580 690 : OMP_CLAUSE_CHAIN (nc) = chain;
15581 690 : OMP_CLAUSE_CHAIN (clause) = nc;
15582 690 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15583 690 : gimplify_omp_ctxp = ctx->outer_context;
15584 690 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
15585 690 : (ctx->region_type & ORT_ACC) != 0);
15586 690 : gimplify_omp_ctxp = ctx;
15587 : }
15588 150095 : *list_p = clause;
15589 150095 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15590 150095 : gimplify_omp_ctxp = ctx->outer_context;
15591 : /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
15592 : in simd. Those are only added for the local vars inside of simd body
15593 : and they don't need to be e.g. default constructible. */
15594 150095 : if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
15595 142045 : lang_hooks.decls.omp_finish_clause (clause, pre_p,
15596 142045 : (ctx->region_type & ORT_ACC) != 0);
15597 150095 : if (gimplify_omp_ctxp)
15598 184427 : for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
15599 93626 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
15600 93626 : && DECL_P (OMP_CLAUSE_SIZE (clause)))
15601 1241 : omp_notice_variable (gimplify_omp_ctxp, OMP_CLAUSE_SIZE (clause),
15602 : true);
15603 150095 : gimplify_omp_ctxp = ctx;
15604 150095 : return 0;
15605 : }
15606 :
15607 : static void
15608 130152 : gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
15609 : enum tree_code code,
15610 : gimple_seq *loops_seq_p = NULL)
15611 : {
15612 130152 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15613 130152 : tree *orig_list_p = list_p;
15614 130152 : tree c, decl;
15615 130152 : bool has_inscan_reductions = false;
15616 :
15617 130152 : if (body)
15618 : {
15619 : struct gimplify_omp_ctx *octx;
15620 226288 : for (octx = ctx; octx; octx = octx->outer_context)
15621 174750 : if ((octx->region_type & (ORT_PARALLEL | ORT_TASK | ORT_TEAMS)) != 0)
15622 : break;
15623 112412 : if (octx)
15624 : {
15625 60874 : struct walk_stmt_info wi;
15626 60874 : memset (&wi, 0, sizeof (wi));
15627 60874 : walk_gimple_seq (body, omp_find_stores_stmt,
15628 : omp_find_stores_op, &wi);
15629 : }
15630 : }
15631 :
15632 130152 : if (ctx->add_safelen1)
15633 : {
15634 : /* If there are VLAs in the body of simd loop, prevent
15635 : vectorization. */
15636 2 : gcc_assert (ctx->region_type == ORT_SIMD);
15637 2 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
15638 2 : OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node;
15639 2 : OMP_CLAUSE_CHAIN (c) = *list_p;
15640 2 : *list_p = c;
15641 2 : list_p = &OMP_CLAUSE_CHAIN (c);
15642 : }
15643 :
15644 130152 : if (ctx->region_type == ORT_WORKSHARE
15645 39991 : && ctx->outer_context
15646 28044 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
15647 : {
15648 25038 : for (c = ctx->outer_context->clauses; c; c = OMP_CLAUSE_CHAIN (c))
15649 12641 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15650 12641 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
15651 : {
15652 125 : decl = OMP_CLAUSE_DECL (c);
15653 125 : splay_tree_node n
15654 125 : = splay_tree_lookup (ctx->outer_context->variables,
15655 : (splay_tree_key) decl);
15656 125 : gcc_checking_assert (!splay_tree_lookup (ctx->variables,
15657 : (splay_tree_key) decl));
15658 125 : omp_add_variable (ctx, decl, n->value);
15659 125 : tree c2 = copy_node (c);
15660 125 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15661 125 : *list_p = c2;
15662 125 : if ((n->value & GOVD_FIRSTPRIVATE) == 0)
15663 103 : continue;
15664 22 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
15665 : OMP_CLAUSE_FIRSTPRIVATE);
15666 22 : OMP_CLAUSE_DECL (c2) = decl;
15667 22 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15668 22 : *list_p = c2;
15669 : }
15670 : }
15671 :
15672 130152 : if (code == OMP_TARGET
15673 130152 : || code == OMP_TARGET_DATA
15674 130152 : || code == OMP_TARGET_ENTER_DATA
15675 113708 : || code == OMP_TARGET_EXIT_DATA)
15676 : {
15677 17235 : tree mapper_clauses = NULL_TREE;
15678 17235 : instantiate_mapper_info im_info;
15679 :
15680 17235 : im_info.mapper_clauses_p = &mapper_clauses;
15681 17235 : im_info.omp_ctx = ctx;
15682 17235 : im_info.pre_p = pre_p;
15683 :
15684 17235 : splay_tree_foreach (ctx->variables,
15685 : omp_instantiate_implicit_mappers,
15686 : (void *) &im_info);
15687 :
15688 17235 : if (mapper_clauses)
15689 : {
15690 53 : mapper_clauses
15691 53 : = lang_hooks.decls.omp_finish_mapper_clauses (mapper_clauses);
15692 :
15693 : /* Stick the implicitly-expanded mapper clauses at the end of the
15694 : clause list. */
15695 53 : tree *tail = list_p;
15696 163 : while (*tail)
15697 110 : tail = &OMP_CLAUSE_CHAIN (*tail);
15698 53 : *tail = mapper_clauses;
15699 : }
15700 :
15701 17235 : vec<omp_mapping_group> *groups;
15702 17235 : groups = omp_gather_mapping_groups (list_p);
15703 17235 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
15704 :
15705 17235 : if (groups)
15706 : {
15707 8640 : grpmap = omp_index_mapping_groups (groups);
15708 :
15709 8640 : omp_resolve_clause_dependencies (code, groups, grpmap);
15710 8640 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15711 : &grpmap, list_p);
15712 :
15713 8640 : omp_mapping_group *outlist = NULL;
15714 :
15715 17280 : delete grpmap;
15716 8640 : delete groups;
15717 :
15718 : /* Rebuild now we have struct sibling lists. */
15719 8640 : groups = omp_gather_mapping_groups (list_p);
15720 8640 : grpmap = omp_index_mapping_groups (groups);
15721 :
15722 8640 : bool enter_exit = (code == OMP_TARGET_ENTER_DATA
15723 8640 : || code == OMP_TARGET_EXIT_DATA);
15724 :
15725 8640 : outlist = omp_tsort_mapping_groups (groups, grpmap, enter_exit);
15726 8640 : outlist = omp_segregate_mapping_groups (outlist);
15727 8640 : list_p = omp_reorder_mapping_groups (groups, outlist, list_p);
15728 :
15729 8640 : delete grpmap;
15730 8640 : delete groups;
15731 : }
15732 17235 : }
15733 112917 : else if (ctx->region_type & ORT_ACC)
15734 : {
15735 29899 : vec<omp_mapping_group> *groups;
15736 29899 : groups = omp_gather_mapping_groups (list_p);
15737 29899 : if (groups)
15738 : {
15739 9462 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap;
15740 9462 : grpmap = omp_index_mapping_groups (groups);
15741 :
15742 9462 : oacc_resolve_clause_dependencies (groups, grpmap);
15743 9462 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15744 : &grpmap, list_p);
15745 :
15746 9462 : delete groups;
15747 18924 : delete grpmap;
15748 : }
15749 : }
15750 :
15751 130152 : tree attach_list = NULL_TREE;
15752 130152 : tree *attach_tail = &attach_list;
15753 :
15754 130152 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
15755 :
15756 380242 : while ((c = *list_p) != NULL)
15757 : {
15758 250090 : splay_tree_node n;
15759 250090 : bool remove = false;
15760 250090 : bool move_attach = false;
15761 :
15762 292778 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
15763 : grp_end = NULL_TREE;
15764 :
15765 250090 : switch (OMP_CLAUSE_CODE (c))
15766 : {
15767 8075 : case OMP_CLAUSE_FIRSTPRIVATE:
15768 8075 : if ((ctx->region_type & ORT_TARGET)
15769 1982 : && (ctx->region_type & ORT_ACC) == 0
15770 9451 : && TYPE_ATOMIC (strip_array_types
15771 : (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
15772 : {
15773 4 : error_at (OMP_CLAUSE_LOCATION (c),
15774 : "%<_Atomic%> %qD in %<firstprivate%> clause on "
15775 2 : "%<target%> construct", OMP_CLAUSE_DECL (c));
15776 2 : remove = true;
15777 2 : break;
15778 : }
15779 8073 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
15780 : {
15781 380 : decl = OMP_CLAUSE_DECL (c);
15782 380 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15783 380 : if ((n->value & GOVD_MAP) != 0)
15784 : {
15785 : remove = true;
15786 : break;
15787 : }
15788 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0;
15789 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0;
15790 : }
15791 : /* FALLTHRU */
15792 36983 : case OMP_CLAUSE_PRIVATE:
15793 36983 : case OMP_CLAUSE_SHARED:
15794 36983 : case OMP_CLAUSE_LINEAR:
15795 36983 : decl = OMP_CLAUSE_DECL (c);
15796 36983 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15797 36983 : remove = !(n->value & GOVD_SEEN);
15798 36983 : if ((n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0
15799 48 : && code == OMP_PARALLEL
15800 37005 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15801 : remove = true;
15802 36961 : if (! remove)
15803 : {
15804 32353 : bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
15805 32353 : if ((n->value & GOVD_DEBUG_PRIVATE)
15806 32353 : || lang_hooks.decls.omp_private_debug_clause (decl, shared))
15807 : {
15808 87 : gcc_assert ((n->value & GOVD_DEBUG_PRIVATE) == 0
15809 : || ((n->value & GOVD_DATA_SHARE_CLASS)
15810 : == GOVD_SHARED));
15811 87 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
15812 87 : OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
15813 : }
15814 32353 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15815 4159 : && ctx->has_depend
15816 32911 : && DECL_P (decl))
15817 558 : n->value |= GOVD_WRITTEN;
15818 32353 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15819 4159 : && (n->value & GOVD_WRITTEN) == 0
15820 3042 : && DECL_P (decl)
15821 35395 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15822 526 : OMP_CLAUSE_SHARED_READONLY (c) = 1;
15823 31827 : else if (DECL_P (decl)
15824 31827 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15825 3633 : && (n->value & GOVD_WRITTEN) != 0)
15826 30710 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15827 9116 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
15828 38885 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15829 5754 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15830 : }
15831 : else
15832 4630 : n->value &= ~GOVD_EXPLICIT;
15833 : break;
15834 :
15835 13010 : case OMP_CLAUSE_LASTPRIVATE:
15836 : /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
15837 : accurately reflect the presence of a FIRSTPRIVATE clause. */
15838 13010 : decl = OMP_CLAUSE_DECL (c);
15839 13010 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15840 13010 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
15841 13010 : = (n->value & GOVD_FIRSTPRIVATE) != 0;
15842 13010 : if (code == OMP_DISTRIBUTE
15843 13010 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
15844 : {
15845 4 : remove = true;
15846 4 : error_at (OMP_CLAUSE_LOCATION (c),
15847 : "same variable used in %<firstprivate%> and "
15848 : "%<lastprivate%> clauses on %<distribute%> "
15849 : "construct");
15850 : }
15851 13010 : if (!remove
15852 13006 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15853 13006 : && DECL_P (decl)
15854 13006 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15855 11411 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15856 13010 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && code == OMP_PARALLEL)
15857 : remove = true;
15858 : break;
15859 :
15860 824 : case OMP_CLAUSE_ALIGNED:
15861 824 : decl = OMP_CLAUSE_DECL (c);
15862 824 : if (!is_global_var (decl))
15863 : {
15864 738 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15865 738 : remove = n == NULL || !(n->value & GOVD_SEEN);
15866 88 : if (!remove && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
15867 : {
15868 88 : struct gimplify_omp_ctx *octx;
15869 88 : if (n != NULL
15870 88 : && (n->value & (GOVD_DATA_SHARE_CLASS
15871 : & ~GOVD_FIRSTPRIVATE)))
15872 : remove = true;
15873 : else
15874 100 : for (octx = ctx->outer_context; octx;
15875 12 : octx = octx->outer_context)
15876 : {
15877 24 : n = splay_tree_lookup (octx->variables,
15878 : (splay_tree_key) decl);
15879 24 : if (n == NULL)
15880 12 : continue;
15881 12 : if (n->value & GOVD_LOCAL)
15882 : break;
15883 : /* We have to avoid assigning a shared variable
15884 : to itself when trying to add
15885 : __builtin_assume_aligned. */
15886 12 : if (n->value & GOVD_SHARED)
15887 : {
15888 : remove = true;
15889 : break;
15890 : }
15891 : }
15892 : }
15893 : }
15894 86 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
15895 : {
15896 86 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15897 86 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
15898 : remove = true;
15899 : }
15900 : break;
15901 :
15902 553 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
15903 553 : decl = OMP_CLAUSE_DECL (c);
15904 553 : while (INDIRECT_REF_P (decl)
15905 602 : || TREE_CODE (decl) == ARRAY_REF)
15906 49 : decl = TREE_OPERAND (decl, 0);
15907 553 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15908 553 : remove = n == NULL || !(n->value & GOVD_SEEN);
15909 : break;
15910 :
15911 900 : case OMP_CLAUSE_IS_DEVICE_PTR:
15912 900 : case OMP_CLAUSE_NONTEMPORAL:
15913 900 : decl = OMP_CLAUSE_DECL (c);
15914 900 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15915 900 : remove = n == NULL || !(n->value & GOVD_SEEN);
15916 : break;
15917 :
15918 56882 : case OMP_CLAUSE_MAP:
15919 56882 : if (OMP_CLAUSE_MAP_GIMPLE_ONLY (c))
15920 : {
15921 90 : remove = true;
15922 90 : goto end_adjust_omp_map_clause;
15923 : }
15924 56792 : decl = OMP_CLAUSE_DECL (c);
15925 56792 : if (!grp_end)
15926 : {
15927 31871 : grp_start_p = list_p;
15928 31871 : grp_end = *omp_group_last (grp_start_p);
15929 : }
15930 56792 : switch (OMP_CLAUSE_MAP_KIND (c))
15931 : {
15932 183 : case GOMP_MAP_PRESENT_ALLOC:
15933 183 : case GOMP_MAP_PRESENT_TO:
15934 183 : case GOMP_MAP_PRESENT_FROM:
15935 183 : case GOMP_MAP_PRESENT_TOFROM:
15936 183 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_PRESENT);
15937 183 : break;
15938 : default:
15939 : break;
15940 : }
15941 56792 : switch (code)
15942 : {
15943 4563 : case OACC_DATA:
15944 4563 : if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
15945 : break;
15946 : /* Fallthrough. */
15947 19317 : case OACC_HOST_DATA:
15948 19317 : case OACC_ENTER_DATA:
15949 19317 : case OACC_EXIT_DATA:
15950 19317 : case OMP_TARGET_DATA:
15951 19317 : case OMP_TARGET_ENTER_DATA:
15952 19317 : case OMP_TARGET_EXIT_DATA:
15953 19317 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15954 19317 : || (OMP_CLAUSE_MAP_KIND (c)
15955 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15956 : /* For target {,enter ,exit }data only the array slice is
15957 : mapped, but not the pointer to it. */
15958 : remove = true;
15959 19317 : if (code == OMP_TARGET_EXIT_DATA
15960 19317 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
15961 2805 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER))
15962 : remove = true;
15963 : break;
15964 : case OMP_TARGET:
15965 : break;
15966 : default:
15967 : break;
15968 : }
15969 19315 : if (remove)
15970 : break;
15971 56457 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
15972 : {
15973 : /* Sanity check: attach/detach map kinds use the size as a bias,
15974 : and it's never right to use the decl size for such
15975 : mappings. */
15976 17835 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
15977 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
15978 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DETACH
15979 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
15980 : && (OMP_CLAUSE_MAP_KIND (c)
15981 : != GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
15982 21894 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
15983 4059 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
15984 : }
15985 56457 : gimplify_omp_ctxp = ctx->outer_context;
15986 56457 : gimple_seq *seq_p;
15987 56457 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
15988 56457 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
15989 : is_gimple_val, fb_rvalue) == GS_ERROR)
15990 : {
15991 0 : gimplify_omp_ctxp = ctx;
15992 0 : remove = true;
15993 0 : goto end_adjust_omp_map_clause;
15994 : }
15995 56457 : else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15996 53536 : || (OMP_CLAUSE_MAP_KIND (c)
15997 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15998 53123 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15999 63100 : && TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
16000 : {
16001 912 : OMP_CLAUSE_SIZE (c)
16002 912 : = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), seq_p, NULL,
16003 : false);
16004 912 : if ((ctx->region_type & ORT_TARGET) != 0)
16005 703 : omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
16006 : GOVD_FIRSTPRIVATE | GOVD_SEEN);
16007 : }
16008 56457 : gimplify_omp_ctxp = ctx;
16009 : /* Data clauses associated with reductions must be
16010 : compatible with present_or_copy. Warn and adjust the clause
16011 : if that is not the case. */
16012 56457 : if (ctx->region_type == ORT_ACC_PARALLEL
16013 47478 : || ctx->region_type == ORT_ACC_SERIAL)
16014 : {
16015 9535 : tree t = DECL_P (decl) ? decl : TREE_OPERAND (decl, 0);
16016 9535 : n = NULL;
16017 :
16018 9535 : if (DECL_P (t))
16019 7770 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
16020 :
16021 7770 : if (n && (n->value & GOVD_REDUCTION))
16022 : {
16023 809 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
16024 :
16025 809 : OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1;
16026 809 : if ((kind & GOMP_MAP_TOFROM) != GOMP_MAP_TOFROM
16027 159 : && kind != GOMP_MAP_FORCE_PRESENT
16028 159 : && kind != GOMP_MAP_POINTER)
16029 : {
16030 120 : warning_at (OMP_CLAUSE_LOCATION (c), 0,
16031 : "incompatible data clause with reduction "
16032 : "on %qE; promoting to %<present_or_copy%>",
16033 120 : DECL_NAME (t));
16034 120 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
16035 : }
16036 : }
16037 : }
16038 56457 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
16039 53671 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
16040 56731 : && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
16041 : {
16042 536 : remove = true;
16043 536 : goto end_adjust_omp_map_clause;
16044 : }
16045 : /* If we have a DECL_VALUE_EXPR (e.g. this is a class member and/or
16046 : a variable captured in a lambda closure), look through that now
16047 : before the DECL_P check below. (A code other than COMPONENT_REF,
16048 : i.e. INDIRECT_REF, will be a VLA/variable-length array
16049 : section. A global var may be a variable in a common block. We
16050 : don't want to do this here for either of those.) */
16051 55921 : if ((ctx->region_type & ORT_ACC) == 0
16052 29714 : && DECL_P (decl)
16053 12765 : && !is_global_var (decl)
16054 11353 : && DECL_HAS_VALUE_EXPR_P (decl)
16055 56111 : && TREE_CODE (DECL_VALUE_EXPR (decl)) == COMPONENT_REF)
16056 0 : decl = OMP_CLAUSE_DECL (c) = DECL_VALUE_EXPR (decl);
16057 55921 : if (TREE_CODE (decl) == TARGET_EXPR)
16058 : {
16059 0 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
16060 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
16061 26324 : remove = true;
16062 : }
16063 55921 : else if (!DECL_P (decl))
16064 : {
16065 29597 : if ((ctx->region_type & ORT_TARGET) != 0
16066 29597 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
16067 : {
16068 24 : if (INDIRECT_REF_P (decl)
16069 0 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
16070 24 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
16071 : == REFERENCE_TYPE))
16072 0 : decl = TREE_OPERAND (decl, 0);
16073 24 : if (TREE_CODE (decl) == COMPONENT_REF)
16074 : {
16075 0 : while (TREE_CODE (decl) == COMPONENT_REF)
16076 0 : decl = TREE_OPERAND (decl, 0);
16077 0 : if (DECL_P (decl))
16078 : {
16079 0 : n = splay_tree_lookup (ctx->variables,
16080 : (splay_tree_key) decl);
16081 0 : if (!(n->value & GOVD_SEEN))
16082 29597 : remove = true;
16083 : }
16084 : }
16085 : }
16086 :
16087 29597 : tree d = decl, *pd;
16088 29597 : if (TREE_CODE (d) == ARRAY_REF)
16089 : {
16090 5836 : while (TREE_CODE (d) == ARRAY_REF)
16091 2978 : d = TREE_OPERAND (d, 0);
16092 2858 : if (TREE_CODE (d) == COMPONENT_REF
16093 2858 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
16094 : decl = d;
16095 : }
16096 29597 : pd = &OMP_CLAUSE_DECL (c);
16097 29597 : if (d == decl
16098 27098 : && TREE_CODE (decl) == INDIRECT_REF
16099 15462 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
16100 1471 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
16101 : == REFERENCE_TYPE)
16102 30397 : && (OMP_CLAUSE_MAP_KIND (c)
16103 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
16104 : {
16105 796 : pd = &TREE_OPERAND (decl, 0);
16106 796 : decl = TREE_OPERAND (decl, 0);
16107 : }
16108 :
16109 29597 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16110 3067 : switch (code)
16111 : {
16112 427 : case OACC_ENTER_DATA:
16113 427 : case OACC_EXIT_DATA:
16114 427 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
16115 : == ARRAY_TYPE)
16116 : remove = true;
16117 417 : else if (code == OACC_ENTER_DATA)
16118 263 : goto change_to_attach;
16119 : /* Fallthrough. */
16120 605 : case OMP_TARGET_EXIT_DATA:
16121 605 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DETACH);
16122 605 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
16123 605 : break;
16124 71 : case OACC_UPDATE:
16125 : /* An "attach/detach" operation on an update directive
16126 : should behave as a GOMP_MAP_ALWAYS_POINTER. Note that
16127 : both GOMP_MAP_ATTACH_DETACH and GOMP_MAP_ALWAYS_POINTER
16128 : kinds depend on the previous mapping (for non-TARGET
16129 : regions). */
16130 71 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
16131 71 : break;
16132 2391 : default:
16133 2391 : change_to_attach:
16134 2391 : gcc_assert (!OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c));
16135 2391 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH);
16136 2391 : if ((ctx->region_type & ORT_TARGET) != 0)
16137 2113 : move_attach = true;
16138 : }
16139 26530 : else if ((ctx->region_type & ORT_TARGET) != 0
16140 26530 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16141 11816 : || (OMP_CLAUSE_MAP_KIND (c)
16142 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16143 : move_attach = true;
16144 :
16145 : /* If we have e.g. map(struct: *var), don't gimplify the
16146 : argument since omp-low.cc wants to see the decl itself. */
16147 29597 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
16148 1136 : goto end_adjust_omp_map_clause;
16149 :
16150 : /* We've already partly gimplified this in
16151 : gimplify_scan_omp_clauses. Don't do any more. */
16152 28461 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
16153 88 : goto end_adjust_omp_map_clause;
16154 :
16155 28373 : gimplify_omp_ctxp = ctx->outer_context;
16156 28373 : if (gimplify_expr (pd, seq_p, NULL, is_gimple_lvalue,
16157 : fb_lvalue) == GS_ERROR)
16158 0 : remove = true;
16159 28373 : gimplify_omp_ctxp = ctx;
16160 28373 : goto end_adjust_omp_map_clause;
16161 : }
16162 :
16163 26324 : if ((code == OMP_TARGET
16164 : || code == OMP_TARGET_DATA
16165 : || code == OMP_TARGET_ENTER_DATA
16166 14453 : || code == OMP_TARGET_EXIT_DATA)
16167 26956 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16168 : {
16169 242 : bool firstprivatize = false;
16170 :
16171 247 : for (struct gimplify_omp_ctx *octx = ctx->outer_context; octx;
16172 5 : octx = octx->outer_context)
16173 : {
16174 6 : splay_tree_node n
16175 12 : = splay_tree_lookup (octx->variables,
16176 6 : (splay_tree_key) OMP_CLAUSE_DECL (c));
16177 : /* If this is contained in an outer OpenMP region as a
16178 : firstprivate value, remove the attach/detach. */
16179 6 : if (n && (n->value & GOVD_FIRSTPRIVATE))
16180 : {
16181 : firstprivatize = true;
16182 : break;
16183 : }
16184 : }
16185 :
16186 242 : enum gomp_map_kind map_kind;
16187 242 : if (firstprivatize)
16188 : map_kind = GOMP_MAP_FIRSTPRIVATE_POINTER;
16189 241 : else if (code == OMP_TARGET_EXIT_DATA)
16190 : map_kind = GOMP_MAP_DETACH;
16191 : else
16192 190 : map_kind = GOMP_MAP_ATTACH;
16193 242 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16194 : }
16195 26082 : else if ((ctx->region_type & ORT_ACC) != 0
16196 26082 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16197 : {
16198 0 : enum gomp_map_kind map_kind = (code == OACC_EXIT_DATA
16199 0 : ? GOMP_MAP_DETACH
16200 : : GOMP_MAP_ATTACH);
16201 0 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16202 : }
16203 :
16204 26324 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16205 26324 : if ((ctx->region_type & ORT_TARGET) != 0
16206 16359 : && !(n->value & GOVD_SEEN)
16207 1511 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) == 0
16208 27588 : && (!is_global_var (decl)
16209 75 : || !lookup_attribute ("omp declare target link",
16210 75 : DECL_ATTRIBUTES (decl))))
16211 : {
16212 1252 : remove = true;
16213 : /* For struct element mapping, if struct is never referenced
16214 : in target block and none of the mapping has always modifier,
16215 : remove all the struct element mappings, which immediately
16216 : follow the GOMP_MAP_STRUCT map clause. */
16217 1252 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
16218 1252 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
16219 : {
16220 30 : HOST_WIDE_INT cnt = tree_to_shwi (OMP_CLAUSE_SIZE (c));
16221 80 : while (cnt--)
16222 50 : OMP_CLAUSE_CHAIN (c)
16223 50 : = OMP_CLAUSE_CHAIN (OMP_CLAUSE_CHAIN (c));
16224 : }
16225 : }
16226 25072 : else if (DECL_SIZE (decl)
16227 25048 : && !poly_int_tree_p (DECL_SIZE (decl))
16228 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER
16229 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
16230 25123 : && (OMP_CLAUSE_MAP_KIND (c)
16231 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
16232 : {
16233 : /* For GOMP_MAP_FORCE_DEVICEPTR, we'll never enter here, because
16234 : for these, TREE_CODE (DECL_SIZE (decl)) will always be
16235 : INTEGER_CST. */
16236 51 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
16237 :
16238 51 : tree decl2 = DECL_VALUE_EXPR (decl);
16239 51 : gcc_assert (INDIRECT_REF_P (decl2));
16240 51 : decl2 = TREE_OPERAND (decl2, 0);
16241 51 : gcc_assert (DECL_P (decl2));
16242 51 : tree mem = build_simple_mem_ref (decl2);
16243 51 : OMP_CLAUSE_DECL (c) = mem;
16244 51 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16245 51 : if (ctx->outer_context)
16246 : {
16247 15 : omp_notice_variable (ctx->outer_context, decl2, true);
16248 30 : omp_notice_variable (ctx->outer_context,
16249 15 : OMP_CLAUSE_SIZE (c), true);
16250 : }
16251 51 : if (((ctx->region_type & ORT_TARGET) != 0
16252 24 : || !ctx->target_firstprivatize_array_bases)
16253 34 : && ((n->value & GOVD_SEEN) == 0
16254 30 : || (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0))
16255 : {
16256 34 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16257 : OMP_CLAUSE_MAP);
16258 34 : OMP_CLAUSE_DECL (nc) = decl;
16259 34 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
16260 34 : if (ctx->target_firstprivatize_array_bases)
16261 27 : OMP_CLAUSE_SET_MAP_KIND (nc,
16262 : GOMP_MAP_FIRSTPRIVATE_POINTER);
16263 : else
16264 7 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
16265 34 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
16266 34 : OMP_CLAUSE_CHAIN (c) = nc;
16267 34 : c = nc;
16268 : }
16269 : }
16270 : else
16271 : {
16272 25021 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16273 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16274 25021 : gcc_assert ((n->value & GOVD_SEEN) == 0
16275 : || ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16276 : == 0));
16277 : }
16278 :
16279 : /* If we have a target region, we can push all the attaches to the
16280 : end of the list (we may have standalone "attach" operations
16281 : synthesized for GOMP_MAP_STRUCT nodes that must be processed after
16282 : the attachment point AND the pointed-to block have been mapped).
16283 : If we have something else, e.g. "enter data", we need to keep
16284 : "attach" nodes together with the previous node they attach to so
16285 : that separate "exit data" operations work properly (see
16286 : libgomp/target.c). */
16287 26324 : if ((ctx->region_type & ORT_TARGET) != 0
16288 26324 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16289 16243 : || (OMP_CLAUSE_MAP_KIND (c)
16290 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16291 : move_attach = true;
16292 :
16293 56547 : end_adjust_omp_map_clause:
16294 56547 : exit_omp_iterator_loop_context (c);
16295 56547 : break;
16296 :
16297 8383 : case OMP_CLAUSE_TO:
16298 8383 : case OMP_CLAUSE_FROM:
16299 8383 : case OMP_CLAUSE__CACHE_:
16300 8383 : decl = OMP_CLAUSE_DECL (c);
16301 8383 : if (!DECL_P (decl))
16302 : break;
16303 6203 : if (DECL_SIZE (decl)
16304 6203 : && !poly_int_tree_p (DECL_SIZE (decl)))
16305 : {
16306 4 : tree decl2 = DECL_VALUE_EXPR (decl);
16307 4 : gcc_assert (INDIRECT_REF_P (decl2));
16308 4 : decl2 = TREE_OPERAND (decl2, 0);
16309 4 : gcc_assert (DECL_P (decl2));
16310 4 : tree mem = build_simple_mem_ref (decl2);
16311 4 : OMP_CLAUSE_DECL (c) = mem;
16312 4 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16313 4 : if (ctx->outer_context)
16314 : {
16315 4 : omp_notice_variable (ctx->outer_context, decl2, true);
16316 4 : omp_notice_variable (ctx->outer_context,
16317 4 : OMP_CLAUSE_SIZE (c), true);
16318 : }
16319 : }
16320 6199 : else if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16321 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16322 : break;
16323 :
16324 15379 : case OMP_CLAUSE_REDUCTION:
16325 15379 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
16326 : {
16327 831 : decl = OMP_CLAUSE_DECL (c);
16328 831 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16329 831 : if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
16330 : {
16331 69 : remove = true;
16332 69 : error_at (OMP_CLAUSE_LOCATION (c),
16333 : "%qD specified in %<inscan%> %<reduction%> clause "
16334 : "but not in %<scan%> directive clause", decl);
16335 69 : break;
16336 : }
16337 : has_inscan_reductions = true;
16338 : }
16339 : /* FALLTHRU */
16340 17914 : case OMP_CLAUSE_IN_REDUCTION:
16341 17914 : case OMP_CLAUSE_TASK_REDUCTION:
16342 17914 : decl = OMP_CLAUSE_DECL (c);
16343 : /* OpenACC reductions need a present_or_copy data clause.
16344 : Add one if necessary. Emit error when the reduction is private. */
16345 17914 : if (ctx->region_type == ORT_ACC_PARALLEL
16346 17382 : || ctx->region_type == ORT_ACC_SERIAL)
16347 : {
16348 803 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16349 803 : if (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16350 : {
16351 13 : remove = true;
16352 13 : error_at (OMP_CLAUSE_LOCATION (c), "invalid private "
16353 13 : "reduction on %qE", DECL_NAME (decl));
16354 : }
16355 790 : else if ((n->value & GOVD_MAP) == 0)
16356 : {
16357 524 : tree next = OMP_CLAUSE_CHAIN (c);
16358 524 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP);
16359 524 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM);
16360 524 : OMP_CLAUSE_DECL (nc) = decl;
16361 524 : OMP_CLAUSE_CHAIN (c) = nc;
16362 524 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
16363 524 : (ctx->region_type
16364 : & ORT_ACC) != 0);
16365 550 : while (1)
16366 : {
16367 537 : OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1;
16368 537 : if (OMP_CLAUSE_CHAIN (nc) == NULL)
16369 : break;
16370 13 : nc = OMP_CLAUSE_CHAIN (nc);
16371 : }
16372 524 : OMP_CLAUSE_CHAIN (nc) = next;
16373 524 : n->value |= GOVD_MAP;
16374 : }
16375 : }
16376 17914 : if (DECL_P (decl)
16377 17914 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
16378 8032 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
16379 : break;
16380 :
16381 3682 : case OMP_CLAUSE_ALLOCATE:
16382 3682 : decl = OMP_CLAUSE_DECL (c);
16383 3682 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16384 3682 : if (n != NULL && !(n->value & GOVD_SEEN))
16385 : {
16386 1180 : if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
16387 : != 0
16388 1180 : && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
16389 : remove = true;
16390 : }
16391 : if (!remove
16392 2502 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
16393 1286 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
16394 492 : && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
16395 347 : || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
16396 287 : || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
16397 : {
16398 223 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
16399 223 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
16400 223 : if (n == NULL)
16401 : {
16402 92 : enum omp_clause_default_kind default_kind
16403 : = ctx->default_kind;
16404 92 : ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
16405 92 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16406 : true);
16407 92 : ctx->default_kind = default_kind;
16408 : }
16409 : else
16410 131 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16411 : true);
16412 : }
16413 : break;
16414 :
16415 : case OMP_CLAUSE_COPYIN:
16416 : case OMP_CLAUSE_COPYPRIVATE:
16417 : case OMP_CLAUSE_IF:
16418 : case OMP_CLAUSE_SELF:
16419 : case OMP_CLAUSE_NUM_THREADS:
16420 : case OMP_CLAUSE_NUM_TEAMS:
16421 : case OMP_CLAUSE_THREAD_LIMIT:
16422 : case OMP_CLAUSE_DIST_SCHEDULE:
16423 : case OMP_CLAUSE_DEVICE:
16424 : case OMP_CLAUSE_SCHEDULE:
16425 : case OMP_CLAUSE_NOWAIT:
16426 : case OMP_CLAUSE_ORDERED:
16427 : case OMP_CLAUSE_DEFAULT:
16428 : case OMP_CLAUSE_UNTIED:
16429 : case OMP_CLAUSE_COLLAPSE:
16430 : case OMP_CLAUSE_FINAL:
16431 : case OMP_CLAUSE_MERGEABLE:
16432 : case OMP_CLAUSE_PROC_BIND:
16433 : case OMP_CLAUSE_SAFELEN:
16434 : case OMP_CLAUSE_SIMDLEN:
16435 : case OMP_CLAUSE_DEPEND:
16436 : case OMP_CLAUSE_DOACROSS:
16437 : case OMP_CLAUSE_PRIORITY:
16438 : case OMP_CLAUSE_GRAINSIZE:
16439 : case OMP_CLAUSE_NUM_TASKS:
16440 : case OMP_CLAUSE_NOGROUP:
16441 : case OMP_CLAUSE_THREADS:
16442 : case OMP_CLAUSE_SIMD:
16443 : case OMP_CLAUSE_FILTER:
16444 : case OMP_CLAUSE_HINT:
16445 : case OMP_CLAUSE_DEFAULTMAP:
16446 : case OMP_CLAUSE_ORDER:
16447 : case OMP_CLAUSE_BIND:
16448 : case OMP_CLAUSE_DETACH:
16449 : case OMP_CLAUSE_USE_DEVICE_PTR:
16450 : case OMP_CLAUSE_USE_DEVICE_ADDR:
16451 : case OMP_CLAUSE_ASYNC:
16452 : case OMP_CLAUSE_WAIT:
16453 : case OMP_CLAUSE_INDEPENDENT:
16454 : case OMP_CLAUSE_NUM_GANGS:
16455 : case OMP_CLAUSE_NUM_WORKERS:
16456 : case OMP_CLAUSE_VECTOR_LENGTH:
16457 : case OMP_CLAUSE_GANG:
16458 : case OMP_CLAUSE_WORKER:
16459 : case OMP_CLAUSE_VECTOR:
16460 : case OMP_CLAUSE_AUTO:
16461 : case OMP_CLAUSE_SEQ:
16462 : case OMP_CLAUSE_TILE:
16463 : case OMP_CLAUSE_IF_PRESENT:
16464 : case OMP_CLAUSE_FINALIZE:
16465 : case OMP_CLAUSE_INCLUSIVE:
16466 : case OMP_CLAUSE_EXCLUSIVE:
16467 : case OMP_CLAUSE_USES_ALLOCATORS:
16468 : case OMP_CLAUSE_DEVICE_TYPE:
16469 : case OMP_CLAUSE_MESSAGE:
16470 : break;
16471 :
16472 0 : case OMP_CLAUSE_NOHOST:
16473 0 : default:
16474 0 : gcc_unreachable ();
16475 : }
16476 :
16477 128824 : if (remove)
16478 9947 : *list_p = OMP_CLAUSE_CHAIN (c);
16479 240143 : else if (move_attach)
16480 : {
16481 : /* Remove attach node from here, separate out into its own list. */
16482 2360 : *attach_tail = c;
16483 2360 : *list_p = OMP_CLAUSE_CHAIN (c);
16484 2360 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
16485 2360 : attach_tail = &OMP_CLAUSE_CHAIN (c);
16486 : }
16487 : else
16488 237783 : list_p = &OMP_CLAUSE_CHAIN (c);
16489 : }
16490 :
16491 : /* Splice attach nodes at the end of the list. */
16492 130152 : if (attach_list)
16493 : {
16494 1127 : *list_p = attach_list;
16495 1127 : list_p = attach_tail;
16496 : }
16497 :
16498 : /* Add in any implicit data sharing. */
16499 130152 : struct gimplify_adjust_omp_clauses_data data;
16500 130152 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
16501 : {
16502 : /* OpenMP. Implicit clauses are added at the start of the clause list,
16503 : but after any non-map clauses. */
16504 : tree *implicit_add_list_p = orig_list_p;
16505 254477 : while (*implicit_add_list_p
16506 254477 : && OMP_CLAUSE_CODE (*implicit_add_list_p) != OMP_CLAUSE_MAP)
16507 154224 : implicit_add_list_p = &OMP_CLAUSE_CHAIN (*implicit_add_list_p);
16508 100253 : data.list_p = implicit_add_list_p;
16509 : }
16510 : else
16511 : /* OpenACC. */
16512 29899 : data.list_p = list_p;
16513 130152 : data.pre_p = pre_p;
16514 130152 : splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
16515 :
16516 130152 : if (has_inscan_reductions)
16517 2499 : for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
16518 1870 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
16519 1870 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
16520 : {
16521 5 : error_at (OMP_CLAUSE_LOCATION (c),
16522 : "%<inscan%> %<reduction%> clause used together with "
16523 : "%<linear%> clause for a variable other than loop "
16524 : "iterator");
16525 5 : break;
16526 : }
16527 :
16528 130152 : gimplify_omp_ctxp = ctx->outer_context;
16529 130152 : delete_omp_context (ctx);
16530 130152 : }
16531 :
16532 : /* Try to evaluate a novariants clause. Return 1 if true, 0 if false or absent,
16533 : * -1 if run-time evaluation is needed. */
16534 :
16535 : int
16536 252021 : omp_has_novariants (void)
16537 : {
16538 252021 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16539 252021 : if (ctx != NULL && ctx->code == OMP_DISPATCH && !ctx->in_call_args)
16540 : {
16541 3290 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOVARIANTS);
16542 3290 : if (c != NULL_TREE)
16543 : {
16544 299 : if (integer_nonzerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16545 : return 1;
16546 171 : else if (integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16547 : return 0;
16548 : else
16549 38 : return -1;
16550 : }
16551 : return 0;
16552 : }
16553 : return 0;
16554 : }
16555 :
16556 : /* Try to evaluate a nocontext clause. Return 1 if true, 0 if false or absent,
16557 : * -1 if run-time evaluation is needed. */
16558 :
16559 : static int
16560 1903 : omp_has_nocontext (void)
16561 : {
16562 1903 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16563 1903 : if (ctx != NULL && ctx->code == OMP_DISPATCH)
16564 : {
16565 1903 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOCONTEXT);
16566 1903 : if (c != NULL_TREE)
16567 : {
16568 256 : if (integer_nonzerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16569 : return 1;
16570 94 : else if (integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16571 : return 0;
16572 : else
16573 44 : return -1;
16574 : }
16575 : return 0;
16576 : }
16577 : return 0;
16578 : }
16579 :
16580 : /* Collect a list of traits for enclosing constructs in the current
16581 : OpenMP context. The list is in the same format as the trait selector
16582 : list of construct trait sets built by the front ends.
16583 :
16584 : Per the OpenMP specification, the construct trait set includes constructs
16585 : up to an enclosing "target" construct. If there is no "target" construct,
16586 : then additional things may be added to the construct trait set (simd for
16587 : simd clones, additional constructs associated with "declare variant",
16588 : the target trait for "declare target"); those are not handled here.
16589 : In particular simd clones are not known during gimplification so
16590 : matching/scoring of context selectors that might involve them needs
16591 : to be deferred to the omp_device_lower pass. */
16592 :
16593 : tree
16594 2247 : omp_get_construct_context (void)
16595 : {
16596 2247 : tree result = NULL_TREE;
16597 4246 : for (struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; ctx;)
16598 : {
16599 2120 : if (((ctx->region_type & (ORT_TARGET | ORT_IMPLICIT_TARGET | ORT_ACC))
16600 : == ORT_TARGET)
16601 121 : && ctx->code == OMP_TARGET)
16602 : {
16603 121 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TARGET,
16604 : NULL_TREE, NULL_TREE, result);
16605 : /* We're not interested in any outer constructs. */
16606 121 : break;
16607 : }
16608 1999 : else if ((ctx->region_type & ORT_PARALLEL) && ctx->code == OMP_PARALLEL)
16609 216 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_PARALLEL,
16610 : NULL_TREE, NULL_TREE, result);
16611 1783 : else if ((ctx->region_type & ORT_TEAMS) && ctx->code == OMP_TEAMS)
16612 75 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TEAMS,
16613 : NULL_TREE, NULL_TREE, result);
16614 1708 : else if (ctx->region_type == ORT_WORKSHARE && ctx->code == OMP_FOR)
16615 164 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_FOR,
16616 : NULL_TREE, NULL_TREE, result);
16617 1544 : else if (ctx->code == OMP_DISPATCH && omp_has_nocontext () != 1)
16618 1279 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_DISPATCH,
16619 : NULL_TREE, NULL_TREE, result);
16620 265 : else if (ctx->region_type == ORT_SIMD
16621 58 : && ctx->code == OMP_SIMD
16622 323 : && !omp_find_clause (ctx->clauses, OMP_CLAUSE_BIND))
16623 : {
16624 58 : tree props = NULL_TREE;
16625 58 : tree *last = &props;
16626 120 : for (tree c = ctx->clauses; c; c = OMP_CLAUSE_CHAIN (c))
16627 62 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMDLEN
16628 42 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INBRANCH
16629 104 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOTINBRANCH)
16630 : {
16631 20 : *last = unshare_expr (c);
16632 20 : last = &(OMP_CLAUSE_CHAIN (c));
16633 : }
16634 58 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_SIMD,
16635 : NULL_TREE, props, result);
16636 : }
16637 207 : else if (ctx->region_type == ORT_WORKSHARE
16638 5 : && ctx->code == OMP_LOOP
16639 0 : && ctx->outer_context
16640 0 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL
16641 0 : && ctx->outer_context->outer_context
16642 0 : && ctx->outer_context->outer_context->code == OMP_LOOP
16643 0 : && ctx->outer_context->outer_context->distribute)
16644 1999 : ctx = ctx->outer_context->outer_context;
16645 1999 : ctx = ctx->outer_context;
16646 : }
16647 :
16648 2247 : return result;
16649 : }
16650 :
16651 : /* Gimplify OACC_CACHE. */
16652 :
16653 : static void
16654 717 : gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
16655 : {
16656 717 : tree expr = *expr_p;
16657 :
16658 717 : gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_ACC,
16659 : OACC_CACHE);
16660 717 : gimplify_adjust_omp_clauses (pre_p, NULL, &OACC_CACHE_CLAUSES (expr),
16661 : OACC_CACHE);
16662 :
16663 : /* TODO: Do something sensible with this information. */
16664 :
16665 717 : *expr_p = NULL_TREE;
16666 717 : }
16667 :
16668 : /* Helper function of gimplify_oacc_declare. The helper's purpose is to,
16669 : if required, translate 'kind' in CLAUSE into an 'entry' kind and 'exit'
16670 : kind. The entry kind will replace the one in CLAUSE, while the exit
16671 : kind will be used in a new omp_clause and returned to the caller. */
16672 :
16673 : static tree
16674 190 : gimplify_oacc_declare_1 (tree clause)
16675 : {
16676 190 : HOST_WIDE_INT kind, new_op;
16677 190 : bool ret = false;
16678 190 : tree c = NULL;
16679 :
16680 190 : kind = OMP_CLAUSE_MAP_KIND (clause);
16681 :
16682 190 : switch (kind)
16683 : {
16684 : case GOMP_MAP_ALLOC:
16685 : new_op = GOMP_MAP_RELEASE;
16686 : ret = true;
16687 : break;
16688 :
16689 29 : case GOMP_MAP_FROM:
16690 29 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_ALLOC);
16691 29 : new_op = GOMP_MAP_FROM;
16692 29 : ret = true;
16693 29 : break;
16694 :
16695 40 : case GOMP_MAP_TOFROM:
16696 40 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_TO);
16697 40 : new_op = GOMP_MAP_FROM;
16698 40 : ret = true;
16699 40 : break;
16700 :
16701 : case GOMP_MAP_DEVICE_RESIDENT:
16702 : case GOMP_MAP_FORCE_DEVICEPTR:
16703 : case GOMP_MAP_FORCE_PRESENT:
16704 : case GOMP_MAP_LINK:
16705 : case GOMP_MAP_POINTER:
16706 : case GOMP_MAP_TO:
16707 : break;
16708 :
16709 0 : default:
16710 0 : gcc_unreachable ();
16711 69 : break;
16712 : }
16713 :
16714 69 : if (ret)
16715 : {
16716 116 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clause), OMP_CLAUSE_MAP);
16717 116 : OMP_CLAUSE_SET_MAP_KIND (c, new_op);
16718 116 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clause);
16719 : }
16720 :
16721 190 : return c;
16722 : }
16723 :
16724 : /* Gimplify OACC_DECLARE. */
16725 :
16726 : static void
16727 254 : gimplify_oacc_declare (tree *expr_p, gimple_seq *pre_p)
16728 : {
16729 254 : tree expr = *expr_p;
16730 254 : gomp_target *stmt;
16731 254 : tree clauses, t, decl;
16732 :
16733 254 : clauses = OACC_DECLARE_CLAUSES (expr);
16734 :
16735 254 : gimplify_scan_omp_clauses (&clauses, pre_p, ORT_TARGET_DATA, OACC_DECLARE);
16736 254 : gimplify_adjust_omp_clauses (pre_p, NULL, &clauses, OACC_DECLARE);
16737 :
16738 516 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16739 : {
16740 262 : decl = OMP_CLAUSE_DECL (t);
16741 :
16742 262 : if (TREE_CODE (decl) == MEM_REF)
16743 8 : decl = TREE_OPERAND (decl, 0);
16744 :
16745 262 : if (VAR_P (decl) && !is_oacc_declared (decl))
16746 : {
16747 262 : tree attr = get_identifier ("oacc declare target");
16748 262 : DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE,
16749 262 : DECL_ATTRIBUTES (decl));
16750 : }
16751 :
16752 262 : if (VAR_P (decl)
16753 262 : && !is_global_var (decl)
16754 452 : && DECL_CONTEXT (decl) == current_function_decl)
16755 : {
16756 190 : tree c = gimplify_oacc_declare_1 (t);
16757 190 : if (c)
16758 : {
16759 116 : if (oacc_declare_returns == NULL)
16760 40 : oacc_declare_returns = new hash_map<tree, tree>;
16761 :
16762 116 : oacc_declare_returns->put (decl, c);
16763 : }
16764 : }
16765 :
16766 262 : if (gimplify_omp_ctxp)
16767 72 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_SEEN);
16768 : }
16769 :
16770 254 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
16771 : clauses);
16772 :
16773 254 : gimplify_seq_add_stmt (pre_p, stmt);
16774 :
16775 254 : *expr_p = NULL_TREE;
16776 254 : }
16777 :
16778 : /* Gimplify the contents of an OMP_PARALLEL statement. This involves
16779 : gimplification of the body, as well as scanning the body for used
16780 : variables. We need to do this scan now, because variable-sized
16781 : decls will be decomposed during gimplification. */
16782 :
16783 : static void
16784 18392 : gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
16785 : {
16786 18392 : tree expr = *expr_p;
16787 18392 : gimple *g;
16788 18392 : gimple_seq body = NULL;
16789 :
16790 36784 : gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
16791 18392 : OMP_PARALLEL_COMBINED (expr)
16792 : ? ORT_COMBINED_PARALLEL
16793 : : ORT_PARALLEL, OMP_PARALLEL);
16794 :
16795 18392 : push_gimplify_context ();
16796 :
16797 18392 : g = gimplify_and_return_first (OMP_PARALLEL_BODY (expr), &body);
16798 18392 : if (gimple_code (g) == GIMPLE_BIND)
16799 18392 : pop_gimplify_context (g);
16800 : else
16801 0 : pop_gimplify_context (NULL);
16802 :
16803 18392 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_PARALLEL_CLAUSES (expr),
16804 : OMP_PARALLEL);
16805 :
16806 36784 : g = gimple_build_omp_parallel (body,
16807 18392 : OMP_PARALLEL_CLAUSES (expr),
16808 : NULL_TREE, NULL_TREE);
16809 18392 : if (OMP_PARALLEL_COMBINED (expr))
16810 12584 : gimple_omp_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
16811 18392 : gimplify_seq_add_stmt (pre_p, g);
16812 18392 : *expr_p = NULL_TREE;
16813 18392 : }
16814 :
16815 : /* Gimplify the contents of an OMP_TASK statement. This involves
16816 : gimplification of the body, as well as scanning the body for used
16817 : variables. We need to do this scan now, because variable-sized
16818 : decls will be decomposed during gimplification. */
16819 :
16820 : static void
16821 4111 : gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
16822 : {
16823 4111 : tree expr = *expr_p;
16824 4111 : gimple *g;
16825 4111 : gimple_seq body = NULL;
16826 4111 : bool nowait = false;
16827 4111 : bool has_depend = false;
16828 :
16829 4111 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16830 : {
16831 242 : for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
16832 153 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
16833 : {
16834 111 : has_depend = true;
16835 111 : if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
16836 : {
16837 9 : error_at (OMP_CLAUSE_LOCATION (c),
16838 : "%<mutexinoutset%> kind in %<depend%> clause on a "
16839 : "%<taskwait%> construct");
16840 9 : break;
16841 : }
16842 : }
16843 42 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT)
16844 42 : nowait = true;
16845 98 : if (nowait && !has_depend)
16846 : {
16847 5 : error_at (EXPR_LOCATION (expr),
16848 : "%<taskwait%> construct with %<nowait%> clause but no "
16849 : "%<depend%> clauses");
16850 5 : *expr_p = NULL_TREE;
16851 5 : return;
16852 : }
16853 : }
16854 :
16855 12318 : gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
16856 4106 : omp_find_clause (OMP_TASK_CLAUSES (expr),
16857 : OMP_CLAUSE_UNTIED)
16858 : ? ORT_UNTIED_TASK : ORT_TASK, OMP_TASK);
16859 :
16860 4106 : if (OMP_TASK_BODY (expr))
16861 : {
16862 4013 : push_gimplify_context ();
16863 :
16864 4013 : g = gimplify_and_return_first (OMP_TASK_BODY (expr), &body);
16865 4013 : if (gimple_code (g) == GIMPLE_BIND)
16866 4013 : pop_gimplify_context (g);
16867 : else
16868 0 : pop_gimplify_context (NULL);
16869 : }
16870 :
16871 4106 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_TASK_CLAUSES (expr),
16872 : OMP_TASK);
16873 :
16874 8212 : g = gimple_build_omp_task (body,
16875 4106 : OMP_TASK_CLAUSES (expr),
16876 : NULL_TREE, NULL_TREE,
16877 : NULL_TREE, NULL_TREE, NULL_TREE);
16878 4106 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16879 93 : gimple_omp_task_set_taskwait_p (g, true);
16880 4106 : gimplify_seq_add_stmt (pre_p, g);
16881 4106 : *expr_p = NULL_TREE;
16882 : }
16883 :
16884 : /* Helper function for gimplify_omp_for. If *TP is not a gimple constant,
16885 : force it into a temporary initialized in PRE_P and add firstprivate clause
16886 : to ORIG_FOR_STMT. */
16887 :
16888 : static void
16889 4399 : gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p,
16890 : tree orig_for_stmt)
16891 : {
16892 4399 : if (*tp == NULL || is_gimple_constant (*tp))
16893 : return;
16894 :
16895 779 : if (TREE_CODE (*tp) == SAVE_EXPR)
16896 135 : gimplify_save_expr (tp, pre_p, NULL);
16897 : else
16898 644 : *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false);
16899 : /* Reference to pointer conversion is considered useless,
16900 : but is significant for firstprivate clause. Force it
16901 : here. */
16902 779 : if (type
16903 687 : && TREE_CODE (type) == POINTER_TYPE
16904 869 : && TREE_CODE (TREE_TYPE (*tp)) == REFERENCE_TYPE)
16905 : {
16906 2 : tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
16907 2 : tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, *tp);
16908 2 : gimplify_and_add (m, pre_p);
16909 2 : *tp = v;
16910 : }
16911 :
16912 779 : tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
16913 779 : OMP_CLAUSE_DECL (c) = *tp;
16914 779 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (orig_for_stmt);
16915 779 : OMP_FOR_CLAUSES (orig_for_stmt) = c;
16916 : }
16917 :
16918 : /* Helper function of gimplify_omp_for, find OMP_ORDERED with
16919 : null OMP_ORDERED_BODY inside of OMP_FOR's body. */
16920 :
16921 : static tree
16922 16496 : find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
16923 : {
16924 16496 : switch (TREE_CODE (*tp))
16925 : {
16926 901 : case OMP_ORDERED:
16927 901 : if (OMP_ORDERED_BODY (*tp) == NULL_TREE)
16928 531 : return *tp;
16929 : break;
16930 23 : case OMP_SIMD:
16931 23 : case OMP_PARALLEL:
16932 23 : case OMP_TARGET:
16933 23 : *walk_subtrees = 0;
16934 23 : break;
16935 : default:
16936 : break;
16937 : }
16938 : return NULL_TREE;
16939 : }
16940 :
16941 : /* Gimplify standalone loop transforming directive which has the
16942 : transformations applied already. So, all that is needed is gimplify
16943 : the remaining loops as normal loops. */
16944 :
16945 : static enum gimplify_status
16946 2266 : gimplify_omp_loop_xform (tree *expr_p, gimple_seq *pre_p)
16947 : {
16948 2266 : tree for_stmt = *expr_p;
16949 :
16950 2266 : if (OMP_FOR_PRE_BODY (for_stmt))
16951 759 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), pre_p);
16952 :
16953 2266 : gimple_seq pre_body = NULL, post_body = NULL;
16954 5207 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16955 : {
16956 2941 : if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE)
16957 1707 : continue;
16958 1285 : tree iters = NULL_TREE;
16959 1285 : if (i == 0
16960 828 : && TREE_CODE (for_stmt) == OMP_UNROLL
16961 1775 : && !omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_PARTIAL))
16962 : {
16963 313 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL))
16964 270 : iters = omp_loop_number_of_iterations (for_stmt, 0, NULL);
16965 : else
16966 43 : iters = build_int_cst (integer_type_node, 8);
16967 : }
16968 1285 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
16969 1285 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
16970 1285 : tree decl = TREE_OPERAND (t, 0);
16971 1285 : gcc_assert (DECL_P (decl));
16972 1285 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
16973 : || POINTER_TYPE_P (TREE_TYPE (decl)));
16974 1285 : if (DECL_ARTIFICIAL (decl)
16975 876 : && TREE_PRIVATE (t)
16976 867 : && gimplify_omp_ctxp
16977 1615 : && gimplify_omp_ctxp->region_type != ORT_NONE)
16978 : {
16979 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16980 504 : do
16981 : {
16982 504 : splay_tree_node n
16983 504 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16984 504 : if (n != NULL)
16985 : break;
16986 346 : else if (ctx->region_type != ORT_WORKSHARE
16987 : && ctx->region_type != ORT_TASKGROUP
16988 62 : && ctx->region_type != ORT_SIMD
16989 38 : && ctx->region_type != ORT_ACC
16990 38 : && !(ctx->region_type & ORT_TARGET_DATA))
16991 : {
16992 38 : omp_add_variable (ctx, decl, GOVD_PRIVATE);
16993 38 : break;
16994 : }
16995 308 : ctx = ctx->outer_context;
16996 : }
16997 308 : while (ctx);
16998 : }
16999 1285 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17000 : {
17001 23 : gcc_assert (seen_error ());
17002 23 : continue;
17003 : }
17004 1262 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
17005 : fb_rvalue);
17006 1262 : gimplify_and_add (t, &pre_body);
17007 1262 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17008 1262 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17009 1262 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17010 : {
17011 28 : gcc_assert (seen_error ());
17012 28 : continue;
17013 : }
17014 1234 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
17015 : fb_rvalue);
17016 1234 : tree l1 = create_artificial_label (UNKNOWN_LOCATION);
17017 1234 : tree l2 = create_artificial_label (UNKNOWN_LOCATION);
17018 1234 : tree l3 = create_artificial_label (UNKNOWN_LOCATION);
17019 1234 : gimplify_seq_add_stmt (&pre_body, gimple_build_goto (l2));
17020 1234 : gimplify_seq_add_stmt (&pre_body, gimple_build_label (l1));
17021 1234 : gimple_seq this_post_body = NULL;
17022 1234 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17023 1234 : if (TREE_CODE (t) == MODIFY_EXPR)
17024 : {
17025 977 : t = TREE_OPERAND (t, 1);
17026 977 : if (TREE_CODE (t) == PLUS_EXPR
17027 977 : && TREE_OPERAND (t, 1) == decl)
17028 : {
17029 0 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
17030 0 : TREE_OPERAND (t, 0) = decl;
17031 : }
17032 977 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
17033 : fb_rvalue);
17034 : }
17035 1234 : gimplify_and_add (TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i),
17036 : &this_post_body);
17037 1234 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l2));
17038 1234 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17039 1234 : gcond *cond = NULL;
17040 1234 : tree d = decl;
17041 1234 : gimplify_expr (&d, &this_post_body, NULL, is_gimple_val, fb_rvalue);
17042 1234 : if (iters && tree_fits_uhwi_p (iters))
17043 : {
17044 301 : unsigned HOST_WIDE_INT niters = tree_to_uhwi (iters);
17045 301 : if ((unsigned HOST_WIDE_INT) (int) niters == niters
17046 301 : && (int) niters > 0)
17047 : {
17048 301 : t = build2 (TREE_CODE (t), boolean_type_node, d,
17049 301 : TREE_OPERAND (t, 1));
17050 301 : t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t,
17051 : build_int_cst (integer_type_node,
17052 : annot_expr_unroll_kind),
17053 301 : build_int_cst (integer_type_node, niters));
17054 301 : gimplify_expr (&t, &this_post_body, NULL, is_gimple_val,
17055 : fb_rvalue);
17056 301 : cond = gimple_build_cond (NE_EXPR, t, boolean_false_node,
17057 : l1, l3);
17058 : }
17059 : }
17060 301 : if (cond == NULL)
17061 933 : cond = gimple_build_cond (TREE_CODE (t), d, TREE_OPERAND (t, 1),
17062 : l1, l3);
17063 1234 : gimplify_seq_add_stmt (&this_post_body, cond);
17064 1234 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l3));
17065 1234 : gimplify_seq_add_seq (&this_post_body, post_body);
17066 1234 : post_body = this_post_body;
17067 : }
17068 2266 : gimplify_seq_add_seq (pre_p, pre_body);
17069 2266 : gimplify_and_add (OMP_FOR_BODY (for_stmt), pre_p);
17070 2266 : gimplify_seq_add_seq (pre_p, post_body);
17071 :
17072 2266 : *expr_p = NULL_TREE;
17073 2266 : return GS_ALL_DONE;
17074 : }
17075 :
17076 : /* Gimplify the gross structure of an OMP_FOR statement. */
17077 :
17078 : static enum gimplify_status
17079 58346 : gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
17080 : {
17081 58346 : tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t;
17082 58346 : enum gimplify_status ret = GS_ALL_DONE;
17083 58346 : enum gimplify_status tret;
17084 58346 : gomp_for *gfor;
17085 58346 : gimple_seq for_body, for_pre_body;
17086 58346 : int i;
17087 58346 : bitmap has_decl_expr = NULL;
17088 58346 : enum omp_region_type ort = ORT_WORKSHARE;
17089 58346 : bool openacc = TREE_CODE (*expr_p) == OACC_LOOP;
17090 :
17091 58346 : orig_for_stmt = for_stmt = *expr_p;
17092 :
17093 58346 : bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND)
17094 58346 : != NULL_TREE);
17095 58417 : while (OMP_FOR_INIT (for_stmt) == NULL_TREE)
17096 : {
17097 17794 : tree *data[4] = { NULL, NULL, NULL, NULL };
17098 17794 : gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
17099 17794 : inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt),
17100 : find_combined_omp_for, data, NULL);
17101 17794 : if (inner_for_stmt == NULL_TREE)
17102 : {
17103 36 : gcc_assert (seen_error ());
17104 36 : *expr_p = NULL_TREE;
17105 3748 : return GS_ERROR;
17106 : }
17107 17758 : gcc_assert (inner_for_stmt == *data[3]);
17108 17758 : omp_maybe_apply_loop_xforms (data[3],
17109 17758 : data[2]
17110 4281 : ? OMP_FOR_CLAUSES (*data[2])
17111 13477 : : TREE_CODE (for_stmt) == OMP_FOR
17112 13477 : ? OMP_FOR_CLAUSES (for_stmt)
17113 : : NULL_TREE);
17114 17758 : if (inner_for_stmt != *data[3])
17115 71 : continue;
17116 17687 : if (data[2] && OMP_FOR_PRE_BODY (*data[2]))
17117 : {
17118 2 : append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]),
17119 : &OMP_FOR_PRE_BODY (for_stmt));
17120 2 : OMP_FOR_PRE_BODY (*data[2]) = NULL_TREE;
17121 : }
17122 17687 : if (OMP_FOR_PRE_BODY (inner_for_stmt))
17123 : {
17124 7231 : append_to_statement_list_force (OMP_FOR_PRE_BODY (inner_for_stmt),
17125 : &OMP_FOR_PRE_BODY (for_stmt));
17126 7231 : OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
17127 : }
17128 :
17129 17687 : if (data[0])
17130 : {
17131 : /* We have some statements or variable declarations in between
17132 : the composite construct directives. Move them around the
17133 : inner_for_stmt. */
17134 3712 : data[0] = expr_p;
17135 14848 : for (i = 0; i < 3; i++)
17136 11136 : if (data[i])
17137 : {
17138 7034 : tree t = *data[i];
17139 7034 : if (i < 2 && data[i + 1] == &OMP_BODY (t))
17140 1005 : data[i + 1] = data[i];
17141 7034 : *data[i] = OMP_BODY (t);
17142 7034 : tree body = build3 (BIND_EXPR, void_type_node, NULL_TREE,
17143 : NULL_TREE, make_node (BLOCK));
17144 7034 : OMP_BODY (t) = body;
17145 7034 : append_to_statement_list_force (inner_for_stmt,
17146 : &BIND_EXPR_BODY (body));
17147 7034 : *data[3] = t;
17148 7034 : data[3] = tsi_stmt_ptr (tsi_start (BIND_EXPR_BODY (body)));
17149 7034 : gcc_assert (*data[3] == inner_for_stmt);
17150 : }
17151 : return GS_OK;
17152 : }
17153 :
17154 36832 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17155 22857 : if (!loop_p
17156 21976 : && OMP_FOR_ORIG_DECLS (inner_for_stmt)
17157 11134 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17158 : i)) == TREE_LIST
17159 22925 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17160 : i)))
17161 : {
17162 40 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17163 : /* Class iterators aren't allowed on OMP_SIMD, so the only
17164 : case we need to solve is distribute parallel for. They are
17165 : allowed on the loop construct, but that is already handled
17166 : in gimplify_omp_loop. */
17167 40 : gcc_assert (TREE_CODE (inner_for_stmt) == OMP_FOR
17168 : && TREE_CODE (for_stmt) == OMP_DISTRIBUTE
17169 : && data[1]);
17170 40 : tree orig_decl = TREE_PURPOSE (orig);
17171 40 : tree last = TREE_VALUE (orig);
17172 40 : tree *pc;
17173 40 : for (pc = &OMP_FOR_CLAUSES (inner_for_stmt);
17174 74 : *pc; pc = &OMP_CLAUSE_CHAIN (*pc))
17175 42 : if ((OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE
17176 35 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE)
17177 43 : && OMP_CLAUSE_DECL (*pc) == orig_decl)
17178 : break;
17179 40 : if (*pc == NULL_TREE)
17180 : {
17181 32 : tree *spc;
17182 32 : for (spc = &OMP_PARALLEL_CLAUSES (*data[1]);
17183 98 : *spc; spc = &OMP_CLAUSE_CHAIN (*spc))
17184 67 : if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE
17185 67 : && OMP_CLAUSE_DECL (*spc) == orig_decl)
17186 : break;
17187 32 : if (*spc)
17188 : {
17189 1 : tree c = *spc;
17190 1 : *spc = OMP_CLAUSE_CHAIN (c);
17191 1 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
17192 1 : *pc = c;
17193 : }
17194 : }
17195 40 : if (*pc == NULL_TREE)
17196 : ;
17197 9 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE)
17198 : {
17199 : /* private clause will appear only on inner_for_stmt.
17200 : Change it into firstprivate, and add private clause
17201 : on for_stmt. */
17202 8 : tree c = copy_node (*pc);
17203 8 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17204 8 : OMP_FOR_CLAUSES (for_stmt) = c;
17205 8 : OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE;
17206 8 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17207 : }
17208 : else
17209 : {
17210 : /* lastprivate clause will appear on both inner_for_stmt
17211 : and for_stmt. Add firstprivate clause to
17212 : inner_for_stmt. */
17213 1 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (*pc),
17214 : OMP_CLAUSE_FIRSTPRIVATE);
17215 1 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc);
17216 1 : OMP_CLAUSE_CHAIN (c) = *pc;
17217 1 : *pc = c;
17218 1 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17219 : }
17220 40 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17221 : OMP_CLAUSE_FIRSTPRIVATE);
17222 40 : OMP_CLAUSE_DECL (c) = last;
17223 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17224 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17225 40 : c = build_omp_clause (UNKNOWN_LOCATION,
17226 40 : *pc ? OMP_CLAUSE_SHARED
17227 : : OMP_CLAUSE_FIRSTPRIVATE);
17228 40 : OMP_CLAUSE_DECL (c) = orig_decl;
17229 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17230 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17231 : }
17232 : /* Similarly, take care of C++ range for temporaries, those should
17233 : be firstprivate on OMP_PARALLEL if any. */
17234 13975 : if (data[1])
17235 17575 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17236 11144 : if (OMP_FOR_ORIG_DECLS (inner_for_stmt)
17237 5763 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17238 : i)) == TREE_LIST
17239 11220 : && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17240 : i)))
17241 : {
17242 49 : tree orig
17243 49 : = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17244 49 : tree v = TREE_CHAIN (orig);
17245 49 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17246 : OMP_CLAUSE_FIRSTPRIVATE);
17247 : /* First add firstprivate clause for the __for_end artificial
17248 : decl. */
17249 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 1);
17250 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17251 : == REFERENCE_TYPE)
17252 0 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17253 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17254 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17255 49 : if (TREE_VEC_ELT (v, 0))
17256 : {
17257 : /* And now the same for __for_range artificial decl if it
17258 : exists. */
17259 49 : c = build_omp_clause (UNKNOWN_LOCATION,
17260 : OMP_CLAUSE_FIRSTPRIVATE);
17261 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 0);
17262 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17263 : == REFERENCE_TYPE)
17264 49 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17265 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17266 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17267 : }
17268 : }
17269 13975 : break;
17270 : }
17271 54598 : if (OMP_FOR_INIT (for_stmt) != NULL_TREE)
17272 : {
17273 40623 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
17274 40623 : if (*expr_p != for_stmt)
17275 : return GS_OK;
17276 : }
17277 :
17278 53716 : switch (TREE_CODE (for_stmt))
17279 : {
17280 18288 : case OMP_FOR:
17281 30594 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17282 : {
17283 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17284 : OMP_CLAUSE_SCHEDULE))
17285 47 : error_at (EXPR_LOCATION (for_stmt),
17286 : "%qs clause may not appear on non-rectangular %qs",
17287 27 : "schedule", lang_GNU_Fortran () ? "do" : "for");
17288 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED))
17289 34 : error_at (EXPR_LOCATION (for_stmt),
17290 : "%qs clause may not appear on non-rectangular %qs",
17291 18 : "ordered", lang_GNU_Fortran () ? "do" : "for");
17292 : }
17293 : break;
17294 8287 : case OMP_DISTRIBUTE:
17295 9230 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)
17296 8287 : && omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17297 : OMP_CLAUSE_DIST_SCHEDULE))
17298 29 : error_at (EXPR_LOCATION (for_stmt),
17299 : "%qs clause may not appear on non-rectangular %qs",
17300 : "dist_schedule", "distribute");
17301 : break;
17302 : case OACC_LOOP:
17303 : ort = ORT_ACC;
17304 : break;
17305 1586 : case OMP_TASKLOOP:
17306 2523 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17307 : {
17308 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17309 : OMP_CLAUSE_GRAINSIZE))
17310 11 : error_at (EXPR_LOCATION (for_stmt),
17311 : "%qs clause may not appear on non-rectangular %qs",
17312 : "grainsize", "taskloop");
17313 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17314 : OMP_CLAUSE_NUM_TASKS))
17315 6 : error_at (EXPR_LOCATION (for_stmt),
17316 : "%qs clause may not appear on non-rectangular %qs",
17317 : "num_tasks", "taskloop");
17318 : }
17319 1586 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED))
17320 : ort = ORT_UNTIED_TASKLOOP;
17321 : else
17322 : ort = ORT_TASKLOOP;
17323 : break;
17324 10737 : case OMP_SIMD:
17325 10737 : ort = ORT_SIMD;
17326 10737 : break;
17327 2266 : case OMP_TILE:
17328 2266 : case OMP_UNROLL:
17329 2266 : gcc_assert (inner_for_stmt == NULL_TREE);
17330 2266 : return gimplify_omp_loop_xform (expr_p, pre_p);
17331 0 : default:
17332 0 : gcc_unreachable ();
17333 : }
17334 :
17335 : /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear
17336 : clause for the IV. */
17337 10784 : if (ort == ORT_SIMD && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17338 : {
17339 7909 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0);
17340 7909 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17341 7909 : decl = TREE_OPERAND (t, 0);
17342 18756 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
17343 11981 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17344 11981 : && OMP_CLAUSE_DECL (c) == decl)
17345 : {
17346 1134 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17347 1134 : break;
17348 : }
17349 : }
17350 :
17351 51450 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP)
17352 51774 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort,
17353 1910 : loop_p && TREE_CODE (for_stmt) != OMP_SIMD
17354 : ? OMP_LOOP : TREE_CODE (for_stmt));
17355 :
17356 51450 : if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE)
17357 8287 : gimplify_omp_ctxp->distribute = true;
17358 :
17359 : /* Handle OMP_FOR_INIT. */
17360 51450 : for_pre_body = NULL;
17361 51450 : if ((ort == ORT_SIMD
17362 40713 : || (inner_for_stmt && TREE_CODE (inner_for_stmt) == OMP_SIMD))
17363 62205 : && OMP_FOR_PRE_BODY (for_stmt))
17364 : {
17365 6848 : has_decl_expr = BITMAP_ALLOC (NULL);
17366 6848 : if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR
17367 6848 : && VAR_P (DECL_EXPR_DECL (OMP_FOR_PRE_BODY (for_stmt))))
17368 : {
17369 18 : t = OMP_FOR_PRE_BODY (for_stmt);
17370 18 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17371 : }
17372 6830 : else if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == STATEMENT_LIST)
17373 : {
17374 6828 : tree_stmt_iterator si;
17375 11362 : for (si = tsi_start (OMP_FOR_PRE_BODY (for_stmt)); !tsi_end_p (si);
17376 4534 : tsi_next (&si))
17377 : {
17378 4534 : t = tsi_stmt (si);
17379 4534 : if (TREE_CODE (t) == DECL_EXPR
17380 4534 : && VAR_P (DECL_EXPR_DECL (t)))
17381 4461 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17382 : }
17383 : }
17384 : }
17385 51450 : if (OMP_FOR_PRE_BODY (for_stmt))
17386 : {
17387 21133 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp)
17388 20408 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17389 : else
17390 : {
17391 725 : struct gimplify_omp_ctx ctx;
17392 725 : memset (&ctx, 0, sizeof (ctx));
17393 725 : ctx.region_type = ORT_NONE;
17394 725 : gimplify_omp_ctxp = &ctx;
17395 725 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17396 725 : gimplify_omp_ctxp = NULL;
17397 : }
17398 : }
17399 51450 : OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
17400 :
17401 51450 : if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
17402 13975 : for_stmt = inner_for_stmt;
17403 :
17404 : /* For taskloop, need to gimplify the start, end and step before the
17405 : taskloop, outside of the taskloop omp context. */
17406 51450 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17407 : {
17408 3458 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17409 : {
17410 1872 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17411 1872 : gimple_seq *for_pre_p = (gimple_seq_empty_p (for_pre_body)
17412 1872 : ? pre_p : &for_pre_body);
17413 1872 : tree type = TREE_TYPE (TREE_OPERAND (t, 0));
17414 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17415 : {
17416 34 : tree v = TREE_OPERAND (t, 1);
17417 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17418 : for_pre_p, orig_for_stmt);
17419 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17420 : for_pre_p, orig_for_stmt);
17421 : }
17422 : else
17423 1838 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17424 : orig_for_stmt);
17425 :
17426 : /* Handle OMP_FOR_COND. */
17427 1872 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17428 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17429 : {
17430 31 : tree v = TREE_OPERAND (t, 1);
17431 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17432 : for_pre_p, orig_for_stmt);
17433 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17434 : for_pre_p, orig_for_stmt);
17435 : }
17436 : else
17437 1841 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17438 : orig_for_stmt);
17439 :
17440 : /* Handle OMP_FOR_INCR. */
17441 1872 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17442 1872 : if (TREE_CODE (t) == MODIFY_EXPR)
17443 : {
17444 590 : decl = TREE_OPERAND (t, 0);
17445 590 : t = TREE_OPERAND (t, 1);
17446 590 : tree *tp = &TREE_OPERAND (t, 1);
17447 590 : if (TREE_CODE (t) == PLUS_EXPR && *tp == decl)
17448 22 : tp = &TREE_OPERAND (t, 0);
17449 :
17450 590 : gimplify_omp_taskloop_expr (NULL_TREE, tp, for_pre_p,
17451 : orig_for_stmt);
17452 : }
17453 : }
17454 :
17455 1586 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort,
17456 : OMP_TASKLOOP);
17457 : }
17458 :
17459 51450 : if (orig_for_stmt != for_stmt)
17460 13975 : gimplify_omp_ctxp->combined_loop = true;
17461 :
17462 51450 : for_body = NULL;
17463 51450 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17464 : == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
17465 51450 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17466 : == TREE_VEC_LENGTH (OMP_FOR_INCR (for_stmt)));
17467 :
17468 51450 : tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
17469 51450 : bool is_doacross = false;
17470 51450 : if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
17471 : find_standalone_omp_ordered, NULL))
17472 : {
17473 531 : OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
17474 531 : is_doacross = true;
17475 531 : int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
17476 531 : gimplify_omp_ctxp->loop_iter_var.create (len * 2);
17477 2200 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
17478 1669 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
17479 : {
17480 10 : error_at (OMP_CLAUSE_LOCATION (*pc),
17481 : "%<linear%> clause may not be specified together "
17482 : "with %<ordered%> clause if stand-alone %<ordered%> "
17483 : "construct is nested in it");
17484 10 : *pc = OMP_CLAUSE_CHAIN (*pc);
17485 : }
17486 : else
17487 1659 : pc = &OMP_CLAUSE_CHAIN (*pc);
17488 : }
17489 51450 : int collapse = 1, tile = 0;
17490 51450 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
17491 51450 : if (c)
17492 13727 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
17493 51450 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
17494 51450 : if (c)
17495 384 : tile = list_length (OMP_CLAUSE_TILE_LIST (c));
17496 51450 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
17497 51450 : hash_set<tree> *allocate_uids = NULL;
17498 51450 : if (c)
17499 : {
17500 275 : allocate_uids = new hash_set<tree>;
17501 1682 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17502 1132 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
17503 478 : allocate_uids->add (OMP_CLAUSE_DECL (c));
17504 : }
17505 124646 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17506 : {
17507 73196 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17508 73196 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17509 73196 : decl = TREE_OPERAND (t, 0);
17510 73196 : gcc_assert (DECL_P (decl));
17511 73196 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
17512 : || POINTER_TYPE_P (TREE_TYPE (decl)));
17513 73196 : if (is_doacross)
17514 : {
17515 1654 : if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt))
17516 : {
17517 960 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17518 960 : if (TREE_CODE (orig_decl) == TREE_LIST)
17519 : {
17520 15 : orig_decl = TREE_PURPOSE (orig_decl);
17521 15 : if (!orig_decl)
17522 0 : orig_decl = decl;
17523 : }
17524 960 : gimplify_omp_ctxp->loop_iter_var.quick_push (orig_decl);
17525 : }
17526 : else
17527 694 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17528 1654 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17529 : }
17530 :
17531 73196 : if (for_stmt == orig_for_stmt)
17532 : {
17533 50339 : tree orig_decl = decl;
17534 50339 : if (OMP_FOR_ORIG_DECLS (for_stmt))
17535 : {
17536 24054 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17537 24054 : if (TREE_CODE (orig_decl) == TREE_LIST)
17538 : {
17539 : orig_decl = TREE_PURPOSE (orig_decl);
17540 : if (!orig_decl)
17541 : orig_decl = decl;
17542 : }
17543 : }
17544 50339 : if (is_global_var (orig_decl) && DECL_THREAD_LOCAL_P (orig_decl))
17545 36 : error_at (EXPR_LOCATION (for_stmt),
17546 : "threadprivate iteration variable %qD", orig_decl);
17547 : }
17548 :
17549 : /* Make sure the iteration variable is private. */
17550 73196 : tree c = NULL_TREE;
17551 73196 : tree c2 = NULL_TREE;
17552 73196 : if (orig_for_stmt != for_stmt)
17553 : {
17554 : /* Preserve this information until we gimplify the inner simd. */
17555 22857 : if (has_decl_expr
17556 22857 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17557 3421 : TREE_PRIVATE (t) = 1;
17558 : }
17559 50339 : else if (ort == ORT_SIMD)
17560 : {
17561 15810 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17562 : (splay_tree_key) decl);
17563 15810 : omp_is_private (gimplify_omp_ctxp, decl,
17564 15810 : 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17565 : != 1));
17566 15810 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
17567 : {
17568 2538 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17569 2538 : if (n->value & GOVD_LASTPRIVATE_CONDITIONAL)
17570 0 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17571 : OMP_CLAUSE_LASTPRIVATE);
17572 0 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17573 : OMP_CLAUSE_LASTPRIVATE))
17574 0 : if (OMP_CLAUSE_DECL (c3) == decl)
17575 : {
17576 0 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17577 : "conditional %<lastprivate%> on loop "
17578 : "iterator %qD ignored", decl);
17579 0 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17580 0 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17581 : }
17582 : }
17583 13272 : else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1 && !loop_p)
17584 : {
17585 5701 : c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17586 5701 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17587 5701 : unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN;
17588 5701 : if ((has_decl_expr
17589 1365 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17590 6385 : || TREE_PRIVATE (t))
17591 : {
17592 2345 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17593 2345 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17594 : }
17595 5701 : struct gimplify_omp_ctx *outer
17596 5701 : = gimplify_omp_ctxp->outer_context;
17597 5701 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17598 : {
17599 2433 : if (outer->region_type == ORT_WORKSHARE
17600 2193 : && outer->combined_loop)
17601 : {
17602 2142 : n = splay_tree_lookup (outer->variables,
17603 : (splay_tree_key)decl);
17604 2142 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17605 : {
17606 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17607 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17608 : }
17609 : else
17610 : {
17611 2142 : struct gimplify_omp_ctx *octx = outer->outer_context;
17612 2142 : if (octx
17613 1714 : && octx->region_type == ORT_COMBINED_PARALLEL
17614 1476 : && octx->outer_context
17615 1209 : && (octx->outer_context->region_type
17616 : == ORT_WORKSHARE)
17617 1079 : && octx->outer_context->combined_loop)
17618 : {
17619 1079 : octx = octx->outer_context;
17620 1079 : n = splay_tree_lookup (octx->variables,
17621 : (splay_tree_key)decl);
17622 1079 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17623 : {
17624 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17625 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17626 : }
17627 : }
17628 : }
17629 : }
17630 : }
17631 :
17632 5701 : OMP_CLAUSE_DECL (c) = decl;
17633 5701 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17634 5701 : OMP_FOR_CLAUSES (for_stmt) = c;
17635 5701 : omp_add_variable (gimplify_omp_ctxp, decl, flags);
17636 5701 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17637 2433 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17638 : true);
17639 : }
17640 : else
17641 : {
17642 7571 : bool lastprivate
17643 : = (!has_decl_expr
17644 7571 : || !bitmap_bit_p (has_decl_expr, DECL_UID (decl)));
17645 7571 : if (TREE_PRIVATE (t))
17646 1787 : lastprivate = false;
17647 7571 : if (loop_p && OMP_FOR_ORIG_DECLS (for_stmt))
17648 : {
17649 509 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17650 509 : if (TREE_CODE (elt) == TREE_LIST && TREE_PURPOSE (elt))
17651 : lastprivate = false;
17652 : }
17653 :
17654 7571 : struct gimplify_omp_ctx *outer
17655 7571 : = gimplify_omp_ctxp->outer_context;
17656 7571 : if (outer && lastprivate)
17657 4887 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17658 : true);
17659 :
17660 9577 : c = build_omp_clause (input_location,
17661 : lastprivate ? OMP_CLAUSE_LASTPRIVATE
17662 : : OMP_CLAUSE_PRIVATE);
17663 7571 : OMP_CLAUSE_DECL (c) = decl;
17664 7571 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17665 7571 : OMP_FOR_CLAUSES (for_stmt) = c;
17666 7571 : omp_add_variable (gimplify_omp_ctxp, decl,
17667 : (lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE)
17668 : | GOVD_EXPLICIT | GOVD_SEEN);
17669 7571 : c = NULL_TREE;
17670 : }
17671 : }
17672 34529 : else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
17673 : {
17674 8739 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17675 8739 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17676 : (splay_tree_key) decl);
17677 8739 : if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL))
17678 80 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17679 : OMP_CLAUSE_LASTPRIVATE);
17680 80 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17681 : OMP_CLAUSE_LASTPRIVATE))
17682 40 : if (OMP_CLAUSE_DECL (c3) == decl)
17683 : {
17684 40 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17685 : "conditional %<lastprivate%> on loop "
17686 : "iterator %qD ignored", decl);
17687 40 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17688 40 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17689 : }
17690 : }
17691 : else
17692 25790 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
17693 :
17694 : /* If DECL is not a gimple register, create a temporary variable to act
17695 : as an iteration counter. This is valid, since DECL cannot be
17696 : modified in the body of the loop. Similarly for any iteration vars
17697 : in simd with collapse > 1 where the iterator vars must be
17698 : lastprivate. And similarly for vars mentioned in allocate clauses. */
17699 73196 : if (orig_for_stmt != for_stmt)
17700 22857 : var = decl;
17701 50339 : else if (!is_gimple_reg (decl)
17702 47072 : || (ort == ORT_SIMD
17703 14209 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
17704 90341 : || (allocate_uids && allocate_uids->contains (decl)))
17705 : {
17706 10369 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17707 : /* Make sure omp_add_variable is not called on it prematurely.
17708 : We call it ourselves a few lines later. */
17709 10369 : gimplify_omp_ctxp = NULL;
17710 10369 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17711 10369 : gimplify_omp_ctxp = ctx;
17712 10369 : TREE_OPERAND (t, 0) = var;
17713 :
17714 10369 : gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
17715 :
17716 10369 : if (ort == ORT_SIMD
17717 10369 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17718 : {
17719 770 : c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17720 770 : OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1;
17721 770 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1;
17722 770 : OMP_CLAUSE_DECL (c2) = var;
17723 770 : OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt);
17724 770 : OMP_FOR_CLAUSES (for_stmt) = c2;
17725 770 : omp_add_variable (gimplify_omp_ctxp, var,
17726 : GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
17727 770 : if (c == NULL_TREE)
17728 : {
17729 518 : c = c2;
17730 518 : c2 = NULL_TREE;
17731 : }
17732 : }
17733 : else
17734 9599 : omp_add_variable (gimplify_omp_ctxp, var,
17735 : GOVD_PRIVATE | GOVD_SEEN);
17736 : }
17737 : else
17738 : var = decl;
17739 :
17740 73196 : gimplify_omp_ctxp->in_for_exprs = true;
17741 73196 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17742 : {
17743 719 : tree lb = TREE_OPERAND (t, 1);
17744 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL,
17745 : is_gimple_val, fb_rvalue, false);
17746 719 : ret = MIN (ret, tret);
17747 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL,
17748 : is_gimple_val, fb_rvalue, false);
17749 : }
17750 : else
17751 72477 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17752 : is_gimple_val, fb_rvalue, false);
17753 73196 : gimplify_omp_ctxp->in_for_exprs = false;
17754 73196 : ret = MIN (ret, tret);
17755 73196 : if (ret == GS_ERROR)
17756 : return ret;
17757 :
17758 : /* Handle OMP_FOR_COND. */
17759 73196 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17760 73196 : gcc_assert (COMPARISON_CLASS_P (t));
17761 73196 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17762 :
17763 73196 : gimplify_omp_ctxp->in_for_exprs = true;
17764 73196 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17765 : {
17766 599 : tree ub = TREE_OPERAND (t, 1);
17767 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL,
17768 : is_gimple_val, fb_rvalue, false);
17769 599 : ret = MIN (ret, tret);
17770 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL,
17771 : is_gimple_val, fb_rvalue, false);
17772 : }
17773 : else
17774 72597 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17775 : is_gimple_val, fb_rvalue, false);
17776 73196 : gimplify_omp_ctxp->in_for_exprs = false;
17777 73196 : ret = MIN (ret, tret);
17778 :
17779 : /* Handle OMP_FOR_INCR. */
17780 73196 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17781 73196 : switch (TREE_CODE (t))
17782 : {
17783 35884 : case PREINCREMENT_EXPR:
17784 35884 : case POSTINCREMENT_EXPR:
17785 35884 : {
17786 35884 : tree decl = TREE_OPERAND (t, 0);
17787 : /* c_omp_for_incr_canonicalize_ptr() should have been
17788 : called to massage things appropriately. */
17789 35884 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17790 :
17791 35884 : if (orig_for_stmt != for_stmt)
17792 : break;
17793 25461 : t = build_int_cst (TREE_TYPE (decl), 1);
17794 25461 : if (c)
17795 4534 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17796 25461 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17797 25461 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17798 25461 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17799 25461 : break;
17800 : }
17801 :
17802 3830 : case PREDECREMENT_EXPR:
17803 3830 : case POSTDECREMENT_EXPR:
17804 : /* c_omp_for_incr_canonicalize_ptr() should have been
17805 : called to massage things appropriately. */
17806 3830 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17807 3830 : if (orig_for_stmt != for_stmt)
17808 : break;
17809 1992 : t = build_int_cst (TREE_TYPE (decl), -1);
17810 1992 : if (c)
17811 112 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17812 1992 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17813 1992 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17814 1992 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17815 1992 : break;
17816 :
17817 33482 : case MODIFY_EXPR:
17818 33482 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17819 33482 : TREE_OPERAND (t, 0) = var;
17820 :
17821 33482 : t = TREE_OPERAND (t, 1);
17822 33482 : switch (TREE_CODE (t))
17823 : {
17824 26550 : case PLUS_EXPR:
17825 26550 : if (TREE_OPERAND (t, 1) == decl)
17826 : {
17827 215 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
17828 215 : TREE_OPERAND (t, 0) = var;
17829 215 : break;
17830 : }
17831 :
17832 : /* Fallthru. */
17833 33267 : case MINUS_EXPR:
17834 33267 : case POINTER_PLUS_EXPR:
17835 33267 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17836 33267 : TREE_OPERAND (t, 0) = var;
17837 33267 : break;
17838 0 : default:
17839 0 : gcc_unreachable ();
17840 : }
17841 :
17842 33482 : gimplify_omp_ctxp->in_for_exprs = true;
17843 33482 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17844 : is_gimple_val, fb_rvalue, false);
17845 33482 : ret = MIN (ret, tret);
17846 33482 : if (c)
17847 : {
17848 1573 : tree step = TREE_OPERAND (t, 1);
17849 1573 : tree stept = TREE_TYPE (decl);
17850 1573 : if (POINTER_TYPE_P (stept))
17851 280 : stept = sizetype;
17852 1573 : step = fold_convert (stept, step);
17853 1573 : if (TREE_CODE (t) == MINUS_EXPR)
17854 295 : step = fold_build1 (NEGATE_EXPR, stept, step);
17855 1573 : OMP_CLAUSE_LINEAR_STEP (c) = step;
17856 1573 : if (step != TREE_OPERAND (t, 1))
17857 : {
17858 295 : tret = gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c),
17859 : &for_pre_body, NULL,
17860 : is_gimple_val, fb_rvalue, false);
17861 295 : ret = MIN (ret, tret);
17862 : }
17863 : }
17864 33482 : gimplify_omp_ctxp->in_for_exprs = false;
17865 33482 : break;
17866 :
17867 0 : default:
17868 0 : gcc_unreachable ();
17869 : }
17870 :
17871 73196 : if (c2)
17872 : {
17873 252 : gcc_assert (c);
17874 252 : OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
17875 : }
17876 :
17877 73196 : if ((var != decl || collapse > 1 || tile) && orig_for_stmt == for_stmt)
17878 : {
17879 86698 : for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
17880 65136 : if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
17881 16218 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
17882 56127 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17883 2159 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)
17884 1373 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
17885 75496 : && OMP_CLAUSE_DECL (c) == decl)
17886 : {
17887 7535 : if (is_doacross && (collapse == 1 || i >= collapse))
17888 : t = var;
17889 : else
17890 : {
17891 7462 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17892 7462 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17893 7462 : gcc_assert (TREE_OPERAND (t, 0) == var);
17894 7462 : t = TREE_OPERAND (t, 1);
17895 7462 : gcc_assert (TREE_CODE (t) == PLUS_EXPR
17896 : || TREE_CODE (t) == MINUS_EXPR
17897 : || TREE_CODE (t) == POINTER_PLUS_EXPR);
17898 7462 : gcc_assert (TREE_OPERAND (t, 0) == var);
17899 14822 : t = build2 (TREE_CODE (t), TREE_TYPE (decl),
17900 : is_doacross ? var : decl,
17901 7462 : TREE_OPERAND (t, 1));
17902 : }
17903 7535 : gimple_seq *seq;
17904 7535 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
17905 6939 : seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
17906 : else
17907 596 : seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c);
17908 7535 : push_gimplify_context ();
17909 7535 : gimplify_assign (decl, t, seq);
17910 7535 : gimple *bind = NULL;
17911 7535 : if (gimplify_ctxp->temps)
17912 : {
17913 2072 : bind = gimple_build_bind (NULL_TREE, *seq, NULL_TREE);
17914 2072 : *seq = NULL;
17915 2072 : gimplify_seq_add_stmt (seq, bind);
17916 : }
17917 7535 : pop_gimplify_context (bind);
17918 : }
17919 : }
17920 73196 : if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl)
17921 2609 : for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17922 : {
17923 1197 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17924 1197 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17925 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17926 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17927 336 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17928 1197 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17929 1197 : gcc_assert (COMPARISON_CLASS_P (t));
17930 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17931 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17932 343 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17933 : }
17934 : }
17935 :
17936 51450 : BITMAP_FREE (has_decl_expr);
17937 51725 : delete allocate_uids;
17938 :
17939 51450 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17940 49864 : || (loop_p && orig_for_stmt == for_stmt))
17941 : {
17942 2642 : push_gimplify_context ();
17943 2642 : if (TREE_CODE (OMP_FOR_BODY (orig_for_stmt)) != BIND_EXPR)
17944 : {
17945 1891 : OMP_FOR_BODY (orig_for_stmt)
17946 1891 : = build3 (BIND_EXPR, void_type_node, NULL,
17947 1891 : OMP_FOR_BODY (orig_for_stmt), NULL);
17948 1891 : TREE_SIDE_EFFECTS (OMP_FOR_BODY (orig_for_stmt)) = 1;
17949 : }
17950 : }
17951 :
17952 51450 : gimple *g = gimplify_and_return_first (OMP_FOR_BODY (orig_for_stmt),
17953 : &for_body);
17954 :
17955 51450 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17956 49864 : || (loop_p && orig_for_stmt == for_stmt))
17957 : {
17958 2642 : if (gimple_code (g) == GIMPLE_BIND)
17959 2642 : pop_gimplify_context (g);
17960 : else
17961 0 : pop_gimplify_context (NULL);
17962 : }
17963 :
17964 51450 : if (orig_for_stmt != for_stmt)
17965 36832 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17966 : {
17967 22857 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17968 22857 : decl = TREE_OPERAND (t, 0);
17969 22857 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17970 22857 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17971 772 : gimplify_omp_ctxp = ctx->outer_context;
17972 22857 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17973 22857 : gimplify_omp_ctxp = ctx;
17974 22857 : omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
17975 22857 : TREE_OPERAND (t, 0) = var;
17976 22857 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17977 22857 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17978 22857 : TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
17979 22857 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
17980 791 : for (int j = i + 1;
17981 791 : j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17982 : {
17983 377 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17984 377 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17985 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17986 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17987 : {
17988 133 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17989 133 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17990 : }
17991 377 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17992 377 : gcc_assert (COMPARISON_CLASS_P (t));
17993 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17994 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17995 : {
17996 67 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17997 67 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17998 : }
17999 : }
18000 : }
18001 :
18002 51450 : gimplify_adjust_omp_clauses (pre_p, for_body,
18003 : &OMP_FOR_CLAUSES (orig_for_stmt),
18004 51450 : TREE_CODE (orig_for_stmt));
18005 :
18006 51450 : int kind;
18007 51450 : switch (TREE_CODE (orig_for_stmt))
18008 : {
18009 : case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
18010 10737 : case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
18011 8287 : case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
18012 1586 : case OMP_TASKLOOP: kind = GF_OMP_FOR_KIND_TASKLOOP; break;
18013 12552 : case OACC_LOOP: kind = GF_OMP_FOR_KIND_OACC_LOOP; break;
18014 0 : default:
18015 0 : gcc_unreachable ();
18016 : }
18017 51450 : if (loop_p && kind == GF_OMP_FOR_KIND_SIMD)
18018 : {
18019 1056 : gimplify_seq_add_seq (pre_p, for_pre_body);
18020 1056 : for_pre_body = NULL;
18021 : }
18022 51450 : gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
18023 51450 : TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
18024 : for_pre_body);
18025 51450 : if (orig_for_stmt != for_stmt)
18026 13975 : gimple_omp_for_set_combined_p (gfor, true);
18027 51450 : if (gimplify_omp_ctxp
18028 42705 : && (gimplify_omp_ctxp->combined_loop
18029 35161 : || (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
18030 12347 : && gimplify_omp_ctxp->outer_context
18031 7895 : && gimplify_omp_ctxp->outer_context->combined_loop)))
18032 : {
18033 13975 : gimple_omp_for_set_combined_into_p (gfor, true);
18034 13975 : if (gimplify_omp_ctxp->combined_loop)
18035 7544 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_SIMD);
18036 : else
18037 6431 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_FOR);
18038 : }
18039 :
18040 124646 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18041 : {
18042 73196 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
18043 73196 : gimple_omp_for_set_index (gfor, i, TREE_OPERAND (t, 0));
18044 73196 : gimple_omp_for_set_initial (gfor, i, TREE_OPERAND (t, 1));
18045 73196 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
18046 73196 : gimple_omp_for_set_cond (gfor, i, TREE_CODE (t));
18047 73196 : gimple_omp_for_set_final (gfor, i, TREE_OPERAND (t, 1));
18048 73196 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
18049 73196 : gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1));
18050 : }
18051 :
18052 : /* OMP_TASKLOOP is gimplified as two GIMPLE_OMP_FOR taskloop
18053 : constructs with GIMPLE_OMP_TASK sandwiched in between them.
18054 : The outer taskloop stands for computing the number of iterations,
18055 : counts for collapsed loops and holding taskloop specific clauses.
18056 : The task construct stands for the effect of data sharing on the
18057 : explicit task it creates and the inner taskloop stands for expansion
18058 : of the static loop inside of the explicit task construct. */
18059 51450 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
18060 : {
18061 1586 : tree *gfor_clauses_ptr = gimple_omp_for_clauses_ptr (gfor);
18062 1586 : tree task_clauses = NULL_TREE;
18063 1586 : tree c = *gfor_clauses_ptr;
18064 1586 : tree *gtask_clauses_ptr = &task_clauses;
18065 1586 : tree outer_for_clauses = NULL_TREE;
18066 1586 : tree *gforo_clauses_ptr = &outer_for_clauses;
18067 1586 : bitmap lastprivate_uids = NULL;
18068 1586 : if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
18069 : {
18070 36 : c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
18071 36 : if (c)
18072 : {
18073 18 : lastprivate_uids = BITMAP_ALLOC (NULL);
18074 54 : for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
18075 : OMP_CLAUSE_LASTPRIVATE))
18076 18 : bitmap_set_bit (lastprivate_uids,
18077 18 : DECL_UID (OMP_CLAUSE_DECL (c)));
18078 : }
18079 36 : c = *gfor_clauses_ptr;
18080 : }
18081 12254 : for (; c; c = OMP_CLAUSE_CHAIN (c))
18082 10668 : switch (OMP_CLAUSE_CODE (c))
18083 : {
18084 : /* These clauses are allowed on task, move them there. */
18085 6230 : case OMP_CLAUSE_SHARED:
18086 6230 : case OMP_CLAUSE_FIRSTPRIVATE:
18087 6230 : case OMP_CLAUSE_DEFAULT:
18088 6230 : case OMP_CLAUSE_IF:
18089 6230 : case OMP_CLAUSE_UNTIED:
18090 6230 : case OMP_CLAUSE_FINAL:
18091 6230 : case OMP_CLAUSE_MERGEABLE:
18092 6230 : case OMP_CLAUSE_PRIORITY:
18093 6230 : case OMP_CLAUSE_REDUCTION:
18094 6230 : case OMP_CLAUSE_IN_REDUCTION:
18095 6230 : *gtask_clauses_ptr = c;
18096 6230 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18097 6230 : break;
18098 2068 : case OMP_CLAUSE_PRIVATE:
18099 2068 : if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
18100 : {
18101 : /* We want private on outer for and firstprivate
18102 : on task. */
18103 26 : *gtask_clauses_ptr
18104 26 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18105 : OMP_CLAUSE_FIRSTPRIVATE);
18106 26 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18107 26 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
18108 : openacc);
18109 26 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18110 26 : *gforo_clauses_ptr = c;
18111 26 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18112 : }
18113 : else
18114 : {
18115 2042 : *gtask_clauses_ptr = c;
18116 2042 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18117 : }
18118 : break;
18119 : /* These clauses go into outer taskloop clauses. */
18120 533 : case OMP_CLAUSE_GRAINSIZE:
18121 533 : case OMP_CLAUSE_NUM_TASKS:
18122 533 : case OMP_CLAUSE_NOGROUP:
18123 533 : *gforo_clauses_ptr = c;
18124 533 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18125 533 : break;
18126 : /* Collapse clause we duplicate on both taskloops. */
18127 584 : case OMP_CLAUSE_COLLAPSE:
18128 584 : *gfor_clauses_ptr = c;
18129 584 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18130 584 : *gforo_clauses_ptr = copy_node (c);
18131 584 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18132 584 : break;
18133 : /* For lastprivate, keep the clause on inner taskloop, and add
18134 : a shared clause on task. If the same decl is also firstprivate,
18135 : add also firstprivate clause on the inner taskloop. */
18136 1191 : case OMP_CLAUSE_LASTPRIVATE:
18137 1191 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18138 : {
18139 : /* For taskloop C++ lastprivate IVs, we want:
18140 : 1) private on outer taskloop
18141 : 2) firstprivate and shared on task
18142 : 3) lastprivate on inner taskloop */
18143 38 : *gtask_clauses_ptr
18144 38 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18145 : OMP_CLAUSE_FIRSTPRIVATE);
18146 38 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18147 38 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
18148 : openacc);
18149 38 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18150 38 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
18151 38 : *gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18152 : OMP_CLAUSE_PRIVATE);
18153 38 : OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
18154 38 : OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
18155 38 : TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
18156 38 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18157 : }
18158 1191 : *gfor_clauses_ptr = c;
18159 1191 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18160 1191 : *gtask_clauses_ptr
18161 1191 : = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_SHARED);
18162 1191 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18163 1191 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
18164 312 : OMP_CLAUSE_SHARED_FIRSTPRIVATE (*gtask_clauses_ptr) = 1;
18165 1191 : gtask_clauses_ptr
18166 1191 : = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18167 1191 : break;
18168 : /* Allocate clause we duplicate on task and inner taskloop
18169 : if the decl is lastprivate, otherwise just put on task. */
18170 62 : case OMP_CLAUSE_ALLOCATE:
18171 62 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
18172 62 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
18173 : {
18174 : /* Additionally, put firstprivate clause on task
18175 : for the allocator if it is not constant. */
18176 34 : *gtask_clauses_ptr
18177 34 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18178 : OMP_CLAUSE_FIRSTPRIVATE);
18179 34 : OMP_CLAUSE_DECL (*gtask_clauses_ptr)
18180 34 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
18181 34 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18182 : }
18183 62 : if (lastprivate_uids
18184 97 : && bitmap_bit_p (lastprivate_uids,
18185 35 : DECL_UID (OMP_CLAUSE_DECL (c))))
18186 : {
18187 17 : *gfor_clauses_ptr = c;
18188 17 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18189 17 : *gtask_clauses_ptr = copy_node (c);
18190 17 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18191 : }
18192 : else
18193 : {
18194 45 : *gtask_clauses_ptr = c;
18195 45 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18196 : }
18197 : break;
18198 0 : default:
18199 0 : gcc_unreachable ();
18200 : }
18201 1586 : *gfor_clauses_ptr = NULL_TREE;
18202 1586 : *gtask_clauses_ptr = NULL_TREE;
18203 1586 : *gforo_clauses_ptr = NULL_TREE;
18204 1586 : BITMAP_FREE (lastprivate_uids);
18205 1586 : gimple_set_location (gfor, input_location);
18206 1586 : g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
18207 1586 : g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
18208 : NULL_TREE, NULL_TREE, NULL_TREE);
18209 1586 : gimple_set_location (g, input_location);
18210 1586 : gimple_omp_task_set_taskloop_p (g, true);
18211 1586 : g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
18212 1586 : gomp_for *gforo
18213 1586 : = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
18214 : gimple_omp_for_collapse (gfor),
18215 : gimple_omp_for_pre_body (gfor));
18216 1586 : gimple_omp_for_set_pre_body (gfor, NULL);
18217 1586 : gimple_omp_for_set_combined_p (gforo, true);
18218 1586 : gimple_omp_for_set_combined_into_p (gfor, true);
18219 3458 : for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
18220 : {
18221 1872 : tree type = TREE_TYPE (gimple_omp_for_index (gfor, i));
18222 1872 : tree v = create_tmp_var (type);
18223 1872 : gimple_omp_for_set_index (gforo, i, v);
18224 1872 : t = unshare_expr (gimple_omp_for_initial (gfor, i));
18225 1872 : gimple_omp_for_set_initial (gforo, i, t);
18226 1872 : gimple_omp_for_set_cond (gforo, i,
18227 : gimple_omp_for_cond (gfor, i));
18228 1872 : t = unshare_expr (gimple_omp_for_final (gfor, i));
18229 1872 : gimple_omp_for_set_final (gforo, i, t);
18230 1872 : t = unshare_expr (gimple_omp_for_incr (gfor, i));
18231 1872 : gcc_assert (TREE_OPERAND (t, 0) == gimple_omp_for_index (gfor, i));
18232 1872 : TREE_OPERAND (t, 0) = v;
18233 1872 : gimple_omp_for_set_incr (gforo, i, t);
18234 1872 : t = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
18235 1872 : OMP_CLAUSE_DECL (t) = v;
18236 1872 : OMP_CLAUSE_CHAIN (t) = gimple_omp_for_clauses (gforo);
18237 1872 : gimple_omp_for_set_clauses (gforo, t);
18238 1872 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
18239 : {
18240 90 : tree *p1 = NULL, *p2 = NULL;
18241 90 : t = gimple_omp_for_initial (gforo, i);
18242 90 : if (TREE_CODE (t) == TREE_VEC)
18243 34 : p1 = &TREE_VEC_ELT (t, 0);
18244 90 : t = gimple_omp_for_final (gforo, i);
18245 90 : if (TREE_CODE (t) == TREE_VEC)
18246 : {
18247 31 : if (p1)
18248 23 : p2 = &TREE_VEC_ELT (t, 0);
18249 : else
18250 8 : p1 = &TREE_VEC_ELT (t, 0);
18251 : }
18252 90 : if (p1)
18253 : {
18254 : int j;
18255 58 : for (j = 0; j < i; j++)
18256 58 : if (*p1 == gimple_omp_for_index (gfor, j))
18257 : {
18258 42 : *p1 = gimple_omp_for_index (gforo, j);
18259 42 : if (p2)
18260 23 : *p2 = *p1;
18261 : break;
18262 : }
18263 42 : gcc_assert (j < i);
18264 : }
18265 : }
18266 : }
18267 1586 : gimplify_seq_add_stmt (pre_p, gforo);
18268 : }
18269 : else
18270 49864 : gimplify_seq_add_stmt (pre_p, gfor);
18271 :
18272 51450 : if (TREE_CODE (orig_for_stmt) == OMP_FOR)
18273 : {
18274 18288 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
18275 18288 : unsigned lastprivate_conditional = 0;
18276 18288 : while (ctx
18277 18324 : && (ctx->region_type == ORT_TARGET_DATA
18278 14238 : || ctx->region_type == ORT_TASKGROUP))
18279 36 : ctx = ctx->outer_context;
18280 18288 : if (ctx && (ctx->region_type & ORT_PARALLEL) != 0)
18281 13978 : for (tree c = gimple_omp_for_clauses (gfor);
18282 63348 : c; c = OMP_CLAUSE_CHAIN (c))
18283 49370 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18284 49370 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18285 158 : ++lastprivate_conditional;
18286 13978 : if (lastprivate_conditional)
18287 : {
18288 118 : struct omp_for_data fd;
18289 118 : omp_extract_for_data (gfor, &fd, NULL);
18290 118 : tree type = build_array_type_nelts (unsigned_type_for (fd.iter_type),
18291 118 : lastprivate_conditional);
18292 118 : tree var = create_tmp_var_raw (type);
18293 118 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
18294 118 : OMP_CLAUSE_DECL (c) = var;
18295 118 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18296 118 : gimple_omp_for_set_clauses (gfor, c);
18297 118 : omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
18298 : }
18299 : }
18300 33162 : else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
18301 : {
18302 10737 : unsigned lastprivate_conditional = 0;
18303 49350 : for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
18304 38613 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18305 38613 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18306 119 : ++lastprivate_conditional;
18307 10737 : if (lastprivate_conditional)
18308 : {
18309 91 : struct omp_for_data fd;
18310 91 : omp_extract_for_data (gfor, &fd, NULL);
18311 91 : tree type = unsigned_type_for (fd.iter_type);
18312 301 : while (lastprivate_conditional--)
18313 : {
18314 119 : tree c = build_omp_clause (UNKNOWN_LOCATION,
18315 : OMP_CLAUSE__CONDTEMP_);
18316 119 : OMP_CLAUSE_DECL (c) = create_tmp_var (type);
18317 119 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18318 119 : gimple_omp_for_set_clauses (gfor, c);
18319 : }
18320 : }
18321 : }
18322 :
18323 51450 : if (ret != GS_ALL_DONE)
18324 : return GS_ERROR;
18325 51450 : *expr_p = NULL_TREE;
18326 51450 : return GS_ALL_DONE;
18327 : }
18328 :
18329 : /* Helper for gimplify_omp_loop, called through walk_tree. */
18330 :
18331 : static tree
18332 294 : note_no_context_vars (tree *tp, int *, void *data)
18333 : {
18334 294 : if (VAR_P (*tp)
18335 56 : && DECL_CONTEXT (*tp) == NULL_TREE
18336 309 : && !is_global_var (*tp))
18337 : {
18338 15 : vec<tree> *d = (vec<tree> *) data;
18339 15 : d->safe_push (*tp);
18340 15 : DECL_CONTEXT (*tp) = current_function_decl;
18341 : }
18342 294 : return NULL_TREE;
18343 : }
18344 :
18345 : /* Gimplify the gross structure of an OMP_LOOP statement. */
18346 :
18347 : static enum gimplify_status
18348 1056 : gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
18349 : {
18350 1056 : tree for_stmt = *expr_p;
18351 1056 : tree clauses = OMP_FOR_CLAUSES (for_stmt);
18352 1056 : struct gimplify_omp_ctx *octx = gimplify_omp_ctxp;
18353 1056 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18354 1056 : int i;
18355 :
18356 1056 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
18357 1056 : if (*expr_p != for_stmt)
18358 : return GS_OK;
18359 :
18360 : /* If order is not present, the behavior is as if order(concurrent)
18361 : appeared. */
18362 1056 : tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER);
18363 1056 : if (order == NULL_TREE)
18364 : {
18365 799 : order = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_ORDER);
18366 799 : OMP_CLAUSE_CHAIN (order) = clauses;
18367 799 : OMP_FOR_CLAUSES (for_stmt) = clauses = order;
18368 : }
18369 :
18370 1056 : tree bind = omp_find_clause (clauses, OMP_CLAUSE_BIND);
18371 1056 : if (bind == NULL_TREE)
18372 : {
18373 574 : if (!flag_openmp) /* flag_openmp_simd */
18374 : ;
18375 557 : else if (octx && (octx->region_type & ORT_TEAMS) != 0)
18376 : kind = OMP_CLAUSE_BIND_TEAMS;
18377 327 : else if (octx && (octx->region_type & ORT_PARALLEL) != 0)
18378 : kind = OMP_CLAUSE_BIND_PARALLEL;
18379 : else
18380 : {
18381 187 : for (; octx; octx = octx->outer_context)
18382 : {
18383 79 : if ((octx->region_type & ORT_ACC) != 0
18384 79 : || octx->region_type == ORT_NONE
18385 79 : || octx->region_type == ORT_IMPLICIT_TARGET)
18386 0 : continue;
18387 : break;
18388 : }
18389 187 : if (octx == NULL && !in_omp_construct)
18390 4 : error_at (EXPR_LOCATION (for_stmt),
18391 : "%<bind%> clause not specified on a %<loop%> "
18392 : "construct not nested inside another OpenMP construct");
18393 : }
18394 574 : bind = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_BIND);
18395 574 : OMP_CLAUSE_CHAIN (bind) = clauses;
18396 574 : OMP_CLAUSE_BIND_KIND (bind) = kind;
18397 574 : OMP_FOR_CLAUSES (for_stmt) = bind;
18398 : }
18399 : else
18400 482 : switch (OMP_CLAUSE_BIND_KIND (bind))
18401 : {
18402 : case OMP_CLAUSE_BIND_THREAD:
18403 : break;
18404 166 : case OMP_CLAUSE_BIND_PARALLEL:
18405 166 : if (!flag_openmp) /* flag_openmp_simd */
18406 : {
18407 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18408 0 : break;
18409 : }
18410 240 : for (; octx; octx = octx->outer_context)
18411 78 : if (octx->region_type == ORT_SIMD
18412 78 : && omp_find_clause (octx->clauses, OMP_CLAUSE_BIND) == NULL_TREE)
18413 : {
18414 4 : error_at (EXPR_LOCATION (for_stmt),
18415 : "%<bind(parallel)%> on a %<loop%> construct nested "
18416 : "inside %<simd%> construct");
18417 4 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18418 4 : break;
18419 : }
18420 : kind = OMP_CLAUSE_BIND_PARALLEL;
18421 : break;
18422 162 : case OMP_CLAUSE_BIND_TEAMS:
18423 162 : if (!flag_openmp) /* flag_openmp_simd */
18424 : {
18425 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18426 0 : break;
18427 : }
18428 162 : if ((octx
18429 128 : && octx->region_type != ORT_IMPLICIT_TARGET
18430 111 : && octx->region_type != ORT_NONE
18431 111 : && (octx->region_type & ORT_TEAMS) == 0)
18432 110 : || in_omp_construct)
18433 : {
18434 64 : error_at (EXPR_LOCATION (for_stmt),
18435 : "%<bind(teams)%> on a %<loop%> region not strictly "
18436 : "nested inside of a %<teams%> region");
18437 64 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18438 64 : break;
18439 : }
18440 : kind = OMP_CLAUSE_BIND_TEAMS;
18441 : break;
18442 0 : default:
18443 0 : gcc_unreachable ();
18444 : }
18445 :
18446 4280 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
18447 3224 : switch (OMP_CLAUSE_CODE (*pc))
18448 : {
18449 343 : case OMP_CLAUSE_REDUCTION:
18450 343 : if (OMP_CLAUSE_REDUCTION_INSCAN (*pc))
18451 : {
18452 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18453 : "%<inscan%> %<reduction%> clause on "
18454 : "%qs construct", "loop");
18455 4 : OMP_CLAUSE_REDUCTION_INSCAN (*pc) = 0;
18456 : }
18457 343 : if (OMP_CLAUSE_REDUCTION_TASK (*pc))
18458 : {
18459 8 : error_at (OMP_CLAUSE_LOCATION (*pc),
18460 : "invalid %<task%> reduction modifier on construct "
18461 : "other than %<parallel%>, %qs or %<sections%>",
18462 4 : lang_GNU_Fortran () ? "do" : "for");
18463 4 : OMP_CLAUSE_REDUCTION_TASK (*pc) = 0;
18464 : }
18465 343 : pc = &OMP_CLAUSE_CHAIN (*pc);
18466 343 : break;
18467 : case OMP_CLAUSE_LASTPRIVATE:
18468 293 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18469 : {
18470 289 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
18471 289 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
18472 289 : if (OMP_CLAUSE_DECL (*pc) == TREE_OPERAND (t, 0))
18473 : break;
18474 26 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18475 25 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18476 : i)) == TREE_LIST
18477 48 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18478 : i)))
18479 : {
18480 22 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18481 22 : if (OMP_CLAUSE_DECL (*pc) == TREE_PURPOSE (orig))
18482 : break;
18483 : }
18484 : }
18485 289 : if (i == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
18486 : {
18487 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18488 : "%<lastprivate%> clause on a %<loop%> construct refers "
18489 : "to a variable %qD which is not the loop iterator",
18490 4 : OMP_CLAUSE_DECL (*pc));
18491 4 : *pc = OMP_CLAUSE_CHAIN (*pc);
18492 4 : break;
18493 : }
18494 285 : pc = &OMP_CLAUSE_CHAIN (*pc);
18495 285 : break;
18496 2592 : default:
18497 2592 : pc = &OMP_CLAUSE_CHAIN (*pc);
18498 2592 : break;
18499 : }
18500 :
18501 1056 : TREE_SET_CODE (for_stmt, OMP_SIMD);
18502 :
18503 1056 : int last;
18504 1056 : switch (kind)
18505 : {
18506 : case OMP_CLAUSE_BIND_THREAD: last = 0; break;
18507 414 : case OMP_CLAUSE_BIND_PARALLEL: last = 1; break;
18508 220 : case OMP_CLAUSE_BIND_TEAMS: last = 2; break;
18509 : }
18510 1910 : for (int pass = 1; pass <= last; pass++)
18511 : {
18512 854 : if (pass == 2)
18513 : {
18514 220 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL,
18515 : make_node (BLOCK));
18516 220 : append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind));
18517 220 : *expr_p = make_node (OMP_PARALLEL);
18518 220 : TREE_TYPE (*expr_p) = void_type_node;
18519 220 : OMP_PARALLEL_BODY (*expr_p) = bind;
18520 220 : OMP_PARALLEL_COMBINED (*expr_p) = 1;
18521 220 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (for_stmt));
18522 220 : tree *pc = &OMP_PARALLEL_CLAUSES (*expr_p);
18523 672 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18524 232 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18525 232 : && (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i))
18526 : == TREE_LIST))
18527 : {
18528 16 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18529 16 : if (TREE_PURPOSE (elt) && TREE_VALUE (elt))
18530 : {
18531 13 : *pc = build_omp_clause (UNKNOWN_LOCATION,
18532 : OMP_CLAUSE_FIRSTPRIVATE);
18533 13 : OMP_CLAUSE_DECL (*pc) = TREE_VALUE (elt);
18534 13 : pc = &OMP_CLAUSE_CHAIN (*pc);
18535 : }
18536 : }
18537 : }
18538 854 : tree t = make_node (pass == 2 ? OMP_DISTRIBUTE : OMP_FOR);
18539 854 : tree *pc = &OMP_FOR_CLAUSES (t);
18540 854 : TREE_TYPE (t) = void_type_node;
18541 854 : OMP_FOR_BODY (t) = *expr_p;
18542 854 : SET_EXPR_LOCATION (t, EXPR_LOCATION (for_stmt));
18543 3968 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
18544 3114 : switch (OMP_CLAUSE_CODE (c))
18545 : {
18546 1992 : case OMP_CLAUSE_BIND:
18547 1992 : case OMP_CLAUSE_ORDER:
18548 1992 : case OMP_CLAUSE_COLLAPSE:
18549 1992 : *pc = copy_node (c);
18550 1992 : pc = &OMP_CLAUSE_CHAIN (*pc);
18551 1992 : break;
18552 : case OMP_CLAUSE_PRIVATE:
18553 : case OMP_CLAUSE_FIRSTPRIVATE:
18554 : /* Only needed on innermost. */
18555 : break;
18556 351 : case OMP_CLAUSE_LASTPRIVATE:
18557 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) && pass != last)
18558 : {
18559 7 : *pc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18560 : OMP_CLAUSE_FIRSTPRIVATE);
18561 7 : OMP_CLAUSE_DECL (*pc) = OMP_CLAUSE_DECL (c);
18562 7 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18563 7 : pc = &OMP_CLAUSE_CHAIN (*pc);
18564 : }
18565 351 : *pc = copy_node (c);
18566 351 : OMP_CLAUSE_LASTPRIVATE_STMT (*pc) = NULL_TREE;
18567 351 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18568 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18569 : {
18570 22 : if (pass != last)
18571 7 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (*pc) = 1;
18572 : else
18573 15 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18574 22 : OMP_CLAUSE_LASTPRIVATE_LOOP_IV (*pc) = 0;
18575 : }
18576 351 : pc = &OMP_CLAUSE_CHAIN (*pc);
18577 351 : break;
18578 463 : case OMP_CLAUSE_REDUCTION:
18579 463 : *pc = copy_node (c);
18580 463 : OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c));
18581 463 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18582 463 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc))
18583 : {
18584 15 : auto_vec<tree> no_context_vars;
18585 15 : int walk_subtrees = 0;
18586 15 : note_no_context_vars (&OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18587 : &walk_subtrees, &no_context_vars);
18588 15 : if (tree p = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c))
18589 0 : note_no_context_vars (&p, &walk_subtrees, &no_context_vars);
18590 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (c),
18591 : note_no_context_vars,
18592 : &no_context_vars);
18593 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (c),
18594 : note_no_context_vars,
18595 : &no_context_vars);
18596 :
18597 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)
18598 15 : = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
18599 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18600 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)
18601 0 : = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c));
18602 :
18603 15 : hash_map<tree, tree> decl_map;
18604 15 : decl_map.put (OMP_CLAUSE_DECL (c), OMP_CLAUSE_DECL (c));
18605 15 : decl_map.put (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18606 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc));
18607 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18608 0 : decl_map.put (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
18609 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc));
18610 :
18611 15 : copy_body_data id;
18612 15 : memset (&id, 0, sizeof (id));
18613 15 : id.src_fn = current_function_decl;
18614 15 : id.dst_fn = current_function_decl;
18615 15 : id.src_cfun = cfun;
18616 15 : id.decl_map = &decl_map;
18617 15 : id.copy_decl = copy_decl_no_change;
18618 15 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
18619 15 : id.transform_new_cfg = true;
18620 15 : id.transform_return_to_modify = false;
18621 15 : id.eh_lp_nr = 0;
18622 15 : walk_tree (&OMP_CLAUSE_REDUCTION_INIT (*pc), copy_tree_body_r,
18623 : &id, NULL);
18624 15 : walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (*pc), copy_tree_body_r,
18625 : &id, NULL);
18626 :
18627 60 : for (tree d : no_context_vars)
18628 : {
18629 15 : DECL_CONTEXT (d) = NULL_TREE;
18630 15 : DECL_CONTEXT (*decl_map.get (d)) = NULL_TREE;
18631 : }
18632 15 : }
18633 : else
18634 : {
18635 448 : OMP_CLAUSE_REDUCTION_INIT (*pc)
18636 448 : = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c));
18637 448 : OMP_CLAUSE_REDUCTION_MERGE (*pc)
18638 896 : = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c));
18639 : }
18640 463 : pc = &OMP_CLAUSE_CHAIN (*pc);
18641 463 : break;
18642 0 : default:
18643 0 : gcc_unreachable ();
18644 : }
18645 854 : *pc = NULL_TREE;
18646 854 : *expr_p = t;
18647 : }
18648 1056 : return gimplify_expr (expr_p, pre_p, NULL, is_gimple_stmt, fb_none);
18649 : }
18650 :
18651 :
18652 : /* Helper function of optimize_target_teams, find OMP_TEAMS inside
18653 : of OMP_TARGET's body. */
18654 :
18655 : static tree
18656 99093 : find_omp_teams (tree *tp, int *walk_subtrees, void *)
18657 : {
18658 99093 : *walk_subtrees = 0;
18659 99093 : switch (TREE_CODE (*tp))
18660 : {
18661 : case OMP_TEAMS:
18662 : return *tp;
18663 27406 : case BIND_EXPR:
18664 27406 : case STATEMENT_LIST:
18665 27406 : *walk_subtrees = 1;
18666 27406 : break;
18667 : default:
18668 : break;
18669 : }
18670 : return NULL_TREE;
18671 : }
18672 :
18673 : /* Helper function of optimize_target_teams, determine if the expression
18674 : can be computed safely before the target construct on the host. */
18675 :
18676 : static tree
18677 1341 : computable_teams_clause (tree *tp, int *walk_subtrees, void *)
18678 : {
18679 1861 : splay_tree_node n;
18680 :
18681 1861 : if (TYPE_P (*tp))
18682 : {
18683 0 : *walk_subtrees = 0;
18684 0 : return NULL_TREE;
18685 : }
18686 1861 : switch (TREE_CODE (*tp))
18687 : {
18688 858 : case VAR_DECL:
18689 858 : case PARM_DECL:
18690 858 : case RESULT_DECL:
18691 858 : *walk_subtrees = 0;
18692 858 : if (error_operand_p (*tp)
18693 858 : || !INTEGRAL_TYPE_P (TREE_TYPE (*tp))
18694 858 : || DECL_HAS_VALUE_EXPR_P (*tp)
18695 858 : || DECL_THREAD_LOCAL_P (*tp)
18696 858 : || TREE_SIDE_EFFECTS (*tp)
18697 1716 : || TREE_THIS_VOLATILE (*tp))
18698 0 : return *tp;
18699 858 : if (is_global_var (*tp)
18700 858 : && (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (*tp))
18701 0 : || lookup_attribute ("omp declare target link",
18702 0 : DECL_ATTRIBUTES (*tp))))
18703 16 : return *tp;
18704 842 : if (VAR_P (*tp)
18705 536 : && !DECL_SEEN_IN_BIND_EXPR_P (*tp)
18706 0 : && !is_global_var (*tp)
18707 842 : && decl_function_context (*tp) == current_function_decl)
18708 0 : return *tp;
18709 1684 : n = splay_tree_lookup (gimplify_omp_ctxp->variables,
18710 842 : (splay_tree_key) *tp);
18711 842 : if (n == NULL)
18712 : {
18713 210 : if (gimplify_omp_ctxp->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
18714 : return NULL_TREE;
18715 0 : return *tp;
18716 : }
18717 632 : else if (n->value & GOVD_LOCAL)
18718 0 : return *tp;
18719 632 : else if (n->value & GOVD_FIRSTPRIVATE)
18720 : return NULL_TREE;
18721 112 : else if ((n->value & (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18722 : == (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18723 : return NULL_TREE;
18724 96 : return *tp;
18725 76 : case INTEGER_CST:
18726 76 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18727 0 : return *tp;
18728 : return NULL_TREE;
18729 520 : case TARGET_EXPR:
18730 520 : if (TARGET_EXPR_INITIAL (*tp)
18731 520 : || TREE_CODE (TARGET_EXPR_SLOT (*tp)) != VAR_DECL)
18732 : return *tp;
18733 520 : return computable_teams_clause (&TARGET_EXPR_SLOT (*tp),
18734 520 : walk_subtrees, NULL);
18735 : /* Allow some reasonable subset of integral arithmetics. */
18736 193 : case PLUS_EXPR:
18737 193 : case MINUS_EXPR:
18738 193 : case MULT_EXPR:
18739 193 : case TRUNC_DIV_EXPR:
18740 193 : case CEIL_DIV_EXPR:
18741 193 : case FLOOR_DIV_EXPR:
18742 193 : case ROUND_DIV_EXPR:
18743 193 : case TRUNC_MOD_EXPR:
18744 193 : case CEIL_MOD_EXPR:
18745 193 : case FLOOR_MOD_EXPR:
18746 193 : case ROUND_MOD_EXPR:
18747 193 : case RDIV_EXPR:
18748 193 : case EXACT_DIV_EXPR:
18749 193 : case MIN_EXPR:
18750 193 : case MAX_EXPR:
18751 193 : case LSHIFT_EXPR:
18752 193 : case RSHIFT_EXPR:
18753 193 : case BIT_IOR_EXPR:
18754 193 : case BIT_XOR_EXPR:
18755 193 : case BIT_AND_EXPR:
18756 193 : case NEGATE_EXPR:
18757 193 : case ABS_EXPR:
18758 193 : case BIT_NOT_EXPR:
18759 193 : case NON_LVALUE_EXPR:
18760 193 : CASE_CONVERT:
18761 193 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18762 0 : return *tp;
18763 : return NULL_TREE;
18764 : /* And disallow anything else, except for comparisons. */
18765 214 : default:
18766 214 : if (COMPARISON_CLASS_P (*tp))
18767 0 : return NULL_TREE;
18768 : return *tp;
18769 : }
18770 : }
18771 :
18772 : /* Try to determine if the num_teams and/or thread_limit expressions
18773 : can have their values determined already before entering the
18774 : target construct.
18775 : INTEGER_CSTs trivially are,
18776 : integral decls that are firstprivate (explicitly or implicitly)
18777 : or explicitly map(always, to:) or map(always, tofrom:) on the target
18778 : region too, and expressions involving simple arithmetics on those
18779 : too, function calls are not ok, dereferencing something neither etc.
18780 : Add NUM_TEAMS and THREAD_LIMIT clauses to the OMP_CLAUSES of
18781 : EXPR based on what we find:
18782 : 0 stands for clause not specified at all, use implementation default
18783 : -1 stands for value that can't be determined easily before entering
18784 : the target construct.
18785 : -2 means that no explicit teams construct was specified
18786 : If teams construct is not present at all, use 1 for num_teams
18787 : and 0 for thread_limit (only one team is involved, and the thread
18788 : limit is implementation defined. */
18789 :
18790 : static void
18791 13567 : optimize_target_teams (tree target, gimple_seq *pre_p)
18792 : {
18793 13567 : tree body = OMP_BODY (target);
18794 13567 : tree teams = walk_tree (&body, find_omp_teams, NULL, NULL);
18795 13567 : tree num_teams_lower = NULL_TREE;
18796 13567 : tree num_teams_upper = integer_zero_node;
18797 13567 : tree thread_limit = integer_zero_node;
18798 13567 : location_t num_teams_loc = EXPR_LOCATION (target);
18799 13567 : location_t thread_limit_loc = EXPR_LOCATION (target);
18800 13567 : tree c, *p, expr;
18801 13567 : struct gimplify_omp_ctx *target_ctx = gimplify_omp_ctxp;
18802 :
18803 13567 : if (teams == NULL_TREE)
18804 7438 : num_teams_upper = build_int_cst (integer_type_node, -2);
18805 : else
18806 10615 : for (c = OMP_TEAMS_CLAUSES (teams); c; c = OMP_CLAUSE_CHAIN (c))
18807 : {
18808 4486 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS)
18809 : {
18810 625 : p = &num_teams_upper;
18811 625 : num_teams_loc = OMP_CLAUSE_LOCATION (c);
18812 625 : if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c))
18813 : {
18814 136 : expr = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c);
18815 136 : if (TREE_CODE (expr) == INTEGER_CST)
18816 18 : num_teams_lower = expr;
18817 118 : else if (walk_tree (&expr, computable_teams_clause,
18818 : NULL, NULL))
18819 12 : num_teams_lower = integer_minus_one_node;
18820 : else
18821 : {
18822 106 : num_teams_lower = expr;
18823 106 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18824 106 : if (gimplify_expr (&num_teams_lower, pre_p, NULL,
18825 : is_gimple_val, fb_rvalue, false)
18826 : == GS_ERROR)
18827 : {
18828 0 : gimplify_omp_ctxp = target_ctx;
18829 0 : num_teams_lower = integer_minus_one_node;
18830 : }
18831 : else
18832 : {
18833 106 : gimplify_omp_ctxp = target_ctx;
18834 106 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18835 28 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
18836 56 : = num_teams_lower;
18837 : }
18838 : }
18839 : }
18840 : }
18841 3861 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
18842 : {
18843 479 : p = &thread_limit;
18844 479 : thread_limit_loc = OMP_CLAUSE_LOCATION (c);
18845 : }
18846 : else
18847 3382 : continue;
18848 1104 : expr = OMP_CLAUSE_OPERAND (c, 0);
18849 1104 : if (TREE_CODE (expr) == INTEGER_CST)
18850 : {
18851 150 : *p = expr;
18852 150 : continue;
18853 : }
18854 954 : if (walk_tree (&expr, computable_teams_clause, NULL, NULL))
18855 : {
18856 314 : *p = integer_minus_one_node;
18857 314 : continue;
18858 : }
18859 640 : *p = expr;
18860 640 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18861 640 : if (gimplify_expr (p, pre_p, NULL, is_gimple_val, fb_rvalue, false)
18862 : == GS_ERROR)
18863 : {
18864 0 : gimplify_omp_ctxp = target_ctx;
18865 0 : *p = integer_minus_one_node;
18866 0 : continue;
18867 : }
18868 640 : gimplify_omp_ctxp = target_ctx;
18869 640 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18870 48 : OMP_CLAUSE_OPERAND (c, 0) = *p;
18871 : }
18872 13567 : if (!omp_find_clause (OMP_TARGET_CLAUSES (target), OMP_CLAUSE_THREAD_LIMIT))
18873 : {
18874 13287 : c = build_omp_clause (thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
18875 13287 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
18876 13287 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18877 13287 : OMP_TARGET_CLAUSES (target) = c;
18878 : }
18879 13567 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
18880 13567 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
18881 13567 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
18882 13567 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18883 13567 : OMP_TARGET_CLAUSES (target) = c;
18884 13567 : }
18885 :
18886 : /* Gimplify the gross structure of several OMP constructs. */
18887 :
18888 : static void
18889 40049 : gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
18890 : {
18891 40049 : tree expr = *expr_p;
18892 40049 : gimple *stmt;
18893 40049 : gimple_seq body = NULL;
18894 40049 : enum omp_region_type ort;
18895 :
18896 40049 : switch (TREE_CODE (expr))
18897 : {
18898 : case OMP_SECTIONS:
18899 : case OMP_SINGLE:
18900 : ort = ORT_WORKSHARE;
18901 : break;
18902 242 : case OMP_SCOPE:
18903 242 : ort = ORT_TASKGROUP;
18904 242 : break;
18905 13567 : case OMP_TARGET:
18906 13567 : ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET;
18907 : break;
18908 2543 : case OACC_KERNELS:
18909 2543 : ort = ORT_ACC_KERNELS;
18910 2543 : break;
18911 7901 : case OACC_PARALLEL:
18912 7901 : ort = ORT_ACC_PARALLEL;
18913 7901 : break;
18914 1040 : case OACC_SERIAL:
18915 1040 : ort = ORT_ACC_SERIAL;
18916 1040 : break;
18917 1950 : case OACC_DATA:
18918 1950 : ort = ORT_ACC_DATA;
18919 1950 : break;
18920 1875 : case OMP_TARGET_DATA:
18921 1875 : ort = ORT_TARGET_DATA;
18922 1875 : break;
18923 8892 : case OMP_TEAMS:
18924 8892 : ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS;
18925 8892 : if (gimplify_omp_ctxp == NULL
18926 6169 : || gimplify_omp_ctxp->region_type == ORT_IMPLICIT_TARGET)
18927 2723 : ort = (enum omp_region_type) (ort | ORT_HOST_TEAMS);
18928 : break;
18929 118 : case OACC_HOST_DATA:
18930 118 : ort = ORT_ACC_HOST_DATA;
18931 118 : break;
18932 0 : default:
18933 0 : gcc_unreachable ();
18934 : }
18935 :
18936 40049 : gimple_seq iterator_loops_seq = NULL;
18937 40049 : if (TREE_CODE (expr) == OMP_TARGET || TREE_CODE (expr) == OMP_TARGET_DATA)
18938 : {
18939 15442 : remove_unused_omp_iterator_vars (&OMP_CLAUSES (expr));
18940 15442 : build_omp_iterators_loops (&OMP_CLAUSES (expr), &iterator_loops_seq);
18941 : }
18942 :
18943 40049 : bool save_in_omp_construct = in_omp_construct;
18944 40049 : if ((ort & ORT_ACC) == 0)
18945 26497 : in_omp_construct = false;
18946 40049 : gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
18947 40049 : TREE_CODE (expr), &iterator_loops_seq);
18948 40049 : if (TREE_CODE (expr) == OMP_TARGET)
18949 13567 : optimize_target_teams (expr, pre_p);
18950 40049 : if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
18951 11055 : || (ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18952 : {
18953 31717 : push_gimplify_context ();
18954 31717 : gimple *g = gimplify_and_return_first (OMP_BODY (expr), &body);
18955 31717 : if (gimple_code (g) == GIMPLE_BIND)
18956 31717 : pop_gimplify_context (g);
18957 : else
18958 0 : pop_gimplify_context (NULL);
18959 31717 : if ((ort & ORT_TARGET_DATA) != 0)
18960 : {
18961 3943 : enum built_in_function end_ix;
18962 3943 : switch (TREE_CODE (expr))
18963 : {
18964 : case OACC_DATA:
18965 : case OACC_HOST_DATA:
18966 : end_ix = BUILT_IN_GOACC_DATA_END;
18967 : break;
18968 1875 : case OMP_TARGET_DATA:
18969 1875 : end_ix = BUILT_IN_GOMP_TARGET_END_DATA;
18970 1875 : break;
18971 0 : default:
18972 0 : gcc_unreachable ();
18973 : }
18974 3943 : tree fn = builtin_decl_explicit (end_ix);
18975 3943 : g = gimple_build_call (fn, 0);
18976 3943 : gimple_seq cleanup = NULL;
18977 3943 : gimple_seq_add_stmt (&cleanup, g);
18978 3943 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
18979 3943 : body = NULL;
18980 3943 : gimple_seq_add_stmt (&body, g);
18981 : }
18982 : }
18983 : else
18984 8332 : gimplify_and_add (OMP_BODY (expr), &body);
18985 40049 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
18986 40049 : TREE_CODE (expr), &iterator_loops_seq);
18987 40049 : in_omp_construct = save_in_omp_construct;
18988 :
18989 40049 : switch (TREE_CODE (expr))
18990 : {
18991 1950 : case OACC_DATA:
18992 3900 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_DATA,
18993 1950 : OMP_CLAUSES (expr));
18994 1950 : break;
18995 118 : case OACC_HOST_DATA:
18996 118 : if (omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT))
18997 : {
18998 128 : for (tree c = OMP_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18999 95 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
19000 57 : OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c) = 1;
19001 : }
19002 :
19003 236 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_HOST_DATA,
19004 118 : OMP_CLAUSES (expr));
19005 118 : break;
19006 2543 : case OACC_KERNELS:
19007 5086 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS,
19008 2543 : OMP_CLAUSES (expr));
19009 2543 : break;
19010 7901 : case OACC_PARALLEL:
19011 15802 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_PARALLEL,
19012 7901 : OMP_CLAUSES (expr));
19013 7901 : break;
19014 1040 : case OACC_SERIAL:
19015 2080 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_SERIAL,
19016 1040 : OMP_CLAUSES (expr));
19017 1040 : break;
19018 634 : case OMP_SECTIONS:
19019 634 : stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
19020 634 : break;
19021 1287 : case OMP_SINGLE:
19022 1287 : stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
19023 1287 : break;
19024 242 : case OMP_SCOPE:
19025 242 : stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
19026 242 : break;
19027 13567 : case OMP_TARGET:
19028 : /* Handle 'device_type(nohost)'. */
19029 13567 : if (tree c = omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_DEVICE_TYPE))
19030 20 : if (OMP_CLAUSE_DEVICE_TYPE_KIND (c) == OMP_CLAUSE_DEVICE_TYPE_NOHOST)
19031 : {
19032 9 : location_t loc = gimple_location (body);
19033 9 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_IS_INITIAL_DEVICE);
19034 9 : fn = build_call_expr_loc (loc, fn, 0);
19035 9 : tree err = builtin_decl_explicit (BUILT_IN_GOMP_ERROR);
19036 9 : const char *str = "Executing device-type 'nohost' target region "
19037 : "on the host";
19038 9 : tree msg = build_string_literal (strlen (str) + 1, str);
19039 9 : tree msglen = build_int_cst (size_type_node, -2);
19040 9 : err = build_call_expr_loc (loc, err, 2, msg, msglen);
19041 9 : tree l1 = create_artificial_label (UNKNOWN_LOCATION);
19042 9 : tree l2 = create_artificial_label (UNKNOWN_LOCATION);
19043 9 : tree l3 = create_artificial_label (UNKNOWN_LOCATION);
19044 :
19045 9 : gimple_seq new_body = NULL;
19046 :
19047 9 : gimplify_expr (&fn, &new_body, NULL, is_gimple_val, fb_rvalue);
19048 9 : gcond *cond = gimple_build_cond (NE_EXPR, fn,
19049 9 : build_int_cst (TREE_TYPE (fn), 0),
19050 : l1, l2);
19051 9 : gimplify_seq_add_stmt (&new_body, cond);
19052 9 : gimplify_seq_add_stmt (&new_body, gimple_build_label (l1));
19053 9 : gimplify_and_add (err, &new_body);
19054 9 : gimplify_seq_add_stmt (&new_body, gimple_build_goto (l3));
19055 9 : gimplify_seq_add_stmt (&new_body, gimple_build_label (l2));
19056 9 : gimple_seq_add_seq (&new_body, body);
19057 9 : gimplify_seq_add_stmt (&new_body, gimple_build_label (l3));
19058 9 : body = gimple_build_bind (NULL_TREE, new_body, make_node (BLOCK));
19059 9 : gimple_set_location (body, loc);
19060 : }
19061 27134 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
19062 13567 : OMP_CLAUSES (expr), iterator_loops_seq);
19063 13567 : break;
19064 1875 : case OMP_TARGET_DATA:
19065 : /* Put use_device_{ptr,addr} clauses last, as map clauses are supposed
19066 : to be evaluated before the use_device_{ptr,addr} clauses if they
19067 : refer to the same variables. */
19068 1875 : {
19069 1875 : tree use_device_clauses;
19070 1875 : tree *pc, *uc = &use_device_clauses;
19071 9974 : for (pc = &OMP_CLAUSES (expr); *pc; )
19072 8099 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
19073 8099 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
19074 : {
19075 1959 : *uc = *pc;
19076 1959 : *pc = OMP_CLAUSE_CHAIN (*pc);
19077 1959 : uc = &OMP_CLAUSE_CHAIN (*uc);
19078 : }
19079 : else
19080 6140 : pc = &OMP_CLAUSE_CHAIN (*pc);
19081 1875 : *uc = NULL_TREE;
19082 1875 : *pc = use_device_clauses;
19083 1875 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_DATA,
19084 1875 : OMP_CLAUSES (expr), iterator_loops_seq);
19085 : }
19086 1875 : break;
19087 8892 : case OMP_TEAMS:
19088 8892 : stmt = gimple_build_omp_teams (body, OMP_CLAUSES (expr));
19089 8892 : if ((ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
19090 2723 : gimple_omp_teams_set_host (as_a <gomp_teams *> (stmt), true);
19091 : break;
19092 0 : default:
19093 0 : gcc_unreachable ();
19094 : }
19095 :
19096 40049 : gimplify_seq_add_stmt (pre_p, stmt);
19097 40049 : *expr_p = NULL_TREE;
19098 40049 : }
19099 :
19100 : /* Gimplify the gross structure of OpenACC enter/exit data, update, and OpenMP
19101 : target update constructs. */
19102 :
19103 : static void
19104 12382 : gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
19105 : {
19106 12382 : tree expr = *expr_p;
19107 12382 : int kind;
19108 12382 : gomp_target *stmt;
19109 12382 : enum omp_region_type ort = ORT_WORKSHARE;
19110 :
19111 12382 : switch (TREE_CODE (expr))
19112 : {
19113 : case OACC_ENTER_DATA:
19114 : kind = GF_OMP_TARGET_KIND_OACC_ENTER_DATA;
19115 : ort = ORT_ACC;
19116 : break;
19117 : case OACC_EXIT_DATA:
19118 : kind = GF_OMP_TARGET_KIND_OACC_EXIT_DATA;
19119 : ort = ORT_ACC;
19120 : break;
19121 : case OACC_UPDATE:
19122 : kind = GF_OMP_TARGET_KIND_OACC_UPDATE;
19123 : ort = ORT_ACC;
19124 : break;
19125 : case OMP_TARGET_UPDATE:
19126 : kind = GF_OMP_TARGET_KIND_UPDATE;
19127 : break;
19128 : case OMP_TARGET_ENTER_DATA:
19129 : kind = GF_OMP_TARGET_KIND_ENTER_DATA;
19130 : break;
19131 : case OMP_TARGET_EXIT_DATA:
19132 : kind = GF_OMP_TARGET_KIND_EXIT_DATA;
19133 : break;
19134 0 : default:
19135 0 : gcc_unreachable ();
19136 : }
19137 :
19138 12382 : gimple_seq iterator_loops_seq = NULL;
19139 12382 : remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr));
19140 12382 : build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr),
19141 : &iterator_loops_seq);
19142 :
19143 12382 : gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
19144 12382 : ort, TREE_CODE (expr), &iterator_loops_seq);
19145 12382 : gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
19146 12382 : TREE_CODE (expr), &iterator_loops_seq);
19147 12382 : if (TREE_CODE (expr) == OACC_UPDATE
19148 12382 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
19149 : OMP_CLAUSE_IF_PRESENT))
19150 : {
19151 : /* The runtime uses GOMP_MAP_{TO,FROM} to denote the if_present
19152 : clause. */
19153 123 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19154 97 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
19155 47 : switch (OMP_CLAUSE_MAP_KIND (c))
19156 : {
19157 14 : case GOMP_MAP_FORCE_TO:
19158 14 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
19159 14 : break;
19160 24 : case GOMP_MAP_FORCE_FROM:
19161 24 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FROM);
19162 24 : break;
19163 : default:
19164 : break;
19165 : }
19166 : }
19167 12356 : else if (TREE_CODE (expr) == OACC_EXIT_DATA
19168 12356 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
19169 : OMP_CLAUSE_FINALIZE))
19170 : {
19171 : /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote "finalize"
19172 : semantics. */
19173 75 : bool have_clause = false;
19174 275 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19175 200 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
19176 117 : switch (OMP_CLAUSE_MAP_KIND (c))
19177 : {
19178 45 : case GOMP_MAP_FROM:
19179 45 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
19180 45 : have_clause = true;
19181 45 : break;
19182 47 : case GOMP_MAP_RELEASE:
19183 47 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
19184 47 : have_clause = true;
19185 47 : break;
19186 : case GOMP_MAP_TO_PSET:
19187 : /* Fortran arrays with descriptors must map that descriptor when
19188 : doing standalone "attach" operations (in OpenACC). In that
19189 : case GOMP_MAP_TO_PSET appears by itself with no preceding
19190 : clause (see trans-openmp.cc:gfc_trans_omp_clauses). */
19191 : break;
19192 2 : case GOMP_MAP_POINTER:
19193 : /* TODO PR92929: we may see these here, but they'll always follow
19194 : one of the clauses above, and will be handled by libgomp as
19195 : one group, so no handling required here. */
19196 2 : gcc_assert (have_clause);
19197 : break;
19198 22 : case GOMP_MAP_DETACH:
19199 22 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_DETACH);
19200 22 : have_clause = false;
19201 22 : break;
19202 : case GOMP_MAP_STRUCT:
19203 : case GOMP_MAP_STRUCT_UNORD:
19204 200 : have_clause = false;
19205 : break;
19206 0 : default:
19207 0 : gcc_unreachable ();
19208 : }
19209 : }
19210 12382 : stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr),
19211 : iterator_loops_seq);
19212 :
19213 12382 : gimplify_seq_add_stmt (pre_p, stmt);
19214 12382 : *expr_p = NULL_TREE;
19215 12382 : }
19216 :
19217 : /* A subroutine of gimplify_omp_atomic. The front end is supposed to have
19218 : stabilized the lhs of the atomic operation as *ADDR. Return true if
19219 : EXPR is this stabilized form. */
19220 :
19221 : static bool
19222 36846 : goa_lhs_expr_p (tree expr, tree addr)
19223 : {
19224 : /* Also include casts to other type variants. The C front end is fond
19225 : of adding these for e.g. volatile variables. This is like
19226 : STRIP_TYPE_NOPS but includes the main variant lookup. */
19227 36846 : STRIP_USELESS_TYPE_CONVERSION (expr);
19228 :
19229 36846 : if (INDIRECT_REF_P (expr))
19230 : {
19231 5027 : expr = TREE_OPERAND (expr, 0);
19232 5027 : while (expr != addr
19233 92 : && (CONVERT_EXPR_P (expr)
19234 92 : || TREE_CODE (expr) == NON_LVALUE_EXPR)
19235 0 : && TREE_CODE (expr) == TREE_CODE (addr)
19236 5027 : && types_compatible_p (TREE_TYPE (expr), TREE_TYPE (addr)))
19237 : {
19238 0 : expr = TREE_OPERAND (expr, 0);
19239 0 : addr = TREE_OPERAND (addr, 0);
19240 : }
19241 5027 : if (expr == addr)
19242 : return true;
19243 92 : return (TREE_CODE (addr) == ADDR_EXPR
19244 62 : && TREE_CODE (expr) == ADDR_EXPR
19245 92 : && TREE_OPERAND (addr, 0) == TREE_OPERAND (expr, 0));
19246 : }
19247 31819 : if (TREE_CODE (addr) == ADDR_EXPR && expr == TREE_OPERAND (addr, 0))
19248 : return true;
19249 : return false;
19250 : }
19251 :
19252 : /* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR. If an
19253 : expression does not involve the lhs, evaluate it into a temporary.
19254 : Return 1 if the lhs appeared as a subexpression, 0 if it did not,
19255 : or -1 if an error was encountered. */
19256 :
19257 : static int
19258 36846 : goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
19259 : tree lhs_var, tree &target_expr, bool rhs, int depth)
19260 : {
19261 36846 : tree expr = *expr_p;
19262 36846 : int saw_lhs = 0;
19263 :
19264 36846 : if (goa_lhs_expr_p (expr, lhs_addr))
19265 : {
19266 9203 : if (pre_p)
19267 8544 : *expr_p = lhs_var;
19268 : return 1;
19269 : }
19270 27643 : if (is_gimple_val (expr))
19271 : return 0;
19272 :
19273 : /* Maximum depth of lhs in expression is for the
19274 : __builtin_clear_padding (...), __builtin_clear_padding (...),
19275 : __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs; */
19276 17299 : if (++depth > 7)
19277 16 : goto finish;
19278 :
19279 17283 : switch (TREE_CODE_CLASS (TREE_CODE (expr)))
19280 : {
19281 9669 : case tcc_binary:
19282 9669 : case tcc_comparison:
19283 9669 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
19284 : lhs_var, target_expr, true, depth);
19285 : /* FALLTHRU */
19286 11712 : case tcc_unary:
19287 11712 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
19288 : lhs_var, target_expr, true, depth);
19289 11712 : break;
19290 2983 : case tcc_expression:
19291 2983 : switch (TREE_CODE (expr))
19292 : {
19293 836 : case TRUTH_ANDIF_EXPR:
19294 836 : case TRUTH_ORIF_EXPR:
19295 836 : case TRUTH_AND_EXPR:
19296 836 : case TRUTH_OR_EXPR:
19297 836 : case TRUTH_XOR_EXPR:
19298 836 : case BIT_INSERT_EXPR:
19299 836 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19300 : lhs_addr, lhs_var, target_expr, true,
19301 : depth);
19302 : /* FALLTHRU */
19303 888 : case TRUTH_NOT_EXPR:
19304 888 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19305 : lhs_addr, lhs_var, target_expr, true,
19306 : depth);
19307 888 : break;
19308 550 : case MODIFY_EXPR:
19309 550 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19310 : target_expr, true, depth))
19311 : break;
19312 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19313 : lhs_addr, lhs_var, target_expr, true,
19314 : depth);
19315 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19316 : lhs_addr, lhs_var, target_expr, false,
19317 : depth);
19318 544 : break;
19319 : /* FALLTHRU */
19320 164 : case ADDR_EXPR:
19321 164 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19322 : target_expr, true, depth))
19323 : break;
19324 138 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19325 : lhs_addr, lhs_var, target_expr, false,
19326 : depth);
19327 138 : break;
19328 : case COMPOUND_EXPR:
19329 : /* Break out any preevaluations from cp_build_modify_expr. */
19330 76 : for (; TREE_CODE (expr) == COMPOUND_EXPR;
19331 38 : expr = TREE_OPERAND (expr, 1))
19332 : {
19333 : /* Special-case __builtin_clear_padding call before
19334 : __builtin_memcmp. */
19335 38 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
19336 : {
19337 2 : tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
19338 2 : if (fndecl
19339 2 : && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
19340 0 : && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
19341 2 : && (!pre_p
19342 0 : || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
19343 : lhs_addr, lhs_var,
19344 : target_expr, true, depth)))
19345 : {
19346 0 : if (pre_p)
19347 0 : *expr_p = expr;
19348 0 : saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
19349 : pre_p, lhs_addr, lhs_var,
19350 : target_expr, true, depth);
19351 0 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
19352 : pre_p, lhs_addr, lhs_var,
19353 : target_expr, rhs, depth);
19354 0 : return saw_lhs;
19355 : }
19356 : }
19357 :
19358 38 : if (pre_p)
19359 35 : gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
19360 : }
19361 38 : if (!pre_p)
19362 3 : return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
19363 3 : target_expr, rhs, depth);
19364 35 : *expr_p = expr;
19365 35 : return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
19366 35 : target_expr, rhs, depth);
19367 442 : case COND_EXPR:
19368 442 : if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
19369 : lhs_var, target_expr, true, depth))
19370 : break;
19371 429 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19372 : lhs_addr, lhs_var, target_expr, true,
19373 : depth);
19374 429 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19375 : lhs_addr, lhs_var, target_expr, true,
19376 : depth);
19377 429 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
19378 : lhs_addr, lhs_var, target_expr, true,
19379 : depth);
19380 429 : break;
19381 880 : case TARGET_EXPR:
19382 880 : if (TARGET_EXPR_INITIAL (expr))
19383 : {
19384 880 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
19385 : lhs_var, target_expr, true,
19386 : depth))
19387 : break;
19388 702 : if (expr == target_expr)
19389 : saw_lhs = 1;
19390 : else
19391 : {
19392 702 : saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
19393 : pre_p, lhs_addr, lhs_var,
19394 : target_expr, true, depth);
19395 702 : if (saw_lhs && target_expr == NULL_TREE && pre_p)
19396 26 : target_expr = expr;
19397 : }
19398 : }
19399 : break;
19400 : default:
19401 : break;
19402 : }
19403 : break;
19404 565 : case tcc_reference:
19405 565 : if (TREE_CODE (expr) == BIT_FIELD_REF
19406 499 : || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
19407 362 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19408 : lhs_addr, lhs_var, target_expr, true,
19409 : depth);
19410 : break;
19411 58 : case tcc_vl_exp:
19412 58 : if (TREE_CODE (expr) == CALL_EXPR)
19413 : {
19414 58 : if (tree fndecl = get_callee_fndecl (expr))
19415 58 : if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING,
19416 : BUILT_IN_MEMCMP))
19417 : {
19418 56 : int nargs = call_expr_nargs (expr);
19419 224 : for (int i = 0; i < nargs; i++)
19420 168 : saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
19421 : pre_p, lhs_addr, lhs_var,
19422 : target_expr, true, depth);
19423 : }
19424 : }
19425 : break;
19426 : default:
19427 : break;
19428 : }
19429 :
19430 17261 : finish:
19431 17261 : if (saw_lhs == 0 && pre_p)
19432 : {
19433 3492 : enum gimplify_status gs;
19434 3492 : if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
19435 : {
19436 0 : gimplify_stmt (&expr, pre_p);
19437 0 : return saw_lhs;
19438 : }
19439 3492 : else if (rhs)
19440 3314 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
19441 : else
19442 178 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
19443 3492 : if (gs != GS_ALL_DONE)
19444 36846 : saw_lhs = -1;
19445 : }
19446 :
19447 : return saw_lhs;
19448 : }
19449 :
19450 : /* Gimplify an OMP_ATOMIC statement. */
19451 :
19452 : static enum gimplify_status
19453 10260 : gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
19454 : {
19455 10260 : tree addr = TREE_OPERAND (*expr_p, 0);
19456 10260 : tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
19457 10260 : ? NULL : TREE_OPERAND (*expr_p, 1);
19458 10260 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
19459 10260 : tree tmp_load;
19460 10260 : gomp_atomic_load *loadstmt;
19461 10260 : gomp_atomic_store *storestmt;
19462 10260 : tree target_expr = NULL_TREE;
19463 :
19464 10260 : tmp_load = create_tmp_reg (type);
19465 10260 : if (rhs
19466 10260 : && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
19467 : true, 0) < 0)
19468 : return GS_ERROR;
19469 :
19470 10260 : if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
19471 : != GS_ALL_DONE)
19472 : return GS_ERROR;
19473 :
19474 10260 : loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
19475 10260 : OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19476 10260 : gimplify_seq_add_stmt (pre_p, loadstmt);
19477 10260 : if (rhs)
19478 : {
19479 : /* BIT_INSERT_EXPR is not valid for non-integral bitfield
19480 : representatives. Use BIT_FIELD_REF on the lhs instead. */
19481 9076 : tree rhsarg = rhs;
19482 9076 : if (TREE_CODE (rhs) == COND_EXPR)
19483 429 : rhsarg = TREE_OPERAND (rhs, 1);
19484 9076 : if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
19485 9076 : && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
19486 : {
19487 32 : tree bitpos = TREE_OPERAND (rhsarg, 2);
19488 32 : tree op1 = TREE_OPERAND (rhsarg, 1);
19489 32 : tree bitsize;
19490 32 : tree tmp_store = tmp_load;
19491 32 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
19492 12 : tmp_store = get_initialized_tmp_var (tmp_load, pre_p);
19493 32 : if (INTEGRAL_TYPE_P (TREE_TYPE (op1)))
19494 32 : bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
19495 : else
19496 0 : bitsize = TYPE_SIZE (TREE_TYPE (op1));
19497 32 : gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
19498 32 : tree t = build2_loc (EXPR_LOCATION (rhsarg),
19499 : MODIFY_EXPR, void_type_node,
19500 32 : build3_loc (EXPR_LOCATION (rhsarg),
19501 32 : BIT_FIELD_REF, TREE_TYPE (op1),
19502 : tmp_store, bitsize, bitpos), op1);
19503 32 : if (TREE_CODE (rhs) == COND_EXPR)
19504 16 : t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
19505 16 : TREE_OPERAND (rhs, 0), t, void_node);
19506 32 : gimplify_and_add (t, pre_p);
19507 32 : rhs = tmp_store;
19508 : }
19509 9076 : bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
19510 9076 : if (TREE_CODE (rhs) == COND_EXPR)
19511 413 : gimplify_ctxp->allow_rhs_cond_expr = true;
19512 9076 : enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
19513 : is_gimple_val, fb_rvalue);
19514 9076 : gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
19515 9076 : if (gs != GS_ALL_DONE)
19516 : return GS_ERROR;
19517 : }
19518 :
19519 10260 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
19520 1184 : rhs = tmp_load;
19521 10260 : storestmt
19522 10260 : = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19523 10260 : if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
19524 : {
19525 38 : gimple_omp_atomic_set_weak (loadstmt);
19526 38 : gimple_omp_atomic_set_weak (storestmt);
19527 : }
19528 10260 : gimplify_seq_add_stmt (pre_p, storestmt);
19529 10260 : switch (TREE_CODE (*expr_p))
19530 : {
19531 2072 : case OMP_ATOMIC_READ:
19532 2072 : case OMP_ATOMIC_CAPTURE_OLD:
19533 2072 : *expr_p = tmp_load;
19534 2072 : gimple_omp_atomic_set_need_value (loadstmt);
19535 2072 : break;
19536 868 : case OMP_ATOMIC_CAPTURE_NEW:
19537 868 : *expr_p = rhs;
19538 868 : gimple_omp_atomic_set_need_value (storestmt);
19539 868 : break;
19540 7320 : default:
19541 7320 : *expr_p = NULL;
19542 7320 : break;
19543 : }
19544 :
19545 : return GS_ALL_DONE;
19546 : }
19547 :
19548 : /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
19549 : body, and adding some EH bits. */
19550 :
19551 : static enum gimplify_status
19552 478 : gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
19553 : {
19554 478 : tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
19555 478 : gimple *body_stmt;
19556 478 : gtransaction *trans_stmt;
19557 478 : gimple_seq body = NULL;
19558 478 : int subcode = 0;
19559 :
19560 : /* Wrap the transaction body in a BIND_EXPR so we have a context
19561 : where to put decls for OMP. */
19562 478 : if (TREE_CODE (tbody) != BIND_EXPR)
19563 : {
19564 439 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
19565 439 : TREE_SIDE_EFFECTS (bind) = 1;
19566 439 : SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
19567 439 : TRANSACTION_EXPR_BODY (expr) = bind;
19568 : }
19569 :
19570 478 : push_gimplify_context ();
19571 478 : temp = voidify_wrapper_expr (*expr_p, NULL);
19572 :
19573 478 : body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
19574 478 : pop_gimplify_context (body_stmt);
19575 :
19576 478 : trans_stmt = gimple_build_transaction (body);
19577 478 : if (TRANSACTION_EXPR_OUTER (expr))
19578 : subcode = GTMA_IS_OUTER;
19579 447 : else if (TRANSACTION_EXPR_RELAXED (expr))
19580 81 : subcode = GTMA_IS_RELAXED;
19581 478 : gimple_transaction_set_subcode (trans_stmt, subcode);
19582 :
19583 478 : gimplify_seq_add_stmt (pre_p, trans_stmt);
19584 :
19585 478 : if (temp)
19586 : {
19587 76 : *expr_p = temp;
19588 76 : return GS_OK;
19589 : }
19590 :
19591 : *expr_p = NULL_TREE;
19592 : return GS_ALL_DONE;
19593 : }
19594 :
19595 : /* Gimplify an OMP_ORDERED construct. EXPR is the tree version. BODY
19596 : is the OMP_BODY of the original EXPR (which has already been
19597 : gimplified so it's not present in the EXPR).
19598 :
19599 : Return the gimplified GIMPLE_OMP_ORDERED tuple. */
19600 :
19601 : static gimple *
19602 1954 : gimplify_omp_ordered (tree expr, gimple_seq body)
19603 : {
19604 1954 : tree c, decls;
19605 1954 : int failures = 0;
19606 1954 : unsigned int i;
19607 1954 : tree source_c = NULL_TREE;
19608 1954 : tree sink_c = NULL_TREE;
19609 :
19610 1954 : if (gimplify_omp_ctxp)
19611 : {
19612 3291 : for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19613 1515 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19614 1515 : && gimplify_omp_ctxp->loop_iter_var.is_empty ())
19615 : {
19616 74 : error_at (OMP_CLAUSE_LOCATION (c),
19617 : "%<ordered%> construct with %qs clause must be "
19618 : "closely nested inside a loop with %<ordered%> clause",
19619 74 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
19620 74 : failures++;
19621 : }
19622 1441 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19623 1441 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
19624 : {
19625 642 : bool fail = false;
19626 642 : sink_c = c;
19627 642 : if (OMP_CLAUSE_DECL (c) == NULL_TREE)
19628 72 : continue; /* omp_cur_iteration - 1 */
19629 570 : for (decls = OMP_CLAUSE_DECL (c), i = 0;
19630 3201 : decls && TREE_CODE (decls) == TREE_LIST;
19631 2631 : decls = TREE_CHAIN (decls), ++i)
19632 2631 : if (i >= gimplify_omp_ctxp->loop_iter_var.length () / 2)
19633 4 : continue;
19634 5254 : else if (TREE_VALUE (decls)
19635 2627 : != gimplify_omp_ctxp->loop_iter_var[2 * i])
19636 : {
19637 8 : error_at (OMP_CLAUSE_LOCATION (c),
19638 : "variable %qE is not an iteration "
19639 : "of outermost loop %d, expected %qE",
19640 8 : TREE_VALUE (decls), i + 1,
19641 8 : gimplify_omp_ctxp->loop_iter_var[2 * i]);
19642 8 : fail = true;
19643 8 : failures++;
19644 : }
19645 : else
19646 5238 : TREE_VALUE (decls)
19647 2619 : = gimplify_omp_ctxp->loop_iter_var[2 * i + 1];
19648 1136 : if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
19649 : {
19650 16 : error_at (OMP_CLAUSE_LOCATION (c),
19651 : "number of variables in %qs clause with "
19652 : "%<sink%> modifier does not match number of "
19653 : "iteration variables",
19654 16 : OMP_CLAUSE_DOACROSS_DEPEND (c)
19655 : ? "depend" : "doacross");
19656 16 : failures++;
19657 : }
19658 : }
19659 799 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19660 799 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
19661 : {
19662 475 : if (source_c)
19663 : {
19664 4 : error_at (OMP_CLAUSE_LOCATION (c),
19665 : "more than one %qs clause with %<source%> "
19666 : "modifier on an %<ordered%> construct",
19667 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c)
19668 : ? "depend" : "doacross");
19669 4 : failures++;
19670 : }
19671 : else
19672 : source_c = c;
19673 : }
19674 : }
19675 1954 : if (source_c && sink_c)
19676 : {
19677 4 : error_at (OMP_CLAUSE_LOCATION (source_c),
19678 : "%qs clause with %<source%> modifier specified "
19679 : "together with %qs clauses with %<sink%> modifier "
19680 : "on the same construct",
19681 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
19682 4 : OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
19683 4 : failures++;
19684 : }
19685 :
19686 1954 : if (failures)
19687 102 : return gimple_build_nop ();
19688 1852 : return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
19689 : }
19690 :
19691 : /* Gimplify an OMP_INTEROP statement. */
19692 :
19693 : static enum gimplify_status
19694 612 : gimplify_omp_interop (tree *expr_p, gimple_seq *pre_p)
19695 : {
19696 612 : tree expr = *expr_p;
19697 :
19698 612 : gimplify_scan_omp_clauses (&OMP_INTEROP_CLAUSES (expr), pre_p, ORT_TASK,
19699 : OMP_INTEROP);
19700 612 : gimple *stmt = gimple_build_omp_interop (OMP_INTEROP_CLAUSES (expr));
19701 612 : gimplify_seq_add_stmt (pre_p, stmt);
19702 612 : *expr_p = NULL_TREE;
19703 612 : return GS_ALL_DONE;
19704 : }
19705 :
19706 : /* Callback for walk_tree to find an IFN_GOMP_DISPATCH. */
19707 :
19708 : static tree
19709 3100 : find_ifn_gomp_dispatch (tree *tp, int *, void *modify)
19710 : {
19711 3100 : tree t = *tp;
19712 :
19713 3100 : if (TREE_CODE (t) == CALL_EXPR && CALL_EXPR_IFN (t) == IFN_GOMP_DISPATCH)
19714 852 : return *(tree *) modify ? *(tree *) modify : *tp;
19715 :
19716 2248 : if (TREE_CODE (t) == MODIFY_EXPR)
19717 513 : *(tree *) modify = *tp;
19718 :
19719 : return NULL_TREE;
19720 : }
19721 :
19722 : /* Gimplify an OMP_DISPATCH construct. */
19723 :
19724 : static enum gimplify_status
19725 852 : gimplify_omp_dispatch (tree *expr_p, gimple_seq *pre_p)
19726 : {
19727 852 : tree expr = *expr_p;
19728 852 : gimple_seq body = NULL;
19729 :
19730 852 : gimplify_scan_omp_clauses (&OMP_DISPATCH_CLAUSES (expr), pre_p, ORT_DISPATCH,
19731 : OMP_DISPATCH);
19732 852 : push_gimplify_context ();
19733 :
19734 : // If device clause, adjust ICV
19735 852 : tree device
19736 852 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_DEVICE);
19737 : // If no device clause exists but an interop clause with a single list
19738 : // item, use it to obtain the device number.
19739 852 : if (device)
19740 272 : device = OMP_CLAUSE_DEVICE_ID (device);
19741 : else
19742 : {
19743 580 : tree first_interop_obj
19744 580 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_INTEROP);
19745 580 : if (first_interop_obj)
19746 96 : for (tree c = TREE_CHAIN (first_interop_obj); c; c = TREE_CHAIN (c))
19747 8 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INTEROP)
19748 : {
19749 : first_interop_obj = NULL_TREE;
19750 : break;
19751 : }
19752 95 : if (first_interop_obj)
19753 : {
19754 88 : device = create_tmp_var (integer_type_node);
19755 88 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (first_interop_obj),
19756 : OMP_CLAUSE_DEVICE);
19757 88 : OMP_CLAUSE_DEVICE_ID (c) = device;
19758 88 : TREE_CHAIN (c) = TREE_CHAIN (first_interop_obj);
19759 88 : TREE_CHAIN (first_interop_obj) = c;
19760 88 : first_interop_obj = OMP_CLAUSE_DECL (first_interop_obj);
19761 : /* device = omp_get_interop_int (obj, omp_ipr_device_num, NULL); */
19762 88 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_INTEROP_INT);
19763 88 : fn = build_call_expr (fn, 3, first_interop_obj,
19764 : build_int_cst (integer_type_node, -5),
19765 : null_pointer_node);
19766 88 : gimplify_assign (device, fold_convert (integer_type_node, fn), &body);
19767 : }
19768 : }
19769 852 : tree saved_device_icv = NULL_TREE;
19770 852 : if (device
19771 852 : && (TREE_CODE (device) != INTEGER_CST
19772 852 : || !wi::eq_p (wi::to_wide (device), -1 /* omp_initial_device */)))
19773 : {
19774 : // Save current default-device-var ICV
19775 360 : saved_device_icv = create_tmp_var (integer_type_node);
19776 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
19777 360 : gcall *call = gimple_build_call (fn, 0);
19778 360 : gimple_call_set_lhs (call, saved_device_icv);
19779 360 : gimplify_seq_add_stmt (&body, call);
19780 :
19781 : // Set default device
19782 360 : fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19783 360 : call = gimple_build_call (fn, 1, device);
19784 360 : gimplify_seq_add_stmt (&body, call);
19785 : }
19786 :
19787 : // If the novariants and nocontext clauses are not compile-time constants,
19788 : // we need to generate code for all possible cases:
19789 : // if (novariants) // implies nocontext
19790 : // base()
19791 : // else if (nocontext)
19792 : // variant1()
19793 : // else
19794 : // variant2()
19795 852 : tree *dispatch_body_p = &OMP_DISPATCH_BODY (expr);
19796 852 : if (TREE_CODE (*dispatch_body_p) == BIND_EXPR)
19797 28 : dispatch_body_p = &BIND_EXPR_BODY (*dispatch_body_p);
19798 852 : tree dispatch_body = *dispatch_body_p;
19799 :
19800 : // Look for IFN_GOMP_DISPATCH and extract the base function call
19801 852 : tree base_call_expr = NULL_TREE;
19802 852 : if (TREE_CODE (dispatch_body) == STATEMENT_LIST)
19803 243 : for (tree_stmt_iterator tsi = tsi_start (dispatch_body); !tsi_end_p (tsi);
19804 187 : tsi_next (&tsi))
19805 : {
19806 243 : tree modify = NULL_TREE;
19807 243 : tree stmt = tsi_stmt (tsi);
19808 243 : base_call_expr
19809 243 : = walk_tree (&stmt, find_ifn_gomp_dispatch, &modify, NULL);
19810 243 : if (base_call_expr != NULL_TREE)
19811 : break;
19812 : }
19813 : else
19814 : {
19815 796 : tree modify = NULL_TREE;
19816 796 : base_call_expr
19817 796 : = walk_tree (dispatch_body_p, find_ifn_gomp_dispatch, &modify, NULL);
19818 : }
19819 852 : gcc_assert (base_call_expr != NULL_TREE);
19820 :
19821 852 : tree dst = NULL_TREE;
19822 852 : if (TREE_CODE (base_call_expr) == MODIFY_EXPR)
19823 : {
19824 290 : dst = TREE_OPERAND (base_call_expr, 0);
19825 290 : base_call_expr = TREE_OPERAND (base_call_expr, 1);
19826 : }
19827 :
19828 880 : while (TREE_CODE (base_call_expr) == FLOAT_EXPR
19829 : || TREE_CODE (base_call_expr) == CONVERT_EXPR
19830 : || TREE_CODE (base_call_expr) == COMPLEX_EXPR
19831 : || TREE_CODE (base_call_expr) == INDIRECT_REF
19832 880 : || TREE_CODE (base_call_expr) == NOP_EXPR)
19833 28 : base_call_expr = TREE_OPERAND (base_call_expr, 0);
19834 :
19835 852 : gcc_assert (CALL_EXPR_IFN (base_call_expr) == IFN_GOMP_DISPATCH);
19836 852 : base_call_expr = CALL_EXPR_ARG (base_call_expr, 0);
19837 :
19838 852 : tree base_fndecl = get_callee_fndecl (base_call_expr);
19839 852 : if (base_fndecl != NULL_TREE)
19840 : {
19841 844 : if (DECL_VIRTUAL_P (base_fndecl))
19842 : {
19843 6 : error_at (
19844 3 : EXPR_LOCATION (base_call_expr),
19845 : "%qD is a virtual function but only a direct call is allowed "
19846 : "in a dispatch construct",
19847 3 : DECL_NAME (base_fndecl));
19848 : }
19849 :
19850 : /* We are not actually going to expand the variant call or use
19851 : the result of omp_get_dynamic candidates here; only check that
19852 : it does not trivially resolve to a call to the base function
19853 : so that we can avoid some extra work in building code that's
19854 : not needed in that case. */
19855 844 : tree construct_context = omp_get_construct_context ();
19856 844 : vec<struct omp_variant> all_candidates
19857 844 : = omp_declare_variant_candidates (base_fndecl, construct_context);
19858 844 : gcc_assert (!all_candidates.is_empty ());
19859 844 : vec<struct omp_variant> candidates
19860 844 : = omp_get_dynamic_candidates (all_candidates, construct_context);
19861 844 : tree variant_fndecl
19862 1676 : = (candidates.length () == 1 ? candidates[0].alternative : NULL_TREE);
19863 :
19864 844 : if (base_fndecl != variant_fndecl
19865 844 : && (omp_has_novariants () == -1 || omp_has_nocontext () == -1))
19866 : {
19867 22 : tree novariants_clause = NULL_TREE, nocontext_clause = NULL_TREE,
19868 22 : novariants_cond = NULL_TREE, nocontext_cond = NULL_TREE;
19869 59 : for (tree c = OMP_DISPATCH_CLAUSES (expr); c; c = TREE_CHAIN (c))
19870 : {
19871 37 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOVARIANTS
19872 37 : && !integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
19873 : {
19874 16 : gcc_assert (novariants_cond == NULL_TREE);
19875 16 : novariants_clause = c;
19876 16 : novariants_cond = OMP_CLAUSE_NOVARIANTS_EXPR (c);
19877 : }
19878 21 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOCONTEXT
19879 21 : && !integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
19880 : {
19881 16 : gcc_assert (nocontext_cond == NULL_TREE);
19882 16 : nocontext_clause = c;
19883 16 : nocontext_cond = OMP_CLAUSE_NOCONTEXT_EXPR (c);
19884 : }
19885 : }
19886 22 : gcc_assert (novariants_cond != NULL_TREE
19887 : || nocontext_cond != NULL_TREE);
19888 :
19889 22 : enum gimplify_status ret
19890 22 : = gimplify_expr (&novariants_cond, &body, NULL, is_gimple_val,
19891 : fb_rvalue);
19892 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19893 0 : return ret;
19894 22 : ret = gimplify_expr (&nocontext_cond, &body, NULL, is_gimple_val,
19895 : fb_rvalue);
19896 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19897 : return ret;
19898 :
19899 22 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19900 :
19901 22 : if (novariants_cond != NULL_TREE)
19902 : {
19903 16 : tree base_label = create_artificial_label (UNKNOWN_LOCATION);
19904 16 : tree cond_label = create_artificial_label (UNKNOWN_LOCATION);
19905 16 : gcond *novariants_cond_stmt
19906 16 : = gimple_build_cond_from_tree (novariants_cond, base_label,
19907 : cond_label);
19908 16 : gimplify_seq_add_stmt (&body, novariants_cond_stmt);
19909 :
19910 16 : gimplify_seq_add_stmt (&body, gimple_build_label (base_label));
19911 16 : tree base_call_expr2 = copy_node (base_call_expr);
19912 16 : base_call_expr2
19913 16 : = build_call_expr_internal_loc (EXPR_LOCATION (base_call_expr2),
19914 : IFN_GOMP_DISPATCH,
19915 16 : TREE_TYPE (base_call_expr2), 1,
19916 : base_call_expr2);
19917 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19918 : {
19919 16 : base_call_expr2 = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19920 : base_call_expr2);
19921 : }
19922 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19923 16 : = boolean_true_node;
19924 16 : gimplify_and_add (base_call_expr2, &body);
19925 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19926 :
19927 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19928 16 : = boolean_false_node;
19929 16 : gimplify_seq_add_stmt (&body, gimple_build_label (cond_label));
19930 : }
19931 :
19932 22 : if (nocontext_cond != NULL_TREE)
19933 : {
19934 16 : tree variant1_label = create_artificial_label (UNKNOWN_LOCATION);
19935 16 : tree variant2_label = create_artificial_label (UNKNOWN_LOCATION);
19936 16 : gcond *nocontext_cond_stmt
19937 16 : = gimple_build_cond_from_tree (nocontext_cond, variant1_label,
19938 : variant2_label);
19939 16 : gimplify_seq_add_stmt (&body, nocontext_cond_stmt);
19940 :
19941 32 : gimplify_seq_add_stmt (&body,
19942 16 : gimple_build_label (variant1_label));
19943 16 : tree variant_call_expr = copy_node (base_call_expr);
19944 32 : variant_call_expr = build_call_expr_internal_loc (
19945 16 : EXPR_LOCATION (variant_call_expr), IFN_GOMP_DISPATCH,
19946 16 : TREE_TYPE (variant_call_expr), 1, variant_call_expr);
19947 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19948 : {
19949 16 : variant_call_expr = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19950 : variant_call_expr);
19951 : }
19952 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_true_node;
19953 16 : gimplify_and_add (variant_call_expr, &body);
19954 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19955 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_false_node;
19956 32 : gimplify_seq_add_stmt (&body,
19957 16 : gimple_build_label (variant2_label));
19958 : }
19959 :
19960 22 : tree variant_call_expr = base_call_expr;
19961 22 : variant_call_expr
19962 22 : = build_call_expr_internal_loc (EXPR_LOCATION (variant_call_expr),
19963 : IFN_GOMP_DISPATCH,
19964 22 : TREE_TYPE (variant_call_expr), 1,
19965 : variant_call_expr);
19966 22 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19967 : {
19968 22 : variant_call_expr
19969 22 : = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, variant_call_expr);
19970 : }
19971 22 : gimplify_and_add (variant_call_expr, &body);
19972 22 : gimplify_seq_add_stmt (&body, gimple_build_label (end_label));
19973 : }
19974 : else
19975 822 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19976 : }
19977 : else
19978 8 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19979 :
19980 : // Restore default-device-var ICV
19981 852 : if (saved_device_icv != NULL_TREE)
19982 : {
19983 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19984 360 : gcall *call = gimple_build_call (fn, 1, saved_device_icv);
19985 360 : gimplify_seq_add_stmt (&body, call);
19986 : }
19987 :
19988 : // Wrap dispatch body into a bind
19989 852 : gimple *bind = gimple_build_bind (NULL_TREE, body, NULL_TREE);
19990 852 : pop_gimplify_context (bind);
19991 :
19992 : // Manually tear down context created by gimplify_scan_omp_clauses to avoid a
19993 : // call to gimplify_adjust_omp_clauses
19994 852 : gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
19995 852 : if (ctx != NULL)
19996 : {
19997 852 : gcc_assert (ctx->code == OMP_DISPATCH);
19998 852 : gimplify_omp_ctxp = ctx->outer_context;
19999 852 : delete_omp_context (ctx);
20000 : }
20001 :
20002 : // Remove nowait as it has no effect on dispatch (OpenMP 5.2), device as it
20003 : // has been handled above, and depend as the front end handled it by inserting
20004 : // taskwait.
20005 852 : tree *dispatch_clauses_ptr = &OMP_DISPATCH_CLAUSES (expr);
20006 1445 : for (tree c = *dispatch_clauses_ptr; c; c = *dispatch_clauses_ptr)
20007 : {
20008 991 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT
20009 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
20010 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE)
20011 : {
20012 398 : *dispatch_clauses_ptr = OMP_CLAUSE_CHAIN (c);
20013 398 : break;
20014 : }
20015 : else
20016 593 : dispatch_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
20017 : }
20018 :
20019 852 : gimple *stmt = gimple_build_omp_dispatch (bind, OMP_DISPATCH_CLAUSES (expr));
20020 852 : gimplify_seq_add_stmt (pre_p, stmt);
20021 852 : *expr_p = NULL_TREE;
20022 852 : return GS_ALL_DONE;
20023 : }
20024 :
20025 : /* Expand a metadirective that has been resolved at gimplification time
20026 : into the candidate directive variants in CANDIDATES. */
20027 :
20028 : static enum gimplify_status
20029 175 : expand_omp_metadirective (vec<struct omp_variant> &candidates,
20030 : gimple_seq *pre_p)
20031 : {
20032 175 : auto_vec<tree> selectors;
20033 175 : auto_vec<tree> directive_labels;
20034 175 : auto_vec<gimple_seq> directive_bodies;
20035 175 : tree body_label = NULL_TREE;
20036 175 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
20037 :
20038 : /* Construct bodies for each candidate. */
20039 605 : for (unsigned i = 0; i < candidates.length(); i++)
20040 : {
20041 255 : struct omp_variant &candidate = candidates[i];
20042 255 : gimple_seq body = NULL;
20043 :
20044 255 : selectors.safe_push (omp_dynamic_cond (candidate.selector,
20045 : find_supercontext ()));
20046 255 : directive_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
20047 :
20048 255 : gimplify_seq_add_stmt (&body,
20049 255 : gimple_build_label (directive_labels.last ()));
20050 255 : if (candidate.alternative != NULL_TREE)
20051 255 : gimplify_stmt (&candidate.alternative, &body);
20052 255 : if (candidate.body != NULL_TREE)
20053 : {
20054 36 : if (body_label != NULL_TREE)
20055 0 : gimplify_seq_add_stmt (&body, gimple_build_goto (body_label));
20056 : else
20057 : {
20058 36 : body_label = create_artificial_label (UNKNOWN_LOCATION);
20059 36 : gimplify_seq_add_stmt (&body, gimple_build_label (body_label));
20060 36 : gimplify_stmt (&candidate.body, &body);
20061 : }
20062 : }
20063 :
20064 255 : directive_bodies.safe_push (body);
20065 : }
20066 :
20067 175 : auto_vec<tree> cond_labels;
20068 :
20069 175 : cond_labels.safe_push (NULL_TREE);
20070 386 : for (unsigned i = 1; i < candidates.length () - 1; i++)
20071 18 : cond_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
20072 175 : if (candidates.length () > 1)
20073 62 : cond_labels.safe_push (directive_labels.last ());
20074 :
20075 : /* Generate conditionals to test each dynamic selector in turn, executing
20076 : the directive candidate if successful. */
20077 510 : for (unsigned i = 0; i < candidates.length () - 1; i++)
20078 : {
20079 80 : if (i != 0)
20080 18 : gimplify_seq_add_stmt (pre_p, gimple_build_label (cond_labels [i]));
20081 :
20082 80 : enum gimplify_status ret = gimplify_expr (&selectors[i], pre_p, NULL,
20083 : is_gimple_val, fb_rvalue);
20084 80 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
20085 : return ret;
20086 :
20087 80 : gcond *cond_stmt
20088 80 : = gimple_build_cond_from_tree (selectors[i], directive_labels[i],
20089 80 : cond_labels[i + 1]);
20090 :
20091 80 : gimplify_seq_add_stmt (pre_p, cond_stmt);
20092 80 : gimplify_seq_add_seq (pre_p, directive_bodies[i]);
20093 80 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (end_label));
20094 : }
20095 :
20096 175 : gimplify_seq_add_seq (pre_p, directive_bodies.last ());
20097 175 : gimplify_seq_add_stmt (pre_p, gimple_build_label (end_label));
20098 :
20099 175 : return GS_ALL_DONE;
20100 175 : }
20101 :
20102 : /* Expand a variant construct that requires late resolution in the ompdevlow
20103 : pass. It's a bit easier to do this in tree form and then gimplify that,
20104 : than to emit gimple. The output is going to look something like:
20105 :
20106 : switch_var = OMP_NEXT_VARIANT (0, state);
20107 : loop_label:
20108 : switch (switch_var)
20109 : {
20110 : case 1:
20111 : if (dynamic_selector_predicate_1)
20112 : {
20113 : alternative_1;
20114 : goto end_label;
20115 : }
20116 : else
20117 : {
20118 : switch_var = OMP_NEXT_VARIANT (1, state);
20119 : goto loop_label;
20120 : }
20121 : case 2:
20122 : ...
20123 : }
20124 : end_label:
20125 :
20126 : OMP_NEXT_VARIANT is a magic cookie that is replaced with the switch variable
20127 : index of the next variant to try, after late resolution. */
20128 :
20129 : static tree
20130 16 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
20131 : tree construct_context)
20132 : {
20133 16 : tree body_label = NULL_TREE;
20134 16 : tree standalone_body = NULL_TREE;
20135 16 : tree loop_label = create_artificial_label (UNKNOWN_LOCATION);
20136 16 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
20137 32 : tree selectors = make_tree_vec (all_candidates.length ());
20138 16 : tree switch_body = NULL_TREE;
20139 16 : tree switch_var = create_tmp_var (integer_type_node, "variant");
20140 16 : tree state = tree_cons (NULL_TREE, construct_context, selectors);
20141 :
20142 108 : for (unsigned int i = 0; i < all_candidates.length (); i++)
20143 : {
20144 76 : tree selector = all_candidates[i].selector;
20145 76 : tree alternative = all_candidates[i].alternative;
20146 76 : tree body = all_candidates[i].body;
20147 76 : TREE_VEC_ELT (selectors, i) = selector;
20148 :
20149 : /* Case label. Numbering is 1-based. */
20150 76 : tree case_val = build_int_cst (integer_type_node, i + 1);
20151 76 : tree case_label
20152 76 : = build_case_label (case_val, NULL_TREE,
20153 : create_artificial_label (UNKNOWN_LOCATION));
20154 76 : append_to_statement_list (case_label, &switch_body);
20155 :
20156 : /* The actual body of the variant. */
20157 76 : tree variant_body = NULL_TREE;
20158 76 : append_to_statement_list (alternative, &variant_body);
20159 :
20160 76 : if (body != NULL_TREE)
20161 : {
20162 0 : if (standalone_body == NULL)
20163 : {
20164 0 : standalone_body = body;
20165 0 : body_label = create_artificial_label (UNKNOWN_LOCATION);
20166 : }
20167 0 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20168 : body_label),
20169 : &variant_body);
20170 : }
20171 : else
20172 76 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20173 : end_label),
20174 : &variant_body);
20175 :
20176 : /* If this is a dynamic selector, wrap variant_body with a conditional.
20177 : If the predicate doesn't match, the else clause sets switch_var and
20178 : jumps to loop_var to try again. */
20179 76 : tree dynamic_selector = omp_dynamic_cond (selector, find_supercontext ());
20180 76 : if (dynamic_selector)
20181 : {
20182 20 : tree else_stmt = NULL_TREE;
20183 20 : tree next = build2 (OMP_NEXT_VARIANT, integer_type_node,
20184 : case_val, state);
20185 20 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20186 : switch_var, next),
20187 : &else_stmt);
20188 20 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20189 : loop_label),
20190 : &else_stmt);
20191 20 : variant_body = build3 (COND_EXPR, void_type_node, dynamic_selector,
20192 : variant_body, else_stmt);
20193 : }
20194 76 : append_to_statement_list (variant_body, &switch_body);
20195 : }
20196 :
20197 : /* Put it all together. */
20198 16 : tree result = NULL_TREE;
20199 16 : tree first = build2 (OMP_NEXT_VARIANT, integer_type_node, integer_zero_node,
20200 : state);
20201 16 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20202 : switch_var, first),
20203 : &result);
20204 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, loop_label),
20205 : &result);
20206 16 : append_to_statement_list (build2 (SWITCH_EXPR, integer_type_node,
20207 : switch_var, switch_body),
20208 : &result);
20209 16 : if (standalone_body)
20210 : {
20211 0 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
20212 : body_label),
20213 : &result);
20214 0 : append_to_statement_list (standalone_body, &result);
20215 : }
20216 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, end_label),
20217 : &result);
20218 16 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
20219 16 : return result;
20220 : }
20221 :
20222 :
20223 : /* Gimplify an OMP_METADIRECTIVE construct. EXPR is the tree version.
20224 : The metadirective will be resolved at this point if possible, otherwise
20225 : a GIMPLE_OMP_VARIANT_CONSTRUCT is created. */
20226 :
20227 : static enum gimplify_status
20228 179 : gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *,
20229 : bool (*) (tree), fallback_t)
20230 : {
20231 : /* Try to resolve the metadirective. */
20232 179 : tree construct_context = omp_get_construct_context ();
20233 179 : vec<struct omp_variant> all_candidates
20234 179 : = omp_metadirective_candidates (*expr_p, construct_context);
20235 179 : vec<struct omp_variant> candidates
20236 179 : = omp_get_dynamic_candidates (all_candidates, construct_context);
20237 179 : if (!candidates.is_empty ())
20238 175 : return expand_omp_metadirective (candidates, pre_p);
20239 :
20240 : /* The metadirective cannot be resolved yet. Turn it into a loop with
20241 : a nested switch statement, using OMP_NEXT_VARIANT to set the control
20242 : variable for the switch. */
20243 4 : *expr_p = expand_late_variant_directive (all_candidates, construct_context);
20244 4 : return GS_OK;
20245 : }
20246 :
20247 : /* Gimplify an OMP_DECLARE_MAPPER node (by just removing it). */
20248 :
20249 : static enum gimplify_status
20250 0 : gimplify_omp_declare_mapper (tree *expr_p)
20251 : {
20252 0 : *expr_p = NULL_TREE;
20253 0 : return GS_ALL_DONE;
20254 : }
20255 :
20256 : /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
20257 : expression produces a value to be used as an operand inside a GIMPLE
20258 : statement, the value will be stored back in *EXPR_P. This value will
20259 : be a tree of class tcc_declaration, tcc_constant, tcc_reference or
20260 : an SSA_NAME. The corresponding sequence of GIMPLE statements is
20261 : emitted in PRE_P and POST_P.
20262 :
20263 : Additionally, this process may overwrite parts of the input
20264 : expression during gimplification. Ideally, it should be
20265 : possible to do non-destructive gimplification.
20266 :
20267 : EXPR_P points to the GENERIC expression to convert to GIMPLE. If
20268 : the expression needs to evaluate to a value to be used as
20269 : an operand in a GIMPLE statement, this value will be stored in
20270 : *EXPR_P on exit. This happens when the caller specifies one
20271 : of fb_lvalue or fb_rvalue fallback flags.
20272 :
20273 : PRE_P will contain the sequence of GIMPLE statements corresponding
20274 : to the evaluation of EXPR and all the side-effects that must
20275 : be executed before the main expression. On exit, the last
20276 : statement of PRE_P is the core statement being gimplified. For
20277 : instance, when gimplifying 'if (++a)' the last statement in
20278 : PRE_P will be 'if (t.1)' where t.1 is the result of
20279 : pre-incrementing 'a'.
20280 :
20281 : POST_P will contain the sequence of GIMPLE statements corresponding
20282 : to the evaluation of all the side-effects that must be executed
20283 : after the main expression. If this is NULL, the post
20284 : side-effects are stored at the end of PRE_P.
20285 :
20286 : The reason why the output is split in two is to handle post
20287 : side-effects explicitly. In some cases, an expression may have
20288 : inner and outer post side-effects which need to be emitted in
20289 : an order different from the one given by the recursive
20290 : traversal. For instance, for the expression (*p--)++ the post
20291 : side-effects of '--' must actually occur *after* the post
20292 : side-effects of '++'. However, gimplification will first visit
20293 : the inner expression, so if a separate POST sequence was not
20294 : used, the resulting sequence would be:
20295 :
20296 : 1 t.1 = *p
20297 : 2 p = p - 1
20298 : 3 t.2 = t.1 + 1
20299 : 4 *p = t.2
20300 :
20301 : However, the post-decrement operation in line #2 must not be
20302 : evaluated until after the store to *p at line #4, so the
20303 : correct sequence should be:
20304 :
20305 : 1 t.1 = *p
20306 : 2 t.2 = t.1 + 1
20307 : 3 *p = t.2
20308 : 4 p = p - 1
20309 :
20310 : So, by specifying a separate post queue, it is possible
20311 : to emit the post side-effects in the correct order.
20312 : If POST_P is NULL, an internal queue will be used. Before
20313 : returning to the caller, the sequence POST_P is appended to
20314 : the main output sequence PRE_P.
20315 :
20316 : GIMPLE_TEST_F points to a function that takes a tree T and
20317 : returns nonzero if T is in the GIMPLE form requested by the
20318 : caller. The GIMPLE predicates are in gimple.cc.
20319 :
20320 : FALLBACK tells the function what sort of a temporary we want if
20321 : gimplification cannot produce an expression that complies with
20322 : GIMPLE_TEST_F.
20323 :
20324 : fb_none means that no temporary should be generated
20325 : fb_rvalue means that an rvalue is OK to generate
20326 : fb_lvalue means that an lvalue is OK to generate
20327 : fb_either means that either is OK, but an lvalue is preferable.
20328 : fb_mayfail means that gimplification may fail (in which case
20329 : GS_ERROR will be returned)
20330 :
20331 : The return value is either GS_ERROR or GS_ALL_DONE, since this
20332 : function iterates until EXPR is completely gimplified or an error
20333 : occurs. */
20334 :
20335 : enum gimplify_status
20336 531755877 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
20337 : bool (*gimple_test_f) (tree), fallback_t fallback)
20338 : {
20339 531755877 : tree tmp;
20340 531755877 : gimple_seq internal_pre = NULL;
20341 531755877 : gimple_seq internal_post = NULL;
20342 531755877 : tree save_expr;
20343 531755877 : bool is_statement;
20344 531755877 : location_t saved_location;
20345 531755877 : enum gimplify_status ret;
20346 531755877 : gimple_stmt_iterator pre_last_gsi, post_last_gsi;
20347 531755877 : tree label;
20348 :
20349 531755877 : save_expr = *expr_p;
20350 531755877 : if (save_expr == NULL_TREE)
20351 : return GS_ALL_DONE;
20352 :
20353 : /* If we are gimplifying a top-level statement, PRE_P must be valid. */
20354 478513032 : is_statement = gimple_test_f == is_gimple_stmt;
20355 478513032 : if (is_statement)
20356 103736426 : gcc_assert (pre_p);
20357 :
20358 : /* Consistency checks. */
20359 478513032 : if (gimple_test_f == is_gimple_reg)
20360 6497988 : gcc_assert (fallback & (fb_rvalue | fb_lvalue));
20361 472015044 : else if (gimple_test_f == is_gimple_val
20362 348108697 : || gimple_test_f == is_gimple_call_addr
20363 331118915 : || gimple_test_f == is_gimple_condexpr_for_cond
20364 325416835 : || gimple_test_f == is_gimple_mem_rhs
20365 325272553 : || gimple_test_f == is_gimple_mem_rhs_or_call
20366 313762143 : || gimple_test_f == is_gimple_reg_rhs
20367 313156158 : || gimple_test_f == is_gimple_reg_rhs_or_call
20368 239706929 : || gimple_test_f == is_gimple_asm_val
20369 239666974 : || gimple_test_f == is_gimple_mem_ref_addr)
20370 248230243 : gcc_assert (fallback & fb_rvalue);
20371 223784801 : else if (gimple_test_f == is_gimple_min_lval
20372 192820302 : || gimple_test_f == is_gimple_lvalue)
20373 85690810 : gcc_assert (fallback & fb_lvalue);
20374 138093991 : else if (gimple_test_f == is_gimple_addressable)
20375 34357565 : gcc_assert (fallback & fb_either);
20376 103736426 : else if (gimple_test_f == is_gimple_stmt)
20377 103736426 : gcc_assert (fallback == fb_none);
20378 : else
20379 : {
20380 : /* We should have recognized the GIMPLE_TEST_F predicate to
20381 : know what kind of fallback to use in case a temporary is
20382 : needed to hold the value or address of *EXPR_P. */
20383 0 : gcc_unreachable ();
20384 : }
20385 :
20386 : /* We used to check the predicate here and return immediately if it
20387 : succeeds. This is wrong; the design is for gimplification to be
20388 : idempotent, and for the predicates to only test for valid forms, not
20389 : whether they are fully simplified. */
20390 478513032 : if (pre_p == NULL)
20391 0 : pre_p = &internal_pre;
20392 :
20393 478513032 : if (post_p == NULL)
20394 193035445 : post_p = &internal_post;
20395 :
20396 : /* Remember the last statements added to PRE_P and POST_P. Every
20397 : new statement added by the gimplification helpers needs to be
20398 : annotated with location information. To centralize the
20399 : responsibility, we remember the last statement that had been
20400 : added to both queues before gimplifying *EXPR_P. If
20401 : gimplification produces new statements in PRE_P and POST_P, those
20402 : statements will be annotated with the same location information
20403 : as *EXPR_P. */
20404 478513032 : pre_last_gsi = gsi_last (*pre_p);
20405 478513032 : post_last_gsi = gsi_last (*post_p);
20406 :
20407 478513032 : saved_location = input_location;
20408 478513032 : if (save_expr != error_mark_node
20409 478513032 : && EXPR_HAS_LOCATION (*expr_p))
20410 179672384 : input_location = EXPR_LOCATION (*expr_p);
20411 :
20412 : /* Loop over the specific gimplifiers until the toplevel node
20413 : remains the same. */
20414 497550930 : do
20415 : {
20416 : /* Strip away as many useless type conversions as possible
20417 : at the toplevel. */
20418 497550930 : STRIP_USELESS_TYPE_CONVERSION (*expr_p);
20419 :
20420 : /* Remember the expr. */
20421 497550930 : save_expr = *expr_p;
20422 :
20423 : /* Die, die, die, my darling. */
20424 497550930 : if (error_operand_p (save_expr))
20425 : {
20426 : ret = GS_ERROR;
20427 : break;
20428 : }
20429 :
20430 : /* Do any language-specific gimplification. */
20431 497547245 : ret = ((enum gimplify_status)
20432 497547245 : lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
20433 497547245 : if (ret == GS_OK)
20434 : {
20435 30220964 : if (*expr_p == NULL_TREE)
20436 : break;
20437 30220964 : if (*expr_p != save_expr)
20438 5049707 : continue;
20439 : }
20440 467326281 : else if (ret != GS_UNHANDLED)
20441 : break;
20442 :
20443 : /* Make sure that all the cases set 'ret' appropriately. */
20444 491881442 : ret = GS_UNHANDLED;
20445 491881442 : switch (TREE_CODE (*expr_p))
20446 : {
20447 : /* First deal with the special cases. */
20448 :
20449 1147886 : case POSTINCREMENT_EXPR:
20450 1147886 : case POSTDECREMENT_EXPR:
20451 1147886 : case PREINCREMENT_EXPR:
20452 1147886 : case PREDECREMENT_EXPR:
20453 2295772 : ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
20454 : fallback != fb_none,
20455 1147886 : TREE_TYPE (*expr_p));
20456 1147886 : break;
20457 :
20458 604704 : case VIEW_CONVERT_EXPR:
20459 604704 : if ((fallback & fb_rvalue)
20460 604590 : && is_gimple_reg_type (TREE_TYPE (*expr_p))
20461 1032234 : && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
20462 : {
20463 415643 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20464 : post_p, is_gimple_val, fb_rvalue);
20465 415643 : recalculate_side_effects (*expr_p);
20466 415643 : break;
20467 : }
20468 : /* Fallthru. */
20469 :
20470 30901455 : case ARRAY_REF:
20471 30901455 : case ARRAY_RANGE_REF:
20472 30901455 : case REALPART_EXPR:
20473 30901455 : case IMAGPART_EXPR:
20474 30901455 : case COMPONENT_REF:
20475 30901455 : ret = gimplify_compound_lval (expr_p, pre_p, post_p,
20476 : fallback ? fallback : fb_rvalue);
20477 30901455 : break;
20478 :
20479 6329445 : case COND_EXPR:
20480 6329445 : ret = gimplify_cond_expr (expr_p, pre_p, fallback);
20481 :
20482 : /* C99 code may assign to an array in a structure value of a
20483 : conditional expression, and this has undefined behavior
20484 : only on execution, so create a temporary if an lvalue is
20485 : required. */
20486 6329445 : if (fallback == fb_lvalue)
20487 : {
20488 7 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20489 7 : mark_addressable (*expr_p);
20490 7 : ret = GS_OK;
20491 : }
20492 : break;
20493 :
20494 17554339 : case CALL_EXPR:
20495 17554339 : ret = gimplify_call_expr (expr_p, pre_p, fallback);
20496 :
20497 : /* C99 code may assign to an array in a structure returned
20498 : from a function, and this has undefined behavior only on
20499 : execution, so create a temporary if an lvalue is
20500 : required. */
20501 17554339 : if (fallback == fb_lvalue)
20502 : {
20503 17155 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20504 17155 : mark_addressable (*expr_p);
20505 17155 : ret = GS_OK;
20506 : }
20507 : break;
20508 :
20509 0 : case TREE_LIST:
20510 0 : gcc_unreachable ();
20511 :
20512 0 : case OMP_ARRAY_SECTION:
20513 0 : gcc_unreachable ();
20514 :
20515 503277 : case COMPOUND_EXPR:
20516 503277 : ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
20517 503277 : break;
20518 :
20519 37242 : case COMPOUND_LITERAL_EXPR:
20520 37242 : ret = gimplify_compound_literal_expr (expr_p, pre_p,
20521 : gimple_test_f, fallback);
20522 37242 : break;
20523 :
20524 51338796 : case MODIFY_EXPR:
20525 51338796 : case INIT_EXPR:
20526 51338796 : ret = gimplify_modify_expr (expr_p, pre_p, post_p,
20527 : fallback != fb_none);
20528 51338796 : break;
20529 :
20530 117034 : case TRUTH_ANDIF_EXPR:
20531 117034 : case TRUTH_ORIF_EXPR:
20532 117034 : {
20533 : /* Preserve the original type of the expression and the
20534 : source location of the outer expression. */
20535 117034 : tree org_type = TREE_TYPE (*expr_p);
20536 117034 : *expr_p = gimple_boolify (*expr_p);
20537 117034 : *expr_p = build3_loc (input_location, COND_EXPR,
20538 : org_type, *expr_p,
20539 : fold_convert_loc
20540 : (input_location,
20541 : org_type, boolean_true_node),
20542 : fold_convert_loc
20543 : (input_location,
20544 : org_type, boolean_false_node));
20545 117034 : ret = GS_OK;
20546 117034 : break;
20547 : }
20548 :
20549 238889 : case TRUTH_NOT_EXPR:
20550 238889 : {
20551 238889 : tree type = TREE_TYPE (*expr_p);
20552 : /* The parsers are careful to generate TRUTH_NOT_EXPR
20553 : only with operands that are always zero or one.
20554 : We do not fold here but handle the only interesting case
20555 : manually, as fold may re-introduce the TRUTH_NOT_EXPR. */
20556 238889 : *expr_p = gimple_boolify (*expr_p);
20557 238889 : if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
20558 238889 : *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
20559 238889 : TREE_TYPE (*expr_p),
20560 238889 : TREE_OPERAND (*expr_p, 0));
20561 : else
20562 0 : *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
20563 0 : TREE_TYPE (*expr_p),
20564 0 : TREE_OPERAND (*expr_p, 0),
20565 0 : build_int_cst (TREE_TYPE (*expr_p), 1));
20566 238889 : if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
20567 6514 : *expr_p = fold_convert_loc (input_location, type, *expr_p);
20568 : ret = GS_OK;
20569 : break;
20570 : }
20571 :
20572 34440966 : case ADDR_EXPR:
20573 34440966 : ret = gimplify_addr_expr (expr_p, pre_p, post_p);
20574 34440966 : break;
20575 :
20576 5801 : case ANNOTATE_EXPR:
20577 5801 : {
20578 5801 : tree cond = TREE_OPERAND (*expr_p, 0);
20579 5801 : tree kind = TREE_OPERAND (*expr_p, 1);
20580 5801 : tree data = TREE_OPERAND (*expr_p, 2);
20581 5801 : tree type = TREE_TYPE (cond);
20582 5801 : if (!INTEGRAL_TYPE_P (type))
20583 : {
20584 0 : *expr_p = cond;
20585 0 : ret = GS_OK;
20586 0 : break;
20587 : }
20588 5801 : tree tmp = create_tmp_var (type);
20589 5801 : gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
20590 5801 : gcall *call
20591 5801 : = gimple_build_call_internal (IFN_ANNOTATE, 3, cond, kind, data);
20592 5801 : gimple_call_set_lhs (call, tmp);
20593 5801 : gimplify_seq_add_stmt (pre_p, call);
20594 5801 : *expr_p = tmp;
20595 5801 : ret = GS_ALL_DONE;
20596 5801 : break;
20597 : }
20598 :
20599 51195 : case VA_ARG_EXPR:
20600 51195 : ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
20601 51195 : break;
20602 :
20603 17811072 : CASE_CONVERT:
20604 17811072 : if (IS_EMPTY_STMT (*expr_p))
20605 : {
20606 : ret = GS_ALL_DONE;
20607 : break;
20608 : }
20609 :
20610 16035245 : if (VOID_TYPE_P (TREE_TYPE (*expr_p))
20611 16035245 : || fallback == fb_none)
20612 : {
20613 : /* Just strip a conversion to void (or in void context) and
20614 : try again. */
20615 2766903 : *expr_p = TREE_OPERAND (*expr_p, 0);
20616 2766903 : ret = GS_OK;
20617 2766903 : break;
20618 : }
20619 :
20620 13268342 : ret = gimplify_conversion (expr_p);
20621 13268342 : if (ret == GS_ERROR)
20622 : break;
20623 13268342 : if (*expr_p != save_expr)
20624 : break;
20625 : /* FALLTHRU */
20626 :
20627 13396391 : case FIX_TRUNC_EXPR:
20628 : /* unary_expr: ... | '(' cast ')' val | ... */
20629 13396391 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20630 : is_gimple_val, fb_rvalue);
20631 13396391 : recalculate_side_effects (*expr_p);
20632 13396391 : break;
20633 :
20634 6428786 : case INDIRECT_REF:
20635 6428786 : {
20636 6428786 : bool volatilep = TREE_THIS_VOLATILE (*expr_p);
20637 6428786 : bool notrap = TREE_THIS_NOTRAP (*expr_p);
20638 6428786 : tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
20639 :
20640 6428786 : *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
20641 6428786 : if (*expr_p != save_expr)
20642 : {
20643 : ret = GS_OK;
20644 : break;
20645 : }
20646 :
20647 6410165 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20648 : is_gimple_reg, fb_rvalue);
20649 6410165 : if (ret == GS_ERROR)
20650 : break;
20651 :
20652 6410164 : recalculate_side_effects (*expr_p);
20653 12820328 : *expr_p = fold_build2_loc (input_location, MEM_REF,
20654 6410164 : TREE_TYPE (*expr_p),
20655 6410164 : TREE_OPERAND (*expr_p, 0),
20656 : build_int_cst (saved_ptr_type, 0));
20657 6410164 : TREE_THIS_VOLATILE (*expr_p) = volatilep;
20658 6410164 : TREE_THIS_NOTRAP (*expr_p) = notrap;
20659 6410164 : ret = GS_OK;
20660 6410164 : break;
20661 : }
20662 :
20663 : /* We arrive here through the various re-gimplifcation paths. */
20664 16332025 : case MEM_REF:
20665 : /* First try re-folding the whole thing. */
20666 16332025 : tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
20667 : TREE_OPERAND (*expr_p, 0),
20668 : TREE_OPERAND (*expr_p, 1));
20669 16332025 : if (tmp)
20670 : {
20671 6580 : REF_REVERSE_STORAGE_ORDER (tmp)
20672 3290 : = REF_REVERSE_STORAGE_ORDER (*expr_p);
20673 3290 : *expr_p = tmp;
20674 3290 : recalculate_side_effects (*expr_p);
20675 3290 : ret = GS_OK;
20676 3290 : break;
20677 : }
20678 : /* Avoid re-gimplifying the address operand if it is already
20679 : in suitable form. Re-gimplifying would mark the address
20680 : operand addressable. Always gimplify when not in SSA form
20681 : as we still may have to gimplify decls with value-exprs. */
20682 16328735 : if (!gimplify_ctxp || !gimple_in_ssa_p (cfun)
20683 17348690 : || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
20684 : {
20685 15363965 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20686 : is_gimple_mem_ref_addr, fb_rvalue);
20687 15363965 : if (ret == GS_ERROR)
20688 : break;
20689 : }
20690 16328735 : recalculate_side_effects (*expr_p);
20691 16328735 : ret = GS_ALL_DONE;
20692 16328735 : break;
20693 :
20694 : /* Constants need not be gimplified. */
20695 45059321 : case INTEGER_CST:
20696 45059321 : case REAL_CST:
20697 45059321 : case FIXED_CST:
20698 45059321 : case STRING_CST:
20699 45059321 : case COMPLEX_CST:
20700 45059321 : case VECTOR_CST:
20701 : /* Drop the overflow flag on constants, we do not want
20702 : that in the GIMPLE IL. */
20703 45059321 : if (TREE_OVERFLOW_P (*expr_p))
20704 887 : *expr_p = drop_tree_overflow (*expr_p);
20705 : ret = GS_ALL_DONE;
20706 : break;
20707 :
20708 118507 : case CONST_DECL:
20709 : /* If we require an lvalue, such as for ADDR_EXPR, retain the
20710 : CONST_DECL node. Otherwise the decl is replaceable by its
20711 : value. */
20712 : /* ??? Should be == fb_lvalue, but ADDR_EXPR passes fb_either. */
20713 118507 : if (fallback & fb_lvalue)
20714 : ret = GS_ALL_DONE;
20715 : else
20716 : {
20717 3297 : *expr_p = DECL_INITIAL (*expr_p);
20718 3297 : ret = GS_OK;
20719 : }
20720 : break;
20721 :
20722 6639478 : case DECL_EXPR:
20723 6639478 : ret = gimplify_decl_expr (expr_p, pre_p);
20724 6639478 : break;
20725 :
20726 6092087 : case BIND_EXPR:
20727 6092087 : ret = gimplify_bind_expr (expr_p, pre_p);
20728 6092087 : break;
20729 :
20730 207479 : case LOOP_EXPR:
20731 207479 : ret = gimplify_loop_expr (expr_p, pre_p);
20732 207479 : break;
20733 :
20734 50872 : case SWITCH_EXPR:
20735 50872 : ret = gimplify_switch_expr (expr_p, pre_p);
20736 50872 : break;
20737 :
20738 3207 : case EXIT_EXPR:
20739 3207 : ret = gimplify_exit_expr (expr_p);
20740 3207 : break;
20741 :
20742 1125877 : case GOTO_EXPR:
20743 : /* If the target is not LABEL, then it is a computed jump
20744 : and the target needs to be gimplified. */
20745 1125877 : if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
20746 : {
20747 1200 : ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
20748 : NULL, is_gimple_val, fb_rvalue);
20749 1200 : if (ret == GS_ERROR)
20750 : break;
20751 : }
20752 2251752 : gimplify_seq_add_stmt (pre_p,
20753 1125876 : gimple_build_goto (GOTO_DESTINATION (*expr_p)));
20754 1125876 : ret = GS_ALL_DONE;
20755 1125876 : break;
20756 :
20757 104488 : case PREDICT_EXPR:
20758 417952 : gimplify_seq_add_stmt (pre_p,
20759 104488 : gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
20760 104488 : PREDICT_EXPR_OUTCOME (*expr_p)));
20761 104488 : ret = GS_ALL_DONE;
20762 104488 : break;
20763 :
20764 2617976 : case LABEL_EXPR:
20765 2617976 : ret = gimplify_label_expr (expr_p, pre_p);
20766 2617976 : label = LABEL_EXPR_LABEL (*expr_p);
20767 2617976 : gcc_assert (decl_function_context (label) == current_function_decl);
20768 :
20769 : /* If the label is used in a goto statement, or address of the label
20770 : is taken, we need to unpoison all variables that were seen so far.
20771 : Doing so would prevent us from reporting a false positives. */
20772 2617976 : if (asan_poisoned_variables
20773 5015 : && asan_used_labels != NULL
20774 1325 : && asan_used_labels->contains (label)
20775 2618888 : && !gimplify_omp_ctxp)
20776 904 : asan_poison_variables (asan_poisoned_variables, false, pre_p);
20777 : break;
20778 :
20779 1045379 : case CASE_LABEL_EXPR:
20780 1045379 : ret = gimplify_case_label_expr (expr_p, pre_p);
20781 :
20782 1045379 : if (gimplify_ctxp->live_switch_vars)
20783 1045192 : asan_poison_variables (gimplify_ctxp->live_switch_vars, false,
20784 : pre_p);
20785 : break;
20786 :
20787 2320406 : case RETURN_EXPR:
20788 2320406 : ret = gimplify_return_expr (*expr_p, pre_p);
20789 2320406 : break;
20790 :
20791 983015 : case CONSTRUCTOR:
20792 : /* Don't reduce this in place; let gimplify_init_constructor work its
20793 : magic. Buf if we're just elaborating this for side effects, just
20794 : gimplify any element that has side-effects. */
20795 983015 : if (fallback == fb_none)
20796 : {
20797 404 : unsigned HOST_WIDE_INT ix;
20798 404 : tree val;
20799 404 : tree temp = NULL_TREE;
20800 421 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
20801 17 : if (TREE_SIDE_EFFECTS (val))
20802 4 : append_to_statement_list (val, &temp);
20803 :
20804 404 : *expr_p = temp;
20805 404 : ret = temp ? GS_OK : GS_ALL_DONE;
20806 : }
20807 : /* C99 code may assign to an array in a constructed
20808 : structure or union, and this has undefined behavior only
20809 : on execution, so create a temporary if an lvalue is
20810 : required. */
20811 982611 : else if (fallback == fb_lvalue)
20812 : {
20813 3 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20814 3 : mark_addressable (*expr_p);
20815 3 : ret = GS_OK;
20816 : }
20817 : else
20818 : ret = GS_ALL_DONE;
20819 : break;
20820 :
20821 : /* The following are special cases that are not handled by the
20822 : original GIMPLE grammar. */
20823 :
20824 : /* SAVE_EXPR nodes are converted into a GIMPLE identifier and
20825 : eliminated. */
20826 444457 : case SAVE_EXPR:
20827 444457 : ret = gimplify_save_expr (expr_p, pre_p, post_p);
20828 444457 : break;
20829 :
20830 322916 : case BIT_FIELD_REF:
20831 322916 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20832 : post_p, is_gimple_lvalue, fb_either);
20833 322916 : recalculate_side_effects (*expr_p);
20834 322916 : break;
20835 :
20836 1983 : case TARGET_MEM_REF:
20837 1983 : {
20838 1983 : enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
20839 :
20840 1983 : if (TMR_BASE (*expr_p))
20841 1983 : r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
20842 : post_p, is_gimple_mem_ref_addr, fb_either);
20843 1983 : if (TMR_INDEX (*expr_p))
20844 1161 : r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
20845 : post_p, is_gimple_val, fb_rvalue);
20846 1983 : if (TMR_INDEX2 (*expr_p))
20847 72 : r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
20848 : post_p, is_gimple_val, fb_rvalue);
20849 : /* TMR_STEP and TMR_OFFSET are always integer constants. */
20850 1983 : ret = MIN (r0, r1);
20851 : }
20852 : break;
20853 :
20854 0 : case NON_LVALUE_EXPR:
20855 : /* This should have been stripped above. */
20856 0 : gcc_unreachable ();
20857 :
20858 83100 : case ASM_EXPR:
20859 83100 : ret = gimplify_asm_expr (expr_p, pre_p, post_p);
20860 83100 : break;
20861 :
20862 525765 : case TRY_FINALLY_EXPR:
20863 525765 : case TRY_CATCH_EXPR:
20864 525765 : {
20865 525765 : gimple_seq eval, cleanup;
20866 525765 : gtry *try_;
20867 :
20868 : /* Calls to destructors are generated automatically in FINALLY/CATCH
20869 : block. They should have location as UNKNOWN_LOCATION. However,
20870 : gimplify_call_expr will reset these call stmts to input_location
20871 : if it finds stmt's location is unknown. To prevent resetting for
20872 : destructors, we set the input_location to unknown.
20873 : Note that this only affects the destructor calls in FINALLY/CATCH
20874 : block, and will automatically reset to its original value by the
20875 : end of gimplify_expr. */
20876 525765 : input_location = UNKNOWN_LOCATION;
20877 525765 : eval = cleanup = NULL;
20878 525765 : gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
20879 525765 : bool save_in_handler_expr = gimplify_ctxp->in_handler_expr;
20880 525765 : if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20881 525765 : && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR)
20882 : {
20883 282 : gimple_seq n = NULL, e = NULL;
20884 282 : gimplify_ctxp->in_handler_expr = true;
20885 282 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20886 : 0), &n);
20887 282 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20888 : 1), &e);
20889 282 : if (!gimple_seq_empty_p (n) || !gimple_seq_empty_p (e))
20890 : {
20891 276 : geh_else *stmt = gimple_build_eh_else (n, e);
20892 276 : gimple_seq_add_stmt (&cleanup, stmt);
20893 : }
20894 : }
20895 : else
20896 : {
20897 525483 : gimplify_ctxp->in_handler_expr = true;
20898 525483 : gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
20899 : }
20900 525765 : gimplify_ctxp->in_handler_expr = save_in_handler_expr;
20901 : /* Don't create bogus GIMPLE_TRY with empty cleanup. */
20902 525765 : if (gimple_seq_empty_p (cleanup))
20903 : {
20904 27714 : gimple_seq_add_seq (pre_p, eval);
20905 27714 : ret = GS_ALL_DONE;
20906 27714 : break;
20907 : }
20908 498051 : try_ = gimple_build_try (eval, cleanup,
20909 498051 : TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20910 : ? GIMPLE_TRY_FINALLY
20911 : : GIMPLE_TRY_CATCH);
20912 498051 : if (EXPR_HAS_LOCATION (save_expr))
20913 911724 : gimple_set_location (try_, EXPR_LOCATION (save_expr));
20914 42189 : else if (LOCATION_LOCUS (saved_location) != UNKNOWN_LOCATION)
20915 31139 : gimple_set_location (try_, saved_location);
20916 498051 : if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
20917 177554 : gimple_try_set_catch_is_cleanup (try_,
20918 177554 : TRY_CATCH_IS_CLEANUP (*expr_p));
20919 498051 : gimplify_seq_add_stmt (pre_p, try_);
20920 498051 : ret = GS_ALL_DONE;
20921 498051 : break;
20922 : }
20923 :
20924 5531759 : case CLEANUP_POINT_EXPR:
20925 5531759 : ret = gimplify_cleanup_point_expr (expr_p, pre_p);
20926 5531759 : break;
20927 :
20928 882656 : case TARGET_EXPR:
20929 882656 : ret = gimplify_target_expr (expr_p, pre_p, post_p);
20930 882656 : break;
20931 :
20932 41968 : case CATCH_EXPR:
20933 41968 : {
20934 41968 : gimple *c;
20935 41968 : gimple_seq handler = NULL;
20936 41968 : gimplify_and_add (CATCH_BODY (*expr_p), &handler);
20937 41968 : c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
20938 41968 : gimplify_seq_add_stmt (pre_p, c);
20939 41968 : ret = GS_ALL_DONE;
20940 41968 : break;
20941 : }
20942 :
20943 5891 : case EH_FILTER_EXPR:
20944 5891 : {
20945 5891 : gimple *ehf;
20946 5891 : gimple_seq failure = NULL;
20947 :
20948 5891 : gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
20949 5891 : ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
20950 5891 : copy_warning (ehf, *expr_p);
20951 5891 : gimplify_seq_add_stmt (pre_p, ehf);
20952 5891 : ret = GS_ALL_DONE;
20953 5891 : break;
20954 : }
20955 :
20956 53343 : case OBJ_TYPE_REF:
20957 53343 : {
20958 53343 : enum gimplify_status r0, r1;
20959 53343 : r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p,
20960 : post_p, is_gimple_val, fb_rvalue);
20961 53343 : r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p,
20962 : post_p, is_gimple_val, fb_rvalue);
20963 53343 : TREE_SIDE_EFFECTS (*expr_p) = 0;
20964 53343 : ret = MIN (r0, r1);
20965 : }
20966 : break;
20967 :
20968 41062 : case LABEL_DECL:
20969 : /* We get here when taking the address of a label. We mark
20970 : the label as "forced"; meaning it can never be removed and
20971 : it is a potential target for any computed goto. */
20972 41062 : FORCED_LABEL (*expr_p) = 1;
20973 41062 : ret = GS_ALL_DONE;
20974 41062 : break;
20975 :
20976 8719235 : case STATEMENT_LIST:
20977 8719235 : ret = gimplify_statement_list (expr_p, pre_p);
20978 8719235 : break;
20979 :
20980 1739 : case WITH_SIZE_EXPR:
20981 1739 : {
20982 2021 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20983 : post_p == &internal_post ? NULL : post_p,
20984 : gimple_test_f, fallback);
20985 1739 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
20986 : is_gimple_val, fb_rvalue);
20987 1739 : ret = GS_ALL_DONE;
20988 : }
20989 1739 : break;
20990 :
20991 111921880 : case VAR_DECL:
20992 111921880 : case PARM_DECL:
20993 111921880 : ret = gimplify_var_or_parm_decl (expr_p);
20994 111921880 : break;
20995 :
20996 352067 : case RESULT_DECL:
20997 : /* When within an OMP context, notice uses of variables. */
20998 352067 : if (gimplify_omp_ctxp)
20999 1412 : omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
21000 : /* Handlers can refer to the function result; if that has been
21001 : moved, we need to track it. */
21002 352067 : if (gimplify_ctxp->in_handler_expr && gimplify_ctxp->return_temp)
21003 68 : *expr_p = gimplify_ctxp->return_temp;
21004 : ret = GS_ALL_DONE;
21005 : break;
21006 :
21007 0 : case DEBUG_EXPR_DECL:
21008 0 : gcc_unreachable ();
21009 :
21010 2517013 : case DEBUG_BEGIN_STMT:
21011 5034026 : gimplify_seq_add_stmt (pre_p,
21012 : gimple_build_debug_begin_stmt
21013 2517013 : (TREE_BLOCK (*expr_p),
21014 2517013 : EXPR_LOCATION (*expr_p)));
21015 2517013 : ret = GS_ALL_DONE;
21016 2517013 : *expr_p = NULL;
21017 2517013 : break;
21018 :
21019 : case SSA_NAME:
21020 : /* Allow callbacks into the gimplifier during optimization. */
21021 : ret = GS_ALL_DONE;
21022 : break;
21023 :
21024 18392 : case OMP_PARALLEL:
21025 18392 : gimplify_omp_parallel (expr_p, pre_p);
21026 18392 : ret = GS_ALL_DONE;
21027 18392 : break;
21028 :
21029 4111 : case OMP_TASK:
21030 4111 : gimplify_omp_task (expr_p, pre_p);
21031 4111 : ret = GS_ALL_DONE;
21032 4111 : break;
21033 :
21034 10767 : case OMP_SIMD:
21035 10767 : {
21036 : /* Temporarily disable into_ssa, as scan_omp_simd
21037 : which calls copy_gimple_seq_and_replace_locals can't deal
21038 : with SSA_NAMEs defined outside of the body properly. */
21039 10767 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
21040 10767 : gimplify_ctxp->into_ssa = false;
21041 10767 : ret = gimplify_omp_for (expr_p, pre_p);
21042 10767 : gimplify_ctxp->into_ssa = saved_into_ssa;
21043 10767 : break;
21044 : }
21045 :
21046 47579 : case OMP_FOR:
21047 47579 : case OMP_DISTRIBUTE:
21048 47579 : case OMP_TASKLOOP:
21049 47579 : case OMP_TILE:
21050 47579 : case OMP_UNROLL:
21051 47579 : case OACC_LOOP:
21052 47579 : ret = gimplify_omp_for (expr_p, pre_p);
21053 47579 : break;
21054 :
21055 1056 : case OMP_LOOP:
21056 1056 : ret = gimplify_omp_loop (expr_p, pre_p);
21057 1056 : break;
21058 :
21059 717 : case OACC_CACHE:
21060 717 : gimplify_oacc_cache (expr_p, pre_p);
21061 717 : ret = GS_ALL_DONE;
21062 717 : break;
21063 :
21064 254 : case OACC_DECLARE:
21065 254 : gimplify_oacc_declare (expr_p, pre_p);
21066 254 : ret = GS_ALL_DONE;
21067 254 : break;
21068 :
21069 40049 : case OACC_HOST_DATA:
21070 40049 : case OACC_DATA:
21071 40049 : case OACC_KERNELS:
21072 40049 : case OACC_PARALLEL:
21073 40049 : case OACC_SERIAL:
21074 40049 : case OMP_SCOPE:
21075 40049 : case OMP_SECTIONS:
21076 40049 : case OMP_SINGLE:
21077 40049 : case OMP_TARGET:
21078 40049 : case OMP_TARGET_DATA:
21079 40049 : case OMP_TEAMS:
21080 40049 : gimplify_omp_workshare (expr_p, pre_p);
21081 40049 : ret = GS_ALL_DONE;
21082 40049 : break;
21083 :
21084 12382 : case OACC_ENTER_DATA:
21085 12382 : case OACC_EXIT_DATA:
21086 12382 : case OACC_UPDATE:
21087 12382 : case OMP_TARGET_UPDATE:
21088 12382 : case OMP_TARGET_ENTER_DATA:
21089 12382 : case OMP_TARGET_EXIT_DATA:
21090 12382 : gimplify_omp_target_update (expr_p, pre_p);
21091 12382 : ret = GS_ALL_DONE;
21092 12382 : break;
21093 :
21094 7089 : case OMP_SECTION:
21095 7089 : case OMP_STRUCTURED_BLOCK:
21096 7089 : case OMP_MASTER:
21097 7089 : case OMP_MASKED:
21098 7089 : case OMP_ORDERED:
21099 7089 : case OMP_CRITICAL:
21100 7089 : case OMP_SCAN:
21101 7089 : {
21102 7089 : gimple_seq body = NULL;
21103 7089 : gimple *g;
21104 7089 : bool saved_in_omp_construct = in_omp_construct;
21105 :
21106 7089 : in_omp_construct = true;
21107 7089 : gimplify_and_add (OMP_BODY (*expr_p), &body);
21108 7089 : in_omp_construct = saved_in_omp_construct;
21109 7089 : switch (TREE_CODE (*expr_p))
21110 : {
21111 1279 : case OMP_SECTION:
21112 1279 : g = gimple_build_omp_section (body);
21113 1279 : break;
21114 791 : case OMP_STRUCTURED_BLOCK:
21115 791 : g = gimple_build_omp_structured_block (body);
21116 791 : break;
21117 874 : case OMP_MASTER:
21118 874 : g = gimple_build_omp_master (body);
21119 874 : break;
21120 1954 : case OMP_ORDERED:
21121 1954 : g = gimplify_omp_ordered (*expr_p, body);
21122 1954 : if (OMP_BODY (*expr_p) == NULL_TREE
21123 1954 : && gimple_code (g) == GIMPLE_OMP_ORDERED)
21124 1025 : gimple_omp_ordered_standalone (g);
21125 : break;
21126 497 : case OMP_MASKED:
21127 497 : gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p),
21128 : pre_p, ORT_WORKSHARE, OMP_MASKED);
21129 497 : gimplify_adjust_omp_clauses (pre_p, body,
21130 : &OMP_MASKED_CLAUSES (*expr_p),
21131 : OMP_MASKED);
21132 994 : g = gimple_build_omp_masked (body,
21133 497 : OMP_MASKED_CLAUSES (*expr_p));
21134 497 : break;
21135 552 : case OMP_CRITICAL:
21136 552 : gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
21137 : pre_p, ORT_WORKSHARE, OMP_CRITICAL);
21138 552 : gimplify_adjust_omp_clauses (pre_p, body,
21139 : &OMP_CRITICAL_CLAUSES (*expr_p),
21140 : OMP_CRITICAL);
21141 1656 : g = gimple_build_omp_critical (body,
21142 552 : OMP_CRITICAL_NAME (*expr_p),
21143 552 : OMP_CRITICAL_CLAUSES (*expr_p));
21144 552 : break;
21145 1142 : case OMP_SCAN:
21146 1142 : gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
21147 : pre_p, ORT_WORKSHARE, OMP_SCAN);
21148 1142 : gimplify_adjust_omp_clauses (pre_p, body,
21149 : &OMP_SCAN_CLAUSES (*expr_p),
21150 : OMP_SCAN);
21151 1142 : g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
21152 1142 : break;
21153 0 : default:
21154 0 : gcc_unreachable ();
21155 : }
21156 7089 : gimplify_seq_add_stmt (pre_p, g);
21157 7089 : ret = GS_ALL_DONE;
21158 7089 : break;
21159 : }
21160 :
21161 611 : case OMP_TASKGROUP:
21162 611 : {
21163 611 : gimple_seq body = NULL;
21164 :
21165 611 : tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p);
21166 611 : bool saved_in_omp_construct = in_omp_construct;
21167 611 : gimplify_scan_omp_clauses (pclauses, pre_p, ORT_TASKGROUP,
21168 : OMP_TASKGROUP);
21169 611 : gimplify_adjust_omp_clauses (pre_p, NULL, pclauses, OMP_TASKGROUP);
21170 :
21171 611 : in_omp_construct = true;
21172 611 : gimplify_and_add (OMP_BODY (*expr_p), &body);
21173 611 : in_omp_construct = saved_in_omp_construct;
21174 611 : gimple_seq cleanup = NULL;
21175 611 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END);
21176 611 : gimple *g = gimple_build_call (fn, 0);
21177 611 : gimple_seq_add_stmt (&cleanup, g);
21178 611 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
21179 611 : body = NULL;
21180 611 : gimple_seq_add_stmt (&body, g);
21181 611 : g = gimple_build_omp_taskgroup (body, *pclauses);
21182 611 : gimplify_seq_add_stmt (pre_p, g);
21183 611 : ret = GS_ALL_DONE;
21184 611 : break;
21185 : }
21186 :
21187 612 : case OMP_INTEROP:
21188 612 : ret = gimplify_omp_interop (expr_p, pre_p);
21189 612 : break;
21190 10260 : case OMP_ATOMIC:
21191 10260 : case OMP_ATOMIC_READ:
21192 10260 : case OMP_ATOMIC_CAPTURE_OLD:
21193 10260 : case OMP_ATOMIC_CAPTURE_NEW:
21194 10260 : ret = gimplify_omp_atomic (expr_p, pre_p);
21195 10260 : break;
21196 :
21197 852 : case OMP_DISPATCH:
21198 852 : ret = gimplify_omp_dispatch (expr_p, pre_p);
21199 852 : break;
21200 :
21201 179 : case OMP_METADIRECTIVE:
21202 179 : ret = gimplify_omp_metadirective (expr_p, pre_p, post_p,
21203 : gimple_test_f, fallback);
21204 179 : break;
21205 :
21206 36 : case OMP_NEXT_VARIANT:
21207 36 : case OMP_TARGET_DEVICE_MATCHES:
21208 : /* These are placeholders for constants. There's nothing to do with
21209 : them here but we must mark the containing function as needing
21210 : to run the ompdevlow pass to resolve them. Note that
21211 : OMP_TARGET_DEVICE_MATCHES, in particular, may be inserted by
21212 : the front ends. */
21213 36 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
21214 36 : ret = GS_ALL_DONE;
21215 36 : break;
21216 :
21217 0 : case OMP_DECLARE_MAPPER:
21218 0 : ret = gimplify_omp_declare_mapper (expr_p);
21219 0 : break;
21220 :
21221 478 : case TRANSACTION_EXPR:
21222 478 : ret = gimplify_transaction (expr_p, pre_p);
21223 478 : break;
21224 :
21225 294106 : case TRUTH_AND_EXPR:
21226 294106 : case TRUTH_OR_EXPR:
21227 294106 : case TRUTH_XOR_EXPR:
21228 294106 : {
21229 294106 : tree orig_type = TREE_TYPE (*expr_p);
21230 294106 : tree new_type, xop0, xop1;
21231 294106 : *expr_p = gimple_boolify (*expr_p);
21232 294106 : new_type = TREE_TYPE (*expr_p);
21233 294106 : if (!useless_type_conversion_p (orig_type, new_type))
21234 : {
21235 1166 : *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
21236 1166 : ret = GS_OK;
21237 1166 : break;
21238 : }
21239 :
21240 : /* Boolified binary truth expressions are semantically equivalent
21241 : to bitwise binary expressions. Canonicalize them to the
21242 : bitwise variant. */
21243 292940 : switch (TREE_CODE (*expr_p))
21244 : {
21245 177141 : case TRUTH_AND_EXPR:
21246 177141 : TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
21247 177141 : break;
21248 115175 : case TRUTH_OR_EXPR:
21249 115175 : TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
21250 115175 : break;
21251 624 : case TRUTH_XOR_EXPR:
21252 624 : TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
21253 624 : break;
21254 : default:
21255 : break;
21256 : }
21257 : /* Now make sure that operands have compatible type to
21258 : expression's new_type. */
21259 292940 : xop0 = TREE_OPERAND (*expr_p, 0);
21260 292940 : xop1 = TREE_OPERAND (*expr_p, 1);
21261 292940 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
21262 326 : TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
21263 : new_type,
21264 : xop0);
21265 292940 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
21266 366 : TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
21267 : new_type,
21268 : xop1);
21269 : /* Continue classified as tcc_binary. */
21270 292940 : goto expr_2;
21271 : }
21272 :
21273 11381 : case VEC_COND_EXPR:
21274 11381 : goto expr_3;
21275 :
21276 134378 : case VEC_PERM_EXPR:
21277 : /* Classified as tcc_expression. */
21278 134378 : goto expr_3;
21279 :
21280 48 : case BIT_INSERT_EXPR:
21281 : /* Argument 3 is a constant. */
21282 48 : goto expr_2;
21283 :
21284 3895274 : case POINTER_PLUS_EXPR:
21285 3895274 : {
21286 3895274 : enum gimplify_status r0, r1;
21287 3895274 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21288 : post_p, is_gimple_val, fb_rvalue);
21289 3895274 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21290 : post_p, is_gimple_val, fb_rvalue);
21291 3895274 : recalculate_side_effects (*expr_p);
21292 3895274 : ret = MIN (r0, r1);
21293 : break;
21294 : }
21295 :
21296 45485421 : default:
21297 45485421 : switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
21298 : {
21299 7114485 : case tcc_comparison:
21300 : /* Handle comparison of objects of non scalar mode aggregates
21301 : with a call to memcmp. It would be nice to only have to do
21302 : this for variable-sized objects, but then we'd have to allow
21303 : the same nest of reference nodes we allow for MODIFY_EXPR and
21304 : that's too complex.
21305 :
21306 : Compare scalar mode aggregates as scalar mode values. Using
21307 : memcmp for them would be very inefficient at best, and is
21308 : plain wrong if bitfields are involved. */
21309 7114485 : if (error_operand_p (TREE_OPERAND (*expr_p, 1)))
21310 : ret = GS_ERROR;
21311 : else
21312 : {
21313 7114485 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
21314 :
21315 : /* Vector comparisons need no boolification. */
21316 7114485 : if (TREE_CODE (type) == VECTOR_TYPE)
21317 13431 : goto expr_2;
21318 7101054 : else if (!AGGREGATE_TYPE_P (type))
21319 : {
21320 7101038 : tree org_type = TREE_TYPE (*expr_p);
21321 7101038 : *expr_p = gimple_boolify (*expr_p);
21322 7101038 : if (!useless_type_conversion_p (org_type,
21323 7101038 : TREE_TYPE (*expr_p)))
21324 : {
21325 58086 : *expr_p = fold_convert_loc (input_location,
21326 : org_type, *expr_p);
21327 58086 : ret = GS_OK;
21328 : }
21329 : else
21330 7042952 : goto expr_2;
21331 : }
21332 16 : else if (SCALAR_INT_MODE_P (TYPE_MODE (type)))
21333 16 : ret = gimplify_scalar_mode_aggregate_compare (expr_p);
21334 : else
21335 0 : ret = gimplify_variable_sized_compare (expr_p);
21336 : }
21337 : break;
21338 :
21339 : /* If *EXPR_P does not need to be special-cased, handle it
21340 : according to its class. */
21341 1631104 : case tcc_unary:
21342 1631104 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21343 : post_p, is_gimple_val, fb_rvalue);
21344 1631104 : break;
21345 :
21346 26812232 : case tcc_binary:
21347 26812232 : expr_2:
21348 26812232 : {
21349 26812232 : enum gimplify_status r0, r1;
21350 :
21351 26812232 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21352 : post_p, is_gimple_val, fb_rvalue);
21353 26812232 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21354 : post_p, is_gimple_val, fb_rvalue);
21355 :
21356 26812232 : ret = MIN (r0, r1);
21357 : break;
21358 : }
21359 :
21360 145759 : expr_3:
21361 145759 : {
21362 145759 : enum gimplify_status r0, r1, r2;
21363 :
21364 145759 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21365 : post_p, is_gimple_val, fb_rvalue);
21366 145759 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21367 : post_p, is_gimple_val, fb_rvalue);
21368 145759 : r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
21369 : post_p, is_gimple_val, fb_rvalue);
21370 :
21371 145759 : ret = MIN (MIN (r0, r1), r2);
21372 : break;
21373 : }
21374 :
21375 17276971 : case tcc_declaration:
21376 17276971 : case tcc_constant:
21377 17276971 : ret = GS_ALL_DONE;
21378 17276971 : goto dont_recalculate;
21379 :
21380 0 : default:
21381 0 : gcc_unreachable ();
21382 : }
21383 :
21384 28647197 : recalculate_side_effects (*expr_p);
21385 :
21386 491881442 : dont_recalculate:
21387 : break;
21388 : }
21389 :
21390 491881442 : gcc_assert (*expr_p || ret != GS_OK);
21391 : }
21392 496931149 : while (ret == GS_OK);
21393 :
21394 : /* If we encountered an error_mark somewhere nested inside, either
21395 : stub out the statement or propagate the error back out. */
21396 478513032 : if (ret == GS_ERROR)
21397 : {
21398 5322 : if (is_statement)
21399 4093 : *expr_p = NULL;
21400 5322 : goto out;
21401 : }
21402 :
21403 : /* This was only valid as a return value from the langhook, which
21404 : we handled. Make sure it doesn't escape from any other context. */
21405 478507710 : gcc_assert (ret != GS_UNHANDLED);
21406 :
21407 478507710 : if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
21408 : {
21409 : /* We aren't looking for a value, and we don't have a valid
21410 : statement. If it doesn't have side-effects, throw it away.
21411 : We can also get here with code such as "*&&L;", where L is
21412 : a LABEL_DECL that is marked as FORCED_LABEL. */
21413 1245868 : if (TREE_CODE (*expr_p) == LABEL_DECL
21414 1245868 : || !TREE_SIDE_EFFECTS (*expr_p))
21415 1244836 : *expr_p = NULL;
21416 1032 : else if (!TREE_THIS_VOLATILE (*expr_p))
21417 : {
21418 : /* This is probably a _REF that contains something nested that
21419 : has side effects. Recurse through the operands to find it. */
21420 0 : enum tree_code code = TREE_CODE (*expr_p);
21421 :
21422 0 : switch (code)
21423 : {
21424 0 : case COMPONENT_REF:
21425 0 : case REALPART_EXPR:
21426 0 : case IMAGPART_EXPR:
21427 0 : case VIEW_CONVERT_EXPR:
21428 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21429 : gimple_test_f, fallback);
21430 0 : break;
21431 :
21432 0 : case ARRAY_REF:
21433 0 : case ARRAY_RANGE_REF:
21434 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21435 : gimple_test_f, fallback);
21436 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
21437 : gimple_test_f, fallback);
21438 0 : break;
21439 :
21440 0 : default:
21441 : /* Anything else with side-effects must be converted to
21442 : a valid statement before we get here. */
21443 0 : gcc_unreachable ();
21444 : }
21445 :
21446 0 : *expr_p = NULL;
21447 : }
21448 1032 : else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
21449 982 : && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode
21450 2001 : && !is_empty_type (TREE_TYPE (*expr_p)))
21451 : {
21452 : /* Historically, the compiler has treated a bare reference
21453 : to a non-BLKmode volatile lvalue as forcing a load. */
21454 909 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
21455 :
21456 : /* Normally, we do not want to create a temporary for a
21457 : TREE_ADDRESSABLE type because such a type should not be
21458 : copied by bitwise-assignment. However, we make an
21459 : exception here, as all we are doing here is ensuring that
21460 : we read the bytes that make up the type. We use
21461 : create_tmp_var_raw because create_tmp_var will abort when
21462 : given a TREE_ADDRESSABLE type. */
21463 909 : tree tmp = create_tmp_var_raw (type, "vol");
21464 909 : gimple_add_tmp_var (tmp);
21465 909 : gimplify_assign (tmp, *expr_p, pre_p);
21466 909 : *expr_p = NULL;
21467 : }
21468 : else
21469 : /* We can't do anything useful with a volatile reference to
21470 : an incomplete type, so just throw it away. Likewise for
21471 : a BLKmode type, since any implicit inner load should
21472 : already have been turned into an explicit one by the
21473 : gimplification process. */
21474 123 : *expr_p = NULL;
21475 : }
21476 :
21477 : /* If we are gimplifying at the statement level, we're done. Tack
21478 : everything together and return. */
21479 478507710 : if (fallback == fb_none || is_statement)
21480 : {
21481 : /* Since *EXPR_P has been converted into a GIMPLE tuple, clear
21482 : it out for GC to reclaim it. */
21483 103732333 : *expr_p = NULL_TREE;
21484 :
21485 103732333 : if (!gimple_seq_empty_p (internal_pre)
21486 103732333 : || !gimple_seq_empty_p (internal_post))
21487 : {
21488 19 : gimplify_seq_add_seq (&internal_pre, internal_post);
21489 19 : gimplify_seq_add_seq (pre_p, internal_pre);
21490 : }
21491 :
21492 : /* The result of gimplifying *EXPR_P is going to be the last few
21493 : statements in *PRE_P and *POST_P. Add location information
21494 : to all the statements that were added by the gimplification
21495 : helpers. */
21496 103732333 : if (!gimple_seq_empty_p (*pre_p))
21497 101197468 : annotate_all_with_location_after (*pre_p, pre_last_gsi, input_location);
21498 :
21499 103732333 : if (!gimple_seq_empty_p (*post_p))
21500 19 : annotate_all_with_location_after (*post_p, post_last_gsi,
21501 : input_location);
21502 :
21503 103732333 : goto out;
21504 : }
21505 :
21506 : #ifdef ENABLE_GIMPLE_CHECKING
21507 374775377 : if (*expr_p)
21508 : {
21509 374775377 : enum tree_code code = TREE_CODE (*expr_p);
21510 : /* These expressions should already be in gimple IR form. */
21511 374775377 : gcc_assert (code != MODIFY_EXPR
21512 : && code != ASM_EXPR
21513 : && code != BIND_EXPR
21514 : && code != CATCH_EXPR
21515 : && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
21516 : && code != EH_FILTER_EXPR
21517 : && code != GOTO_EXPR
21518 : && code != LABEL_EXPR
21519 : && code != LOOP_EXPR
21520 : && code != SWITCH_EXPR
21521 : && code != TRY_FINALLY_EXPR
21522 : && code != EH_ELSE_EXPR
21523 : && code != OACC_PARALLEL
21524 : && code != OACC_KERNELS
21525 : && code != OACC_SERIAL
21526 : && code != OACC_DATA
21527 : && code != OACC_HOST_DATA
21528 : && code != OACC_DECLARE
21529 : && code != OACC_UPDATE
21530 : && code != OACC_ENTER_DATA
21531 : && code != OACC_EXIT_DATA
21532 : && code != OACC_CACHE
21533 : && code != OMP_CRITICAL
21534 : && code != OMP_FOR
21535 : && code != OACC_LOOP
21536 : && code != OMP_MASTER
21537 : && code != OMP_MASKED
21538 : && code != OMP_TASKGROUP
21539 : && code != OMP_ORDERED
21540 : && code != OMP_PARALLEL
21541 : && code != OMP_SCAN
21542 : && code != OMP_SECTIONS
21543 : && code != OMP_SECTION
21544 : && code != OMP_STRUCTURED_BLOCK
21545 : && code != OMP_SINGLE
21546 : && code != OMP_SCOPE
21547 : && code != OMP_DISPATCH);
21548 : }
21549 : #endif
21550 :
21551 : /* Otherwise we're gimplifying a subexpression, so the resulting
21552 : value is interesting. If it's a valid operand that matches
21553 : GIMPLE_TEST_F, we're done. Unless we are handling some
21554 : post-effects internally; if that's the case, we need to copy into
21555 : a temporary before adding the post-effects to POST_P. */
21556 374775377 : if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
21557 348201470 : goto out;
21558 :
21559 : /* Otherwise, we need to create a new temporary for the gimplified
21560 : expression. */
21561 :
21562 : /* We can't return an lvalue if we have an internal postqueue. The
21563 : object the lvalue refers to would (probably) be modified by the
21564 : postqueue; we need to copy the value out first, which means an
21565 : rvalue. */
21566 26573907 : if ((fallback & fb_lvalue)
21567 599396 : && gimple_seq_empty_p (internal_post)
21568 27173303 : && is_gimple_addressable (*expr_p))
21569 : {
21570 : /* An lvalue will do. Take the address of the expression, store it
21571 : in a temporary, and replace the expression with an INDIRECT_REF of
21572 : that temporary. */
21573 15 : tree ref_alias_type = reference_alias_ptr_type (*expr_p);
21574 15 : unsigned int ref_align = get_object_alignment (*expr_p);
21575 15 : tree ref_type = TREE_TYPE (*expr_p);
21576 15 : tmp = build_fold_addr_expr_loc (input_location, *expr_p);
21577 15 : gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
21578 15 : if (TYPE_ALIGN (ref_type) != ref_align)
21579 1 : ref_type = build_aligned_type (ref_type, ref_align);
21580 15 : *expr_p = build2 (MEM_REF, ref_type,
21581 : tmp, build_zero_cst (ref_alias_type));
21582 : }
21583 26573892 : else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
21584 : {
21585 : /* An rvalue will do. Assign the gimplified expression into a
21586 : new temporary TMP and replace the original expression with
21587 : TMP. First, make sure that the expression has a type so that
21588 : it can be assigned into a temporary. */
21589 26573884 : gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
21590 26573884 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
21591 : }
21592 : else
21593 : {
21594 : #ifdef ENABLE_GIMPLE_CHECKING
21595 8 : if (!(fallback & fb_mayfail))
21596 : {
21597 0 : fprintf (stderr, "gimplification failed:\n");
21598 0 : print_generic_expr (stderr, *expr_p);
21599 0 : debug_tree (*expr_p);
21600 0 : internal_error ("gimplification failed");
21601 : }
21602 : #endif
21603 8 : gcc_assert (fallback & fb_mayfail);
21604 :
21605 : /* If this is an asm statement, and the user asked for the
21606 : impossible, don't die. Fail and let gimplify_asm_expr
21607 : issue an error. */
21608 8 : ret = GS_ERROR;
21609 8 : goto out;
21610 : }
21611 :
21612 : /* Make sure the temporary matches our predicate. */
21613 26573899 : gcc_assert ((*gimple_test_f) (*expr_p));
21614 :
21615 26573899 : if (!gimple_seq_empty_p (internal_post))
21616 : {
21617 0 : annotate_all_with_location (internal_post, input_location);
21618 0 : gimplify_seq_add_seq (pre_p, internal_post);
21619 : }
21620 :
21621 26573899 : out:
21622 478513032 : input_location = saved_location;
21623 478513032 : return ret;
21624 : }
21625 :
21626 : /* Like gimplify_expr but make sure the gimplified result is not itself
21627 : a SSA name (but a decl if it were). Temporaries required by
21628 : evaluating *EXPR_P may be still SSA names. */
21629 :
21630 : static enum gimplify_status
21631 35472211 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
21632 : bool (*gimple_test_f) (tree), fallback_t fallback,
21633 : bool allow_ssa)
21634 : {
21635 35472211 : enum gimplify_status ret = gimplify_expr (expr_p, pre_p, post_p,
21636 : gimple_test_f, fallback);
21637 35472211 : if (! allow_ssa
21638 267011 : && TREE_CODE (*expr_p) == SSA_NAME)
21639 68648 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false);
21640 35472211 : return ret;
21641 : }
21642 :
21643 : /* Look through TYPE for variable-sized objects and gimplify each such
21644 : size that we find. Add to LIST_P any statements generated. */
21645 :
21646 : void
21647 8505670 : gimplify_type_sizes (tree type, gimple_seq *list_p)
21648 : {
21649 8505670 : if (type == NULL || type == error_mark_node)
21650 : return;
21651 :
21652 8505424 : const bool ignored_p
21653 8505424 : = TYPE_NAME (type)
21654 4213200 : && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
21655 12491763 : && DECL_IGNORED_P (TYPE_NAME (type));
21656 8505424 : tree t;
21657 :
21658 : /* We first do the main variant, then copy into any other variants. */
21659 8505424 : type = TYPE_MAIN_VARIANT (type);
21660 :
21661 : /* Avoid infinite recursion. */
21662 8505424 : if (TYPE_SIZES_GIMPLIFIED (type))
21663 : return;
21664 :
21665 2532114 : TYPE_SIZES_GIMPLIFIED (type) = 1;
21666 :
21667 2532114 : switch (TREE_CODE (type))
21668 : {
21669 500004 : case INTEGER_TYPE:
21670 500004 : case ENUMERAL_TYPE:
21671 500004 : case BOOLEAN_TYPE:
21672 500004 : case REAL_TYPE:
21673 500004 : case FIXED_POINT_TYPE:
21674 500004 : gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
21675 500004 : gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
21676 :
21677 10296702 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21678 : {
21679 9796698 : TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
21680 9796698 : TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
21681 : }
21682 : break;
21683 :
21684 183613 : case ARRAY_TYPE:
21685 : /* These types may not have declarations, so handle them here. */
21686 183613 : gimplify_type_sizes (TREE_TYPE (type), list_p);
21687 183613 : gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
21688 : /* Ensure VLA bounds aren't removed, for -O0 they should be variables
21689 : with assigned stack slots, for -O1+ -g they should be tracked
21690 : by VTA. */
21691 183613 : if (!ignored_p
21692 183613 : && TYPE_DOMAIN (type)
21693 367001 : && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
21694 : {
21695 183388 : t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
21696 183388 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21697 0 : DECL_IGNORED_P (t) = 0;
21698 183388 : t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
21699 183388 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21700 19058 : DECL_IGNORED_P (t) = 0;
21701 : }
21702 : break;
21703 :
21704 514512 : case RECORD_TYPE:
21705 514512 : case UNION_TYPE:
21706 514512 : case QUAL_UNION_TYPE:
21707 11474336 : for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
21708 10959824 : if (TREE_CODE (field) == FIELD_DECL)
21709 : {
21710 1117666 : gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
21711 : /* Likewise, ensure variable offsets aren't removed. */
21712 1117666 : if (!ignored_p
21713 1117666 : && (t = DECL_FIELD_OFFSET (field))
21714 1117654 : && VAR_P (t)
21715 1117828 : && DECL_ARTIFICIAL (t))
21716 162 : DECL_IGNORED_P (t) = 0;
21717 1117666 : gimplify_one_sizepos (&DECL_SIZE (field), list_p);
21718 1117666 : gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
21719 1117666 : gimplify_type_sizes (TREE_TYPE (field), list_p);
21720 : }
21721 : break;
21722 :
21723 : case POINTER_TYPE:
21724 : case REFERENCE_TYPE:
21725 : /* We used to recurse on the pointed-to type here, which turned out to
21726 : be incorrect because its definition might refer to variables not
21727 : yet initialized at this point if a forward declaration is involved.
21728 :
21729 : It was actually useful for anonymous pointed-to types to ensure
21730 : that the sizes evaluation dominates every possible later use of the
21731 : values. Restricting to such types here would be safe since there
21732 : is no possible forward declaration around, but would introduce an
21733 : undesirable middle-end semantic to anonymity. We then defer to
21734 : front-ends the responsibility of ensuring that the sizes are
21735 : evaluated both early and late enough, e.g. by attaching artificial
21736 : type declarations to the tree. */
21737 : break;
21738 :
21739 : default:
21740 : break;
21741 : }
21742 :
21743 2532114 : gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
21744 2532114 : gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
21745 :
21746 17015953 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21747 : {
21748 14483839 : TYPE_SIZE (t) = TYPE_SIZE (type);
21749 14483839 : TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
21750 14483839 : TYPE_SIZES_GIMPLIFIED (t) = 1;
21751 : }
21752 : }
21753 :
21754 : /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
21755 : a size or position, has had all of its SAVE_EXPRs evaluated.
21756 : We add any required statements to *STMT_P. */
21757 :
21758 : void
21759 9435480 : gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
21760 : {
21761 9435480 : tree expr = *expr_p;
21762 :
21763 : /* We don't do anything if the value isn't there, is constant, or contains
21764 : A PLACEHOLDER_EXPR. We also don't want to do anything if it's already
21765 : a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
21766 : will want to replace it with a new variable, but that will cause problems
21767 : if this type is from outside the function. It's OK to have that here. */
21768 9435480 : if (expr == NULL_TREE
21769 9516752 : || is_gimple_constant (expr)
21770 81272 : || VAR_P (expr)
21771 9512703 : || CONTAINS_PLACEHOLDER_P (expr))
21772 : return;
21773 :
21774 77223 : *expr_p = unshare_expr (expr);
21775 :
21776 : /* SSA names in decl/type fields are a bad idea - they'll get reclaimed
21777 : if the def vanishes. */
21778 77223 : gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false);
21779 :
21780 : /* If expr wasn't already is_gimple_sizepos or is_gimple_constant from the
21781 : FE, ensure that it is a VAR_DECL, otherwise we might handle some decls
21782 : as gimplify_vla_decl even when they would have all sizes INTEGER_CSTs. */
21783 77223 : if (is_gimple_constant (*expr_p))
21784 548 : *expr_p = get_initialized_tmp_var (*expr_p, stmt_p, NULL, false);
21785 : }
21786 :
21787 : /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
21788 : containing the sequence of corresponding GIMPLE statements. If DO_PARMS
21789 : is true, also gimplify the parameters. */
21790 :
21791 : gbind *
21792 3049005 : gimplify_body (tree fndecl, bool do_parms)
21793 : {
21794 3049005 : location_t saved_location = input_location;
21795 3049005 : gimple_seq parm_stmts, parm_cleanup = NULL, seq;
21796 3049005 : gimple *outer_stmt;
21797 3049005 : gbind *outer_bind;
21798 :
21799 3049005 : timevar_push (TV_TREE_GIMPLIFY);
21800 :
21801 3049005 : init_tree_ssa (cfun);
21802 :
21803 : /* Initialize for optimize_insn_for_s{ize,peed}_p possibly called during
21804 : gimplification. */
21805 3049005 : default_rtl_profile ();
21806 :
21807 3049005 : gcc_assert (gimplify_ctxp == NULL);
21808 3049005 : push_gimplify_context (true);
21809 :
21810 3049005 : if (flag_openacc || flag_openmp)
21811 : {
21812 55294 : gcc_assert (gimplify_omp_ctxp == NULL);
21813 55294 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)))
21814 9753 : gimplify_omp_ctxp = new_omp_context (ORT_IMPLICIT_TARGET);
21815 : }
21816 :
21817 : /* Unshare most shared trees in the body and in that of any nested functions.
21818 : It would seem we don't have to do this for nested functions because
21819 : they are supposed to be output and then the outer function gimplified
21820 : first, but the g++ front end doesn't always do it that way. */
21821 3049005 : unshare_body (fndecl);
21822 3049005 : unvisit_body (fndecl);
21823 :
21824 : /* Make sure input_location isn't set to something weird. */
21825 3049005 : input_location = DECL_SOURCE_LOCATION (fndecl);
21826 :
21827 : /* Resolve callee-copies. This has to be done before processing
21828 : the body so that DECL_VALUE_EXPR gets processed correctly. */
21829 3049005 : parm_stmts = do_parms ? gimplify_parameters (&parm_cleanup) : NULL;
21830 :
21831 : /* Gimplify the function's body. */
21832 3049005 : seq = NULL;
21833 3049005 : gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
21834 3049005 : outer_stmt = gimple_seq_first_nondebug_stmt (seq);
21835 3049005 : if (!outer_stmt)
21836 : {
21837 27242 : outer_stmt = gimple_build_nop ();
21838 27242 : gimplify_seq_add_stmt (&seq, outer_stmt);
21839 : }
21840 :
21841 : /* The body must contain exactly one statement, a GIMPLE_BIND. If this is
21842 : not the case, wrap everything in a GIMPLE_BIND to make it so. */
21843 3049005 : if (gimple_code (outer_stmt) == GIMPLE_BIND
21844 3049005 : && (gimple_seq_first_nondebug_stmt (seq)
21845 1744785 : == gimple_seq_last_nondebug_stmt (seq)))
21846 : {
21847 1680109 : outer_bind = as_a <gbind *> (outer_stmt);
21848 1680109 : if (gimple_seq_first_stmt (seq) != outer_stmt
21849 1680109 : || gimple_seq_last_stmt (seq) != outer_stmt)
21850 : {
21851 : /* If there are debug stmts before or after outer_stmt, move them
21852 : inside of outer_bind body. */
21853 1 : gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq);
21854 1 : gimple_seq second_seq = NULL;
21855 1 : if (gimple_seq_first_stmt (seq) != outer_stmt
21856 2 : && gimple_seq_last_stmt (seq) != outer_stmt)
21857 : {
21858 0 : second_seq = gsi_split_seq_after (gsi);
21859 0 : gsi_remove (&gsi, false);
21860 : }
21861 1 : else if (gimple_seq_first_stmt (seq) != outer_stmt)
21862 1 : gsi_remove (&gsi, false);
21863 : else
21864 : {
21865 0 : gsi_remove (&gsi, false);
21866 0 : second_seq = seq;
21867 0 : seq = NULL;
21868 : }
21869 1 : gimple_seq_add_seq_without_update (&seq,
21870 : gimple_bind_body (outer_bind));
21871 1 : gimple_seq_add_seq_without_update (&seq, second_seq);
21872 1 : gimple_bind_set_body (outer_bind, seq);
21873 : }
21874 : }
21875 : else
21876 1368896 : outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
21877 :
21878 3049005 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
21879 :
21880 : /* If we had callee-copies statements, insert them at the beginning
21881 : of the function and clear DECL_HAS_VALUE_EXPR_P on the parameters. */
21882 3049005 : if (!gimple_seq_empty_p (parm_stmts))
21883 : {
21884 41 : tree parm;
21885 :
21886 41 : gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
21887 41 : if (parm_cleanup)
21888 : {
21889 0 : gtry *g = gimple_build_try (parm_stmts, parm_cleanup,
21890 : GIMPLE_TRY_FINALLY);
21891 0 : parm_stmts = NULL;
21892 0 : gimple_seq_add_stmt (&parm_stmts, g);
21893 : }
21894 41 : gimple_bind_set_body (outer_bind, parm_stmts);
21895 :
21896 41 : for (parm = DECL_ARGUMENTS (current_function_decl);
21897 101 : parm; parm = DECL_CHAIN (parm))
21898 60 : if (DECL_HAS_VALUE_EXPR_P (parm))
21899 : {
21900 0 : DECL_HAS_VALUE_EXPR_P (parm) = 0;
21901 0 : DECL_IGNORED_P (parm) = 0;
21902 : }
21903 : }
21904 :
21905 3049005 : if ((flag_openacc || flag_openmp || flag_openmp_simd)
21906 57565 : && gimplify_omp_ctxp)
21907 : {
21908 9806 : delete_omp_context (gimplify_omp_ctxp);
21909 9806 : gimplify_omp_ctxp = NULL;
21910 : }
21911 :
21912 3049005 : pop_gimplify_context (outer_bind);
21913 3049005 : gcc_assert (gimplify_ctxp == NULL);
21914 :
21915 3049005 : if (flag_checking && !seen_error ())
21916 2997562 : verify_gimple_in_seq (gimple_bind_body (outer_bind));
21917 :
21918 3049005 : timevar_pop (TV_TREE_GIMPLIFY);
21919 3049005 : input_location = saved_location;
21920 :
21921 3049005 : return outer_bind;
21922 : }
21923 :
21924 : typedef char *char_p; /* For DEF_VEC_P. */
21925 :
21926 : /* Return whether we should exclude FNDECL from instrumentation. */
21927 :
21928 : static bool
21929 43 : flag_instrument_functions_exclude_p (tree fndecl)
21930 : {
21931 43 : vec<char_p> *v;
21932 :
21933 43 : v = (vec<char_p> *) flag_instrument_functions_exclude_functions;
21934 44 : if (v && v->length () > 0)
21935 : {
21936 1 : const char *name;
21937 1 : int i;
21938 1 : char *s;
21939 :
21940 1 : name = lang_hooks.decl_printable_name (fndecl, 1);
21941 2 : FOR_EACH_VEC_ELT (*v, i, s)
21942 1 : if (strstr (name, s) != NULL)
21943 43 : return true;
21944 : }
21945 :
21946 42 : v = (vec<char_p> *) flag_instrument_functions_exclude_files;
21947 43 : if (v && v->length () > 0)
21948 : {
21949 1 : const char *name;
21950 1 : int i;
21951 1 : char *s;
21952 :
21953 1 : name = DECL_SOURCE_FILE (fndecl);
21954 1 : FOR_EACH_VEC_ELT (*v, i, s)
21955 1 : if (strstr (name, s) != NULL)
21956 43 : return true;
21957 : }
21958 :
21959 : return false;
21960 : }
21961 :
21962 : /* Build a call to the instrumentation function FNCODE and add it to SEQ.
21963 : If COND_VAR is not NULL, it is a boolean variable guarding the call to
21964 : the instrumentation function. IF STMT is not NULL, it is a statement
21965 : to be executed just before the call to the instrumentation function. */
21966 :
21967 : static void
21968 82 : build_instrumentation_call (gimple_seq *seq, enum built_in_function fncode,
21969 : tree cond_var, gimple *stmt)
21970 : {
21971 : /* The instrumentation hooks aren't going to call the instrumented
21972 : function and the address they receive is expected to be matchable
21973 : against symbol addresses. Make sure we don't create a trampoline,
21974 : in case the current function is nested. */
21975 82 : tree this_fn_addr = build_fold_addr_expr (current_function_decl);
21976 82 : TREE_NO_TRAMPOLINE (this_fn_addr) = 1;
21977 :
21978 82 : tree label_true, label_false;
21979 82 : if (cond_var)
21980 : {
21981 20 : label_true = create_artificial_label (UNKNOWN_LOCATION);
21982 20 : label_false = create_artificial_label (UNKNOWN_LOCATION);
21983 20 : gcond *cond = gimple_build_cond (EQ_EXPR, cond_var, boolean_false_node,
21984 : label_true, label_false);
21985 20 : gimplify_seq_add_stmt (seq, cond);
21986 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_true));
21987 20 : gimplify_seq_add_stmt (seq, gimple_build_predict (PRED_COLD_LABEL,
21988 : NOT_TAKEN));
21989 : }
21990 :
21991 82 : if (stmt)
21992 10 : gimplify_seq_add_stmt (seq, stmt);
21993 :
21994 82 : tree x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
21995 82 : gcall *call = gimple_build_call (x, 1, integer_zero_node);
21996 82 : tree tmp_var = create_tmp_var (ptr_type_node, "return_addr");
21997 82 : gimple_call_set_lhs (call, tmp_var);
21998 82 : gimplify_seq_add_stmt (seq, call);
21999 82 : x = builtin_decl_implicit (fncode);
22000 82 : call = gimple_build_call (x, 2, this_fn_addr, tmp_var);
22001 82 : gimplify_seq_add_stmt (seq, call);
22002 :
22003 82 : if (cond_var)
22004 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_false));
22005 82 : }
22006 :
22007 : /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
22008 : node for the function we want to gimplify.
22009 :
22010 : Return the sequence of GIMPLE statements corresponding to the body
22011 : of FNDECL. */
22012 :
22013 : void
22014 3048501 : gimplify_function_tree (tree fndecl)
22015 : {
22016 3048501 : gimple_seq seq;
22017 3048501 : gbind *bind;
22018 :
22019 3048501 : gcc_assert (!gimple_body (fndecl));
22020 :
22021 3048501 : if (DECL_STRUCT_FUNCTION (fndecl))
22022 3044102 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
22023 : else
22024 4399 : push_struct_function (fndecl);
22025 :
22026 3048501 : reset_cond_uid ();
22027 3048501 : if (cond_uids)
22028 : {
22029 68 : delete cond_uids;
22030 68 : cond_uids = NULL;
22031 : }
22032 :
22033 : /* Tentatively set PROP_gimple_lva here, and reset it in gimplify_va_arg_expr
22034 : if necessary. */
22035 3048501 : cfun->curr_properties |= PROP_gimple_lva;
22036 :
22037 3048501 : if (asan_sanitize_use_after_scope ())
22038 8600 : asan_poisoned_variables = new hash_set<tree> ();
22039 3048501 : if (flag_openmp)
22040 47561 : omp_resolved_variant_calls = new hash_set<tree> ();
22041 :
22042 3048501 : bind = gimplify_body (fndecl, true);
22043 :
22044 3048501 : if (omp_resolved_variant_calls)
22045 : {
22046 47561 : delete omp_resolved_variant_calls;
22047 47561 : omp_resolved_variant_calls = NULL;
22048 : }
22049 3048501 : if (asan_poisoned_variables)
22050 : {
22051 8600 : delete asan_poisoned_variables;
22052 8600 : asan_poisoned_variables = NULL;
22053 : }
22054 :
22055 : /* The tree body of the function is no longer needed, replace it
22056 : with the new GIMPLE body. */
22057 3048501 : seq = NULL;
22058 3048501 : gimple_seq_add_stmt (&seq, bind);
22059 3048501 : gimple_set_body (fndecl, seq);
22060 :
22061 : /* If we're instrumenting function entry/exit, then prepend the call to
22062 : the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
22063 : catch the exit hook. */
22064 : /* ??? Add some way to ignore exceptions for this TFE. */
22065 3048501 : if (flag_instrument_function_entry_exit
22066 97 : && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
22067 : /* Do not instrument extern inline functions. */
22068 44 : && !(DECL_DECLARED_INLINE_P (fndecl)
22069 6 : && DECL_EXTERNAL (fndecl)
22070 1 : && DECL_DISREGARD_INLINE_LIMITS (fndecl))
22071 3048544 : && !flag_instrument_functions_exclude_p (fndecl))
22072 : {
22073 41 : gimple_seq body = NULL, cleanup = NULL;
22074 41 : gassign *assign;
22075 41 : tree cond_var;
22076 :
22077 : /* If -finstrument-functions-once is specified, generate:
22078 :
22079 : static volatile bool C.0 = false;
22080 : bool tmp_called;
22081 :
22082 : tmp_called = C.0;
22083 : if (!tmp_called)
22084 : {
22085 : C.0 = true;
22086 : [call profiling enter function]
22087 : }
22088 :
22089 : without specific protection for data races. */
22090 41 : if (flag_instrument_function_entry_exit > 1)
22091 : {
22092 10 : tree first_var
22093 10 : = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
22094 : VAR_DECL,
22095 : create_tmp_var_name ("C"),
22096 : boolean_type_node);
22097 10 : DECL_ARTIFICIAL (first_var) = 1;
22098 10 : DECL_IGNORED_P (first_var) = 1;
22099 10 : TREE_STATIC (first_var) = 1;
22100 10 : TREE_THIS_VOLATILE (first_var) = 1;
22101 10 : TREE_USED (first_var) = 1;
22102 10 : DECL_INITIAL (first_var) = boolean_false_node;
22103 10 : varpool_node::add (first_var);
22104 :
22105 10 : cond_var = create_tmp_var (boolean_type_node, "tmp_called");
22106 10 : assign = gimple_build_assign (cond_var, first_var);
22107 10 : gimplify_seq_add_stmt (&body, assign);
22108 :
22109 10 : assign = gimple_build_assign (first_var, boolean_true_node);
22110 : }
22111 :
22112 : else
22113 : {
22114 : cond_var = NULL_TREE;
22115 : assign = NULL;
22116 : }
22117 :
22118 41 : build_instrumentation_call (&body, BUILT_IN_PROFILE_FUNC_ENTER,
22119 : cond_var, assign);
22120 :
22121 : /* If -finstrument-functions-once is specified, generate:
22122 :
22123 : if (!tmp_called)
22124 : [call profiling exit function]
22125 :
22126 : without specific protection for data races. */
22127 41 : build_instrumentation_call (&cleanup, BUILT_IN_PROFILE_FUNC_EXIT,
22128 : cond_var, NULL);
22129 :
22130 41 : gimple *tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
22131 41 : gimplify_seq_add_stmt (&body, tf);
22132 41 : gbind *new_bind = gimple_build_bind (NULL, body, NULL);
22133 :
22134 : /* Replace the current function body with the body
22135 : wrapped in the try/finally TF. */
22136 41 : seq = NULL;
22137 41 : gimple_seq_add_stmt (&seq, new_bind);
22138 41 : gimple_set_body (fndecl, seq);
22139 41 : bind = new_bind;
22140 : }
22141 :
22142 3048501 : if (sanitize_flags_p (SANITIZE_THREAD)
22143 3048501 : && param_tsan_instrument_func_entry_exit)
22144 : {
22145 967 : gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
22146 967 : gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
22147 967 : gbind *new_bind = gimple_build_bind (NULL, tf, NULL);
22148 : /* Replace the current function body with the body
22149 : wrapped in the try/finally TF. */
22150 967 : seq = NULL;
22151 967 : gimple_seq_add_stmt (&seq, new_bind);
22152 967 : gimple_set_body (fndecl, seq);
22153 : }
22154 :
22155 3048501 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
22156 3048501 : cfun->curr_properties |= PROP_gimple_any;
22157 :
22158 3048501 : pop_cfun ();
22159 :
22160 3048501 : dump_function (TDI_gimple, fndecl);
22161 3048501 : }
22162 :
22163 : /* Return a dummy expression of type TYPE in order to keep going after an
22164 : error. */
22165 :
22166 : static tree
22167 30 : dummy_object (tree type)
22168 : {
22169 30 : tree t = build_int_cst (build_pointer_type (type), 0);
22170 30 : return build2 (MEM_REF, type, t, t);
22171 : }
22172 :
22173 : /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
22174 : builtin function, but a very special sort of operator. */
22175 :
22176 : enum gimplify_status
22177 51195 : gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
22178 : gimple_seq *post_p ATTRIBUTE_UNUSED)
22179 : {
22180 51195 : tree promoted_type, have_va_type;
22181 51195 : tree valist = TREE_OPERAND (*expr_p, 0);
22182 51195 : tree type = TREE_TYPE (*expr_p);
22183 51195 : tree t, tag, aptag;
22184 51195 : location_t loc = EXPR_LOCATION (*expr_p);
22185 :
22186 : /* Verify that valist is of the proper type. */
22187 51195 : have_va_type = TREE_TYPE (valist);
22188 51195 : if (have_va_type == error_mark_node)
22189 : return GS_ERROR;
22190 51176 : have_va_type = targetm.canonical_va_list_type (have_va_type);
22191 51176 : if (have_va_type == NULL_TREE
22192 51176 : && POINTER_TYPE_P (TREE_TYPE (valist)))
22193 : /* Handle 'Case 1: Not an array type' from c-common.cc/build_va_arg. */
22194 270 : have_va_type
22195 270 : = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
22196 51176 : gcc_assert (have_va_type != NULL_TREE);
22197 :
22198 : /* Generate a diagnostic for requesting data of a type that cannot
22199 : be passed through `...' due to type promotion at the call site. */
22200 51176 : if ((promoted_type = lang_hooks.types.type_promotes_to (type))
22201 : != type)
22202 : {
22203 30 : static bool gave_help;
22204 30 : bool warned;
22205 : /* Use the expansion point to handle cases such as passing bool (defined
22206 : in a system header) through `...'. */
22207 30 : location_t xloc
22208 30 : = expansion_point_location_if_in_system_header (loc);
22209 :
22210 : /* Unfortunately, this is merely undefined, rather than a constraint
22211 : violation, so we cannot make this an error. If this call is never
22212 : executed, the program is still strictly conforming. */
22213 30 : auto_diagnostic_group d;
22214 30 : warned = warning_at (xloc, 0,
22215 : "%qT is promoted to %qT when passed through %<...%>",
22216 : type, promoted_type);
22217 30 : if (!gave_help && warned)
22218 : {
22219 15 : gave_help = true;
22220 15 : inform (xloc, "(so you should pass %qT not %qT to %<va_arg%>)",
22221 : promoted_type, type);
22222 : }
22223 :
22224 : /* We can, however, treat "undefined" any way we please.
22225 : Call abort to encourage the user to fix the program. */
22226 23 : if (warned)
22227 23 : inform (xloc, "if this code is reached, the program will abort");
22228 : /* Before the abort, allow the evaluation of the va_list
22229 : expression to exit or longjmp. */
22230 30 : gimplify_and_add (valist, pre_p);
22231 60 : t = build_call_expr_loc (loc,
22232 : builtin_decl_implicit (BUILT_IN_TRAP), 0);
22233 30 : gimplify_and_add (t, pre_p);
22234 :
22235 : /* This is dead code, but go ahead and finish so that the
22236 : mode of the result comes out right. */
22237 30 : *expr_p = dummy_object (type);
22238 30 : return GS_ALL_DONE;
22239 30 : }
22240 :
22241 51146 : tag = build_int_cst (build_pointer_type (type), 0);
22242 51146 : aptag = build_int_cst (TREE_TYPE (valist), 0);
22243 :
22244 51146 : *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3,
22245 : valist, tag, aptag);
22246 :
22247 : /* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
22248 : needs to be expanded. */
22249 51146 : cfun->curr_properties &= ~PROP_gimple_lva;
22250 :
22251 51146 : return GS_OK;
22252 : }
22253 :
22254 : /* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P.
22255 :
22256 : DST/SRC are the destination and source respectively. You can pass
22257 : ungimplified trees in DST or SRC, in which case they will be
22258 : converted to a gimple operand if necessary.
22259 :
22260 : This function returns the newly created GIMPLE_ASSIGN tuple. */
22261 :
22262 : gimple *
22263 913879 : gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
22264 : {
22265 913879 : tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
22266 913879 : gimplify_and_add (t, seq_p);
22267 913879 : ggc_free (t);
22268 913879 : return gimple_seq_last_stmt (*seq_p);
22269 : }
22270 :
22271 : inline hashval_t
22272 1615996 : gimplify_hasher::hash (const elt_t *p)
22273 : {
22274 1615996 : tree t = p->val;
22275 1615996 : return iterative_hash_expr (t, 0);
22276 : }
22277 :
22278 : inline bool
22279 598535 : gimplify_hasher::equal (const elt_t *p1, const elt_t *p2)
22280 : {
22281 598535 : tree t1 = p1->val;
22282 598535 : tree t2 = p2->val;
22283 598535 : enum tree_code code = TREE_CODE (t1);
22284 :
22285 598535 : if (TREE_CODE (t2) != code
22286 598535 : || TREE_TYPE (t1) != TREE_TYPE (t2))
22287 : return false;
22288 :
22289 366899 : if (!operand_equal_p (t1, t2, 0))
22290 : return false;
22291 :
22292 : return true;
22293 : }
|