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 5770808 : next_cond_uid ()
94 : {
95 5770808 : 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 2880744 : reset_cond_uid ()
104 : {
105 2880744 : 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 1205202 : tree_associate_condition_with_expr (tree stmt, unsigned uid)
115 : {
116 1205202 : if (!condition_coverage_flag)
117 : return;
118 :
119 527 : if (!cond_uids)
120 65 : cond_uids = new hash_map <tree, unsigned> ();
121 :
122 527 : 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 : GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
189 : | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
190 : | GOVD_LOCAL)
191 : };
192 :
193 :
194 : enum omp_region_type
195 : {
196 : ORT_WORKSHARE = 0x00,
197 : ORT_TASKGROUP = 0x01,
198 : ORT_DISPATCH = 0x02,
199 : ORT_SIMD = 0x04,
200 :
201 : ORT_PARALLEL = 0x08,
202 : ORT_COMBINED_PARALLEL = ORT_PARALLEL | 1,
203 :
204 : ORT_TASK = 0x10,
205 : ORT_UNTIED_TASK = ORT_TASK | 1,
206 : ORT_TASKLOOP = ORT_TASK | 2,
207 : ORT_UNTIED_TASKLOOP = ORT_UNTIED_TASK | 2,
208 :
209 : ORT_TEAMS = 0x20,
210 : ORT_COMBINED_TEAMS = ORT_TEAMS | 1,
211 : ORT_HOST_TEAMS = ORT_TEAMS | 2,
212 : ORT_COMBINED_HOST_TEAMS = ORT_COMBINED_TEAMS | 2,
213 :
214 : /* Data region. */
215 : ORT_TARGET_DATA = 0x40,
216 :
217 : /* Data region with offloading. */
218 : ORT_TARGET = 0x80,
219 : ORT_COMBINED_TARGET = ORT_TARGET | 1,
220 : ORT_IMPLICIT_TARGET = ORT_TARGET | 2,
221 :
222 : /* OpenACC variants. */
223 : ORT_ACC = 0x100, /* A generic OpenACC region. */
224 : ORT_ACC_DATA = ORT_ACC | ORT_TARGET_DATA, /* Data construct. */
225 : ORT_ACC_PARALLEL = ORT_ACC | ORT_TARGET, /* Parallel construct */
226 : ORT_ACC_KERNELS = ORT_ACC | ORT_TARGET | 2, /* Kernels construct. */
227 : ORT_ACC_SERIAL = ORT_ACC | ORT_TARGET | 4, /* Serial construct. */
228 : ORT_ACC_HOST_DATA = ORT_ACC | ORT_TARGET_DATA | 2, /* Host data. */
229 :
230 : /* Dummy OpenMP region, used to disable expansion of
231 : DECL_VALUE_EXPRs in taskloop pre body. */
232 : ORT_NONE = 0x200
233 : };
234 :
235 : /* Gimplify hashtable helper. */
236 :
237 : struct gimplify_hasher : free_ptr_hash <elt_t>
238 : {
239 : static inline hashval_t hash (const elt_t *);
240 : static inline bool equal (const elt_t *, const elt_t *);
241 : };
242 :
243 : struct gimplify_ctx
244 : {
245 : struct gimplify_ctx *prev_context;
246 :
247 : vec<gbind *> bind_expr_stack;
248 : tree temps;
249 : gimple_seq conditional_cleanups;
250 : tree exit_label;
251 : tree return_temp;
252 :
253 : vec<tree> case_labels;
254 : hash_set<tree> *live_switch_vars;
255 : /* The formal temporary table. Should this be persistent? */
256 : hash_table<gimplify_hasher> *temp_htab;
257 :
258 : int conditions;
259 : unsigned into_ssa : 1;
260 : unsigned allow_rhs_cond_expr : 1;
261 : unsigned in_cleanup_point_expr : 1;
262 : unsigned keep_stack : 1;
263 : unsigned save_stack : 1;
264 : unsigned in_switch_expr : 1;
265 : unsigned in_handler_expr : 1;
266 : };
267 :
268 : enum gimplify_defaultmap_kind
269 : {
270 : GDMK_SCALAR,
271 : GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only. */
272 : GDMK_AGGREGATE,
273 : GDMK_ALLOCATABLE,
274 : GDMK_POINTER
275 : };
276 :
277 : struct gimplify_omp_ctx
278 : {
279 : struct gimplify_omp_ctx *outer_context;
280 : splay_tree variables;
281 : hash_map<omp_name_type<tree>, tree> *implicit_mappers;
282 : hash_set<tree> *privatized_types;
283 : tree clauses;
284 : /* Iteration variables in an OMP_FOR. */
285 : vec<tree> loop_iter_var;
286 : location_t location;
287 : enum omp_clause_default_kind default_kind;
288 : enum omp_region_type region_type;
289 : enum tree_code code;
290 : bool combined_loop;
291 : bool distribute;
292 : bool target_firstprivatize_array_bases;
293 : bool add_safelen1;
294 : bool order_concurrent;
295 : bool has_depend;
296 : bool in_for_exprs;
297 : bool in_call_args;
298 : int defaultmap[5];
299 : };
300 :
301 : static struct gimplify_ctx *gimplify_ctxp;
302 : static struct gimplify_omp_ctx *gimplify_omp_ctxp;
303 : static bool in_omp_construct;
304 :
305 : /* Forward declaration. */
306 : static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
307 : static hash_map<tree, tree> *oacc_declare_returns;
308 : static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
309 : bool (*) (tree), fallback_t, bool);
310 : static void prepare_gimple_addressable (tree *, gimple_seq *);
311 :
312 : /* Shorter alias name for the above function for use in gimplify.cc
313 : only. */
314 :
315 : static inline void
316 92150048 : gimplify_seq_add_stmt (gimple_seq *seq_p, gimple *gs)
317 : {
318 92150048 : gimple_seq_add_stmt_without_update (seq_p, gs);
319 6617887 : }
320 :
321 : /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
322 : NULL, a new sequence is allocated. This function is
323 : similar to gimple_seq_add_seq, but does not scan the operands.
324 : During gimplification, we need to manipulate statement sequences
325 : before the def/use vectors have been constructed. */
326 :
327 : static void
328 9151082 : gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
329 : {
330 9151082 : gimple_stmt_iterator si;
331 :
332 9151082 : if (src == NULL)
333 4023500 : return;
334 :
335 5127582 : si = gsi_last (*dst_p);
336 5127582 : gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
337 : }
338 :
339 :
340 : /* Pointer to a list of allocated gimplify_ctx structs to be used for pushing
341 : and popping gimplify contexts. */
342 :
343 : static struct gimplify_ctx *ctx_pool = NULL;
344 :
345 : /* Return a gimplify context struct from the pool. */
346 :
347 : static inline struct gimplify_ctx *
348 8843408 : ctx_alloc (void)
349 : {
350 8843408 : struct gimplify_ctx * c = ctx_pool;
351 :
352 8843408 : if (c)
353 8572269 : ctx_pool = c->prev_context;
354 : else
355 271139 : c = XNEW (struct gimplify_ctx);
356 :
357 8843408 : memset (c, '\0', sizeof (*c));
358 8843408 : return c;
359 : }
360 :
361 : /* Put gimplify context C back into the pool. */
362 :
363 : static inline void
364 8843404 : ctx_free (struct gimplify_ctx *c)
365 : {
366 8843404 : c->prev_context = ctx_pool;
367 8843404 : ctx_pool = c;
368 : }
369 :
370 : /* Free allocated ctx stack memory. */
371 :
372 : void
373 238613 : free_gimplify_stack (void)
374 : {
375 238613 : struct gimplify_ctx *c;
376 :
377 477488 : while ((c = ctx_pool))
378 : {
379 238875 : ctx_pool = c->prev_context;
380 238875 : free (c);
381 : }
382 238613 : }
383 :
384 :
385 : /* Set up a context for the gimplifier. */
386 :
387 : void
388 8843408 : push_gimplify_context (bool in_ssa, bool rhs_cond_ok)
389 : {
390 8843408 : struct gimplify_ctx *c = ctx_alloc ();
391 :
392 8843408 : c->prev_context = gimplify_ctxp;
393 8843408 : gimplify_ctxp = c;
394 8843408 : gimplify_ctxp->into_ssa = in_ssa;
395 8843408 : gimplify_ctxp->allow_rhs_cond_expr = rhs_cond_ok;
396 8843408 : }
397 :
398 : /* Tear down a context for the gimplifier. If BODY is non-null, then
399 : put the temporaries into the outer BIND_EXPR. Otherwise, put them
400 : in the local_decls.
401 :
402 : BODY is not a sequence, but the first tuple in a sequence. */
403 :
404 : void
405 8843404 : pop_gimplify_context (gimple *body)
406 : {
407 8843404 : struct gimplify_ctx *c = gimplify_ctxp;
408 :
409 8843404 : gcc_assert (c
410 : && (!c->bind_expr_stack.exists ()
411 : || c->bind_expr_stack.is_empty ()));
412 8843404 : c->bind_expr_stack.release ();
413 8843404 : gimplify_ctxp = c->prev_context;
414 :
415 8843404 : if (body)
416 3005240 : declare_vars (c->temps, body, false);
417 : else
418 5838164 : record_vars (c->temps);
419 :
420 8843404 : delete c->temp_htab;
421 8843404 : c->temp_htab = NULL;
422 8843404 : ctx_free (c);
423 8843404 : }
424 :
425 : /* Push a GIMPLE_BIND tuple onto the stack of bindings. */
426 :
427 : static void
428 5930032 : gimple_push_bind_expr (gbind *bind_stmt)
429 : {
430 5930032 : gimplify_ctxp->bind_expr_stack.reserve (8);
431 5930032 : gimplify_ctxp->bind_expr_stack.safe_push (bind_stmt);
432 5930032 : }
433 :
434 : /* Pop the first element off the stack of bindings. */
435 :
436 : static void
437 5930032 : gimple_pop_bind_expr (void)
438 : {
439 0 : gimplify_ctxp->bind_expr_stack.pop ();
440 2207 : }
441 :
442 : /* Return the first element of the stack of bindings. */
443 :
444 : gbind *
445 0 : gimple_current_bind_expr (void)
446 : {
447 0 : return gimplify_ctxp->bind_expr_stack.last ();
448 : }
449 :
450 : /* Return the stack of bindings created during gimplification. */
451 :
452 : vec<gbind *>
453 359 : gimple_bind_expr_stack (void)
454 : {
455 359 : return gimplify_ctxp->bind_expr_stack;
456 : }
457 :
458 : /* Return true iff there is a COND_EXPR between us and the innermost
459 : CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
460 :
461 : static bool
462 2786448 : gimple_conditional_context (void)
463 : {
464 2786448 : return gimplify_ctxp->conditions > 0;
465 : }
466 :
467 : /* Note that we've entered a COND_EXPR. */
468 :
469 : static void
470 5771243 : gimple_push_condition (void)
471 : {
472 : #ifdef ENABLE_GIMPLE_CHECKING
473 5771243 : if (gimplify_ctxp->conditions == 0)
474 3801866 : gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
475 : #endif
476 5771243 : ++(gimplify_ctxp->conditions);
477 5771243 : }
478 :
479 : /* Note that we've left a COND_EXPR. If we're back at unconditional scope
480 : now, add any conditional cleanups we've seen to the prequeue. */
481 :
482 : static void
483 5771243 : gimple_pop_condition (gimple_seq *pre_p)
484 : {
485 5771243 : int conds = --(gimplify_ctxp->conditions);
486 :
487 5771243 : gcc_assert (conds >= 0);
488 5771243 : if (conds == 0)
489 : {
490 3801866 : gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
491 3801866 : gimplify_ctxp->conditional_cleanups = NULL;
492 : }
493 5771243 : }
494 :
495 : /* A stable comparison routine for use with splay trees and DECLs. */
496 :
497 : static int
498 18331412 : splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
499 : {
500 18331412 : tree a = (tree) xa;
501 18331412 : tree b = (tree) xb;
502 :
503 18331412 : return DECL_UID (a) - DECL_UID (b);
504 : }
505 :
506 : /* Create a new omp construct that deals with variable remapping. */
507 :
508 : static struct gimplify_omp_ctx *
509 140298 : new_omp_context (enum omp_region_type region_type)
510 : {
511 140298 : struct gimplify_omp_ctx *c;
512 :
513 140298 : c = XCNEW (struct gimplify_omp_ctx);
514 140298 : c->outer_context = gimplify_omp_ctxp;
515 140298 : c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
516 140298 : c->implicit_mappers = new hash_map<omp_name_type<tree>, tree>;
517 140298 : c->privatized_types = new hash_set<tree>;
518 140298 : c->location = input_location;
519 140298 : c->region_type = region_type;
520 140298 : if ((region_type & ORT_TASK) == 0)
521 134250 : c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
522 : else
523 6048 : c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
524 140298 : c->defaultmap[GDMK_SCALAR] = GOVD_MAP;
525 140298 : c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP;
526 140298 : c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP;
527 140298 : c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP;
528 140298 : c->defaultmap[GDMK_POINTER] = GOVD_MAP;
529 :
530 140298 : return c;
531 : }
532 :
533 : /* Destroy an omp construct that deals with variable remapping. */
534 :
535 : static void
536 139739 : delete_omp_context (struct gimplify_omp_ctx *c)
537 : {
538 139739 : splay_tree_delete (c->variables);
539 279478 : delete c->privatized_types;
540 279478 : delete c->implicit_mappers;
541 139739 : c->loop_iter_var.release ();
542 139739 : XDELETE (c);
543 139739 : }
544 :
545 : static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
546 : static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
547 :
548 : /* Both gimplify the statement T and append it to *SEQ_P. This function
549 : behaves exactly as gimplify_stmt, but you don't have to pass T as a
550 : reference. */
551 :
552 : void
553 37899253 : gimplify_and_add (tree t, gimple_seq *seq_p)
554 : {
555 37899253 : gimplify_stmt (&t, seq_p);
556 37899253 : }
557 :
558 : /* Gimplify statement T into sequence *SEQ_P, and return the first
559 : tuple in the sequence of generated tuples for this statement.
560 : Return NULL if gimplifying T produced no tuples. */
561 :
562 : static gimple *
563 105352 : gimplify_and_return_first (tree t, gimple_seq *seq_p)
564 : {
565 105352 : gimple_stmt_iterator last = gsi_last (*seq_p);
566 :
567 105352 : gimplify_and_add (t, seq_p);
568 :
569 105352 : if (!gsi_end_p (last))
570 : {
571 4881 : gsi_next (&last);
572 4881 : return gsi_stmt (last);
573 : }
574 : else
575 100471 : return gimple_seq_first_stmt (*seq_p);
576 : }
577 :
578 : /* Returns true iff T is a valid RHS for an assignment to an un-renamed
579 : LHS, or for a call argument. */
580 :
581 : static bool
582 237406 : is_gimple_mem_rhs (tree t)
583 : {
584 : /* If we're dealing with a renamable type, either source or dest must be
585 : a renamed variable. */
586 237406 : if (is_gimple_reg_type (TREE_TYPE (t)))
587 234041 : return is_gimple_val (t);
588 : else
589 3365 : return is_gimple_val (t) || is_gimple_lvalue (t);
590 : }
591 :
592 : /* Return true if T is a CALL_EXPR or an expression that can be
593 : assigned to a temporary. Note that this predicate should only be
594 : used during gimplification. See the rationale for this in
595 : gimplify_modify_expr. */
596 :
597 : static bool
598 97371074 : is_gimple_reg_rhs_or_call (tree t)
599 : {
600 71517597 : return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
601 97371074 : || TREE_CODE (t) == CALL_EXPR);
602 : }
603 :
604 : /* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
605 : this predicate should only be used during gimplification. See the
606 : rationale for this in gimplify_modify_expr. */
607 :
608 : static bool
609 14236971 : is_gimple_mem_rhs_or_call (tree t)
610 : {
611 : /* If we're dealing with a renamable type, either source or dest must be
612 : a renamed variable. */
613 14236971 : if (is_gimple_reg_type (TREE_TYPE (t)))
614 10904355 : return is_gimple_val (t);
615 : else
616 3332616 : return (is_gimple_val (t)
617 1669884 : || is_gimple_lvalue (t)
618 1154040 : || (TREE_CODE (t) == CONSTRUCTOR && CONSTRUCTOR_NELTS (t) == 0)
619 4486266 : || TREE_CODE (t) == CALL_EXPR);
620 : }
621 :
622 : /* Create a temporary with a name derived from VAL. Subroutine of
623 : lookup_tmp_var; nobody else should call this function. */
624 :
625 : static inline tree
626 2145871 : create_tmp_from_val (tree val)
627 : {
628 : /* Drop all qualifiers and address-space information from the value type. */
629 2145871 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
630 2145871 : tree var = create_tmp_var (type, get_name (val));
631 2145871 : return var;
632 : }
633 :
634 : /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
635 : an existing expression temporary. If NOT_GIMPLE_REG, mark it as such. */
636 :
637 : static tree
638 2381586 : lookup_tmp_var (tree val, bool is_formal, bool not_gimple_reg)
639 : {
640 2381586 : tree ret;
641 :
642 : /* We cannot mark a formal temporary with DECL_NOT_GIMPLE_REG_P. */
643 2381586 : gcc_assert (!is_formal || !not_gimple_reg);
644 :
645 : /* If not optimizing, never really reuse a temporary. local-alloc
646 : won't allocate any variable that is used in more than one basic
647 : block, which means it will go into memory, causing much extra
648 : work in reload and final and poorer code generation, outweighing
649 : the extra memory allocation here. */
650 2381586 : if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
651 : {
652 1089184 : ret = create_tmp_from_val (val);
653 1089184 : DECL_NOT_GIMPLE_REG_P (ret) = not_gimple_reg;
654 : }
655 : else
656 : {
657 1292402 : elt_t elt, *elt_p;
658 1292402 : elt_t **slot;
659 :
660 1292402 : elt.val = val;
661 1292402 : if (!gimplify_ctxp->temp_htab)
662 395610 : gimplify_ctxp->temp_htab = new hash_table<gimplify_hasher> (1000);
663 1292402 : slot = gimplify_ctxp->temp_htab->find_slot (&elt, INSERT);
664 1292402 : if (*slot == NULL)
665 : {
666 1056687 : elt_p = XNEW (elt_t);
667 1056687 : elt_p->val = val;
668 1056687 : elt_p->temp = ret = create_tmp_from_val (val);
669 1056687 : *slot = elt_p;
670 : }
671 : else
672 : {
673 235715 : elt_p = *slot;
674 235715 : ret = elt_p->temp;
675 : }
676 : }
677 :
678 2381586 : return ret;
679 : }
680 :
681 : /* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
682 :
683 : static tree
684 26387748 : internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
685 : bool is_formal, bool allow_ssa, bool not_gimple_reg)
686 : {
687 26387748 : tree t, mod;
688 :
689 : /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
690 : can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
691 26387748 : gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
692 : fb_rvalue);
693 :
694 26387748 : if (allow_ssa
695 26119930 : && gimplify_ctxp->into_ssa
696 51062137 : && is_gimple_reg_type (TREE_TYPE (val)))
697 : {
698 24006163 : t = make_ssa_name (TYPE_MAIN_VARIANT (TREE_TYPE (val)));
699 24006163 : if (! gimple_in_ssa_p (cfun))
700 : {
701 20679097 : const char *name = get_name (val);
702 20679097 : if (name)
703 6773144 : SET_SSA_NAME_VAR_OR_IDENTIFIER (t, create_tmp_var_name (name));
704 : }
705 : }
706 : else
707 2381585 : t = lookup_tmp_var (val, is_formal, not_gimple_reg);
708 :
709 26387748 : mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
710 :
711 26387748 : SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location));
712 :
713 : /* gimplify_modify_expr might want to reduce this further. */
714 26387748 : gimplify_and_add (mod, pre_p);
715 26387748 : ggc_free (mod);
716 :
717 : /* If we failed to gimplify VAL then we can end up with the temporary
718 : SSA name not having a definition. In this case return a decl. */
719 26387748 : if (TREE_CODE (t) == SSA_NAME && ! SSA_NAME_DEF_STMT (t))
720 1 : return lookup_tmp_var (val, is_formal, not_gimple_reg);
721 :
722 : return t;
723 : }
724 :
725 : /* Return a formal temporary variable initialized with VAL. PRE_P is as
726 : in gimplify_expr. Only use this function if:
727 :
728 : 1) The value of the unfactored expression represented by VAL will not
729 : change between the initialization and use of the temporary, and
730 : 2) The temporary will not be otherwise modified.
731 :
732 : For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
733 : and #2 means it is inappropriate for && temps.
734 :
735 : For other cases, use get_initialized_tmp_var instead. */
736 :
737 : tree
738 25892033 : get_formal_tmp_var (tree val, gimple_seq *pre_p)
739 : {
740 25892033 : return internal_get_tmp_var (val, pre_p, NULL, true, true, false);
741 : }
742 :
743 : /* Return a temporary variable initialized with VAL. PRE_P and POST_P
744 : are as in gimplify_expr. */
745 :
746 : tree
747 483694 : get_initialized_tmp_var (tree val, gimple_seq *pre_p,
748 : gimple_seq *post_p /* = NULL */,
749 : bool allow_ssa /* = true */)
750 : {
751 483694 : return internal_get_tmp_var (val, pre_p, post_p, false, allow_ssa, false);
752 : }
753 :
754 : /* Declare all the variables in VARS in SCOPE. If DEBUG_INFO is true,
755 : generate debug info for them; otherwise don't. */
756 :
757 : void
758 3013264 : declare_vars (tree vars, gimple *gs, bool debug_info)
759 : {
760 3013264 : tree last = vars;
761 3013264 : if (last)
762 : {
763 1885599 : tree temps, block;
764 :
765 1885599 : gbind *scope = as_a <gbind *> (gs);
766 :
767 1885599 : temps = nreverse (last);
768 :
769 1885599 : block = gimple_bind_block (scope);
770 1885599 : gcc_assert (!block || TREE_CODE (block) == BLOCK);
771 1885599 : if (!block || !debug_info)
772 : {
773 1881867 : DECL_CHAIN (last) = gimple_bind_vars (scope);
774 1881867 : gimple_bind_set_vars (scope, temps);
775 : }
776 : else
777 : {
778 : /* We need to attach the nodes both to the BIND_EXPR and to its
779 : associated BLOCK for debugging purposes. The key point here
780 : is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
781 : is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
782 3732 : if (BLOCK_VARS (block))
783 3539 : BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
784 : else
785 : {
786 193 : gimple_bind_set_vars (scope,
787 : chainon (gimple_bind_vars (scope), temps));
788 193 : BLOCK_VARS (block) = temps;
789 : }
790 : }
791 : }
792 3013264 : }
793 :
794 : /* For VAR a VAR_DECL of variable size, try to find a constant upper bound
795 : for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
796 : no such upper bound can be obtained. */
797 :
798 : static void
799 0 : force_constant_size (tree var)
800 : {
801 : /* The only attempt we make is by querying the maximum size of objects
802 : of the variable's type. */
803 :
804 0 : HOST_WIDE_INT max_size;
805 :
806 0 : gcc_assert (VAR_P (var));
807 :
808 0 : max_size = max_int_size_in_bytes (TREE_TYPE (var));
809 :
810 0 : gcc_assert (max_size >= 0);
811 :
812 0 : DECL_SIZE_UNIT (var)
813 0 : = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
814 0 : DECL_SIZE (var)
815 0 : = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
816 0 : }
817 :
818 : /* Push the temporary variable TMP into the current binding. */
819 :
820 : void
821 24028 : gimple_add_tmp_var_fn (struct function *fn, tree tmp)
822 : {
823 24028 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
824 :
825 : /* Later processing assumes that the object size is constant, which might
826 : not be true at this point. Force the use of a constant upper bound in
827 : this case. */
828 24028 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
829 0 : force_constant_size (tmp);
830 :
831 24028 : DECL_CONTEXT (tmp) = fn->decl;
832 24028 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
833 :
834 24028 : record_vars_into (tmp, fn->decl);
835 24028 : }
836 :
837 : /* Push the temporary variable TMP into the current binding. */
838 :
839 : void
840 16281386 : gimple_add_tmp_var (tree tmp)
841 : {
842 16281386 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
843 :
844 : /* Later processing assumes that the object size is constant, which might
845 : not be true at this point. Force the use of a constant upper bound in
846 : this case. */
847 16281386 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
848 0 : force_constant_size (tmp);
849 :
850 16281386 : DECL_CONTEXT (tmp) = current_function_decl;
851 16281386 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
852 :
853 16281386 : if (gimplify_ctxp)
854 : {
855 5576886 : DECL_CHAIN (tmp) = gimplify_ctxp->temps;
856 5576886 : gimplify_ctxp->temps = tmp;
857 :
858 : /* Mark temporaries local within the nearest enclosing parallel. */
859 5576886 : if (gimplify_omp_ctxp)
860 : {
861 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
862 553323 : int flag = GOVD_LOCAL | GOVD_SEEN;
863 : while (ctx
864 553323 : && (ctx->region_type == ORT_WORKSHARE
865 : || ctx->region_type == ORT_TASKGROUP
866 405784 : || ctx->region_type == ORT_SIMD
867 355593 : || ctx->region_type == ORT_ACC))
868 : {
869 204588 : if (ctx->region_type == ORT_SIMD
870 50191 : && TREE_ADDRESSABLE (tmp)
871 95 : && !TREE_STATIC (tmp))
872 : {
873 95 : if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST)
874 0 : ctx->add_safelen1 = true;
875 95 : else if (ctx->in_for_exprs)
876 : flag = GOVD_PRIVATE;
877 : else
878 : flag = GOVD_PRIVATE | GOVD_SEEN;
879 : break;
880 : }
881 204493 : ctx = ctx->outer_context;
882 : }
883 348735 : if (ctx)
884 321649 : omp_add_variable (ctx, tmp, flag);
885 : }
886 : }
887 10704500 : else if (cfun)
888 10704500 : record_vars (tmp);
889 : else
890 : {
891 0 : gimple_seq body_seq;
892 :
893 : /* This case is for nested functions. We need to expose the locals
894 : they create. */
895 0 : body_seq = gimple_body (current_function_decl);
896 0 : declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
897 : }
898 16281386 : }
899 :
900 : /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
901 : any nested functions. */
902 :
903 : static void
904 2907361 : unshare_body (tree fndecl)
905 : {
906 2907361 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
907 : /* If the language requires deep unsharing, we need a pointer set to make
908 : sure we don't repeatedly unshare subtrees of unshareable nodes. */
909 2907361 : hash_set<tree> *visited
910 2907361 : = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
911 :
912 2907361 : copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
913 2907361 : copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
914 2907361 : copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
915 :
916 2911537 : delete visited;
917 :
918 2907361 : if (cgn)
919 5858554 : for (cgn = first_nested_function (cgn); cgn;
920 26113 : cgn = next_nested_function (cgn))
921 26113 : unshare_body (cgn->decl);
922 2907361 : }
923 :
924 : /* Callback for walk_tree to unmark the visited trees rooted at *TP.
925 : Subtrees are walked until the first unvisited node is encountered. */
926 :
927 : static tree
928 278287029 : unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
929 : {
930 278287029 : tree t = *tp;
931 :
932 : /* If this node has been visited, unmark it and keep looking. */
933 278287029 : if (TREE_VISITED (t))
934 194895506 : TREE_VISITED (t) = 0;
935 :
936 : /* Otherwise, don't look any deeper. */
937 : else
938 83391523 : *walk_subtrees = 0;
939 :
940 278287029 : return NULL_TREE;
941 : }
942 :
943 : /* Unmark the visited trees rooted at *TP. */
944 :
945 : static inline void
946 8722083 : unmark_visited (tree *tp)
947 : {
948 8722083 : walk_tree (tp, unmark_visited_r, NULL, NULL);
949 8722083 : }
950 :
951 : /* Likewise, but mark all trees as not visited. */
952 :
953 : static void
954 2907361 : unvisit_body (tree fndecl)
955 : {
956 2907361 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
957 :
958 2907361 : unmark_visited (&DECL_SAVED_TREE (fndecl));
959 2907361 : unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
960 2907361 : unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
961 :
962 2907361 : if (cgn)
963 2929277 : for (cgn = first_nested_function (cgn);
964 2929277 : cgn; cgn = next_nested_function (cgn))
965 26113 : unvisit_body (cgn->decl);
966 2907361 : }
967 :
968 : /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
969 : one, OR_ELSE otherwise. The location of a STATEMENT_LISTs
970 : comprising at least one DEBUG_BEGIN_STMT followed by exactly one
971 : EXPR is the location of the EXPR. */
972 :
973 : static location_t
974 1170066 : rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
975 : {
976 1170066 : if (!expr)
977 : return or_else;
978 :
979 1170066 : if (EXPR_HAS_LOCATION (expr))
980 817487 : return EXPR_LOCATION (expr);
981 :
982 352579 : if (TREE_CODE (expr) != STATEMENT_LIST)
983 : return or_else;
984 :
985 0 : tree_stmt_iterator i = tsi_start (expr);
986 :
987 0 : bool found = false;
988 0 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
989 : {
990 0 : found = true;
991 0 : tsi_next (&i);
992 : }
993 :
994 352579 : if (!found || !tsi_one_before_end_p (i))
995 : return or_else;
996 :
997 0 : return rexpr_location (tsi_stmt (i), or_else);
998 : }
999 :
1000 : /* Return TRUE iff EXPR (maybe recursively) has a location; see
1001 : rexpr_location for the potential recursion. */
1002 :
1003 : static inline bool
1004 508861 : rexpr_has_location (tree expr)
1005 : {
1006 305783 : return rexpr_location (expr) != UNKNOWN_LOCATION;
1007 : }
1008 :
1009 :
1010 : /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
1011 : contain statements and have a value. Assign its value to a temporary
1012 : and give it void_type_node. Return the temporary, or NULL_TREE if
1013 : WRAPPER was already void. */
1014 :
1015 : tree
1016 20030948 : voidify_wrapper_expr (tree wrapper, tree temp)
1017 : {
1018 20030948 : tree type = TREE_TYPE (wrapper);
1019 20030948 : if (type && !VOID_TYPE_P (type))
1020 : {
1021 : tree *p;
1022 :
1023 : /* Set p to point to the body of the wrapper. Loop until we find
1024 : something that isn't a wrapper. */
1025 766407 : for (p = &wrapper; p && *p; )
1026 : {
1027 766407 : switch (TREE_CODE (*p))
1028 : {
1029 3144 : case BIND_EXPR:
1030 3144 : TREE_SIDE_EFFECTS (*p) = 1;
1031 3144 : TREE_TYPE (*p) = void_type_node;
1032 : /* For a BIND_EXPR, the body is operand 1. */
1033 3144 : p = &BIND_EXPR_BODY (*p);
1034 3144 : break;
1035 :
1036 353747 : case CLEANUP_POINT_EXPR:
1037 353747 : case TRY_FINALLY_EXPR:
1038 353747 : case TRY_CATCH_EXPR:
1039 353747 : TREE_SIDE_EFFECTS (*p) = 1;
1040 353747 : TREE_TYPE (*p) = void_type_node;
1041 353747 : p = &TREE_OPERAND (*p, 0);
1042 353747 : break;
1043 :
1044 17903 : case STATEMENT_LIST:
1045 17903 : {
1046 17903 : tree_stmt_iterator i = tsi_last (*p);
1047 17903 : TREE_SIDE_EFFECTS (*p) = 1;
1048 17903 : TREE_TYPE (*p) = void_type_node;
1049 17903 : p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
1050 : }
1051 17903 : break;
1052 :
1053 : case COMPOUND_EXPR:
1054 : /* Advance to the last statement. Set all container types to
1055 : void. */
1056 63512 : for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
1057 : {
1058 31759 : TREE_SIDE_EFFECTS (*p) = 1;
1059 31759 : TREE_TYPE (*p) = void_type_node;
1060 : }
1061 : break;
1062 :
1063 76 : case TRANSACTION_EXPR:
1064 76 : TREE_SIDE_EFFECTS (*p) = 1;
1065 76 : TREE_TYPE (*p) = void_type_node;
1066 76 : p = &TRANSACTION_EXPR_BODY (*p);
1067 76 : break;
1068 :
1069 359784 : default:
1070 : /* Assume that any tree upon which voidify_wrapper_expr is
1071 : directly called is a wrapper, and that its body is op0. */
1072 359784 : if (p == &wrapper)
1073 : {
1074 33 : TREE_SIDE_EFFECTS (*p) = 1;
1075 33 : TREE_TYPE (*p) = void_type_node;
1076 33 : p = &TREE_OPERAND (*p, 0);
1077 33 : break;
1078 : }
1079 359751 : goto out;
1080 : }
1081 : }
1082 :
1083 0 : out:
1084 359751 : if (p == NULL || IS_EMPTY_STMT (*p))
1085 : temp = NULL_TREE;
1086 359751 : else if (temp)
1087 : {
1088 : /* The wrapper is on the RHS of an assignment that we're pushing
1089 : down. */
1090 1933 : gcc_assert (TREE_CODE (temp) == INIT_EXPR
1091 : || TREE_CODE (temp) == MODIFY_EXPR);
1092 1933 : TREE_OPERAND (temp, 1) = *p;
1093 1933 : *p = temp;
1094 : }
1095 : else
1096 : {
1097 357818 : temp = create_tmp_var (type, "retval");
1098 357818 : *p = build2 (INIT_EXPR, type, temp, *p);
1099 : }
1100 :
1101 359751 : return temp;
1102 : }
1103 :
1104 : return NULL_TREE;
1105 : }
1106 :
1107 : /* Prepare calls to builtins to SAVE and RESTORE the stack as well as
1108 : a temporary through which they communicate. */
1109 :
1110 : static void
1111 7870 : build_stack_save_restore (gcall **save, gcall **restore)
1112 : {
1113 7870 : tree tmp_var;
1114 :
1115 15740 : *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
1116 7870 : tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
1117 7870 : gimple_call_set_lhs (*save, tmp_var);
1118 :
1119 7870 : *restore
1120 7870 : = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1121 : 1, tmp_var);
1122 7870 : }
1123 :
1124 : /* Generate IFN_ASAN_MARK call that poisons shadow memory of the DECL
1125 : variable. */
1126 :
1127 : static tree
1128 478 : build_asan_poison_call_expr (tree decl)
1129 : {
1130 : /* Do not poison variables that have size equal to zero. */
1131 478 : tree unit_size = DECL_SIZE_UNIT (decl);
1132 478 : if (zerop (unit_size))
1133 : return NULL_TREE;
1134 :
1135 478 : tree base = build_fold_addr_expr (decl);
1136 :
1137 478 : return build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_ASAN_MARK,
1138 : void_type_node, 3,
1139 : build_int_cst (integer_type_node,
1140 : ASAN_MARK_POISON),
1141 : base, unit_size);
1142 : }
1143 :
1144 : /* Generate IFN_ASAN_MARK call that would poison or unpoison, depending
1145 : on POISON flag, shadow memory of a DECL variable. The call will be
1146 : put on location identified by IT iterator, where BEFORE flag drives
1147 : position where the stmt will be put. */
1148 :
1149 : static void
1150 5065 : asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
1151 : bool before)
1152 : {
1153 5065 : tree unit_size = DECL_SIZE_UNIT (decl);
1154 5065 : tree base = build_fold_addr_expr (decl);
1155 :
1156 : /* Do not poison variables that have size equal to zero. */
1157 5065 : if (zerop (unit_size))
1158 5065 : return;
1159 :
1160 : /* It's necessary to have all stack variables aligned to ASAN granularity
1161 : bytes. */
1162 5051 : gcc_assert (!hwassist_sanitize_p () || hwassist_sanitize_stack_p ());
1163 5051 : unsigned shadow_granularity
1164 5051 : = (hwassist_sanitize_p ()
1165 5051 : ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY);
1166 5051 : if (DECL_ALIGN_UNIT (decl) <= shadow_granularity)
1167 4849 : SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity);
1168 :
1169 5051 : HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON;
1170 :
1171 5051 : gimple *g
1172 5051 : = gimple_build_call_internal (IFN_ASAN_MARK, 3,
1173 5051 : build_int_cst (integer_type_node, flags),
1174 : base, unit_size);
1175 :
1176 5051 : if (before)
1177 2648 : gsi_insert_before (it, g, GSI_NEW_STMT);
1178 : else
1179 2403 : gsi_insert_after (it, g, GSI_NEW_STMT);
1180 : }
1181 :
1182 : /* Generate IFN_ASAN_MARK internal call that depending on POISON flag
1183 : either poisons or unpoisons a DECL. Created statement is appended
1184 : to SEQ_P gimple sequence. */
1185 :
1186 : static void
1187 4587 : asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
1188 : {
1189 4587 : gimple_stmt_iterator it = gsi_last (*seq_p);
1190 4587 : bool before = false;
1191 :
1192 4587 : if (gsi_end_p (it))
1193 2433 : before = true;
1194 :
1195 4587 : asan_poison_variable (decl, poison, &it, before);
1196 4587 : }
1197 :
1198 : /* Sort pair of VAR_DECLs A and B by DECL_UID. */
1199 :
1200 : static int
1201 135 : sort_by_decl_uid (const void *a, const void *b)
1202 : {
1203 135 : const tree *t1 = (const tree *)a;
1204 135 : const tree *t2 = (const tree *)b;
1205 :
1206 135 : int uid1 = DECL_UID (*t1);
1207 135 : int uid2 = DECL_UID (*t2);
1208 :
1209 135 : if (uid1 < uid2)
1210 : return -1;
1211 57 : else if (uid1 > uid2)
1212 : return 1;
1213 : else
1214 0 : return 0;
1215 : }
1216 :
1217 : /* Generate IFN_ASAN_MARK internal call for all VARIABLES
1218 : depending on POISON flag. Created statement is appended
1219 : to SEQ_P gimple sequence. */
1220 :
1221 : static void
1222 1034761 : asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p)
1223 : {
1224 1034761 : unsigned c = variables->elements ();
1225 1034761 : if (c == 0)
1226 1034487 : return;
1227 :
1228 274 : auto_vec<tree> sorted_variables (c);
1229 :
1230 274 : for (hash_set<tree>::iterator it = variables->begin ();
1231 864 : it != variables->end (); ++it)
1232 295 : sorted_variables.safe_push (*it);
1233 :
1234 274 : sorted_variables.qsort (sort_by_decl_uid);
1235 :
1236 : unsigned i;
1237 : tree var;
1238 843 : FOR_EACH_VEC_ELT (sorted_variables, i, var)
1239 : {
1240 295 : asan_poison_variable (var, poison, seq_p);
1241 :
1242 : /* Add use_after_scope_memory attribute for the variable in order
1243 : to prevent re-written into SSA. */
1244 295 : if (!lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
1245 295 : DECL_ATTRIBUTES (var)))
1246 97 : DECL_ATTRIBUTES (var)
1247 194 : = tree_cons (get_identifier (ASAN_USE_AFTER_SCOPE_ATTRIBUTE),
1248 : integer_one_node,
1249 97 : DECL_ATTRIBUTES (var));
1250 : }
1251 274 : }
1252 :
1253 : /* Gimplify a BIND_EXPR. Just voidify and recurse. */
1254 :
1255 : static enum gimplify_status
1256 5927825 : gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
1257 : {
1258 5927825 : tree bind_expr = *expr_p;
1259 5927825 : bool old_keep_stack = gimplify_ctxp->keep_stack;
1260 5927825 : bool old_save_stack = gimplify_ctxp->save_stack;
1261 5927825 : tree t;
1262 5927825 : gbind *bind_stmt;
1263 5927825 : gimple_seq body, cleanup;
1264 5927825 : gcall *stack_save;
1265 5927825 : location_t start_locus = 0, end_locus = 0;
1266 5927825 : tree ret_clauses = NULL;
1267 :
1268 5927825 : tree temp = voidify_wrapper_expr (bind_expr, NULL);
1269 :
1270 : /* Mark variables seen in this bind expr. */
1271 12738720 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1272 : {
1273 6810895 : if (VAR_P (t))
1274 : {
1275 6169366 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1276 6169366 : tree attr;
1277 :
1278 6169366 : if (flag_openmp
1279 258255 : && !is_global_var (t)
1280 249341 : && !TREE_STATIC (t)
1281 249341 : && DECL_CONTEXT (t) == current_function_decl
1282 249341 : && TREE_USED (t)
1283 6417086 : && (attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1284 : != NULL_TREE)
1285 : {
1286 76 : gcc_assert (!DECL_HAS_VALUE_EXPR_P (t));
1287 76 : tree alloc = TREE_PURPOSE (TREE_VALUE (attr));
1288 76 : tree align = TREE_VALUE (TREE_VALUE (attr));
1289 : /* Allocate directives that appear in a target region must specify
1290 : an allocator clause unless a requires directive with the
1291 : dynamic_allocators clause is present in the same compilation
1292 : unit. */
1293 76 : bool missing_dyn_alloc = false;
1294 76 : if (alloc == NULL_TREE
1295 48 : && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS)
1296 : == 0))
1297 : {
1298 : /* This comes too early for omp_discover_declare_target...,
1299 : but should at least catch the most common cases. */
1300 42 : missing_dyn_alloc
1301 42 : = cgraph_node::get (current_function_decl)->offloadable;
1302 42 : for (struct gimplify_omp_ctx *ctx2 = ctx;
1303 48 : ctx2 && !missing_dyn_alloc; ctx2 = ctx2->outer_context)
1304 6 : if (ctx2->code == OMP_TARGET)
1305 2 : missing_dyn_alloc = true;
1306 : }
1307 42 : if (missing_dyn_alloc)
1308 4 : error_at (DECL_SOURCE_LOCATION (t),
1309 : "%<allocate%> directive for %qD inside a target "
1310 : "region must specify an %<allocator%> clause", t);
1311 : /* Skip for omp_default_mem_alloc (= 1),
1312 : unless align is present. For C/C++, there should be always a
1313 : statement list following if TREE_USED, except for, e.g., using
1314 : this decl in a static_assert; in that case, only a single
1315 : DECL_EXPR remains, which can be skipped here. */
1316 72 : else if (!errorcount
1317 57 : && (align != NULL_TREE
1318 57 : || alloc == NULL_TREE
1319 12 : || !integer_onep (alloc))
1320 127 : && (lang_GNU_Fortran ()
1321 27 : || (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1322 : != DECL_EXPR)))
1323 : {
1324 : /* Fortran might already use a pointer type internally;
1325 : use that pointer except for type(C_ptr) and type(C_funptr);
1326 : note that normal proc pointers are rejected. */
1327 55 : tree type = TREE_TYPE (t);
1328 55 : tree tmp, v;
1329 55 : if (lang_GNU_Fortran ()
1330 28 : && POINTER_TYPE_P (type)
1331 8 : && TREE_TYPE (type) != void_type_node
1332 61 : && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
1333 : {
1334 6 : type = TREE_TYPE (type);
1335 6 : v = t;
1336 : }
1337 : else
1338 : {
1339 49 : tmp = build_pointer_type (type);
1340 49 : v = create_tmp_var (tmp, get_name (t));
1341 49 : DECL_IGNORED_P (v) = 0;
1342 49 : DECL_ATTRIBUTES (v)
1343 49 : = tree_cons (get_identifier ("omp allocate var"),
1344 : build_tree_list (NULL_TREE, t),
1345 : remove_attribute ("omp allocate",
1346 49 : DECL_ATTRIBUTES (t)));
1347 49 : tmp = build_fold_indirect_ref (v);
1348 49 : TREE_THIS_NOTRAP (tmp) = 1;
1349 49 : SET_DECL_VALUE_EXPR (t, tmp);
1350 49 : DECL_HAS_VALUE_EXPR_P (t) = 1;
1351 : }
1352 55 : tree sz = TYPE_SIZE_UNIT (type);
1353 : /* The size to use in Fortran might not match TYPE_SIZE_UNIT;
1354 : hence, for some decls, a size variable is saved in the
1355 : attributes; use it, if available. */
1356 55 : if (TREE_CHAIN (TREE_VALUE (attr))
1357 28 : && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))
1358 61 : && TREE_PURPOSE (
1359 : TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))))
1360 : {
1361 6 : sz = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1362 6 : sz = TREE_PURPOSE (sz);
1363 : }
1364 55 : if (alloc == NULL_TREE)
1365 36 : alloc = build_zero_cst (ptr_type_node);
1366 55 : if (align == NULL_TREE)
1367 44 : align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (t));
1368 : else
1369 11 : align = build_int_cst (size_type_node,
1370 11 : MAX (tree_to_uhwi (align),
1371 : DECL_ALIGN_UNIT (t)));
1372 55 : location_t loc = DECL_SOURCE_LOCATION (t);
1373 55 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
1374 55 : tmp = build_call_expr_loc (loc, tmp, 3, align, sz, alloc);
1375 55 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1376 55 : fold_convert (TREE_TYPE (v), tmp));
1377 55 : gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE);
1378 : /* Ensure that either TREE_CHAIN (TREE_VALUE (attr) is set
1379 : and GOMP_FREE added here or that DECL_HAS_VALUE_EXPR_P (t)
1380 : is set, using in a condition much further below. */
1381 61 : gcc_assert (DECL_HAS_VALUE_EXPR_P (t)
1382 : || TREE_CHAIN (TREE_VALUE (attr)));
1383 55 : if (TREE_CHAIN (TREE_VALUE (attr)))
1384 : {
1385 : /* Fortran is special as it does not have properly nest
1386 : declarations in blocks. And as there is no
1387 : initializer, there is also no expression to look for.
1388 : Hence, the FE makes the statement list of the
1389 : try-finally block available. We can put the GOMP_alloc
1390 : at the top, unless an allocator or size expression
1391 : requires to put it afterward; note that the size is
1392 : always later in generated code; for strings, no
1393 : size expr but still an expr might be available.
1394 : As LTO does not handle a statement list, 'sl' has
1395 : to be removed; done so by removing the attribute. */
1396 28 : DECL_ATTRIBUTES (t)
1397 28 : = remove_attribute ("omp allocate",
1398 28 : DECL_ATTRIBUTES (t));
1399 28 : tree sl = TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)));
1400 28 : tree_stmt_iterator e = tsi_start (sl);
1401 28 : tree needle = NULL_TREE;
1402 28 : if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1403 : {
1404 6 : needle = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1405 6 : needle = (TREE_VALUE (needle) ? TREE_VALUE (needle)
1406 : : sz);
1407 : }
1408 22 : else if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1409 : needle = sz;
1410 22 : else if (DECL_P (alloc) && DECL_ARTIFICIAL (alloc))
1411 : needle = alloc;
1412 :
1413 10 : if (needle != NULL_TREE)
1414 : {
1415 49 : while (!tsi_end_p (e))
1416 : {
1417 49 : if (*e == needle
1418 49 : || (TREE_CODE (*e) == MODIFY_EXPR
1419 49 : && TREE_OPERAND (*e, 0) == needle))
1420 : break;
1421 39 : ++e;
1422 : }
1423 10 : gcc_assert (!tsi_end_p (e));
1424 : }
1425 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1426 :
1427 : /* As the cleanup is in BIND_EXPR_BODY, GOMP_free is added
1428 : here; for C/C++ it will be added in the 'cleanup'
1429 : section after gimplification. But Fortran already has
1430 : a try-finally block. */
1431 28 : sl = TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)));
1432 28 : e = tsi_last (sl);
1433 28 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1434 28 : tmp = build_call_expr_loc (EXPR_LOCATION (*e), tmp, 2, v,
1435 : build_zero_cst (ptr_type_node));
1436 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1437 28 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1438 28 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1439 28 : fold_convert (TREE_TYPE (v), tmp));
1440 28 : ++e;
1441 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1442 : }
1443 : else
1444 : {
1445 27 : gcc_assert (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1446 : == STATEMENT_LIST);
1447 27 : tree_stmt_iterator e;
1448 27 : e = tsi_start (BIND_EXPR_BODY (bind_expr));
1449 117 : while (!tsi_end_p (e))
1450 : {
1451 90 : if ((TREE_CODE (*e) == DECL_EXPR
1452 60 : && TREE_OPERAND (*e, 0) == t)
1453 123 : || (TREE_CODE (*e) == CLEANUP_POINT_EXPR
1454 0 : && (TREE_CODE (TREE_OPERAND (*e, 0))
1455 : == DECL_EXPR)
1456 0 : && (TREE_OPERAND (TREE_OPERAND (*e, 0), 0)
1457 : == t)))
1458 : break;
1459 63 : ++e;
1460 : }
1461 27 : gcc_assert (!tsi_end_p (e));
1462 27 : tsi_link_before (&e, tmp, TSI_SAME_STMT);
1463 : }
1464 : }
1465 : }
1466 :
1467 : /* Mark variable as local. */
1468 6169366 : if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t))
1469 : {
1470 100748 : if (! DECL_SEEN_IN_BIND_EXPR_P (t)
1471 100748 : || splay_tree_lookup (ctx->variables,
1472 : (splay_tree_key) t) == NULL)
1473 : {
1474 100748 : int flag = GOVD_LOCAL;
1475 100748 : if (ctx->region_type == ORT_SIMD
1476 4374 : && TREE_ADDRESSABLE (t)
1477 81 : && !TREE_STATIC (t))
1478 : {
1479 69 : if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST)
1480 2 : ctx->add_safelen1 = true;
1481 : else
1482 : flag = GOVD_PRIVATE;
1483 : }
1484 100748 : omp_add_variable (ctx, t, flag | GOVD_SEEN);
1485 : }
1486 : /* Static locals inside of target construct or offloaded
1487 : routines need to be "omp declare target". */
1488 100748 : if (TREE_STATIC (t))
1489 1380 : for (; ctx; ctx = ctx->outer_context)
1490 1201 : if ((ctx->region_type & ORT_TARGET) != 0)
1491 : {
1492 964 : if (!lookup_attribute ("omp declare target",
1493 964 : DECL_ATTRIBUTES (t)))
1494 : {
1495 952 : tree id = get_identifier ("omp declare target");
1496 952 : DECL_ATTRIBUTES (t)
1497 952 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
1498 952 : varpool_node *node = varpool_node::get (t);
1499 952 : if (node)
1500 : {
1501 33 : node->offloadable = 1;
1502 33 : if (ENABLE_OFFLOADING && !DECL_EXTERNAL (t))
1503 : {
1504 : g->have_offload = true;
1505 : if (!in_lto_p)
1506 : vec_safe_push (offload_vars, t);
1507 : }
1508 : }
1509 : }
1510 : break;
1511 : }
1512 : }
1513 :
1514 6169366 : DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
1515 :
1516 6169366 : if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
1517 1088 : cfun->has_local_explicit_reg_vars = true;
1518 : }
1519 : }
1520 :
1521 11855650 : bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
1522 5927825 : BIND_EXPR_BLOCK (bind_expr));
1523 5927825 : gimple_push_bind_expr (bind_stmt);
1524 :
1525 5927825 : gimplify_ctxp->keep_stack = false;
1526 5927825 : gimplify_ctxp->save_stack = false;
1527 :
1528 : /* Gimplify the body into the GIMPLE_BIND tuple's body. */
1529 5927825 : body = NULL;
1530 5927825 : gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
1531 5927825 : gimple_bind_set_body (bind_stmt, body);
1532 :
1533 : /* Source location wise, the cleanup code (stack_restore and clobbers)
1534 : belongs to the end of the block, so propagate what we have. The
1535 : stack_save operation belongs to the beginning of block, which we can
1536 : infer from the bind_expr directly if the block has no explicit
1537 : assignment. */
1538 5927825 : if (BIND_EXPR_BLOCK (bind_expr))
1539 : {
1540 5796410 : end_locus = BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1541 5796410 : start_locus = BLOCK_SOURCE_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1542 : }
1543 5796410 : if (start_locus == 0)
1544 5927825 : start_locus = EXPR_LOCATION (bind_expr);
1545 :
1546 5927825 : cleanup = NULL;
1547 5927825 : stack_save = NULL;
1548 :
1549 : /* Add clobbers for all variables that go out of scope. */
1550 12738720 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1551 : {
1552 6810895 : if (VAR_P (t)
1553 6169366 : && !is_global_var (t)
1554 12762527 : && DECL_CONTEXT (t) == current_function_decl)
1555 : {
1556 5951632 : if (flag_openmp
1557 249326 : && DECL_HAS_VALUE_EXPR_P (t)
1558 1087 : && TREE_USED (t)
1559 5952700 : && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1560 : {
1561 : /* For Fortran, TREE_CHAIN (TREE_VALUE (attr)) is set, which
1562 : causes that the GOMP_free call is already added above;
1563 : and "omp allocate" is removed from DECL_ATTRIBUTES. */
1564 27 : tree v = TREE_OPERAND (DECL_VALUE_EXPR (t), 0);
1565 27 : tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1566 27 : tmp = build_call_expr_loc (end_locus, tmp, 2, v,
1567 : build_zero_cst (ptr_type_node));
1568 27 : gimplify_and_add (tmp, &cleanup);
1569 27 : gimple *clobber_stmt;
1570 27 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1571 27 : clobber_stmt = gimple_build_assign (v, tmp);
1572 27 : gimple_set_location (clobber_stmt, end_locus);
1573 27 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1574 : }
1575 5951632 : if (!DECL_HARD_REGISTER (t)
1576 5950544 : && !TREE_THIS_VOLATILE (t)
1577 5911549 : && !DECL_HAS_VALUE_EXPR_P (t)
1578 : /* Only care for variables that have to be in memory. Others
1579 : will be rewritten into SSA names, hence moved to the
1580 : top-level. */
1581 5808109 : && !is_gimple_reg (t)
1582 7189832 : && flag_stack_reuse != SR_NONE)
1583 : {
1584 1234753 : tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_STORAGE_END);
1585 1234753 : gimple *clobber_stmt;
1586 1234753 : clobber_stmt = gimple_build_assign (t, clobber);
1587 1234753 : gimple_set_location (clobber_stmt, end_locus);
1588 1234753 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1589 : }
1590 :
1591 5951632 : if (flag_openacc && oacc_declare_returns != NULL)
1592 : {
1593 207 : tree key = t;
1594 207 : if (DECL_HAS_VALUE_EXPR_P (key))
1595 : {
1596 8 : key = DECL_VALUE_EXPR (key);
1597 8 : if (INDIRECT_REF_P (key))
1598 8 : key = TREE_OPERAND (key, 0);
1599 : }
1600 207 : tree *c = oacc_declare_returns->get (key);
1601 207 : if (c != NULL)
1602 : {
1603 116 : if (ret_clauses)
1604 64 : OMP_CLAUSE_CHAIN (*c) = ret_clauses;
1605 :
1606 116 : ret_clauses = unshare_expr (*c);
1607 :
1608 116 : oacc_declare_returns->remove (key);
1609 :
1610 116 : if (oacc_declare_returns->is_empty ())
1611 : {
1612 40 : delete oacc_declare_returns;
1613 40 : oacc_declare_returns = NULL;
1614 : }
1615 : }
1616 : }
1617 : }
1618 :
1619 6810895 : if (asan_poisoned_variables != NULL
1620 6810895 : && asan_poisoned_variables->contains (t))
1621 : {
1622 2146 : asan_poisoned_variables->remove (t);
1623 2146 : asan_poison_variable (t, true, &cleanup);
1624 : }
1625 :
1626 6810895 : if (gimplify_ctxp->live_switch_vars != NULL
1627 6810895 : && gimplify_ctxp->live_switch_vars->contains (t))
1628 55 : gimplify_ctxp->live_switch_vars->remove (t);
1629 : }
1630 :
1631 : /* If the code both contains VLAs and calls alloca, then we cannot reclaim
1632 : the stack space allocated to the VLAs. */
1633 5927825 : if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack)
1634 : {
1635 7870 : gcall *stack_restore;
1636 :
1637 : /* Save stack on entry and restore it on exit. Add a try_finally
1638 : block to achieve this. */
1639 7870 : build_stack_save_restore (&stack_save, &stack_restore);
1640 :
1641 7870 : gimple_set_location (stack_save, start_locus);
1642 7870 : gimple_set_location (stack_restore, end_locus);
1643 :
1644 7870 : gimplify_seq_add_stmt (&cleanup, stack_restore);
1645 : }
1646 :
1647 5927825 : if (ret_clauses)
1648 : {
1649 52 : gomp_target *stmt;
1650 52 : gimple_stmt_iterator si = gsi_start (cleanup);
1651 :
1652 52 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
1653 : ret_clauses);
1654 52 : gsi_insert_seq_before_without_update (&si, stmt, GSI_NEW_STMT);
1655 : }
1656 :
1657 5927825 : if (cleanup)
1658 : {
1659 762931 : gtry *gs;
1660 762931 : gimple_seq new_body;
1661 :
1662 762931 : new_body = NULL;
1663 762931 : gs = gimple_build_try (gimple_bind_body (bind_stmt), cleanup,
1664 : GIMPLE_TRY_FINALLY);
1665 :
1666 762931 : if (stack_save)
1667 7870 : gimplify_seq_add_stmt (&new_body, stack_save);
1668 762931 : gimplify_seq_add_stmt (&new_body, gs);
1669 762931 : gimple_bind_set_body (bind_stmt, new_body);
1670 : }
1671 :
1672 : /* keep_stack propagates all the way up to the outermost BIND_EXPR. */
1673 5927825 : if (!gimplify_ctxp->keep_stack)
1674 5912504 : gimplify_ctxp->keep_stack = old_keep_stack;
1675 5927825 : gimplify_ctxp->save_stack = old_save_stack;
1676 :
1677 5927825 : gimple_pop_bind_expr ();
1678 :
1679 5927825 : gimplify_seq_add_stmt (pre_p, bind_stmt);
1680 :
1681 5927825 : if (temp)
1682 : {
1683 1709 : *expr_p = temp;
1684 1709 : return GS_OK;
1685 : }
1686 :
1687 5926116 : *expr_p = NULL_TREE;
1688 5926116 : return GS_ALL_DONE;
1689 : }
1690 :
1691 : /* Maybe add early return predict statement to PRE_P sequence. */
1692 :
1693 : static void
1694 2201599 : maybe_add_early_return_predict_stmt (gimple_seq *pre_p)
1695 : {
1696 : /* If we are not in a conditional context, add PREDICT statement. */
1697 2201599 : if (gimple_conditional_context ())
1698 : {
1699 440612 : gimple *predict = gimple_build_predict (PRED_TREE_EARLY_RETURN,
1700 : NOT_TAKEN);
1701 440612 : gimplify_seq_add_stmt (pre_p, predict);
1702 : }
1703 2201599 : }
1704 :
1705 : /* Gimplify a RETURN_EXPR. If the expression to be returned is not a
1706 : GIMPLE value, it is assigned to a new temporary and the statement is
1707 : re-written to return the temporary.
1708 :
1709 : PRE_P points to the sequence where side effects that must happen before
1710 : STMT should be stored. */
1711 :
1712 : static enum gimplify_status
1713 2201605 : gimplify_return_expr (tree stmt, gimple_seq *pre_p)
1714 : {
1715 2201605 : greturn *ret;
1716 2201605 : tree ret_expr = TREE_OPERAND (stmt, 0);
1717 2201605 : tree result_decl, result;
1718 :
1719 2201605 : if (ret_expr == error_mark_node)
1720 : return GS_ERROR;
1721 :
1722 2201599 : if (!ret_expr
1723 2114743 : || TREE_CODE (ret_expr) == RESULT_DECL)
1724 : {
1725 100582 : maybe_add_early_return_predict_stmt (pre_p);
1726 100582 : greturn *ret = gimple_build_return (ret_expr);
1727 100582 : copy_warning (ret, stmt);
1728 100582 : gimplify_seq_add_stmt (pre_p, ret);
1729 100582 : return GS_ALL_DONE;
1730 : }
1731 :
1732 2101017 : if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
1733 : result_decl = NULL_TREE;
1734 2100691 : else if (TREE_CODE (ret_expr) == COMPOUND_EXPR)
1735 : {
1736 : /* Used in C++ for handling EH cleanup of the return value if a local
1737 : cleanup throws. Assume the front-end knows what it's doing. */
1738 4807 : result_decl = DECL_RESULT (current_function_decl);
1739 : /* But crash if we end up trying to modify ret_expr below. */
1740 4807 : ret_expr = NULL_TREE;
1741 : }
1742 : else
1743 : {
1744 2095884 : result_decl = TREE_OPERAND (ret_expr, 0);
1745 :
1746 : /* See through a return by reference. */
1747 2095884 : if (INDIRECT_REF_P (result_decl))
1748 42340 : result_decl = TREE_OPERAND (result_decl, 0);
1749 :
1750 2095884 : gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
1751 : || TREE_CODE (ret_expr) == INIT_EXPR)
1752 : && TREE_CODE (result_decl) == RESULT_DECL);
1753 : }
1754 :
1755 : /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
1756 : Recall that aggregate_value_p is FALSE for any aggregate type that is
1757 : returned in registers. If we're returning values in registers, then
1758 : we don't want to extend the lifetime of the RESULT_DECL, particularly
1759 : across another call. In addition, for those aggregates for which
1760 : hard_function_value generates a PARALLEL, we'll die during normal
1761 : expansion of structure assignments; there's special code in expand_return
1762 : to handle this case that does not exist in expand_expr. */
1763 4807 : if (!result_decl)
1764 : result = NULL_TREE;
1765 2100691 : else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
1766 : {
1767 178288 : if (!poly_int_tree_p (DECL_SIZE (result_decl)))
1768 : {
1769 48 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
1770 0 : gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
1771 : /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
1772 : should be effectively allocated by the caller, i.e. all calls to
1773 : this function must be subject to the Return Slot Optimization. */
1774 48 : gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
1775 48 : gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
1776 : }
1777 : result = result_decl;
1778 : }
1779 1922403 : else if (gimplify_ctxp->return_temp)
1780 : result = gimplify_ctxp->return_temp;
1781 : else
1782 : {
1783 1433697 : result = create_tmp_reg (TREE_TYPE (result_decl));
1784 :
1785 : /* ??? With complex control flow (usually involving abnormal edges),
1786 : we can wind up warning about an uninitialized value for this. Due
1787 : to how this variable is constructed and initialized, this is never
1788 : true. Give up and never warn. */
1789 1433697 : suppress_warning (result, OPT_Wuninitialized);
1790 :
1791 1433697 : gimplify_ctxp->return_temp = result;
1792 : }
1793 :
1794 : /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
1795 : Then gimplify the whole thing. */
1796 2101017 : if (result != result_decl)
1797 1922403 : TREE_OPERAND (ret_expr, 0) = result;
1798 :
1799 2101017 : gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
1800 :
1801 2101017 : maybe_add_early_return_predict_stmt (pre_p);
1802 2101017 : ret = gimple_build_return (result);
1803 2101017 : copy_warning (ret, stmt);
1804 2101017 : gimplify_seq_add_stmt (pre_p, ret);
1805 :
1806 2101017 : return GS_ALL_DONE;
1807 : }
1808 :
1809 : /* Gimplify a variable-length array DECL. */
1810 :
1811 : static void
1812 8970 : gimplify_vla_decl (tree decl, gimple_seq *seq_p)
1813 : {
1814 : /* This is a variable-sized decl. Simplify its size and mark it
1815 : for deferred expansion. */
1816 8970 : tree t, addr, ptr_type;
1817 :
1818 8970 : gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
1819 8970 : gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
1820 :
1821 : /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */
1822 8970 : if (DECL_HAS_VALUE_EXPR_P (decl))
1823 : return;
1824 :
1825 : /* All occurrences of this decl in final gimplified code will be
1826 : replaced by indirection. Setting DECL_VALUE_EXPR does two
1827 : things: First, it lets the rest of the gimplifier know what
1828 : replacement to use. Second, it lets the debug info know
1829 : where to find the value. */
1830 8965 : ptr_type = build_pointer_type (TREE_TYPE (decl));
1831 8965 : addr = create_tmp_var (ptr_type, get_name (decl));
1832 8965 : DECL_IGNORED_P (addr) = 0;
1833 8965 : t = build_fold_indirect_ref (addr);
1834 8965 : TREE_THIS_NOTRAP (t) = 1;
1835 8965 : SET_DECL_VALUE_EXPR (decl, t);
1836 8965 : DECL_HAS_VALUE_EXPR_P (decl) = 1;
1837 :
1838 8965 : t = build_alloca_call_expr (DECL_SIZE_UNIT (decl), DECL_ALIGN (decl),
1839 8965 : max_int_size_in_bytes (TREE_TYPE (decl)));
1840 : /* The call has been built for a variable-sized object. */
1841 8965 : CALL_ALLOCA_FOR_VAR_P (t) = 1;
1842 8965 : t = fold_convert (ptr_type, t);
1843 8965 : t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
1844 :
1845 8965 : gimplify_and_add (t, seq_p);
1846 :
1847 : /* Record the dynamic allocation associated with DECL if requested. */
1848 8965 : if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
1849 0 : record_dynamic_alloc (decl);
1850 : }
1851 :
1852 : /* A helper function to be called via walk_tree. Mark all labels under *TP
1853 : as being forced. To be called for DECL_INITIAL of static variables. */
1854 :
1855 : static tree
1856 857051 : force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1857 : {
1858 857051 : if (TYPE_P (*tp))
1859 0 : *walk_subtrees = 0;
1860 857051 : if (TREE_CODE (*tp) == LABEL_DECL)
1861 : {
1862 926 : FORCED_LABEL (*tp) = 1;
1863 926 : cfun->has_forced_label_in_static = 1;
1864 : }
1865 :
1866 857051 : return NULL_TREE;
1867 : }
1868 :
1869 : /* Generate an initialization to automatic variable DECL based on INIT_TYPE.
1870 : Build a call to internal const function DEFERRED_INIT:
1871 : 1st argument: SIZE of the DECL;
1872 : 2nd argument: INIT_TYPE;
1873 : 3rd argument: NAME of the DECL;
1874 :
1875 : as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL). */
1876 :
1877 : static void
1878 122819 : gimple_add_init_for_auto_var (tree decl,
1879 : enum auto_init_type init_type,
1880 : gimple_seq *seq_p)
1881 : {
1882 122819 : gcc_assert (auto_var_p (decl));
1883 122819 : gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
1884 :
1885 122819 : const location_t loc = DECL_SOURCE_LOCATION (decl);
1886 122819 : tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
1887 122819 : tree init_type_node = build_int_cst (integer_type_node, (int) init_type);
1888 122819 : tree decl_name;
1889 :
1890 122819 : if (DECL_NAME (decl))
1891 69231 : decl_name = build_string_literal (DECL_NAME (decl));
1892 : else
1893 : {
1894 53588 : char decl_name_anonymous[3 + (HOST_BITS_PER_INT + 2) / 3];
1895 53588 : sprintf (decl_name_anonymous, "D.%u", DECL_UID (decl));
1896 53588 : decl_name = build_string_literal (decl_name_anonymous);
1897 : }
1898 :
1899 122819 : tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT,
1900 122819 : TREE_TYPE (decl), 3,
1901 : decl_size, init_type_node,
1902 : decl_name);
1903 :
1904 122819 : gimplify_assign (decl, call, seq_p);
1905 122819 : }
1906 :
1907 : /* Generate padding initialization for automatic variable DECL.
1908 : C guarantees that brace-init with fewer initializers than members
1909 : aggregate will initialize the rest of the aggregate as-if it were
1910 : static initialization. In turn static initialization guarantees
1911 : that padding is initialized to zero. So, we always initialize paddings
1912 : to zeroes regardless INIT_TYPE.
1913 : To do the padding initialization, we insert a call to
1914 : __builtin_clear_padding (&decl, 0, for_auto_init = true).
1915 : Note, we add an additional dummy argument for __builtin_clear_padding,
1916 : 'for_auto_init' to distinguish whether this call is for automatic
1917 : variable initialization or not.
1918 : */
1919 : static void
1920 115 : gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
1921 : gimple_seq *seq_p)
1922 : {
1923 115 : tree addr_of_decl = NULL_TREE;
1924 115 : tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
1925 :
1926 115 : if (is_vla)
1927 : {
1928 : /* The temporary address variable for this vla should be
1929 : created in gimplify_vla_decl. */
1930 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
1931 0 : gcc_assert (INDIRECT_REF_P (DECL_VALUE_EXPR (decl)));
1932 0 : addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
1933 : }
1934 : else
1935 : {
1936 115 : mark_addressable (decl);
1937 115 : addr_of_decl = build_fold_addr_expr (decl);
1938 : }
1939 :
1940 115 : gimple *call = gimple_build_call (fn, 2, addr_of_decl,
1941 115 : build_one_cst (TREE_TYPE (addr_of_decl)));
1942 115 : gimplify_seq_add_stmt (seq_p, call);
1943 115 : }
1944 :
1945 : /* Return true if the DECL need to be automatically initialized by the
1946 : compiler. */
1947 : static bool
1948 4200813 : var_needs_auto_init_p (tree decl)
1949 : {
1950 4200813 : if (auto_var_p (decl)
1951 4105808 : && (TREE_CODE (decl) != VAR_DECL || !DECL_HARD_REGISTER (decl))
1952 4105100 : && flag_auto_var_init > AUTO_INIT_UNINITIALIZED
1953 247727 : && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
1954 247719 : && !lookup_attribute ("indeterminate", DECL_ATTRIBUTES (decl))
1955 247710 : && !OPAQUE_TYPE_P (TREE_TYPE (decl))
1956 4448523 : && !is_empty_type (TREE_TYPE (decl)))
1957 : return true;
1958 : return false;
1959 : }
1960 :
1961 : /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
1962 : and initialization explicit. */
1963 :
1964 : static enum gimplify_status
1965 6523205 : gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
1966 : {
1967 6523205 : tree stmt = *stmt_p;
1968 6523205 : tree decl = DECL_EXPR_DECL (stmt);
1969 :
1970 6523205 : *stmt_p = NULL_TREE;
1971 :
1972 6523205 : if (TREE_TYPE (decl) == error_mark_node)
1973 : return GS_ERROR;
1974 :
1975 6523127 : if ((TREE_CODE (decl) == TYPE_DECL
1976 6479907 : || VAR_P (decl))
1977 12999958 : && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
1978 : {
1979 696590 : gimplify_type_sizes (TREE_TYPE (decl), seq_p);
1980 696590 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1981 21422 : gimplify_type_sizes (TREE_TYPE (TREE_TYPE (decl)), seq_p);
1982 : }
1983 :
1984 : /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
1985 : in case its size expressions contain problematic nodes like CALL_EXPR. */
1986 6523127 : if (TREE_CODE (decl) == TYPE_DECL
1987 43220 : && DECL_ORIGINAL_TYPE (decl)
1988 6528448 : && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
1989 : {
1990 0 : gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
1991 0 : if (TREE_CODE (DECL_ORIGINAL_TYPE (decl)) == REFERENCE_TYPE)
1992 0 : gimplify_type_sizes (TREE_TYPE (DECL_ORIGINAL_TYPE (decl)), seq_p);
1993 : }
1994 :
1995 6523127 : if (VAR_P (decl) && !DECL_EXTERNAL (decl))
1996 : {
1997 6476831 : tree init = DECL_INITIAL (decl);
1998 6476831 : bool is_vla = false;
1999 : /* Check whether a decl has FE created VALUE_EXPR here BEFORE
2000 : gimplify_vla_decl creates VALUE_EXPR for a vla decl.
2001 : If the decl has VALUE_EXPR that was created by FE (usually
2002 : C++FE), it's a proxy variable, and FE already initialized
2003 : the VALUE_EXPR of it, we should not initialize it anymore. */
2004 6476831 : bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
2005 :
2006 6476831 : poly_uint64 size;
2007 6476831 : if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
2008 6476831 : || (!TREE_STATIC (decl)
2009 6352454 : && flag_stack_check == GENERIC_STACK_CHECK
2010 234 : && maybe_gt (size,
2011 : (unsigned HOST_WIDE_INT) STACK_CHECK_MAX_VAR_SIZE)))
2012 : {
2013 8843 : gimplify_vla_decl (decl, seq_p);
2014 8843 : is_vla = true;
2015 : }
2016 :
2017 6476831 : if (asan_poisoned_variables
2018 5162 : && !is_vla
2019 4976 : && TREE_ADDRESSABLE (decl)
2020 2441 : && !TREE_STATIC (decl)
2021 2231 : && !DECL_HAS_VALUE_EXPR_P (decl)
2022 2154 : && DECL_ALIGN (decl) <= MAX_SUPPORTED_STACK_ALIGNMENT
2023 2154 : && dbg_cnt (asan_use_after_scope)
2024 2154 : && !gimplify_omp_ctxp
2025 : /* GNAT introduces temporaries to hold return values of calls in
2026 : initializers of variables defined in other units, so the
2027 : declaration of the variable is discarded completely. We do not
2028 : want to issue poison calls for such dropped variables. */
2029 6478977 : && (DECL_SEEN_IN_BIND_EXPR_P (decl)
2030 0 : || (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)))
2031 : {
2032 2146 : asan_poisoned_variables->add (decl);
2033 2146 : asan_poison_variable (decl, false, seq_p);
2034 2146 : if (!DECL_ARTIFICIAL (decl) && gimplify_ctxp->live_switch_vars)
2035 55 : gimplify_ctxp->live_switch_vars->add (decl);
2036 : }
2037 :
2038 : /* Some front ends do not explicitly declare all anonymous
2039 : artificial variables. We compensate here by declaring the
2040 : variables, though it would be better if the front ends would
2041 : explicitly declare them. */
2042 6476831 : if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
2043 6476831 : && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
2044 15960 : gimple_add_tmp_var (decl);
2045 :
2046 6476831 : if (init && init != error_mark_node)
2047 : {
2048 3688754 : if (!TREE_STATIC (decl))
2049 : {
2050 3659111 : DECL_INITIAL (decl) = NULL_TREE;
2051 3659111 : init = build2 (INIT_EXPR, void_type_node, decl, init);
2052 3659111 : gimplify_and_add (init, seq_p);
2053 3659111 : ggc_free (init);
2054 : /* Clear TREE_READONLY if we really have an initialization. */
2055 3659111 : if (!DECL_INITIAL (decl)
2056 3659111 : && !omp_privatize_by_reference (decl))
2057 3640962 : TREE_READONLY (decl) = 0;
2058 : }
2059 : else
2060 : /* We must still examine initializers for static variables
2061 : as they may contain a label address. */
2062 29643 : walk_tree (&init, force_labels_r, NULL, NULL);
2063 : }
2064 : /* When there is no explicit initializer, if the user requested,
2065 : We should insert an artificial initializer for this automatic
2066 : variable. */
2067 2788077 : else if (var_needs_auto_init_p (decl)
2068 2788077 : && !decl_had_value_expr_p)
2069 : {
2070 74948 : gimple_add_init_for_auto_var (decl,
2071 : flag_auto_var_init,
2072 : seq_p);
2073 : /* The expanding of a call to the above .DEFERRED_INIT will apply
2074 : block initialization to the whole space covered by this variable.
2075 : As a result, all the paddings will be initialized to zeroes
2076 : for zero initialization and 0xFE byte-repeatable patterns for
2077 : pattern initialization.
2078 : In order to make the paddings as zeroes for pattern init, We
2079 : should add a call to __builtin_clear_padding to clear the
2080 : paddings to zero in compatible with CLANG.
2081 : We cannot insert this call if the variable is a gimple register
2082 : since __builtin_clear_padding will take the address of the
2083 : variable. As a result, if a long double/_Complex long double
2084 : variable will spilled into stack later, its padding is 0XFE. */
2085 74948 : if (flag_auto_var_init == AUTO_INIT_PATTERN
2086 183 : && !is_gimple_reg (decl)
2087 75045 : && clear_padding_type_may_have_padding_p (TREE_TYPE (decl)))
2088 74 : gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
2089 : }
2090 : }
2091 :
2092 : return GS_ALL_DONE;
2093 : }
2094 :
2095 : /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
2096 : and replacing the LOOP_EXPR with goto, but if the loop contains an
2097 : EXIT_EXPR, we need to append a label for it to jump to. */
2098 :
2099 : static enum gimplify_status
2100 203308 : gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
2101 : {
2102 203308 : tree saved_label = gimplify_ctxp->exit_label;
2103 203308 : tree start_label = create_artificial_label (UNKNOWN_LOCATION);
2104 :
2105 203308 : gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
2106 :
2107 203308 : gimplify_ctxp->exit_label = NULL_TREE;
2108 :
2109 203308 : gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
2110 :
2111 203308 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
2112 :
2113 203308 : if (gimplify_ctxp->exit_label)
2114 6132 : gimplify_seq_add_stmt (pre_p,
2115 3066 : gimple_build_label (gimplify_ctxp->exit_label));
2116 :
2117 203308 : gimplify_ctxp->exit_label = saved_label;
2118 :
2119 203308 : *expr_p = NULL;
2120 203308 : return GS_ALL_DONE;
2121 : }
2122 :
2123 : /* Gimplify a statement list onto a sequence. These may be created either
2124 : by an enlightened front-end, or by shortcut_cond_expr. */
2125 :
2126 : static enum gimplify_status
2127 8453338 : gimplify_statement_list (tree *expr_p, gimple_seq *pre_p)
2128 : {
2129 8453338 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
2130 :
2131 8453338 : tree_stmt_iterator i = tsi_start (*expr_p);
2132 :
2133 54597535 : while (!tsi_end_p (i))
2134 : {
2135 37690859 : gimplify_stmt (tsi_stmt_ptr (i), pre_p);
2136 37690859 : tsi_delink (&i);
2137 : }
2138 :
2139 8453338 : if (temp)
2140 : {
2141 14759 : *expr_p = temp;
2142 14759 : return GS_OK;
2143 : }
2144 :
2145 : return GS_ALL_DONE;
2146 : }
2147 :
2148 :
2149 : /* Emit warning for the unreachable statement STMT if needed.
2150 : Return the gimple itself when the warning is emitted, otherwise
2151 : return NULL. */
2152 : static gimple *
2153 181 : emit_warn_switch_unreachable (gimple *stmt)
2154 : {
2155 181 : if (gimple_code (stmt) == GIMPLE_GOTO
2156 50 : && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL
2157 231 : && DECL_ARTIFICIAL (gimple_goto_dest (stmt)))
2158 : /* Don't warn for compiler-generated gotos. These occur
2159 : in Duff's devices, for example. */
2160 : return NULL;
2161 : else
2162 131 : warning_at (gimple_location (stmt), OPT_Wswitch_unreachable,
2163 : "statement will never be executed");
2164 131 : return stmt;
2165 : }
2166 :
2167 : /* Callback for walk_gimple_seq. */
2168 :
2169 : static tree
2170 48451 : warn_switch_unreachable_and_auto_init_r (gimple_stmt_iterator *gsi_p,
2171 : bool *handled_ops_p,
2172 : struct walk_stmt_info *wi)
2173 : {
2174 48451 : gimple *stmt = gsi_stmt (*gsi_p);
2175 48451 : bool unreachable_issued = wi->info != NULL;
2176 :
2177 48451 : *handled_ops_p = true;
2178 48451 : switch (gimple_code (stmt))
2179 : {
2180 155 : case GIMPLE_TRY:
2181 : /* A compiler-generated cleanup or a user-written try block.
2182 : If it's empty, don't dive into it--that would result in
2183 : worse location info. */
2184 155 : if (gimple_try_eval (stmt) == NULL)
2185 : {
2186 3 : if (warn_switch_unreachable && !unreachable_issued)
2187 3 : wi->info = emit_warn_switch_unreachable (stmt);
2188 :
2189 : /* Stop when auto var init warning is not on. */
2190 3 : if (!warn_trivial_auto_var_init)
2191 3 : return integer_zero_node;
2192 : }
2193 : /* Fall through. */
2194 1796 : case GIMPLE_BIND:
2195 1796 : case GIMPLE_CATCH:
2196 1796 : case GIMPLE_EH_FILTER:
2197 1796 : case GIMPLE_TRANSACTION:
2198 : /* Walk the sub-statements. */
2199 1796 : *handled_ops_p = false;
2200 1796 : break;
2201 :
2202 : case GIMPLE_DEBUG:
2203 : /* Ignore these. We may generate them before declarations that
2204 : are never executed. If there's something to warn about,
2205 : there will be non-debug stmts too, and we'll catch those. */
2206 : break;
2207 :
2208 60 : case GIMPLE_ASSIGN:
2209 : /* See comment below in the GIMPLE_CALL case. */
2210 60 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2211 20 : && gimple_assign_single_p (stmt)
2212 79 : && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
2213 : {
2214 6 : gimple *g = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
2215 6 : if (gimple_call_internal_p (g, IFN_DEFERRED_INIT))
2216 : break;
2217 : }
2218 54 : goto do_default;
2219 :
2220 45450 : case GIMPLE_LABEL:
2221 : /* Stop till the first Label. */
2222 45450 : return integer_zero_node;
2223 62 : case GIMPLE_CALL:
2224 62 : if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2225 : {
2226 8 : *handled_ops_p = false;
2227 8 : break;
2228 : }
2229 : /* Don't warn for compiler-generated initializations for
2230 : -ftrivial-auto-var-init for -Wswitch-unreachable. Though
2231 : do warn for -Wtrivial-auto-var-init.
2232 : There are 3 cases:
2233 : case 1: a call to .DEFERRED_INIT;
2234 : case 2: a call to __builtin_clear_padding with the 2nd argument is
2235 : present and non-zero;
2236 : case 3: a gimple assign store right after the call to .DEFERRED_INIT
2237 : that has the LHS of .DEFERRED_INIT as the RHS as following:
2238 : _1 = .DEFERRED_INIT (4, 2, &"i1"[0]);
2239 : i1 = _1.
2240 : case 3 is handled above in the GIMPLE_ASSIGN case. */
2241 54 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2242 54 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2243 : {
2244 33 : if (warn_trivial_auto_var_init)
2245 : {
2246 : /* Get the variable name from the 3rd argument of call. */
2247 12 : tree var_name = gimple_call_arg (stmt, 2);
2248 12 : var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0);
2249 12 : const char *var_name_str = TREE_STRING_POINTER (var_name);
2250 :
2251 12 : warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init,
2252 : "%qs cannot be initialized with "
2253 : "%<-ftrivial-auto-var_init%>", var_name_str);
2254 : }
2255 : break;
2256 : }
2257 21 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2258 7 : && gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
2259 24 : && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
2260 : break;
2261 : /* Fall through. */
2262 178 : default:
2263 178 : do_default:
2264 : /* check the first "real" statement (not a decl/lexical scope/...), issue
2265 : warning if needed. */
2266 178 : if (warn_switch_unreachable && !unreachable_issued)
2267 178 : wi->info = emit_warn_switch_unreachable (stmt);
2268 : /* Stop when auto var init warning is not on. */
2269 178 : if (!warn_trivial_auto_var_init)
2270 178 : return integer_zero_node;
2271 : break;
2272 : }
2273 : return NULL_TREE;
2274 : }
2275 :
2276 :
2277 : /* Possibly warn about unreachable statements between switch's controlling
2278 : expression and the first case. Also warn about -ftrivial-auto-var-init
2279 : cannot initialize the auto variable under such situation.
2280 : SEQ is the body of a switch expression. */
2281 :
2282 : static void
2283 49515 : maybe_warn_switch_unreachable_and_auto_init (gimple_seq seq)
2284 : {
2285 60 : if ((!warn_switch_unreachable && !warn_trivial_auto_var_init)
2286 : /* This warning doesn't play well with Fortran when optimizations
2287 : are on. */
2288 49455 : || lang_GNU_Fortran ()
2289 95320 : || seq == NULL)
2290 3881 : return;
2291 :
2292 45634 : struct walk_stmt_info wi;
2293 :
2294 45634 : memset (&wi, 0, sizeof (wi));
2295 45634 : walk_gimple_seq (seq, warn_switch_unreachable_and_auto_init_r, NULL, &wi);
2296 : }
2297 :
2298 :
2299 : /* A label entry that pairs label and a location. */
2300 : struct label_entry
2301 : {
2302 : tree label;
2303 : location_t loc;
2304 : };
2305 :
2306 : /* Find LABEL in vector of label entries VEC. */
2307 :
2308 : static struct label_entry *
2309 12198 : find_label_entry (const auto_vec<struct label_entry> *vec, tree label)
2310 : {
2311 12198 : unsigned int i;
2312 12198 : struct label_entry *l;
2313 :
2314 23346 : FOR_EACH_VEC_ELT (*vec, i, l)
2315 19988 : if (l->label == label)
2316 : return l;
2317 : return NULL;
2318 : }
2319 :
2320 : /* Return true if LABEL, a LABEL_DECL, represents a case label
2321 : in a vector of labels CASES. */
2322 :
2323 : static bool
2324 16405 : case_label_p (const vec<tree> *cases, tree label)
2325 : {
2326 16405 : unsigned int i;
2327 16405 : tree l;
2328 :
2329 164574 : FOR_EACH_VEC_ELT (*cases, i, l)
2330 164240 : if (CASE_LABEL (l) == label)
2331 : return true;
2332 : return false;
2333 : }
2334 :
2335 : /* Find the last nondebug statement in a scope STMT. */
2336 :
2337 : static gimple *
2338 2265 : last_stmt_in_scope (gimple *stmt)
2339 : {
2340 4200 : if (!stmt)
2341 : return NULL;
2342 :
2343 6838 : auto last_stmt_in_seq = [] (gimple_seq s)
2344 : {
2345 2649 : gimple_seq_node n;
2346 2649 : for (n = gimple_seq_last (s);
2347 2654 : n && (is_gimple_debug (n)
2348 2641 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2349 110 : && gimple_call_internal_p (n, IFN_DEFERRED_INIT)));
2350 5 : n = n->prev)
2351 7 : if (n == s)
2352 : return (gimple *) NULL;
2353 : return (gimple *) n;
2354 : };
2355 :
2356 4189 : switch (gimple_code (stmt))
2357 : {
2358 1387 : case GIMPLE_BIND:
2359 1387 : {
2360 1387 : gbind *bind = as_a <gbind *> (stmt);
2361 1387 : stmt = last_stmt_in_seq (gimple_bind_body (bind));
2362 1387 : return last_stmt_in_scope (stmt);
2363 : }
2364 :
2365 714 : case GIMPLE_TRY:
2366 714 : {
2367 714 : gtry *try_stmt = as_a <gtry *> (stmt);
2368 714 : stmt = last_stmt_in_seq (gimple_try_eval (try_stmt));
2369 714 : gimple *last_eval = last_stmt_in_scope (stmt);
2370 714 : if (gimple_stmt_may_fallthru (last_eval)
2371 567 : && (last_eval == NULL
2372 564 : || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH))
2373 1274 : && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
2374 : {
2375 548 : stmt = last_stmt_in_seq (gimple_try_cleanup (try_stmt));
2376 548 : return last_stmt_in_scope (stmt);
2377 : }
2378 : else
2379 : return last_eval;
2380 : }
2381 :
2382 0 : case GIMPLE_DEBUG:
2383 0 : gcc_unreachable ();
2384 :
2385 : default:
2386 : return stmt;
2387 : }
2388 : }
2389 :
2390 : /* Collect labels that may fall through into LABELS and return the statement
2391 : preceding another case label, or a user-defined label. Store a location
2392 : useful to give warnings at *PREVLOC (usually the location of the returned
2393 : statement or of its surrounding scope). */
2394 :
2395 : static gimple *
2396 20996 : collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
2397 : auto_vec <struct label_entry> *labels,
2398 : location_t *prevloc)
2399 : {
2400 20996 : gimple *prev = NULL;
2401 :
2402 20996 : *prevloc = UNKNOWN_LOCATION;
2403 101593 : do
2404 : {
2405 101593 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND)
2406 : {
2407 : /* Recognize the special GIMPLE_BIND added by gimplify_switch_expr,
2408 : which starts on a GIMPLE_SWITCH and ends with a break label.
2409 : Handle that as a single statement that can fall through. */
2410 1448 : gbind *bind = as_a <gbind *> (gsi_stmt (*gsi_p));
2411 1448 : gimple *first = gimple_seq_first_stmt (gimple_bind_body (bind));
2412 1448 : gimple *last = gimple_seq_last_stmt (gimple_bind_body (bind));
2413 1442 : if (last
2414 1442 : && gimple_code (first) == GIMPLE_SWITCH
2415 1544 : && gimple_code (last) == GIMPLE_LABEL)
2416 : {
2417 102 : tree label = gimple_label_label (as_a <glabel *> (last));
2418 102 : if (SWITCH_BREAK_LABEL_P (label))
2419 : {
2420 102 : prev = bind;
2421 102 : gsi_next (gsi_p);
2422 102 : continue;
2423 : }
2424 : }
2425 : }
2426 101491 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
2427 101491 : || gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
2428 : {
2429 : /* Nested scope. Only look at the last statement of
2430 : the innermost scope. */
2431 1551 : location_t bind_loc = gimple_location (gsi_stmt (*gsi_p));
2432 1551 : gimple *last = last_stmt_in_scope (gsi_stmt (*gsi_p));
2433 1551 : if (last)
2434 : {
2435 1543 : prev = last;
2436 : /* It might be a label without a location. Use the
2437 : location of the scope then. */
2438 1543 : if (!gimple_has_location (prev))
2439 671 : *prevloc = bind_loc;
2440 : }
2441 1551 : gsi_next (gsi_p);
2442 1551 : continue;
2443 1551 : }
2444 :
2445 : /* Ifs are tricky. */
2446 99940 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
2447 : {
2448 7176 : gcond *cond_stmt = as_a <gcond *> (gsi_stmt (*gsi_p));
2449 7176 : tree false_lab = gimple_cond_false_label (cond_stmt);
2450 7176 : location_t if_loc = gimple_location (cond_stmt);
2451 :
2452 : /* If we have e.g.
2453 : if (i > 1) goto <D.2259>; else goto D;
2454 : we can't do much with the else-branch. */
2455 7176 : if (!DECL_ARTIFICIAL (false_lab))
2456 : break;
2457 :
2458 : /* Go on until the false label, then one step back. */
2459 54654 : for (; !gsi_end_p (*gsi_p); gsi_next (gsi_p))
2460 : {
2461 54654 : gimple *stmt = gsi_stmt (*gsi_p);
2462 54654 : if (gimple_code (stmt) == GIMPLE_LABEL
2463 54654 : && gimple_label_label (as_a <glabel *> (stmt)) == false_lab)
2464 : break;
2465 : }
2466 :
2467 : /* Not found? Oops. */
2468 7176 : if (gsi_end_p (*gsi_p))
2469 : break;
2470 :
2471 : /* A dead label can't fall through. */
2472 7176 : if (!UNUSED_LABEL_P (false_lab))
2473 : {
2474 7129 : struct label_entry l = { false_lab, if_loc };
2475 7129 : labels->safe_push (l);
2476 : }
2477 :
2478 : /* Go to the last statement of the then branch. */
2479 7176 : gsi_prev (gsi_p);
2480 :
2481 : /* if (i != 0) goto <D.1759>; else goto <D.1760>;
2482 : <D.1759>:
2483 : <stmt>;
2484 : goto <D.1761>;
2485 : <D.1760>:
2486 : */
2487 7176 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2488 7176 : && !gimple_has_location (gsi_stmt (*gsi_p)))
2489 : {
2490 : /* Look at the statement before, it might be
2491 : attribute fallthrough, in which case don't warn. */
2492 1570 : gsi_prev (gsi_p);
2493 1570 : bool fallthru_before_dest
2494 1570 : = gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
2495 1570 : gsi_next (gsi_p);
2496 1570 : tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
2497 1570 : if (!fallthru_before_dest)
2498 : {
2499 1513 : struct label_entry l = { goto_dest, if_loc };
2500 1513 : labels->safe_push (l);
2501 : }
2502 : }
2503 : /* This case is about
2504 : if (1 != 0) goto <D.2022>; else goto <D.2023>;
2505 : <D.2022>:
2506 : n = n + 1; // #1
2507 : <D.2023>: // #2
2508 : <D.1988>: // #3
2509 : where #2 is UNUSED_LABEL_P and we want to warn about #1 falling
2510 : through to #3. So set PREV to #1. */
2511 5606 : else if (UNUSED_LABEL_P (false_lab))
2512 47 : prev = gsi_stmt (*gsi_p);
2513 :
2514 : /* And move back. */
2515 7176 : gsi_next (gsi_p);
2516 : }
2517 :
2518 99940 : tree lab;
2519 : /* Remember the last statement. Skip labels that are of no interest
2520 : to us. */
2521 99940 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2522 : {
2523 11980 : tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (*gsi_p)));
2524 11980 : if (find_label_entry (labels, label))
2525 75114 : prev = gsi_stmt (*gsi_p);
2526 : }
2527 87960 : else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
2528 : ;
2529 87960 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2530 87960 : && gimple_call_internal_p (gsi_stmt (*gsi_p),
2531 : IFN_DEFERRED_INIT))
2532 : ;
2533 87960 : else if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_PREDICT)
2534 : ;
2535 86736 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2536 2136 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2537 316 : && (lab = gimple_goto_dest (gsi_stmt (*gsi_p)))
2538 316 : && TREE_CODE (lab) == LABEL_DECL
2539 87051 : && VACUOUS_INIT_LABEL_P (lab))
2540 : ;
2541 86736 : else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
2542 75114 : prev = gsi_stmt (*gsi_p);
2543 99940 : gsi_next (gsi_p);
2544 : }
2545 101593 : while (!gsi_end_p (*gsi_p)
2546 : /* Stop if we find a case or a user-defined label. */
2547 203186 : && (gimple_code (gsi_stmt (*gsi_p)) != GIMPLE_LABEL
2548 21729 : || !gimple_has_location (gsi_stmt (*gsi_p))));
2549 :
2550 20996 : if (prev && gimple_has_location (prev))
2551 20551 : *prevloc = gimple_location (prev);
2552 20996 : return prev;
2553 : }
2554 :
2555 : /* Return true if the switch fallthrough warning should occur. LABEL is
2556 : the label statement that we're falling through to. */
2557 :
2558 : static bool
2559 16918 : should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
2560 : {
2561 16918 : gimple_stmt_iterator gsi = *gsi_p;
2562 :
2563 : /* Don't warn if the label is marked with a "falls through" comment. */
2564 16918 : if (FALLTHROUGH_LABEL_P (label))
2565 : return false;
2566 :
2567 : /* Don't warn for non-case labels followed by a statement:
2568 : case 0:
2569 : foo ();
2570 : label:
2571 : bar ();
2572 : as these are likely intentional. */
2573 16146 : if (!case_label_p (&gimplify_ctxp->case_labels, label))
2574 : {
2575 : tree l;
2576 334 : while (!gsi_end_p (gsi)
2577 334 : && ((gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2578 259 : && (l
2579 259 : = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi))))
2580 259 : && !case_label_p (&gimplify_ctxp->case_labels, l))
2581 153 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2582 31 : && gimple_call_internal_p (gsi_stmt (gsi),
2583 : IFN_DEFERRED_INIT))))
2584 173 : gsi_next_nondebug (&gsi);
2585 161 : if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
2586 : return false;
2587 : }
2588 :
2589 : /* Don't warn for terminated branches, i.e. when the subsequent case labels
2590 : immediately breaks. */
2591 16071 : gsi = *gsi_p;
2592 :
2593 : /* Skip all immediately following labels. */
2594 35694 : while (!gsi_end_p (gsi)
2595 35694 : && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2596 16214 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT
2597 16005 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2598 734 : && gimple_call_internal_p (gsi_stmt (gsi),
2599 : IFN_DEFERRED_INIT))))
2600 19623 : gsi_next_nondebug (&gsi);
2601 :
2602 : /* { ... something; default:; } */
2603 16071 : if (gsi_end_p (gsi)
2604 : /* { ... something; default: break; } or
2605 : { ... something; default: goto L; } */
2606 16005 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
2607 : /* { ... something; default: return; } */
2608 30977 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
2609 : return false;
2610 :
2611 : return true;
2612 : }
2613 :
2614 : /* Callback for walk_gimple_seq. */
2615 :
2616 : static tree
2617 21956 : warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2618 : struct walk_stmt_info *)
2619 : {
2620 21956 : gimple *stmt = gsi_stmt (*gsi_p);
2621 :
2622 21956 : *handled_ops_p = true;
2623 21956 : switch (gimple_code (stmt))
2624 : {
2625 267 : case GIMPLE_TRY:
2626 267 : case GIMPLE_BIND:
2627 267 : case GIMPLE_CATCH:
2628 267 : case GIMPLE_EH_FILTER:
2629 267 : case GIMPLE_TRANSACTION:
2630 : /* Walk the sub-statements. */
2631 267 : *handled_ops_p = false;
2632 267 : break;
2633 :
2634 : /* Find a sequence of form:
2635 :
2636 : GIMPLE_LABEL
2637 : [...]
2638 : <may fallthru stmt>
2639 : GIMPLE_LABEL
2640 :
2641 : and possibly warn. */
2642 : case GIMPLE_LABEL:
2643 : {
2644 : /* Found a label. Skip all immediately following labels. */
2645 49227 : while (!gsi_end_p (*gsi_p)
2646 49227 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2647 27997 : gsi_next_nondebug (gsi_p);
2648 :
2649 : /* There might be no more statements. */
2650 21230 : if (gsi_end_p (*gsi_p))
2651 4305 : return integer_zero_node;
2652 :
2653 : /* Vector of labels that fall through. */
2654 20996 : auto_vec <struct label_entry> labels;
2655 20996 : location_t prevloc;
2656 20996 : gimple *prev = collect_fallthrough_labels (gsi_p, &labels, &prevloc);
2657 :
2658 : /* There might be no more statements. */
2659 20996 : if (gsi_end_p (*gsi_p))
2660 4071 : return integer_zero_node;
2661 :
2662 16925 : gimple *next = gsi_stmt (*gsi_p);
2663 16925 : tree label;
2664 : /* If what follows is a label, then we may have a fallthrough. */
2665 16925 : if (gimple_code (next) == GIMPLE_LABEL
2666 16925 : && gimple_has_location (next)
2667 16925 : && (label = gimple_label_label (as_a <glabel *> (next)))
2668 33850 : && prev != NULL)
2669 : {
2670 16918 : struct label_entry *l;
2671 16918 : bool warned_p = false;
2672 16918 : auto_diagnostic_group d;
2673 16918 : if (!should_warn_for_implicit_fallthrough (gsi_p, label))
2674 : /* Quiet. */;
2675 14879 : else if (gimple_code (prev) == GIMPLE_LABEL
2676 218 : && (label = gimple_label_label (as_a <glabel *> (prev)))
2677 15097 : && (l = find_label_entry (&labels, label)))
2678 198 : warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough_,
2679 : "this statement may fall through");
2680 14681 : else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH)
2681 : /* Try to be clever and don't warn when the statement
2682 : can't actually fall through. */
2683 14145 : && gimple_stmt_may_fallthru (prev)
2684 14982 : && prevloc != UNKNOWN_LOCATION)
2685 301 : warned_p = warning_at (prevloc,
2686 301 : OPT_Wimplicit_fallthrough_,
2687 : "this statement may fall through");
2688 499 : if (warned_p)
2689 499 : inform (gimple_location (next), "here");
2690 :
2691 : /* Mark this label as processed so as to prevent multiple
2692 : warnings in nested switches. */
2693 16918 : FALLTHROUGH_LABEL_P (label) = true;
2694 :
2695 : /* So that next warn_implicit_fallthrough_r will start looking for
2696 : a new sequence starting with this label. */
2697 16918 : gsi_prev (gsi_p);
2698 16918 : }
2699 4071 : }
2700 16925 : break;
2701 : default:
2702 : break;
2703 : }
2704 : return NULL_TREE;
2705 : }
2706 :
2707 : /* Warn when a switch case falls through. */
2708 :
2709 : static void
2710 49515 : maybe_warn_implicit_fallthrough (gimple_seq seq)
2711 : {
2712 49515 : if (!warn_implicit_fallthrough)
2713 45351 : return;
2714 :
2715 : /* This warning is meant for C/C++/ObjC/ObjC++ only. */
2716 4164 : if (!(lang_GNU_C ()
2717 1228 : || lang_GNU_CXX ()
2718 0 : || lang_GNU_OBJC ()))
2719 : return;
2720 :
2721 4164 : struct walk_stmt_info wi;
2722 4164 : memset (&wi, 0, sizeof (wi));
2723 4164 : walk_gimple_seq (seq, warn_implicit_fallthrough_r, NULL, &wi);
2724 : }
2725 :
2726 : /* Callback for walk_gimple_seq. */
2727 :
2728 : static tree
2729 3210636 : expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2730 : struct walk_stmt_info *wi)
2731 : {
2732 3210636 : gimple *stmt = gsi_stmt (*gsi_p);
2733 :
2734 3210636 : *handled_ops_p = true;
2735 3210636 : switch (gimple_code (stmt))
2736 : {
2737 146890 : case GIMPLE_TRY:
2738 146890 : case GIMPLE_BIND:
2739 146890 : case GIMPLE_CATCH:
2740 146890 : case GIMPLE_EH_FILTER:
2741 146890 : case GIMPLE_TRANSACTION:
2742 : /* Walk the sub-statements. */
2743 146890 : *handled_ops_p = false;
2744 146890 : break;
2745 246718 : case GIMPLE_CALL:
2746 246718 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2747 246718 : if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
2748 : {
2749 2563 : location_t loc = gimple_location (stmt);
2750 2563 : gsi_remove (gsi_p, true);
2751 2563 : wi->removed_stmt = true;
2752 :
2753 : /* nothrow flag is added by genericize_c_loop to mark fallthrough
2754 : statement at the end of some loop's body. Those should be
2755 : always diagnosed, either because they indeed don't precede
2756 : a case label or default label, or because the next statement
2757 : is not within the same iteration statement. */
2758 2563 : if ((stmt->subcode & GF_CALL_NOTHROW) != 0)
2759 : {
2760 12 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2761 : "a case label or default label");
2762 12 : break;
2763 : }
2764 :
2765 2551 : if (gsi_end_p (*gsi_p))
2766 : {
2767 32 : static_cast<location_t *>(wi->info)[0] = BUILTINS_LOCATION;
2768 32 : static_cast<location_t *>(wi->info)[1] = loc;
2769 32 : break;
2770 : }
2771 :
2772 2519 : bool found = false;
2773 :
2774 2519 : gimple_stmt_iterator gsi2 = *gsi_p;
2775 2519 : stmt = gsi_stmt (gsi2);
2776 2519 : tree lab;
2777 2519 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2778 934 : && gimple_code (stmt) == GIMPLE_GOTO
2779 20 : && (lab = gimple_goto_dest (stmt))
2780 20 : && TREE_CODE (lab) == LABEL_DECL
2781 2539 : && VACUOUS_INIT_LABEL_P (lab))
2782 : {
2783 : /* Handle for C++ artificial -ftrivial-auto-var-init=
2784 : sequences. Those look like:
2785 : goto lab1;
2786 : lab2:;
2787 : v1 = .DEFERRED_INIT (...);
2788 : v2 = .DEFERRED_INIT (...);
2789 : lab3:;
2790 : v3 = .DEFERRED_INIT (...);
2791 : lab1:;
2792 : In this case, a case/default label can be either in between
2793 : the GIMPLE_GOTO and the corresponding GIMPLE_LABEL, if jumps
2794 : from the switch condition to the case/default label cross
2795 : vacuous initialization of some variables, or after the
2796 : corresponding GIMPLE_LABEL, if those jumps don't cross
2797 : any such initialization but there is an adjacent named label
2798 : which crosses such initialization. So, for the purpose of
2799 : this function, just ignore the goto but until reaching the
2800 : corresponding GIMPLE_LABEL allow also .DEFERRED_INIT
2801 : calls. */
2802 5 : gsi_next (&gsi2);
2803 : }
2804 2514 : else if (gimple_code (stmt) == GIMPLE_GOTO
2805 2514 : && !gimple_has_location (stmt))
2806 : {
2807 : /* Go on until the artificial label. */
2808 57 : tree goto_dest = gimple_goto_dest (stmt);
2809 414 : for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
2810 : {
2811 357 : if (gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL
2812 357 : && gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)))
2813 : == goto_dest)
2814 : break;
2815 : }
2816 :
2817 : /* Not found? Stop. */
2818 57 : if (gsi_end_p (gsi2))
2819 : break;
2820 :
2821 : /* Look one past it. */
2822 57 : gsi_next (&gsi2);
2823 : }
2824 :
2825 : /* We're looking for a case label or default label here. */
2826 2617 : while (!gsi_end_p (gsi2))
2827 : {
2828 2617 : stmt = gsi_stmt (gsi2);
2829 2617 : if (gimple_code (stmt) == GIMPLE_LABEL)
2830 : {
2831 2574 : tree label = gimple_label_label (as_a <glabel *> (stmt));
2832 2574 : if (gimple_has_location (stmt) && DECL_ARTIFICIAL (label))
2833 : {
2834 : found = true;
2835 : break;
2836 : }
2837 : }
2838 43 : else if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2839 : ;
2840 43 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2841 43 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2842 : ;
2843 43 : else if (!is_gimple_debug (stmt))
2844 : /* Anything else is not expected. */
2845 : break;
2846 98 : gsi_next (&gsi2);
2847 : }
2848 2519 : if (!found)
2849 23 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2850 : "a case label or default label");
2851 : }
2852 : break;
2853 2817028 : default:
2854 2817028 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2855 2817028 : break;
2856 : }
2857 3210636 : return NULL_TREE;
2858 : }
2859 :
2860 : /* Expand all FALLTHROUGH () calls in SEQ. */
2861 :
2862 : static void
2863 47829 : expand_FALLTHROUGH (gimple_seq *seq_p)
2864 : {
2865 47829 : auto_urlify_attributes sentinel;
2866 :
2867 47829 : struct walk_stmt_info wi;
2868 47829 : location_t loc[2];
2869 47829 : memset (&wi, 0, sizeof (wi));
2870 47829 : loc[0] = UNKNOWN_LOCATION;
2871 47829 : loc[1] = UNKNOWN_LOCATION;
2872 47829 : wi.info = (void *) &loc[0];
2873 47829 : walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
2874 47829 : if (loc[0] != UNKNOWN_LOCATION)
2875 : /* We've found [[fallthrough]]; at the end of a switch, which the C++
2876 : standard says is ill-formed; see [dcl.attr.fallthrough]. */
2877 8 : pedwarn (loc[1], 0, "attribute %<fallthrough%> not preceding "
2878 : "a case label or default label");
2879 47829 : }
2880 :
2881 :
2882 : /* Gimplify a SWITCH_EXPR, and collect the vector of labels it can
2883 : branch to. */
2884 :
2885 : static enum gimplify_status
2886 49515 : gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
2887 : {
2888 49515 : tree switch_expr = *expr_p;
2889 49515 : gimple_seq switch_body_seq = NULL;
2890 49515 : enum gimplify_status ret;
2891 49515 : tree index_type = TREE_TYPE (switch_expr);
2892 49515 : if (index_type == NULL_TREE)
2893 11396 : index_type = TREE_TYPE (SWITCH_COND (switch_expr));
2894 :
2895 49515 : ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
2896 : fb_rvalue);
2897 49515 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
2898 : return ret;
2899 :
2900 49515 : if (SWITCH_BODY (switch_expr))
2901 : {
2902 49515 : vec<tree> labels;
2903 49515 : vec<tree> saved_labels;
2904 49515 : hash_set<tree> *saved_live_switch_vars = NULL;
2905 49515 : tree default_case = NULL_TREE;
2906 49515 : gswitch *switch_stmt;
2907 :
2908 : /* Save old labels, get new ones from body, then restore the old
2909 : labels. Save all the things from the switch body to append after. */
2910 49515 : saved_labels = gimplify_ctxp->case_labels;
2911 49515 : gimplify_ctxp->case_labels.create (8);
2912 :
2913 : /* Do not create live_switch_vars if SWITCH_BODY is not a BIND_EXPR. */
2914 49515 : saved_live_switch_vars = gimplify_ctxp->live_switch_vars;
2915 49515 : tree_code body_type = TREE_CODE (SWITCH_BODY (switch_expr));
2916 49515 : if (body_type == BIND_EXPR || body_type == STATEMENT_LIST)
2917 49231 : gimplify_ctxp->live_switch_vars = new hash_set<tree> (4);
2918 : else
2919 284 : gimplify_ctxp->live_switch_vars = NULL;
2920 :
2921 49515 : bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
2922 49515 : gimplify_ctxp->in_switch_expr = true;
2923 :
2924 49515 : gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
2925 :
2926 49515 : gimplify_ctxp->in_switch_expr = old_in_switch_expr;
2927 49515 : maybe_warn_switch_unreachable_and_auto_init (switch_body_seq);
2928 49515 : maybe_warn_implicit_fallthrough (switch_body_seq);
2929 : /* Only do this for the outermost GIMPLE_SWITCH. */
2930 49515 : if (!gimplify_ctxp->in_switch_expr)
2931 47829 : expand_FALLTHROUGH (&switch_body_seq);
2932 :
2933 49515 : labels = gimplify_ctxp->case_labels;
2934 49515 : gimplify_ctxp->case_labels = saved_labels;
2935 :
2936 49515 : if (gimplify_ctxp->live_switch_vars)
2937 : {
2938 49231 : gcc_assert (gimplify_ctxp->live_switch_vars->is_empty ());
2939 49231 : delete gimplify_ctxp->live_switch_vars;
2940 : }
2941 49515 : gimplify_ctxp->live_switch_vars = saved_live_switch_vars;
2942 :
2943 49515 : preprocess_case_label_vec_for_gimple (labels, index_type,
2944 : &default_case);
2945 :
2946 49515 : bool add_bind = false;
2947 49515 : if (!default_case)
2948 : {
2949 14790 : glabel *new_default;
2950 :
2951 14790 : default_case
2952 14790 : = build_case_label (NULL_TREE, NULL_TREE,
2953 : create_artificial_label (UNKNOWN_LOCATION));
2954 14790 : if (old_in_switch_expr)
2955 : {
2956 1083 : SWITCH_BREAK_LABEL_P (CASE_LABEL (default_case)) = 1;
2957 1083 : add_bind = true;
2958 : }
2959 14790 : new_default = gimple_build_label (CASE_LABEL (default_case));
2960 14790 : gimplify_seq_add_stmt (&switch_body_seq, new_default);
2961 : }
2962 34725 : else if (old_in_switch_expr)
2963 : {
2964 603 : gimple *last = gimple_seq_last_stmt (switch_body_seq);
2965 603 : if (last && gimple_code (last) == GIMPLE_LABEL)
2966 : {
2967 338 : tree label = gimple_label_label (as_a <glabel *> (last));
2968 338 : if (SWITCH_BREAK_LABEL_P (label))
2969 49515 : add_bind = true;
2970 : }
2971 : }
2972 :
2973 49515 : switch_stmt = gimple_build_switch (SWITCH_COND (switch_expr),
2974 : default_case, labels);
2975 49515 : gimple_set_location (switch_stmt, EXPR_LOCATION (switch_expr));
2976 : /* For the benefit of -Wimplicit-fallthrough, if switch_body_seq
2977 : ends with a GIMPLE_LABEL holding SWITCH_BREAK_LABEL_P LABEL_DECL,
2978 : wrap the GIMPLE_SWITCH up to that GIMPLE_LABEL into a GIMPLE_BIND,
2979 : so that we can easily find the start and end of the switch
2980 : statement. */
2981 49515 : if (add_bind)
2982 : {
2983 1420 : gimple_seq bind_body = NULL;
2984 1420 : gimplify_seq_add_stmt (&bind_body, switch_stmt);
2985 1420 : gimple_seq_add_seq (&bind_body, switch_body_seq);
2986 1420 : gbind *bind = gimple_build_bind (NULL_TREE, bind_body, NULL_TREE);
2987 1420 : gimple_set_location (bind, EXPR_LOCATION (switch_expr));
2988 1420 : gimplify_seq_add_stmt (pre_p, bind);
2989 : }
2990 : else
2991 : {
2992 48095 : gimplify_seq_add_stmt (pre_p, switch_stmt);
2993 48095 : gimplify_seq_add_seq (pre_p, switch_body_seq);
2994 : }
2995 49515 : labels.release ();
2996 : }
2997 : else
2998 0 : gcc_unreachable ();
2999 :
3000 49515 : return GS_ALL_DONE;
3001 : }
3002 :
3003 : /* Gimplify the LABEL_EXPR pointed to by EXPR_P. */
3004 :
3005 : static enum gimplify_status
3006 2544320 : gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
3007 : {
3008 2544320 : gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
3009 : == current_function_decl);
3010 :
3011 2544320 : tree label = LABEL_EXPR_LABEL (*expr_p);
3012 2544320 : glabel *label_stmt = gimple_build_label (label);
3013 2544320 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3014 2544320 : gimplify_seq_add_stmt (pre_p, label_stmt);
3015 :
3016 2544320 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3017 21 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3018 : NOT_TAKEN));
3019 2544299 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3020 11 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3021 : TAKEN));
3022 :
3023 2544320 : return GS_ALL_DONE;
3024 : }
3025 :
3026 : /* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
3027 :
3028 : static enum gimplify_status
3029 1034044 : gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
3030 : {
3031 1034044 : struct gimplify_ctx *ctxp;
3032 1034044 : glabel *label_stmt;
3033 :
3034 : /* Invalid programs can play Duff's Device type games with, for example,
3035 : #pragma omp parallel. At least in the C front end, we don't
3036 : detect such invalid branches until after gimplification, in the
3037 : diagnose_omp_blocks pass. */
3038 1034054 : for (ctxp = gimplify_ctxp; ; ctxp = ctxp->prev_context)
3039 1034054 : if (ctxp->case_labels.exists ())
3040 : break;
3041 :
3042 1034044 : tree label = CASE_LABEL (*expr_p);
3043 1034044 : label_stmt = gimple_build_label (label);
3044 1034044 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3045 1034044 : ctxp->case_labels.safe_push (*expr_p);
3046 1034044 : gimplify_seq_add_stmt (pre_p, label_stmt);
3047 :
3048 1034044 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3049 16 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3050 : NOT_TAKEN));
3051 1034028 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3052 20 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3053 : TAKEN));
3054 :
3055 1034044 : return GS_ALL_DONE;
3056 : }
3057 :
3058 : /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first
3059 : if necessary. */
3060 :
3061 : tree
3062 1769987 : build_and_jump (tree *label_p)
3063 : {
3064 1769987 : if (label_p == NULL)
3065 : /* If there's nowhere to jump, just fall through. */
3066 : return NULL_TREE;
3067 :
3068 1200559 : if (*label_p == NULL_TREE)
3069 : {
3070 686740 : tree label = create_artificial_label (UNKNOWN_LOCATION);
3071 686740 : *label_p = label;
3072 : }
3073 :
3074 1200559 : return build1 (GOTO_EXPR, void_type_node, *label_p);
3075 : }
3076 :
3077 : /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
3078 : This also involves building a label to jump to and communicating it to
3079 : gimplify_loop_expr through gimplify_ctxp->exit_label. */
3080 :
3081 : static enum gimplify_status
3082 3069 : gimplify_exit_expr (tree *expr_p)
3083 : {
3084 3069 : tree cond = TREE_OPERAND (*expr_p, 0);
3085 3069 : tree expr;
3086 :
3087 3069 : expr = build_and_jump (&gimplify_ctxp->exit_label);
3088 3069 : expr = build3 (COND_EXPR, void_type_node, cond, expr, NULL_TREE);
3089 3069 : *expr_p = expr;
3090 :
3091 3069 : return GS_OK;
3092 : }
3093 :
3094 : /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is
3095 : different from its canonical type, wrap the whole thing inside a
3096 : NOP_EXPR and force the type of the COMPONENT_REF to be the canonical
3097 : type.
3098 :
3099 : The canonical type of a COMPONENT_REF is the type of the field being
3100 : referenced--unless the field is a bit-field which can be read directly
3101 : in a smaller mode, in which case the canonical type is the
3102 : sign-appropriate type corresponding to that mode. */
3103 :
3104 : static void
3105 18466753 : canonicalize_component_ref (tree *expr_p)
3106 : {
3107 18466753 : tree expr = *expr_p;
3108 18466753 : tree type;
3109 :
3110 18466753 : gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
3111 :
3112 18466753 : if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
3113 7520014 : type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
3114 : else
3115 10946739 : type = TREE_TYPE (TREE_OPERAND (expr, 1));
3116 :
3117 : /* One could argue that all the stuff below is not necessary for
3118 : the non-bitfield case and declare it a FE error if type
3119 : adjustment would be needed. */
3120 18466753 : if (TREE_TYPE (expr) != type)
3121 : {
3122 : #ifdef ENABLE_TYPES_CHECKING
3123 739089 : tree old_type = TREE_TYPE (expr);
3124 : #endif
3125 739089 : int type_quals;
3126 :
3127 : /* We need to preserve qualifiers and propagate them from
3128 : operand 0. */
3129 739089 : type_quals = TYPE_QUALS (type)
3130 739089 : | TYPE_QUALS (TREE_TYPE (TREE_OPERAND (expr, 0)));
3131 739089 : if (TYPE_QUALS (type) != type_quals)
3132 738929 : type = build_qualified_type (TYPE_MAIN_VARIANT (type), type_quals);
3133 :
3134 : /* Set the type of the COMPONENT_REF to the underlying type. */
3135 739089 : TREE_TYPE (expr) = type;
3136 :
3137 : #ifdef ENABLE_TYPES_CHECKING
3138 : /* It is now a FE error, if the conversion from the canonical
3139 : type to the original expression type is not useless. */
3140 739089 : gcc_assert (useless_type_conversion_p (old_type, type));
3141 : #endif
3142 : }
3143 18466753 : }
3144 :
3145 : /* If a NOP conversion is changing a pointer to array of foo to a pointer
3146 : to foo, embed that change in the ADDR_EXPR by converting
3147 : T array[U];
3148 : (T *)&array
3149 : ==>
3150 : &array[L]
3151 : where L is the lower bound. For simplicity, only do this for constant
3152 : lower bound.
3153 : The constraint is that the type of &array[L] is trivially convertible
3154 : to T *. */
3155 :
3156 : static void
3157 518447 : canonicalize_addr_expr (tree *expr_p)
3158 : {
3159 518447 : tree expr = *expr_p;
3160 518447 : tree addr_expr = TREE_OPERAND (expr, 0);
3161 518447 : tree datype, ddatype, pddatype;
3162 :
3163 : /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
3164 1036548 : if (!POINTER_TYPE_P (TREE_TYPE (expr))
3165 518447 : || TREE_CODE (addr_expr) != ADDR_EXPR)
3166 : return;
3167 :
3168 : /* The addr_expr type should be a pointer to an array. */
3169 346 : datype = TREE_TYPE (TREE_TYPE (addr_expr));
3170 346 : if (TREE_CODE (datype) != ARRAY_TYPE)
3171 : return;
3172 :
3173 : /* The pointer to element type shall be trivially convertible to
3174 : the expression pointer type. */
3175 28 : ddatype = TREE_TYPE (datype);
3176 28 : pddatype = build_pointer_type (ddatype);
3177 28 : if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
3178 : pddatype))
3179 : return;
3180 :
3181 : /* The lower bound and element sizes must be constant. */
3182 0 : if (!TYPE_SIZE_UNIT (ddatype)
3183 0 : || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
3184 0 : || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
3185 0 : || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
3186 : return;
3187 :
3188 : /* All checks succeeded. Build a new node to merge the cast. */
3189 0 : *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
3190 0 : TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
3191 : NULL_TREE, NULL_TREE);
3192 0 : *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
3193 :
3194 : /* We can have stripped a required restrict qualifier above. */
3195 0 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
3196 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
3197 : }
3198 :
3199 : /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
3200 : underneath as appropriate. */
3201 :
3202 : static enum gimplify_status
3203 12824675 : gimplify_conversion (tree *expr_p)
3204 : {
3205 12824675 : location_t loc = EXPR_LOCATION (*expr_p);
3206 12824675 : gcc_assert (CONVERT_EXPR_P (*expr_p));
3207 :
3208 : /* Then strip away all but the outermost conversion. */
3209 12824675 : STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
3210 :
3211 : /* And remove the outermost conversion if it's useless. */
3212 12824675 : if (tree_ssa_useless_type_conversion (*expr_p))
3213 0 : *expr_p = TREE_OPERAND (*expr_p, 0);
3214 :
3215 : /* If we still have a conversion at the toplevel,
3216 : then canonicalize some constructs. */
3217 12824675 : if (CONVERT_EXPR_P (*expr_p))
3218 : {
3219 12824675 : tree sub = TREE_OPERAND (*expr_p, 0);
3220 :
3221 : /* If a NOP conversion is changing the type of a COMPONENT_REF
3222 : expression, then canonicalize its type now in order to expose more
3223 : redundant conversions. */
3224 12824675 : if (TREE_CODE (sub) == COMPONENT_REF)
3225 272556 : canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0));
3226 :
3227 : /* If a NOP conversion is changing a pointer to array of foo
3228 : to a pointer to foo, embed that change in the ADDR_EXPR. */
3229 12552119 : else if (TREE_CODE (sub) == ADDR_EXPR)
3230 518447 : canonicalize_addr_expr (expr_p);
3231 : }
3232 :
3233 : /* If we have a conversion to a non-register type force the
3234 : use of a VIEW_CONVERT_EXPR instead. */
3235 12824675 : if (CONVERT_EXPR_P (*expr_p) && !is_gimple_reg_type (TREE_TYPE (*expr_p)))
3236 90 : *expr_p = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p),
3237 90 : TREE_OPERAND (*expr_p, 0));
3238 :
3239 : /* Canonicalize CONVERT_EXPR to NOP_EXPR. */
3240 12824675 : if (TREE_CODE (*expr_p) == CONVERT_EXPR)
3241 227554 : TREE_SET_CODE (*expr_p, NOP_EXPR);
3242 :
3243 12824675 : return GS_OK;
3244 : }
3245 :
3246 : /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
3247 : DECL_VALUE_EXPR, and it's worth re-examining things. */
3248 :
3249 : static enum gimplify_status
3250 126210064 : gimplify_var_or_parm_decl (tree *expr_p)
3251 : {
3252 126210064 : tree decl = *expr_p;
3253 :
3254 : /* ??? If this is a local variable, and it has not been seen in any
3255 : outer BIND_EXPR, then it's probably the result of a duplicate
3256 : declaration, for which we've already issued an error. It would
3257 : be really nice if the front end wouldn't leak these at all.
3258 : Currently the only known culprit is C++ destructors, as seen
3259 : in g++.old-deja/g++.jason/binding.C.
3260 : Another possible culpit are size expressions for variably modified
3261 : types which are lost in the FE or not gimplified correctly. */
3262 126210064 : if (VAR_P (decl)
3263 98695927 : && !DECL_SEEN_IN_BIND_EXPR_P (decl)
3264 17066461 : && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
3265 126270058 : && decl_function_context (decl) == current_function_decl)
3266 : {
3267 75 : gcc_assert (seen_error ());
3268 : return GS_ERROR;
3269 : }
3270 :
3271 : /* When within an OMP context, notice uses of variables. */
3272 126209989 : if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
3273 : return GS_ALL_DONE;
3274 :
3275 : /* If the decl is an alias for another expression, substitute it now. */
3276 126204169 : if (DECL_HAS_VALUE_EXPR_P (decl))
3277 : {
3278 432049 : *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
3279 432049 : return GS_OK;
3280 : }
3281 :
3282 : return GS_ALL_DONE;
3283 : }
3284 :
3285 : /* Recalculate the value of the TREE_SIDE_EFFECTS flag for T. */
3286 :
3287 : static void
3288 110194377 : recalculate_side_effects (tree t)
3289 : {
3290 110194377 : enum tree_code code = TREE_CODE (t);
3291 110194377 : int len = TREE_OPERAND_LENGTH (t);
3292 110194377 : int i;
3293 :
3294 110194377 : switch (TREE_CODE_CLASS (code))
3295 : {
3296 660970 : case tcc_expression:
3297 660970 : switch (code)
3298 : {
3299 : case INIT_EXPR:
3300 : case MODIFY_EXPR:
3301 : case VA_ARG_EXPR:
3302 : case PREDECREMENT_EXPR:
3303 : case PREINCREMENT_EXPR:
3304 : case POSTDECREMENT_EXPR:
3305 : case POSTINCREMENT_EXPR:
3306 : /* All of these have side-effects, no matter what their
3307 : operands are. */
3308 : return;
3309 :
3310 : default:
3311 : break;
3312 : }
3313 : /* Fall through. */
3314 :
3315 110194375 : case tcc_comparison: /* a comparison expression */
3316 110194375 : case tcc_unary: /* a unary arithmetic expression */
3317 110194375 : case tcc_binary: /* a binary arithmetic expression */
3318 110194375 : case tcc_reference: /* a reference */
3319 110194375 : case tcc_vl_exp: /* a function call */
3320 110194375 : TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
3321 359375421 : for (i = 0; i < len; ++i)
3322 : {
3323 249181046 : tree op = TREE_OPERAND (t, i);
3324 249181046 : if (op && TREE_SIDE_EFFECTS (op))
3325 1276360 : TREE_SIDE_EFFECTS (t) = 1;
3326 : }
3327 : break;
3328 :
3329 : case tcc_constant:
3330 : /* No side-effects. */
3331 : return;
3332 :
3333 2 : default:
3334 2 : if (code == SSA_NAME)
3335 : /* No side-effects. */
3336 : return;
3337 0 : gcc_unreachable ();
3338 : }
3339 : }
3340 :
3341 : /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
3342 : node *EXPR_P.
3343 :
3344 : compound_lval
3345 : : min_lval '[' val ']'
3346 : | min_lval '.' ID
3347 : | compound_lval '[' val ']'
3348 : | compound_lval '.' ID
3349 :
3350 : This is not part of the original SIMPLE definition, which separates
3351 : array and member references, but it seems reasonable to handle them
3352 : together. Also, this way we don't run into problems with union
3353 : aliasing; gcc requires that for accesses through a union to alias, the
3354 : union reference must be explicit, which was not always the case when we
3355 : were splitting up array and member refs.
3356 :
3357 : PRE_P points to the sequence where side effects that must happen before
3358 : *EXPR_P should be stored.
3359 :
3360 : POST_P points to the sequence where side effects that must happen after
3361 : *EXPR_P should be stored. */
3362 :
3363 : static enum gimplify_status
3364 29894761 : gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3365 : fallback_t fallback)
3366 : {
3367 29894761 : tree *p;
3368 29894761 : enum gimplify_status ret = GS_ALL_DONE, tret;
3369 29894761 : int i;
3370 29894761 : location_t loc = EXPR_LOCATION (*expr_p);
3371 29894761 : tree expr = *expr_p;
3372 :
3373 : /* Create a stack of the subexpressions so later we can walk them in
3374 : order from inner to outer. */
3375 29894761 : auto_vec<tree, 10> expr_stack;
3376 :
3377 : /* We can handle anything that get_inner_reference can deal with. */
3378 72171144 : for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
3379 : {
3380 42276383 : restart:
3381 : /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
3382 72237119 : if (TREE_CODE (*p) == INDIRECT_REF)
3383 3872789 : *p = fold_indirect_ref_loc (loc, *p);
3384 :
3385 72237119 : if (handled_component_p (*p))
3386 : ;
3387 : /* Expand DECL_VALUE_EXPR now. In some cases that may expose
3388 : additional COMPONENT_REFs. */
3389 13067651 : else if ((VAR_P (*p) || TREE_CODE (*p) == PARM_DECL)
3390 31404434 : && gimplify_var_or_parm_decl (p) == GS_OK)
3391 65975 : goto restart;
3392 : else
3393 : break;
3394 :
3395 42276383 : expr_stack.safe_push (*p);
3396 : }
3397 :
3398 29894761 : gcc_assert (expr_stack.length ());
3399 :
3400 : /* Now EXPR_STACK is a stack of pointers to all the refs we've
3401 : walked through and P points to the innermost expression.
3402 :
3403 : Java requires that we elaborated nodes in source order. That
3404 : means we must gimplify the inner expression followed by each of
3405 : the indices, in order. But we can't gimplify the inner
3406 : expression until we deal with any variable bounds, sizes, or
3407 : positions in order to deal with PLACEHOLDER_EXPRs.
3408 :
3409 : The base expression may contain a statement expression that
3410 : has declarations used in size expressions, so has to be
3411 : gimplified before gimplifying the size expressions.
3412 :
3413 : So we do this in three steps. First we deal with variable
3414 : bounds, sizes, and positions, then we gimplify the base and
3415 : ensure it is memory if needed, then we deal with the annotations
3416 : for any variables in the components and any indices, from left
3417 : to right. */
3418 :
3419 29894761 : bool need_non_reg = false;
3420 72171141 : for (i = expr_stack.length () - 1; i >= 0; i--)
3421 : {
3422 42276383 : tree t = expr_stack[i];
3423 :
3424 42276383 : if (error_operand_p (TREE_OPERAND (t, 0)))
3425 : return GS_ERROR;
3426 :
3427 42276380 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3428 : {
3429 : /* Deal with the low bound and element type size and put them into
3430 : the ARRAY_REF. If these values are set, they have already been
3431 : gimplified. */
3432 8954378 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3433 : {
3434 8888491 : tree low = unshare_expr (array_ref_low_bound (t));
3435 8888491 : if (!is_gimple_min_invariant (low))
3436 : {
3437 0 : TREE_OPERAND (t, 2) = low;
3438 : }
3439 : }
3440 :
3441 8954378 : if (TREE_OPERAND (t, 3) == NULL_TREE)
3442 : {
3443 8940853 : tree elmt_size = array_ref_element_size (t);
3444 8940853 : if (!is_gimple_min_invariant (elmt_size))
3445 : {
3446 8497 : elmt_size = unshare_expr (elmt_size);
3447 8497 : tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
3448 8497 : tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
3449 :
3450 : /* Divide the element size by the alignment of the element
3451 : type (above). */
3452 8497 : elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR,
3453 : elmt_size, factor);
3454 :
3455 8497 : TREE_OPERAND (t, 3) = elmt_size;
3456 : }
3457 : }
3458 : need_non_reg = true;
3459 : }
3460 33322002 : else if (TREE_CODE (t) == COMPONENT_REF)
3461 : {
3462 : /* Set the field offset into T and gimplify it. */
3463 32144669 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3464 : {
3465 32144290 : tree offset = component_ref_field_offset (t);
3466 32144290 : if (!is_gimple_min_invariant (offset))
3467 : {
3468 287 : offset = unshare_expr (offset);
3469 287 : tree field = TREE_OPERAND (t, 1);
3470 287 : tree factor
3471 287 : = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
3472 :
3473 : /* Divide the offset by its alignment. */
3474 287 : offset = size_binop_loc (loc, EXACT_DIV_EXPR,
3475 : offset, factor);
3476 :
3477 287 : TREE_OPERAND (t, 2) = offset;
3478 : }
3479 : }
3480 : need_non_reg = true;
3481 : }
3482 1177333 : else if (!is_gimple_reg_type (TREE_TYPE (t)))
3483 : /* When the result of an operation, in particular a VIEW_CONVERT_EXPR
3484 : is a non-register type then require the base object to be a
3485 : non-register as well. */
3486 41377178 : need_non_reg = true;
3487 : }
3488 :
3489 : /* Step 2 is to gimplify the base expression. Make sure lvalue is set
3490 : so as to match the min_lval predicate. Failure to do so may result
3491 : in the creation of large aggregate temporaries. */
3492 29894758 : tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
3493 : fallback | fb_lvalue);
3494 29894758 : ret = MIN (ret, tret);
3495 29894758 : if (ret == GS_ERROR)
3496 : return GS_ERROR;
3497 :
3498 : /* Step 2a: if we have component references we do not support on
3499 : registers then make sure the base isn't a register. Of course
3500 : we can only do so if an rvalue is OK. */
3501 29894758 : if (need_non_reg && (fallback & fb_rvalue))
3502 22330460 : prepare_gimple_addressable (p, pre_p);
3503 :
3504 :
3505 : /* Step 3: gimplify size expressions and the indices and operands of
3506 : ARRAY_REF. During this loop we also remove any useless conversions.
3507 : If we operate on a register also make sure to properly gimplify
3508 : to individual operations. */
3509 :
3510 29894758 : bool reg_operations = is_gimple_reg (*p);
3511 72171138 : for (; expr_stack.length () > 0; )
3512 : {
3513 42276380 : tree t = expr_stack.pop ();
3514 :
3515 42276380 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3516 : {
3517 8954378 : gcc_assert (!reg_operations);
3518 :
3519 : /* Gimplify the low bound and element type size. */
3520 8954378 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3521 : is_gimple_reg, fb_rvalue);
3522 8954378 : ret = MIN (ret, tret);
3523 :
3524 8954378 : tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
3525 : is_gimple_reg, fb_rvalue);
3526 8954378 : ret = MIN (ret, tret);
3527 :
3528 : /* Gimplify the dimension. */
3529 8954378 : tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
3530 : is_gimple_val, fb_rvalue);
3531 8954378 : ret = MIN (ret, tret);
3532 : }
3533 33322002 : else if (TREE_CODE (t) == COMPONENT_REF)
3534 : {
3535 32144669 : gcc_assert (!reg_operations);
3536 :
3537 32144669 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3538 : is_gimple_reg, fb_rvalue);
3539 32144669 : ret = MIN (ret, tret);
3540 : }
3541 1177333 : else if (reg_operations)
3542 : {
3543 780696 : tret = gimplify_expr (&TREE_OPERAND (t, 0), pre_p, post_p,
3544 : is_gimple_val, fb_rvalue);
3545 1177333 : ret = MIN (ret, tret);
3546 : }
3547 :
3548 42276380 : STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
3549 :
3550 : /* The innermost expression P may have originally had
3551 : TREE_SIDE_EFFECTS set which would have caused all the outer
3552 : expressions in *EXPR_P leading to P to also have had
3553 : TREE_SIDE_EFFECTS set. */
3554 42276380 : recalculate_side_effects (t);
3555 : }
3556 :
3557 : /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */
3558 29894758 : if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
3559 : {
3560 18194197 : canonicalize_component_ref (expr_p);
3561 : }
3562 :
3563 29894758 : expr_stack.release ();
3564 :
3565 29894758 : gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
3566 :
3567 : return ret;
3568 29894761 : }
3569 :
3570 : /* Gimplify the self modifying expression pointed to by EXPR_P
3571 : (++, --, +=, -=).
3572 :
3573 : PRE_P points to the list where side effects that must happen before
3574 : *EXPR_P should be stored.
3575 :
3576 : POST_P points to the list where side effects that must happen after
3577 : *EXPR_P should be stored.
3578 :
3579 : WANT_VALUE is nonzero iff we want to use the value of this expression
3580 : in another expression.
3581 :
3582 : ARITH_TYPE is the type the computation should be performed in. */
3583 :
3584 : enum gimplify_status
3585 1131142 : gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3586 : bool want_value, tree arith_type)
3587 : {
3588 1131142 : enum tree_code code;
3589 1131142 : tree lhs, lvalue, rhs, t1;
3590 1131142 : gimple_seq post = NULL, *orig_post_p = post_p;
3591 1131142 : bool postfix;
3592 1131142 : enum tree_code arith_code;
3593 1131142 : enum gimplify_status ret;
3594 1131142 : location_t loc = EXPR_LOCATION (*expr_p);
3595 :
3596 1131142 : code = TREE_CODE (*expr_p);
3597 :
3598 1131142 : gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
3599 : || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
3600 :
3601 : /* Prefix or postfix? */
3602 1131142 : if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
3603 : /* Faster to treat as prefix if result is not used. */
3604 : postfix = want_value;
3605 : else
3606 : postfix = false;
3607 :
3608 : /* For postfix, make sure the inner expression's post side effects
3609 : are executed after side effects from this expression. */
3610 400067 : if (postfix)
3611 1131142 : post_p = &post;
3612 :
3613 : /* Add or subtract? */
3614 1131142 : if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
3615 : arith_code = PLUS_EXPR;
3616 : else
3617 43665 : arith_code = MINUS_EXPR;
3618 :
3619 : /* Gimplify the LHS into a GIMPLE lvalue. */
3620 1131142 : lvalue = TREE_OPERAND (*expr_p, 0);
3621 1131142 : ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
3622 1131142 : if (ret == GS_ERROR)
3623 : return ret;
3624 :
3625 : /* Extract the operands to the arithmetic operation. */
3626 1131137 : lhs = lvalue;
3627 1131137 : rhs = TREE_OPERAND (*expr_p, 1);
3628 :
3629 : /* For postfix operator, we evaluate the LHS to an rvalue and then use
3630 : that as the result value and in the postqueue operation. */
3631 1131137 : if (postfix)
3632 : {
3633 188196 : ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
3634 188196 : if (ret == GS_ERROR)
3635 : return ret;
3636 :
3637 188196 : lhs = get_initialized_tmp_var (lhs, pre_p);
3638 : }
3639 :
3640 : /* For POINTERs increment, use POINTER_PLUS_EXPR. */
3641 1131137 : if (POINTER_TYPE_P (TREE_TYPE (lhs)))
3642 : {
3643 231315 : rhs = convert_to_ptrofftype_loc (loc, rhs);
3644 231315 : if (arith_code == MINUS_EXPR)
3645 9646 : rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
3646 231315 : t1 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
3647 : }
3648 : else
3649 899822 : t1 = fold_convert (TREE_TYPE (*expr_p),
3650 : fold_build2 (arith_code, arith_type,
3651 : fold_convert (arith_type, lhs),
3652 : fold_convert (arith_type, rhs)));
3653 :
3654 1131137 : if (postfix)
3655 : {
3656 188196 : gimplify_assign (lvalue, t1, pre_p);
3657 188196 : gimplify_seq_add_seq (orig_post_p, post);
3658 188196 : *expr_p = lhs;
3659 188196 : return GS_ALL_DONE;
3660 : }
3661 : else
3662 : {
3663 942941 : *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
3664 942941 : return GS_OK;
3665 : }
3666 : }
3667 :
3668 : /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
3669 :
3670 : static void
3671 80452196 : maybe_with_size_expr (tree *expr_p)
3672 : {
3673 80452196 : tree expr = *expr_p;
3674 80452196 : tree type = TREE_TYPE (expr);
3675 80452196 : tree size;
3676 :
3677 : /* If we've already wrapped this or the type is error_mark_node, we can't do
3678 : anything. */
3679 80452196 : if (TREE_CODE (expr) == WITH_SIZE_EXPR
3680 80452071 : || type == error_mark_node)
3681 : return;
3682 :
3683 : /* If the size isn't known or is a constant, we have nothing to do. */
3684 80451923 : size = TYPE_SIZE_UNIT (type);
3685 80451923 : if (!size || poly_int_tree_p (size))
3686 : return;
3687 :
3688 : /* Otherwise, make a WITH_SIZE_EXPR. */
3689 1699 : size = unshare_expr (size);
3690 1699 : size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
3691 1699 : *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
3692 : }
3693 :
3694 : /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P
3695 : Store any side-effects in PRE_P. CALL_LOCATION is the location of
3696 : the CALL_EXPR. If ALLOW_SSA is set the actual parameter may be
3697 : gimplified to an SSA name. */
3698 :
3699 : enum gimplify_status
3700 33006812 : gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
3701 : bool allow_ssa)
3702 : {
3703 33006812 : bool (*test) (tree);
3704 33006812 : fallback_t fb;
3705 :
3706 : /* In general, we allow lvalues for function arguments to avoid
3707 : extra overhead of copying large aggregates out of even larger
3708 : aggregates into temporaries only to copy the temporaries to
3709 : the argument list. Make optimizers happy by pulling out to
3710 : temporaries those types that fit in registers. */
3711 33006812 : if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
3712 : test = is_gimple_val, fb = fb_rvalue;
3713 : else
3714 : {
3715 1549438 : test = is_gimple_lvalue, fb = fb_either;
3716 : /* Also strip a TARGET_EXPR that would force an extra copy. */
3717 1549438 : if (TREE_CODE (*arg_p) == TARGET_EXPR)
3718 : {
3719 299989 : tree init = TARGET_EXPR_INITIAL (*arg_p);
3720 299989 : if (init
3721 299986 : && !VOID_TYPE_P (TREE_TYPE (init))
3722 : /* Currently, due to c++/116015, it is not desirable to
3723 : strip a TARGET_EXPR whose initializer is a {}. The
3724 : problem is that if we do elide it, we also have to
3725 : replace all the occurrences of the slot temporary in the
3726 : initializer with the temporary created for the argument.
3727 : But we do not have that temporary yet so the replacement
3728 : would be quite awkward and it might be needed to resort
3729 : back to a PLACEHOLDER_EXPR. Note that stripping the
3730 : TARGET_EXPR wouldn't help anyway, as gimplify_expr would
3731 : just allocate a temporary to store the CONSTRUCTOR into.
3732 : (FIXME PR116375.)
3733 :
3734 : See convert_for_arg_passing for the C++ code that marks
3735 : the TARGET_EXPR as eliding or not. */
3736 561505 : && TREE_CODE (init) != CONSTRUCTOR)
3737 231337 : *arg_p = init;
3738 : }
3739 : }
3740 :
3741 : /* If this is a variable sized type, we must remember the size. */
3742 33006812 : maybe_with_size_expr (arg_p);
3743 :
3744 : /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */
3745 : /* Make sure arguments have the same location as the function call
3746 : itself. */
3747 33006812 : protected_set_expr_location (*arg_p, call_location);
3748 :
3749 : /* There is a sequence point before a function call. Side effects in
3750 : the argument list must occur before the actual call. So, when
3751 : gimplifying arguments, force gimplify_expr to use an internal
3752 : post queue which is then appended to the end of PRE_P. */
3753 33006812 : return gimplify_expr (arg_p, pre_p, NULL, test, fb, allow_ssa);
3754 : }
3755 :
3756 : /* Don't fold inside offloading or taskreg regions: it can break code by
3757 : adding decl references that weren't in the source. We'll do it during
3758 : omplower pass instead. */
3759 :
3760 : static bool
3761 58869966 : maybe_fold_stmt (gimple_stmt_iterator *gsi)
3762 : {
3763 58869966 : struct gimplify_omp_ctx *ctx;
3764 59398081 : for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
3765 1198525 : if ((ctx->region_type & (ORT_TARGET | ORT_PARALLEL | ORT_TASK)) != 0)
3766 : return false;
3767 533064 : else if ((ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
3768 : return false;
3769 : /* Delay folding of builtins until the IL is in consistent state
3770 : so the diagnostic machinery can do a better job. */
3771 58199556 : if (gimple_call_builtin_p (gsi_stmt (*gsi)))
3772 : return false;
3773 55849953 : return fold_stmt (gsi);
3774 : }
3775 :
3776 : static tree
3777 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
3778 : tree construct_context);
3779 :
3780 :
3781 : /* Helper function for calls to omp_dynamic_cond: find the current
3782 : enclosing block in the gimplification context. */
3783 : static tree
3784 359 : find_supercontext (void)
3785 : {
3786 359 : vec<gbind *>stack = gimple_bind_expr_stack ();
3787 686 : for (int i = stack.length () - 1; i >= 0; i++)
3788 : {
3789 327 : gbind *b = stack[i];
3790 327 : if (b->block)
3791 : return b->block;
3792 : }
3793 : return NULL_TREE;
3794 : }
3795 :
3796 : /* OpenMP: Handle the append_args and adjust_args clauses of
3797 : declare_variant for EXPR, which is a CALL_EXPR whose CALL_EXPR_FN
3798 : is the variant, within a dispatch construct with clauses DISPATCH_CLAUSES.
3799 : WANT_VALUE and POINTERIZE are as for expand_variant_call_expr.
3800 :
3801 : 'append_args' causes interop objects are added after the last regular
3802 : (nonhidden, nonvariadic) arguments of the variant function.
3803 : 'adjust_args' with need_device_{addr,ptr} converts the pointer target of
3804 : a pointer from a host to a device address. This uses either the default
3805 : device or the passed device number, which then sets the default device
3806 : address. */
3807 : static tree
3808 471 : modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
3809 : bool want_value, bool pointerize)
3810 : {
3811 471 : location_t loc = EXPR_LOCATION (expr);
3812 471 : tree fndecl = get_callee_fndecl (expr);
3813 :
3814 : /* Skip processing if we don't get the expected call form. */
3815 471 : if (!fndecl)
3816 : return expr;
3817 :
3818 471 : tree init_code = NULL_TREE;
3819 471 : tree cleanup = NULL_TREE;
3820 471 : tree clobbers = NULL_TREE;
3821 471 : int nargs = call_expr_nargs (expr);
3822 471 : tree dispatch_device_num = NULL_TREE;
3823 471 : tree dispatch_interop = NULL_TREE;
3824 471 : tree dispatch_append_args = NULL_TREE;
3825 471 : int nfirst_args = 0;
3826 471 : tree dispatch_adjust_args_list
3827 471 : = lookup_attribute ("omp declare variant variant args",
3828 471 : DECL_ATTRIBUTES (fndecl));
3829 :
3830 471 : if (dispatch_adjust_args_list)
3831 : {
3832 389 : dispatch_adjust_args_list = TREE_VALUE (dispatch_adjust_args_list);
3833 389 : dispatch_append_args = TREE_CHAIN (dispatch_adjust_args_list);
3834 389 : if (TREE_PURPOSE (dispatch_adjust_args_list) == NULL_TREE
3835 389 : && TREE_VALUE (dispatch_adjust_args_list) == NULL_TREE)
3836 : dispatch_adjust_args_list = NULL_TREE;
3837 : }
3838 389 : if (dispatch_append_args)
3839 : {
3840 245 : nfirst_args = tree_to_shwi (TREE_PURPOSE (dispatch_append_args));
3841 245 : dispatch_append_args = TREE_VALUE (dispatch_append_args);
3842 : }
3843 471 : dispatch_device_num = omp_find_clause (dispatch_clauses, OMP_CLAUSE_DEVICE);
3844 471 : if (dispatch_device_num)
3845 287 : dispatch_device_num = OMP_CLAUSE_DEVICE_ID (dispatch_device_num);
3846 471 : dispatch_interop = omp_find_clause (dispatch_clauses, OMP_CLAUSE_INTEROP);
3847 471 : int nappend = 0, ninterop = 0;
3848 880 : for (tree t = dispatch_append_args; t; t = TREE_CHAIN (t))
3849 409 : nappend++;
3850 :
3851 : /* FIXME: error checking should be taken out of this function and
3852 : handled before any attempt at filtering or resolution happens.
3853 : Otherwise whether or not diagnostics appear is determined by
3854 : GCC internals, how good the front ends are at constant-folding,
3855 : the split between early/late resolution, etc instead of the code
3856 : as written by the user. */
3857 471 : if (dispatch_interop)
3858 861 : for (tree t = dispatch_interop; t; t = TREE_CHAIN (t))
3859 605 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3860 409 : ninterop++;
3861 471 : if (dispatch_interop && !dispatch_device_num)
3862 : {
3863 7 : gcc_checking_assert (ninterop > 1);
3864 7 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3865 : "the %<device%> clause must be present if the %<interop%> "
3866 : "clause has more than one list item");
3867 : }
3868 471 : if (nappend < ninterop)
3869 : {
3870 48 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3871 : "number of list items in %<interop%> clause (%d) "
3872 : "exceeds the number of %<append_args%> items (%d) for "
3873 : "%<declare variant%> candidate %qD", ninterop, nappend, fndecl);
3874 88 : inform (dispatch_append_args
3875 8 : ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args))
3876 40 : : DECL_SOURCE_LOCATION (fndecl),
3877 : "%<declare variant%> candidate %qD declared here", fndecl);
3878 48 : ninterop = nappend;
3879 : }
3880 471 : if (dispatch_append_args)
3881 : {
3882 245 : tree *buffer = XALLOCAVEC (tree, nargs + nappend);
3883 245 : tree arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
3884 : /* Copy the first arguments; insert then the interop objects,
3885 : and then copy the rest (nargs - nfirst_args) args. */
3886 245 : int i;
3887 679 : for (i = 0; i < nfirst_args; i++)
3888 : {
3889 434 : arg = TREE_CHAIN (arg);
3890 434 : buffer[i] = CALL_EXPR_ARG (expr, i);
3891 : }
3892 : int j = ninterop;
3893 583 : for (tree t = dispatch_interop; t && j > 0; t = TREE_CHAIN (t))
3894 338 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3895 338 : buffer[i + --j] = OMP_CLAUSE_DECL (t);
3896 245 : gcc_checking_assert (j == 0);
3897 :
3898 : /* Do we need to create additional interop objects? */
3899 245 : if (ninterop < nappend)
3900 : {
3901 56 : if (dispatch_device_num == NULL_TREE)
3902 : /* Not remapping device number. */
3903 22 : dispatch_device_num = build_int_cst (integer_type_node,
3904 : GOMP_DEVICE_DEFAULT_OMP_61);
3905 56 : int nnew = nappend - ninterop;
3906 56 : tree nobjs = build_int_cst (integer_type_node, nnew);
3907 56 : tree a, t;
3908 :
3909 : /* Skip to the append_args clause for the first constructed
3910 : interop argument. */
3911 56 : tree apparg = dispatch_append_args;
3912 83 : for (j = 0; j < ninterop; j++)
3913 27 : apparg = TREE_CHAIN (apparg);
3914 :
3915 : /* omp_interop_t *objs[n]; */
3916 56 : tree objtype = build_pointer_type (pointer_sized_int_node);
3917 56 : t = build_array_type_nelts (objtype, nnew);
3918 56 : tree objs = create_tmp_var (t, "interopobjs");
3919 :
3920 : /* int target_tgtsync[n]; */
3921 56 : t = build_array_type_nelts (integer_type_node, nnew);
3922 56 : tree target_tgtsync = create_tmp_var (t, "tgt_tgtsync");
3923 :
3924 : /* Scan first to determine if we need a prefer_type array. */
3925 56 : tree prefer_type = NULL_TREE;
3926 56 : tree prefer_type_type = NULL_TREE;
3927 141 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3928 64 : if (TREE_VALUE (a) != NULL_TREE)
3929 : {
3930 : /* const char *prefer_type[n]; */
3931 35 : t = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
3932 35 : prefer_type_type = build_pointer_type (t);
3933 35 : t = build_array_type_nelts (prefer_type_type, nnew);
3934 35 : prefer_type = create_tmp_var (t, "pref_type");
3935 35 : break;
3936 : }
3937 :
3938 : /* Initialize the arrays, generating temp vars and clobbers for
3939 : the interop objects. (The constructed array holding the
3940 : pointers to these objects shouldn't need clobbering as there's
3941 : no reason for GOMP_interop to modify its contents.) */
3942 127 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3943 : {
3944 : /* The allocated temporaries for the interop objects
3945 : have type omp_interop_t, which is an integer type that
3946 : can encode a pointer. */
3947 71 : tree objvar = create_tmp_var (pointer_sized_int_node, "interop");
3948 71 : buffer[i + j] = objvar;
3949 71 : TREE_ADDRESSABLE (objvar) = 1;
3950 : /* Generate a clobber for the temporary for when we're done
3951 : with it. */
3952 71 : tree c = build_clobber (pointer_sized_int_node,
3953 : CLOBBER_OBJECT_END);
3954 71 : c = build2 (MODIFY_EXPR, pointer_sized_int_node, objvar, c);
3955 71 : if (clobbers)
3956 15 : clobbers = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
3957 : c, clobbers);
3958 : else
3959 : clobbers = c;
3960 :
3961 : /* objs[offset] = &objvar; */
3962 71 : tree offset = build_int_cst (integer_type_node, j - ninterop);
3963 71 : tree init = build4 (ARRAY_REF, objtype, objs, offset,
3964 : NULL_TREE, NULL_TREE);
3965 71 : init = build2 (MODIFY_EXPR, objtype, init,
3966 : build_fold_addr_expr (objvar));
3967 71 : if (init_code)
3968 15 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
3969 : init_code, init);
3970 : else
3971 : init_code = init;
3972 :
3973 : /* target_tgtsync[offset] = tgt;
3974 : (Don't blame me, I didn't design the encoding of this
3975 : info into the dispatch interop clause data structure,
3976 : but the runtime wants a bit mask.) */
3977 71 : tree tree_tgt = TREE_OPERAND (TREE_PURPOSE (a), 0);
3978 71 : int tgt = 0;
3979 71 : if (TREE_PURPOSE (tree_tgt) == boolean_true_node)
3980 42 : tgt |= GOMP_INTEROP_TARGET;
3981 71 : if (TREE_VALUE (tree_tgt) == boolean_true_node)
3982 36 : tgt |= GOMP_INTEROP_TARGETSYNC;
3983 71 : init = build4 (ARRAY_REF, integer_type_node,
3984 : target_tgtsync, offset, NULL_TREE, NULL_TREE);
3985 71 : init = build2 (MODIFY_EXPR, integer_type_node, init,
3986 71 : build_int_cst (integer_type_node, tgt));
3987 71 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
3988 : init_code, init);
3989 :
3990 71 : if (prefer_type)
3991 : {
3992 45 : tree pref = TREE_VALUE (a);
3993 45 : if (pref == NULL_TREE)
3994 6 : pref = null_pointer_node;
3995 : else
3996 39 : pref = build_fold_addr_expr (pref);
3997 45 : init = build4 (ARRAY_REF, prefer_type_type, prefer_type,
3998 : offset, NULL_TREE, NULL_TREE);
3999 45 : init = build2 (MODIFY_EXPR, prefer_type_type, init,
4000 : pref);
4001 45 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4002 : init_code, init);
4003 : }
4004 : }
4005 :
4006 56 : objs = build_fold_addr_expr (objs);
4007 56 : target_tgtsync = build_fold_addr_expr (target_tgtsync);
4008 56 : prefer_type = prefer_type ? build_fold_addr_expr (prefer_type)
4009 : : null_pointer_node;
4010 56 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
4011 56 : tree create
4012 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4013 : nobjs, objs, target_tgtsync, prefer_type,
4014 : integer_zero_node, null_pointer_node,
4015 : integer_zero_node, null_pointer_node,
4016 : integer_zero_node, null_pointer_node);
4017 56 : if (init_code)
4018 56 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (create),
4019 : init_code, create);
4020 : else
4021 : init_code = create;
4022 :
4023 56 : cleanup
4024 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4025 : integer_zero_node, null_pointer_node,
4026 : null_pointer_node, null_pointer_node,
4027 : integer_zero_node, null_pointer_node,
4028 : nobjs, objs,
4029 : integer_zero_node, null_pointer_node);
4030 56 : if (clobbers)
4031 56 : cleanup = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
4032 : cleanup, clobbers);
4033 : }
4034 :
4035 654 : for (j = 0; j < nappend; j++)
4036 : {
4037 : /* Fortran permits by-reference or by-value for the dummy arg
4038 : and by-value, by-reference, ptr by-reference as actual
4039 : argument. Handle this. */
4040 409 : tree obj = buffer[i + j]; // interop object
4041 409 : tree a2 = TREE_VALUE (arg); // parameter type
4042 766 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4043 436 : && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (obj))))
4044 : {
4045 32 : tree t = TREE_TYPE (TREE_TYPE (obj));
4046 32 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (t)));
4047 32 : obj = fold_build1 (INDIRECT_REF, t, obj);
4048 : }
4049 750 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4050 420 : && INTEGRAL_TYPE_P (a2))
4051 : {
4052 43 : tree t = TREE_TYPE (TREE_TYPE (obj));
4053 43 : gcc_checking_assert (INTEGRAL_TYPE_P (t));
4054 43 : obj = fold_build1 (INDIRECT_REF, t, obj);
4055 : }
4056 497 : else if (INTEGRAL_TYPE_P (TREE_TYPE (obj))
4057 461 : && POINTER_TYPE_P (a2))
4058 : {
4059 18 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4060 18 : obj = build_fold_addr_expr (obj);
4061 : }
4062 348 : else if (!INTEGRAL_TYPE_P (a2)
4063 348 : || !INTEGRAL_TYPE_P (TREE_TYPE (obj)))
4064 : {
4065 36 : tree t = TREE_TYPE (obj);
4066 36 : gcc_checking_assert (POINTER_TYPE_P (t)
4067 : && POINTER_TYPE_P (a2)
4068 : && INTEGRAL_TYPE_P (TREE_TYPE (t))
4069 : && INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4070 : }
4071 409 : buffer[i + j] = obj;
4072 409 : arg = TREE_CHAIN (arg);
4073 : }
4074 245 : i += nappend;
4075 534 : for (j = nfirst_args; j < nargs; j++)
4076 289 : buffer[i++] = CALL_EXPR_ARG (expr, j);
4077 245 : nargs += nappend;
4078 245 : tree call = expr;
4079 490 : expr = build_call_array_loc (EXPR_LOCATION (expr), TREE_TYPE (call),
4080 245 : CALL_EXPR_FN (call), nargs, buffer);
4081 :
4082 : /* Copy all CALL_EXPR flags. */
4083 245 : CALL_EXPR_STATIC_CHAIN (expr) = CALL_EXPR_STATIC_CHAIN (call);
4084 245 : CALL_EXPR_TAILCALL (expr) = CALL_EXPR_TAILCALL (call);
4085 245 : CALL_EXPR_RETURN_SLOT_OPT (expr)
4086 245 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4087 245 : CALL_FROM_THUNK_P (expr) = CALL_FROM_THUNK_P (call);
4088 245 : SET_EXPR_LOCATION (expr, EXPR_LOCATION (call));
4089 245 : CALL_EXPR_VA_ARG_PACK (expr) = CALL_EXPR_VA_ARG_PACK (call);
4090 : }
4091 :
4092 : /* Nothing to do for adjust_args? */
4093 471 : if (!dispatch_adjust_args_list || !TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
4094 260 : goto add_cleanup;
4095 :
4096 : /* Handle adjust_args. */
4097 966 : for (int i = 0; i < nargs; i++)
4098 : {
4099 755 : tree *arg_p = &CALL_EXPR_ARG (expr, i);
4100 :
4101 : /* Nothing to do if arg is constant null pointer. */
4102 755 : if (integer_zerop (*arg_p))
4103 6 : continue;
4104 :
4105 : bool need_device_ptr = false;
4106 : bool need_device_addr = false;
4107 2247 : for (int need_addr = 0; need_addr <= 1; need_addr++)
4108 2301 : for (tree arg = (need_addr
4109 1498 : ? TREE_VALUE (dispatch_adjust_args_list)
4110 1498 : : TREE_PURPOSE (dispatch_adjust_args_list));
4111 2301 : arg != NULL; arg = TREE_CHAIN (arg))
4112 : {
4113 1152 : if (TREE_VALUE (arg)
4114 1152 : && TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST
4115 2304 : && wi::eq_p (i, wi::to_wide (TREE_VALUE (arg))))
4116 : {
4117 349 : if (need_addr)
4118 : need_device_addr = true;
4119 : else
4120 349 : need_device_ptr = true;
4121 : break;
4122 : }
4123 : }
4124 :
4125 749 : if (need_device_ptr || need_device_addr)
4126 : {
4127 740 : bool is_device_ptr = false;
4128 740 : bool has_device_addr = false;
4129 :
4130 740 : for (tree c = dispatch_clauses; c; c = TREE_CHAIN (c))
4131 : {
4132 454 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
4133 454 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
4134 : {
4135 164 : tree decl1 = DECL_NAME (OMP_CLAUSE_DECL (c));
4136 164 : tree decl2 = tree_strip_nop_conversions (*arg_p);
4137 164 : if (TREE_CODE (decl2) == ADDR_EXPR)
4138 19 : decl2 = TREE_OPERAND (decl2, 0);
4139 164 : if (VAR_P (decl2) || TREE_CODE (decl2) == PARM_DECL)
4140 : {
4141 140 : decl2 = DECL_NAME (decl2);
4142 140 : if (decl1 == decl2
4143 203 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
4144 : {
4145 58 : if (need_device_addr)
4146 0 : warning_at (OMP_CLAUSE_LOCATION (c),
4147 0 : OPT_Wopenmp,
4148 : "%<is_device_ptr%> for %qD does"
4149 : " not imply %<has_device_addr%> "
4150 : "required for %<need_device_addr%>",
4151 0 : OMP_CLAUSE_DECL (c));
4152 : is_device_ptr = true;
4153 : break;
4154 : }
4155 82 : else if (decl1 == decl2)
4156 : {
4157 5 : if (need_device_ptr)
4158 10 : warning_at (OMP_CLAUSE_LOCATION (c),
4159 5 : OPT_Wopenmp,
4160 : "%<has_device_addr%> for %qD does"
4161 : " not imply %<is_device_ptr%> "
4162 : "required for %<need_device_ptr%>",
4163 5 : OMP_CLAUSE_DECL (c));
4164 : has_device_addr = true;
4165 : break;
4166 : }
4167 : }
4168 : }
4169 : }
4170 :
4171 349 : if ((need_device_ptr && !is_device_ptr)
4172 58 : || (need_device_addr && !has_device_addr))
4173 : {
4174 291 : if (dispatch_device_num == NULL_TREE)
4175 : {
4176 : // device_num = omp_get_default_device ()
4177 105 : tree fn
4178 105 : = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
4179 105 : tree call = build_call_expr (fn, 0);
4180 105 : dispatch_device_num = create_tmp_var_raw (TREE_TYPE (call));
4181 105 : tree init
4182 105 : = build4 (TARGET_EXPR, TREE_TYPE (call),
4183 : dispatch_device_num, call, NULL_TREE, NULL_TREE);
4184 105 : if (init_code)
4185 0 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4186 : init_code, init);
4187 : else
4188 : init_code = init;
4189 : }
4190 :
4191 : // We want to emit the following statement:
4192 : // mapped_arg = omp_get_mapped_ptr (arg,
4193 : // device_num)
4194 : // but arg has to be the actual pointer, not a
4195 : // reference or a conversion expression.
4196 291 : tree actual_ptr
4197 291 : = ((TREE_CODE (*arg_p) == ADDR_EXPR)
4198 291 : ? TREE_OPERAND (*arg_p, 0)
4199 38 : : *arg_p);
4200 291 : if (TREE_CODE (actual_ptr) == NOP_EXPR
4201 291 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (actual_ptr, 0)))
4202 : == REFERENCE_TYPE))
4203 : {
4204 6 : actual_ptr = TREE_OPERAND (actual_ptr, 0);
4205 6 : actual_ptr = build1 (INDIRECT_REF,
4206 6 : TREE_TYPE (actual_ptr),
4207 : actual_ptr);
4208 : }
4209 291 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_MAPPED_PTR);
4210 291 : tree mapped_arg = build_call_expr_loc (loc, fn, 2, actual_ptr,
4211 : dispatch_device_num);
4212 :
4213 291 : if (TREE_CODE (*arg_p) == ADDR_EXPR
4214 291 : || (TREE_CODE (TREE_TYPE (actual_ptr)) == REFERENCE_TYPE))
4215 47 : mapped_arg = build_fold_addr_expr (mapped_arg);
4216 244 : else if (TREE_CODE (*arg_p) == NOP_EXPR)
4217 35 : mapped_arg = build1 (NOP_EXPR, TREE_TYPE (*arg_p),
4218 : mapped_arg);
4219 291 : *arg_p = mapped_arg;
4220 : }
4221 : }
4222 : }
4223 :
4224 471 : add_cleanup:
4225 471 : if (cleanup)
4226 : {
4227 56 : tree result = NULL_TREE;
4228 56 : if (want_value && pointerize)
4229 : {
4230 0 : tree tmp = create_tmp_var (build_pointer_type (TREE_TYPE (expr)),
4231 : "cleanuptmp");
4232 0 : result = build_simple_mem_ref (tmp);
4233 0 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp,
4234 : build_fold_addr_expr (expr));
4235 : }
4236 56 : else if (want_value)
4237 : {
4238 18 : tree tmp = create_tmp_var (TREE_TYPE (expr), "cleanuptmp");
4239 18 : result = tmp;
4240 18 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp, expr);
4241 : }
4242 56 : if (init_code)
4243 56 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4244 56 : expr = build2 (TRY_FINALLY_EXPR, void_type_node, expr, cleanup);
4245 :
4246 56 : if (result)
4247 18 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (result), expr, result);
4248 : }
4249 415 : else if (init_code)
4250 105 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4251 :
4252 : return expr;
4253 : }
4254 :
4255 : /* Helper function for gimplify_call_expr: handle "declare variant"
4256 : resolution and expansion of the CALL_EXPR EXPR. WANT_VALUE is true
4257 : if the result value of the call is needed; POINTERIZE is true if it
4258 : also needs to be pointerized. If OMP_DISPATCH_P is true, apply
4259 : associated transformations using DISPATCH_CLAUSES.
4260 : This function may return either the original call or some other
4261 : expression such as a conditional to select one of multiple calls.
4262 :
4263 : FIXME: this function is written to be independent of gimplifier internals
4264 : so that it could be moved to omp-general.cc and invoked from the
4265 : front ends instead, per PR115076. */
4266 :
4267 : static tree
4268 1326 : expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
4269 : bool omp_dispatch_p, tree dispatch_clauses)
4270 : {
4271 : /* If we've already processed this call, stop now. This can happen
4272 : if the variant call resolves to the original function, or to
4273 : a dynamic conditional that includes the default call to the original
4274 : function. */
4275 1326 : gcc_assert (omp_resolved_variant_calls != NULL);
4276 1326 : if (omp_resolved_variant_calls->contains (expr))
4277 131 : return expr;
4278 :
4279 1195 : tree fndecl = get_callee_fndecl (expr);
4280 1195 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (expr));
4281 1195 : location_t loc = EXPR_LOCATION (expr);
4282 1195 : tree construct_context = omp_get_construct_context ();
4283 1195 : vec<struct omp_variant> all_candidates
4284 1195 : = omp_declare_variant_candidates (fndecl, construct_context);
4285 1195 : gcc_assert (!all_candidates.is_empty ());
4286 1195 : vec<struct omp_variant> candidates
4287 1195 : = omp_get_dynamic_candidates (all_candidates, construct_context);
4288 :
4289 : /* If the variant call could be resolved now, build a nest of COND_EXPRs
4290 : if there are dynamic candidates, and/or a new CALL_EXPR for each
4291 : candidate call. */
4292 1195 : if (!candidates.is_empty ())
4293 : {
4294 1183 : int n = candidates.length ();
4295 1183 : tree tail = NULL_TREE;
4296 :
4297 2404 : for (int i = n - 1; i >= 0; i--)
4298 : {
4299 1221 : if (tail)
4300 38 : gcc_assert (candidates[i].dynamic_selector);
4301 : else
4302 1183 : gcc_assert (!candidates[i].dynamic_selector);
4303 1221 : if (candidates[i].alternative == fndecl)
4304 : {
4305 : /* We should only get the original function back as the
4306 : default. */
4307 261 : gcc_assert (!tail);
4308 261 : omp_resolved_variant_calls->add (expr);
4309 261 : tail = expr;
4310 : }
4311 : else
4312 : {
4313 : /* For the final static selector, we can re-use the old
4314 : CALL_EXPR and just replace the function, unless it may
4315 : need dispatch argument modification. Otherwise,
4316 : make a copy of it. */
4317 960 : tree thiscall = (tail || omp_dispatch_p
4318 960 : ? unshare_expr (expr) : expr);
4319 960 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype,
4320 960 : candidates[i].alternative);
4321 960 : if (omp_dispatch_p)
4322 471 : thiscall = modify_call_for_omp_dispatch (thiscall,
4323 : dispatch_clauses,
4324 : want_value,
4325 : pointerize);
4326 960 : if (!tail)
4327 : tail = thiscall;
4328 : else
4329 76 : tail = build3 (COND_EXPR, TREE_TYPE (expr),
4330 38 : omp_dynamic_cond (candidates[i].selector,
4331 : find_supercontext ()),
4332 : thiscall, tail);
4333 : }
4334 : }
4335 : return tail;
4336 : }
4337 :
4338 : /* If we couldn't resolve the variant call now, expand it into a loop using
4339 : a switch and OMP_NEXT_VARIANT for dispatch. The ompdevlow pass will
4340 : handle OMP_NEXT_VARIANT expansion. */
4341 : else
4342 : {
4343 : /* If we need a usable return value, we need a temporary
4344 : and an assignment in each alternative. This logic was borrowed
4345 : from gimplify_cond_expr. */
4346 12 : tree type = TREE_TYPE (expr);
4347 12 : tree tmp = NULL_TREE, result = NULL_TREE;
4348 :
4349 12 : if (want_value)
4350 : {
4351 12 : if (pointerize)
4352 : {
4353 0 : type = build_pointer_type (type);
4354 0 : tmp = create_tmp_var (type, "iftmp");
4355 0 : result = build_simple_mem_ref_loc (loc, tmp);
4356 : }
4357 : else
4358 : {
4359 12 : tmp = create_tmp_var (type, "iftmp");
4360 12 : result = tmp;
4361 : }
4362 : }
4363 :
4364 : /* Preprocess the all_candidates array so that the alternative field of
4365 : each element holds the actual function call expression and possible
4366 : assignment, instead of just the decl for the variant function. */
4367 60 : for (unsigned int i = 0; i < all_candidates.length (); i++)
4368 : {
4369 48 : tree decl = all_candidates[i].alternative;
4370 48 : tree thiscall;
4371 :
4372 : /* We need to turn the decl from the candidate into a function
4373 : call and possible assignment, and stuff that in
4374 : the directive seq of the gomp_variant. */
4375 48 : if (decl == fndecl)
4376 : {
4377 12 : thiscall = expr;
4378 12 : omp_resolved_variant_calls->add (expr);
4379 : }
4380 : else
4381 : {
4382 36 : thiscall = unshare_expr (expr);
4383 36 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype, decl);
4384 36 : if (omp_dispatch_p)
4385 0 : thiscall = modify_call_for_omp_dispatch (thiscall,
4386 : dispatch_clauses,
4387 : want_value,
4388 : pointerize);
4389 : }
4390 48 : if (pointerize)
4391 0 : thiscall = build_fold_addr_expr_loc (loc, thiscall);
4392 48 : if (want_value)
4393 48 : thiscall = build2 (INIT_EXPR, type, tmp, thiscall);
4394 48 : all_candidates[i].alternative = thiscall;
4395 : }
4396 :
4397 12 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
4398 12 : tree expansion = expand_late_variant_directive (all_candidates,
4399 : construct_context);
4400 12 : if (result)
4401 12 : expansion = build2 (COMPOUND_EXPR, TREE_TYPE (result),
4402 : expansion, result);
4403 12 : return expansion;
4404 : }
4405 : }
4406 :
4407 : /* Wrapper around expand_variant_call_expr to interface with gimplifier
4408 : state. EXPR and OMP_DISPATCH_P are as for expand_variant_call_expr,
4409 : FALLBACK is used to compute the WANT_VALUE and POINTERIZE arguments. */
4410 : static tree
4411 1326 : gimplify_variant_call_expr (tree expr, fallback_t fallback,
4412 : bool omp_dispatch_p)
4413 : {
4414 1326 : tree type = TREE_TYPE (expr);
4415 1326 : bool want_value = (fallback != fb_none && !VOID_TYPE_P (type));
4416 673 : bool pointerize = false;
4417 : /* If the result value must be an lvalue or the result type must
4418 : live in memory, then we have to pointerize it if we need a temporary. */
4419 673 : if (want_value
4420 673 : && ((!(fallback & fb_rvalue) && (fallback & fb_lvalue))
4421 673 : || TREE_ADDRESSABLE (type)))
4422 0 : pointerize = true;
4423 :
4424 1838 : return expand_variant_call_expr (expr, want_value, pointerize,
4425 : omp_dispatch_p,
4426 : (omp_dispatch_p
4427 512 : ? gimplify_omp_ctxp->clauses
4428 1326 : : NULL_TREE));
4429 : }
4430 :
4431 :
4432 : /* Helper function for gimplify_call_expr, called via walk_tree.
4433 : Find used user labels. */
4434 :
4435 : static tree
4436 766 : find_used_user_labels (tree *tp, int *, void *)
4437 : {
4438 766 : if (TREE_CODE (*tp) == LABEL_EXPR
4439 15 : && !DECL_ARTIFICIAL (LABEL_EXPR_LABEL (*tp))
4440 15 : && DECL_NAME (LABEL_EXPR_LABEL (*tp))
4441 781 : && TREE_USED (LABEL_EXPR_LABEL (*tp)))
4442 15 : return *tp;
4443 : return NULL_TREE;
4444 : }
4445 :
4446 :
4447 : /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
4448 : WANT_VALUE is true if the result of the call is desired. */
4449 :
4450 : static enum gimplify_status
4451 16669640 : gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
4452 : {
4453 16669640 : bool want_value = (fallback != fb_none);
4454 16669640 : tree fndecl, parms, p, fnptrtype;
4455 16669640 : enum gimplify_status ret;
4456 16669640 : int i, nargs;
4457 16669640 : gcall *call;
4458 16669640 : bool builtin_va_start_p = false, omp_dispatch_p = false;
4459 16669640 : location_t loc = EXPR_LOCATION (*expr_p);
4460 :
4461 16669640 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4462 :
4463 : /* For reliable diagnostics during inlining, it is necessary that
4464 : every call_expr be annotated with file and line. */
4465 16669640 : if (! EXPR_HAS_LOCATION (*expr_p))
4466 562691 : SET_EXPR_LOCATION (*expr_p, input_location);
4467 :
4468 : /* Gimplify internal functions created in the FEs. */
4469 16669640 : if (CALL_EXPR_FN (*expr_p) == NULL_TREE)
4470 : {
4471 563746 : enum internal_fn ifn = CALL_EXPR_IFN (*expr_p);
4472 563746 : if (ifn == IFN_GOMP_DISPATCH)
4473 : {
4474 884 : gcc_assert (flag_openmp
4475 : && gimplify_omp_ctxp
4476 : && gimplify_omp_ctxp->code == OMP_DISPATCH);
4477 884 : *expr_p = CALL_EXPR_ARG (*expr_p, 0);
4478 884 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4479 884 : if (! EXPR_HAS_LOCATION (*expr_p))
4480 94 : SET_EXPR_LOCATION (*expr_p, input_location);
4481 : omp_dispatch_p = true;
4482 : }
4483 : else
4484 : {
4485 562862 : if (want_value)
4486 : return GS_ALL_DONE;
4487 :
4488 19580 : nargs = call_expr_nargs (*expr_p);
4489 19580 : auto_vec<tree> vargs (nargs);
4490 :
4491 19580 : if (ifn == IFN_ASSUME)
4492 : {
4493 513 : if (simple_condition_p (CALL_EXPR_ARG (*expr_p, 0)))
4494 : {
4495 : /* If the [[assume (cond)]]; condition is simple
4496 : enough and can be evaluated unconditionally
4497 : without side-effects, expand it as
4498 : if (!cond) __builtin_unreachable (); */
4499 293 : tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
4500 293 : *expr_p
4501 586 : = build3 (COND_EXPR, void_type_node,
4502 293 : CALL_EXPR_ARG (*expr_p, 0), void_node,
4503 293 : build_call_expr_loc (EXPR_LOCATION (*expr_p),
4504 : fndecl, 0));
4505 293 : return GS_OK;
4506 : }
4507 : /* If not optimizing, ignore the assumptions unless there
4508 : are used user labels in it. */
4509 220 : if ((!optimize
4510 98 : && !walk_tree_without_duplicates (&CALL_EXPR_ARG (*expr_p,
4511 : 0),
4512 : find_used_user_labels,
4513 : NULL))
4514 235 : || seen_error ())
4515 : {
4516 94 : *expr_p = NULL_TREE;
4517 94 : return GS_ALL_DONE;
4518 : }
4519 : /* Temporarily, until gimple lowering, transform
4520 : .ASSUME (cond);
4521 : into:
4522 : [[assume (guard)]]
4523 : {
4524 : guard = cond;
4525 : }
4526 : such that gimple lowering can outline the condition into
4527 : a separate function easily. */
4528 126 : tree guard = create_tmp_var (boolean_type_node);
4529 126 : *expr_p = build2 (MODIFY_EXPR, void_type_node, guard,
4530 126 : gimple_boolify (CALL_EXPR_ARG (*expr_p, 0)));
4531 126 : *expr_p = build3 (BIND_EXPR, void_type_node, NULL, *expr_p, NULL);
4532 126 : push_gimplify_context ();
4533 126 : gimple_seq body = NULL;
4534 126 : gimple *g = gimplify_and_return_first (*expr_p, &body);
4535 126 : pop_gimplify_context (g);
4536 126 : g = gimple_build_assume (guard, body);
4537 126 : gimple_set_location (g, loc);
4538 126 : gimplify_seq_add_stmt (pre_p, g);
4539 126 : *expr_p = NULL_TREE;
4540 126 : return GS_ALL_DONE;
4541 : }
4542 19067 : else if (ifn == IFN_UBSAN_BOUNDS
4543 19067 : && nargs == 3
4544 19067 : && integer_onep (CALL_EXPR_ARG (*expr_p, 0)))
4545 : {
4546 : /* If first argument is one, add TYPE_MAX_VALUE (TYPE_DOMAIN (t))
4547 : to 3rd argument and change first argument to 0. This is
4548 : done by ubsan_instrument_bounds so that we can use the
4549 : max value from gimplify_type_sizes here instead of original
4550 : expression for VLAs. */
4551 406 : tree type = TREE_TYPE (CALL_EXPR_ARG (*expr_p, 0));
4552 406 : CALL_EXPR_ARG (*expr_p, 0) = build_int_cst (type, 0);
4553 406 : gcc_assert (TREE_CODE (type) == POINTER_TYPE);
4554 406 : type = TREE_TYPE (type);
4555 406 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4556 406 : tree maxv = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4557 406 : gcc_assert (maxv);
4558 406 : tree arg3 = CALL_EXPR_ARG (*expr_p, 2);
4559 406 : CALL_EXPR_ARG (*expr_p, 2)
4560 812 : = fold_build2 (PLUS_EXPR, TREE_TYPE (arg3), maxv, arg3);
4561 : }
4562 :
4563 44694 : for (i = 0; i < nargs; i++)
4564 : {
4565 25627 : gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
4566 25627 : EXPR_LOCATION (*expr_p));
4567 25627 : vargs.quick_push (CALL_EXPR_ARG (*expr_p, i));
4568 : }
4569 :
4570 19067 : gcall *call = gimple_build_call_internal_vec (ifn, vargs);
4571 19067 : gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p));
4572 19067 : gimplify_seq_add_stmt (pre_p, call);
4573 19067 : return GS_ALL_DONE;
4574 19580 : }
4575 : }
4576 :
4577 : /* This may be a call to a builtin function.
4578 :
4579 : Builtin function calls may be transformed into different
4580 : (and more efficient) builtin function calls under certain
4581 : circumstances. Unfortunately, gimplification can muck things
4582 : up enough that the builtin expanders are not aware that certain
4583 : transformations are still valid.
4584 :
4585 : So we attempt transformation/gimplification of the call before
4586 : we gimplify the CALL_EXPR. At this time we do not manage to
4587 : transform all calls in the same manner as the expanders do, but
4588 : we do transform most of them. */
4589 16106778 : fndecl = get_callee_fndecl (*expr_p);
4590 16106778 : if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
4591 3943829 : switch (DECL_FUNCTION_CODE (fndecl))
4592 : {
4593 95347 : CASE_BUILT_IN_ALLOCA:
4594 : /* If the call has been built for a variable-sized object, then we
4595 : want to restore the stack level when the enclosing BIND_EXPR is
4596 : exited to reclaim the allocated space; otherwise, we precisely
4597 : need to do the opposite and preserve the latest stack level. */
4598 95347 : if (CALL_ALLOCA_FOR_VAR_P (*expr_p))
4599 8965 : gimplify_ctxp->save_stack = true;
4600 : else
4601 86382 : gimplify_ctxp->keep_stack = true;
4602 : break;
4603 :
4604 20884 : case BUILT_IN_VA_START:
4605 20884 : {
4606 20884 : builtin_va_start_p = true;
4607 20884 : if (call_expr_nargs (*expr_p) < 2)
4608 : {
4609 1 : error ("too few arguments to function %<va_start%>");
4610 1 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4611 1 : return GS_OK;
4612 : }
4613 :
4614 20883 : if (fold_builtin_next_arg (*expr_p, true))
4615 : {
4616 8 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4617 8 : return GS_OK;
4618 : }
4619 : break;
4620 : }
4621 :
4622 30 : case BUILT_IN_EH_RETURN:
4623 30 : cfun->calls_eh_return = true;
4624 30 : break;
4625 :
4626 1030 : case BUILT_IN_CLEAR_PADDING:
4627 1030 : if (call_expr_nargs (*expr_p) == 1)
4628 : {
4629 : /* Remember the original type of the argument in an internal
4630 : dummy second argument, as in GIMPLE pointer conversions are
4631 : useless. Also mark this call as not for automatic
4632 : initialization in the internal dummy third argument. */
4633 515 : p = CALL_EXPR_ARG (*expr_p, 0);
4634 515 : *expr_p
4635 515 : = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
4636 515 : build_zero_cst (TREE_TYPE (p)));
4637 515 : return GS_OK;
4638 : }
4639 : break;
4640 :
4641 : default:
4642 : ;
4643 : }
4644 16106254 : if (fndecl && fndecl_built_in_p (fndecl))
4645 : {
4646 4179412 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4647 4179412 : if (new_tree && new_tree != *expr_p)
4648 : {
4649 : /* There was a transformation of this call which computes the
4650 : same value, but in a more efficient way. Return and try
4651 : again. */
4652 755 : *expr_p = new_tree;
4653 755 : return GS_OK;
4654 : }
4655 : }
4656 :
4657 : /* Remember the original function pointer type. */
4658 16105499 : fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
4659 :
4660 : /* Handle "declare variant" resolution and arglist processing. */
4661 16105499 : if (flag_openmp
4662 448281 : && fndecl
4663 447600 : && cfun
4664 447600 : && (cfun->curr_properties & PROP_gimple_any) == 0
4665 250405 : && !omp_has_novariants ()
4666 16355792 : && lookup_attribute ("omp declare variant base",
4667 250293 : DECL_ATTRIBUTES (fndecl)))
4668 : {
4669 1326 : tree orig = *expr_p;
4670 1326 : *expr_p = gimplify_variant_call_expr (*expr_p, fallback,
4671 : omp_dispatch_p);
4672 :
4673 : /* This may resolve to the same call, or the call expr with just
4674 : the function replaced, in which case we should just continue to
4675 : gimplify it normally. Otherwise, if we get something else back,
4676 : stop here and re-gimplify the whole replacement expr. */
4677 1326 : if (*expr_p != orig)
4678 : return GS_OK;
4679 : }
4680 :
4681 : /* There is a sequence point before the call, so any side effects in
4682 : the calling expression must occur before the actual call. Force
4683 : gimplify_expr to use an internal post queue. */
4684 16105010 : ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
4685 : is_gimple_call_addr, fb_rvalue);
4686 :
4687 16105010 : if (ret == GS_ERROR)
4688 : return GS_ERROR;
4689 :
4690 16105008 : nargs = call_expr_nargs (*expr_p);
4691 :
4692 : /* Get argument types for verification. */
4693 16105008 : fndecl = get_callee_fndecl (*expr_p);
4694 16105008 : parms = NULL_TREE;
4695 16105008 : if (fndecl)
4696 15884085 : parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
4697 : else
4698 220923 : parms = TYPE_ARG_TYPES (TREE_TYPE (fnptrtype));
4699 :
4700 31989093 : if (fndecl && DECL_ARGUMENTS (fndecl))
4701 : p = DECL_ARGUMENTS (fndecl);
4702 7309010 : else if (parms)
4703 : p = parms;
4704 : else
4705 : p = NULL_TREE;
4706 42773876 : for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
4707 : ;
4708 :
4709 : /* If the last argument is __builtin_va_arg_pack () and it is not
4710 : passed as a named argument, decrease the number of CALL_EXPR
4711 : arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */
4712 16105008 : if (!p
4713 16105008 : && i < nargs
4714 16105008 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR)
4715 : {
4716 5946 : tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1);
4717 5946 : tree last_arg_fndecl = get_callee_fndecl (last_arg);
4718 :
4719 5946 : if (last_arg_fndecl
4720 5946 : && fndecl_built_in_p (last_arg_fndecl, BUILT_IN_VA_ARG_PACK))
4721 : {
4722 131 : tree call = *expr_p;
4723 :
4724 131 : --nargs;
4725 262 : *expr_p = build_call_array_loc (loc, TREE_TYPE (call),
4726 131 : CALL_EXPR_FN (call),
4727 131 : nargs, CALL_EXPR_ARGP (call));
4728 :
4729 : /* Copy all CALL_EXPR flags, location and block, except
4730 : CALL_EXPR_VA_ARG_PACK flag. */
4731 131 : CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call);
4732 131 : CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call);
4733 131 : CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
4734 131 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4735 131 : CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
4736 131 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
4737 :
4738 : /* Set CALL_EXPR_VA_ARG_PACK. */
4739 131 : CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
4740 : }
4741 : }
4742 :
4743 : /* If the call returns twice then after building the CFG the call
4744 : argument computations will no longer dominate the call because
4745 : we add an abnormal incoming edge to the call. So do not use SSA
4746 : vars there. */
4747 16105008 : bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE;
4748 :
4749 :
4750 : /* Gimplify the function arguments. */
4751 16105008 : if (nargs > 0)
4752 : {
4753 13941431 : for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
4754 42048684 : PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
4755 28107253 : PUSH_ARGS_REVERSED ? i-- : i++)
4756 : {
4757 28107253 : enum gimplify_status t;
4758 :
4759 : /* Avoid gimplifying the second argument to va_start, which needs to
4760 : be the plain PARM_DECL. */
4761 28107253 : if ((i != 1) || !builtin_va_start_p)
4762 : {
4763 28086378 : tree *arg_p = &CALL_EXPR_ARG (*expr_p, i);
4764 :
4765 28086378 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4766 6687 : gimplify_omp_ctxp->in_call_args = true;
4767 28086378 : t = gimplify_arg (arg_p, pre_p, EXPR_LOCATION (*expr_p),
4768 28086378 : !returns_twice);
4769 28086378 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4770 6687 : gimplify_omp_ctxp->in_call_args = false;
4771 :
4772 28086378 : if (t == GS_ERROR)
4773 28107253 : ret = GS_ERROR;
4774 : }
4775 : }
4776 : }
4777 :
4778 : /* Gimplify the static chain. */
4779 16105008 : if (CALL_EXPR_STATIC_CHAIN (*expr_p))
4780 : {
4781 28852 : if (fndecl && !DECL_STATIC_CHAIN (fndecl))
4782 3 : CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL;
4783 : else
4784 : {
4785 28173 : enum gimplify_status t;
4786 28173 : t = gimplify_arg (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p,
4787 28173 : EXPR_LOCATION (*expr_p), ! returns_twice);
4788 28173 : if (t == GS_ERROR)
4789 16105008 : ret = GS_ERROR;
4790 : }
4791 : }
4792 :
4793 : /* Verify the function result. */
4794 16105008 : if (want_value && fndecl
4795 16105008 : && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
4796 : {
4797 0 : error_at (loc, "using result of function returning %<void%>");
4798 0 : ret = GS_ERROR;
4799 : }
4800 :
4801 : /* Try this again in case gimplification exposed something. */
4802 16105008 : if (ret != GS_ERROR)
4803 : {
4804 16104860 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4805 :
4806 16104860 : if (new_tree && new_tree != *expr_p)
4807 : {
4808 : /* There was a transformation of this call which computes the
4809 : same value, but in a more efficient way. Return and try
4810 : again. */
4811 11459 : *expr_p = new_tree;
4812 11459 : return GS_OK;
4813 : }
4814 : }
4815 : else
4816 : {
4817 148 : *expr_p = error_mark_node;
4818 148 : return GS_ERROR;
4819 : }
4820 :
4821 : /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
4822 : decl. This allows us to eliminate redundant or useless
4823 : calls to "const" functions. */
4824 16093401 : if (TREE_CODE (*expr_p) == CALL_EXPR)
4825 : {
4826 16093401 : int flags = call_expr_flags (*expr_p);
4827 16093401 : if (flags & (ECF_CONST | ECF_PURE)
4828 : /* An infinite loop is considered a side effect. */
4829 2439141 : && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
4830 2066699 : TREE_SIDE_EFFECTS (*expr_p) = 0;
4831 : }
4832 :
4833 : /* If the value is not needed by the caller, emit a new GIMPLE_CALL
4834 : and clear *EXPR_P. Otherwise, leave *EXPR_P in its gimplified
4835 : form and delegate the creation of a GIMPLE_CALL to
4836 : gimplify_modify_expr. This is always possible because when
4837 : WANT_VALUE is true, the caller wants the result of this call into
4838 : a temporary, which means that we will emit an INIT_EXPR in
4839 : internal_get_tmp_var which will then be handled by
4840 : gimplify_modify_expr. */
4841 16093401 : if (!want_value)
4842 : {
4843 : /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
4844 : have to do is replicate it as a GIMPLE_CALL tuple. */
4845 6148687 : gimple_stmt_iterator gsi;
4846 6148687 : call = gimple_build_call_from_tree (*expr_p, fnptrtype);
4847 6148687 : notice_special_calls (call);
4848 6148687 : gimplify_seq_add_stmt (pre_p, call);
4849 6148687 : gsi = gsi_last (*pre_p);
4850 6148687 : maybe_fold_stmt (&gsi);
4851 6148687 : *expr_p = NULL_TREE;
4852 : }
4853 : else
4854 : /* Remember the original function type. */
4855 9944714 : CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
4856 9944714 : CALL_EXPR_FN (*expr_p));
4857 :
4858 : return ret;
4859 : }
4860 :
4861 : /* Handle shortcut semantics in the predicate operand of a COND_EXPR by
4862 : rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs.
4863 :
4864 : TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the
4865 : condition is true or false, respectively. If null, we should generate
4866 : our own to skip over the evaluation of this specific expression.
4867 :
4868 : LOCUS is the source location of the COND_EXPR.
4869 :
4870 : The condition_uid is a discriminator tag for condition coverage used to map
4871 : conditions to its corresponding full Boolean function.
4872 :
4873 : This function is the tree equivalent of do_jump.
4874 :
4875 : shortcut_cond_r should only be called by shortcut_cond_expr. */
4876 :
4877 : static tree
4878 1308126 : shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
4879 : location_t locus, unsigned condition_uid)
4880 : {
4881 1308126 : tree local_label = NULL_TREE;
4882 1308126 : tree t, expr = NULL;
4883 :
4884 : /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
4885 : retain the shortcut semantics. Just insert the gotos here;
4886 : shortcut_cond_expr will append the real blocks later. */
4887 1308126 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
4888 : {
4889 120646 : location_t new_locus;
4890 :
4891 : /* Turn if (a && b) into
4892 :
4893 : if (a); else goto no;
4894 : if (b) goto yes; else goto no;
4895 : (no:) */
4896 :
4897 120646 : if (false_label_p == NULL)
4898 3981 : false_label_p = &local_label;
4899 :
4900 : /* Keep the original source location on the first 'if'. */
4901 120646 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus,
4902 : condition_uid);
4903 120646 : append_to_statement_list (t, &expr);
4904 :
4905 : /* Set the source location of the && on the second 'if'. */
4906 120646 : new_locus = rexpr_location (pred, locus);
4907 120646 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4908 : new_locus, condition_uid);
4909 120646 : append_to_statement_list (t, &expr);
4910 : }
4911 1187480 : else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
4912 : {
4913 380858 : location_t new_locus;
4914 :
4915 : /* Turn if (a || b) into
4916 :
4917 : if (a) goto yes;
4918 : if (b) goto yes; else goto no;
4919 : (yes:) */
4920 :
4921 380858 : if (true_label_p == NULL)
4922 227736 : true_label_p = &local_label;
4923 :
4924 : /* Keep the original source location on the first 'if'. */
4925 380858 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus,
4926 : condition_uid);
4927 380858 : append_to_statement_list (t, &expr);
4928 :
4929 : /* Set the source location of the || on the second 'if'. */
4930 380858 : new_locus = rexpr_location (pred, locus);
4931 380858 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4932 : new_locus, condition_uid);
4933 380858 : append_to_statement_list (t, &expr);
4934 : }
4935 806622 : else if (TREE_CODE (pred) == COND_EXPR
4936 852 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
4937 807474 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
4938 : {
4939 846 : location_t new_locus;
4940 :
4941 : /* As long as we're messing with gotos, turn if (a ? b : c) into
4942 : if (a)
4943 : if (b) goto yes; else goto no;
4944 : else
4945 : if (c) goto yes; else goto no;
4946 :
4947 : Don't do this if one of the arms has void type, which can happen
4948 : in C++ when the arm is throw. */
4949 :
4950 : /* Keep the original source location on the first 'if'. Set the source
4951 : location of the ? on the second 'if'. */
4952 846 : new_locus = rexpr_location (pred, locus);
4953 1692 : expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
4954 846 : shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
4955 : false_label_p, locus, condition_uid),
4956 846 : shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
4957 : false_label_p, new_locus,
4958 : condition_uid));
4959 846 : tree_associate_condition_with_expr (expr, condition_uid);
4960 : }
4961 : else
4962 : {
4963 805776 : expr = build3 (COND_EXPR, void_type_node, pred,
4964 : build_and_jump (true_label_p),
4965 : build_and_jump (false_label_p));
4966 805776 : SET_EXPR_LOCATION (expr, locus);
4967 805776 : tree_associate_condition_with_expr (expr, condition_uid);
4968 : }
4969 :
4970 1308126 : if (local_label)
4971 : {
4972 231717 : t = build1 (LABEL_EXPR, void_type_node, local_label);
4973 231717 : append_to_statement_list (t, &expr);
4974 : }
4975 :
4976 1308126 : return expr;
4977 : }
4978 :
4979 : /* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip
4980 : any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
4981 : statement, if it is the last one. Otherwise, return NULL. */
4982 :
4983 : static tree
4984 11454954 : find_goto (tree expr)
4985 : {
4986 11783268 : if (!expr)
4987 : return NULL_TREE;
4988 :
4989 9842738 : if (TREE_CODE (expr) == GOTO_EXPR)
4990 : return expr;
4991 :
4992 7857705 : if (TREE_CODE (expr) != STATEMENT_LIST)
4993 : return NULL_TREE;
4994 :
4995 1029513 : tree_stmt_iterator i = tsi_start (expr);
4996 :
4997 1383162 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
4998 353649 : tsi_next (&i);
4999 :
5000 10396113 : if (!tsi_one_before_end_p (i))
5001 : return NULL_TREE;
5002 :
5003 328314 : return find_goto (tsi_stmt (i));
5004 : }
5005 :
5006 : /* Same as find_goto, except that it returns NULL if the destination
5007 : is not a LABEL_DECL. */
5008 :
5009 : static inline tree
5010 11454954 : find_goto_label (tree expr)
5011 : {
5012 11454954 : tree dest = find_goto (expr);
5013 13439987 : if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
5014 1984922 : return dest;
5015 : return NULL_TREE;
5016 : }
5017 :
5018 :
5019 : /* Given a multi-term condition (ANDIF, ORIF), walk the predicate PRED and tag
5020 : every basic condition with CONDITION_UID. Two basic conditions share the
5021 : CONDITION_UID discriminator when they belong to the same predicate, which is
5022 : used by the condition coverage. Doing this as an explicit step makes for a
5023 : simpler implementation than weaving it into the splitting code as the
5024 : splitting code eventually calls the entry point gimplfiy_expr which makes
5025 : bookkeeping complicated. */
5026 : static void
5027 564813 : tag_shortcut_cond (tree pred, unsigned condition_uid)
5028 : {
5029 603642 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR
5030 603642 : || TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5031 : {
5032 554593 : tree fst = TREE_OPERAND (pred, 0);
5033 554593 : tree lst = TREE_OPERAND (pred, 1);
5034 :
5035 554593 : if (TREE_CODE (fst) == TRUTH_ANDIF_EXPR
5036 554593 : || TREE_CODE (fst) == TRUTH_ORIF_EXPR)
5037 166922 : tag_shortcut_cond (fst, condition_uid);
5038 387671 : else if (TREE_CODE (fst) == COND_EXPR)
5039 244 : tree_associate_condition_with_expr (fst, condition_uid);
5040 :
5041 554593 : if (TREE_CODE (lst) == TRUTH_ANDIF_EXPR
5042 554593 : || TREE_CODE (lst) == TRUTH_ORIF_EXPR)
5043 : tag_shortcut_cond (lst, condition_uid);
5044 515764 : else if (TREE_CODE (lst) == COND_EXPR)
5045 445 : tree_associate_condition_with_expr (lst, condition_uid);
5046 : }
5047 564813 : }
5048 :
5049 : /* Given a conditional expression EXPR with short-circuit boolean
5050 : predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
5051 : predicate apart into the equivalent sequence of conditionals. CONDITION_UID
5052 : is a the tag/discriminator for this EXPR - all basic conditions in the
5053 : expression will be given the same CONDITION_UID. */
5054 : static tree
5055 397891 : shortcut_cond_expr (tree expr, unsigned condition_uid)
5056 : {
5057 397891 : tree pred = TREE_OPERAND (expr, 0);
5058 397891 : tree then_ = TREE_OPERAND (expr, 1);
5059 397891 : tree else_ = TREE_OPERAND (expr, 2);
5060 397891 : tree true_label, false_label, end_label, t;
5061 397891 : tree *true_label_p;
5062 397891 : tree *false_label_p;
5063 397891 : bool emit_end, emit_false, jump_over_else;
5064 397891 : bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
5065 397891 : bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
5066 :
5067 397891 : tag_shortcut_cond (pred, condition_uid);
5068 :
5069 : /* First do simple transformations. */
5070 397891 : if (!else_se)
5071 : {
5072 : /* If there is no 'else', turn
5073 : if (a && b) then c
5074 : into
5075 : if (a) if (b) then c. */
5076 287851 : while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
5077 : {
5078 : /* Keep the original source location on the first 'if'. */
5079 49904 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5080 49904 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5081 : /* Set the source location of the && on the second 'if'. */
5082 49904 : if (rexpr_has_location (pred))
5083 48880 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5084 49904 : then_ = shortcut_cond_expr (expr, condition_uid);
5085 49904 : then_se = then_ && TREE_SIDE_EFFECTS (then_);
5086 49904 : pred = TREE_OPERAND (pred, 0);
5087 49904 : expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
5088 49904 : SET_EXPR_LOCATION (expr, locus);
5089 : }
5090 : }
5091 :
5092 397891 : if (!then_se)
5093 : {
5094 : /* If there is no 'then', turn
5095 : if (a || b); else d
5096 : into
5097 : if (a); else if (b); else d. */
5098 25281 : while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5099 : {
5100 : /* Keep the original source location on the first 'if'. */
5101 795 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5102 795 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5103 : /* Set the source location of the || on the second 'if'. */
5104 795 : if (rexpr_has_location (pred))
5105 794 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5106 795 : else_ = shortcut_cond_expr (expr, condition_uid);
5107 795 : else_se = else_ && TREE_SIDE_EFFECTS (else_);
5108 795 : pred = TREE_OPERAND (pred, 0);
5109 795 : expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
5110 795 : SET_EXPR_LOCATION (expr, locus);
5111 : }
5112 : }
5113 :
5114 : /* The expr tree should also have the expression id set. */
5115 397891 : tree_associate_condition_with_expr (expr, condition_uid);
5116 :
5117 : /* If we're done, great. */
5118 397891 : if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR
5119 397891 : && TREE_CODE (pred) != TRUTH_ORIF_EXPR)
5120 94465 : return expr;
5121 :
5122 : /* Otherwise we need to mess with gotos. Change
5123 : if (a) c; else d;
5124 : to
5125 : if (a); else goto no;
5126 : c; goto end;
5127 : no: d; end:
5128 : and recursively gimplify the condition. */
5129 :
5130 303426 : true_label = false_label = end_label = NULL_TREE;
5131 :
5132 : /* If our arms just jump somewhere, hijack those labels so we don't
5133 : generate jumps to jumps. */
5134 :
5135 303426 : if (tree then_goto = find_goto_label (then_))
5136 : {
5137 4555 : true_label = GOTO_DESTINATION (then_goto);
5138 4555 : then_ = NULL;
5139 4555 : then_se = false;
5140 : }
5141 :
5142 303426 : if (tree else_goto = find_goto_label (else_))
5143 : {
5144 4148 : false_label = GOTO_DESTINATION (else_goto);
5145 4148 : else_ = NULL;
5146 4148 : else_se = false;
5147 : }
5148 :
5149 : /* If we aren't hijacking a label for the 'then' branch, it falls through. */
5150 303426 : if (true_label)
5151 : true_label_p = &true_label;
5152 : else
5153 298871 : true_label_p = NULL;
5154 :
5155 : /* The 'else' branch also needs a label if it contains interesting code. */
5156 303426 : if (false_label || else_se)
5157 : false_label_p = &false_label;
5158 : else
5159 : false_label_p = NULL;
5160 :
5161 : /* If there was nothing else in our arms, just forward the label(s). */
5162 148597 : if (!then_se && !else_se)
5163 8440 : return shortcut_cond_r (pred, true_label_p, false_label_p,
5164 12660 : EXPR_LOC_OR_LOC (expr, input_location), condition_uid);
5165 :
5166 : /* If our last subexpression already has a terminal label, reuse it. */
5167 299206 : if (else_se)
5168 154829 : t = expr_last (else_);
5169 144377 : else if (then_se)
5170 144377 : t = expr_last (then_);
5171 : else
5172 : t = NULL;
5173 299206 : if (t && TREE_CODE (t) == LABEL_EXPR)
5174 963 : end_label = LABEL_EXPR_LABEL (t);
5175 :
5176 : /* If we don't care about jumping to the 'else' branch, jump to the end
5177 : if the condition is false. */
5178 299206 : if (!false_label_p)
5179 144135 : false_label_p = &end_label;
5180 :
5181 : /* We only want to emit these labels if we aren't hijacking them. */
5182 299206 : emit_end = (end_label == NULL_TREE);
5183 299206 : emit_false = (false_label == NULL_TREE);
5184 :
5185 : /* We only emit the jump over the else clause if we have to--if the
5186 : then clause may fall through. Otherwise we can wind up with a
5187 : useless jump and a useless label at the end of gimplified code,
5188 : which will cause us to think that this conditional as a whole
5189 : falls through even if it doesn't. If we then inline a function
5190 : which ends with such a condition, that can cause us to issue an
5191 : inappropriate warning about control reaching the end of a
5192 : non-void function. */
5193 299206 : jump_over_else = block_may_fallthru (then_);
5194 :
5195 597789 : pred = shortcut_cond_r (pred, true_label_p, false_label_p,
5196 597789 : EXPR_LOC_OR_LOC (expr, input_location),
5197 : condition_uid);
5198 :
5199 299206 : expr = NULL;
5200 299206 : append_to_statement_list (pred, &expr);
5201 :
5202 299206 : append_to_statement_list (then_, &expr);
5203 299206 : if (else_se)
5204 : {
5205 154829 : if (jump_over_else)
5206 : {
5207 152379 : tree last = expr_last (expr);
5208 152379 : t = build_and_jump (&end_label);
5209 152379 : if (rexpr_has_location (last))
5210 37178 : SET_EXPR_LOCATION (t, rexpr_location (last));
5211 152379 : append_to_statement_list (t, &expr);
5212 : }
5213 154829 : if (emit_false)
5214 : {
5215 154829 : t = build1 (LABEL_EXPR, void_type_node, false_label);
5216 154829 : append_to_statement_list (t, &expr);
5217 : }
5218 154829 : append_to_statement_list (else_, &expr);
5219 : }
5220 299206 : if (emit_end && end_label)
5221 : {
5222 295556 : t = build1 (LABEL_EXPR, void_type_node, end_label);
5223 295556 : append_to_statement_list (t, &expr);
5224 : }
5225 :
5226 299206 : return expr;
5227 : }
5228 :
5229 : /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */
5230 :
5231 : tree
5232 16364196 : gimple_boolify (tree expr)
5233 : {
5234 16364196 : tree type = TREE_TYPE (expr);
5235 16364196 : location_t loc = EXPR_LOCATION (expr);
5236 :
5237 16364196 : if (TREE_CODE (expr) == NE_EXPR
5238 5667310 : && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
5239 17302170 : && integer_zerop (TREE_OPERAND (expr, 1)))
5240 : {
5241 484547 : tree call = TREE_OPERAND (expr, 0);
5242 484547 : tree fn = get_callee_fndecl (call);
5243 :
5244 : /* For __builtin_expect ((long) (x), y) recurse into x as well
5245 : if x is truth_value_p. */
5246 484547 : if (fn
5247 483576 : && fndecl_built_in_p (fn, BUILT_IN_EXPECT)
5248 617746 : && call_expr_nargs (call) == 2)
5249 : {
5250 133199 : tree arg = CALL_EXPR_ARG (call, 0);
5251 133199 : if (arg)
5252 : {
5253 133199 : if (TREE_CODE (arg) == NOP_EXPR
5254 133199 : && TREE_TYPE (arg) == TREE_TYPE (call))
5255 62715 : arg = TREE_OPERAND (arg, 0);
5256 133199 : if (truth_value_p (TREE_CODE (arg)))
5257 : {
5258 110099 : arg = gimple_boolify (arg);
5259 110099 : CALL_EXPR_ARG (call, 0)
5260 220198 : = fold_convert_loc (loc, TREE_TYPE (call), arg);
5261 : }
5262 : }
5263 : }
5264 : }
5265 :
5266 16364196 : switch (TREE_CODE (expr))
5267 : {
5268 1215654 : case TRUTH_AND_EXPR:
5269 1215654 : case TRUTH_OR_EXPR:
5270 1215654 : case TRUTH_XOR_EXPR:
5271 1215654 : case TRUTH_ANDIF_EXPR:
5272 1215654 : case TRUTH_ORIF_EXPR:
5273 : /* Also boolify the arguments of truth exprs. */
5274 1215654 : TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
5275 : /* FALLTHRU */
5276 :
5277 1635409 : case TRUTH_NOT_EXPR:
5278 1635409 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5279 :
5280 : /* These expressions always produce boolean results. */
5281 1635409 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5282 306418 : TREE_TYPE (expr) = boolean_type_node;
5283 : return expr;
5284 :
5285 5222 : case ANNOTATE_EXPR:
5286 5222 : switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)))
5287 : {
5288 5222 : case annot_expr_ivdep_kind:
5289 5222 : case annot_expr_unroll_kind:
5290 5222 : case annot_expr_no_vector_kind:
5291 5222 : case annot_expr_vector_kind:
5292 5222 : case annot_expr_parallel_kind:
5293 5222 : case annot_expr_maybe_infinite_kind:
5294 5222 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5295 5222 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5296 3323 : TREE_TYPE (expr) = boolean_type_node;
5297 : return expr;
5298 0 : default:
5299 0 : gcc_unreachable ();
5300 : }
5301 :
5302 14723565 : default:
5303 14723565 : if (COMPARISON_CLASS_P (expr))
5304 : {
5305 : /* These expressions always produce boolean results. */
5306 12885396 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5307 1583153 : TREE_TYPE (expr) = boolean_type_node;
5308 12885396 : return expr;
5309 : }
5310 : /* Other expressions that get here must have boolean values, but
5311 : might need to be converted to the appropriate mode. */
5312 1838169 : if (TREE_CODE (type) == BOOLEAN_TYPE)
5313 : return expr;
5314 202150 : return fold_convert_loc (loc, boolean_type_node, expr);
5315 : }
5316 : }
5317 :
5318 : /* Given a conditional expression *EXPR_P without side effects, gimplify
5319 : its operands. New statements are inserted to PRE_P. */
5320 :
5321 : static enum gimplify_status
5322 46264 : gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
5323 : {
5324 46264 : tree expr = *expr_p, cond;
5325 46264 : enum gimplify_status ret, tret;
5326 46264 : enum tree_code code;
5327 :
5328 46264 : cond = gimple_boolify (COND_EXPR_COND (expr));
5329 :
5330 : /* We need to handle && and || specially, as their gimplification
5331 : creates pure cond_expr, thus leading to an infinite cycle otherwise. */
5332 46264 : code = TREE_CODE (cond);
5333 46264 : if (code == TRUTH_ANDIF_EXPR)
5334 35 : TREE_SET_CODE (cond, TRUTH_AND_EXPR);
5335 46229 : else if (code == TRUTH_ORIF_EXPR)
5336 4641 : TREE_SET_CODE (cond, TRUTH_OR_EXPR);
5337 46264 : ret = gimplify_expr (&cond, pre_p, NULL, is_gimple_val, fb_rvalue);
5338 46264 : COND_EXPR_COND (*expr_p) = cond;
5339 :
5340 46264 : tret = gimplify_expr (&COND_EXPR_THEN (expr), pre_p, NULL,
5341 : is_gimple_val, fb_rvalue);
5342 46264 : ret = MIN (ret, tret);
5343 46264 : tret = gimplify_expr (&COND_EXPR_ELSE (expr), pre_p, NULL,
5344 : is_gimple_val, fb_rvalue);
5345 :
5346 46264 : return MIN (ret, tret);
5347 : }
5348 :
5349 : /* Return true if evaluating EXPR could trap.
5350 : EXPR is GENERIC, while tree_could_trap_p can be called
5351 : only on GIMPLE. */
5352 :
5353 : bool
5354 15876794 : generic_expr_could_trap_p (tree expr)
5355 : {
5356 15876794 : unsigned i, n;
5357 :
5358 15876794 : if (!expr || is_gimple_val (expr))
5359 7081227 : return false;
5360 :
5361 8795567 : if (!EXPR_P (expr) || tree_could_trap_p (expr))
5362 2319171 : return true;
5363 :
5364 6476396 : n = TREE_OPERAND_LENGTH (expr);
5365 15590159 : for (i = 0; i < n; i++)
5366 11276742 : if (generic_expr_could_trap_p (TREE_OPERAND (expr, i)))
5367 : return true;
5368 :
5369 : return false;
5370 : }
5371 :
5372 : /* Associate the condition STMT with the discriminator UID. STMTs that are
5373 : broken down with ANDIF/ORIF from the same Boolean expression should be given
5374 : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
5375 : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
5376 : for condition coverage. */
5377 : static void
5378 5424051 : gimple_associate_condition_with_expr (struct function *fn, gcond *stmt,
5379 : unsigned uid)
5380 : {
5381 5424051 : if (!condition_coverage_flag)
5382 : return;
5383 :
5384 641 : if (!fn->cond_uids)
5385 139 : fn->cond_uids = new hash_map <gcond*, unsigned> ();
5386 :
5387 641 : fn->cond_uids->put (stmt, uid);
5388 : }
5389 :
5390 : /* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
5391 : into
5392 :
5393 : if (p) if (p)
5394 : t1 = a; a;
5395 : else or else
5396 : t1 = b; b;
5397 : t1;
5398 :
5399 : The second form is used when *EXPR_P is of type void.
5400 :
5401 : PRE_P points to the list where side effects that must happen before
5402 : *EXPR_P should be stored. */
5403 :
5404 : static enum gimplify_status
5405 6186388 : gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
5406 : {
5407 6186388 : tree expr = *expr_p;
5408 6186388 : tree type = TREE_TYPE (expr);
5409 6186388 : location_t loc = EXPR_LOCATION (expr);
5410 6186388 : tree tmp, arm1, arm2;
5411 6186388 : enum gimplify_status ret;
5412 6186388 : tree label_true, label_false, label_cont;
5413 6186388 : bool have_then_clause_p, have_else_clause_p;
5414 6186388 : gcond *cond_stmt;
5415 6186388 : enum tree_code pred_code;
5416 6186388 : gimple_seq seq = NULL;
5417 :
5418 : /* If this COND_EXPR has a value, copy the values into a temporary within
5419 : the arms. */
5420 6186388 : if (!VOID_TYPE_P (type))
5421 : {
5422 414369 : tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
5423 414369 : tree result;
5424 :
5425 : /* If either an rvalue is ok or we do not require an lvalue, create the
5426 : temporary. But we cannot do that if the type is addressable. */
5427 414369 : if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
5428 414362 : && !TREE_ADDRESSABLE (type))
5429 : {
5430 414362 : if (gimplify_ctxp->allow_rhs_cond_expr
5431 : /* If either branch has side effects or could trap, it can't be
5432 : evaluated unconditionally. */
5433 46264 : && !TREE_SIDE_EFFECTS (then_)
5434 46264 : && !generic_expr_could_trap_p (then_)
5435 46264 : && !TREE_SIDE_EFFECTS (else_)
5436 460626 : && !generic_expr_could_trap_p (else_))
5437 46264 : return gimplify_pure_cond_expr (expr_p, pre_p);
5438 :
5439 368098 : tmp = create_tmp_var (type, "iftmp");
5440 368098 : result = tmp;
5441 : }
5442 :
5443 : /* Otherwise, only create and copy references to the values. */
5444 : else
5445 : {
5446 7 : type = build_pointer_type (type);
5447 :
5448 7 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5449 7 : then_ = build_fold_addr_expr_loc (loc, then_);
5450 :
5451 7 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5452 7 : else_ = build_fold_addr_expr_loc (loc, else_);
5453 :
5454 7 : expr
5455 7 : = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
5456 :
5457 7 : tmp = create_tmp_var (type, "iftmp");
5458 7 : result = build_simple_mem_ref_loc (loc, tmp);
5459 : }
5460 :
5461 : /* Build the new then clause, `tmp = then_;'. But don't build the
5462 : assignment if the value is void; in C++ it can be if it's a throw. */
5463 368105 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5464 286545 : TREE_OPERAND (expr, 1) = build2 (INIT_EXPR, type, tmp, then_);
5465 :
5466 : /* Similarly, build the new else clause, `tmp = else_;'. */
5467 368105 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5468 357475 : TREE_OPERAND (expr, 2) = build2 (INIT_EXPR, type, tmp, else_);
5469 :
5470 368105 : TREE_TYPE (expr) = void_type_node;
5471 368105 : recalculate_side_effects (expr);
5472 :
5473 : /* Move the COND_EXPR to the prequeue. */
5474 368105 : gimplify_stmt (&expr, pre_p);
5475 :
5476 368105 : *expr_p = result;
5477 368105 : return GS_ALL_DONE;
5478 : }
5479 :
5480 : /* Remove any COMPOUND_EXPR so the following cases will be caught. */
5481 5787266 : STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
5482 5772019 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
5483 80968 : gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
5484 :
5485 : /* Make sure the condition has BOOLEAN_TYPE. */
5486 5772019 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5487 :
5488 : /* Break apart && and || conditions. */
5489 5772019 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
5490 5772019 : || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
5491 : {
5492 347192 : expr = shortcut_cond_expr (expr, next_cond_uid ());
5493 :
5494 347192 : if (expr != *expr_p)
5495 : {
5496 347192 : *expr_p = expr;
5497 :
5498 : /* We can't rely on gimplify_expr to re-gimplify the expanded
5499 : form properly, as cleanups might cause the target labels to be
5500 : wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to
5501 : set up a conditional context. */
5502 347192 : gimple_push_condition ();
5503 347192 : gimplify_stmt (expr_p, &seq);
5504 347192 : gimple_pop_condition (pre_p);
5505 347192 : gimple_seq_add_seq (pre_p, seq);
5506 :
5507 347192 : return GS_ALL_DONE;
5508 : }
5509 : }
5510 :
5511 : /* Now do the normal gimplification. */
5512 :
5513 : /* Gimplify condition. */
5514 5424827 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
5515 : is_gimple_condexpr_for_cond, fb_rvalue);
5516 5424827 : if (ret == GS_ERROR)
5517 : return GS_ERROR;
5518 5424051 : gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
5519 :
5520 5424051 : gimple_push_condition ();
5521 :
5522 5424051 : have_then_clause_p = have_else_clause_p = false;
5523 5424051 : label_true = find_goto_label (TREE_OPERAND (expr, 1));
5524 5424051 : if (label_true
5525 1268723 : && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
5526 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5527 : have different locations, otherwise we end up with incorrect
5528 : location information on the branches. */
5529 6692774 : && (optimize
5530 231903 : || !EXPR_HAS_LOCATION (expr)
5531 205035 : || !rexpr_has_location (label_true)
5532 71846 : || EXPR_LOCATION (expr) == rexpr_location (label_true)))
5533 : {
5534 1267563 : have_then_clause_p = true;
5535 1267563 : label_true = GOTO_DESTINATION (label_true);
5536 : }
5537 : else
5538 4156488 : label_true = create_artificial_label (UNKNOWN_LOCATION);
5539 5424051 : label_false = find_goto_label (TREE_OPERAND (expr, 2));
5540 5424051 : if (label_false
5541 707496 : && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
5542 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5543 : have different locations, otherwise we end up with incorrect
5544 : location information on the branches. */
5545 6131547 : && (optimize
5546 101626 : || !EXPR_HAS_LOCATION (expr)
5547 100748 : || !rexpr_has_location (label_false)
5548 157 : || EXPR_LOCATION (expr) == rexpr_location (label_false)))
5549 : {
5550 707351 : have_else_clause_p = true;
5551 707351 : label_false = GOTO_DESTINATION (label_false);
5552 : }
5553 : else
5554 4716700 : label_false = create_artificial_label (UNKNOWN_LOCATION);
5555 :
5556 5424051 : unsigned cond_uid = 0;
5557 5424051 : if (cond_uids)
5558 455 : if (unsigned *v = cond_uids->get (expr))
5559 435 : cond_uid = *v;
5560 435 : if (cond_uid == 0)
5561 5423616 : cond_uid = next_cond_uid ();
5562 :
5563 5424051 : gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
5564 : &arm2);
5565 5424051 : cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
5566 : label_false);
5567 5424051 : gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
5568 5424051 : gimple_associate_condition_with_expr (cfun, cond_stmt, cond_uid);
5569 5424051 : copy_warning (cond_stmt, COND_EXPR_COND (expr));
5570 5424051 : gimplify_seq_add_stmt (&seq, cond_stmt);
5571 5424051 : gimple_stmt_iterator gsi = gsi_last (seq);
5572 5424051 : maybe_fold_stmt (&gsi);
5573 :
5574 5424051 : label_cont = NULL_TREE;
5575 5424051 : if (!have_then_clause_p)
5576 : {
5577 : /* For if (...) {} else { code; } put label_true after
5578 : the else block. */
5579 4156488 : if (TREE_OPERAND (expr, 1) == NULL_TREE
5580 193899 : && !have_else_clause_p
5581 4157256 : && TREE_OPERAND (expr, 2) != NULL_TREE)
5582 : {
5583 : /* For if (0) {} else { code; } tell -Wimplicit-fallthrough
5584 : handling that label_cont == label_true can be only reached
5585 : through fallthrough from { code; }. */
5586 768 : if (integer_zerop (COND_EXPR_COND (expr)))
5587 0 : UNUSED_LABEL_P (label_true) = 1;
5588 : label_cont = label_true;
5589 : }
5590 : else
5591 : {
5592 4155720 : bool then_side_effects
5593 4155720 : = (TREE_OPERAND (expr, 1)
5594 4155720 : && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)));
5595 4155720 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
5596 4155720 : have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
5597 : /* For if (...) { code; } else {} or
5598 : if (...) { code; } else goto label; or
5599 : if (...) { code; return; } else { ... }
5600 : label_cont isn't needed. */
5601 4155720 : if (!have_else_clause_p
5602 3961443 : && TREE_OPERAND (expr, 2) != NULL_TREE
5603 6900141 : && gimple_seq_may_fallthru (seq))
5604 : {
5605 1911571 : gimple *g;
5606 1911571 : label_cont = create_artificial_label (UNKNOWN_LOCATION);
5607 :
5608 : /* For if (0) { non-side-effect-code } else { code }
5609 : tell -Wimplicit-fallthrough handling that label_cont can
5610 : be only reached through fallthrough from { code }. */
5611 1911571 : if (integer_zerop (COND_EXPR_COND (expr)))
5612 : {
5613 72707 : UNUSED_LABEL_P (label_true) = 1;
5614 72707 : if (!then_side_effects)
5615 12081 : UNUSED_LABEL_P (label_cont) = 1;
5616 : }
5617 :
5618 1911571 : g = gimple_build_goto (label_cont);
5619 :
5620 : /* GIMPLE_COND's are very low level; they have embedded
5621 : gotos. This particular embedded goto should not be marked
5622 : with the location of the original COND_EXPR, as it would
5623 : correspond to the COND_EXPR's condition, not the ELSE or the
5624 : THEN arms. To avoid marking it with the wrong location, flag
5625 : it as "no location". */
5626 1911571 : gimple_set_do_not_emit_location (g);
5627 :
5628 1911571 : gimplify_seq_add_stmt (&seq, g);
5629 : }
5630 : }
5631 : }
5632 5424051 : if (!have_else_clause_p)
5633 : {
5634 : /* For if (1) { code } or if (1) { code } else { non-side-effect-code }
5635 : tell -Wimplicit-fallthrough handling that label_false can be only
5636 : reached through fallthrough from { code }. */
5637 4716700 : if (integer_nonzerop (COND_EXPR_COND (expr))
5638 4716700 : && (TREE_OPERAND (expr, 2) == NULL_TREE
5639 56684 : || !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2))))
5640 7039 : UNUSED_LABEL_P (label_false) = 1;
5641 4716700 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_false));
5642 4716700 : have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq);
5643 : }
5644 5424051 : if (label_cont)
5645 1912339 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_cont));
5646 :
5647 5424051 : gimple_pop_condition (pre_p);
5648 5424051 : gimple_seq_add_seq (pre_p, seq);
5649 :
5650 5424051 : if (ret == GS_ERROR)
5651 : ; /* Do nothing. */
5652 5424051 : else if (have_then_clause_p || have_else_clause_p)
5653 : ret = GS_ALL_DONE;
5654 : else
5655 : {
5656 : /* Both arms are empty; replace the COND_EXPR with its predicate. */
5657 2761 : expr = TREE_OPERAND (expr, 0);
5658 2761 : gimplify_stmt (&expr, pre_p);
5659 : }
5660 :
5661 5424051 : *expr_p = NULL;
5662 5424051 : return ret;
5663 : }
5664 :
5665 : /* Prepare the node pointed to by EXPR_P, an is_gimple_addressable expression,
5666 : to be marked addressable.
5667 :
5668 : We cannot rely on such an expression being directly markable if a temporary
5669 : has been created by the gimplification. In this case, we create another
5670 : temporary and initialize it with a copy, which will become a store after we
5671 : mark it addressable. This can happen if the front-end passed us something
5672 : that it could not mark addressable yet, like a Fortran pass-by-reference
5673 : parameter (int) floatvar. */
5674 :
5675 : static void
5676 54773279 : prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
5677 : {
5678 60052419 : while (handled_component_p (*expr_p))
5679 5279140 : expr_p = &TREE_OPERAND (*expr_p, 0);
5680 :
5681 : /* Do not allow an SSA name as the temporary. */
5682 54773279 : if (is_gimple_reg (*expr_p))
5683 12021 : *expr_p = internal_get_tmp_var (*expr_p, seq_p, NULL, false, false, true);
5684 54773279 : }
5685 :
5686 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5687 : a call to __builtin_memcpy. */
5688 :
5689 : static enum gimplify_status
5690 1106 : gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
5691 : gimple_seq *seq_p)
5692 : {
5693 1106 : tree t, to, to_ptr, from, from_ptr;
5694 1106 : gcall *gs;
5695 1106 : location_t loc = EXPR_LOCATION (*expr_p);
5696 :
5697 1106 : to = TREE_OPERAND (*expr_p, 0);
5698 1106 : from = TREE_OPERAND (*expr_p, 1);
5699 1106 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to)))
5700 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))));
5701 :
5702 : /* Mark the RHS addressable. Beware that it may not be possible to do so
5703 : directly if a temporary has been created by the gimplification. */
5704 1106 : prepare_gimple_addressable (&from, seq_p);
5705 :
5706 1106 : mark_addressable (from);
5707 1106 : from_ptr = build_fold_addr_expr_loc (loc, from);
5708 1106 : gimplify_arg (&from_ptr, seq_p, loc);
5709 :
5710 1106 : mark_addressable (to);
5711 1106 : to_ptr = build_fold_addr_expr_loc (loc, to);
5712 1106 : gimplify_arg (&to_ptr, seq_p, loc);
5713 :
5714 1106 : t = builtin_decl_implicit (BUILT_IN_MEMCPY);
5715 :
5716 1106 : gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
5717 1106 : gimple_call_set_alloca_for_var (gs, true);
5718 :
5719 1106 : if (want_value)
5720 : {
5721 : /* tmp = memcpy() */
5722 8 : t = create_tmp_var (TREE_TYPE (to_ptr));
5723 8 : gimple_call_set_lhs (gs, t);
5724 8 : gimplify_seq_add_stmt (seq_p, gs);
5725 :
5726 8 : *expr_p = build_simple_mem_ref (t);
5727 8 : return GS_ALL_DONE;
5728 : }
5729 :
5730 1098 : gimplify_seq_add_stmt (seq_p, gs);
5731 1098 : *expr_p = NULL;
5732 1098 : return GS_ALL_DONE;
5733 : }
5734 :
5735 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5736 : a call to __builtin_memset. In this case we know that the RHS is
5737 : a CONSTRUCTOR with an empty element list. */
5738 :
5739 : static enum gimplify_status
5740 84 : gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
5741 : gimple_seq *seq_p)
5742 : {
5743 84 : tree t, from, to, to_ptr;
5744 84 : gcall *gs;
5745 84 : location_t loc = EXPR_LOCATION (*expr_p);
5746 :
5747 : /* Assert our assumptions, to abort instead of producing wrong code
5748 : silently if they are not met. Beware that the RHS CONSTRUCTOR might
5749 : not be immediately exposed. */
5750 84 : from = TREE_OPERAND (*expr_p, 1);
5751 84 : if (TREE_CODE (from) == WITH_SIZE_EXPR)
5752 84 : from = TREE_OPERAND (from, 0);
5753 :
5754 84 : gcc_assert (TREE_CODE (from) == CONSTRUCTOR
5755 : && vec_safe_is_empty (CONSTRUCTOR_ELTS (from)));
5756 :
5757 : /* Now proceed. */
5758 84 : to = TREE_OPERAND (*expr_p, 0);
5759 84 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to))));
5760 :
5761 84 : to_ptr = build_fold_addr_expr_loc (loc, to);
5762 84 : gimplify_arg (&to_ptr, seq_p, loc);
5763 84 : t = builtin_decl_implicit (BUILT_IN_MEMSET);
5764 :
5765 84 : gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
5766 :
5767 84 : if (want_value)
5768 : {
5769 : /* tmp = memset() */
5770 0 : t = create_tmp_var (TREE_TYPE (to_ptr));
5771 0 : gimple_call_set_lhs (gs, t);
5772 0 : gimplify_seq_add_stmt (seq_p, gs);
5773 :
5774 0 : *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
5775 0 : return GS_ALL_DONE;
5776 : }
5777 :
5778 84 : gimplify_seq_add_stmt (seq_p, gs);
5779 84 : *expr_p = NULL;
5780 84 : return GS_ALL_DONE;
5781 : }
5782 :
5783 : /* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
5784 : determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
5785 : assignment. Return non-null if we detect a potential overlap. */
5786 :
5787 : struct gimplify_init_ctor_preeval_data
5788 : {
5789 : /* The base decl of the lhs object. May be NULL, in which case we
5790 : have to assume the lhs is indirect. */
5791 : tree lhs_base_decl;
5792 :
5793 : /* The alias set of the lhs object. */
5794 : alias_set_type lhs_alias_set;
5795 : };
5796 :
5797 : static tree
5798 116067 : gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
5799 : {
5800 116067 : struct gimplify_init_ctor_preeval_data *data
5801 : = (struct gimplify_init_ctor_preeval_data *) xdata;
5802 116067 : tree t = *tp;
5803 :
5804 : /* If we find the base object, obviously we have overlap. */
5805 116067 : if (data->lhs_base_decl == t)
5806 : return t;
5807 :
5808 : /* If the constructor component is indirect, determine if we have a
5809 : potential overlap with the lhs. The only bits of information we
5810 : have to go on at this point are addressability and alias sets. */
5811 116066 : if ((INDIRECT_REF_P (t)
5812 116066 : || TREE_CODE (t) == MEM_REF)
5813 651 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5814 116582 : && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
5815 : return t;
5816 :
5817 : /* If the constructor component is a call, determine if it can hide a
5818 : potential overlap with the lhs through an INDIRECT_REF like above.
5819 : ??? Ugh - this is completely broken. In fact this whole analysis
5820 : doesn't look conservative. */
5821 115550 : if (TREE_CODE (t) == CALL_EXPR)
5822 : {
5823 0 : tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
5824 :
5825 0 : for (type = TYPE_ARG_TYPES (fntype); type; type = TREE_CHAIN (type))
5826 0 : if (POINTER_TYPE_P (TREE_VALUE (type))
5827 0 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5828 0 : && alias_sets_conflict_p (data->lhs_alias_set,
5829 : get_alias_set
5830 0 : (TREE_TYPE (TREE_VALUE (type)))))
5831 : return t;
5832 : }
5833 :
5834 115550 : if (IS_TYPE_OR_DECL_P (t))
5835 10968 : *walk_subtrees = 0;
5836 : return NULL;
5837 : }
5838 :
5839 : /* A subroutine of gimplify_init_constructor. Pre-evaluate EXPR,
5840 : force values that overlap with the lhs (as described by *DATA)
5841 : into temporaries. */
5842 :
5843 : static void
5844 413037 : gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
5845 : struct gimplify_init_ctor_preeval_data *data)
5846 : {
5847 413037 : enum gimplify_status one;
5848 :
5849 : /* If the value is constant, then there's nothing to pre-evaluate. */
5850 413037 : if (TREE_CONSTANT (*expr_p))
5851 : {
5852 : /* Ensure it does not have side effects, it might contain a reference to
5853 : the object we're initializing. */
5854 195599 : gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
5855 : return;
5856 : }
5857 :
5858 : /* If the type has non-trivial constructors, we can't pre-evaluate. */
5859 217438 : if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
5860 : return;
5861 :
5862 : /* Recurse for nested constructors. */
5863 217438 : if (TREE_CODE (*expr_p) == CONSTRUCTOR)
5864 : {
5865 73614 : unsigned HOST_WIDE_INT ix;
5866 73614 : constructor_elt *ce;
5867 73614 : vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (*expr_p);
5868 :
5869 270973 : FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
5870 197359 : gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
5871 :
5872 : return;
5873 : }
5874 :
5875 : /* If this is a variable sized type, we must remember the size. */
5876 143824 : maybe_with_size_expr (expr_p);
5877 :
5878 : /* Gimplify the constructor element to something appropriate for the rhs
5879 : of a MODIFY_EXPR. Given that we know the LHS is an aggregate, we know
5880 : the gimplifier will consider this a store to memory. Doing this
5881 : gimplification now means that we won't have to deal with complicated
5882 : language-specific trees, nor trees like SAVE_EXPR that can induce
5883 : exponential search behavior. */
5884 143824 : one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
5885 143824 : if (one == GS_ERROR)
5886 : {
5887 0 : *expr_p = NULL;
5888 0 : return;
5889 : }
5890 :
5891 : /* If we gimplified to a bare decl, we can be sure that it doesn't overlap
5892 : with the lhs, since "a = { .x=a }" doesn't make sense. This will
5893 : always be true for all scalars, since is_gimple_mem_rhs insists on a
5894 : temporary variable for them. */
5895 143824 : if (DECL_P (*expr_p))
5896 : return;
5897 :
5898 : /* If this is of variable size, we have no choice but to assume it doesn't
5899 : overlap since we can't make a temporary for it. */
5900 104503 : if (TREE_CODE (TYPE_SIZE (TREE_TYPE (*expr_p))) != INTEGER_CST)
5901 : return;
5902 :
5903 : /* Otherwise, we must search for overlap ... */
5904 104503 : if (!walk_tree (expr_p, gimplify_init_ctor_preeval_1, data, NULL))
5905 : return;
5906 :
5907 : /* ... and if found, force the value into a temporary. */
5908 517 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
5909 : }
5910 :
5911 : /* A subroutine of gimplify_init_ctor_eval. Create a loop for
5912 : a RANGE_EXPR in a CONSTRUCTOR for an array.
5913 :
5914 : var = lower;
5915 : loop_entry:
5916 : object[var] = value;
5917 : if (var == upper)
5918 : goto loop_exit;
5919 : var = var + 1;
5920 : goto loop_entry;
5921 : loop_exit:
5922 :
5923 : We increment var _after_ the loop exit check because we might otherwise
5924 : fail if upper == TYPE_MAX_VALUE (type for upper).
5925 :
5926 : Note that we never have to deal with SAVE_EXPRs here, because this has
5927 : already been taken care of for us, in gimplify_init_ctor_preeval(). */
5928 :
5929 : static void gimplify_init_ctor_eval (tree, vec<constructor_elt, va_gc> *,
5930 : gimple_seq *, bool);
5931 :
5932 : static void
5933 437 : gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
5934 : tree value, tree array_elt_type,
5935 : gimple_seq *pre_p, bool cleared)
5936 : {
5937 437 : tree loop_entry_label, loop_exit_label, fall_thru_label;
5938 437 : tree var, var_type, cref, tmp;
5939 :
5940 437 : loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
5941 437 : loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
5942 437 : fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
5943 :
5944 : /* Create and initialize the index variable. */
5945 437 : var_type = TREE_TYPE (upper);
5946 437 : var = create_tmp_var (var_type);
5947 437 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
5948 :
5949 : /* Add the loop entry label. */
5950 437 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
5951 :
5952 : /* Build the reference. */
5953 437 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
5954 : var, NULL_TREE, NULL_TREE);
5955 :
5956 : /* If we are a constructor, just call gimplify_init_ctor_eval to do
5957 : the store. Otherwise just assign value to the reference. */
5958 :
5959 437 : if (TREE_CODE (value) == CONSTRUCTOR)
5960 : /* NB we might have to call ourself recursively through
5961 : gimplify_init_ctor_eval if the value is a constructor. */
5962 120 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
5963 : pre_p, cleared);
5964 : else
5965 : {
5966 317 : if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue)
5967 : != GS_ERROR)
5968 317 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
5969 : }
5970 :
5971 : /* We exit the loop when the index var is equal to the upper bound. */
5972 874 : gimplify_seq_add_stmt (pre_p,
5973 437 : gimple_build_cond (EQ_EXPR, var, upper,
5974 : loop_exit_label, fall_thru_label));
5975 :
5976 437 : gimplify_seq_add_stmt (pre_p, gimple_build_label (fall_thru_label));
5977 :
5978 : /* Otherwise, increment the index var... */
5979 437 : tmp = build2 (PLUS_EXPR, var_type, var,
5980 : fold_convert (var_type, integer_one_node));
5981 437 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
5982 :
5983 : /* ...and jump back to the loop entry. */
5984 437 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
5985 :
5986 : /* Add the loop exit label. */
5987 437 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
5988 437 : }
5989 :
5990 : /* A subroutine of gimplify_init_constructor. Generate individual
5991 : MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the
5992 : assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the
5993 : CONSTRUCTOR. CLEARED is true if the entire LHS object has been
5994 : zeroed first. */
5995 :
5996 : static void
5997 1234701 : gimplify_init_ctor_eval (tree object, vec<constructor_elt, va_gc> *elts,
5998 : gimple_seq *pre_p, bool cleared)
5999 : {
6000 1234701 : tree array_elt_type = NULL;
6001 1234701 : unsigned HOST_WIDE_INT ix;
6002 1234701 : tree purpose, value;
6003 :
6004 1234701 : if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
6005 139252 : array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
6006 :
6007 4590192 : FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
6008 : {
6009 3355491 : tree cref;
6010 :
6011 : /* NULL values are created above for gimplification errors. */
6012 3355491 : if (value == NULL)
6013 317673 : continue;
6014 :
6015 3355491 : if (cleared && initializer_zerop (value))
6016 317074 : continue;
6017 :
6018 : /* ??? Here's to hoping the front end fills in all of the indices,
6019 : so we don't have to figure out what's missing ourselves. */
6020 3038417 : gcc_assert (purpose);
6021 :
6022 : /* Skip zero-sized fields, unless value has side-effects. This can
6023 : happen with calls to functions returning a empty type, which
6024 : we shouldn't discard. As a number of downstream passes don't
6025 : expect sets of empty type fields, we rely on the gimplification of
6026 : the MODIFY_EXPR we make below to drop the assignment statement. */
6027 3038417 : if (!TREE_SIDE_EFFECTS (value)
6028 2745679 : && TREE_CODE (purpose) == FIELD_DECL
6029 5319447 : && is_empty_type (TREE_TYPE (purpose)))
6030 162 : continue;
6031 :
6032 : /* If we have a RANGE_EXPR, we have to build a loop to assign the
6033 : whole range. */
6034 3038255 : if (TREE_CODE (purpose) == RANGE_EXPR)
6035 : {
6036 447 : tree lower = TREE_OPERAND (purpose, 0);
6037 447 : tree upper = TREE_OPERAND (purpose, 1);
6038 :
6039 : /* If the lower bound is equal to upper, just treat it as if
6040 : upper was the index. */
6041 447 : if (simple_cst_equal (lower, upper))
6042 : purpose = upper;
6043 : else
6044 : {
6045 437 : gimplify_init_ctor_eval_range (object, lower, upper, value,
6046 : array_elt_type, pre_p, cleared);
6047 437 : continue;
6048 : }
6049 : }
6050 :
6051 3037818 : if (array_elt_type)
6052 : {
6053 : /* Do not use bitsizetype for ARRAY_REF indices. */
6054 554655 : if (TYPE_DOMAIN (TREE_TYPE (object)))
6055 554655 : purpose
6056 554655 : = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
6057 : purpose);
6058 554655 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
6059 : purpose, NULL_TREE, NULL_TREE);
6060 : }
6061 : else
6062 : {
6063 2483163 : gcc_assert (TREE_CODE (purpose) == FIELD_DECL);
6064 2483163 : cref = build3 (COMPONENT_REF, TREE_TYPE (purpose),
6065 : unshare_expr (object), purpose, NULL_TREE);
6066 : }
6067 :
6068 3037818 : if (TREE_CODE (value) == CONSTRUCTOR
6069 3037818 : && TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE)
6070 291086 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
6071 : pre_p, cleared);
6072 2746732 : else if (TREE_CODE (value) == RAW_DATA_CST)
6073 : {
6074 43 : if (RAW_DATA_LENGTH (value) <= 32)
6075 : {
6076 13 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value);
6077 : ++i)
6078 12 : if (!cleared || RAW_DATA_POINTER (value)[i])
6079 : {
6080 12 : if (i)
6081 : {
6082 11 : tree p
6083 11 : = fold_build2 (PLUS_EXPR, TREE_TYPE (purpose),
6084 : purpose,
6085 : build_int_cst (TREE_TYPE (purpose),
6086 : i));
6087 11 : cref = build4 (ARRAY_REF, array_elt_type,
6088 : unshare_expr (object), p, NULL_TREE,
6089 : NULL_TREE);
6090 : }
6091 12 : tree init
6092 12 : = build2 (INIT_EXPR, TREE_TYPE (cref), cref,
6093 12 : build_int_cst (TREE_TYPE (value),
6094 12 : RAW_DATA_UCHAR_ELT (value, i)));
6095 12 : gimplify_and_add (init, pre_p);
6096 12 : ggc_free (init);
6097 : }
6098 : }
6099 : else
6100 : {
6101 42 : tree rtype = build_array_type_nelts (TREE_TYPE (value),
6102 42 : RAW_DATA_LENGTH (value));
6103 42 : tree rctor = build_constructor_single (rtype, bitsize_zero_node,
6104 : value);
6105 42 : tree addr = build_fold_addr_expr (cref);
6106 42 : cref = build2 (MEM_REF, rtype, addr,
6107 : build_int_cst (ptr_type_node, 0));
6108 42 : rctor = tree_output_constant_def (rctor);
6109 42 : if (!useless_type_conversion_p (rtype, TREE_TYPE (rctor)))
6110 4 : rctor = build1 (VIEW_CONVERT_EXPR, rtype, rctor);
6111 42 : if (gimplify_expr (&cref, pre_p, NULL, is_gimple_lvalue,
6112 : fb_lvalue) != GS_ERROR)
6113 84 : gimplify_seq_add_stmt (pre_p,
6114 42 : gimple_build_assign (cref, rctor));
6115 : }
6116 : }
6117 : else
6118 : {
6119 2746689 : tree init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
6120 2746689 : gimplify_and_add (init, pre_p);
6121 2746689 : ggc_free (init);
6122 : }
6123 : }
6124 1234701 : }
6125 :
6126 : /* Return the appropriate RHS predicate for this LHS. */
6127 :
6128 : gimple_predicate
6129 48428227 : rhs_predicate_for (tree lhs)
6130 : {
6131 48428227 : if (is_gimple_reg (lhs))
6132 : return is_gimple_reg_rhs_or_call;
6133 : else
6134 11384935 : return is_gimple_mem_rhs_or_call;
6135 : }
6136 :
6137 : /* Return the initial guess for an appropriate RHS predicate for this LHS,
6138 : before the LHS has been gimplified. */
6139 :
6140 : static gimple_predicate
6141 47301476 : initial_rhs_predicate_for (tree lhs)
6142 : {
6143 47301476 : if (is_gimple_reg_type (TREE_TYPE (lhs)))
6144 : return is_gimple_reg_rhs_or_call;
6145 : else
6146 2354251 : return is_gimple_mem_rhs_or_call;
6147 : }
6148 :
6149 : /* Gimplify a C99 compound literal expression. This just means adding
6150 : the DECL_EXPR before the current statement and using its anonymous
6151 : decl instead. */
6152 :
6153 : static enum gimplify_status
6154 37190 : gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
6155 : bool (*gimple_test_f) (tree),
6156 : fallback_t fallback)
6157 : {
6158 37190 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
6159 37190 : tree decl = DECL_EXPR_DECL (decl_s);
6160 37190 : tree init = DECL_INITIAL (decl);
6161 : /* Mark the decl as addressable if the compound literal
6162 : expression is addressable now, otherwise it is marked too late
6163 : after we gimplify the initialization expression. */
6164 37190 : if (TREE_ADDRESSABLE (*expr_p))
6165 542 : TREE_ADDRESSABLE (decl) = 1;
6166 : /* Otherwise, if we don't need an lvalue and have a literal directly
6167 : substitute it. Check if it matches the gimple predicate, as
6168 : otherwise we'd generate a new temporary, and we can as well just
6169 : use the decl we already have. */
6170 36648 : else if (!TREE_ADDRESSABLE (decl)
6171 36648 : && !TREE_THIS_VOLATILE (decl)
6172 36643 : && init
6173 36635 : && (fallback & fb_lvalue) == 0
6174 73131 : && gimple_test_f (init))
6175 : {
6176 35395 : *expr_p = init;
6177 35395 : return GS_OK;
6178 : }
6179 :
6180 : /* If the decl is not addressable, then it is being used in some
6181 : expression or on the right hand side of a statement, and it can
6182 : be put into a readonly data section. */
6183 1795 : if (!TREE_ADDRESSABLE (decl) && (fallback & fb_lvalue) == 0)
6184 1093 : TREE_READONLY (decl) = 1;
6185 :
6186 : /* This decl isn't mentioned in the enclosing block, so add it to the
6187 : list of temps. FIXME it seems a bit of a kludge to say that
6188 : anonymous artificial vars aren't pushed, but everything else is. */
6189 1795 : if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
6190 2 : gimple_add_tmp_var (decl);
6191 :
6192 1795 : gimplify_and_add (decl_s, pre_p);
6193 1795 : *expr_p = decl;
6194 1795 : return GS_OK;
6195 : }
6196 :
6197 : /* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
6198 : return a new CONSTRUCTOR if something changed. */
6199 :
6200 : static tree
6201 1836632 : optimize_compound_literals_in_ctor (tree orig_ctor)
6202 : {
6203 1836632 : tree ctor = orig_ctor;
6204 1836632 : vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
6205 1836632 : unsigned int idx, num = vec_safe_length (elts);
6206 :
6207 6140241 : for (idx = 0; idx < num; idx++)
6208 : {
6209 4303609 : tree value = (*elts)[idx].value;
6210 4303609 : tree newval = value;
6211 4303609 : if (TREE_CODE (value) == CONSTRUCTOR)
6212 528025 : newval = optimize_compound_literals_in_ctor (value);
6213 3775584 : else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
6214 : {
6215 103 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
6216 103 : tree decl = DECL_EXPR_DECL (decl_s);
6217 103 : tree init = DECL_INITIAL (decl);
6218 :
6219 103 : if (!TREE_ADDRESSABLE (value)
6220 103 : && !TREE_ADDRESSABLE (decl)
6221 103 : && init
6222 103 : && TREE_CODE (init) == CONSTRUCTOR)
6223 52 : newval = optimize_compound_literals_in_ctor (init);
6224 : }
6225 4303609 : if (newval == value)
6226 4303549 : continue;
6227 :
6228 60 : if (ctor == orig_ctor)
6229 : {
6230 49 : ctor = copy_node (orig_ctor);
6231 98 : CONSTRUCTOR_ELTS (ctor) = vec_safe_copy (elts);
6232 49 : elts = CONSTRUCTOR_ELTS (ctor);
6233 : }
6234 60 : (*elts)[idx].value = newval;
6235 : }
6236 1836632 : return ctor;
6237 : }
6238 :
6239 : /* A subroutine of gimplify_modify_expr. Break out elements of a
6240 : CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
6241 :
6242 : Note that we still need to clear any elements that don't have explicit
6243 : initializers, so if not all elements are initialized we keep the
6244 : original MODIFY_EXPR, we just remove all of the constructor elements.
6245 :
6246 : If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
6247 : GS_ERROR if we would have to create a temporary when gimplifying
6248 : this constructor. Otherwise, return GS_OK.
6249 :
6250 : If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
6251 :
6252 : static enum gimplify_status
6253 1308555 : gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
6254 : bool want_value, bool notify_temp_creation)
6255 : {
6256 1308555 : tree object, ctor, type;
6257 1308555 : enum gimplify_status ret;
6258 1308555 : vec<constructor_elt, va_gc> *elts;
6259 1308555 : bool cleared = false;
6260 1308555 : bool is_empty_ctor = false;
6261 1308555 : bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR);
6262 :
6263 1308555 : gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
6264 :
6265 1308555 : if (!notify_temp_creation)
6266 : {
6267 1300357 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
6268 : is_gimple_lvalue, fb_lvalue);
6269 1300357 : if (ret == GS_ERROR)
6270 : return ret;
6271 : }
6272 :
6273 1308555 : object = TREE_OPERAND (*expr_p, 0);
6274 1308555 : ctor = TREE_OPERAND (*expr_p, 1)
6275 1308555 : = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
6276 1308555 : type = TREE_TYPE (ctor);
6277 1308555 : elts = CONSTRUCTOR_ELTS (ctor);
6278 1308555 : ret = GS_ALL_DONE;
6279 :
6280 1308555 : switch (TREE_CODE (type))
6281 : {
6282 1301251 : case RECORD_TYPE:
6283 1301251 : case UNION_TYPE:
6284 1301251 : case QUAL_UNION_TYPE:
6285 1301251 : case ARRAY_TYPE:
6286 1301251 : {
6287 : /* Use readonly data for initializers of this or smaller size
6288 : regardless of the num_nonzero_elements / num_unique_nonzero_elements
6289 : ratio. */
6290 1301251 : const HOST_WIDE_INT min_unique_size = 64;
6291 : /* If num_nonzero_elements / num_unique_nonzero_elements ratio
6292 : is smaller than this, use readonly data. */
6293 1301251 : const int unique_nonzero_ratio = 8;
6294 : /* True if a single access of the object must be ensured. This is the
6295 : case if the target is volatile, the type is non-addressable and more
6296 : than one field need to be assigned. */
6297 1301251 : const bool ensure_single_access
6298 1301251 : = TREE_THIS_VOLATILE (object)
6299 255 : && !TREE_ADDRESSABLE (type)
6300 1301454 : && vec_safe_length (elts) > 1;
6301 1301251 : struct gimplify_init_ctor_preeval_data preeval_data;
6302 1301251 : HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
6303 1301251 : HOST_WIDE_INT num_unique_nonzero_elements;
6304 1301251 : ctor_completeness complete_p;
6305 1301251 : bool valid_const_initializer;
6306 :
6307 : /* Aggregate types must lower constructors to initialization of
6308 : individual elements. The exception is that a CONSTRUCTOR node
6309 : with no elements indicates zero-initialization of the whole. */
6310 1301251 : if (vec_safe_is_empty (elts))
6311 : {
6312 328068 : if (notify_temp_creation)
6313 9781 : return GS_OK;
6314 :
6315 : /* The var will be initialized and so appear on lhs of
6316 : assignment, it can't be TREE_READONLY anymore. */
6317 328020 : if (VAR_P (object))
6318 182928 : TREE_READONLY (object) = 0;
6319 :
6320 : is_empty_ctor = true;
6321 330604 : break;
6322 : }
6323 :
6324 : /* Fetch information about the constructor to direct later processing.
6325 : We might want to make static versions of it in various cases, and
6326 : can only do so if it known to be a valid constant initializer. */
6327 973183 : valid_const_initializer
6328 973183 : = categorize_ctor_elements (ctor, &num_nonzero_elements,
6329 : &num_unique_nonzero_elements,
6330 : &num_ctor_elements, &complete_p);
6331 :
6332 : /* If a const aggregate variable is being initialized, then it
6333 : should never be a lose to promote the variable to be static. */
6334 973183 : if (valid_const_initializer
6335 595806 : && num_nonzero_elements > 1
6336 443565 : && TREE_READONLY (object)
6337 5204 : && VAR_P (object)
6338 4827 : && !DECL_REGISTER (object)
6339 4820 : && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)
6340 3837 : || DECL_MERGEABLE (object))
6341 : /* For ctors that have many repeated nonzero elements
6342 : represented through RANGE_EXPRs, prefer initializing
6343 : those through runtime loops over copies of large amounts
6344 : of data from readonly data section. */
6345 973183 : && (num_unique_nonzero_elements
6346 2584 : > num_nonzero_elements / unique_nonzero_ratio
6347 0 : || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
6348 : <= (unsigned HOST_WIDE_INT) min_unique_size)))
6349 : {
6350 2584 : if (notify_temp_creation)
6351 : return GS_ERROR;
6352 :
6353 2584 : DECL_INITIAL (object) = ctor;
6354 2584 : TREE_STATIC (object) = 1;
6355 2584 : if (!DECL_NAME (object) || DECL_NAMELESS (object))
6356 2122 : DECL_NAME (object) = create_tmp_var_name ("C");
6357 2584 : walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL);
6358 :
6359 : /* ??? C++ doesn't automatically append a .<number> to the
6360 : assembler name, and even when it does, it looks at FE private
6361 : data structures to figure out what that number should be,
6362 : which are not set for this variable. I suppose this is
6363 : important for local statics for inline functions, which aren't
6364 : "local" in the object file sense. So in order to get a unique
6365 : TU-local symbol, we must invoke the lhd version now. */
6366 2584 : lhd_set_decl_assembler_name (object);
6367 :
6368 2584 : *expr_p = NULL_TREE;
6369 2584 : break;
6370 : }
6371 :
6372 : /* The var will be initialized and so appear on lhs of
6373 : assignment, it can't be TREE_READONLY anymore. */
6374 970599 : if (VAR_P (object) && !notify_temp_creation)
6375 765871 : TREE_READONLY (object) = 0;
6376 :
6377 : /* If there are "lots" of initialized elements, even discounting
6378 : those that are not address constants (and thus *must* be
6379 : computed at runtime), then partition the constructor into
6380 : constant and non-constant parts. Block copy the constant
6381 : parts in, then generate code for the non-constant parts. */
6382 : /* TODO. There's code in cp/typeck.cc to do this. */
6383 :
6384 970599 : if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
6385 : /* store_constructor will ignore the clearing of variable-sized
6386 : objects. Initializers for such objects must explicitly set
6387 : every field that needs to be set. */
6388 : cleared = false;
6389 970579 : else if (complete_p.sparse)
6390 : /* If the constructor isn't complete, clear the whole object
6391 : beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
6392 :
6393 : ??? This ought not to be needed. For any element not present
6394 : in the initializer, we should simply set them to zero. Except
6395 : we'd need to *find* the elements that are not present, and that
6396 : requires trickery to avoid quadratic compile-time behavior in
6397 : large cases or excessive memory use in small cases. */
6398 183017 : cleared = !CONSTRUCTOR_NO_CLEARING (ctor);
6399 787562 : else if (num_ctor_elements - num_nonzero_elements
6400 787562 : > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
6401 787562 : && num_nonzero_elements < num_ctor_elements / 4)
6402 : /* If there are "lots" of zeros, it's more efficient to clear
6403 : the memory and then set the nonzero elements. */
6404 : cleared = true;
6405 786688 : else if (ensure_single_access && num_nonzero_elements == 0)
6406 : /* If a single access to the target must be ensured and all elements
6407 : are zero, then it's optimal to clear whatever their number. */
6408 : cleared = true;
6409 : /* If the object is small enough to go in registers, and it's
6410 : not required to be constructed in memory, clear it first.
6411 : That will avoid wasting cycles preserving any padding bits
6412 : that might be there, and if there aren't any, the compiler
6413 : is smart enough to optimize the clearing out. */
6414 786679 : else if ((complete_p.sparse || complete_p.padded_union
6415 786455 : || complete_p.padded_non_union)
6416 13805 : && !TREE_ADDRESSABLE (ctor)
6417 13719 : && !TREE_THIS_VOLATILE (object)
6418 13716 : && (TYPE_MODE (type) != BLKmode || TYPE_NO_FORCE_BLK (type))
6419 793443 : && optimize)
6420 : cleared = true;
6421 : else
6422 : cleared = false;
6423 :
6424 : /* If there are "lots" of initialized elements, and all of them
6425 : are valid address constants, then the entire initializer can
6426 : be dropped to memory, and then memcpy'd out. Don't do this
6427 : for sparse arrays, though, as it's more efficient to follow
6428 : the standard CONSTRUCTOR behavior of memset followed by
6429 : individual element initialization. Also don't do this for small
6430 : all-zero initializers (which aren't big enough to merit
6431 : clearing), and don't try to make bitwise copies of
6432 : TREE_ADDRESSABLE types. */
6433 970599 : if (valid_const_initializer
6434 593222 : && !complete_p.sparse
6435 425201 : && !(cleared || num_nonzero_elements == 0)
6436 332165 : && !TREE_ADDRESSABLE (type))
6437 : {
6438 330614 : HOST_WIDE_INT size = int_size_in_bytes (type);
6439 330614 : unsigned int align;
6440 :
6441 : /* ??? We can still get unbounded array types, at least
6442 : from the C++ front end. This seems wrong, but attempt
6443 : to work around it for now. */
6444 330614 : if (size < 0)
6445 : {
6446 9 : size = int_size_in_bytes (TREE_TYPE (object));
6447 9 : if (size >= 0)
6448 0 : TREE_TYPE (ctor) = type = TREE_TYPE (object);
6449 : }
6450 :
6451 : /* Find the maximum alignment we can assume for the object. */
6452 : /* ??? Make use of DECL_OFFSET_ALIGN. */
6453 330614 : if (DECL_P (object))
6454 316858 : align = DECL_ALIGN (object);
6455 : else
6456 13756 : align = TYPE_ALIGN (type);
6457 :
6458 : /* Do a block move either if the size is so small as to make
6459 : each individual move a sub-unit move on average, or if it
6460 : is so large as to make individual moves inefficient. */
6461 330614 : if (size > 0
6462 330605 : && num_nonzero_elements > 1
6463 : /* For ctors that have many repeated nonzero elements
6464 : represented through RANGE_EXPRs, prefer initializing
6465 : those through runtime loops over copies of large amounts
6466 : of data from readonly data section. */
6467 298184 : && (num_unique_nonzero_elements
6468 298184 : > num_nonzero_elements / unique_nonzero_ratio
6469 56 : || size <= min_unique_size)
6470 628742 : && (size < num_nonzero_elements
6471 298022 : || !can_move_by_pieces (size, align)))
6472 : {
6473 2840 : if (notify_temp_creation)
6474 : return GS_ERROR;
6475 :
6476 1422 : walk_tree (&ctor, force_labels_r, NULL, NULL);
6477 1422 : ctor = tree_output_constant_def (ctor);
6478 1422 : if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
6479 0 : ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
6480 1422 : TREE_OPERAND (*expr_p, 1) = ctor;
6481 :
6482 : /* This is no longer an assignment of a CONSTRUCTOR, but
6483 : we still may have processing to do on the LHS. So
6484 : pretend we didn't do anything here to let that happen. */
6485 1422 : return GS_UNHANDLED;
6486 : }
6487 : }
6488 :
6489 963329 : if (!cleared)
6490 : {
6491 777804 : if (complete_p.padded_non_union
6492 7128 : && warn_zero_init_padding_bits >= ZERO_INIT_PADDING_BITS_ALL)
6493 12 : warning (OPT_Wzero_init_padding_bits_,
6494 : "padding might not be initialized to zero; "
6495 : "if code relies on it being zero, consider "
6496 : "using %<-fzero-init-padding-bits=all%>");
6497 777792 : else if (complete_p.padded_union
6498 116 : && warn_zero_init_padding_bits
6499 : >= ZERO_INIT_PADDING_BITS_UNIONS)
6500 14 : warning (OPT_Wzero_init_padding_bits_,
6501 : "padding might not be initialized to zero; "
6502 : "if code relies on it being zero, consider "
6503 : "using %<-fzero-init-padding-bits=unions%> "
6504 : "or %<-fzero-init-padding-bits=all%>");
6505 : }
6506 :
6507 : /* If a single access to the target must be ensured and there are
6508 : nonzero elements or the zero elements are not assigned en masse,
6509 : initialize the target from a temporary. */
6510 967759 : if (ensure_single_access && (num_nonzero_elements > 0 || !cleared))
6511 : {
6512 167 : if (notify_temp_creation)
6513 : return GS_ERROR;
6514 :
6515 161 : tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type));
6516 161 : TREE_OPERAND (*expr_p, 0) = temp;
6517 161 : *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
6518 : *expr_p,
6519 : build2 (MODIFY_EXPR, void_type_node,
6520 : object, temp));
6521 161 : return GS_OK;
6522 : }
6523 :
6524 967592 : if (notify_temp_creation)
6525 : return GS_OK;
6526 :
6527 : /* If there are nonzero elements and if needed, pre-evaluate to capture
6528 : elements overlapping with the lhs into temporaries. We must do this
6529 : before clearing to fetch the values before they are zeroed-out. */
6530 960866 : if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
6531 : {
6532 215678 : preeval_data.lhs_base_decl = get_base_address (object);
6533 215678 : if (!DECL_P (preeval_data.lhs_base_decl))
6534 41151 : preeval_data.lhs_base_decl = NULL;
6535 215678 : preeval_data.lhs_alias_set = get_alias_set (object);
6536 :
6537 215678 : gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
6538 : pre_p, post_p, &preeval_data);
6539 : }
6540 :
6541 960866 : bool ctor_has_side_effects_p
6542 960866 : = TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1));
6543 :
6544 960866 : if (cleared)
6545 : {
6546 : /* Zap the CONSTRUCTOR element list, which simplifies this case.
6547 : Note that we still have to gimplify, in order to handle the
6548 : case of variable sized types. Avoid shared tree structures. */
6549 189754 : CONSTRUCTOR_ELTS (ctor) = NULL;
6550 189754 : TREE_SIDE_EFFECTS (ctor) = 0;
6551 189754 : object = unshare_expr (object);
6552 189754 : gimplify_stmt (expr_p, pre_p);
6553 : }
6554 :
6555 : /* If we have not block cleared the object, or if there are nonzero
6556 : elements in the constructor, or if the constructor has side effects,
6557 : add assignments to the individual scalar fields of the object. */
6558 189754 : if (!cleared
6559 189754 : || num_nonzero_elements > 0
6560 17766 : || ctor_has_side_effects_p)
6561 943495 : gimplify_init_ctor_eval (object, elts, pre_p, cleared);
6562 :
6563 960866 : *expr_p = NULL_TREE;
6564 : }
6565 960866 : break;
6566 :
6567 0 : case COMPLEX_TYPE:
6568 0 : {
6569 0 : tree r, i;
6570 :
6571 0 : if (notify_temp_creation)
6572 : return GS_OK;
6573 :
6574 : /* Extract the real and imaginary parts out of the ctor. */
6575 0 : gcc_assert (elts->length () == 2);
6576 0 : r = (*elts)[0].value;
6577 0 : i = (*elts)[1].value;
6578 0 : if (r == NULL || i == NULL)
6579 : {
6580 0 : tree zero = build_zero_cst (TREE_TYPE (type));
6581 0 : if (r == NULL)
6582 0 : r = zero;
6583 0 : if (i == NULL)
6584 0 : i = zero;
6585 : }
6586 :
6587 : /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to
6588 : represent creation of a complex value. */
6589 0 : if (TREE_CONSTANT (r) && TREE_CONSTANT (i))
6590 : {
6591 0 : ctor = build_complex (type, r, i);
6592 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6593 : }
6594 : else
6595 : {
6596 0 : ctor = build2 (COMPLEX_EXPR, type, r, i);
6597 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6598 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1),
6599 : pre_p,
6600 : post_p,
6601 0 : rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
6602 : fb_rvalue);
6603 : }
6604 : }
6605 : break;
6606 :
6607 7304 : case VECTOR_TYPE:
6608 7304 : {
6609 7304 : unsigned HOST_WIDE_INT ix;
6610 7304 : constructor_elt *ce;
6611 :
6612 7304 : if (notify_temp_creation)
6613 1308555 : return GS_OK;
6614 :
6615 : /* Vector types use CONSTRUCTOR all the way through gimple
6616 : compilation as a general initializer. */
6617 67322 : FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
6618 : {
6619 60018 : enum gimplify_status tret;
6620 60018 : tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
6621 : fb_rvalue);
6622 60018 : if (tret == GS_ERROR)
6623 : ret = GS_ERROR;
6624 60017 : else if (TREE_STATIC (ctor)
6625 60049 : && !initializer_constant_valid_p (ce->value,
6626 32 : TREE_TYPE (ce->value)))
6627 32 : TREE_STATIC (ctor) = 0;
6628 : }
6629 7304 : recompute_constructor_flags (ctor);
6630 :
6631 : /* Go ahead and simplify constant constructors to VECTOR_CST. */
6632 7304 : if (TREE_CONSTANT (ctor))
6633 : {
6634 2705 : bool constant_p = true;
6635 : tree value;
6636 :
6637 : /* Even when ctor is constant, it might contain non-*_CST
6638 : elements, such as addresses or trapping values like
6639 : 1.0/0.0 - 1.0/0.0. Such expressions don't belong
6640 : in VECTOR_CST nodes. */
6641 2705 : FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
6642 2483 : if (!CONSTANT_CLASS_P (value))
6643 : {
6644 : constant_p = false;
6645 : break;
6646 : }
6647 :
6648 222 : if (constant_p)
6649 : {
6650 222 : TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts);
6651 222 : break;
6652 : }
6653 : }
6654 :
6655 7082 : if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
6656 918 : TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
6657 : }
6658 : break;
6659 :
6660 0 : default:
6661 : /* So how did we get a CONSTRUCTOR for a scalar type? */
6662 0 : gcc_unreachable ();
6663 : }
6664 :
6665 1298774 : if (ret == GS_ERROR)
6666 : return GS_ERROR;
6667 : /* If we have gimplified both sides of the initializer but have
6668 : not emitted an assignment, do so now. */
6669 1298773 : if (*expr_p
6670 : /* If the type is an empty type, we don't need to emit the
6671 : assignment. */
6672 1298773 : && !is_empty_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
6673 : {
6674 331485 : tree lhs = TREE_OPERAND (*expr_p, 0);
6675 331485 : tree rhs = TREE_OPERAND (*expr_p, 1);
6676 331485 : if (want_value && object == lhs)
6677 12 : lhs = unshare_expr (lhs);
6678 331485 : gassign *init = gimple_build_assign (lhs, rhs);
6679 331485 : gimplify_seq_add_stmt (pre_p, init);
6680 : }
6681 1298773 : if (want_value)
6682 : {
6683 19 : *expr_p = object;
6684 19 : ret = GS_OK;
6685 : }
6686 : else
6687 : {
6688 1298754 : *expr_p = NULL;
6689 1298754 : ret = GS_ALL_DONE;
6690 : }
6691 :
6692 : /* If the user requests to initialize automatic variables, we
6693 : should initialize paddings inside the variable. Add a call to
6694 : __builtin_clear_pading (&object, 0, for_auto_init = true) to
6695 : initialize paddings of object always to zero regardless of
6696 : INIT_TYPE. Note, we will not insert this call if the aggregate
6697 : variable has be completely cleared already or it's initialized
6698 : with an empty constructor. We cannot insert this call if the
6699 : variable is a gimple register since __builtin_clear_padding will take
6700 : the address of the variable. As a result, if a long double/_Complex long
6701 : double variable will be spilled into stack later, its padding cannot
6702 : be cleared with __builtin_clear_padding. We should clear its padding
6703 : when it is spilled into memory. */
6704 1298773 : if (is_init_expr
6705 920489 : && !is_gimple_reg (object)
6706 915927 : && clear_padding_type_may_have_padding_p (type)
6707 873431 : && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
6708 217350 : || !AGGREGATE_TYPE_P (type))
6709 656081 : && var_needs_auto_init_p (object)
6710 1319050 : && flag_auto_var_init != AUTO_INIT_CXX26)
6711 41 : gimple_add_padding_init_for_auto_var (object, false, pre_p);
6712 :
6713 : return ret;
6714 : }
6715 :
6716 : /* Given a pointer value OP0, return a simplified version of an
6717 : indirection through OP0, or NULL_TREE if no simplification is
6718 : possible. This may only be applied to a rhs of an expression.
6719 : Note that the resulting type may be different from the type pointed
6720 : to in the sense that it is still compatible from the langhooks
6721 : point of view. */
6722 :
6723 : static tree
6724 515738 : gimple_fold_indirect_ref_rhs (tree t)
6725 : {
6726 0 : return gimple_fold_indirect_ref (t);
6727 : }
6728 :
6729 : /* Subroutine of gimplify_modify_expr to do simplifications of
6730 : MODIFY_EXPRs based on the code of the RHS. We loop for as long as
6731 : something changes. */
6732 :
6733 : static enum gimplify_status
6734 96607429 : gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
6735 : gimple_seq *pre_p, gimple_seq *post_p,
6736 : bool want_value)
6737 : {
6738 96607429 : enum gimplify_status ret = GS_UNHANDLED;
6739 97229736 : bool changed;
6740 :
6741 95781449 : do
6742 : {
6743 97229736 : changed = false;
6744 97229736 : switch (TREE_CODE (*from_p))
6745 : {
6746 11897748 : case VAR_DECL:
6747 : /* If we're assigning from a read-only variable initialized with
6748 : a constructor and not volatile, do the direct assignment from
6749 : the constructor, but only if the target is not volatile either
6750 : since this latter assignment might end up being done on a per
6751 : field basis. However, if the target is volatile and the type
6752 : is aggregate and non-addressable, gimplify_init_constructor
6753 : knows that it needs to ensure a single access to the target
6754 : and it will return GS_OK only in this case. */
6755 11897748 : if (TREE_READONLY (*from_p)
6756 92130 : && DECL_INITIAL (*from_p)
6757 61086 : && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR
6758 8198 : && !TREE_THIS_VOLATILE (*from_p)
6759 11905946 : && (!TREE_THIS_VOLATILE (*to_p)
6760 6 : || (AGGREGATE_TYPE_P (TREE_TYPE (*to_p))
6761 6 : && !TREE_ADDRESSABLE (TREE_TYPE (*to_p)))))
6762 : {
6763 8198 : tree old_from = *from_p;
6764 8198 : enum gimplify_status subret;
6765 :
6766 : /* Move the constructor into the RHS. */
6767 8198 : *from_p = unshare_expr (DECL_INITIAL (*from_p));
6768 :
6769 : /* Let's see if gimplify_init_constructor will need to put
6770 : it in memory. */
6771 8198 : subret = gimplify_init_constructor (expr_p, NULL, NULL,
6772 : false, true);
6773 8198 : if (subret == GS_ERROR)
6774 : {
6775 : /* If so, revert the change. */
6776 1424 : *from_p = old_from;
6777 : }
6778 : else
6779 : {
6780 : ret = GS_OK;
6781 : changed = true;
6782 : }
6783 : }
6784 : break;
6785 523573 : case INDIRECT_REF:
6786 523573 : if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
6787 : /* If we have code like
6788 :
6789 : *(const A*)(A*)&x
6790 :
6791 : where the type of "x" is a (possibly cv-qualified variant
6792 : of "A"), treat the entire expression as identical to "x".
6793 : This kind of code arises in C++ when an object is bound
6794 : to a const reference, and if "x" is a TARGET_EXPR we want
6795 : to take advantage of the optimization below. But not if
6796 : the type is TREE_ADDRESSABLE; then C++17 says that the
6797 : TARGET_EXPR needs to be a temporary. */
6798 1031476 : if (tree t
6799 515738 : = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)))
6800 : {
6801 120575 : bool volatile_p = TREE_THIS_VOLATILE (*from_p);
6802 120575 : if (TREE_THIS_VOLATILE (t) != volatile_p)
6803 : {
6804 5 : if (DECL_P (t))
6805 0 : t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
6806 : build_fold_addr_expr (t));
6807 5 : if (REFERENCE_CLASS_P (t))
6808 5 : TREE_THIS_VOLATILE (t) = volatile_p;
6809 : }
6810 120575 : *from_p = t;
6811 120575 : ret = GS_OK;
6812 120575 : changed = true;
6813 : }
6814 : break;
6815 :
6816 179178 : case TARGET_EXPR:
6817 179178 : {
6818 : /* If we are initializing something from a TARGET_EXPR, strip the
6819 : TARGET_EXPR and initialize it directly, if possible. This can't
6820 : be done if the initializer is void, since that implies that the
6821 : temporary is set in some non-trivial way.
6822 :
6823 : ??? What about code that pulls out the temp and uses it
6824 : elsewhere? I think that such code never uses the TARGET_EXPR as
6825 : an initializer. If I'm wrong, we'll die because the temp won't
6826 : have any RTL. In that case, I guess we'll need to replace
6827 : references somehow. */
6828 179178 : tree init = TARGET_EXPR_INITIAL (*from_p);
6829 :
6830 179178 : if (init
6831 178462 : && (TREE_CODE (*expr_p) != MODIFY_EXPR
6832 46690 : || !TARGET_EXPR_NO_ELIDE (*from_p))
6833 357434 : && !VOID_TYPE_P (TREE_TYPE (init)))
6834 : {
6835 164586 : *from_p = init;
6836 164586 : ret = GS_OK;
6837 164586 : changed = true;
6838 : }
6839 : }
6840 : break;
6841 :
6842 330008 : case COMPOUND_EXPR:
6843 : /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
6844 : caught. */
6845 330008 : gimplify_compound_expr (from_p, pre_p, true);
6846 330008 : ret = GS_OK;
6847 330008 : changed = true;
6848 330008 : break;
6849 :
6850 1321732 : case CONSTRUCTOR:
6851 : /* If we already made some changes, let the front end have a
6852 : crack at this before we break it down. */
6853 1321732 : if (ret != GS_UNHANDLED)
6854 : break;
6855 :
6856 : /* If we're initializing from a CONSTRUCTOR, break this into
6857 : individual MODIFY_EXPRs. */
6858 1300357 : ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
6859 : false);
6860 1300357 : return ret;
6861 :
6862 223266 : case COND_EXPR:
6863 : /* If we're assigning to a non-register type, push the assignment
6864 : down into the branches. This is mandatory for ADDRESSABLE types,
6865 : since we cannot generate temporaries for such, but it saves a
6866 : copy in other cases as well.
6867 : Also avoid an extra temporary and copy when assigning to
6868 : a register. */
6869 223266 : if (!is_gimple_reg_type (TREE_TYPE (*from_p))
6870 223266 : || (is_gimple_reg (*to_p) && !gimplify_ctxp->allow_rhs_cond_expr))
6871 : {
6872 : /* This code should mirror the code in gimplify_cond_expr. */
6873 141567 : enum tree_code code = TREE_CODE (*expr_p);
6874 141567 : tree cond = *from_p;
6875 141567 : tree result = *to_p;
6876 :
6877 141567 : ret = gimplify_expr (&result, pre_p, post_p,
6878 : is_gimple_lvalue, fb_lvalue);
6879 141567 : if (ret != GS_ERROR)
6880 141567 : ret = GS_OK;
6881 :
6882 : /* If we are going to write RESULT more than once, clear
6883 : TREE_READONLY flag, otherwise we might incorrectly promote
6884 : the variable to static const and initialize it at compile
6885 : time in one of the branches. */
6886 141567 : if (VAR_P (result)
6887 140537 : && TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node
6888 273031 : && TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6889 131372 : TREE_READONLY (result) = 0;
6890 141567 : if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
6891 132358 : TREE_OPERAND (cond, 1)
6892 264716 : = build2 (code, void_type_node, result,
6893 132358 : TREE_OPERAND (cond, 1));
6894 141567 : if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6895 141475 : TREE_OPERAND (cond, 2)
6896 282950 : = build2 (code, void_type_node, unshare_expr (result),
6897 141475 : TREE_OPERAND (cond, 2));
6898 :
6899 141567 : TREE_TYPE (cond) = void_type_node;
6900 141567 : recalculate_side_effects (cond);
6901 :
6902 141567 : if (want_value)
6903 : {
6904 68 : gimplify_and_add (cond, pre_p);
6905 68 : *expr_p = unshare_expr (result);
6906 : }
6907 : else
6908 141499 : *expr_p = cond;
6909 141567 : return ret;
6910 : }
6911 : break;
6912 :
6913 9753467 : case CALL_EXPR:
6914 : /* For calls that return in memory, give *to_p as the CALL_EXPR's
6915 : return slot so that we don't generate a temporary. */
6916 9753467 : if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
6917 9753467 : && aggregate_value_p (*from_p, *from_p))
6918 : {
6919 248932 : bool use_target;
6920 :
6921 248932 : if (!(rhs_predicate_for (*to_p))(*from_p))
6922 : /* If we need a temporary, *to_p isn't accurate. */
6923 : use_target = false;
6924 : /* It's OK to use the return slot directly unless it's an NRV. */
6925 248160 : else if (TREE_CODE (*to_p) == RESULT_DECL
6926 5623 : && DECL_NAME (*to_p) == NULL_TREE
6927 253639 : && needs_to_live_in_memory (*to_p))
6928 : use_target = true;
6929 242681 : else if (is_gimple_reg_type (TREE_TYPE (*to_p))
6930 242681 : || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
6931 : /* Don't force regs into memory. */
6932 : use_target = false;
6933 228371 : else if (TREE_CODE (*expr_p) == INIT_EXPR)
6934 : /* It's OK to use the target directly if it's being
6935 : initialized. */
6936 : use_target = true;
6937 14407 : else if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p)))
6938 : != INTEGER_CST)
6939 : /* Always use the target and thus RSO for variable-sized types.
6940 : GIMPLE cannot deal with a variable-sized assignment
6941 : embedded in a call statement. */
6942 : use_target = true;
6943 14379 : else if (TREE_CODE (*to_p) != SSA_NAME
6944 14379 : && (!is_gimple_variable (*to_p)
6945 11105 : || needs_to_live_in_memory (*to_p)))
6946 : /* Don't use the original target if it's already addressable;
6947 : if its address escapes, and the called function uses the
6948 : NRV optimization, a conforming program could see *to_p
6949 : change before the called function returns; see c++/19317.
6950 : When optimizing, the return_slot pass marks more functions
6951 : as safe after we have escape info. */
6952 : use_target = false;
6953 : else
6954 : use_target = true;
6955 :
6956 : if (use_target)
6957 : {
6958 221569 : CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
6959 221569 : mark_addressable (*to_p);
6960 : }
6961 : }
6962 : break;
6963 :
6964 1561 : case WITH_SIZE_EXPR:
6965 : /* Likewise for calls that return an aggregate of non-constant size,
6966 : since we would not be able to generate a temporary at all. */
6967 1561 : if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
6968 : {
6969 351 : *from_p = TREE_OPERAND (*from_p, 0);
6970 : /* We don't change ret in this case because the
6971 : WITH_SIZE_EXPR might have been added in
6972 : gimplify_modify_expr, so returning GS_OK would lead to an
6973 : infinite loop. */
6974 351 : changed = true;
6975 : }
6976 : break;
6977 :
6978 : /* If we're initializing from a container, push the initialization
6979 : inside it. */
6980 1933 : case CLEANUP_POINT_EXPR:
6981 1933 : case BIND_EXPR:
6982 1933 : case STATEMENT_LIST:
6983 1933 : {
6984 1933 : tree wrap = *from_p;
6985 1933 : tree t;
6986 :
6987 1933 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
6988 : fb_lvalue);
6989 1933 : if (ret != GS_ERROR)
6990 1933 : ret = GS_OK;
6991 :
6992 1933 : t = voidify_wrapper_expr (wrap, *expr_p);
6993 1933 : gcc_assert (t == *expr_p);
6994 :
6995 1933 : if (want_value)
6996 : {
6997 6 : gimplify_and_add (wrap, pre_p);
6998 6 : *expr_p = unshare_expr (*to_p);
6999 : }
7000 : else
7001 1927 : *expr_p = wrap;
7002 : return GS_OK;
7003 : }
7004 :
7005 9466146 : case NOP_EXPR:
7006 : /* Pull out compound literal expressions from a NOP_EXPR.
7007 : Those are created in the C FE to drop qualifiers during
7008 : lvalue conversion. */
7009 9466146 : if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR)
7010 9466146 : && tree_ssa_useless_type_conversion (*from_p))
7011 : {
7012 13 : *from_p = TREE_OPERAND (*from_p, 0);
7013 13 : ret = GS_OK;
7014 13 : changed = true;
7015 : }
7016 : break;
7017 :
7018 4430 : case COMPOUND_LITERAL_EXPR:
7019 4430 : {
7020 4430 : tree complit = TREE_OPERAND (*expr_p, 1);
7021 4430 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
7022 4430 : tree decl = DECL_EXPR_DECL (decl_s);
7023 4430 : tree init = DECL_INITIAL (decl);
7024 :
7025 : /* struct T x = (struct T) { 0, 1, 2 } can be optimized
7026 : into struct T x = { 0, 1, 2 } if the address of the
7027 : compound literal has never been taken. */
7028 4430 : if (!TREE_ADDRESSABLE (complit)
7029 4430 : && !TREE_ADDRESSABLE (decl)
7030 4430 : && init)
7031 : {
7032 4430 : *expr_p = copy_node (*expr_p);
7033 4430 : TREE_OPERAND (*expr_p, 1) = init;
7034 4430 : return GS_OK;
7035 : }
7036 : }
7037 :
7038 : default:
7039 : break;
7040 : }
7041 : }
7042 : while (changed);
7043 :
7044 : return ret;
7045 : }
7046 :
7047 :
7048 : /* Return true if T looks like a valid GIMPLE statement. */
7049 :
7050 : static bool
7051 19030625 : is_gimple_stmt (tree t)
7052 : {
7053 19030625 : const enum tree_code code = TREE_CODE (t);
7054 :
7055 19030625 : switch (code)
7056 : {
7057 1712112 : case NOP_EXPR:
7058 : /* The only valid NOP_EXPR is the empty statement. */
7059 1712112 : return IS_EMPTY_STMT (t);
7060 :
7061 0 : case BIND_EXPR:
7062 0 : case COND_EXPR:
7063 : /* These are only valid if they're void. */
7064 0 : return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
7065 :
7066 : case SWITCH_EXPR:
7067 : case GOTO_EXPR:
7068 : case RETURN_EXPR:
7069 : case LABEL_EXPR:
7070 : case CASE_LABEL_EXPR:
7071 : case TRY_CATCH_EXPR:
7072 : case TRY_FINALLY_EXPR:
7073 : case EH_FILTER_EXPR:
7074 : case CATCH_EXPR:
7075 : case ASM_EXPR:
7076 : case STATEMENT_LIST:
7077 : case OACC_PARALLEL:
7078 : case OACC_KERNELS:
7079 : case OACC_SERIAL:
7080 : case OACC_DATA:
7081 : case OACC_HOST_DATA:
7082 : case OACC_DECLARE:
7083 : case OACC_UPDATE:
7084 : case OACC_ENTER_DATA:
7085 : case OACC_EXIT_DATA:
7086 : case OACC_CACHE:
7087 : case OMP_PARALLEL:
7088 : case OMP_FOR:
7089 : case OMP_SIMD:
7090 : case OMP_DISTRIBUTE:
7091 : case OMP_LOOP:
7092 : case OMP_TILE:
7093 : case OMP_UNROLL:
7094 : case OACC_LOOP:
7095 : case OMP_SCAN:
7096 : case OMP_SCOPE:
7097 : case OMP_DISPATCH:
7098 : case OMP_SECTIONS:
7099 : case OMP_SECTION:
7100 : case OMP_STRUCTURED_BLOCK:
7101 : case OMP_SINGLE:
7102 : case OMP_MASTER:
7103 : case OMP_MASKED:
7104 : case OMP_TASKGROUP:
7105 : case OMP_ORDERED:
7106 : case OMP_CRITICAL:
7107 : case OMP_METADIRECTIVE:
7108 : case OMP_TASK:
7109 : case OMP_TARGET:
7110 : case OMP_TARGET_DATA:
7111 : case OMP_TARGET_UPDATE:
7112 : case OMP_TARGET_ENTER_DATA:
7113 : case OMP_TARGET_EXIT_DATA:
7114 : case OMP_TASKLOOP:
7115 : case OMP_TEAMS:
7116 : /* These are always void. */
7117 : return true;
7118 :
7119 : case CALL_EXPR:
7120 : case MODIFY_EXPR:
7121 : case PREDICT_EXPR:
7122 : /* These are valid regardless of their type. */
7123 : return true;
7124 :
7125 : default:
7126 : return false;
7127 : }
7128 : }
7129 :
7130 :
7131 : /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
7132 : a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
7133 :
7134 : IMPORTANT NOTE: This promotion is performed by introducing a load of the
7135 : other, unmodified part of the complex object just before the total store.
7136 : As a consequence, if the object is still uninitialized, an undefined value
7137 : will be loaded into a register, which may result in a spurious exception
7138 : if the register is floating-point and the value happens to be a signaling
7139 : NaN for example. Then the fully-fledged complex operations lowering pass
7140 : followed by a DCE pass are necessary in order to fix things up. */
7141 :
7142 : static enum gimplify_status
7143 1942 : gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
7144 : bool want_value)
7145 : {
7146 1942 : enum tree_code code, ocode;
7147 1942 : tree lhs, rhs, new_rhs, other, realpart, imagpart;
7148 :
7149 1942 : lhs = TREE_OPERAND (*expr_p, 0);
7150 1942 : rhs = TREE_OPERAND (*expr_p, 1);
7151 1942 : code = TREE_CODE (lhs);
7152 1942 : lhs = TREE_OPERAND (lhs, 0);
7153 :
7154 1942 : ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
7155 1942 : other = build1 (ocode, TREE_TYPE (rhs), lhs);
7156 1942 : suppress_warning (other);
7157 1942 : other = get_formal_tmp_var (other, pre_p);
7158 :
7159 1942 : realpart = code == REALPART_EXPR ? rhs : other;
7160 957 : imagpart = code == REALPART_EXPR ? other : rhs;
7161 :
7162 1942 : if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
7163 0 : new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
7164 : else
7165 1942 : new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
7166 :
7167 1942 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
7168 1942 : *expr_p = (want_value) ? rhs : NULL_TREE;
7169 :
7170 1942 : return GS_ALL_DONE;
7171 : }
7172 :
7173 : /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
7174 :
7175 : modify_expr
7176 : : varname '=' rhs
7177 : | '*' ID '=' rhs
7178 :
7179 : PRE_P points to the list where side effects that must happen before
7180 : *EXPR_P should be stored.
7181 :
7182 : POST_P points to the list where side effects that must happen after
7183 : *EXPR_P should be stored.
7184 :
7185 : WANT_VALUE is nonzero iff we want to use the value of this expression
7186 : in another expression. */
7187 :
7188 : static enum gimplify_status
7189 49865939 : gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
7190 : bool want_value)
7191 : {
7192 49865939 : tree *from_p = &TREE_OPERAND (*expr_p, 1);
7193 49865939 : tree *to_p = &TREE_OPERAND (*expr_p, 0);
7194 49865939 : enum gimplify_status ret = GS_UNHANDLED;
7195 49865939 : gimple *assign;
7196 49865939 : location_t loc = EXPR_LOCATION (*expr_p);
7197 49865939 : gimple_stmt_iterator gsi;
7198 :
7199 49865939 : if (error_operand_p (*from_p) || error_operand_p (*to_p))
7200 : return GS_ERROR;
7201 :
7202 49865911 : gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
7203 : || TREE_CODE (*expr_p) == INIT_EXPR);
7204 :
7205 : /* Trying to simplify a clobber using normal logic doesn't work,
7206 : so handle it here. */
7207 49865911 : if (TREE_CLOBBER_P (*from_p))
7208 : {
7209 559637 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7210 559637 : if (ret == GS_ERROR)
7211 : return ret;
7212 559637 : gcc_assert (!want_value);
7213 559637 : if (!VAR_P (*to_p) && TREE_CODE (*to_p) != MEM_REF)
7214 : {
7215 201 : tree addr = get_initialized_tmp_var (build_fold_addr_expr (*to_p),
7216 : pre_p, post_p);
7217 201 : *to_p = build_simple_mem_ref_loc (EXPR_LOCATION (*to_p), addr);
7218 : }
7219 559637 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
7220 559637 : *expr_p = NULL;
7221 559637 : return GS_ALL_DONE;
7222 : }
7223 :
7224 : /* Convert initialization from an empty variable-size CONSTRUCTOR to
7225 : memset. */
7226 49306274 : if (TREE_TYPE (*from_p) != error_mark_node
7227 49306274 : && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
7228 49306274 : && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
7229 1594 : && TREE_CODE (*from_p) == CONSTRUCTOR
7230 49306378 : && CONSTRUCTOR_NELTS (*from_p) == 0)
7231 : {
7232 84 : maybe_with_size_expr (from_p);
7233 84 : gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
7234 84 : return gimplify_modify_expr_to_memset (expr_p,
7235 84 : TREE_OPERAND (*from_p, 1),
7236 84 : want_value, pre_p);
7237 : }
7238 :
7239 : /* Insert pointer conversions required by the middle-end that are not
7240 : required by the frontend. This fixes middle-end type checking for
7241 : for example gcc.dg/redecl-6.c. */
7242 49306190 : if (POINTER_TYPE_P (TREE_TYPE (*to_p)))
7243 : {
7244 13317864 : STRIP_USELESS_TYPE_CONVERSION (*from_p);
7245 13317864 : if (!useless_type_conversion_p (TREE_TYPE (*to_p), TREE_TYPE (*from_p)))
7246 754 : *from_p = fold_convert_loc (loc, TREE_TYPE (*to_p), *from_p);
7247 : }
7248 :
7249 : /* See if any simplifications can be done based on what the RHS is. */
7250 49306190 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7251 : want_value);
7252 49306190 : if (ret != GS_UNHANDLED)
7253 : return ret;
7254 :
7255 : /* For empty types only gimplify the left hand side and right hand
7256 : side as statements and throw away the assignment. Do this after
7257 : gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable
7258 : types properly. */
7259 47303580 : if (is_empty_type (TREE_TYPE (*from_p))
7260 13289 : && !want_value
7261 : /* Don't do this for calls that return addressable types, expand_call
7262 : relies on those having a lhs. */
7263 47316862 : && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
7264 11178 : && TREE_CODE (*from_p) == CALL_EXPR))
7265 : {
7266 2104 : suppress_warning (*from_p, OPT_Wunused_result);
7267 2104 : gimplify_stmt (from_p, pre_p);
7268 2104 : gimplify_stmt (to_p, pre_p);
7269 2104 : *expr_p = NULL_TREE;
7270 2104 : return GS_ALL_DONE;
7271 : }
7272 :
7273 : /* If the value being copied is of variable width, compute the length
7274 : of the copy into a WITH_SIZE_EXPR. Note that we need to do this
7275 : before gimplifying any of the operands so that we can resolve any
7276 : PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
7277 : the size of the expression to be copied, not of the destination, so
7278 : that is what we must do here. */
7279 47301476 : maybe_with_size_expr (from_p);
7280 :
7281 : /* As a special case, we have to temporarily allow for assignments
7282 : with a CALL_EXPR on the RHS. Since in GIMPLE a function call is
7283 : a toplevel statement, when gimplifying the GENERIC expression
7284 : MODIFY_EXPR <a, CALL_EXPR <foo>>, we cannot create the tuple
7285 : GIMPLE_ASSIGN <a, GIMPLE_CALL <foo>>.
7286 :
7287 : Instead, we need to create the tuple GIMPLE_CALL <a, foo>. To
7288 : prevent gimplify_expr from trying to create a new temporary for
7289 : foo's LHS, we tell it that it should only gimplify until it
7290 : reaches the CALL_EXPR. On return from gimplify_expr, the newly
7291 : created GIMPLE_CALL <foo> will be the last statement in *PRE_P
7292 : and all we need to do here is set 'a' to be its LHS. */
7293 :
7294 : /* Gimplify the RHS first for C++17 and bug 71104. */
7295 47301476 : gimple_predicate initial_pred = initial_rhs_predicate_for (*to_p);
7296 47301476 : ret = gimplify_expr (from_p, pre_p, post_p, initial_pred, fb_rvalue);
7297 47301476 : if (ret == GS_ERROR)
7298 : return ret;
7299 :
7300 : /* Then gimplify the LHS. */
7301 : /* If we gimplified the RHS to a CALL_EXPR and that call may return
7302 : twice we have to make sure to gimplify into non-SSA as otherwise
7303 : the abnormal edge added later will make those defs not dominate
7304 : their uses.
7305 : ??? Technically this applies only to the registers used in the
7306 : resulting non-register *TO_P. */
7307 47301314 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
7308 47301314 : if (saved_into_ssa
7309 44940527 : && TREE_CODE (*from_p) == CALL_EXPR
7310 52260643 : && call_expr_flags (*from_p) & ECF_RETURNS_TWICE)
7311 1530 : gimplify_ctxp->into_ssa = false;
7312 47301314 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7313 47301314 : gimplify_ctxp->into_ssa = saved_into_ssa;
7314 47301314 : if (ret == GS_ERROR)
7315 : return ret;
7316 :
7317 : /* Now that the LHS is gimplified, re-gimplify the RHS if our initial
7318 : guess for the predicate was wrong. */
7319 47301239 : gimple_predicate final_pred = rhs_predicate_for (*to_p);
7320 47301239 : if (final_pred != initial_pred)
7321 : {
7322 8084260 : ret = gimplify_expr (from_p, pre_p, post_p, final_pred, fb_rvalue);
7323 8084260 : if (ret == GS_ERROR)
7324 : return ret;
7325 : }
7326 :
7327 : /* In case of va_arg internal fn wrapped in a WITH_SIZE_EXPR, add the type
7328 : size as argument to the call. */
7329 47301239 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7330 : {
7331 1458 : tree call = TREE_OPERAND (*from_p, 0);
7332 1458 : tree vlasize = TREE_OPERAND (*from_p, 1);
7333 :
7334 1458 : if (TREE_CODE (call) == CALL_EXPR
7335 1458 : && CALL_EXPR_IFN (call) == IFN_VA_ARG)
7336 : {
7337 95 : int nargs = call_expr_nargs (call);
7338 95 : tree type = TREE_TYPE (call);
7339 95 : tree ap = CALL_EXPR_ARG (call, 0);
7340 95 : tree tag = CALL_EXPR_ARG (call, 1);
7341 95 : tree aptag = CALL_EXPR_ARG (call, 2);
7342 95 : tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
7343 : IFN_VA_ARG, type,
7344 : nargs + 1, ap, tag,
7345 : aptag, vlasize);
7346 95 : TREE_OPERAND (*from_p, 0) = newcall;
7347 : }
7348 : }
7349 :
7350 : /* Now see if the above changed *from_p to something we handle specially. */
7351 47301239 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7352 : want_value);
7353 47301239 : if (ret != GS_UNHANDLED)
7354 : return ret;
7355 :
7356 : /* If we've got a variable sized assignment between two lvalues (i.e. does
7357 : not involve a call), then we can make things a bit more straightforward
7358 : by converting the assignment to memcpy or memset. */
7359 47300276 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7360 : {
7361 1107 : tree from = TREE_OPERAND (*from_p, 0);
7362 1107 : tree size = TREE_OPERAND (*from_p, 1);
7363 :
7364 1107 : if (TREE_CODE (from) == CONSTRUCTOR)
7365 0 : return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
7366 1107 : else if (is_gimple_addressable (from)
7367 1107 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (*to_p)))
7368 2213 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))))
7369 : {
7370 1106 : *from_p = from;
7371 1106 : return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
7372 1106 : pre_p);
7373 : }
7374 : }
7375 :
7376 : /* Transform partial stores to non-addressable complex variables into
7377 : total stores. This allows us to use real instead of virtual operands
7378 : for these variables, which improves optimization. */
7379 47299170 : if ((TREE_CODE (*to_p) == REALPART_EXPR
7380 47299170 : || TREE_CODE (*to_p) == IMAGPART_EXPR)
7381 47299170 : && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
7382 1942 : return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
7383 :
7384 : /* Try to alleviate the effects of the gimplification creating artificial
7385 : temporaries (see for example is_gimple_reg_rhs) on the debug info, but
7386 : make sure not to create DECL_DEBUG_EXPR links across functions. */
7387 47297228 : if (!gimplify_ctxp->into_ssa
7388 2359861 : && VAR_P (*from_p)
7389 471098 : && DECL_IGNORED_P (*from_p)
7390 350285 : && DECL_P (*to_p)
7391 138206 : && !DECL_IGNORED_P (*to_p)
7392 38111 : && decl_function_context (*to_p) == current_function_decl
7393 47329779 : && decl_function_context (*from_p) == current_function_decl)
7394 : {
7395 32546 : if (!DECL_NAME (*from_p) && DECL_NAME (*to_p))
7396 27294 : DECL_NAME (*from_p)
7397 54588 : = create_tmp_var_name (IDENTIFIER_POINTER (DECL_NAME (*to_p)));
7398 32546 : DECL_HAS_DEBUG_EXPR_P (*from_p) = 1;
7399 32546 : SET_DECL_DEBUG_EXPR (*from_p, *to_p);
7400 : }
7401 :
7402 47297228 : if (want_value && TREE_THIS_VOLATILE (*to_p))
7403 526 : *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
7404 :
7405 47297228 : if (TREE_CODE (*from_p) == CALL_EXPR)
7406 : {
7407 : /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
7408 : instead of a GIMPLE_ASSIGN. */
7409 4668134 : gcall *call_stmt;
7410 4668134 : if (CALL_EXPR_FN (*from_p) == NULL_TREE)
7411 : {
7412 : /* Gimplify internal functions created in the FEs. */
7413 307161 : int nargs = call_expr_nargs (*from_p), i;
7414 307161 : enum internal_fn ifn = CALL_EXPR_IFN (*from_p);
7415 307161 : auto_vec<tree> vargs (nargs);
7416 :
7417 1548592 : for (i = 0; i < nargs; i++)
7418 : {
7419 934270 : gimplify_arg (&CALL_EXPR_ARG (*from_p, i), pre_p,
7420 934270 : EXPR_LOCATION (*from_p));
7421 934270 : vargs.quick_push (CALL_EXPR_ARG (*from_p, i));
7422 : }
7423 307161 : call_stmt = gimple_build_call_internal_vec (ifn, vargs);
7424 307161 : gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p));
7425 614322 : gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p));
7426 307161 : }
7427 : else
7428 : {
7429 4360973 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
7430 4360973 : CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
7431 4360973 : STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
7432 4360973 : tree fndecl = get_callee_fndecl (*from_p);
7433 4360973 : if (fndecl
7434 4246544 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
7435 4494669 : && call_expr_nargs (*from_p) == 3)
7436 66558 : call_stmt = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3,
7437 66558 : CALL_EXPR_ARG (*from_p, 0),
7438 66558 : CALL_EXPR_ARG (*from_p, 1),
7439 66558 : CALL_EXPR_ARG (*from_p, 2));
7440 : else
7441 : {
7442 4294415 : call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
7443 : }
7444 : }
7445 4668134 : notice_special_calls (call_stmt);
7446 4668134 : if (!gimple_call_noreturn_p (call_stmt) || !should_remove_lhs_p (*to_p))
7447 4667953 : gimple_call_set_lhs (call_stmt, *to_p);
7448 181 : else if (TREE_CODE (*to_p) == SSA_NAME)
7449 : /* The above is somewhat premature, avoid ICEing later for a
7450 : SSA name w/o a definition. We may have uses in the GIMPLE IL.
7451 : ??? This doesn't make it a default-def. */
7452 86 : SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop ();
7453 :
7454 : assign = call_stmt;
7455 : }
7456 : else
7457 : {
7458 42629094 : assign = gimple_build_assign (*to_p, *from_p);
7459 42629094 : gimple_set_location (assign, EXPR_LOCATION (*expr_p));
7460 42629094 : if (COMPARISON_CLASS_P (*from_p))
7461 1219260 : copy_warning (assign, *from_p);
7462 : }
7463 :
7464 47297228 : if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
7465 : {
7466 : /* We should have got an SSA name from the start. */
7467 34976788 : gcc_assert (TREE_CODE (*to_p) == SSA_NAME
7468 : || ! gimple_in_ssa_p (cfun));
7469 : }
7470 :
7471 47297228 : gimplify_seq_add_stmt (pre_p, assign);
7472 47297228 : gsi = gsi_last (*pre_p);
7473 47297228 : maybe_fold_stmt (&gsi);
7474 :
7475 47297228 : if (want_value)
7476 : {
7477 661706 : *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
7478 661706 : return GS_OK;
7479 : }
7480 : else
7481 46635522 : *expr_p = NULL;
7482 :
7483 46635522 : return GS_ALL_DONE;
7484 : }
7485 :
7486 : /* Gimplify a comparison between two variable-sized objects. Do this
7487 : with a call to BUILT_IN_MEMCMP. */
7488 :
7489 : static enum gimplify_status
7490 0 : gimplify_variable_sized_compare (tree *expr_p)
7491 : {
7492 0 : location_t loc = EXPR_LOCATION (*expr_p);
7493 0 : tree op0 = TREE_OPERAND (*expr_p, 0);
7494 0 : tree op1 = TREE_OPERAND (*expr_p, 1);
7495 0 : tree t, arg, dest, src, expr;
7496 :
7497 0 : arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
7498 0 : arg = unshare_expr (arg);
7499 0 : arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
7500 0 : src = build_fold_addr_expr_loc (loc, op1);
7501 0 : dest = build_fold_addr_expr_loc (loc, op0);
7502 0 : t = builtin_decl_implicit (BUILT_IN_MEMCMP);
7503 0 : t = build_call_expr_loc (loc, t, 3, dest, src, arg);
7504 :
7505 0 : expr
7506 0 : = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
7507 0 : SET_EXPR_LOCATION (expr, loc);
7508 0 : *expr_p = expr;
7509 :
7510 0 : return GS_OK;
7511 : }
7512 :
7513 : /* Gimplify a comparison between two aggregate objects of integral scalar
7514 : mode as a comparison between the bitwise equivalent scalar values. */
7515 :
7516 : static enum gimplify_status
7517 16 : gimplify_scalar_mode_aggregate_compare (tree *expr_p)
7518 : {
7519 16 : const location_t loc = EXPR_LOCATION (*expr_p);
7520 16 : const enum tree_code code = TREE_CODE (*expr_p);
7521 16 : tree op0 = TREE_OPERAND (*expr_p, 0);
7522 16 : tree op1 = TREE_OPERAND (*expr_p, 1);
7523 16 : tree type = TREE_TYPE (op0);
7524 16 : tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
7525 :
7526 16 : op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
7527 16 : op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
7528 :
7529 : /* We need to perform ordering comparisons in memory order like memcmp and,
7530 : therefore, may need to byte-swap operands for little-endian targets. */
7531 16 : if (code != EQ_EXPR && code != NE_EXPR)
7532 : {
7533 0 : gcc_assert (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN);
7534 0 : gcc_assert (TREE_CODE (scalar_type) == INTEGER_TYPE);
7535 0 : tree fndecl;
7536 :
7537 0 : if (BYTES_BIG_ENDIAN)
7538 : fndecl = NULL_TREE;
7539 : else
7540 0 : switch (int_size_in_bytes (scalar_type))
7541 : {
7542 : case 1:
7543 : fndecl = NULL_TREE;
7544 : break;
7545 0 : case 2:
7546 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP16);
7547 0 : break;
7548 0 : case 4:
7549 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP32);
7550 0 : break;
7551 0 : case 8:
7552 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP64);
7553 0 : break;
7554 0 : case 16:
7555 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP128);
7556 0 : break;
7557 0 : default:
7558 0 : gcc_unreachable ();
7559 : }
7560 :
7561 0 : if (fndecl)
7562 : {
7563 0 : op0 = build_call_expr_loc (loc, fndecl, 1, op0);
7564 0 : op1 = build_call_expr_loc (loc, fndecl, 1, op1);
7565 : }
7566 : }
7567 :
7568 16 : *expr_p = fold_build2_loc (loc, code, TREE_TYPE (*expr_p), op0, op1);
7569 :
7570 16 : return GS_OK;
7571 : }
7572 :
7573 : /* Gimplify an expression sequence. This function gimplifies each
7574 : expression and rewrites the original expression with the last
7575 : expression of the sequence in GIMPLE form.
7576 :
7577 : PRE_P points to the list where the side effects for all the
7578 : expressions in the sequence will be emitted.
7579 :
7580 : WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
7581 :
7582 : static enum gimplify_status
7583 1093896 : gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
7584 : {
7585 1093896 : tree t = *expr_p;
7586 :
7587 1180115 : do
7588 : {
7589 1180115 : tree *sub_p = &TREE_OPERAND (t, 0);
7590 :
7591 1180115 : if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
7592 204156 : gimplify_compound_expr (sub_p, pre_p, false);
7593 : else
7594 975959 : gimplify_stmt (sub_p, pre_p);
7595 :
7596 1180115 : t = TREE_OPERAND (t, 1);
7597 : }
7598 1180115 : while (TREE_CODE (t) == COMPOUND_EXPR);
7599 :
7600 1093896 : *expr_p = t;
7601 1093896 : if (want_value)
7602 : return GS_OK;
7603 : else
7604 : {
7605 598152 : gimplify_stmt (expr_p, pre_p);
7606 598152 : return GS_ALL_DONE;
7607 : }
7608 : }
7609 :
7610 : /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
7611 : gimplify. After gimplification, EXPR_P will point to a new temporary
7612 : that holds the original value of the SAVE_EXPR node.
7613 :
7614 : PRE_P points to the list where side effects that must happen before
7615 : *EXPR_P should be stored. */
7616 :
7617 : static enum gimplify_status
7618 439345 : gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7619 : {
7620 439345 : enum gimplify_status ret = GS_ALL_DONE;
7621 439345 : tree val;
7622 :
7623 439345 : gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
7624 439345 : val = TREE_OPERAND (*expr_p, 0);
7625 :
7626 439345 : if (val && TREE_TYPE (val) == error_mark_node)
7627 : return GS_ERROR;
7628 :
7629 : /* If the SAVE_EXPR has not been resolved, then evaluate it once. */
7630 439343 : if (!SAVE_EXPR_RESOLVED_P (*expr_p))
7631 : {
7632 : /* The operand may be a void-valued expression. It is
7633 : being executed only for its side-effects. */
7634 168402 : if (TREE_TYPE (val) == void_type_node)
7635 : {
7636 750 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7637 : is_gimple_stmt, fb_none);
7638 750 : val = NULL;
7639 : }
7640 : else
7641 : /* The temporary may not be an SSA name as later abnormal and EH
7642 : control flow may invalidate use/def domination. When in SSA
7643 : form then assume there are no such issues and SAVE_EXPRs only
7644 : appear via GENERIC foldings. */
7645 335304 : val = get_initialized_tmp_var (val, pre_p, post_p,
7646 335304 : gimple_in_ssa_p (cfun));
7647 :
7648 168402 : TREE_OPERAND (*expr_p, 0) = val;
7649 168402 : SAVE_EXPR_RESOLVED_P (*expr_p) = 1;
7650 : }
7651 :
7652 439343 : *expr_p = val;
7653 :
7654 439343 : return ret;
7655 : }
7656 :
7657 : /* Rewrite the ADDR_EXPR node pointed to by EXPR_P
7658 :
7659 : unary_expr
7660 : : ...
7661 : | '&' varname
7662 : ...
7663 :
7664 : PRE_P points to the list where side effects that must happen before
7665 : *EXPR_P should be stored.
7666 :
7667 : POST_P points to the list where side effects that must happen after
7668 : *EXPR_P should be stored. */
7669 :
7670 : static enum gimplify_status
7671 32518792 : gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7672 : {
7673 32518792 : tree expr = *expr_p;
7674 32518792 : tree op0 = TREE_OPERAND (expr, 0);
7675 32518792 : enum gimplify_status ret;
7676 32518792 : location_t loc = EXPR_LOCATION (*expr_p);
7677 :
7678 32518792 : switch (TREE_CODE (op0))
7679 : {
7680 94325 : case INDIRECT_REF:
7681 94325 : do_indirect_ref:
7682 : /* Check if we are dealing with an expression of the form '&*ptr'.
7683 : While the front end folds away '&*ptr' into 'ptr', these
7684 : expressions may be generated internally by the compiler (e.g.,
7685 : builtins like __builtin_va_end). */
7686 : /* Caution: the silent array decomposition semantics we allow for
7687 : ADDR_EXPR means we can't always discard the pair. */
7688 : /* Gimplification of the ADDR_EXPR operand may drop
7689 : cv-qualification conversions, so make sure we add them if
7690 : needed. */
7691 94325 : {
7692 94325 : tree op00 = TREE_OPERAND (op0, 0);
7693 94325 : tree t_expr = TREE_TYPE (expr);
7694 94325 : tree t_op00 = TREE_TYPE (op00);
7695 :
7696 94325 : if (!useless_type_conversion_p (t_expr, t_op00))
7697 0 : op00 = fold_convert_loc (loc, TREE_TYPE (expr), op00);
7698 94325 : *expr_p = op00;
7699 94325 : ret = GS_OK;
7700 : }
7701 94325 : break;
7702 :
7703 0 : case VIEW_CONVERT_EXPR:
7704 : /* Take the address of our operand and then convert it to the type of
7705 : this ADDR_EXPR.
7706 :
7707 : ??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
7708 : all clear. The impact of this transformation is even less clear. */
7709 :
7710 : /* If the operand is a useless conversion, look through it. Doing so
7711 : guarantees that the ADDR_EXPR and its operand will remain of the
7712 : same type. */
7713 0 : if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
7714 0 : op0 = TREE_OPERAND (op0, 0);
7715 :
7716 0 : *expr_p = fold_convert_loc (loc, TREE_TYPE (expr),
7717 : build_fold_addr_expr_loc (loc,
7718 0 : TREE_OPERAND (op0, 0)));
7719 0 : ret = GS_OK;
7720 0 : break;
7721 :
7722 64924 : case MEM_REF:
7723 64924 : if (integer_zerop (TREE_OPERAND (op0, 1)))
7724 36547 : goto do_indirect_ref;
7725 :
7726 : /* fall through */
7727 :
7728 32441698 : default:
7729 : /* If we see a call to a declared builtin or see its address
7730 : being taken (we can unify those cases here) then we can mark
7731 : the builtin for implicit generation by GCC. */
7732 32441698 : if (TREE_CODE (op0) == FUNCTION_DECL
7733 16224741 : && fndecl_built_in_p (op0, BUILT_IN_NORMAL)
7734 36385025 : && builtin_decl_declared_p (DECL_FUNCTION_CODE (op0)))
7735 1280918 : set_builtin_decl_implicit_p (DECL_FUNCTION_CODE (op0), true);
7736 :
7737 : /* We use fb_either here because the C frontend sometimes takes
7738 : the address of a call that returns a struct; see
7739 : gcc.dg/c99-array-lval-1.c. The gimplifier will correctly make
7740 : the implied temporary explicit. */
7741 :
7742 : /* Make the operand addressable. */
7743 32441698 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
7744 : is_gimple_addressable, fb_either);
7745 32441698 : if (ret == GS_ERROR)
7746 : break;
7747 :
7748 : /* Then mark it. Beware that it may not be possible to do so directly
7749 : if a temporary has been created by the gimplification. */
7750 32441696 : prepare_gimple_addressable (&TREE_OPERAND (expr, 0), pre_p);
7751 :
7752 32441696 : op0 = TREE_OPERAND (expr, 0);
7753 :
7754 : /* For various reasons, the gimplification of the expression
7755 : may have made a new INDIRECT_REF. */
7756 32441696 : if (INDIRECT_REF_P (op0)
7757 32441696 : || (TREE_CODE (op0) == MEM_REF
7758 45608 : && integer_zerop (TREE_OPERAND (op0, 1))))
7759 17231 : goto do_indirect_ref;
7760 :
7761 32424465 : mark_addressable (TREE_OPERAND (expr, 0));
7762 :
7763 : /* The FEs may end up building ADDR_EXPRs early on a decl with
7764 : an incomplete type. Re-build ADDR_EXPRs in canonical form
7765 : here. */
7766 32424465 : if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
7767 145257 : *expr_p = build_fold_addr_expr (op0);
7768 :
7769 : /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */
7770 32424465 : if (TREE_CODE (*expr_p) == ADDR_EXPR)
7771 32424464 : recompute_tree_invariant_for_addr_expr (*expr_p);
7772 :
7773 : /* If we re-built the ADDR_EXPR add a conversion to the original type
7774 : if required. */
7775 32424465 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
7776 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
7777 :
7778 : break;
7779 : }
7780 :
7781 32518792 : return ret;
7782 : }
7783 :
7784 : /* Return the number of times character C occurs in string S. */
7785 :
7786 : static int
7787 94307 : num_occurrences (int c, const char *s)
7788 : {
7789 94307 : int n = 0;
7790 255985 : while (*s)
7791 161678 : n += (*s++ == c);
7792 94307 : return n;
7793 : }
7794 :
7795 : /* A subroutine of gimplify_asm_expr. Check that all operands have
7796 : the same number of alternatives. Return -1 if this is violated. Otherwise
7797 : return the number of alternatives. */
7798 :
7799 : static int
7800 196414 : num_alternatives (const_tree link)
7801 : {
7802 196414 : if (link == nullptr)
7803 : return 0;
7804 :
7805 48488 : const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7806 48488 : int num = num_occurrences (',', constraint);
7807 :
7808 48488 : if (num + 1 > MAX_RECOG_ALTERNATIVES)
7809 : return -1;
7810 :
7811 94307 : for (link = TREE_CHAIN (link); link; link = TREE_CHAIN (link))
7812 : {
7813 45819 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7814 91638 : if (num_occurrences (',', constraint) != num)
7815 : return -1;
7816 : }
7817 48488 : return num + 1;
7818 : }
7819 :
7820 : /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple
7821 : value; output operands should be a gimple lvalue. */
7822 :
7823 : static enum gimplify_status
7824 98207 : gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7825 : {
7826 98207 : tree expr;
7827 98207 : int noutputs;
7828 98207 : const char **oconstraints;
7829 98207 : int i;
7830 98207 : tree link;
7831 98207 : const char *constraint;
7832 98207 : bool allows_mem, allows_reg, is_inout;
7833 98207 : enum gimplify_status ret, tret;
7834 98207 : gasm *stmt;
7835 98207 : vec<tree, va_gc> *inputs;
7836 98207 : vec<tree, va_gc> *outputs;
7837 98207 : vec<tree, va_gc> *clobbers;
7838 98207 : vec<tree, va_gc> *labels;
7839 98207 : tree link_next;
7840 :
7841 98207 : expr = *expr_p;
7842 98207 : noutputs = list_length (ASM_OUTPUTS (expr));
7843 98207 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
7844 :
7845 98207 : inputs = NULL;
7846 98207 : outputs = NULL;
7847 98207 : clobbers = NULL;
7848 98207 : labels = NULL;
7849 :
7850 98207 : int num_alternatives_out = num_alternatives (ASM_OUTPUTS (expr));
7851 98207 : int num_alternatives_in = num_alternatives (ASM_INPUTS (expr));
7852 98207 : if (num_alternatives_out == -1 || num_alternatives_in == -1
7853 98207 : || (num_alternatives_out > 0 && num_alternatives_in > 0
7854 17156 : && num_alternatives_out != num_alternatives_in))
7855 : {
7856 0 : error ("operand constraints for %<asm%> differ "
7857 : "in number of alternatives");
7858 0 : return GS_ERROR;
7859 : }
7860 98207 : int num_alternatives = MAX (num_alternatives_out, num_alternatives_in);
7861 :
7862 98207 : gimplify_reg_info reg_info (num_alternatives, noutputs);
7863 :
7864 98207 : link_next = NULL_TREE;
7865 193670 : for (link = ASM_CLOBBERS (expr); link; link = link_next)
7866 : {
7867 : /* The clobber entry could also be an error marker. */
7868 95463 : if (TREE_CODE (TREE_VALUE (link)) == STRING_CST)
7869 : {
7870 95440 : const char *regname= TREE_STRING_POINTER (TREE_VALUE (link));
7871 95440 : int regno = decode_reg_name (regname);
7872 95440 : if (regno >= 0)
7873 41262 : reg_info.set_clobbered (regno);
7874 : }
7875 95463 : link_next = TREE_CHAIN (link);
7876 95463 : TREE_CHAIN (link) = NULL_TREE;
7877 95463 : vec_safe_push (clobbers, link);
7878 : }
7879 :
7880 98207 : ret = GS_ALL_DONE;
7881 98207 : link_next = NULL_TREE;
7882 159258 : for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
7883 : {
7884 61084 : bool ok;
7885 61084 : size_t constraint_len;
7886 :
7887 61084 : if (error_operand_p (TREE_VALUE (link)))
7888 : return GS_ERROR;
7889 61063 : link_next = TREE_CHAIN (link);
7890 :
7891 122126 : oconstraints[i]
7892 61063 : = constraint
7893 61063 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7894 61063 : constraint_len = strlen (constraint);
7895 61063 : if (constraint_len == 0)
7896 0 : continue;
7897 :
7898 61063 : reg_info.operand = TREE_VALUE (link);
7899 61063 : ok = parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
7900 : &allows_reg, &is_inout, ®_info);
7901 61063 : if (!ok)
7902 : {
7903 11 : ret = GS_ERROR;
7904 11 : is_inout = false;
7905 : }
7906 :
7907 : /* If we can't make copies, we can only accept memory.
7908 : Similarly for VLAs. */
7909 61063 : tree outtype = TREE_TYPE (TREE_VALUE (link));
7910 61063 : if (TREE_ADDRESSABLE (outtype)
7911 61048 : || !COMPLETE_TYPE_P (outtype)
7912 122086 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (outtype)))
7913 : {
7914 303 : if (allows_mem)
7915 291 : allows_reg = 0;
7916 : else
7917 : {
7918 12 : error ("impossible constraint in %<asm%>");
7919 12 : error ("non-memory output %d must stay in memory", i);
7920 12 : return GS_ERROR;
7921 : }
7922 : }
7923 :
7924 61051 : if (!allows_reg && allows_mem)
7925 1807 : mark_addressable (TREE_VALUE (link));
7926 :
7927 61051 : tree orig = TREE_VALUE (link);
7928 113434 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
7929 : is_inout ? is_gimple_min_lval : is_gimple_lvalue,
7930 : fb_lvalue | fb_mayfail);
7931 61051 : if (tret == GS_ERROR)
7932 : {
7933 0 : if (orig != error_mark_node)
7934 0 : error ("invalid lvalue in %<asm%> output %d", i);
7935 : ret = tret;
7936 : }
7937 :
7938 : /* If the gimplified operand is a register we do not allow memory. */
7939 61051 : if (allows_reg
7940 59241 : && allows_mem
7941 66977 : && (is_gimple_reg (TREE_VALUE (link))
7942 267 : || (handled_component_p (TREE_VALUE (link))
7943 36 : && is_gimple_reg (TREE_OPERAND (TREE_VALUE (link), 0)))))
7944 5660 : allows_mem = 0;
7945 :
7946 : /* If the constraint does not allow memory make sure we gimplify
7947 : it to a register if it is not already but its base is. This
7948 : happens for complex and vector components. */
7949 61051 : if (!allows_mem)
7950 : {
7951 58978 : tree op = TREE_VALUE (link);
7952 58978 : if (! is_gimple_val (op)
7953 21654 : && is_gimple_reg_type (TREE_TYPE (op))
7954 80631 : && is_gimple_reg (get_base_address (op)))
7955 : {
7956 19 : tree tem = create_tmp_reg (TREE_TYPE (op));
7957 19 : tree ass;
7958 19 : if (is_inout)
7959 : {
7960 7 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem),
7961 : tem, unshare_expr (op));
7962 7 : gimplify_and_add (ass, pre_p);
7963 : }
7964 19 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem), op, tem);
7965 19 : gimplify_and_add (ass, post_p);
7966 :
7967 19 : TREE_VALUE (link) = tem;
7968 19 : tret = GS_OK;
7969 : }
7970 : }
7971 :
7972 61051 : vec_safe_push (outputs, link);
7973 61051 : TREE_CHAIN (link) = NULL_TREE;
7974 :
7975 61051 : if (is_inout)
7976 : {
7977 : /* An input/output operand. To give the optimizers more
7978 : flexibility, split it into separate input and output
7979 : operands. */
7980 8668 : tree input;
7981 : /* Buffer big enough to format a 32-bit UINT_MAX into. */
7982 8668 : char buf[11];
7983 :
7984 : /* Turn the in/out constraint into an output constraint. */
7985 8668 : char *p = xstrdup (constraint);
7986 8668 : p[0] = '=';
7987 8668 : TREE_PURPOSE (link) = unshare_expr (TREE_PURPOSE (link));
7988 8668 : TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
7989 :
7990 : /* And add a matching input constraint. */
7991 8668 : if (allows_reg)
7992 : {
7993 8167 : sprintf (buf, "%u", i);
7994 :
7995 : /* If there are multiple alternatives in the constraint,
7996 : handle each of them individually. Those that allow register
7997 : will be replaced with operand number, the others will stay
7998 : unchanged. */
7999 8167 : if (strchr (p, ',') != NULL)
8000 : {
8001 100 : size_t len = 0, buflen = strlen (buf);
8002 100 : char *beg, *end, *str, *dst;
8003 :
8004 100 : for (beg = p + 1;;)
8005 : {
8006 200 : end = strchr (beg, ',');
8007 200 : if (end == NULL)
8008 100 : end = strchr (beg, '\0');
8009 200 : if ((size_t) (end - beg) < buflen)
8010 28 : len += buflen + 1;
8011 : else
8012 172 : len += end - beg + 1;
8013 200 : if (*end)
8014 100 : beg = end + 1;
8015 : else
8016 : break;
8017 : }
8018 :
8019 100 : str = (char *) alloca (len);
8020 100 : for (beg = p + 1, dst = str;;)
8021 : {
8022 200 : const char *tem;
8023 200 : bool mem_p, reg_p, inout_p;
8024 :
8025 200 : end = strchr (beg, ',');
8026 200 : if (end)
8027 100 : *end = '\0';
8028 200 : beg[-1] = '=';
8029 200 : tem = beg - 1;
8030 200 : parse_output_constraint (&tem, i, 0, 0, &mem_p, ®_p,
8031 : &inout_p, nullptr);
8032 200 : if (dst != str)
8033 100 : *dst++ = ',';
8034 200 : if (reg_p)
8035 : {
8036 115 : memcpy (dst, buf, buflen);
8037 115 : dst += buflen;
8038 : }
8039 : else
8040 : {
8041 85 : if (end)
8042 0 : len = end - beg;
8043 : else
8044 85 : len = strlen (beg);
8045 85 : memcpy (dst, beg, len);
8046 85 : dst += len;
8047 : }
8048 200 : if (end)
8049 100 : beg = end + 1;
8050 : else
8051 : break;
8052 100 : }
8053 100 : *dst = '\0';
8054 100 : input = build_string (dst - str, str);
8055 : }
8056 : else
8057 8067 : input = build_string (strlen (buf), buf);
8058 : }
8059 : else
8060 501 : input = build_string (constraint_len - 1, constraint + 1);
8061 :
8062 8668 : free (p);
8063 :
8064 8668 : input = build_tree_list (build_tree_list (NULL_TREE, input),
8065 8668 : unshare_expr (TREE_VALUE (link)));
8066 8668 : ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
8067 : }
8068 : }
8069 :
8070 : /* After all output operands have been gimplified, verify that each output
8071 : operand is used at most once in case of hard register constraints. Thus,
8072 : error out in cases like
8073 : asm ("" : "={0}" (x), "={1}" (x));
8074 : or even for
8075 : asm ("" : "=r" (x), "={1}" (x));
8076 :
8077 : FIXME: Ideally we would also error out for cases like
8078 : int x;
8079 : asm ("" : "=r" (x), "=r" (x));
8080 : However, since code like that was previously accepted, erroring out now might
8081 : break existing code. On the other hand, we already error out for register
8082 : asm like
8083 : register int x asm ("0");
8084 : asm ("" : "=r" (x), "=r" (x));
8085 : Thus, maybe it wouldn't be too bad to also error out in the former
8086 : non-register-asm case.
8087 : */
8088 159221 : for (unsigned i = 0; i < vec_safe_length (outputs); ++i)
8089 : {
8090 61049 : tree link = (*outputs)[i];
8091 61049 : tree op1 = TREE_VALUE (link);
8092 61049 : const char *constraint
8093 61049 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8094 61049 : if (strchr (constraint, '{') != nullptr)
8095 236 : for (unsigned j = 0; j < vec_safe_length (outputs); ++j)
8096 : {
8097 142 : if (i == j)
8098 95 : continue;
8099 47 : tree link2 = (*outputs)[j];
8100 47 : tree op2 = TREE_VALUE (link2);
8101 47 : if (op1 == op2)
8102 : {
8103 2 : error ("multiple outputs to lvalue %qE", op2);
8104 2 : return GS_ERROR;
8105 : }
8106 : }
8107 : }
8108 :
8109 98172 : link_next = NULL_TREE;
8110 98172 : int input_num = 0;
8111 140001 : for (link = ASM_INPUTS (expr); link; ++input_num, ++i, link = link_next)
8112 : {
8113 41887 : if (error_operand_p (TREE_VALUE (link)))
8114 : return GS_ERROR;
8115 41838 : link_next = TREE_CHAIN (link);
8116 41838 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8117 41838 : reg_info.operand = TREE_VALUE (link);
8118 41838 : bool ok = parse_input_constraint (&constraint, input_num, 0, noutputs, 0,
8119 : oconstraints, &allows_mem, &allows_reg,
8120 : ®_info);
8121 41838 : if (!ok)
8122 : {
8123 30 : ret = GS_ERROR;
8124 30 : is_inout = false;
8125 : }
8126 :
8127 : /* If we can't make copies, we can only accept memory. */
8128 41838 : tree intype = TREE_TYPE (TREE_VALUE (link));
8129 41838 : if (TREE_ADDRESSABLE (intype)
8130 41820 : || !COMPLETE_TYPE_P (intype)
8131 83619 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (intype)))
8132 : {
8133 312 : if (allows_mem)
8134 303 : allows_reg = 0;
8135 : else
8136 : {
8137 9 : error ("impossible constraint in %<asm%>");
8138 9 : error ("non-memory input %d must stay in memory", i);
8139 9 : return GS_ERROR;
8140 : }
8141 : }
8142 :
8143 : /* If the operand is a memory input, it should be an lvalue. */
8144 41829 : if (!allows_reg && allows_mem)
8145 : {
8146 2165 : tree inputv = TREE_VALUE (link);
8147 2165 : STRIP_NOPS (inputv);
8148 2165 : if (TREE_CODE (inputv) == PREDECREMENT_EXPR
8149 : || TREE_CODE (inputv) == PREINCREMENT_EXPR
8150 : || TREE_CODE (inputv) == POSTDECREMENT_EXPR
8151 2165 : || TREE_CODE (inputv) == POSTINCREMENT_EXPR
8152 2153 : || TREE_CODE (inputv) == MODIFY_EXPR
8153 4316 : || VOID_TYPE_P (TREE_TYPE (inputv)))
8154 38 : TREE_VALUE (link) = error_mark_node;
8155 2165 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8156 : is_gimple_lvalue, fb_lvalue | fb_mayfail);
8157 2165 : if (tret != GS_ERROR)
8158 : {
8159 : /* Unlike output operands, memory inputs are not guaranteed
8160 : to be lvalues by the FE, and while the expressions are
8161 : marked addressable there, if it is e.g. a statement
8162 : expression, temporaries in it might not end up being
8163 : addressable. They might be already used in the IL and thus
8164 : it is too late to make them addressable now though. */
8165 2119 : tree x = TREE_VALUE (link);
8166 2261 : while (handled_component_p (x))
8167 142 : x = TREE_OPERAND (x, 0);
8168 2119 : if (TREE_CODE (x) == MEM_REF
8169 2119 : && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
8170 0 : x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
8171 2119 : if ((VAR_P (x)
8172 : || TREE_CODE (x) == PARM_DECL
8173 : || TREE_CODE (x) == RESULT_DECL)
8174 1530 : && !TREE_ADDRESSABLE (x)
8175 23 : && is_gimple_reg (x))
8176 : {
8177 17 : warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link),
8178 17 : input_location), 0,
8179 : "memory input %d is not directly addressable",
8180 : i);
8181 17 : prepare_gimple_addressable (&TREE_VALUE (link), pre_p);
8182 : }
8183 : }
8184 2165 : mark_addressable (TREE_VALUE (link));
8185 2165 : if (tret == GS_ERROR)
8186 : {
8187 46 : if (inputv != error_mark_node)
8188 46 : error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
8189 : "memory input %d is not directly addressable", i);
8190 : ret = tret;
8191 : }
8192 : }
8193 : else
8194 : {
8195 39664 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8196 : is_gimple_asm_val, fb_rvalue);
8197 39664 : if (tret == GS_ERROR)
8198 46 : ret = tret;
8199 : }
8200 :
8201 41829 : TREE_CHAIN (link) = NULL_TREE;
8202 41829 : vec_safe_push (inputs, link);
8203 : }
8204 :
8205 98114 : link_next = NULL_TREE;
8206 99011 : for (link = ASM_LABELS (expr); link; link = link_next)
8207 : {
8208 897 : link_next = TREE_CHAIN (link);
8209 897 : TREE_CHAIN (link) = NULL_TREE;
8210 897 : vec_safe_push (labels, link);
8211 : }
8212 :
8213 : /* Do not add ASMs with errors to the gimple IL stream. */
8214 98114 : if (ret != GS_ERROR)
8215 : {
8216 98031 : stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
8217 : inputs, outputs, clobbers, labels);
8218 :
8219 : /* asm is volatile if it was marked by the user as volatile or
8220 : there are no outputs or this is an asm goto. */
8221 196062 : gimple_asm_set_volatile (stmt,
8222 98031 : ASM_VOLATILE_P (expr)
8223 7541 : || noutputs == 0
8224 105558 : || labels);
8225 98031 : gimple_asm_set_basic (stmt, ASM_BASIC_P (expr));
8226 98031 : gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
8227 :
8228 98031 : gimplify_seq_add_stmt (pre_p, stmt);
8229 : }
8230 :
8231 : return ret;
8232 98207 : }
8233 :
8234 : /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding
8235 : GIMPLE_WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
8236 : gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we
8237 : return to this function.
8238 :
8239 : FIXME should we complexify the prequeue handling instead? Or use flags
8240 : for all the cleanups and let the optimizer tighten them up? The current
8241 : code seems pretty fragile; it will break on a cleanup within any
8242 : non-conditional nesting. But any such nesting would be broken, anyway;
8243 : we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
8244 : and continues out of it. We can do that at the RTL level, though, so
8245 : having an optimizer to tighten up try/finally regions would be a Good
8246 : Thing. */
8247 :
8248 : static enum gimplify_status
8249 5105785 : gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
8250 : {
8251 5105785 : gimple_stmt_iterator iter;
8252 5105785 : gimple_seq body_sequence = NULL;
8253 :
8254 5105785 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
8255 :
8256 : /* We only care about the number of conditions between the innermost
8257 : CLEANUP_POINT_EXPR and the cleanup. So save and reset the count and
8258 : any cleanups collected outside the CLEANUP_POINT_EXPR. */
8259 5105785 : int old_conds = gimplify_ctxp->conditions;
8260 5105785 : gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
8261 5105785 : bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
8262 5105785 : gimplify_ctxp->conditions = 0;
8263 5105785 : gimplify_ctxp->conditional_cleanups = NULL;
8264 5105785 : gimplify_ctxp->in_cleanup_point_expr = true;
8265 :
8266 5105785 : gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
8267 :
8268 5105785 : gimplify_ctxp->conditions = old_conds;
8269 5105785 : gimplify_ctxp->conditional_cleanups = old_cleanups;
8270 5105785 : gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
8271 :
8272 26546039 : for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
8273 : {
8274 16374378 : gimple *wce = gsi_stmt (iter);
8275 :
8276 16374378 : if (gimple_code (wce) == GIMPLE_WITH_CLEANUP_EXPR)
8277 : {
8278 584849 : if (gsi_one_before_end_p (iter))
8279 : {
8280 : /* Note that gsi_insert_seq_before and gsi_remove do not
8281 : scan operands, unlike some other sequence mutators. */
8282 3029 : if (!gimple_wce_cleanup_eh_only (wce))
8283 3029 : gsi_insert_seq_before_without_update (&iter,
8284 : gimple_wce_cleanup (wce),
8285 : GSI_SAME_STMT);
8286 3029 : gsi_remove (&iter, true);
8287 3029 : break;
8288 : }
8289 : else
8290 : {
8291 581820 : gtry *gtry;
8292 581820 : gimple_seq seq;
8293 581820 : enum gimple_try_flags kind;
8294 :
8295 581820 : if (gimple_wce_cleanup_eh_only (wce))
8296 : kind = GIMPLE_TRY_CATCH;
8297 : else
8298 568131 : kind = GIMPLE_TRY_FINALLY;
8299 581820 : seq = gsi_split_seq_after (iter);
8300 :
8301 581820 : gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
8302 : /* Do not use gsi_replace here, as it may scan operands.
8303 : We want to do a simple structural modification only. */
8304 581820 : gsi_set_stmt (&iter, gtry);
8305 1163640 : iter = gsi_start (gtry->eval);
8306 : }
8307 : }
8308 : else
8309 15789529 : gsi_next (&iter);
8310 : }
8311 :
8312 5105785 : gimplify_seq_add_seq (pre_p, body_sequence);
8313 5105785 : if (temp)
8314 : {
8315 341241 : *expr_p = temp;
8316 341241 : return GS_OK;
8317 : }
8318 : else
8319 : {
8320 4764544 : *expr_p = NULL;
8321 4764544 : return GS_ALL_DONE;
8322 : }
8323 : }
8324 :
8325 : /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
8326 : is the cleanup action required. EH_ONLY is true if the cleanup should
8327 : only be executed if an exception is thrown, not on normal exit.
8328 : If FORCE_UNCOND is true perform the cleanup unconditionally; this is
8329 : only valid for clobbers. */
8330 :
8331 : static void
8332 589696 : gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
8333 : bool force_uncond = false)
8334 : {
8335 589696 : gimple *wce;
8336 589696 : gimple_seq cleanup_stmts = NULL;
8337 :
8338 : /* Errors can result in improperly nested cleanups. Which results in
8339 : confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
8340 589696 : if (seen_error ())
8341 4847 : return;
8342 :
8343 584849 : if (gimple_conditional_context ())
8344 : {
8345 : /* If we're in a conditional context, this is more complex. We only
8346 : want to run the cleanup if we actually ran the initialization that
8347 : necessitates it, but we want to run it after the end of the
8348 : conditional context. So we wrap the try/finally around the
8349 : condition and use a flag to determine whether or not to actually
8350 : run the destructor. Thus
8351 :
8352 : test ? f(A()) : 0
8353 :
8354 : becomes (approximately)
8355 :
8356 : flag = 0;
8357 : try {
8358 : if (test) { A::A(temp); flag = 1; val = f(temp); }
8359 : else { val = 0; }
8360 : } finally {
8361 : if (flag) A::~A(temp);
8362 : }
8363 : val
8364 : */
8365 14223 : if (force_uncond)
8366 : {
8367 13337 : gimplify_stmt (&cleanup, &cleanup_stmts);
8368 13337 : wce = gimple_build_wce (cleanup_stmts);
8369 13337 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8370 : }
8371 : else
8372 : {
8373 886 : tree flag = create_tmp_var (boolean_type_node, "cleanup");
8374 886 : gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
8375 886 : gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
8376 :
8377 886 : cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
8378 886 : gimplify_stmt (&cleanup, &cleanup_stmts);
8379 886 : wce = gimple_build_wce (cleanup_stmts);
8380 886 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8381 :
8382 886 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
8383 886 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8384 886 : gimplify_seq_add_stmt (pre_p, ftrue);
8385 :
8386 : /* Because of this manipulation, and the EH edges that jump
8387 : threading cannot redirect, the temporary (VAR) will appear
8388 : to be used uninitialized. Don't warn. */
8389 886 : suppress_warning (var, OPT_Wuninitialized);
8390 : }
8391 : }
8392 : else
8393 : {
8394 570626 : gimplify_stmt (&cleanup, &cleanup_stmts);
8395 570626 : wce = gimple_build_wce (cleanup_stmts);
8396 570626 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8397 570626 : gimplify_seq_add_stmt (pre_p, wce);
8398 : }
8399 : }
8400 :
8401 : /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
8402 :
8403 : static enum gimplify_status
8404 790742 : gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
8405 : {
8406 790742 : tree targ = *expr_p;
8407 790742 : tree temp = TARGET_EXPR_SLOT (targ);
8408 790742 : tree init = TARGET_EXPR_INITIAL (targ);
8409 790742 : enum gimplify_status ret;
8410 :
8411 790742 : bool unpoison_empty_seq = false;
8412 790742 : gimple_stmt_iterator unpoison_it;
8413 :
8414 790742 : if (init)
8415 : {
8416 756655 : gimple_seq init_pre_p = NULL;
8417 756655 : bool is_vla = false;
8418 :
8419 : /* TARGET_EXPR temps aren't part of the enclosing block, so add it
8420 : to the temps list. Handle also variable length TARGET_EXPRs. */
8421 756655 : if (!poly_int_tree_p (DECL_SIZE (temp)))
8422 : {
8423 44 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
8424 1 : gimplify_type_sizes (TREE_TYPE (temp), &init_pre_p);
8425 : /* FIXME: this is correct only when the size of the type does
8426 : not depend on expressions evaluated in init. */
8427 44 : gimplify_vla_decl (temp, &init_pre_p);
8428 44 : is_vla = true;
8429 : }
8430 : else
8431 : {
8432 : /* Save location where we need to place unpoisoning. It's possible
8433 : that a variable will be converted to needs_to_live_in_memory. */
8434 756611 : unpoison_it = gsi_last (*pre_p);
8435 756611 : unpoison_empty_seq = gsi_end_p (unpoison_it);
8436 :
8437 756611 : gimple_add_tmp_var (temp);
8438 : }
8439 :
8440 756655 : if (var_needs_auto_init_p (temp) && VOID_TYPE_P (TREE_TYPE (init)))
8441 : {
8442 47871 : gimple_add_init_for_auto_var (temp, flag_auto_var_init, &init_pre_p);
8443 47871 : if (flag_auto_var_init == AUTO_INIT_PATTERN
8444 0 : && !is_gimple_reg (temp)
8445 47871 : && clear_padding_type_may_have_padding_p (TREE_TYPE (temp)))
8446 0 : gimple_add_padding_init_for_auto_var (temp, is_vla, &init_pre_p);
8447 : }
8448 :
8449 : /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
8450 : expression is supposed to initialize the slot. */
8451 756655 : if (VOID_TYPE_P (TREE_TYPE (init)))
8452 272578 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8453 : fb_none);
8454 : else
8455 : {
8456 484077 : tree init_expr = build2 (INIT_EXPR, void_type_node, temp, init);
8457 484077 : init = init_expr;
8458 484077 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8459 : fb_none);
8460 484077 : init = NULL;
8461 484077 : ggc_free (init_expr);
8462 : }
8463 756655 : if (ret == GS_ERROR)
8464 : {
8465 : /* PR c++/28266 Make sure this is expanded only once. */
8466 10 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8467 10 : return GS_ERROR;
8468 : }
8469 :
8470 756645 : if (init)
8471 0 : gimplify_and_add (init, &init_pre_p);
8472 :
8473 : /* Add a clobber for the temporary going out of scope, like
8474 : gimplify_bind_expr. But only if we did not promote the
8475 : temporary to static storage. */
8476 756645 : if (gimplify_ctxp->in_cleanup_point_expr
8477 611378 : && !TREE_STATIC (temp)
8478 1366620 : && needs_to_live_in_memory (temp))
8479 : {
8480 451232 : if (flag_stack_reuse == SR_ALL)
8481 : {
8482 450746 : tree clobber = build_clobber (TREE_TYPE (temp),
8483 : CLOBBER_STORAGE_END);
8484 450746 : clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
8485 450746 : gimple_push_cleanup (temp, clobber, false, pre_p, true);
8486 : }
8487 451232 : if (asan_poisoned_variables
8488 486 : && DECL_ALIGN (temp) <= MAX_SUPPORTED_STACK_ALIGNMENT
8489 486 : && !TREE_STATIC (temp)
8490 486 : && dbg_cnt (asan_use_after_scope)
8491 451718 : && !gimplify_omp_ctxp)
8492 : {
8493 478 : tree asan_cleanup = build_asan_poison_call_expr (temp);
8494 478 : if (asan_cleanup)
8495 : {
8496 478 : if (unpoison_empty_seq)
8497 223 : unpoison_it = gsi_start (*pre_p);
8498 :
8499 478 : asan_poison_variable (temp, false, &unpoison_it,
8500 : unpoison_empty_seq);
8501 478 : gimple_push_cleanup (temp, asan_cleanup, false, pre_p);
8502 : }
8503 : }
8504 : }
8505 :
8506 756645 : gimple_seq_add_seq (pre_p, init_pre_p);
8507 :
8508 : /* If needed, push the cleanup for the temp. */
8509 756645 : if (TARGET_EXPR_CLEANUP (targ))
8510 138472 : gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
8511 138472 : CLEANUP_EH_ONLY (targ), pre_p);
8512 :
8513 : /* Only expand this once. */
8514 756645 : TREE_OPERAND (targ, 3) = init;
8515 756645 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8516 : }
8517 : else
8518 : /* We should have expanded this before. */
8519 34087 : gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
8520 :
8521 790732 : *expr_p = temp;
8522 790732 : return GS_OK;
8523 : }
8524 :
8525 : /* Gimplification of expression trees. */
8526 :
8527 : /* Gimplify an expression which appears at statement context. The
8528 : corresponding GIMPLE statements are added to *SEQ_P. If *SEQ_P is
8529 : NULL, a new sequence is allocated.
8530 :
8531 : Return true if we actually added a statement to the queue. */
8532 :
8533 : bool
8534 101498366 : gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
8535 : {
8536 101498366 : gimple_seq_node last;
8537 :
8538 101498366 : last = gimple_seq_last (*seq_p);
8539 101498366 : gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
8540 101498366 : return last != gimple_seq_last (*seq_p);
8541 : }
8542 :
8543 : /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
8544 : to CTX. If entries already exist, force them to be some flavor of private.
8545 : If there is no enclosing parallel, do nothing. */
8546 :
8547 : void
8548 123596 : omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
8549 : {
8550 123596 : splay_tree_node n;
8551 :
8552 123596 : if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE)
8553 : return;
8554 :
8555 36976 : do
8556 : {
8557 36976 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8558 36976 : if (n != NULL)
8559 : {
8560 4298 : if (n->value & GOVD_SHARED)
8561 183 : n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
8562 4115 : else if (n->value & GOVD_MAP)
8563 58 : n->value |= GOVD_MAP_TO_ONLY;
8564 : else
8565 : return;
8566 : }
8567 32678 : else if ((ctx->region_type & ORT_TARGET) != 0)
8568 : {
8569 7020 : if (ctx->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
8570 4261 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8571 : else
8572 2759 : omp_add_variable (ctx, decl, GOVD_MAP | GOVD_MAP_TO_ONLY);
8573 : }
8574 25658 : else if (ctx->region_type != ORT_WORKSHARE
8575 : && ctx->region_type != ORT_TASKGROUP
8576 23829 : && ctx->region_type != ORT_SIMD
8577 23205 : && ctx->region_type != ORT_ACC
8578 23088 : && !(ctx->region_type & ORT_TARGET_DATA))
8579 14507 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8580 :
8581 32919 : ctx = ctx->outer_context;
8582 : }
8583 32919 : while (ctx);
8584 : }
8585 :
8586 : /* Similarly for each of the type sizes of TYPE. */
8587 :
8588 : static void
8589 39972 : omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
8590 : {
8591 39972 : if (type == NULL || type == error_mark_node)
8592 : return;
8593 39968 : type = TYPE_MAIN_VARIANT (type);
8594 :
8595 39968 : if (ctx->privatized_types->add (type))
8596 : return;
8597 :
8598 30581 : switch (TREE_CODE (type))
8599 : {
8600 13016 : case INTEGER_TYPE:
8601 13016 : case ENUMERAL_TYPE:
8602 13016 : case BOOLEAN_TYPE:
8603 13016 : case REAL_TYPE:
8604 13016 : case FIXED_POINT_TYPE:
8605 13016 : omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
8606 13016 : omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
8607 13016 : break;
8608 :
8609 5390 : case ARRAY_TYPE:
8610 5390 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8611 5390 : omp_firstprivatize_type_sizes (ctx, TYPE_DOMAIN (type));
8612 5390 : break;
8613 :
8614 2502 : case RECORD_TYPE:
8615 2502 : case UNION_TYPE:
8616 2502 : case QUAL_UNION_TYPE:
8617 2502 : {
8618 2502 : tree field;
8619 26645 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
8620 24143 : if (TREE_CODE (field) == FIELD_DECL)
8621 : {
8622 8997 : omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
8623 8997 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (field));
8624 : }
8625 : }
8626 : break;
8627 :
8628 9023 : case POINTER_TYPE:
8629 9023 : case REFERENCE_TYPE:
8630 9023 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8631 9023 : break;
8632 :
8633 : default:
8634 : break;
8635 : }
8636 :
8637 30581 : omp_firstprivatize_variable (ctx, TYPE_SIZE (type));
8638 30581 : omp_firstprivatize_variable (ctx, TYPE_SIZE_UNIT (type));
8639 30581 : lang_hooks.types.omp_firstprivatize_type_sizes (ctx, type);
8640 : }
8641 :
8642 : /* Add an entry for DECL in the OMP context CTX with FLAGS. */
8643 :
8644 : static void
8645 716217 : omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
8646 : {
8647 716217 : splay_tree_node n;
8648 716217 : unsigned int nflags;
8649 716217 : tree t;
8650 :
8651 716217 : if (error_operand_p (decl) || ctx->region_type == ORT_NONE)
8652 : return;
8653 :
8654 : /* Never elide decls whose type has TREE_ADDRESSABLE set. This means
8655 : there are constructors involved somewhere. Exception is a shared clause,
8656 : there is nothing privatized in that case. */
8657 716072 : if ((flags & GOVD_SHARED) == 0
8658 716072 : && (TREE_ADDRESSABLE (TREE_TYPE (decl))
8659 655681 : || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
8660 7766 : flags |= GOVD_SEEN;
8661 :
8662 716072 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8663 716072 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
8664 : {
8665 : /* We shouldn't be re-adding the decl with the same data
8666 : sharing class. */
8667 824 : gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
8668 824 : nflags = n->value | flags;
8669 : /* The only combination of data sharing classes we should see is
8670 : FIRSTPRIVATE and LASTPRIVATE. However, OpenACC permits
8671 : reduction variables to be used in data sharing clauses. */
8672 824 : gcc_assert ((ctx->region_type & ORT_ACC) != 0
8673 : || ((nflags & GOVD_DATA_SHARE_CLASS)
8674 : == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE))
8675 : || (flags & GOVD_DATA_SHARE_CLASS) == 0);
8676 824 : n->value = nflags;
8677 824 : return;
8678 : }
8679 :
8680 : /* When adding a variable-sized variable, we have to handle all sorts
8681 : of additional bits of data: the pointer replacement variable, and
8682 : the parameters of the type. */
8683 715248 : if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl)))
8684 : {
8685 : /* Add the pointer replacement variable as PRIVATE if the variable
8686 : replacement is private, else FIRSTPRIVATE since we'll need the
8687 : address of the original variable either for SHARED, or for the
8688 : copy into or out of the context. */
8689 1330 : if (!(flags & GOVD_LOCAL) && ctx->region_type != ORT_TASKGROUP)
8690 : {
8691 1238 : if (flags & GOVD_MAP)
8692 : nflags = GOVD_MAP | GOVD_MAP_TO_ONLY | GOVD_EXPLICIT;
8693 531 : else if (flags & GOVD_PRIVATE)
8694 : nflags = GOVD_PRIVATE;
8695 441 : else if (((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
8696 50 : && (flags & GOVD_FIRSTPRIVATE))
8697 431 : || (ctx->region_type == ORT_TARGET_DATA
8698 6 : && (flags & GOVD_DATA_SHARE_CLASS) == 0))
8699 : nflags = GOVD_PRIVATE | GOVD_EXPLICIT;
8700 : else
8701 1238 : nflags = GOVD_FIRSTPRIVATE;
8702 1238 : nflags |= flags & GOVD_SEEN;
8703 1238 : t = DECL_VALUE_EXPR (decl);
8704 1238 : gcc_assert (INDIRECT_REF_P (t));
8705 1238 : t = TREE_OPERAND (t, 0);
8706 1238 : gcc_assert (DECL_P (t));
8707 1238 : omp_add_variable (ctx, t, nflags);
8708 : }
8709 :
8710 : /* Add all of the variable and type parameters (which should have
8711 : been gimplified to a formal temporary) as FIRSTPRIVATE. */
8712 1330 : omp_firstprivatize_variable (ctx, DECL_SIZE_UNIT (decl));
8713 1330 : omp_firstprivatize_variable (ctx, DECL_SIZE (decl));
8714 1330 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8715 :
8716 : /* The variable-sized variable itself is never SHARED, only some form
8717 : of PRIVATE. The sharing would take place via the pointer variable
8718 : which we remapped above. */
8719 1330 : if (flags & GOVD_SHARED)
8720 284 : flags = GOVD_SHARED | GOVD_DEBUG_PRIVATE
8721 284 : | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
8722 :
8723 : /* We're going to make use of the TYPE_SIZE_UNIT at least in the
8724 : alloca statement we generate for the variable, so make sure it
8725 : is available. This isn't automatically needed for the SHARED
8726 : case, since we won't be allocating local storage then.
8727 : For local variables TYPE_SIZE_UNIT might not be gimplified yet,
8728 : in this case omp_notice_variable will be called later
8729 : on when it is gimplified. */
8730 1046 : else if (! (flags & (GOVD_LOCAL | GOVD_MAP))
8731 1046 : && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
8732 275 : omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
8733 : }
8734 713918 : else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
8735 713918 : && omp_privatize_by_reference (decl))
8736 : {
8737 9842 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8738 :
8739 : /* Similar to the direct variable sized case above, we'll need the
8740 : size of references being privatized. */
8741 9842 : if ((flags & GOVD_SHARED) == 0)
8742 : {
8743 6157 : t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
8744 6157 : if (t && DECL_P (t))
8745 1397 : omp_notice_variable (ctx, t, true);
8746 : }
8747 : }
8748 :
8749 715248 : if (n != NULL)
8750 1868 : n->value |= flags;
8751 : else
8752 713380 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
8753 :
8754 : /* For reductions clauses in OpenACC loop directives, by default create a
8755 : copy clause on the enclosing parallel construct for carrying back the
8756 : results. */
8757 715248 : if (ctx->region_type == ORT_ACC && (flags & GOVD_REDUCTION))
8758 : {
8759 4716 : struct gimplify_omp_ctx *outer_ctx = ctx->outer_context;
8760 6454 : while (outer_ctx)
8761 : {
8762 5788 : n = splay_tree_lookup (outer_ctx->variables, (splay_tree_key)decl);
8763 5788 : if (n != NULL)
8764 : {
8765 : /* Ignore local variables and explicitly declared clauses. */
8766 3990 : if (n->value & (GOVD_LOCAL | GOVD_EXPLICIT))
8767 : break;
8768 443 : else if (outer_ctx->region_type == ORT_ACC_KERNELS)
8769 : {
8770 : /* According to the OpenACC spec, such a reduction variable
8771 : should already have a copy map on a kernels construct,
8772 : verify that here. */
8773 143 : gcc_assert (!(n->value & GOVD_FIRSTPRIVATE)
8774 : && (n->value & GOVD_MAP));
8775 : }
8776 300 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8777 : {
8778 : /* Remove firstprivate and make it a copy map. */
8779 150 : n->value &= ~GOVD_FIRSTPRIVATE;
8780 150 : n->value |= GOVD_MAP;
8781 : }
8782 : }
8783 1798 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8784 : {
8785 503 : splay_tree_insert (outer_ctx->variables, (splay_tree_key)decl,
8786 : GOVD_MAP | GOVD_SEEN);
8787 503 : break;
8788 : }
8789 1738 : outer_ctx = outer_ctx->outer_context;
8790 : }
8791 : }
8792 : }
8793 :
8794 : /* Notice a threadprivate variable DECL used in OMP context CTX.
8795 : This just prints out diagnostics about threadprivate variable uses
8796 : in untied tasks. If DECL2 is non-NULL, prevent this warning
8797 : on that variable. */
8798 :
8799 : static bool
8800 14183 : omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
8801 : tree decl2)
8802 : {
8803 14183 : splay_tree_node n;
8804 14183 : struct gimplify_omp_ctx *octx;
8805 :
8806 28798 : for (octx = ctx; octx; octx = octx->outer_context)
8807 14615 : if ((octx->region_type & ORT_TARGET) != 0
8808 14615 : || octx->order_concurrent)
8809 : {
8810 112 : n = splay_tree_lookup (octx->variables, (splay_tree_key)decl);
8811 112 : if (n == NULL)
8812 : {
8813 20 : if (octx->order_concurrent)
8814 : {
8815 20 : error ("threadprivate variable %qE used in a region with"
8816 20 : " %<order(concurrent)%> clause", DECL_NAME (decl));
8817 20 : inform (octx->location, "enclosing region");
8818 : }
8819 : else
8820 : {
8821 0 : error ("threadprivate variable %qE used in target region",
8822 0 : DECL_NAME (decl));
8823 0 : inform (octx->location, "enclosing target region");
8824 : }
8825 20 : splay_tree_insert (octx->variables, (splay_tree_key)decl, 0);
8826 : }
8827 112 : if (decl2)
8828 0 : splay_tree_insert (octx->variables, (splay_tree_key)decl2, 0);
8829 : }
8830 :
8831 14183 : if (ctx->region_type != ORT_UNTIED_TASK)
8832 : return false;
8833 37 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8834 37 : if (n == NULL)
8835 : {
8836 6 : error ("threadprivate variable %qE used in untied task",
8837 6 : DECL_NAME (decl));
8838 6 : inform (ctx->location, "enclosing task");
8839 6 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
8840 : }
8841 37 : if (decl2)
8842 4 : splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
8843 : return false;
8844 : }
8845 :
8846 : /* Return true if global var DECL is device resident. */
8847 :
8848 : static bool
8849 642 : device_resident_p (tree decl)
8850 : {
8851 642 : tree attr = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (decl));
8852 :
8853 642 : if (!attr)
8854 : return false;
8855 :
8856 0 : for (tree t = TREE_VALUE (attr); t; t = TREE_PURPOSE (t))
8857 : {
8858 0 : tree c = TREE_VALUE (t);
8859 0 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DEVICE_RESIDENT)
8860 : return true;
8861 : }
8862 :
8863 : return false;
8864 : }
8865 :
8866 : /* Return true if DECL has an ACC DECLARE attribute. */
8867 :
8868 : static bool
8869 9101 : is_oacc_declared (tree decl)
8870 : {
8871 9101 : tree t = TREE_CODE (decl) == MEM_REF ? TREE_OPERAND (decl, 0) : decl;
8872 9101 : tree declared = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (t));
8873 9101 : return declared != NULL_TREE;
8874 : }
8875 :
8876 : /* Determine outer default flags for DECL mentioned in an OMP region
8877 : but not declared in an enclosing clause.
8878 :
8879 : ??? Some compiler-generated variables (like SAVE_EXPRs) could be
8880 : remapped firstprivate instead of shared. To some extent this is
8881 : addressed in omp_firstprivatize_type_sizes, but not
8882 : effectively. */
8883 :
8884 : static unsigned
8885 47882 : omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
8886 : bool in_code, unsigned flags)
8887 : {
8888 47882 : enum omp_clause_default_kind default_kind = ctx->default_kind;
8889 47882 : enum omp_clause_default_kind kind;
8890 :
8891 47882 : kind = lang_hooks.decls.omp_predetermined_sharing (decl);
8892 47882 : if (ctx->region_type & ORT_TASK)
8893 : {
8894 3971 : tree detach_clause = omp_find_clause (ctx->clauses, OMP_CLAUSE_DETACH);
8895 :
8896 : /* The event-handle specified by a detach clause should always be firstprivate,
8897 : regardless of the current default. */
8898 4183 : if (detach_clause && OMP_CLAUSE_DECL (detach_clause) == decl)
8899 : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
8900 : }
8901 47882 : if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
8902 : default_kind = kind;
8903 45068 : else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
8904 : default_kind = OMP_CLAUSE_DEFAULT_SHARED;
8905 : /* For C/C++ default({,first}private), variables with static storage duration
8906 : declared in a namespace or global scope and referenced in construct
8907 : must be explicitly specified, i.e. acts as default(none). */
8908 45067 : else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
8909 45067 : || default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
8910 368 : && VAR_P (decl)
8911 321 : && is_global_var (decl)
8912 184 : && (DECL_FILE_SCOPE_P (decl)
8913 104 : || (DECL_CONTEXT (decl)
8914 104 : && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
8915 45195 : && !lang_GNU_Fortran ())
8916 : default_kind = OMP_CLAUSE_DEFAULT_NONE;
8917 :
8918 47753 : switch (default_kind)
8919 : {
8920 267 : case OMP_CLAUSE_DEFAULT_NONE:
8921 267 : {
8922 267 : const char *rtype;
8923 :
8924 267 : if (ctx->region_type & ORT_PARALLEL)
8925 : rtype = "parallel";
8926 108 : else if ((ctx->region_type & ORT_TASKLOOP) == ORT_TASKLOOP)
8927 : rtype = "taskloop";
8928 72 : else if (ctx->region_type & ORT_TASK)
8929 : rtype = "task";
8930 36 : else if (ctx->region_type & ORT_TEAMS)
8931 : rtype = "teams";
8932 : else
8933 0 : gcc_unreachable ();
8934 :
8935 267 : error ("%qE not specified in enclosing %qs",
8936 267 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)), rtype);
8937 267 : inform (ctx->location, "enclosing %qs", rtype);
8938 : }
8939 : /* FALLTHRU */
8940 44249 : case OMP_CLAUSE_DEFAULT_SHARED:
8941 44249 : flags |= GOVD_SHARED;
8942 44249 : break;
8943 155 : case OMP_CLAUSE_DEFAULT_PRIVATE:
8944 155 : flags |= GOVD_PRIVATE;
8945 155 : break;
8946 277 : case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
8947 277 : flags |= GOVD_FIRSTPRIVATE;
8948 277 : break;
8949 3201 : case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
8950 : /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */
8951 3201 : gcc_assert ((ctx->region_type & ORT_TASK) != 0);
8952 3201 : if (struct gimplify_omp_ctx *octx = ctx->outer_context)
8953 : {
8954 2164 : omp_notice_variable (octx, decl, in_code);
8955 2994 : for (; octx; octx = octx->outer_context)
8956 : {
8957 2938 : splay_tree_node n2;
8958 :
8959 2938 : n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
8960 2938 : if ((octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)) != 0
8961 5 : && (n2 == NULL || (n2->value & GOVD_DATA_SHARE_CLASS) == 0))
8962 5 : continue;
8963 2933 : if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
8964 : {
8965 898 : flags |= GOVD_FIRSTPRIVATE;
8966 898 : goto found_outer;
8967 : }
8968 2035 : if ((octx->region_type & (ORT_PARALLEL | ORT_TEAMS)) != 0)
8969 : {
8970 1210 : flags |= GOVD_SHARED;
8971 1210 : goto found_outer;
8972 : }
8973 : }
8974 : }
8975 :
8976 1093 : if (TREE_CODE (decl) == PARM_DECL
8977 1093 : || (!is_global_var (decl)
8978 288 : && DECL_CONTEXT (decl) == current_function_decl))
8979 713 : flags |= GOVD_FIRSTPRIVATE;
8980 : else
8981 380 : flags |= GOVD_SHARED;
8982 47882 : found_outer:
8983 : break;
8984 :
8985 0 : default:
8986 0 : gcc_unreachable ();
8987 : }
8988 :
8989 47882 : return flags;
8990 : }
8991 :
8992 : /* Return string name for types of OpenACC constructs from ORT_* values. */
8993 :
8994 : static const char *
8995 570 : oacc_region_type_name (enum omp_region_type region_type)
8996 : {
8997 570 : switch (region_type)
8998 : {
8999 : case ORT_ACC_DATA:
9000 : return "data";
9001 140 : case ORT_ACC_PARALLEL:
9002 140 : return "parallel";
9003 140 : case ORT_ACC_KERNELS:
9004 140 : return "kernels";
9005 140 : case ORT_ACC_SERIAL:
9006 140 : return "serial";
9007 0 : default:
9008 0 : gcc_unreachable ();
9009 : }
9010 : }
9011 :
9012 : /* Determine outer default flags for DECL mentioned in an OACC region
9013 : but not declared in an enclosing clause. */
9014 :
9015 : static unsigned
9016 8839 : oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
9017 : {
9018 8839 : struct gimplify_omp_ctx *ctx_default = ctx;
9019 : /* If no 'default' clause appears on this compute construct... */
9020 8839 : if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED)
9021 : {
9022 : /* ..., see if one appears on a lexically containing 'data'
9023 : construct. */
9024 9618 : while ((ctx_default = ctx_default->outer_context))
9025 : {
9026 1534 : if (ctx_default->region_type == ORT_ACC_DATA
9027 1534 : && ctx_default->default_kind != OMP_CLAUSE_DEFAULT_SHARED)
9028 : break;
9029 : }
9030 : /* If not, reset. */
9031 8260 : if (!ctx_default)
9032 8663 : ctx_default = ctx;
9033 : }
9034 :
9035 8839 : bool on_device = false;
9036 8839 : bool is_private = false;
9037 8839 : bool declared = is_oacc_declared (decl);
9038 8839 : tree type = TREE_TYPE (decl);
9039 :
9040 8839 : if (omp_privatize_by_reference (decl))
9041 338 : type = TREE_TYPE (type);
9042 :
9043 : /* For Fortran COMMON blocks, only used variables in those blocks are
9044 : transferred and remapped. The block itself will have a private clause to
9045 : avoid transferring the data twice.
9046 : The hook evaluates to false by default. For a variable in Fortran's COMMON
9047 : or EQUIVALENCE block, returns 'true' (as we have shared=false) - as only
9048 : the variables in such a COMMON/EQUIVALENCE block shall be privatized not
9049 : the whole block. For C++ and Fortran, it can also be true under certain
9050 : other conditions, if DECL_HAS_VALUE_EXPR. */
9051 8839 : if (RECORD_OR_UNION_TYPE_P (type))
9052 983 : is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false);
9053 :
9054 8839 : if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0
9055 8839 : && is_global_var (decl)
9056 642 : && device_resident_p (decl)
9057 8839 : && !is_private)
9058 : {
9059 0 : on_device = true;
9060 0 : flags |= GOVD_MAP_TO_ONLY;
9061 : }
9062 :
9063 8839 : switch (ctx->region_type)
9064 : {
9065 1460 : case ORT_ACC_KERNELS:
9066 1460 : if (is_private)
9067 0 : flags |= GOVD_FIRSTPRIVATE;
9068 1460 : else if (AGGREGATE_TYPE_P (type))
9069 : {
9070 : /* Aggregates default to 'present_or_copy', or 'present'. */
9071 415 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9072 397 : flags |= GOVD_MAP;
9073 : else
9074 18 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9075 : }
9076 : else
9077 : /* Scalars default to 'copy'. */
9078 1045 : flags |= GOVD_MAP | GOVD_MAP_FORCE;
9079 :
9080 : break;
9081 :
9082 7379 : case ORT_ACC_PARALLEL:
9083 7379 : case ORT_ACC_SERIAL:
9084 7379 : if (is_private)
9085 0 : flags |= GOVD_FIRSTPRIVATE;
9086 7379 : else if (on_device || declared)
9087 17 : flags |= GOVD_MAP;
9088 7362 : else if (AGGREGATE_TYPE_P (type))
9089 : {
9090 : /* Aggregates default to 'present_or_copy', or 'present'. */
9091 3697 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9092 3431 : flags |= GOVD_MAP;
9093 : else
9094 266 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9095 : }
9096 : else
9097 : /* Scalars default to 'firstprivate'. */
9098 3665 : flags |= GOVD_FIRSTPRIVATE;
9099 :
9100 : break;
9101 :
9102 0 : default:
9103 0 : gcc_unreachable ();
9104 : }
9105 :
9106 8839 : if (DECL_ARTIFICIAL (decl))
9107 : ; /* We can get compiler-generated decls, and should not complain
9108 : about them. */
9109 8528 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_NONE)
9110 : {
9111 420 : error ("%qE not specified in enclosing OpenACC %qs construct",
9112 210 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)),
9113 : oacc_region_type_name (ctx->region_type));
9114 210 : if (ctx_default != ctx)
9115 150 : inform (ctx->location, "enclosing OpenACC %qs construct and",
9116 : oacc_region_type_name (ctx->region_type));
9117 210 : inform (ctx_default->location,
9118 : "enclosing OpenACC %qs construct with %qs clause",
9119 : oacc_region_type_name (ctx_default->region_type),
9120 : "default(none)");
9121 : }
9122 8318 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_PRESENT)
9123 : ; /* Handled above. */
9124 : else
9125 7785 : gcc_checking_assert (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED);
9126 :
9127 8839 : return flags;
9128 : }
9129 :
9130 : /* Record the fact that DECL was used within the OMP context CTX.
9131 : IN_CODE is true when real code uses DECL, and false when we should
9132 : merely emit default(none) errors. Return true if DECL is going to
9133 : be remapped and thus DECL shouldn't be gimplified into its
9134 : DECL_VALUE_EXPR (if any). */
9135 :
9136 : static bool
9137 3910584 : omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
9138 : {
9139 3910584 : splay_tree_node n;
9140 3910584 : unsigned flags = in_code ? GOVD_SEEN : 0;
9141 3910584 : bool ret = false, shared;
9142 :
9143 3910584 : if (error_operand_p (decl))
9144 : return false;
9145 :
9146 3910584 : if (DECL_ARTIFICIAL (decl))
9147 : {
9148 2233835 : tree attr = lookup_attribute ("omp allocate var", DECL_ATTRIBUTES (decl));
9149 2233835 : if (attr)
9150 543 : decl = TREE_VALUE (TREE_VALUE (attr));
9151 : }
9152 :
9153 3910584 : if (ctx->region_type == ORT_NONE)
9154 248 : return lang_hooks.decls.omp_disregard_value_expr (decl, false);
9155 :
9156 3910336 : if (is_global_var (decl))
9157 : {
9158 : /* Threadprivate variables are predetermined. */
9159 501812 : if (DECL_THREAD_LOCAL_P (decl))
9160 13565 : return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
9161 :
9162 488247 : if (DECL_HAS_VALUE_EXPR_P (decl))
9163 : {
9164 4380 : if (ctx->region_type & ORT_ACC)
9165 : /* For OpenACC, defer expansion of value to avoid transferring
9166 : privatized common block data instead of im-/explicitly
9167 : transferred variables which are in common blocks. */
9168 : ;
9169 : else
9170 : {
9171 2104 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
9172 :
9173 2104 : if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
9174 618 : return omp_notice_threadprivate_variable (ctx, decl, value);
9175 : }
9176 : }
9177 :
9178 487629 : if (gimplify_omp_ctxp->outer_context == NULL
9179 113735 : && VAR_P (decl)
9180 601364 : && oacc_get_fn_attrib (current_function_decl))
9181 : {
9182 765 : location_t loc = DECL_SOURCE_LOCATION (decl);
9183 :
9184 765 : if (lookup_attribute ("omp declare target link",
9185 765 : DECL_ATTRIBUTES (decl)))
9186 : {
9187 48 : error_at (loc,
9188 : "%qE with %<link%> clause used in %<routine%> function",
9189 24 : DECL_NAME (decl));
9190 24 : return false;
9191 : }
9192 741 : else if (!lookup_attribute ("omp declare target",
9193 741 : DECL_ATTRIBUTES (decl)))
9194 : {
9195 132 : error_at (loc,
9196 : "%qE requires a %<declare%> directive for use "
9197 66 : "in a %<routine%> function", DECL_NAME (decl));
9198 66 : return false;
9199 : }
9200 : }
9201 : }
9202 :
9203 3896063 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9204 3896063 : if ((ctx->region_type & ORT_TARGET) != 0)
9205 : {
9206 850824 : if (n == NULL)
9207 : {
9208 45055 : unsigned nflags = flags;
9209 45055 : if ((ctx->region_type & ORT_ACC) == 0)
9210 : {
9211 34101 : bool is_declare_target = false;
9212 34101 : if (is_global_var (decl)
9213 34101 : && varpool_node::get_create (decl)->offloadable)
9214 : {
9215 7002 : struct gimplify_omp_ctx *octx;
9216 7002 : for (octx = ctx->outer_context;
9217 7010 : octx; octx = octx->outer_context)
9218 : {
9219 9 : n = splay_tree_lookup (octx->variables,
9220 : (splay_tree_key)decl);
9221 9 : if (n
9222 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED
9223 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
9224 : break;
9225 : }
9226 7002 : is_declare_target = octx == NULL;
9227 : }
9228 7002 : if (!is_declare_target)
9229 : {
9230 27100 : int gdmk;
9231 27100 : enum omp_clause_defaultmap_kind kind;
9232 27100 : if (lang_hooks.decls.omp_allocatable_p (decl))
9233 : gdmk = GDMK_ALLOCATABLE;
9234 26753 : else if (lang_hooks.decls.omp_scalar_target_p (decl))
9235 : gdmk = GDMK_SCALAR_TARGET;
9236 26678 : else if (lang_hooks.decls.omp_scalar_p (decl, false))
9237 : gdmk = GDMK_SCALAR;
9238 11164 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
9239 11164 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
9240 3102 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
9241 : == POINTER_TYPE)))
9242 : gdmk = GDMK_POINTER;
9243 : else
9244 : gdmk = GDMK_AGGREGATE;
9245 27100 : kind = lang_hooks.decls.omp_predetermined_mapping (decl);
9246 27100 : if (kind != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
9247 : {
9248 1096 : if (kind == OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE)
9249 101 : nflags |= GOVD_FIRSTPRIVATE;
9250 995 : else if (kind == OMP_CLAUSE_DEFAULTMAP_TO)
9251 995 : nflags |= GOVD_MAP | GOVD_MAP_TO_ONLY;
9252 : else
9253 0 : gcc_unreachable ();
9254 : }
9255 26004 : else if (ctx->defaultmap[gdmk] == 0)
9256 : {
9257 77 : tree d = lang_hooks.decls.omp_report_decl (decl);
9258 77 : error ("%qE not specified in enclosing %<target%>",
9259 77 : DECL_NAME (d));
9260 77 : inform (ctx->location, "enclosing %<target%>");
9261 : }
9262 25927 : else if (ctx->defaultmap[gdmk]
9263 25927 : & (GOVD_MAP_0LEN_ARRAY | GOVD_FIRSTPRIVATE))
9264 9125 : nflags |= ctx->defaultmap[gdmk];
9265 16802 : else if (ctx->defaultmap[gdmk] & GOVD_MAP_FORCE_PRESENT)
9266 : {
9267 42 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9268 42 : nflags |= ctx->defaultmap[gdmk] | GOVD_MAP_ALLOC_ONLY;
9269 : }
9270 : else
9271 : {
9272 16760 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9273 16760 : nflags |= ctx->defaultmap[gdmk] & ~GOVD_MAP;
9274 : }
9275 : }
9276 : }
9277 :
9278 45055 : struct gimplify_omp_ctx *octx = ctx->outer_context;
9279 45055 : if ((ctx->region_type & ORT_ACC) && octx)
9280 : {
9281 : /* Look in outer OpenACC contexts, to see if there's a
9282 : data attribute for this variable. */
9283 3535 : omp_notice_variable (octx, decl, in_code);
9284 :
9285 5307 : for (; octx; octx = octx->outer_context)
9286 : {
9287 3883 : if (!(octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)))
9288 : break;
9289 3883 : splay_tree_node n2
9290 3883 : = splay_tree_lookup (octx->variables,
9291 : (splay_tree_key) decl);
9292 3883 : if (n2)
9293 : {
9294 2111 : if (octx->region_type == ORT_ACC_HOST_DATA)
9295 4 : error ("variable %qE declared in enclosing "
9296 4 : "%<host_data%> region", DECL_NAME (decl));
9297 2111 : nflags |= GOVD_MAP;
9298 2111 : if (octx->region_type == ORT_ACC_DATA
9299 2107 : && (n2->value & GOVD_MAP_0LEN_ARRAY))
9300 288 : nflags |= GOVD_MAP_0LEN_ARRAY;
9301 2111 : goto found_outer;
9302 : }
9303 : }
9304 : }
9305 :
9306 42944 : if ((nflags & ~(GOVD_MAP_TO_ONLY | GOVD_MAP_FROM_ONLY
9307 : | GOVD_MAP_ALLOC_ONLY)) == flags)
9308 : {
9309 32681 : tree type = TREE_TYPE (decl);
9310 32681 : location_t loc = DECL_SOURCE_LOCATION (decl);
9311 :
9312 32681 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases
9313 32681 : && omp_privatize_by_reference (decl))
9314 28 : type = TREE_TYPE (type);
9315 :
9316 32681 : if (!verify_type_context (loc, TCTX_OMP_MAP_IMP_REF, type))
9317 : /* Check if TYPE can appear in a target region.
9318 : verify_type_context has already issued an error if it
9319 : can't. */
9320 0 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9321 32681 : else if (!omp_mappable_type (type))
9322 : {
9323 8 : error ("%qD referenced in target region does not have "
9324 : "a mappable type", decl);
9325 8 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9326 : }
9327 : else
9328 : {
9329 32673 : if ((ctx->region_type & ORT_ACC) != 0)
9330 8839 : nflags = oacc_default_clause (ctx, decl, flags);
9331 : else
9332 23834 : nflags |= GOVD_MAP;
9333 : }
9334 : }
9335 10263 : found_outer:
9336 45055 : omp_add_variable (ctx, decl, nflags);
9337 45055 : if (ctx->region_type & ORT_ACC)
9338 : /* For OpenACC, as remarked above, defer expansion. */
9339 : shared = false;
9340 : else
9341 34101 : shared = (nflags & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9342 45055 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9343 : }
9344 : else
9345 : {
9346 805769 : if (ctx->region_type & ORT_ACC)
9347 : /* For OpenACC, as remarked above, defer expansion. */
9348 : shared = false;
9349 : else
9350 509344 : shared = ((n->value | flags)
9351 509344 : & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9352 805769 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9353 : /* If nothing changed, there's nothing left to do. */
9354 805769 : if ((n->value & flags) == flags)
9355 : return ret;
9356 16549 : flags |= n->value;
9357 16549 : n->value = flags;
9358 : }
9359 61604 : goto do_outer;
9360 : }
9361 :
9362 3045239 : if (n == NULL)
9363 : {
9364 1181884 : if (ctx->region_type == ORT_WORKSHARE
9365 : || ctx->region_type == ORT_TASKGROUP
9366 560831 : || ctx->region_type == ORT_SIMD
9367 288788 : || ctx->region_type == ORT_ACC
9368 92535 : || (ctx->region_type & ORT_TARGET_DATA) != 0)
9369 1134002 : goto do_outer;
9370 :
9371 47882 : flags = omp_default_clause (ctx, decl, in_code, flags);
9372 :
9373 47882 : if ((flags & GOVD_PRIVATE)
9374 47882 : && lang_hooks.decls.omp_private_outer_ref (decl))
9375 6 : flags |= GOVD_PRIVATE_OUTER_REF;
9376 :
9377 47882 : omp_add_variable (ctx, decl, flags);
9378 :
9379 47882 : shared = (flags & GOVD_SHARED) != 0;
9380 47882 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9381 47882 : goto do_outer;
9382 : }
9383 :
9384 : /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd
9385 : lb, b or incr expressions, those shouldn't be turned into simd arrays. */
9386 1863355 : if (ctx->region_type == ORT_SIMD
9387 151155 : && ctx->in_for_exprs
9388 70 : && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT))
9389 : == GOVD_PRIVATE))
9390 1863355 : flags &= ~GOVD_SEEN;
9391 :
9392 1863355 : if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
9393 31870 : && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
9394 1895186 : && DECL_SIZE (decl))
9395 : {
9396 31830 : tree size;
9397 31830 : if (!poly_int_tree_p (DECL_SIZE (decl)))
9398 : {
9399 148 : splay_tree_node n2;
9400 148 : tree t = DECL_VALUE_EXPR (decl);
9401 148 : gcc_assert (INDIRECT_REF_P (t));
9402 148 : t = TREE_OPERAND (t, 0);
9403 148 : gcc_assert (DECL_P (t));
9404 148 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
9405 148 : n2->value |= GOVD_SEEN;
9406 : }
9407 31682 : else if (omp_privatize_by_reference (decl)
9408 4193 : && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
9409 35838 : && !poly_int_tree_p (size))
9410 : {
9411 1337 : splay_tree_node n2;
9412 1337 : gcc_assert (DECL_P (size));
9413 1337 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size);
9414 1337 : if (n2)
9415 629 : omp_notice_variable (ctx, size, true);
9416 : }
9417 : }
9418 :
9419 1863355 : if (ctx->region_type & ORT_ACC)
9420 : /* For OpenACC, as remarked above, defer expansion. */
9421 : shared = false;
9422 : else
9423 1681420 : shared = ((flags | n->value) & GOVD_SHARED) != 0;
9424 1863355 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9425 :
9426 : /* If nothing changed, there's nothing left to do. */
9427 1863355 : if ((n->value & flags) == flags)
9428 : return ret;
9429 31831 : flags |= n->value;
9430 31831 : n->value = flags;
9431 :
9432 1275319 : do_outer:
9433 : /* If the variable is private in the current context, then we don't
9434 : need to propagate anything to an outer context. */
9435 1275319 : if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF))
9436 : return ret;
9437 1264933 : if ((flags & (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9438 : == (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9439 : return ret;
9440 1264873 : if ((flags & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
9441 : | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9442 : == (GOVD_LASTPRIVATE | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9443 : return ret;
9444 1264873 : if (ctx->outer_context
9445 1264873 : && omp_notice_variable (ctx->outer_context, decl, in_code))
9446 : return true;
9447 : return ret;
9448 : }
9449 :
9450 : /* Verify that DECL is private within CTX. If there's specific information
9451 : to the contrary in the innermost scope, generate an error. */
9452 :
9453 : static bool
9454 50137 : omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd)
9455 : {
9456 95834 : splay_tree_node n;
9457 :
9458 95834 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9459 95834 : if (n != NULL)
9460 : {
9461 17960 : if (n->value & GOVD_SHARED)
9462 : {
9463 407 : if (ctx == gimplify_omp_ctxp)
9464 : {
9465 0 : if (simd)
9466 0 : error ("iteration variable %qE is predetermined linear",
9467 0 : DECL_NAME (decl));
9468 : else
9469 0 : error ("iteration variable %qE should be private",
9470 0 : DECL_NAME (decl));
9471 0 : n->value = GOVD_PRIVATE;
9472 0 : return true;
9473 : }
9474 : else
9475 : return false;
9476 : }
9477 17553 : else if ((n->value & GOVD_EXPLICIT) != 0
9478 9711 : && (ctx == gimplify_omp_ctxp
9479 340 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9480 220 : && gimplify_omp_ctxp->outer_context == ctx)))
9481 : {
9482 9591 : if ((n->value & GOVD_FIRSTPRIVATE) != 0)
9483 4 : error ("iteration variable %qE should not be firstprivate",
9484 4 : DECL_NAME (decl));
9485 9587 : else if ((n->value & GOVD_REDUCTION) != 0)
9486 8 : error ("iteration variable %qE should not be reduction",
9487 8 : DECL_NAME (decl));
9488 9579 : else if (simd != 1 && (n->value & GOVD_LINEAR) != 0)
9489 58 : error ("iteration variable %qE should not be linear",
9490 58 : DECL_NAME (decl));
9491 : }
9492 17553 : return (ctx == gimplify_omp_ctxp
9493 17553 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9494 19435 : && gimplify_omp_ctxp->outer_context == ctx));
9495 : }
9496 :
9497 77874 : if (ctx->region_type != ORT_WORKSHARE
9498 : && ctx->region_type != ORT_TASKGROUP
9499 49422 : && ctx->region_type != ORT_SIMD
9500 36157 : && ctx->region_type != ORT_ACC)
9501 : return false;
9502 53890 : else if (ctx->outer_context)
9503 : return omp_is_private (ctx->outer_context, decl, simd);
9504 : return false;
9505 : }
9506 :
9507 : /* Return true if DECL is private within a parallel region
9508 : that binds to the current construct's context or in parallel
9509 : region's REDUCTION clause. */
9510 :
9511 : static bool
9512 11547 : omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
9513 : {
9514 11619 : splay_tree_node n;
9515 :
9516 11619 : do
9517 : {
9518 11619 : ctx = ctx->outer_context;
9519 11619 : if (ctx == NULL)
9520 : {
9521 2764 : if (is_global_var (decl))
9522 : return false;
9523 :
9524 : /* References might be private, but might be shared too,
9525 : when checking for copyprivate, assume they might be
9526 : private, otherwise assume they might be shared. */
9527 1290 : if (copyprivate)
9528 : return true;
9529 :
9530 1244 : if (omp_privatize_by_reference (decl))
9531 : return false;
9532 :
9533 : /* Treat C++ privatized non-static data members outside
9534 : of the privatization the same. */
9535 1198 : if (omp_member_access_dummy_var (decl))
9536 : return false;
9537 :
9538 : return true;
9539 : }
9540 :
9541 8855 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
9542 :
9543 8855 : if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
9544 1291 : && (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0))
9545 : {
9546 242 : if ((ctx->region_type & ORT_TARGET_DATA) != 0
9547 238 : || n == NULL
9548 230 : || (n->value & GOVD_MAP) == 0)
9549 12 : continue;
9550 : return false;
9551 : }
9552 :
9553 7564 : if (n != NULL)
9554 : {
9555 5360 : if ((n->value & GOVD_LOCAL) != 0
9556 5360 : && omp_member_access_dummy_var (decl))
9557 : return false;
9558 5321 : return (n->value & GOVD_SHARED) == 0;
9559 : }
9560 :
9561 3253 : if (ctx->region_type == ORT_WORKSHARE
9562 : || ctx->region_type == ORT_TASKGROUP
9563 3197 : || ctx->region_type == ORT_SIMD
9564 3193 : || ctx->region_type == ORT_ACC)
9565 60 : continue;
9566 :
9567 : break;
9568 : }
9569 : while (1);
9570 : return false;
9571 : }
9572 :
9573 : /* Callback for walk_tree to find a DECL_EXPR for the given DECL. */
9574 :
9575 : static tree
9576 3148 : find_decl_expr (tree *tp, int *walk_subtrees, void *data)
9577 : {
9578 3148 : tree t = *tp;
9579 :
9580 : /* If this node has been visited, unmark it and keep looking. */
9581 3148 : if (TREE_CODE (t) == DECL_EXPR && DECL_EXPR_DECL (t) == (tree) data)
9582 : return t;
9583 :
9584 2724 : if (IS_TYPE_OR_DECL_P (t))
9585 452 : *walk_subtrees = 0;
9586 : return NULL_TREE;
9587 : }
9588 :
9589 :
9590 : /* Gimplify the affinity clause but effectively ignore it.
9591 : Generate:
9592 : var = begin;
9593 : if ((step > 1) ? var <= end : var > end)
9594 : locatator_var_expr; */
9595 :
9596 : static void
9597 374 : gimplify_omp_affinity (tree *list_p, gimple_seq *pre_p)
9598 : {
9599 374 : tree last_iter = NULL_TREE;
9600 374 : tree last_bind = NULL_TREE;
9601 374 : tree label = NULL_TREE;
9602 374 : tree *last_body = NULL;
9603 1011 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9604 637 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
9605 : {
9606 637 : tree t = OMP_CLAUSE_DECL (c);
9607 637 : if (OMP_ITERATOR_DECL_P (t))
9608 : {
9609 389 : if (TREE_VALUE (t) == null_pointer_node)
9610 201 : continue;
9611 188 : if (TREE_PURPOSE (t) != last_iter)
9612 : {
9613 127 : if (last_bind)
9614 : {
9615 9 : append_to_statement_list (label, last_body);
9616 9 : gimplify_and_add (last_bind, pre_p);
9617 9 : last_bind = NULL_TREE;
9618 : }
9619 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9620 : {
9621 147 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
9622 : is_gimple_val, fb_rvalue) == GS_ERROR
9623 147 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
9624 : is_gimple_val, fb_rvalue) == GS_ERROR
9625 147 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
9626 : is_gimple_val, fb_rvalue) == GS_ERROR
9627 294 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
9628 : is_gimple_val, fb_rvalue)
9629 : == GS_ERROR))
9630 0 : return;
9631 : }
9632 127 : last_iter = TREE_PURPOSE (t);
9633 127 : tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 5);
9634 127 : last_bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
9635 : NULL, block);
9636 127 : last_body = &BIND_EXPR_BODY (last_bind);
9637 127 : tree cond = NULL_TREE;
9638 127 : location_t loc = OMP_CLAUSE_LOCATION (c);
9639 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9640 : {
9641 147 : tree var = TREE_VEC_ELT (it, 0);
9642 147 : tree begin = TREE_VEC_ELT (it, 1);
9643 147 : tree end = TREE_VEC_ELT (it, 2);
9644 147 : tree step = TREE_VEC_ELT (it, 3);
9645 147 : loc = DECL_SOURCE_LOCATION (var);
9646 147 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
9647 : var, begin);
9648 147 : append_to_statement_list_force (tem, last_body);
9649 :
9650 147 : tree cond1 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9651 147 : step, build_zero_cst (TREE_TYPE (step)));
9652 147 : tree cond2 = fold_build2_loc (loc, LE_EXPR, boolean_type_node,
9653 : var, end);
9654 147 : tree cond3 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9655 : var, end);
9656 147 : cond1 = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
9657 : cond1, cond2, cond3);
9658 147 : if (cond)
9659 20 : cond = fold_build2_loc (loc, TRUTH_AND_EXPR,
9660 : boolean_type_node, cond, cond1);
9661 : else
9662 : cond = cond1;
9663 : }
9664 127 : tree cont_label = create_artificial_label (loc);
9665 127 : label = build1 (LABEL_EXPR, void_type_node, cont_label);
9666 127 : tree tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9667 : void_node,
9668 : build_and_jump (&cont_label));
9669 127 : append_to_statement_list_force (tem, last_body);
9670 : }
9671 188 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
9672 : {
9673 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t), 0),
9674 : last_body);
9675 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
9676 : }
9677 188 : if (error_operand_p (TREE_VALUE (t)))
9678 : return;
9679 188 : append_to_statement_list_force (TREE_VALUE (t), last_body);
9680 188 : TREE_VALUE (t) = null_pointer_node;
9681 : }
9682 : else
9683 : {
9684 248 : if (last_bind)
9685 : {
9686 9 : append_to_statement_list (label, last_body);
9687 9 : gimplify_and_add (last_bind, pre_p);
9688 9 : last_bind = NULL_TREE;
9689 : }
9690 248 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
9691 : {
9692 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
9693 : NULL, is_gimple_val, fb_rvalue);
9694 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
9695 : }
9696 248 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
9697 : return;
9698 248 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
9699 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
9700 : return;
9701 248 : gimplify_and_add (OMP_CLAUSE_DECL (c), pre_p);
9702 : }
9703 : }
9704 374 : if (last_bind)
9705 : {
9706 109 : append_to_statement_list (label, last_body);
9707 109 : gimplify_and_add (last_bind, pre_p);
9708 : }
9709 : return;
9710 : }
9711 :
9712 : /* Returns a tree expression containing the total iteration count of the
9713 : OpenMP iterator IT. */
9714 :
9715 : static tree
9716 379 : compute_omp_iterator_count (tree it, gimple_seq *pre_p)
9717 : {
9718 379 : tree tcnt = size_one_node;
9719 837 : for (; it; it = TREE_CHAIN (it))
9720 : {
9721 458 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
9722 : is_gimple_val, fb_rvalue) == GS_ERROR
9723 458 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
9724 : is_gimple_val, fb_rvalue) == GS_ERROR
9725 458 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
9726 : is_gimple_val, fb_rvalue) == GS_ERROR
9727 916 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
9728 : is_gimple_val, fb_rvalue) == GS_ERROR))
9729 0 : return NULL_TREE;
9730 458 : tree var = TREE_VEC_ELT (it, 0);
9731 458 : tree begin = TREE_VEC_ELT (it, 1);
9732 458 : tree end = TREE_VEC_ELT (it, 2);
9733 458 : tree step = TREE_VEC_ELT (it, 3);
9734 458 : tree orig_step = TREE_VEC_ELT (it, 4);
9735 458 : tree type = TREE_TYPE (var);
9736 458 : tree stype = TREE_TYPE (step);
9737 458 : location_t loc = DECL_SOURCE_LOCATION (var);
9738 458 : tree endmbegin;
9739 : /* Compute count for this iterator as
9740 : orig_step > 0
9741 : ? (begin < end ? (end - begin + (step - 1)) / step : 0)
9742 : : (begin > end ? (end - begin + (step + 1)) / step : 0)
9743 : and compute product of those for the entire clause. */
9744 458 : if (POINTER_TYPE_P (type))
9745 42 : endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR, stype, end, begin);
9746 : else
9747 416 : endmbegin = fold_build2_loc (loc, MINUS_EXPR, type, end, begin);
9748 : /* Account for iteration stopping on the end value in Fortran rather
9749 : than before it. */
9750 458 : tree stepm1 = step;
9751 458 : tree stepp1 = step;
9752 458 : if (!lang_GNU_Fortran ())
9753 : {
9754 360 : stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype, step,
9755 : build_int_cst (stype, 1));
9756 360 : stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
9757 : build_int_cst (stype, 1));
9758 : }
9759 458 : tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
9760 : unshare_expr (endmbegin), stepm1);
9761 458 : pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, pos, step);
9762 458 : tree neg = fold_build2_loc (loc, PLUS_EXPR, stype, endmbegin, stepp1);
9763 458 : if (TYPE_UNSIGNED (stype))
9764 : {
9765 31 : neg = fold_build1_loc (loc, NEGATE_EXPR, stype, neg);
9766 31 : step = fold_build1_loc (loc, NEGATE_EXPR, stype, step);
9767 : }
9768 458 : neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, neg, step);
9769 458 : step = NULL_TREE;
9770 458 : tree_code cmp_op = lang_GNU_Fortran () ? LE_EXPR : LT_EXPR;
9771 458 : tree cond = fold_build2_loc (loc, cmp_op, boolean_type_node, begin, end);
9772 458 : pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
9773 : build_int_cst (stype, 0));
9774 458 : cond = fold_build2_loc (loc, cmp_op, boolean_type_node, end, begin);
9775 458 : neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
9776 : build_int_cst (stype, 0));
9777 458 : tree osteptype = TREE_TYPE (orig_step);
9778 458 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9779 : build_int_cst (osteptype, 0));
9780 458 : tree cnt = fold_build3_loc (loc, COND_EXPR, stype, cond, pos, neg);
9781 458 : cnt = fold_convert_loc (loc, sizetype, cnt);
9782 458 : if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
9783 : fb_rvalue) == GS_ERROR)
9784 : return NULL_TREE;
9785 458 : tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
9786 : }
9787 379 : if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
9788 : return NULL_TREE;
9789 :
9790 379 : return tcnt;
9791 : }
9792 :
9793 : /* Build loops iterating over the space defined by the OpenMP iterator IT.
9794 : Returns a pointer to the BIND_EXPR_BODY in the innermost loop body.
9795 : LAST_BIND is set to point to the BIND_EXPR containing the whole loop. */
9796 :
9797 : static tree *
9798 379 : build_omp_iterator_loop (tree it, gimple_seq *pre_p, tree *last_bind)
9799 : {
9800 379 : if (*last_bind)
9801 31 : gimplify_and_add (*last_bind, pre_p);
9802 379 : tree block = TREE_VEC_ELT (it, 5);
9803 464 : tree block_stmts = lang_GNU_Fortran () ? BLOCK_SUBBLOCKS (block) : NULL_TREE;
9804 379 : *last_bind = build3 (BIND_EXPR, void_type_node,
9805 379 : BLOCK_VARS (block), NULL, block);
9806 379 : TREE_SIDE_EFFECTS (*last_bind) = 1;
9807 379 : tree *p = &BIND_EXPR_BODY (*last_bind);
9808 837 : for (; it; it = TREE_CHAIN (it))
9809 : {
9810 458 : tree var = TREE_VEC_ELT (it, 0);
9811 458 : tree begin = TREE_VEC_ELT (it, 1);
9812 458 : tree end = TREE_VEC_ELT (it, 2);
9813 458 : tree step = TREE_VEC_ELT (it, 3);
9814 458 : tree orig_step = TREE_VEC_ELT (it, 4);
9815 458 : block = TREE_VEC_ELT (it, 5);
9816 458 : tree type = TREE_TYPE (var);
9817 458 : location_t loc = DECL_SOURCE_LOCATION (var);
9818 : /* Emit:
9819 : var = begin;
9820 : goto cond_label;
9821 : beg_label:
9822 : ...
9823 : var = var + step;
9824 : cond_label:
9825 : if (orig_step > 0) {
9826 : if (var < end) goto beg_label; // <= for Fortran
9827 : } else {
9828 : if (var > end) goto beg_label; // >= for Fortran
9829 : }
9830 : for each iterator, with inner iterators added to
9831 : the ... above. */
9832 458 : tree beg_label = create_artificial_label (loc);
9833 458 : tree cond_label = NULL_TREE;
9834 458 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, begin);
9835 458 : append_to_statement_list_force (tem, p);
9836 458 : tem = build_and_jump (&cond_label);
9837 458 : append_to_statement_list_force (tem, p);
9838 458 : tem = build1 (LABEL_EXPR, void_type_node, beg_label);
9839 458 : append_to_statement_list (tem, p);
9840 458 : tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
9841 : NULL_TREE, NULL_TREE);
9842 458 : TREE_SIDE_EFFECTS (bind) = 1;
9843 458 : SET_EXPR_LOCATION (bind, loc);
9844 458 : append_to_statement_list_force (bind, p);
9845 458 : if (POINTER_TYPE_P (type))
9846 42 : tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
9847 : var, fold_convert_loc (loc, sizetype, step));
9848 : else
9849 416 : tem = build2_loc (loc, PLUS_EXPR, type, var, step);
9850 458 : tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, tem);
9851 458 : append_to_statement_list_force (tem, p);
9852 458 : tem = build1 (LABEL_EXPR, void_type_node, cond_label);
9853 458 : append_to_statement_list (tem, p);
9854 818 : tree cond = fold_build2_loc (loc, lang_GNU_Fortran () ? LE_EXPR : LT_EXPR,
9855 : boolean_type_node, var, end);
9856 458 : tree pos = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9857 : build_and_jump (&beg_label), void_node);
9858 818 : cond = fold_build2_loc (loc, lang_GNU_Fortran () ? GE_EXPR : GT_EXPR,
9859 : boolean_type_node, var, end);
9860 458 : tree neg = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9861 : build_and_jump (&beg_label), void_node);
9862 458 : tree osteptype = TREE_TYPE (orig_step);
9863 458 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9864 : build_int_cst (osteptype, 0));
9865 458 : tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, pos, neg);
9866 458 : append_to_statement_list_force (tem, p);
9867 458 : p = &BIND_EXPR_BODY (bind);
9868 : /* The Fortran front-end stashes statements into the BLOCK_SUBBLOCKS
9869 : of the last element of the first iterator. These should go into the
9870 : body of the innermost loop. */
9871 458 : if (!TREE_CHAIN (it))
9872 379 : append_to_statement_list_force (block_stmts, p);
9873 : }
9874 :
9875 379 : return p;
9876 : }
9877 :
9878 :
9879 : /* Callback for walk_tree to find a VAR_DECL (stored in DATA) in the
9880 : tree TP. */
9881 :
9882 : static tree
9883 3813 : find_var_decl (tree *tp, int *, void *data)
9884 : {
9885 3813 : if (*tp == (tree) data)
9886 357 : return *tp;
9887 :
9888 : return NULL_TREE;
9889 : }
9890 :
9891 : /* Returns an element-by-element copy of OMP iterator tree IT. */
9892 :
9893 : static tree
9894 337 : copy_omp_iterator (tree it, int elem_count = -1)
9895 : {
9896 337 : if (elem_count < 0)
9897 74 : elem_count = TREE_VEC_LENGTH (it);
9898 337 : tree new_it = make_tree_vec (elem_count);
9899 2359 : for (int i = 0; i < TREE_VEC_LENGTH (it); i++)
9900 2022 : TREE_VEC_ELT (new_it, i) = TREE_VEC_ELT (it, i);
9901 :
9902 337 : return new_it;
9903 : }
9904 :
9905 : /* Helper function for walk_tree in remap_omp_iterator_var. */
9906 :
9907 : static tree
9908 1063 : remap_omp_iterator_var_1 (tree *tp, int *, void *data)
9909 : {
9910 1063 : tree old_var = ((tree *) data)[0];
9911 1063 : tree new_var = ((tree *) data)[1];
9912 :
9913 1063 : if (*tp == old_var)
9914 106 : *tp = new_var;
9915 1063 : return NULL_TREE;
9916 : }
9917 :
9918 : /* Replace instances of OLD_VAR in TP with NEW_VAR. */
9919 :
9920 : static void
9921 212 : remap_omp_iterator_var (tree *tp, tree old_var, tree new_var)
9922 : {
9923 212 : tree vars[2] = { old_var, new_var };
9924 212 : walk_tree (tp, remap_omp_iterator_var_1, vars, NULL);
9925 212 : }
9926 :
9927 : /* Scan through all clauses using OpenMP iterators in LIST_P. If any
9928 : clauses have iterators with variables that are not used by the clause
9929 : decl or size, issue a warning and replace the iterator with a copy with
9930 : the unused variables removed. */
9931 :
9932 : static void
9933 27661 : remove_unused_omp_iterator_vars (tree *list_p)
9934 : {
9935 27661 : auto_vec< vec<tree> > iter_vars;
9936 27661 : auto_vec<tree> new_iterators;
9937 :
9938 80586 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9939 : {
9940 52925 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
9941 52861 : continue;
9942 276 : auto_vec<tree> vars;
9943 276 : bool need_new_iterators = false;
9944 710 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
9945 : {
9946 434 : tree var = TREE_VEC_ELT (it, 0);
9947 434 : tree t = walk_tree (&OMP_CLAUSE_DECL (c), find_var_decl, var, NULL);
9948 434 : if (t == NULL_TREE)
9949 143 : t = walk_tree (&OMP_CLAUSE_SIZE (c), find_var_decl, var, NULL);
9950 143 : if (t == NULL_TREE)
9951 : need_new_iterators = true;
9952 : else
9953 357 : vars.safe_push (var);
9954 : }
9955 276 : if (!need_new_iterators)
9956 199 : continue;
9957 77 : if (vars.is_empty ())
9958 : {
9959 : /* No iteration variables are used in the clause - remove the
9960 : iterator from the clause. */
9961 13 : OMP_CLAUSE_ITERATORS (c) = NULL_TREE;
9962 13 : continue;
9963 : }
9964 :
9965 : /* If a new iterator has been created for the current set of used
9966 : iterator variables, then use that as the iterator. Otherwise,
9967 : create a new iterator for the current iterator variable set. */
9968 : unsigned i;
9969 106 : for (i = 0; i < iter_vars.length (); i++)
9970 : {
9971 124 : if (vars.length () != iter_vars[i].length ())
9972 0 : continue;
9973 : bool identical_p = true;
9974 150 : for (unsigned j = 0; j < vars.length () && identical_p; j++)
9975 88 : identical_p = vars[j] == iter_vars[i][j];
9976 :
9977 62 : if (identical_p)
9978 : break;
9979 : }
9980 64 : if (i < iter_vars.length ())
9981 20 : OMP_CLAUSE_ITERATORS (c) = new_iterators[i];
9982 : else
9983 : {
9984 44 : tree new_iters = NULL_TREE;
9985 44 : tree *new_iters_p = &new_iters;
9986 44 : tree new_vars = NULL_TREE;
9987 44 : tree *new_vars_p = &new_vars;
9988 44 : i = 0;
9989 140 : for (tree it = OMP_CLAUSE_ITERATORS (c); it && i < vars.length();
9990 96 : it = TREE_CHAIN (it))
9991 : {
9992 96 : tree var = TREE_VEC_ELT (it, 0);
9993 96 : if (var == vars[i])
9994 : {
9995 74 : *new_iters_p = copy_omp_iterator (it);
9996 74 : *new_vars_p = build_decl (OMP_CLAUSE_LOCATION (c), VAR_DECL,
9997 74 : DECL_NAME (var), TREE_TYPE (var));
9998 74 : DECL_ARTIFICIAL (*new_vars_p) = 1;
9999 74 : DECL_CONTEXT (*new_vars_p) = DECL_CONTEXT (var);
10000 74 : TREE_VEC_ELT (*new_iters_p, 0) = *new_vars_p;
10001 74 : new_iters_p = &TREE_CHAIN (*new_iters_p);
10002 74 : new_vars_p = &DECL_CHAIN (*new_vars_p);
10003 74 : i++;
10004 : }
10005 : }
10006 44 : tree old_block = TREE_VEC_ELT (OMP_CLAUSE_ITERATORS (c), 5);
10007 44 : tree new_block = make_node (BLOCK);
10008 44 : BLOCK_VARS (new_block) = new_vars;
10009 44 : if (BLOCK_SUBBLOCKS (old_block))
10010 : {
10011 4 : BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block);
10012 4 : BLOCK_SUBBLOCKS (old_block) = NULL_TREE;
10013 : }
10014 44 : TREE_VEC_ELT (new_iters, 5) = new_block;
10015 44 : new_iterators.safe_push (new_iters);
10016 44 : iter_vars.safe_push (vars.copy ());
10017 44 : OMP_CLAUSE_ITERATORS (c) = new_iters;
10018 : }
10019 :
10020 : /* Remap clause to use the new variables. */
10021 64 : i = 0;
10022 170 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
10023 : {
10024 106 : tree old_var = vars[i++];
10025 106 : tree new_var = TREE_VEC_ELT (it, 0);
10026 106 : remap_omp_iterator_var (&OMP_CLAUSE_DECL (c), old_var, new_var);
10027 106 : remap_omp_iterator_var (&OMP_CLAUSE_SIZE (c), old_var, new_var);
10028 : }
10029 276 : }
10030 :
10031 27705 : for (unsigned i = 0; i < iter_vars.length (); i++)
10032 44 : iter_vars[i].release ();
10033 27661 : }
10034 :
10035 248 : struct iterator_loop_info_t
10036 : {
10037 : tree bind;
10038 : tree count;
10039 : tree index;
10040 : tree body_label;
10041 : auto_vec<tree> clauses;
10042 : };
10043 :
10044 : typedef hash_map<tree, iterator_loop_info_t> iterator_loop_info_map_t;
10045 :
10046 : /* Builds a loop to expand any OpenMP iterators in the clauses in LIST_P,
10047 : reusing any previously built loops if they use the same set of iterators.
10048 : Generated Gimple statements are placed into LOOPS_SEQ_P. The clause
10049 : iterators are updated with information on how and where to insert code into
10050 : the loop body. */
10051 :
10052 : static void
10053 27661 : build_omp_iterators_loops (tree *list_p, gimple_seq *loops_seq_p)
10054 : {
10055 27661 : iterator_loop_info_map_t loops;
10056 :
10057 80586 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10058 : {
10059 52925 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10060 52662 : continue;
10061 :
10062 263 : bool built_p;
10063 263 : iterator_loop_info_t &loop
10064 263 : = loops.get_or_insert (OMP_CLAUSE_ITERATORS (c), &built_p);
10065 :
10066 263 : if (!built_p)
10067 : {
10068 124 : loop.count = compute_omp_iterator_count (OMP_CLAUSE_ITERATORS (c),
10069 : loops_seq_p);
10070 124 : if (!loop.count)
10071 0 : continue;
10072 124 : if (integer_zerop (loop.count))
10073 8 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
10074 : "iteration count is zero");
10075 :
10076 124 : loop.bind = NULL_TREE;
10077 124 : tree *body = build_omp_iterator_loop (OMP_CLAUSE_ITERATORS (c),
10078 : loops_seq_p, &loop.bind);
10079 :
10080 124 : loop.index = create_tmp_var (sizetype);
10081 124 : SET_EXPR_LOCATION (loop.bind, OMP_CLAUSE_LOCATION (c));
10082 :
10083 : /* BEFORE LOOP: */
10084 : /* idx = -1; */
10085 : /* This should be initialized to before the individual elements,
10086 : as idx is pre-incremented in the loop body. */
10087 124 : gimple *assign = gimple_build_assign (loop.index, size_int (-1));
10088 124 : gimple_seq_add_stmt (loops_seq_p, assign);
10089 :
10090 : /* IN LOOP BODY: */
10091 : /* Create a label so we can find this point later. */
10092 124 : loop.body_label = create_artificial_label (OMP_CLAUSE_LOCATION (c));
10093 124 : tree tem = build1 (LABEL_EXPR, void_type_node, loop.body_label);
10094 124 : append_to_statement_list_force (tem, body);
10095 :
10096 : /* idx += 2; */
10097 124 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10098 : void_type_node, loop.index,
10099 : size_binop (PLUS_EXPR, loop.index, size_int (2)));
10100 124 : append_to_statement_list_force (tem, body);
10101 : }
10102 :
10103 : /* Create array to hold expanded values. */
10104 263 : tree last_count_2 = size_binop (MULT_EXPR, loop.count, size_int (2));
10105 263 : tree arr_length = size_binop (PLUS_EXPR, last_count_2, size_int (1));
10106 263 : tree elems = NULL_TREE;
10107 263 : if (TREE_CONSTANT (arr_length))
10108 : {
10109 263 : tree type = build_array_type (ptr_type_node,
10110 : build_index_type (arr_length));
10111 263 : elems = create_tmp_var_raw (type, "omp_iter_data");
10112 263 : TREE_ADDRESSABLE (elems) = 1;
10113 263 : gimple_add_tmp_var (elems);
10114 : }
10115 : else
10116 : {
10117 : /* Handle dynamic sizes. */
10118 0 : sorry ("dynamic iterator sizes not implemented yet");
10119 : }
10120 :
10121 : /* BEFORE LOOP: */
10122 : /* elems[0] = count; */
10123 263 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, size_int (0),
10124 : NULL_TREE, NULL_TREE);
10125 263 : tree tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10126 : void_type_node, lhs, loop.count);
10127 263 : gimplify_and_add (tem, loops_seq_p);
10128 :
10129 : /* Make a copy of the iterator with extra info at the end. */
10130 263 : int elem_count = TREE_VEC_LENGTH (OMP_CLAUSE_ITERATORS (c));
10131 263 : tree new_iterator = copy_omp_iterator (OMP_CLAUSE_ITERATORS (c),
10132 : elem_count + 3);
10133 263 : TREE_VEC_ELT (new_iterator, elem_count) = loop.body_label;
10134 263 : TREE_VEC_ELT (new_iterator, elem_count + 1) = elems;
10135 263 : TREE_VEC_ELT (new_iterator, elem_count + 2) = loop.index;
10136 263 : TREE_CHAIN (new_iterator) = TREE_CHAIN (OMP_CLAUSE_ITERATORS (c));
10137 263 : OMP_CLAUSE_ITERATORS (c) = new_iterator;
10138 :
10139 263 : loop.clauses.safe_push (c);
10140 : }
10141 :
10142 : /* Now gimplify and add all the loops that were built. */
10143 27785 : for (hash_map<tree, iterator_loop_info_t>::iterator it = loops.begin ();
10144 55570 : it != loops.end (); ++it)
10145 124 : gimplify_and_add ((*it).second.bind, loops_seq_p);
10146 27661 : }
10147 :
10148 : /* Helper function for enter_omp_iterator_loop_context. */
10149 :
10150 : static gimple_seq *
10151 2905 : enter_omp_iterator_loop_context_1 (tree iterator, gimple_seq *loops_seq_p)
10152 : {
10153 : /* Drill into the nested bind expressions to get to the loop body. */
10154 2905 : for (gimple_stmt_iterator gsi = gsi_start (*loops_seq_p);
10155 19171 : !gsi_end_p (gsi); gsi_next (&gsi))
10156 : {
10157 18612 : gimple *stmt = gsi_stmt (gsi);
10158 :
10159 18612 : switch (gimple_code (stmt))
10160 : {
10161 2207 : case GIMPLE_BIND:
10162 2207 : {
10163 2207 : gbind *bind_stmt = as_a<gbind *> (stmt);
10164 2207 : gimple_push_bind_expr (bind_stmt);
10165 2207 : gimple_seq *bind_body_p = gimple_bind_body_ptr (bind_stmt);
10166 2207 : gimple_seq *seq =
10167 2207 : enter_omp_iterator_loop_context_1 (iterator, bind_body_p);
10168 2207 : if (seq)
10169 : return seq;
10170 559 : gimple_pop_bind_expr ();
10171 : }
10172 559 : break;
10173 3 : case GIMPLE_TRY:
10174 3 : {
10175 3 : gimple_seq *try_eval_p = gimple_try_eval_ptr (stmt);
10176 3 : gimple_seq *seq =
10177 3 : enter_omp_iterator_loop_context_1 (iterator, try_eval_p);
10178 3 : if (seq)
10179 : return seq;
10180 : }
10181 : break;
10182 2913 : case GIMPLE_LABEL:
10183 2913 : {
10184 2913 : glabel *label_stmt = as_a<glabel *> (stmt);
10185 2913 : tree label = gimple_label_label (label_stmt);
10186 2913 : if (label == TREE_VEC_ELT (iterator, 6))
10187 : return loops_seq_p;
10188 : }
10189 : break;
10190 : default:
10191 : break;
10192 : }
10193 : }
10194 :
10195 : return NULL;
10196 : }
10197 :
10198 : /* Enter the Gimplification context in LOOPS_SEQ_P for the iterator loop
10199 : associated with OpenMP clause C. Returns the gimple_seq for the loop body
10200 : if C has OpenMP iterators, or ALT_SEQ_P if not. */
10201 :
10202 : static gimple_seq *
10203 65003 : enter_omp_iterator_loop_context (tree c, gimple_seq *loops_seq_p,
10204 : gimple_seq *alt_seq_p)
10205 : {
10206 65003 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10207 : return alt_seq_p;
10208 :
10209 695 : push_gimplify_context ();
10210 :
10211 695 : gimple_seq *seq = enter_omp_iterator_loop_context_1 (OMP_CLAUSE_ITERATORS (c),
10212 : loops_seq_p);
10213 695 : gcc_assert (seq);
10214 : return seq;
10215 : }
10216 :
10217 : /* Enter the Gimplification context in STMT for the iterator loop associated
10218 : with OpenMP clause C. Returns the gimple_seq for the loop body if C has
10219 : OpenMP iterators, or ALT_SEQ_P if not. */
10220 :
10221 : gimple_seq *
10222 434 : enter_omp_iterator_loop_context (tree c, gomp_target *stmt,
10223 : gimple_seq *alt_seq_p)
10224 : {
10225 434 : gimple_seq *loops_seq_p = gimple_omp_target_iterator_loops_ptr (stmt);
10226 434 : return enter_omp_iterator_loop_context (c, loops_seq_p, alt_seq_p);
10227 : }
10228 :
10229 : /* Exit the Gimplification context for the OpenMP clause C. */
10230 :
10231 : void
10232 65093 : exit_omp_iterator_loop_context (tree c)
10233 : {
10234 65093 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10235 : return;
10236 2343 : while (!gimplify_ctxp->bind_expr_stack.is_empty ())
10237 1648 : gimple_pop_bind_expr ();
10238 695 : pop_gimplify_context (NULL);
10239 : }
10240 :
10241 : /* If *LIST_P contains any OpenMP depend clauses with iterators,
10242 : lower all the depend clauses by populating corresponding depend
10243 : array. Returns 0 if there are no such depend clauses, or
10244 : 2 if all depend clauses should be removed, 1 otherwise. */
10245 :
10246 : static int
10247 1905 : gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
10248 : {
10249 1905 : tree c;
10250 1905 : gimple *g;
10251 1905 : size_t n[5] = { 0, 0, 0, 0, 0 };
10252 1905 : bool unused[5];
10253 1905 : tree counts[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
10254 1905 : tree last_iter = NULL_TREE, last_count = NULL_TREE;
10255 1905 : size_t i, j;
10256 1905 : location_t first_loc = UNKNOWN_LOCATION;
10257 :
10258 6250 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10259 4345 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10260 : {
10261 2207 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10262 : {
10263 : case OMP_CLAUSE_DEPEND_IN:
10264 : i = 2;
10265 : break;
10266 : case OMP_CLAUSE_DEPEND_OUT:
10267 : case OMP_CLAUSE_DEPEND_INOUT:
10268 : i = 0;
10269 : break;
10270 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10271 : i = 1;
10272 : break;
10273 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10274 : i = 3;
10275 : break;
10276 : case OMP_CLAUSE_DEPEND_INOUTSET:
10277 : i = 4;
10278 : break;
10279 0 : default:
10280 0 : gcc_unreachable ();
10281 : }
10282 2207 : tree t = OMP_CLAUSE_DECL (c);
10283 2207 : if (first_loc == UNKNOWN_LOCATION)
10284 1905 : first_loc = OMP_CLAUSE_LOCATION (c);
10285 2207 : if (OMP_ITERATOR_DECL_P (t))
10286 : {
10287 302 : if (TREE_PURPOSE (t) != last_iter)
10288 : {
10289 255 : tree tcnt = compute_omp_iterator_count (TREE_PURPOSE (t),
10290 : pre_p);
10291 255 : if (!tcnt)
10292 : return 2;
10293 255 : last_iter = TREE_PURPOSE (t);
10294 255 : last_count = tcnt;
10295 : }
10296 302 : if (counts[i] == NULL_TREE)
10297 248 : counts[i] = last_count;
10298 : else
10299 54 : counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
10300 : PLUS_EXPR, counts[i], last_count);
10301 : }
10302 : else
10303 1905 : n[i]++;
10304 : }
10305 10620 : for (i = 0; i < 5; i++)
10306 8925 : if (counts[i])
10307 : break;
10308 1905 : if (i == 5)
10309 : return 0;
10310 :
10311 210 : tree total = size_zero_node;
10312 1260 : for (i = 0; i < 5; i++)
10313 : {
10314 1050 : unused[i] = counts[i] == NULL_TREE && n[i] == 0;
10315 1050 : if (counts[i] == NULL_TREE)
10316 802 : counts[i] = size_zero_node;
10317 1050 : if (n[i])
10318 44 : counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
10319 1050 : if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
10320 : fb_rvalue) == GS_ERROR)
10321 : return 2;
10322 1050 : total = size_binop (PLUS_EXPR, total, counts[i]);
10323 : }
10324 :
10325 210 : if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
10326 : == GS_ERROR)
10327 : return 2;
10328 210 : bool is_old = unused[1] && unused[3] && unused[4];
10329 210 : tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
10330 : size_int (is_old ? 1 : 4));
10331 210 : if (!unused[4])
10332 3 : totalpx = size_binop (PLUS_EXPR, totalpx,
10333 : size_binop (MULT_EXPR, counts[4], size_int (2)));
10334 210 : tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
10335 210 : tree array = create_tmp_var_raw (type);
10336 210 : TREE_ADDRESSABLE (array) = 1;
10337 210 : if (!poly_int_tree_p (totalpx))
10338 : {
10339 83 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
10340 83 : gimplify_type_sizes (TREE_TYPE (array), pre_p);
10341 83 : if (gimplify_omp_ctxp)
10342 : {
10343 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
10344 : while (ctx
10345 22 : && (ctx->region_type == ORT_WORKSHARE
10346 : || ctx->region_type == ORT_TASKGROUP
10347 22 : || ctx->region_type == ORT_SIMD
10348 22 : || ctx->region_type == ORT_ACC))
10349 0 : ctx = ctx->outer_context;
10350 22 : if (ctx)
10351 22 : omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
10352 : }
10353 83 : gimplify_vla_decl (array, pre_p);
10354 : }
10355 : else
10356 127 : gimple_add_tmp_var (array);
10357 210 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
10358 : NULL_TREE);
10359 210 : tree tem;
10360 210 : if (!is_old)
10361 : {
10362 31 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10363 : build_int_cst (ptr_type_node, 0));
10364 31 : gimplify_and_add (tem, pre_p);
10365 31 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
10366 : NULL_TREE);
10367 : }
10368 210 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10369 : fold_convert (ptr_type_node, total));
10370 210 : gimplify_and_add (tem, pre_p);
10371 816 : for (i = 1; i < (is_old ? 2 : 4); i++)
10372 : {
10373 272 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
10374 : NULL_TREE, NULL_TREE);
10375 272 : tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
10376 272 : gimplify_and_add (tem, pre_p);
10377 : }
10378 :
10379 : tree cnts[6];
10380 740 : for (j = 5; j; j--)
10381 740 : if (!unused[j - 1])
10382 : break;
10383 1260 : for (i = 0; i < 5; i++)
10384 : {
10385 1050 : if (i && (i >= j || unused[i - 1]))
10386 : {
10387 790 : cnts[i] = cnts[i - 1];
10388 790 : continue;
10389 : }
10390 260 : cnts[i] = create_tmp_var (sizetype);
10391 260 : if (i == 0)
10392 241 : g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
10393 : else
10394 : {
10395 50 : tree t;
10396 50 : if (is_old)
10397 38 : t = size_binop (PLUS_EXPR, counts[0], size_int (2));
10398 : else
10399 12 : t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
10400 50 : if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
10401 : == GS_ERROR)
10402 0 : return 2;
10403 50 : g = gimple_build_assign (cnts[i], t);
10404 : }
10405 260 : gimple_seq_add_stmt (pre_p, g);
10406 : }
10407 210 : if (unused[4])
10408 207 : cnts[5] = NULL_TREE;
10409 : else
10410 : {
10411 3 : tree t = size_binop (PLUS_EXPR, total, size_int (5));
10412 3 : cnts[5] = create_tmp_var (sizetype);
10413 3 : g = gimple_build_assign (cnts[i], t);
10414 3 : gimple_seq_add_stmt (pre_p, g);
10415 : }
10416 :
10417 210 : last_iter = NULL_TREE;
10418 210 : tree last_bind = NULL_TREE;
10419 210 : tree *last_body = NULL;
10420 573 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10421 363 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10422 : {
10423 348 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10424 : {
10425 : case OMP_CLAUSE_DEPEND_IN:
10426 : i = 2;
10427 : break;
10428 : case OMP_CLAUSE_DEPEND_OUT:
10429 : case OMP_CLAUSE_DEPEND_INOUT:
10430 : i = 0;
10431 : break;
10432 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10433 : i = 1;
10434 : break;
10435 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10436 : i = 3;
10437 : break;
10438 : case OMP_CLAUSE_DEPEND_INOUTSET:
10439 : i = 4;
10440 : break;
10441 0 : default:
10442 0 : gcc_unreachable ();
10443 : }
10444 348 : tree t = OMP_CLAUSE_DECL (c);
10445 348 : if (OMP_ITERATOR_DECL_P (t))
10446 : {
10447 302 : if (TREE_PURPOSE (t) != last_iter)
10448 : {
10449 255 : last_body = build_omp_iterator_loop (TREE_PURPOSE (t), pre_p,
10450 : &last_bind);
10451 255 : SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
10452 : }
10453 302 : last_iter = TREE_PURPOSE (t);
10454 302 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
10455 : {
10456 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
10457 : 0), last_body);
10458 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
10459 : }
10460 302 : if (error_operand_p (TREE_VALUE (t)))
10461 : return 2;
10462 302 : if (TREE_VALUE (t) != null_pointer_node)
10463 296 : TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
10464 302 : if (i == 4)
10465 : {
10466 3 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10467 : NULL_TREE, NULL_TREE);
10468 3 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10469 : NULL_TREE, NULL_TREE);
10470 3 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10471 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10472 : void_type_node, r, r2);
10473 3 : append_to_statement_list_force (tem, last_body);
10474 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10475 : void_type_node, cnts[i],
10476 : size_binop (PLUS_EXPR, cnts[i],
10477 : size_int (1)));
10478 3 : append_to_statement_list_force (tem, last_body);
10479 3 : i = 5;
10480 : }
10481 302 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10482 : NULL_TREE, NULL_TREE);
10483 604 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10484 302 : void_type_node, r, TREE_VALUE (t));
10485 302 : append_to_statement_list_force (tem, last_body);
10486 302 : if (i == 5)
10487 : {
10488 3 : r = build4 (ARRAY_REF, ptr_type_node, array,
10489 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10490 : NULL_TREE, NULL_TREE);
10491 3 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10492 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10493 : void_type_node, r, tem);
10494 3 : append_to_statement_list_force (tem, last_body);
10495 : }
10496 302 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10497 : void_type_node, cnts[i],
10498 302 : size_binop (PLUS_EXPR, cnts[i],
10499 : size_int (1 + (i == 5))));
10500 302 : append_to_statement_list_force (tem, last_body);
10501 302 : TREE_VALUE (t) = null_pointer_node;
10502 : }
10503 : else
10504 : {
10505 46 : if (last_bind)
10506 : {
10507 18 : gimplify_and_add (last_bind, pre_p);
10508 18 : last_bind = NULL_TREE;
10509 : }
10510 46 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
10511 : {
10512 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
10513 : NULL, is_gimple_val, fb_rvalue);
10514 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
10515 : }
10516 46 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
10517 : return 2;
10518 46 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
10519 46 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
10520 46 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
10521 : is_gimple_val, fb_rvalue) == GS_ERROR)
10522 : return 2;
10523 46 : if (i == 4)
10524 : {
10525 0 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10526 : NULL_TREE, NULL_TREE);
10527 0 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10528 : NULL_TREE, NULL_TREE);
10529 0 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10530 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, r2);
10531 0 : gimplify_and_add (tem, pre_p);
10532 0 : g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR,
10533 : cnts[i],
10534 : size_int (1)));
10535 0 : gimple_seq_add_stmt (pre_p, g);
10536 0 : i = 5;
10537 : }
10538 46 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10539 : NULL_TREE, NULL_TREE);
10540 46 : tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
10541 46 : gimplify_and_add (tem, pre_p);
10542 46 : if (i == 5)
10543 : {
10544 0 : r = build4 (ARRAY_REF, ptr_type_node, array,
10545 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10546 : NULL_TREE, NULL_TREE);
10547 0 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10548 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, tem);
10549 0 : append_to_statement_list_force (tem, last_body);
10550 0 : gimplify_and_add (tem, pre_p);
10551 : }
10552 46 : g = gimple_build_assign (cnts[i],
10553 46 : size_binop (PLUS_EXPR, cnts[i],
10554 : size_int (1 + (i == 5))));
10555 46 : gimple_seq_add_stmt (pre_p, g);
10556 : }
10557 : }
10558 210 : if (last_bind)
10559 206 : gimplify_and_add (last_bind, pre_p);
10560 210 : tree cond = boolean_false_node;
10561 210 : if (is_old)
10562 : {
10563 179 : if (!unused[0])
10564 92 : cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
10565 : size_binop_loc (first_loc, PLUS_EXPR, counts[0],
10566 : size_int (2)));
10567 179 : if (!unused[2])
10568 125 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10569 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10570 : cnts[2],
10571 : size_binop_loc (first_loc, PLUS_EXPR,
10572 : totalpx,
10573 : size_int (1))));
10574 : }
10575 : else
10576 : {
10577 31 : tree prev = size_int (5);
10578 186 : for (i = 0; i < 5; i++)
10579 : {
10580 155 : if (unused[i])
10581 112 : continue;
10582 43 : prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
10583 43 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10584 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10585 : cnts[i], unshare_expr (prev)));
10586 : }
10587 : }
10588 210 : tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
10589 : build_call_expr_loc (first_loc,
10590 : builtin_decl_explicit (BUILT_IN_TRAP),
10591 : 0), void_node);
10592 210 : gimplify_and_add (tem, pre_p);
10593 210 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10594 210 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
10595 210 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10596 210 : OMP_CLAUSE_CHAIN (c) = *list_p;
10597 210 : *list_p = c;
10598 210 : return 1;
10599 : }
10600 :
10601 : /* True if mapping node C maps, or unmaps, a (Fortran) array descriptor. */
10602 :
10603 : static bool
10604 125724 : omp_map_clause_descriptor_p (tree c)
10605 : {
10606 125724 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
10607 : return false;
10608 :
10609 125720 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)
10610 : return true;
10611 :
10612 82502 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
10613 74464 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE)
10614 82984 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (c))
10615 6135 : return true;
10616 :
10617 : return false;
10618 : }
10619 :
10620 : /* For a set of mappings describing an array section pointed to by a struct
10621 : (or derived type, etc.) component, create an "alloc" or "release" node to
10622 : insert into a list following a GOMP_MAP_STRUCT node. For some types of
10623 : mapping (e.g. Fortran arrays with descriptors), an additional mapping may
10624 : be created that is inserted into the list of mapping nodes attached to the
10625 : directive being processed -- not part of the sorted list of nodes after
10626 : GOMP_MAP_STRUCT.
10627 :
10628 : CODE is the code of the directive being processed. GRP_START and GRP_END
10629 : are the first and last of two or three nodes representing this array section
10630 : mapping (e.g. a data movement node like GOMP_MAP_{TO,FROM}, optionally a
10631 : GOMP_MAP_TO_PSET, and finally a GOMP_MAP_ALWAYS_POINTER). EXTRA_NODE is
10632 : filled with the additional node described above, if needed.
10633 :
10634 : This function does not add the new nodes to any lists itself. It is the
10635 : responsibility of the caller to do that. */
10636 :
10637 : static tree
10638 1729 : build_omp_struct_comp_nodes (enum tree_code code, tree grp_start, tree grp_end,
10639 : tree *extra_node)
10640 : {
10641 1524 : enum gomp_map_kind mkind
10642 1729 : = (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
10643 1729 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
10644 :
10645 1729 : gcc_assert (grp_start != grp_end);
10646 :
10647 1729 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10648 1729 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
10649 1729 : OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (grp_end));
10650 1729 : OMP_CLAUSE_CHAIN (c2) = NULL_TREE;
10651 1729 : tree grp_mid = NULL_TREE;
10652 1729 : if (OMP_CLAUSE_CHAIN (grp_start) != grp_end)
10653 197 : grp_mid = OMP_CLAUSE_CHAIN (grp_start);
10654 :
10655 197 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
10656 0 : OMP_CLAUSE_SIZE (c2) = OMP_CLAUSE_SIZE (grp_mid);
10657 : else
10658 1729 : OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node);
10659 :
10660 1729 : if (grp_mid
10661 197 : && OMP_CLAUSE_CODE (grp_mid) == OMP_CLAUSE_MAP
10662 1926 : && OMP_CLAUSE_MAP_KIND (grp_mid) == GOMP_MAP_ALWAYS_POINTER)
10663 : {
10664 0 : tree c3
10665 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10666 0 : OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
10667 0 : OMP_CLAUSE_DECL (c3) = unshare_expr (OMP_CLAUSE_DECL (grp_mid));
10668 0 : OMP_CLAUSE_SIZE (c3) = TYPE_SIZE_UNIT (ptr_type_node);
10669 0 : OMP_CLAUSE_CHAIN (c3) = NULL_TREE;
10670 :
10671 0 : *extra_node = c3;
10672 : }
10673 : else
10674 1729 : *extra_node = NULL_TREE;
10675 :
10676 1729 : return c2;
10677 : }
10678 :
10679 : /* Strip ARRAY_REFS or an indirect ref off BASE, find the containing object,
10680 : and set *BITPOSP and *POFFSETP to the bit offset of the access.
10681 : If BASE_REF is non-NULL and the containing object is a reference, set
10682 : *BASE_REF to that reference before dereferencing the object.
10683 : If BASE_REF is NULL, check that the containing object is a COMPONENT_REF or
10684 : has array type, else return NULL. */
10685 :
10686 : static tree
10687 7739 : extract_base_bit_offset (tree base, poly_int64 *bitposp,
10688 : poly_offset_int *poffsetp,
10689 : bool *variable_offset,
10690 : tree iterator)
10691 : {
10692 7739 : tree offset;
10693 7739 : poly_int64 bitsize, bitpos;
10694 7739 : machine_mode mode;
10695 7739 : int unsignedp, reversep, volatilep = 0;
10696 7739 : poly_offset_int poffset;
10697 :
10698 7739 : STRIP_NOPS (base);
10699 :
10700 7739 : if (iterator)
10701 : {
10702 : /* Replace any iterator variables with the lower bound of the iterator.
10703 : This will give us the nominal offset and bit position of the first
10704 : element, which is all we should need to lay out the mappings. The
10705 : actual locations of the iterated mappings are elsewhere. */
10706 : tree it;
10707 72 : for (it = iterator; it; it = TREE_CHAIN (it))
10708 39 : base = simplify_replace_tree (base, TREE_VEC_ELT (it, 0),
10709 39 : TREE_VEC_ELT (it, 1));
10710 : }
10711 :
10712 7739 : base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
10713 : &unsignedp, &reversep, &volatilep);
10714 :
10715 7739 : STRIP_NOPS (base);
10716 :
10717 7739 : if (offset && poly_int_tree_p (offset))
10718 : {
10719 0 : poffset = wi::to_poly_offset (offset);
10720 0 : *variable_offset = false;
10721 : }
10722 : else
10723 : {
10724 7739 : poffset = 0;
10725 7739 : *variable_offset = (offset != NULL_TREE);
10726 : }
10727 :
10728 7739 : if (maybe_ne (bitpos, 0))
10729 5627 : poffset += bits_to_bytes_round_down (bitpos);
10730 :
10731 7739 : *bitposp = bitpos;
10732 7739 : *poffsetp = poffset;
10733 :
10734 7739 : return base;
10735 : }
10736 :
10737 : /* Used for topological sorting of mapping groups. UNVISITED means we haven't
10738 : started processing the group yet. The TEMPORARY mark is used when we first
10739 : encounter a group on a depth-first traversal, and the PERMANENT mark is used
10740 : when we have processed all the group's children (i.e. all the base pointers
10741 : referred to by the group's mapping nodes, recursively). */
10742 :
10743 : enum omp_tsort_mark {
10744 : UNVISITED,
10745 : TEMPORARY,
10746 : PERMANENT
10747 : };
10748 :
10749 : /* Hash for trees based on operand_equal_p. Like tree_operand_hash
10750 : but ignores side effects in the equality comparisons. */
10751 :
10752 : struct tree_operand_hash_no_se : tree_operand_hash
10753 : {
10754 : static inline bool equal (const value_type &,
10755 : const compare_type &);
10756 : };
10757 :
10758 : inline bool
10759 405714 : tree_operand_hash_no_se::equal (const value_type &t1,
10760 : const compare_type &t2)
10761 : {
10762 405714 : return operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS);
10763 : }
10764 :
10765 : /* A group of OMP_CLAUSE_MAP nodes that correspond to a single "map"
10766 : clause. */
10767 :
10768 : struct omp_mapping_group {
10769 : tree *grp_start;
10770 : tree grp_end;
10771 : omp_tsort_mark mark;
10772 : /* If we've removed the group but need to reindex, mark the group as
10773 : deleted. */
10774 : bool deleted;
10775 : /* The group points to an already-created "GOMP_MAP_STRUCT
10776 : GOMP_MAP_ATTACH_DETACH" pair. */
10777 : bool reprocess_struct;
10778 : /* The group should use "zero-length" allocations for pointers that are not
10779 : mapped "to" on the same directive. */
10780 : bool fragile;
10781 : struct omp_mapping_group *sibling;
10782 : struct omp_mapping_group *next;
10783 : };
10784 :
10785 : DEBUG_FUNCTION void
10786 0 : debug_mapping_group (omp_mapping_group *grp)
10787 : {
10788 0 : tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end);
10789 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = NULL;
10790 0 : debug_generic_expr (*grp->grp_start);
10791 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = tmp;
10792 0 : }
10793 :
10794 : /* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there
10795 : isn't one. */
10796 :
10797 : static tree
10798 36320 : omp_get_base_pointer (tree expr)
10799 : {
10800 36320 : while (TREE_CODE (expr) == ARRAY_REF
10801 43559 : || TREE_CODE (expr) == COMPONENT_REF)
10802 7239 : expr = TREE_OPERAND (expr, 0);
10803 :
10804 36320 : if (INDIRECT_REF_P (expr)
10805 36320 : || (TREE_CODE (expr) == MEM_REF
10806 1 : && integer_zerop (TREE_OPERAND (expr, 1))))
10807 : {
10808 10582 : expr = TREE_OPERAND (expr, 0);
10809 10619 : while (TREE_CODE (expr) == COMPOUND_EXPR)
10810 37 : expr = TREE_OPERAND (expr, 1);
10811 10582 : if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
10812 841 : expr = TREE_OPERAND (expr, 0);
10813 10582 : if (TREE_CODE (expr) == SAVE_EXPR)
10814 31 : expr = TREE_OPERAND (expr, 0);
10815 10582 : STRIP_NOPS (expr);
10816 10582 : return expr;
10817 : }
10818 :
10819 : return NULL_TREE;
10820 : }
10821 :
10822 : /* An attach or detach operation depends directly on the address being
10823 : attached/detached. Return that address, or none if there are no
10824 : attachments/detachments. */
10825 :
10826 : static tree
10827 16811 : omp_get_attachment (omp_mapping_group *grp)
10828 : {
10829 16811 : tree node = *grp->grp_start;
10830 :
10831 16811 : switch (OMP_CLAUSE_MAP_KIND (node))
10832 : {
10833 13857 : case GOMP_MAP_TO:
10834 13857 : case GOMP_MAP_FROM:
10835 13857 : case GOMP_MAP_TOFROM:
10836 13857 : case GOMP_MAP_ALWAYS_FROM:
10837 13857 : case GOMP_MAP_ALWAYS_TO:
10838 13857 : case GOMP_MAP_ALWAYS_TOFROM:
10839 13857 : case GOMP_MAP_FORCE_FROM:
10840 13857 : case GOMP_MAP_FORCE_TO:
10841 13857 : case GOMP_MAP_FORCE_TOFROM:
10842 13857 : case GOMP_MAP_FORCE_PRESENT:
10843 13857 : case GOMP_MAP_PRESENT_ALLOC:
10844 13857 : case GOMP_MAP_PRESENT_FROM:
10845 13857 : case GOMP_MAP_PRESENT_TO:
10846 13857 : case GOMP_MAP_PRESENT_TOFROM:
10847 13857 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
10848 13857 : case GOMP_MAP_ALWAYS_PRESENT_TO:
10849 13857 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
10850 13857 : case GOMP_MAP_ALLOC:
10851 13857 : case GOMP_MAP_RELEASE:
10852 13857 : case GOMP_MAP_DELETE:
10853 13857 : case GOMP_MAP_FORCE_ALLOC:
10854 13857 : if (node == grp->grp_end)
10855 : return NULL_TREE;
10856 :
10857 6613 : node = OMP_CLAUSE_CHAIN (node);
10858 6613 : if (node && omp_map_clause_descriptor_p (node))
10859 : {
10860 1038 : gcc_assert (node != grp->grp_end);
10861 1038 : node = OMP_CLAUSE_CHAIN (node);
10862 : }
10863 6613 : if (node)
10864 6613 : switch (OMP_CLAUSE_MAP_KIND (node))
10865 : {
10866 : case GOMP_MAP_POINTER:
10867 : case GOMP_MAP_ALWAYS_POINTER:
10868 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
10869 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
10870 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
10871 : return NULL_TREE;
10872 :
10873 2554 : case GOMP_MAP_ATTACH_DETACH:
10874 2554 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10875 2554 : case GOMP_MAP_DETACH:
10876 2554 : return OMP_CLAUSE_DECL (node);
10877 :
10878 0 : default:
10879 0 : internal_error ("unexpected mapping node");
10880 : }
10881 0 : return error_mark_node;
10882 :
10883 0 : case GOMP_MAP_TO_PSET:
10884 0 : gcc_assert (node != grp->grp_end);
10885 0 : node = OMP_CLAUSE_CHAIN (node);
10886 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
10887 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
10888 0 : return OMP_CLAUSE_DECL (node);
10889 : else
10890 0 : internal_error ("unexpected mapping node");
10891 : return error_mark_node;
10892 :
10893 537 : case GOMP_MAP_ATTACH:
10894 537 : case GOMP_MAP_DETACH:
10895 537 : node = OMP_CLAUSE_CHAIN (node);
10896 537 : if (!node || *grp->grp_start == grp->grp_end)
10897 537 : return OMP_CLAUSE_DECL (*grp->grp_start);
10898 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
10899 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
10900 0 : return OMP_CLAUSE_DECL (*grp->grp_start);
10901 : else
10902 0 : internal_error ("unexpected mapping node");
10903 : return error_mark_node;
10904 :
10905 : case GOMP_MAP_STRUCT:
10906 : case GOMP_MAP_STRUCT_UNORD:
10907 : case GOMP_MAP_FORCE_DEVICEPTR:
10908 : case GOMP_MAP_DEVICE_RESIDENT:
10909 : case GOMP_MAP_LINK:
10910 : case GOMP_MAP_IF_PRESENT:
10911 : case GOMP_MAP_FIRSTPRIVATE:
10912 : case GOMP_MAP_FIRSTPRIVATE_INT:
10913 : case GOMP_MAP_USE_DEVICE_PTR:
10914 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10915 : return NULL_TREE;
10916 :
10917 0 : default:
10918 0 : internal_error ("unexpected mapping node");
10919 : }
10920 :
10921 : return error_mark_node;
10922 : }
10923 :
10924 : /* Given a pointer START_P to the start of a group of related (e.g. pointer)
10925 : mappings, return the chain pointer to the end of that group in the list. */
10926 :
10927 : static tree *
10928 111132 : omp_group_last (tree *start_p)
10929 : {
10930 111132 : tree c = *start_p, nc, *grp_last_p = start_p;
10931 :
10932 111132 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
10933 :
10934 111132 : nc = OMP_CLAUSE_CHAIN (c);
10935 :
10936 193958 : if (!nc || OMP_CLAUSE_CODE (nc) != OMP_CLAUSE_MAP)
10937 : return grp_last_p;
10938 :
10939 70617 : switch (OMP_CLAUSE_MAP_KIND (c))
10940 : {
10941 : default:
10942 : while (nc
10943 113532 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
10944 238448 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
10945 106354 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
10946 95765 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH
10947 82958 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
10948 56874 : || (OMP_CLAUSE_MAP_KIND (nc)
10949 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
10950 56858 : || (OMP_CLAUSE_MAP_KIND (nc)
10951 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)
10952 56491 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH
10953 56436 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER
10954 54524 : || omp_map_clause_descriptor_p (nc)))
10955 : {
10956 66931 : tree nc2 = OMP_CLAUSE_CHAIN (nc);
10957 66931 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH)
10958 : {
10959 : /* In the specific case we're doing "exit data" on an array
10960 : slice of a reference-to-pointer struct component, we will see
10961 : DETACH followed by ATTACH_DETACH here. We want to treat that
10962 : as a single group. In other cases DETACH might represent a
10963 : stand-alone "detach" clause, so we don't want to consider
10964 : that part of the group. */
10965 55 : if (nc2
10966 16 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
10967 71 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH)
10968 0 : goto consume_two_nodes;
10969 : else
10970 : break;
10971 : }
10972 66876 : if (nc2
10973 48983 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
10974 42470 : && (OMP_CLAUSE_MAP_KIND (nc)
10975 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
10976 66892 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH)
10977 : {
10978 16 : consume_two_nodes:
10979 16 : grp_last_p = &OMP_CLAUSE_CHAIN (nc);
10980 16 : c = nc2;
10981 16 : nc = OMP_CLAUSE_CHAIN (nc2);
10982 : }
10983 : else
10984 : {
10985 66860 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
10986 66860 : c = nc;
10987 66860 : nc = nc2;
10988 : }
10989 : }
10990 : break;
10991 :
10992 302 : case GOMP_MAP_ATTACH:
10993 302 : case GOMP_MAP_DETACH:
10994 : /* This is a weird artifact of how directives are parsed: bare attach or
10995 : detach clauses get a subsequent (meaningless) FIRSTPRIVATE_POINTER or
10996 : FIRSTPRIVATE_REFERENCE node. FIXME. */
10997 302 : if (nc
10998 302 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
10999 302 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11000 302 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER))
11001 0 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11002 : break;
11003 :
11004 39 : case GOMP_MAP_TO_PSET:
11005 39 : if (OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11006 39 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH
11007 12 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH))
11008 39 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11009 : break;
11010 :
11011 5723 : case GOMP_MAP_STRUCT:
11012 5723 : case GOMP_MAP_STRUCT_UNORD:
11013 5723 : {
11014 5723 : unsigned HOST_WIDE_INT num_mappings
11015 5723 : = tree_to_uhwi (OMP_CLAUSE_SIZE (c));
11016 5723 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
11017 5385 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11018 10626 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH)
11019 1134 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11020 14389 : for (unsigned i = 0; i < num_mappings; i++)
11021 8666 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11022 : }
11023 : break;
11024 : }
11025 :
11026 : return grp_last_p;
11027 : }
11028 :
11029 : /* Walk through LIST_P, and return a list of groups of mappings found (e.g.
11030 : OMP_CLAUSE_MAP with GOMP_MAP_{TO/FROM/TOFROM} followed by one or two
11031 : associated GOMP_MAP_POINTER mappings). Return a vector of omp_mapping_group
11032 : if we have more than one such group, else return NULL. */
11033 :
11034 : static void
11035 89638 : omp_gather_mapping_groups_1 (tree *list_p, vec<omp_mapping_group> *groups,
11036 : tree gather_sentinel)
11037 : {
11038 89638 : for (tree *cp = list_p;
11039 267687 : *cp && *cp != gather_sentinel;
11040 178049 : cp = &OMP_CLAUSE_CHAIN (*cp))
11041 : {
11042 178049 : if (OMP_CLAUSE_CODE (*cp) != OMP_CLAUSE_MAP)
11043 98601 : continue;
11044 :
11045 79448 : tree *grp_last_p = omp_group_last (cp);
11046 79448 : omp_mapping_group grp;
11047 :
11048 79448 : grp.grp_start = cp;
11049 79448 : grp.grp_end = *grp_last_p;
11050 79448 : grp.mark = UNVISITED;
11051 79448 : grp.sibling = NULL;
11052 79448 : grp.deleted = false;
11053 79448 : grp.reprocess_struct = false;
11054 79448 : grp.fragile = false;
11055 79448 : grp.next = NULL;
11056 79448 : groups->safe_push (grp);
11057 :
11058 79448 : cp = grp_last_p;
11059 : }
11060 89638 : }
11061 :
11062 : static vec<omp_mapping_group> *
11063 89320 : omp_gather_mapping_groups (tree *list_p)
11064 : {
11065 89320 : vec<omp_mapping_group> *groups = new vec<omp_mapping_group> ();
11066 :
11067 89320 : omp_gather_mapping_groups_1 (list_p, groups, NULL_TREE);
11068 :
11069 89320 : if (groups->length () > 0)
11070 : return groups;
11071 : else
11072 : {
11073 44650 : delete groups;
11074 44650 : return NULL;
11075 : }
11076 : }
11077 :
11078 : /* A pointer mapping group GRP may define a block of memory starting at some
11079 : base address, and maybe also define a firstprivate pointer or firstprivate
11080 : reference that points to that block. The return value is a node containing
11081 : the former, and the *FIRSTPRIVATE pointer is set if we have the latter.
11082 : If we define several base pointers, i.e. for a GOMP_MAP_STRUCT mapping,
11083 : return the number of consecutive chained nodes in CHAINED. */
11084 :
11085 : static tree
11086 79842 : omp_group_base (omp_mapping_group *grp, unsigned int *chained,
11087 : tree *firstprivate)
11088 : {
11089 79842 : tree node = *grp->grp_start;
11090 :
11091 79842 : *firstprivate = NULL_TREE;
11092 79842 : *chained = 1;
11093 :
11094 79842 : switch (OMP_CLAUSE_MAP_KIND (node))
11095 : {
11096 75658 : case GOMP_MAP_TO:
11097 75658 : case GOMP_MAP_FROM:
11098 75658 : case GOMP_MAP_TOFROM:
11099 75658 : case GOMP_MAP_ALWAYS_FROM:
11100 75658 : case GOMP_MAP_ALWAYS_TO:
11101 75658 : case GOMP_MAP_ALWAYS_TOFROM:
11102 75658 : case GOMP_MAP_FORCE_FROM:
11103 75658 : case GOMP_MAP_FORCE_TO:
11104 75658 : case GOMP_MAP_FORCE_TOFROM:
11105 75658 : case GOMP_MAP_FORCE_PRESENT:
11106 75658 : case GOMP_MAP_PRESENT_ALLOC:
11107 75658 : case GOMP_MAP_PRESENT_FROM:
11108 75658 : case GOMP_MAP_PRESENT_TO:
11109 75658 : case GOMP_MAP_PRESENT_TOFROM:
11110 75658 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
11111 75658 : case GOMP_MAP_ALWAYS_PRESENT_TO:
11112 75658 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
11113 75658 : case GOMP_MAP_ALLOC:
11114 75658 : case GOMP_MAP_RELEASE:
11115 75658 : case GOMP_MAP_DELETE:
11116 75658 : case GOMP_MAP_FORCE_ALLOC:
11117 75658 : case GOMP_MAP_IF_PRESENT:
11118 75658 : if (node == grp->grp_end)
11119 : return node;
11120 :
11121 34756 : node = OMP_CLAUSE_CHAIN (node);
11122 34756 : if (!node)
11123 0 : internal_error ("unexpected mapping node");
11124 34756 : if (omp_map_clause_descriptor_p (node))
11125 : {
11126 10754 : if (node == grp->grp_end)
11127 0 : return *grp->grp_start;
11128 10754 : node = OMP_CLAUSE_CHAIN (node);
11129 : }
11130 34756 : switch (OMP_CLAUSE_MAP_KIND (node))
11131 : {
11132 23458 : case GOMP_MAP_POINTER:
11133 23458 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11134 23458 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11135 23458 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11136 23458 : *firstprivate = OMP_CLAUSE_DECL (node);
11137 23458 : return *grp->grp_start;
11138 :
11139 11298 : case GOMP_MAP_ALWAYS_POINTER:
11140 11298 : case GOMP_MAP_ATTACH_DETACH:
11141 11298 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11142 11298 : case GOMP_MAP_DETACH:
11143 11298 : return *grp->grp_start;
11144 :
11145 0 : default:
11146 0 : internal_error ("unexpected mapping node");
11147 : }
11148 : return error_mark_node;
11149 :
11150 26 : case GOMP_MAP_TO_PSET:
11151 26 : gcc_assert (node != grp->grp_end);
11152 26 : node = OMP_CLAUSE_CHAIN (node);
11153 26 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
11154 26 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
11155 : return NULL_TREE;
11156 : else
11157 0 : internal_error ("unexpected mapping node");
11158 : return error_mark_node;
11159 :
11160 1097 : case GOMP_MAP_ATTACH:
11161 1097 : case GOMP_MAP_DETACH:
11162 1097 : node = OMP_CLAUSE_CHAIN (node);
11163 1097 : if (!node || *grp->grp_start == grp->grp_end)
11164 : return NULL_TREE;
11165 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11166 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11167 : {
11168 : /* We're mapping the base pointer itself in a bare attach or detach
11169 : node. This is a side effect of how parsing works, and the mapping
11170 : will be removed anyway (at least for enter/exit data directives).
11171 : We should ignore the mapping here. FIXME. */
11172 : return NULL_TREE;
11173 : }
11174 : else
11175 0 : internal_error ("unexpected mapping node");
11176 : return error_mark_node;
11177 :
11178 2777 : case GOMP_MAP_STRUCT:
11179 2777 : case GOMP_MAP_STRUCT_UNORD:
11180 2777 : {
11181 2777 : unsigned HOST_WIDE_INT num_mappings
11182 2777 : = tree_to_uhwi (OMP_CLAUSE_SIZE (node));
11183 2777 : node = OMP_CLAUSE_CHAIN (node);
11184 2777 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11185 2777 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11186 : {
11187 393 : *firstprivate = OMP_CLAUSE_DECL (node);
11188 393 : node = OMP_CLAUSE_CHAIN (node);
11189 : }
11190 2384 : else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH_DETACH)
11191 314 : node = OMP_CLAUSE_CHAIN (node);
11192 2777 : *chained = num_mappings;
11193 2777 : return node;
11194 : }
11195 :
11196 : case GOMP_MAP_FORCE_DEVICEPTR:
11197 : case GOMP_MAP_DEVICE_RESIDENT:
11198 : case GOMP_MAP_LINK:
11199 : case GOMP_MAP_FIRSTPRIVATE:
11200 : case GOMP_MAP_FIRSTPRIVATE_INT:
11201 : case GOMP_MAP_USE_DEVICE_PTR:
11202 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11203 : return NULL_TREE;
11204 :
11205 0 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11206 0 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11207 0 : case GOMP_MAP_POINTER:
11208 0 : case GOMP_MAP_ALWAYS_POINTER:
11209 0 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11210 : /* These shouldn't appear by themselves. */
11211 0 : if (!seen_error ())
11212 0 : internal_error ("unexpected pointer mapping node");
11213 0 : return error_mark_node;
11214 :
11215 0 : default:
11216 0 : gcc_unreachable ();
11217 : }
11218 :
11219 : return error_mark_node;
11220 : }
11221 :
11222 : /* Given a vector of omp_mapping_groups, build a hash table so we can look up
11223 : nodes by tree_operand_hash_no_se. */
11224 :
11225 : static void
11226 45154 : omp_index_mapping_groups_1 (hash_map<tree_operand_hash_no_se,
11227 : omp_mapping_group *> *grpmap,
11228 : vec<omp_mapping_group> *groups,
11229 : tree reindex_sentinel)
11230 : {
11231 45154 : omp_mapping_group *grp;
11232 45154 : unsigned int i;
11233 45154 : bool reindexing = reindex_sentinel != NULL_TREE, above_hwm = false;
11234 :
11235 125450 : FOR_EACH_VEC_ELT (*groups, i, grp)
11236 : {
11237 80296 : if (reindexing && *grp->grp_start == reindex_sentinel)
11238 80296 : above_hwm = true;
11239 :
11240 80296 : if (reindexing && !above_hwm)
11241 56445 : continue;
11242 :
11243 79996 : if (grp->reprocess_struct)
11244 154 : continue;
11245 :
11246 79842 : tree fpp;
11247 79842 : unsigned int chained;
11248 79842 : tree node = omp_group_base (grp, &chained, &fpp);
11249 :
11250 79842 : if (node == error_mark_node || (!node && !fpp))
11251 1407 : continue;
11252 :
11253 : for (unsigned j = 0;
11254 158314 : node && j < chained;
11255 79879 : node = OMP_CLAUSE_CHAIN (node), j++)
11256 : {
11257 79879 : tree decl = OMP_CLAUSE_DECL (node);
11258 : /* Sometimes we see zero-offset MEM_REF instead of INDIRECT_REF,
11259 : meaning node-hash lookups don't work. This is a workaround for
11260 : that, but ideally we should just create the INDIRECT_REF at
11261 : source instead. FIXME. */
11262 79879 : if (TREE_CODE (decl) == MEM_REF
11263 79879 : && integer_zerop (TREE_OPERAND (decl, 1)))
11264 0 : decl = build_fold_indirect_ref (TREE_OPERAND (decl, 0));
11265 :
11266 79879 : omp_mapping_group **prev = grpmap->get (decl);
11267 :
11268 79879 : if (prev && *prev == grp)
11269 : /* Empty. */;
11270 79879 : else if (prev)
11271 : {
11272 : /* Mapping the same thing twice is normally diagnosed as an error,
11273 : but can happen under some circumstances, e.g. in pr99928-16.c,
11274 : the directive:
11275 :
11276 : #pragma omp target simd reduction(+:a[:3]) \
11277 : map(always, tofrom: a[:6])
11278 : ...
11279 :
11280 : will result in two "a[0]" mappings (of different sizes). */
11281 :
11282 326 : grp->sibling = (*prev)->sibling;
11283 326 : (*prev)->sibling = grp;
11284 : }
11285 : else
11286 79553 : grpmap->put (decl, grp);
11287 : }
11288 :
11289 78435 : if (!fpp)
11290 54584 : continue;
11291 :
11292 23851 : omp_mapping_group **prev = grpmap->get (fpp);
11293 23851 : if (prev && *prev != grp)
11294 : {
11295 12 : grp->sibling = (*prev)->sibling;
11296 12 : (*prev)->sibling = grp;
11297 : }
11298 : else
11299 23839 : grpmap->put (fpp, grp);
11300 : }
11301 45154 : }
11302 :
11303 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11304 44670 : omp_index_mapping_groups (vec<omp_mapping_group> *groups)
11305 : {
11306 44670 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11307 44670 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11308 :
11309 44670 : omp_index_mapping_groups_1 (grpmap, groups, NULL_TREE);
11310 :
11311 44670 : return grpmap;
11312 : }
11313 :
11314 : /* Rebuild group map from partially-processed clause list (during
11315 : omp_build_struct_sibling_lists). We have already processed nodes up until
11316 : a high-water mark (HWM). This is a bit tricky because the list is being
11317 : reordered as it is scanned, but we know:
11318 :
11319 : 1. The list after HWM has not been touched yet, so we can reindex it safely.
11320 :
11321 : 2. The list before and including HWM has been altered, but remains
11322 : well-formed throughout the sibling-list building operation.
11323 :
11324 : so, we can do the reindex operation in two parts, on the processed and
11325 : then the unprocessed halves of the list. */
11326 :
11327 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11328 318 : omp_reindex_mapping_groups (tree *list_p,
11329 : vec<omp_mapping_group> *groups,
11330 : vec<omp_mapping_group> *processed_groups,
11331 : tree sentinel)
11332 : {
11333 318 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11334 318 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11335 :
11336 318 : processed_groups->truncate (0);
11337 :
11338 318 : omp_gather_mapping_groups_1 (list_p, processed_groups, sentinel);
11339 318 : omp_index_mapping_groups_1 (grpmap, processed_groups, NULL_TREE);
11340 318 : if (sentinel)
11341 166 : omp_index_mapping_groups_1 (grpmap, groups, sentinel);
11342 :
11343 318 : return grpmap;
11344 : }
11345 :
11346 : /* Find the immediately-containing struct for a component ref (etc.)
11347 : expression EXPR. */
11348 :
11349 : static tree
11350 47979 : omp_containing_struct (tree expr)
11351 : {
11352 47979 : tree expr0 = expr;
11353 :
11354 47979 : STRIP_NOPS (expr);
11355 :
11356 : /* Note: don't strip NOPs unless we're also stripping off array refs or a
11357 : component ref. */
11358 47979 : if (TREE_CODE (expr) != ARRAY_REF && TREE_CODE (expr) != COMPONENT_REF)
11359 : return expr0;
11360 :
11361 27222 : while (TREE_CODE (expr) == ARRAY_REF)
11362 3675 : expr = TREE_OPERAND (expr, 0);
11363 :
11364 23547 : if (TREE_CODE (expr) == COMPONENT_REF)
11365 21093 : expr = TREE_OPERAND (expr, 0);
11366 :
11367 : return expr;
11368 : }
11369 :
11370 : /* Return TRUE if DECL describes a component that is part of a whole structure
11371 : that is mapped elsewhere in GRPMAP. *MAPPED_BY_GROUP is set to the group
11372 : that maps that structure, if present. */
11373 :
11374 : static bool
11375 25671 : omp_mapped_by_containing_struct (hash_map<tree_operand_hash_no_se,
11376 : omp_mapping_group *> *grpmap,
11377 : tree decl,
11378 : omp_mapping_group **mapped_by_group)
11379 : {
11380 25671 : tree wsdecl = NULL_TREE;
11381 :
11382 25671 : *mapped_by_group = NULL;
11383 :
11384 47979 : while (true)
11385 : {
11386 47979 : wsdecl = omp_containing_struct (decl);
11387 47979 : if (wsdecl == decl)
11388 : break;
11389 23547 : omp_mapping_group **wholestruct = grpmap->get (wsdecl);
11390 23547 : if (!wholestruct
11391 20978 : && TREE_CODE (wsdecl) == MEM_REF
11392 23548 : && integer_zerop (TREE_OPERAND (wsdecl, 1)))
11393 : {
11394 1 : tree deref = TREE_OPERAND (wsdecl, 0);
11395 1 : deref = build_fold_indirect_ref (deref);
11396 1 : wholestruct = grpmap->get (deref);
11397 : }
11398 23547 : if (wholestruct)
11399 : {
11400 : /* An intermediate descriptor should not match here because the
11401 : pointee is actually not mapped by this group -- it is just a
11402 : zero-length alloc. */
11403 2569 : tree desc = OMP_CLAUSE_CHAIN (*(*wholestruct)->grp_start);
11404 2569 : if (desc != NULL_TREE && omp_map_clause_descriptor_p (desc))
11405 1330 : goto next;
11406 1239 : *mapped_by_group = *wholestruct;
11407 1239 : return true;
11408 : }
11409 20978 : next:
11410 : decl = wsdecl;
11411 : }
11412 :
11413 : return false;
11414 : }
11415 :
11416 : /* Helper function for omp_tsort_mapping_groups. Returns TRUE on success, or
11417 : FALSE on error. */
11418 :
11419 : static bool
11420 20147 : omp_tsort_mapping_groups_1 (omp_mapping_group ***outlist,
11421 : vec<omp_mapping_group> *groups,
11422 : hash_map<tree_operand_hash_no_se,
11423 : omp_mapping_group *> *grpmap,
11424 : omp_mapping_group *grp)
11425 : {
11426 20147 : if (grp->mark == PERMANENT)
11427 : return true;
11428 16811 : if (grp->mark == TEMPORARY)
11429 : {
11430 0 : fprintf (stderr, "when processing group:\n");
11431 0 : debug_mapping_group (grp);
11432 0 : internal_error ("base pointer cycle detected");
11433 : return false;
11434 : }
11435 16811 : grp->mark = TEMPORARY;
11436 :
11437 16811 : tree attaches_to = omp_get_attachment (grp);
11438 :
11439 16811 : if (attaches_to)
11440 : {
11441 3091 : omp_mapping_group **basep = grpmap->get (attaches_to);
11442 :
11443 3091 : if (basep && *basep != grp)
11444 : {
11445 2920 : for (omp_mapping_group *w = *basep; w; w = w->sibling)
11446 1460 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11447 : return false;
11448 : }
11449 : }
11450 :
11451 16811 : tree decl = OMP_CLAUSE_DECL (*grp->grp_start);
11452 :
11453 23025 : while (decl)
11454 : {
11455 23025 : tree base = omp_get_base_pointer (decl);
11456 :
11457 23025 : if (!base)
11458 : break;
11459 :
11460 8974 : omp_mapping_group **innerp = grpmap->get (base);
11461 8974 : omp_mapping_group *wholestruct;
11462 :
11463 : /* We should treat whole-structure mappings as if all (pointer, in this
11464 : case) members are mapped as individual list items. Check if we have
11465 : such a whole-structure mapping, if we don't have an explicit reference
11466 : to the pointer member itself. */
11467 8974 : if (!innerp
11468 4165 : && TREE_CODE (base) == COMPONENT_REF
11469 11205 : && omp_mapped_by_containing_struct (grpmap, base, &wholestruct))
11470 : innerp = &wholestruct;
11471 :
11472 8974 : if (innerp && *innerp != grp)
11473 : {
11474 5532 : for (omp_mapping_group *w = *innerp; w; w = w->sibling)
11475 2772 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11476 0 : return false;
11477 : break;
11478 : }
11479 :
11480 6214 : decl = base;
11481 : }
11482 :
11483 16811 : grp->mark = PERMANENT;
11484 :
11485 : /* Emit grp to output list. */
11486 :
11487 16811 : **outlist = grp;
11488 16811 : *outlist = &grp->next;
11489 :
11490 16811 : return true;
11491 : }
11492 :
11493 : /* Topologically sort GROUPS, so that OMP 5.0-defined base pointers come
11494 : before mappings that use those pointers. This is an implementation of the
11495 : depth-first search algorithm, described e.g. at:
11496 :
11497 : https://en.wikipedia.org/wiki/Topological_sorting
11498 : */
11499 :
11500 : static omp_mapping_group *
11501 8515 : omp_tsort_mapping_groups (vec<omp_mapping_group> *groups,
11502 : hash_map<tree_operand_hash_no_se, omp_mapping_group *>
11503 : *grpmap,
11504 : bool enter_exit_data)
11505 : {
11506 8515 : omp_mapping_group *grp, *outlist = NULL, **cursor;
11507 8515 : unsigned int i;
11508 8515 : bool saw_runtime_implicit = false;
11509 :
11510 8515 : cursor = &outlist;
11511 :
11512 25326 : FOR_EACH_VEC_ELT (*groups, i, grp)
11513 : {
11514 16811 : if (grp->mark != PERMANENT)
11515 : {
11516 15939 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11517 : {
11518 683 : saw_runtime_implicit = true;
11519 683 : continue;
11520 : }
11521 15256 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11522 : return NULL;
11523 : }
11524 : }
11525 :
11526 8515 : if (!saw_runtime_implicit)
11527 8233 : return outlist;
11528 :
11529 1634 : FOR_EACH_VEC_ELT (*groups, i, grp)
11530 : {
11531 1352 : if (grp->mark != PERMANENT
11532 1352 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11533 : {
11534 : /* Clear the flag for enter/exit data because it is currently
11535 : meaningless for those operations in libgomp. */
11536 659 : if (enter_exit_data)
11537 446 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start) = 0;
11538 :
11539 659 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11540 : return NULL;
11541 : }
11542 : }
11543 :
11544 282 : return outlist;
11545 : }
11546 :
11547 : /* Split INLIST into three parts:
11548 :
11549 : - "present" alloc/to/from groups
11550 : - other to/from groups
11551 : - other alloc/release/delete groups
11552 :
11553 : These sub-lists are then concatenated together to form the final list.
11554 : Each sub-list retains the order of the original list.
11555 : Note that ATTACH nodes are later moved to the end of the list in
11556 : gimplify_adjust_omp_clauses, for target regions. */
11557 :
11558 : static omp_mapping_group *
11559 8515 : omp_segregate_mapping_groups (omp_mapping_group *inlist)
11560 : {
11561 8515 : omp_mapping_group *ard_groups = NULL, *tf_groups = NULL;
11562 8515 : omp_mapping_group *p_groups = NULL;
11563 8515 : omp_mapping_group **ard_tail = &ard_groups, **tf_tail = &tf_groups;
11564 8515 : omp_mapping_group **p_tail = &p_groups;
11565 :
11566 25326 : for (omp_mapping_group *w = inlist; w;)
11567 : {
11568 16811 : tree c = *w->grp_start;
11569 16811 : omp_mapping_group *next = w->next;
11570 :
11571 16811 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
11572 :
11573 16811 : switch (OMP_CLAUSE_MAP_KIND (c))
11574 : {
11575 1939 : case GOMP_MAP_ALLOC:
11576 1939 : case GOMP_MAP_RELEASE:
11577 1939 : case GOMP_MAP_DELETE:
11578 1939 : *ard_tail = w;
11579 1939 : w->next = NULL;
11580 1939 : ard_tail = &w->next;
11581 1939 : break;
11582 :
11583 : /* These map types are all semantically identical, so are moved into a
11584 : single group. They will each be changed into GOMP_MAP_FORCE_PRESENT
11585 : in gimplify_adjust_omp_clauses. */
11586 149 : case GOMP_MAP_PRESENT_ALLOC:
11587 149 : case GOMP_MAP_PRESENT_FROM:
11588 149 : case GOMP_MAP_PRESENT_TO:
11589 149 : case GOMP_MAP_PRESENT_TOFROM:
11590 149 : *p_tail = w;
11591 149 : w->next = NULL;
11592 149 : p_tail = &w->next;
11593 149 : break;
11594 :
11595 14723 : default:
11596 14723 : *tf_tail = w;
11597 14723 : w->next = NULL;
11598 14723 : tf_tail = &w->next;
11599 : }
11600 :
11601 : w = next;
11602 : }
11603 :
11604 : /* Now splice the lists together... */
11605 8515 : *tf_tail = ard_groups;
11606 8515 : *p_tail = tf_groups;
11607 :
11608 8515 : return p_groups;
11609 : }
11610 :
11611 : /* Given a list LIST_P containing groups of mappings given by GROUPS, reorder
11612 : those groups based on the output list of omp_tsort_mapping_groups --
11613 : singly-linked, threaded through each element's NEXT pointer starting at
11614 : HEAD. Each list element appears exactly once in that linked list.
11615 :
11616 : Each element of GROUPS may correspond to one or several mapping nodes.
11617 : Node groups are kept together, and in the reordered list, the positions of
11618 : the original groups are reused for the positions of the reordered list.
11619 : Hence if we have e.g.
11620 :
11621 : {to ptr ptr} firstprivate {tofrom ptr} ...
11622 : ^ ^ ^
11623 : first group non-"map" second group
11624 :
11625 : and say the second group contains a base pointer for the first so must be
11626 : moved before it, the resulting list will contain:
11627 :
11628 : {tofrom ptr} firstprivate {to ptr ptr} ...
11629 : ^ prev. second group ^ prev. first group
11630 : */
11631 :
11632 : static tree *
11633 8515 : omp_reorder_mapping_groups (vec<omp_mapping_group> *groups,
11634 : omp_mapping_group *head,
11635 : tree *list_p)
11636 : {
11637 8515 : omp_mapping_group *grp;
11638 8515 : unsigned int i;
11639 8515 : unsigned numgroups = groups->length ();
11640 8515 : auto_vec<tree> old_heads (numgroups);
11641 8515 : auto_vec<tree *> old_headps (numgroups);
11642 8515 : auto_vec<tree> new_heads (numgroups);
11643 8515 : auto_vec<tree> old_succs (numgroups);
11644 8515 : bool map_at_start = (list_p == (*groups)[0].grp_start);
11645 :
11646 8515 : tree *new_grp_tail = NULL;
11647 :
11648 : /* Stash the start & end nodes of each mapping group before we start
11649 : modifying the list. */
11650 25326 : FOR_EACH_VEC_ELT (*groups, i, grp)
11651 : {
11652 16811 : old_headps.quick_push (grp->grp_start);
11653 16811 : old_heads.quick_push (*grp->grp_start);
11654 16811 : old_succs.quick_push (OMP_CLAUSE_CHAIN (grp->grp_end));
11655 : }
11656 :
11657 : /* And similarly, the heads of the groups in the order we want to rearrange
11658 : the list to. */
11659 25326 : for (omp_mapping_group *w = head; w; w = w->next)
11660 16811 : new_heads.quick_push (*w->grp_start);
11661 :
11662 25326 : FOR_EACH_VEC_ELT (*groups, i, grp)
11663 : {
11664 16811 : gcc_assert (head);
11665 :
11666 16811 : if (new_grp_tail && old_succs[i - 1] == old_heads[i])
11667 : {
11668 : /* a {b c d} {e f g} h i j (original)
11669 : -->
11670 : a {k l m} {e f g} h i j (inserted new group on last iter)
11671 : -->
11672 : a {k l m} {n o p} h i j (this time, chain last group to new one)
11673 : ^new_grp_tail
11674 : */
11675 7674 : *new_grp_tail = new_heads[i];
11676 : }
11677 9137 : else if (new_grp_tail)
11678 : {
11679 : /* a {b c d} e {f g h} i j k (original)
11680 : -->
11681 : a {l m n} e {f g h} i j k (gap after last iter's group)
11682 : -->
11683 : a {l m n} e {o p q} h i j (chain last group to old successor)
11684 : ^new_grp_tail
11685 : */
11686 622 : *new_grp_tail = old_succs[i - 1];
11687 622 : *old_headps[i] = new_heads[i];
11688 : }
11689 : else
11690 : {
11691 : /* The first inserted group -- point to new group, and leave end
11692 : open.
11693 : a {b c d} e f
11694 : -->
11695 : a {g h i...
11696 : */
11697 8515 : *grp->grp_start = new_heads[i];
11698 : }
11699 :
11700 16811 : new_grp_tail = &OMP_CLAUSE_CHAIN (head->grp_end);
11701 :
11702 16811 : head = head->next;
11703 : }
11704 :
11705 8515 : if (new_grp_tail)
11706 8515 : *new_grp_tail = old_succs[numgroups - 1];
11707 :
11708 8515 : gcc_assert (!head);
11709 :
11710 11909 : return map_at_start ? (*groups)[0].grp_start : list_p;
11711 8515 : }
11712 :
11713 : /* DECL is supposed to have lastprivate semantics in the outer contexts
11714 : of combined/composite constructs, starting with OCTX.
11715 : Add needed lastprivate, shared or map clause if no data sharing or
11716 : mapping clause are present. IMPLICIT_P is true if it is an implicit
11717 : clause (IV on simd), in which case the lastprivate will not be
11718 : copied to some constructs. */
11719 :
11720 : static void
11721 14652 : omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx,
11722 : tree decl, bool implicit_p)
11723 : {
11724 14652 : struct gimplify_omp_ctx *orig_octx = octx;
11725 26973 : for (; octx; octx = octx->outer_context)
11726 : {
11727 25900 : if ((octx->region_type == ORT_COMBINED_PARALLEL
11728 20864 : || (octx->region_type & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS)
11729 25331 : && splay_tree_lookup (octx->variables,
11730 : (splay_tree_key) decl) == NULL)
11731 : {
11732 3887 : omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN);
11733 3887 : continue;
11734 : }
11735 18374 : if ((octx->region_type & ORT_TASK) != 0
11736 575 : && octx->combined_loop
11737 18655 : && splay_tree_lookup (octx->variables,
11738 : (splay_tree_key) decl) == NULL)
11739 : {
11740 248 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11741 248 : continue;
11742 : }
11743 22710 : if (implicit_p
11744 13619 : && octx->region_type == ORT_WORKSHARE
11745 10405 : && octx->combined_loop
11746 10300 : && splay_tree_lookup (octx->variables,
11747 : (splay_tree_key) decl) == NULL
11748 10300 : && octx->outer_context
11749 8907 : && octx->outer_context->region_type == ORT_COMBINED_PARALLEL
11750 22717 : && splay_tree_lookup (octx->outer_context->variables,
11751 : (splay_tree_key) decl) == NULL)
11752 : {
11753 4832 : octx = octx->outer_context;
11754 4832 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11755 4832 : continue;
11756 : }
11757 5564 : if ((octx->region_type == ORT_WORKSHARE || octx->region_type == ORT_ACC)
11758 7482 : && octx->combined_loop
11759 7295 : && splay_tree_lookup (octx->variables,
11760 : (splay_tree_key) decl) == NULL
11761 19071 : && !omp_check_private (octx, decl, false))
11762 : {
11763 3354 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11764 3354 : continue;
11765 : }
11766 9692 : if (octx->region_type == ORT_COMBINED_TARGET)
11767 : {
11768 2008 : splay_tree_node n = splay_tree_lookup (octx->variables,
11769 : (splay_tree_key) decl);
11770 2008 : if (n == NULL)
11771 : {
11772 1986 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11773 1986 : octx = octx->outer_context;
11774 : }
11775 22 : else if (!implicit_p
11776 22 : && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT))
11777 : {
11778 12 : n->value &= ~(GOVD_FIRSTPRIVATE
11779 : | GOVD_FIRSTPRIVATE_IMPLICIT
11780 : | GOVD_EXPLICIT);
11781 12 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11782 12 : octx = octx->outer_context;
11783 : }
11784 : }
11785 : break;
11786 : }
11787 14652 : if (octx && (implicit_p || octx != orig_octx))
11788 4046 : omp_notice_variable (octx, decl, true);
11789 14652 : }
11790 :
11791 : /* We might have indexed several groups for DECL, e.g. a "TO" mapping and also
11792 : a "FIRSTPRIVATE" mapping. Return the one that isn't firstprivate, etc. */
11793 :
11794 : static omp_mapping_group *
11795 5977 : omp_get_nonfirstprivate_group (hash_map<tree_operand_hash_no_se,
11796 : omp_mapping_group *> *grpmap,
11797 : tree decl, bool allow_deleted = false)
11798 : {
11799 5977 : omp_mapping_group **to_group_p = grpmap->get (decl);
11800 :
11801 5977 : if (!to_group_p)
11802 : return NULL;
11803 :
11804 2449 : omp_mapping_group *to_group = *to_group_p;
11805 :
11806 3776 : for (; to_group; to_group = to_group->sibling)
11807 : {
11808 2486 : tree grp_end = to_group->grp_end;
11809 2486 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
11810 : {
11811 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11812 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11813 : break;
11814 :
11815 1161 : default:
11816 1161 : if (allow_deleted || !to_group->deleted)
11817 : return to_group;
11818 : }
11819 : }
11820 :
11821 : return NULL;
11822 : }
11823 :
11824 : /* Return TRUE if the directive (whose clauses are described by the hash table
11825 : of mapping groups, GRPMAP) maps DECL explicitly. If TO_SPECIFICALLY is
11826 : true, only count TO mappings. If ALLOW_DELETED is true, ignore the
11827 : "deleted" flag for groups. If CONTAINED_IN_STRUCT is true, also return
11828 : TRUE if DECL is mapped as a member of a whole-struct mapping. */
11829 :
11830 : static bool
11831 4445 : omp_directive_maps_explicitly (hash_map<tree_operand_hash_no_se,
11832 : omp_mapping_group *> *grpmap,
11833 : tree decl, omp_mapping_group **base_group,
11834 : bool to_specifically, bool allow_deleted,
11835 : bool contained_in_struct)
11836 : {
11837 4445 : omp_mapping_group *decl_group
11838 4445 : = omp_get_nonfirstprivate_group (grpmap, decl, allow_deleted);
11839 :
11840 4445 : *base_group = NULL;
11841 :
11842 4445 : if (decl_group)
11843 : {
11844 1042 : tree grp_first = *decl_group->grp_start;
11845 : /* We might be called during omp_build_struct_sibling_lists, when
11846 : GOMP_MAP_STRUCT might have been inserted at the start of the group.
11847 : Skip over that, and also possibly the node after it. */
11848 1042 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT
11849 1042 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT_UNORD)
11850 : {
11851 6 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11852 6 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_FIRSTPRIVATE_POINTER
11853 6 : || (OMP_CLAUSE_MAP_KIND (grp_first)
11854 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11855 12 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_ATTACH_DETACH)
11856 0 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11857 : }
11858 1042 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
11859 1042 : if (!to_specifically
11860 592 : || GOMP_MAP_COPY_TO_P (first_kind)
11861 382 : || first_kind == GOMP_MAP_ALLOC)
11862 : {
11863 960 : *base_group = decl_group;
11864 960 : return true;
11865 : }
11866 : }
11867 :
11868 3485 : if (contained_in_struct
11869 3485 : && omp_mapped_by_containing_struct (grpmap, decl, base_group))
11870 : return true;
11871 :
11872 : return false;
11873 : }
11874 :
11875 : /* If we have mappings INNER and OUTER, where INNER is a component access and
11876 : OUTER is a mapping of the whole containing struct, check that the mappings
11877 : are compatible. We'll be deleting the inner mapping, so we need to make
11878 : sure the outer mapping does (at least) the same transfers to/from the device
11879 : as the inner mapping. */
11880 :
11881 : bool
11882 172 : omp_check_mapping_compatibility (location_t loc,
11883 : omp_mapping_group *outer,
11884 : omp_mapping_group *inner)
11885 : {
11886 172 : tree first_outer = *outer->grp_start, first_inner = *inner->grp_start;
11887 :
11888 172 : gcc_assert (OMP_CLAUSE_CODE (first_outer) == OMP_CLAUSE_MAP);
11889 172 : gcc_assert (OMP_CLAUSE_CODE (first_inner) == OMP_CLAUSE_MAP);
11890 :
11891 172 : enum gomp_map_kind outer_kind = OMP_CLAUSE_MAP_KIND (first_outer);
11892 172 : enum gomp_map_kind inner_kind = OMP_CLAUSE_MAP_KIND (first_inner);
11893 :
11894 172 : if (outer_kind == inner_kind)
11895 : return true;
11896 :
11897 70 : switch (outer_kind)
11898 : {
11899 0 : case GOMP_MAP_ALWAYS_TO:
11900 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11901 0 : || inner_kind == GOMP_MAP_ALLOC
11902 0 : || inner_kind == GOMP_MAP_TO)
11903 : return true;
11904 : break;
11905 :
11906 0 : case GOMP_MAP_ALWAYS_FROM:
11907 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11908 0 : || inner_kind == GOMP_MAP_RELEASE
11909 : || inner_kind == GOMP_MAP_FROM)
11910 : return true;
11911 : break;
11912 :
11913 10 : case GOMP_MAP_TO:
11914 10 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11915 10 : || inner_kind == GOMP_MAP_ALLOC)
11916 : return true;
11917 : break;
11918 :
11919 8 : case GOMP_MAP_FROM:
11920 8 : if (inner_kind == GOMP_MAP_RELEASE
11921 8 : || inner_kind == GOMP_MAP_FORCE_PRESENT)
11922 : return true;
11923 : break;
11924 :
11925 32 : case GOMP_MAP_ALWAYS_TOFROM:
11926 32 : case GOMP_MAP_TOFROM:
11927 32 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11928 32 : || inner_kind == GOMP_MAP_ALLOC
11929 : || inner_kind == GOMP_MAP_TO
11930 24 : || inner_kind == GOMP_MAP_FROM
11931 12 : || inner_kind == GOMP_MAP_TOFROM)
11932 : return true;
11933 : break;
11934 :
11935 28 : default:
11936 28 : ;
11937 : }
11938 :
11939 84 : error_at (loc, "data movement for component %qE is not compatible with "
11940 28 : "movement for struct %qE", OMP_CLAUSE_DECL (first_inner),
11941 28 : OMP_CLAUSE_DECL (first_outer));
11942 :
11943 28 : return false;
11944 : }
11945 :
11946 : /* This function handles several cases where clauses on a mapping directive
11947 : can interact with each other.
11948 :
11949 : If we have a FIRSTPRIVATE_POINTER node and we're also mapping the pointer
11950 : on the same directive, change the mapping of the first node to
11951 : ATTACH_DETACH. We should have detected that this will happen already in
11952 : c-omp.cc:c_omp_adjust_map_clauses and marked the appropriate decl
11953 : as addressable. (If we didn't, bail out.)
11954 :
11955 : If we have a FIRSTPRIVATE_REFERENCE (for a reference to pointer) and we're
11956 : mapping the base pointer also, we may need to change the mapping type to
11957 : ATTACH_DETACH and synthesize an alloc node for the reference itself.
11958 :
11959 : If we have an ATTACH_DETACH node, this is an array section with a pointer
11960 : base. If we're mapping the base on the same directive too, we can drop its
11961 : mapping. However, if we have a reference to pointer, make other appropriate
11962 : adjustments to the mapping nodes instead.
11963 :
11964 : If we have an ATTACH_DETACH node with a Fortran pointer-set (array
11965 : descriptor) mapping for a derived-type component, and we're also mapping the
11966 : whole of the derived-type variable on another clause, the pointer-set
11967 : mapping is removed.
11968 :
11969 : If we have a component access but we're also mapping the whole of the
11970 : containing struct, drop the former access.
11971 :
11972 : If the expression is a component access, and we're also mapping a base
11973 : pointer used in that component access in the same expression, change the
11974 : mapping type of the latter to ALLOC (ready for processing by
11975 : omp_build_struct_sibling_lists). */
11976 :
11977 : void
11978 8515 : omp_resolve_clause_dependencies (enum tree_code code,
11979 : vec<omp_mapping_group> *groups,
11980 : hash_map<tree_operand_hash_no_se,
11981 : omp_mapping_group *> *grpmap)
11982 : {
11983 8515 : int i;
11984 8515 : omp_mapping_group *grp;
11985 8515 : bool repair_chain = false;
11986 :
11987 24262 : FOR_EACH_VEC_ELT (*groups, i, grp)
11988 : {
11989 15747 : tree grp_end = grp->grp_end;
11990 15747 : tree decl = OMP_CLAUSE_DECL (grp_end);
11991 :
11992 15747 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
11993 :
11994 15747 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
11995 : {
11996 1216 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11997 1216 : {
11998 1216 : omp_mapping_group *to_group
11999 1216 : = omp_get_nonfirstprivate_group (grpmap, decl);
12000 :
12001 1216 : if (!to_group || to_group == grp)
12002 1191 : continue;
12003 :
12004 25 : tree grp_first = *to_group->grp_start;
12005 25 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12006 :
12007 25 : if ((GOMP_MAP_COPY_TO_P (first_kind)
12008 7 : || first_kind == GOMP_MAP_ALLOC)
12009 50 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12010 : != GOMP_MAP_FIRSTPRIVATE_POINTER))
12011 : {
12012 25 : gcc_assert (TREE_ADDRESSABLE (OMP_CLAUSE_DECL (grp_end)));
12013 25 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12014 : }
12015 : }
12016 : break;
12017 :
12018 160 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
12019 160 : {
12020 160 : tree ptr = build_fold_indirect_ref (decl);
12021 :
12022 160 : omp_mapping_group *to_group
12023 160 : = omp_get_nonfirstprivate_group (grpmap, ptr);
12024 :
12025 160 : if (!to_group || to_group == grp)
12026 156 : continue;
12027 :
12028 4 : tree grp_first = *to_group->grp_start;
12029 4 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12030 :
12031 4 : if (GOMP_MAP_COPY_TO_P (first_kind)
12032 4 : || first_kind == GOMP_MAP_ALLOC)
12033 : {
12034 4 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12035 4 : OMP_CLAUSE_DECL (grp_end) = ptr;
12036 4 : if ((OMP_CLAUSE_CHAIN (*to_group->grp_start)
12037 4 : == to_group->grp_end)
12038 4 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12039 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
12040 : {
12041 0 : gcc_assert (TREE_ADDRESSABLE
12042 : (OMP_CLAUSE_DECL (to_group->grp_end)));
12043 0 : OMP_CLAUSE_SET_MAP_KIND (to_group->grp_end,
12044 : GOMP_MAP_ATTACH_DETACH);
12045 :
12046 0 : location_t loc = OMP_CLAUSE_LOCATION (to_group->grp_end);
12047 0 : tree alloc
12048 0 : = build_omp_clause (loc, OMP_CLAUSE_MAP);
12049 0 : OMP_CLAUSE_SET_MAP_KIND (alloc, GOMP_MAP_ALLOC);
12050 0 : tree tmp = build_fold_addr_expr (OMP_CLAUSE_DECL
12051 : (to_group->grp_end));
12052 0 : tree char_ptr_type = build_pointer_type (char_type_node);
12053 0 : OMP_CLAUSE_DECL (alloc)
12054 0 : = build2 (MEM_REF, char_type_node,
12055 : tmp,
12056 : build_int_cst (char_ptr_type, 0));
12057 0 : OMP_CLAUSE_SIZE (alloc) = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
12058 :
12059 0 : OMP_CLAUSE_CHAIN (alloc)
12060 0 : = OMP_CLAUSE_CHAIN (*to_group->grp_start);
12061 0 : OMP_CLAUSE_CHAIN (*to_group->grp_start) = alloc;
12062 : }
12063 : }
12064 : }
12065 : break;
12066 :
12067 : case GOMP_MAP_ATTACH_DETACH:
12068 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
12069 : {
12070 2621 : tree base_ptr, referenced_ptr_node = NULL_TREE;
12071 :
12072 2621 : while (TREE_CODE (decl) == ARRAY_REF)
12073 0 : decl = TREE_OPERAND (decl, 0);
12074 :
12075 2621 : if (TREE_CODE (decl) == INDIRECT_REF)
12076 13 : decl = TREE_OPERAND (decl, 0);
12077 :
12078 : /* Only component accesses. */
12079 2621 : if (DECL_P (decl))
12080 226 : continue;
12081 :
12082 : /* We want the pointer itself when checking if the base pointer is
12083 : mapped elsewhere in the same directive -- if we have a
12084 : reference to the pointer, don't use that. */
12085 :
12086 2395 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12087 2395 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12088 : {
12089 394 : referenced_ptr_node = OMP_CLAUSE_CHAIN (*grp->grp_start);
12090 394 : base_ptr = OMP_CLAUSE_DECL (referenced_ptr_node);
12091 : }
12092 : else
12093 : base_ptr = decl;
12094 :
12095 1977 : gomp_map_kind zlas_kind
12096 2395 : = (code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
12097 2395 : ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION;
12098 :
12099 2395 : if (TREE_CODE (TREE_TYPE (base_ptr)) == POINTER_TYPE)
12100 : {
12101 : /* If we map the base TO, and we're doing an attachment, we can
12102 : skip the TO mapping altogether and create an ALLOC mapping
12103 : instead, since the attachment will overwrite the device
12104 : pointer in that location immediately anyway. Otherwise,
12105 : change our mapping to
12106 : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION in case the
12107 : attachment target has not been copied to the device already
12108 : by some earlier directive. */
12109 :
12110 1971 : bool base_mapped_to = false;
12111 :
12112 1971 : omp_mapping_group *base_group;
12113 :
12114 1971 : if (omp_directive_maps_explicitly (grpmap, base_ptr,
12115 : &base_group, false, true,
12116 : false))
12117 : {
12118 450 : if (referenced_ptr_node)
12119 : {
12120 129 : base_mapped_to = true;
12121 129 : if ((OMP_CLAUSE_MAP_KIND (base_group->grp_end)
12122 : == GOMP_MAP_ATTACH_DETACH)
12123 129 : && (OMP_CLAUSE_CHAIN (*base_group->grp_start)
12124 : == base_group->grp_end))
12125 : {
12126 258 : OMP_CLAUSE_CHAIN (*base_group->grp_start)
12127 129 : = OMP_CLAUSE_CHAIN (base_group->grp_end);
12128 129 : base_group->grp_end = *base_group->grp_start;
12129 129 : repair_chain = true;
12130 : }
12131 : }
12132 : else
12133 : {
12134 321 : base_group->deleted = true;
12135 321 : OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end) = 1;
12136 : }
12137 : }
12138 :
12139 : /* We're dealing with a reference to a pointer, and we are
12140 : attaching both the reference and the pointer. We know the
12141 : reference itself is on the target, because we are going to
12142 : create an ALLOC node for it in accumulate_sibling_list. The
12143 : pointer might be on the target already or it might not, but
12144 : if it isn't then it's not an error, so use
12145 : GOMP_MAP_ATTACH_ZLAS for it. */
12146 1971 : if (!base_mapped_to && referenced_ptr_node)
12147 56 : OMP_CLAUSE_SET_MAP_KIND (referenced_ptr_node, zlas_kind);
12148 :
12149 1971 : omp_mapping_group *struct_group;
12150 1971 : tree desc;
12151 1971 : if ((desc = OMP_CLAUSE_CHAIN (*grp->grp_start))
12152 1971 : && omp_map_clause_descriptor_p (desc)
12153 3049 : && omp_mapped_by_containing_struct (grpmap, decl,
12154 : &struct_group))
12155 : /* If we have a pointer set but we're mapping (or unmapping)
12156 : the whole of the containing struct, we can remove the
12157 : pointer set mapping. */
12158 15 : OMP_CLAUSE_CHAIN (*grp->grp_start) = OMP_CLAUSE_CHAIN (desc);
12159 : }
12160 424 : else if (TREE_CODE (TREE_TYPE (base_ptr)) == REFERENCE_TYPE
12161 424 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (base_ptr)))
12162 : == ARRAY_TYPE)
12163 562 : && OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION
12164 : (*grp->grp_start))
12165 92 : OMP_CLAUSE_SET_MAP_KIND (grp->grp_end, zlas_kind);
12166 : }
12167 : break;
12168 :
12169 : case GOMP_MAP_ATTACH:
12170 : /* Ignore standalone attach here. */
12171 : break;
12172 :
12173 11687 : default:
12174 11687 : {
12175 11687 : omp_mapping_group *struct_group;
12176 11687 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12177 11687 : && *grp->grp_start == grp_end)
12178 : {
12179 94 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12180 : struct_group, grp);
12181 : /* Remove the whole of this mapping -- redundant. */
12182 94 : grp->deleted = true;
12183 : }
12184 :
12185 : tree base = decl;
12186 13295 : while ((base = omp_get_base_pointer (base)))
12187 : {
12188 1608 : omp_mapping_group *base_group;
12189 :
12190 1608 : if (omp_directive_maps_explicitly (grpmap, base, &base_group,
12191 : true, true, false))
12192 : {
12193 343 : tree grp_first = *base_group->grp_start;
12194 343 : OMP_CLAUSE_SET_MAP_KIND (grp_first, GOMP_MAP_ALLOC);
12195 : }
12196 : }
12197 : }
12198 : }
12199 : }
12200 :
12201 8515 : if (repair_chain)
12202 : {
12203 : /* Group start pointers may have become detached from the
12204 : OMP_CLAUSE_CHAIN of previous groups if elements were removed from the
12205 : end of those groups. Fix that now. */
12206 : tree *new_next = NULL;
12207 716 : FOR_EACH_VEC_ELT (*groups, i, grp)
12208 : {
12209 587 : if (new_next)
12210 458 : grp->grp_start = new_next;
12211 :
12212 587 : new_next = &OMP_CLAUSE_CHAIN (grp->grp_end);
12213 : }
12214 : }
12215 8515 : }
12216 :
12217 : /* Similar to omp_resolve_clause_dependencies, but for OpenACC. The only
12218 : clause dependencies we handle for now are struct element mappings and
12219 : whole-struct mappings on the same directive, and duplicate clause
12220 : detection. */
12221 :
12222 : void
12223 9462 : oacc_resolve_clause_dependencies (vec<omp_mapping_group> *groups,
12224 : hash_map<tree_operand_hash_no_se,
12225 : omp_mapping_group *> *grpmap)
12226 : {
12227 9462 : int i;
12228 9462 : omp_mapping_group *grp;
12229 9462 : hash_set<tree_operand_hash> *seen_components = NULL;
12230 9462 : hash_set<tree_operand_hash> *shown_error = NULL;
12231 :
12232 24643 : FOR_EACH_VEC_ELT (*groups, i, grp)
12233 : {
12234 15181 : tree grp_end = grp->grp_end;
12235 15181 : tree decl = OMP_CLAUSE_DECL (grp_end);
12236 :
12237 15181 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12238 :
12239 15181 : if (DECL_P (grp_end))
12240 14664 : continue;
12241 :
12242 15181 : tree c = OMP_CLAUSE_DECL (*grp->grp_start);
12243 16806 : while (TREE_CODE (c) == ARRAY_REF)
12244 1625 : c = TREE_OPERAND (c, 0);
12245 15181 : if (TREE_CODE (c) != COMPONENT_REF)
12246 14664 : continue;
12247 517 : if (!seen_components)
12248 474 : seen_components = new hash_set<tree_operand_hash> ();
12249 517 : if (!shown_error)
12250 474 : shown_error = new hash_set<tree_operand_hash> ();
12251 517 : if (seen_components->contains (c)
12252 517 : && !shown_error->contains (c))
12253 : {
12254 10 : error_at (OMP_CLAUSE_LOCATION (grp_end),
12255 : "%qE appears more than once in map clauses",
12256 5 : OMP_CLAUSE_DECL (grp_end));
12257 5 : shown_error->add (c);
12258 : }
12259 : else
12260 512 : seen_components->add (c);
12261 :
12262 517 : omp_mapping_group *struct_group;
12263 517 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12264 517 : && *grp->grp_start == grp_end)
12265 : {
12266 78 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12267 : struct_group, grp);
12268 : /* Remove the whole of this mapping -- redundant. */
12269 78 : grp->deleted = true;
12270 : }
12271 : }
12272 :
12273 9462 : if (seen_components)
12274 474 : delete seen_components;
12275 9462 : if (shown_error)
12276 474 : delete shown_error;
12277 9462 : }
12278 :
12279 : /* Link node NEWNODE so it is pointed to by chain INSERT_AT. NEWNODE's chain
12280 : is linked to the previous node pointed to by INSERT_AT. */
12281 :
12282 : static tree *
12283 1133 : omp_siblist_insert_node_after (tree newnode, tree *insert_at)
12284 : {
12285 1133 : OMP_CLAUSE_CHAIN (newnode) = *insert_at;
12286 1133 : *insert_at = newnode;
12287 1133 : return &OMP_CLAUSE_CHAIN (newnode);
12288 : }
12289 :
12290 : /* Move NODE (which is currently pointed to by the chain OLD_POS) so it is
12291 : pointed to by chain MOVE_AFTER instead. */
12292 :
12293 : static void
12294 1320 : omp_siblist_move_node_after (tree node, tree *old_pos, tree *move_after)
12295 : {
12296 1320 : gcc_assert (node == *old_pos);
12297 1320 : *old_pos = OMP_CLAUSE_CHAIN (node);
12298 1320 : OMP_CLAUSE_CHAIN (node) = *move_after;
12299 1320 : *move_after = node;
12300 1320 : }
12301 :
12302 : /* Move nodes from FIRST_PTR (pointed to by previous node's chain) to
12303 : LAST_NODE to after MOVE_AFTER chain. Similar to below function, but no
12304 : new nodes are prepended to the list before splicing into the new position.
12305 : Return the position we should continue scanning the list at, or NULL to
12306 : stay where we were. */
12307 :
12308 : static tree *
12309 254 : omp_siblist_move_nodes_after (tree *first_ptr, tree last_node,
12310 : tree *move_after)
12311 : {
12312 254 : if (first_ptr == move_after)
12313 : return NULL;
12314 :
12315 243 : tree tmp = *first_ptr;
12316 243 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12317 243 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12318 243 : *move_after = tmp;
12319 :
12320 243 : return first_ptr;
12321 : }
12322 :
12323 : /* Concatenate two lists described by [FIRST_NEW, LAST_NEW_TAIL] and
12324 : [FIRST_PTR, LAST_NODE], and insert them in the OMP clause list after chain
12325 : pointer MOVE_AFTER.
12326 :
12327 : The latter list was previously part of the OMP clause list, and the former
12328 : (prepended) part is comprised of new nodes.
12329 :
12330 : We start with a list of nodes starting with a struct mapping node. We
12331 : rearrange the list so that new nodes starting from FIRST_NEW and whose last
12332 : node's chain is LAST_NEW_TAIL comes directly after MOVE_AFTER, followed by
12333 : the group of mapping nodes we are currently processing (from the chain
12334 : FIRST_PTR to LAST_NODE). The return value is the pointer to the next chain
12335 : we should continue processing from, or NULL to stay where we were.
12336 :
12337 : The transformation (in the case where MOVE_AFTER and FIRST_PTR are
12338 : different) is worked through below. Here we are processing LAST_NODE, and
12339 : FIRST_PTR points at the preceding mapping clause:
12340 :
12341 : #. mapping node chain
12342 : ---------------------------------------------------
12343 : A. struct_node [->B]
12344 : B. comp_1 [->C]
12345 : C. comp_2 [->D (move_after)]
12346 : D. map_to_3 [->E]
12347 : E. attach_3 [->F (first_ptr)]
12348 : F. map_to_4 [->G (continue_at)]
12349 : G. attach_4 (last_node) [->H]
12350 : H. ...
12351 :
12352 : *last_new_tail = *first_ptr;
12353 :
12354 : I. new_node (first_new) [->F (last_new_tail)]
12355 :
12356 : *first_ptr = OMP_CLAUSE_CHAIN (last_node)
12357 :
12358 : #. mapping node chain
12359 : ----------------------------------------------------
12360 : A. struct_node [->B]
12361 : B. comp_1 [->C]
12362 : C. comp_2 [->D (move_after)]
12363 : D. map_to_3 [->E]
12364 : E. attach_3 [->H (first_ptr)]
12365 : F. map_to_4 [->G (continue_at)]
12366 : G. attach_4 (last_node) [->H]
12367 : H. ...
12368 :
12369 : I. new_node (first_new) [->F (last_new_tail)]
12370 :
12371 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12372 :
12373 : #. mapping node chain
12374 : ---------------------------------------------------
12375 : A. struct_node [->B]
12376 : B. comp_1 [->C]
12377 : C. comp_2 [->D (move_after)]
12378 : D. map_to_3 [->E]
12379 : E. attach_3 [->H (continue_at)]
12380 : F. map_to_4 [->G]
12381 : G. attach_4 (last_node) [->D]
12382 : H. ...
12383 :
12384 : I. new_node (first_new) [->F (last_new_tail)]
12385 :
12386 : *move_after = first_new;
12387 :
12388 : #. mapping node chain
12389 : ---------------------------------------------------
12390 : A. struct_node [->B]
12391 : B. comp_1 [->C]
12392 : C. comp_2 [->I (move_after)]
12393 : D. map_to_3 [->E]
12394 : E. attach_3 [->H (continue_at)]
12395 : F. map_to_4 [->G]
12396 : G. attach_4 (last_node) [->D]
12397 : H. ...
12398 : I. new_node (first_new) [->F (last_new_tail)]
12399 :
12400 : or, in order:
12401 :
12402 : #. mapping node chain
12403 : ---------------------------------------------------
12404 : A. struct_node [->B]
12405 : B. comp_1 [->C]
12406 : C. comp_2 [->I (move_after)]
12407 : I. new_node (first_new) [->F (last_new_tail)]
12408 : F. map_to_4 [->G]
12409 : G. attach_4 (last_node) [->D]
12410 : D. map_to_3 [->E]
12411 : E. attach_3 [->H (continue_at)]
12412 : H. ...
12413 : */
12414 :
12415 : static tree *
12416 71 : omp_siblist_move_concat_nodes_after (tree first_new, tree *last_new_tail,
12417 : tree *first_ptr, tree last_node,
12418 : tree *move_after)
12419 : {
12420 71 : tree *continue_at = NULL;
12421 71 : *last_new_tail = *first_ptr;
12422 71 : if (first_ptr == move_after)
12423 12 : *move_after = first_new;
12424 : else
12425 : {
12426 59 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12427 59 : continue_at = first_ptr;
12428 59 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12429 59 : *move_after = first_new;
12430 : }
12431 71 : return continue_at;
12432 : }
12433 :
12434 : static omp_addr_token *
12435 11540 : omp_first_chained_access_token (vec<omp_addr_token *> &addr_tokens)
12436 : {
12437 11540 : using namespace omp_addr_tokenizer;
12438 11540 : int idx = addr_tokens.length () - 1;
12439 11540 : gcc_assert (idx >= 0);
12440 11540 : if (addr_tokens[idx]->type != ACCESS_METHOD)
12441 : return addr_tokens[idx];
12442 11567 : while (idx > 0 && addr_tokens[idx - 1]->type == ACCESS_METHOD)
12443 : idx--;
12444 11540 : return addr_tokens[idx];
12445 : }
12446 :
12447 : /* Mapping struct members causes an additional set of nodes to be created,
12448 : starting with GOMP_MAP_STRUCT followed by a number of mappings equal to the
12449 : number of members being mapped, in order of ascending position (address or
12450 : bitwise).
12451 :
12452 : We scan through the list of mapping clauses, calling this function for each
12453 : struct member mapping we find, and build up the list of mappings after the
12454 : initial GOMP_MAP_STRUCT node. For pointer members, these will be
12455 : newly-created ALLOC nodes. For non-pointer members, the existing mapping is
12456 : moved into place in the sorted list.
12457 :
12458 : struct {
12459 : int *a;
12460 : int *b;
12461 : int c;
12462 : int *d;
12463 : };
12464 :
12465 : #pragma (acc|omp directive) copy(struct.a[0:n], struct.b[0:n], struct.c,
12466 : struct.d[0:n])
12467 :
12468 : GOMP_MAP_STRUCT (4)
12469 : [GOMP_MAP_FIRSTPRIVATE_REFERENCE -- for refs to structs]
12470 : GOMP_MAP_ALLOC (struct.a)
12471 : GOMP_MAP_ALLOC (struct.b)
12472 : GOMP_MAP_TO (struct.c)
12473 : GOMP_MAP_ALLOC (struct.d)
12474 : ...
12475 :
12476 : In the case where we are mapping references to pointers, or in Fortran if
12477 : we are mapping an array with a descriptor, additional nodes may be created
12478 : after the struct node list also.
12479 :
12480 : The return code is either a pointer to the next node to process (if the
12481 : list has been rearranged), else NULL to continue with the next node in the
12482 : original list. */
12483 :
12484 : static tree *
12485 4765 : omp_accumulate_sibling_list (enum omp_region_type region_type,
12486 : enum tree_code code,
12487 : hash_map<tree_operand_hash, tree>
12488 : *&struct_map_to_clause,
12489 : hash_map<tree_operand_hash_no_se,
12490 : omp_mapping_group *> *group_map,
12491 : tree *grp_start_p, tree grp_end,
12492 : vec<omp_addr_token *> &addr_tokens, tree **inner,
12493 : bool *fragile_p, bool reprocessing_struct,
12494 : tree **added_tail)
12495 : {
12496 4765 : using namespace omp_addr_tokenizer;
12497 4765 : poly_offset_int coffset;
12498 4765 : poly_int64 cbitpos;
12499 4765 : tree ocd = OMP_CLAUSE_DECL (grp_end);
12500 4765 : bool openmp = !(region_type & ORT_ACC);
12501 4765 : bool target = (region_type & ORT_TARGET) != 0;
12502 4765 : tree *continue_at = NULL;
12503 :
12504 5078 : while (TREE_CODE (ocd) == ARRAY_REF)
12505 313 : ocd = TREE_OPERAND (ocd, 0);
12506 :
12507 4765 : if (*fragile_p)
12508 : {
12509 156 : omp_mapping_group *to_group
12510 156 : = omp_get_nonfirstprivate_group (group_map, ocd, true);
12511 :
12512 156 : if (to_group)
12513 : return NULL;
12514 : }
12515 :
12516 4677 : omp_addr_token *last_token = omp_first_chained_access_token (addr_tokens);
12517 4677 : if (last_token->type == ACCESS_METHOD)
12518 : {
12519 4677 : switch (last_token->u.access_kind)
12520 : {
12521 735 : case ACCESS_REF:
12522 735 : case ACCESS_REF_TO_POINTER:
12523 735 : case ACCESS_REF_TO_POINTER_OFFSET:
12524 735 : case ACCESS_INDEXED_REF_TO_ARRAY:
12525 : /* We may see either a bare reference or a dereferenced
12526 : "convert_from_reference"-like one here. Handle either way. */
12527 735 : if (TREE_CODE (ocd) == INDIRECT_REF)
12528 64 : ocd = TREE_OPERAND (ocd, 0);
12529 735 : gcc_assert (TREE_CODE (TREE_TYPE (ocd)) == REFERENCE_TYPE);
12530 : break;
12531 :
12532 : default:
12533 : ;
12534 : }
12535 : }
12536 :
12537 4677 : bool variable_offset;
12538 9354 : tree iterators = OMP_CLAUSE_HAS_ITERATORS (grp_end)
12539 4710 : ? OMP_CLAUSE_ITERATORS (grp_end) : NULL_TREE;
12540 4677 : tree base
12541 4677 : = extract_base_bit_offset (ocd, &cbitpos, &coffset, &variable_offset,
12542 4677 : iterators);
12543 :
12544 4677 : int base_token;
12545 23897 : for (base_token = addr_tokens.length () - 1; base_token >= 0; base_token--)
12546 : {
12547 19220 : if (addr_tokens[base_token]->type == ARRAY_BASE
12548 19220 : || addr_tokens[base_token]->type == STRUCTURE_BASE)
12549 : break;
12550 : }
12551 :
12552 : /* The two expressions in the assertion below aren't quite the same: if we
12553 : have 'struct_base_decl access_indexed_array' for something like
12554 : "myvar[2].x" then base will be "myvar" and addr_tokens[base_token]->expr
12555 : will be "myvar[2]" -- the actual base of the structure.
12556 : The former interpretation leads to a strange situation where we get
12557 : struct(myvar) alloc(myvar[2].ptr1)
12558 : That is, the array of structures is kind of treated as one big structure
12559 : for the purposes of gathering sibling lists, etc. */
12560 : /* gcc_assert (base == addr_tokens[base_token]->expr); */
12561 :
12562 4677 : bool attach_detach = ((OMP_CLAUSE_MAP_KIND (grp_end)
12563 : == GOMP_MAP_ATTACH_DETACH)
12564 4677 : || (OMP_CLAUSE_MAP_KIND (grp_end)
12565 4677 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
12566 4677 : bool has_descriptor = false;
12567 4677 : if (OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
12568 : {
12569 3137 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
12570 3137 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
12571 : has_descriptor = true;
12572 : }
12573 :
12574 4677 : if (!struct_map_to_clause || struct_map_to_clause->get (base) == NULL)
12575 : {
12576 3058 : enum gomp_map_kind str_kind = GOMP_MAP_STRUCT;
12577 :
12578 3058 : if (struct_map_to_clause == NULL)
12579 2495 : struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
12580 :
12581 3058 : if (variable_offset)
12582 274 : str_kind = GOMP_MAP_STRUCT_UNORD;
12583 :
12584 3058 : tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
12585 :
12586 3058 : OMP_CLAUSE_SET_MAP_KIND (l, str_kind);
12587 3058 : OMP_CLAUSE_DECL (l) = unshare_expr (base);
12588 3058 : OMP_CLAUSE_SIZE (l) = size_int (1);
12589 :
12590 3058 : struct_map_to_clause->put (base, l);
12591 :
12592 : /* On first iterating through the clause list, we insert the struct node
12593 : just before the component access node that triggers the initial
12594 : omp_accumulate_sibling_list call for a particular sibling list (and
12595 : it then forms the first entry in that list). When reprocessing
12596 : struct bases that are themselves component accesses, we insert the
12597 : struct node on an off-side list to avoid inserting the new
12598 : GOMP_MAP_STRUCT into the middle of the old one. */
12599 3058 : tree *insert_node_pos = reprocessing_struct ? *added_tail : grp_start_p;
12600 :
12601 3058 : if (has_descriptor)
12602 : {
12603 759 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
12604 759 : if (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
12605 187 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
12606 759 : tree sc = *insert_node_pos;
12607 759 : OMP_CLAUSE_CHAIN (l) = desc;
12608 759 : OMP_CLAUSE_CHAIN (*grp_start_p) = OMP_CLAUSE_CHAIN (desc);
12609 759 : OMP_CLAUSE_CHAIN (desc) = sc;
12610 759 : *insert_node_pos = l;
12611 : }
12612 2299 : else if (attach_detach)
12613 : {
12614 1396 : tree extra_node;
12615 1396 : tree alloc_node
12616 1396 : = build_omp_struct_comp_nodes (code, *grp_start_p, grp_end,
12617 : &extra_node);
12618 1396 : tree *tail;
12619 1396 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12620 :
12621 1396 : if (extra_node)
12622 : {
12623 0 : OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos;
12624 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
12625 0 : tail = &OMP_CLAUSE_CHAIN (extra_node);
12626 : }
12627 : else
12628 : {
12629 1396 : OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
12630 1396 : tail = &OMP_CLAUSE_CHAIN (alloc_node);
12631 : }
12632 :
12633 : /* For OpenMP semantics, we don't want to implicitly allocate
12634 : space for the pointer here for non-compute regions (e.g. "enter
12635 : data"). A FRAGILE_P node is only being created so that
12636 : omp-low.cc is able to rewrite the struct properly.
12637 : For references (to pointers), we want to actually allocate the
12638 : space for the reference itself in the sorted list following the
12639 : struct node.
12640 : For pointers, we want to allocate space if we had an explicit
12641 : mapping of the attachment point, but not otherwise. */
12642 1396 : if (*fragile_p
12643 1396 : || (openmp
12644 : && !target
12645 : && attach_detach
12646 234 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
12647 88 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
12648 : {
12649 133 : if (!lang_GNU_Fortran ())
12650 : /* In Fortran, pointers are dereferenced automatically, but may
12651 : be unassociated. So we still want to allocate space for the
12652 : pointer (as the base for an attach operation that should be
12653 : present in the same directive's clause list also). */
12654 103 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
12655 133 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
12656 : }
12657 :
12658 1396 : *insert_node_pos = l;
12659 :
12660 1396 : if (reprocessing_struct)
12661 : {
12662 : /* When reprocessing a struct node group used as the base of a
12663 : subcomponent access, if we have a reference-to-pointer base,
12664 : we will see:
12665 : struct(**ptr) attach(*ptr)
12666 : whereas for a non-reprocess-struct group, we see, e.g.:
12667 : tofrom(**ptr) attach(*ptr) attach(ptr)
12668 : and we create the "alloc" for the second "attach", i.e.
12669 : for the reference itself. When reprocessing a struct group we
12670 : thus change the pointer attachment into a reference attachment
12671 : by stripping the indirection. (The attachment of the
12672 : referenced pointer must happen elsewhere, either on the same
12673 : directive, or otherwise.) */
12674 180 : tree adecl = OMP_CLAUSE_DECL (alloc_node);
12675 :
12676 180 : if ((TREE_CODE (adecl) == INDIRECT_REF
12677 148 : || (TREE_CODE (adecl) == MEM_REF
12678 0 : && integer_zerop (TREE_OPERAND (adecl, 1))))
12679 32 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (adecl, 0)))
12680 : == REFERENCE_TYPE)
12681 212 : && (TREE_CODE (TREE_TYPE (TREE_TYPE
12682 : (TREE_OPERAND (adecl, 0)))) == POINTER_TYPE))
12683 32 : OMP_CLAUSE_DECL (alloc_node) = TREE_OPERAND (adecl, 0);
12684 :
12685 180 : *added_tail = tail;
12686 : }
12687 : }
12688 : else
12689 : {
12690 903 : gcc_assert (*grp_start_p == grp_end);
12691 903 : if (reprocessing_struct)
12692 : {
12693 : /* If we don't have an attach/detach node, this is a
12694 : "target data" directive or similar, not an offload region.
12695 : Synthesize an "alloc" node using just the initiating
12696 : GOMP_MAP_STRUCT decl. */
12697 16 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
12698 32 : || code == OACC_EXIT_DATA)
12699 32 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
12700 32 : tree alloc_node
12701 32 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12702 : OMP_CLAUSE_MAP);
12703 32 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
12704 32 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
12705 64 : OMP_CLAUSE_SIZE (alloc_node)
12706 32 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
12707 :
12708 32 : OMP_CLAUSE_CHAIN (alloc_node) = OMP_CLAUSE_CHAIN (l);
12709 32 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12710 32 : *insert_node_pos = l;
12711 32 : *added_tail = &OMP_CLAUSE_CHAIN (alloc_node);
12712 : }
12713 : else
12714 871 : grp_start_p = omp_siblist_insert_node_after (l, insert_node_pos);
12715 : }
12716 :
12717 3058 : unsigned last_access = base_token + 1;
12718 :
12719 3058 : while (last_access + 1 < addr_tokens.length ()
12720 3393 : && addr_tokens[last_access + 1]->type == ACCESS_METHOD)
12721 : last_access++;
12722 :
12723 3058 : if ((region_type & ORT_TARGET)
12724 3058 : && addr_tokens[base_token + 1]->type == ACCESS_METHOD)
12725 : {
12726 1708 : bool base_ref = false;
12727 1708 : access_method_kinds access_kind
12728 1708 : = addr_tokens[last_access]->u.access_kind;
12729 :
12730 1708 : switch (access_kind)
12731 : {
12732 : case ACCESS_DIRECT:
12733 : case ACCESS_INDEXED_ARRAY:
12734 1060 : return NULL;
12735 :
12736 403 : case ACCESS_REF:
12737 403 : case ACCESS_REF_TO_POINTER:
12738 403 : case ACCESS_REF_TO_POINTER_OFFSET:
12739 403 : case ACCESS_INDEXED_REF_TO_ARRAY:
12740 403 : base_ref = true;
12741 403 : break;
12742 :
12743 866 : default:
12744 866 : ;
12745 : }
12746 866 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12747 : OMP_CLAUSE_MAP);
12748 866 : enum gomp_map_kind mkind;
12749 866 : omp_mapping_group *decl_group;
12750 866 : tree use_base;
12751 866 : switch (access_kind)
12752 : {
12753 463 : case ACCESS_POINTER:
12754 463 : case ACCESS_POINTER_OFFSET:
12755 463 : use_base = addr_tokens[last_access]->expr;
12756 463 : break;
12757 198 : case ACCESS_REF_TO_POINTER:
12758 198 : case ACCESS_REF_TO_POINTER_OFFSET:
12759 198 : use_base
12760 198 : = build_fold_indirect_ref (addr_tokens[last_access]->expr);
12761 198 : break;
12762 205 : default:
12763 205 : use_base = addr_tokens[base_token]->expr;
12764 : }
12765 866 : bool mapped_to_p
12766 866 : = omp_directive_maps_explicitly (group_map, use_base, &decl_group,
12767 : true, false, true);
12768 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12769 866 : && DECL_P (addr_tokens[last_access]->expr)
12770 1372 : && !mapped_to_p)
12771 444 : mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
12772 : : GOMP_MAP_FIRSTPRIVATE_POINTER;
12773 : else
12774 : mkind = GOMP_MAP_ATTACH_DETACH;
12775 :
12776 866 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
12777 : /* If we have a reference to pointer base, we want to attach the
12778 : pointer here, not the reference. The reference attachment happens
12779 : elsewhere. */
12780 866 : bool ref_to_ptr
12781 866 : = (access_kind == ACCESS_REF_TO_POINTER
12782 866 : || access_kind == ACCESS_REF_TO_POINTER_OFFSET);
12783 866 : tree sdecl = addr_tokens[last_access]->expr;
12784 866 : tree sdecl_ptr = ref_to_ptr ? build_fold_indirect_ref (sdecl)
12785 : : sdecl;
12786 : /* For the FIRSTPRIVATE_REFERENCE after the struct node, we
12787 : want to use the reference itself for the decl, but we
12788 : still want to use the pointer to calculate the bias. */
12789 866 : OMP_CLAUSE_DECL (c2) = (mkind == GOMP_MAP_ATTACH_DETACH)
12790 866 : ? sdecl_ptr : sdecl;
12791 866 : sdecl = sdecl_ptr;
12792 866 : tree baddr = build_fold_addr_expr (base);
12793 866 : baddr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12794 : ptrdiff_type_node, baddr);
12795 866 : tree decladdr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12796 : ptrdiff_type_node, sdecl);
12797 866 : OMP_CLAUSE_SIZE (c2)
12798 866 : = fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR,
12799 : ptrdiff_type_node, baddr, decladdr);
12800 : /* Insert after struct node. */
12801 866 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
12802 866 : OMP_CLAUSE_CHAIN (l) = c2;
12803 :
12804 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12805 866 : && (addr_tokens[base_token]->u.structure_base_kind
12806 : == BASE_COMPONENT_EXPR)
12807 286 : && mkind == GOMP_MAP_ATTACH_DETACH
12808 1152 : && addr_tokens[last_access]->u.access_kind != ACCESS_REF)
12809 : {
12810 218 : *inner = insert_node_pos;
12811 218 : if (openmp)
12812 166 : *fragile_p = true;
12813 218 : return NULL;
12814 : }
12815 : }
12816 :
12817 1998 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12818 1998 : && (addr_tokens[base_token]->u.structure_base_kind
12819 : == BASE_COMPONENT_EXPR)
12820 2465 : && addr_tokens[last_access]->u.access_kind == ACCESS_REF)
12821 100 : *inner = insert_node_pos;
12822 :
12823 1998 : return NULL;
12824 : }
12825 1619 : else if (struct_map_to_clause)
12826 : {
12827 1619 : tree *osc = struct_map_to_clause->get (base);
12828 1619 : tree *sc = NULL, *scp = NULL;
12829 :
12830 1619 : unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
12831 1619 : sc = &OMP_CLAUSE_CHAIN (*osc);
12832 : /* The struct mapping might be immediately followed by a
12833 : FIRSTPRIVATE_POINTER, FIRSTPRIVATE_REFERENCE or an ATTACH_DETACH --
12834 : if it's an indirect access or a reference, or if the structure base
12835 : is not a decl. The FIRSTPRIVATE_* nodes are removed in omp-low.cc
12836 : after they have been processed there, and ATTACH_DETACH nodes are
12837 : recomputed and moved out of the GOMP_MAP_STRUCT construct once
12838 : sibling list building is complete. */
12839 1619 : if (OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_POINTER
12840 1574 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
12841 3148 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_ATTACH_DETACH)
12842 201 : sc = &OMP_CLAUSE_CHAIN (*sc);
12843 4108 : for (i = 0; i < elems; i++, sc = &OMP_CLAUSE_CHAIN (*sc))
12844 3062 : if (attach_detach && sc == grp_start_p)
12845 : break;
12846 3062 : else if (TREE_CODE (OMP_CLAUSE_DECL (*sc)) != COMPONENT_REF
12847 182 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != INDIRECT_REF
12848 3244 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != ARRAY_REF)
12849 : break;
12850 : else
12851 : {
12852 3062 : tree sc_decl = OMP_CLAUSE_DECL (*sc);
12853 3062 : poly_offset_int offset;
12854 3062 : poly_int64 bitpos;
12855 :
12856 3062 : if (TREE_CODE (sc_decl) == ARRAY_REF)
12857 : {
12858 366 : while (TREE_CODE (sc_decl) == ARRAY_REF)
12859 184 : sc_decl = TREE_OPERAND (sc_decl, 0);
12860 182 : if (TREE_CODE (sc_decl) != COMPONENT_REF
12861 182 : || TREE_CODE (TREE_TYPE (sc_decl)) != ARRAY_TYPE)
12862 : break;
12863 : }
12864 2880 : else if (INDIRECT_REF_P (sc_decl)
12865 0 : && TREE_CODE (TREE_OPERAND (sc_decl, 0)) == COMPONENT_REF
12866 2880 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (sc_decl, 0)))
12867 : == REFERENCE_TYPE))
12868 0 : sc_decl = TREE_OPERAND (sc_decl, 0);
12869 :
12870 3062 : bool variable_offset2;
12871 3062 : tree iterators2 = OMP_CLAUSE_HAS_ITERATORS (*sc)
12872 3062 : ? OMP_CLAUSE_ITERATORS (*sc) : NULL_TREE;
12873 :
12874 3062 : tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset,
12875 : &variable_offset2,
12876 : iterators2);
12877 3062 : if (!base2 || !operand_equal_p (base2, base, 0))
12878 : break;
12879 3062 : if (scp)
12880 469 : continue;
12881 2842 : if (variable_offset2)
12882 : {
12883 341 : OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
12884 :
12885 341 : if (has_descriptor)
12886 : {
12887 : /* Sort mapped components by offset. This is needed for
12888 : libgomp to handle Fortran derived-type allocatable
12889 : components transparently. */
12890 :
12891 323 : poly_int64 bitsize;
12892 323 : tree offset, coffset;
12893 323 : machine_mode mode;
12894 323 : int unsignedp, reversep, volatilep;
12895 323 : tree inner_ref1
12896 323 : = get_inner_reference (sc_decl, &bitsize, &bitpos,
12897 : &offset, &mode, &unsignedp,
12898 : &reversep, &volatilep);
12899 323 : tree osc_decl = ocd;
12900 323 : STRIP_NOPS (osc_decl);
12901 323 : tree inner_ref2
12902 323 : = get_inner_reference (osc_decl, &bitsize, &bitpos,
12903 : &coffset, &mode, &unsignedp,
12904 : &reversep, &volatilep);
12905 323 : gcc_assert (operand_equal_p (inner_ref1, inner_ref2, 0));
12906 323 : tree offset_diff
12907 323 : = fold_binary_to_constant (MINUS_EXPR, size_type_node,
12908 : coffset, offset);
12909 572 : if (offset_diff == NULL_TREE
12910 323 : || TREE_INT_CST_ELT (offset_diff, 0) > 0)
12911 249 : continue;
12912 : else
12913 : break;
12914 : }
12915 : }
12916 2501 : else if ((region_type & ORT_ACC) != 0)
12917 : {
12918 : /* For OpenACC, allow (ignore) duplicate struct accesses in
12919 : the middle of a mapping clause, e.g. "mystruct->foo" in:
12920 : copy(mystruct->foo->bar) copy(mystruct->foo->qux). */
12921 223 : if (reprocessing_struct
12922 8 : && known_eq (coffset, offset)
12923 223 : && known_eq (cbitpos, bitpos))
12924 16 : return NULL;
12925 : }
12926 2278 : else if (known_eq (coffset, offset)
12927 2278 : && known_eq (cbitpos, bitpos))
12928 : {
12929 : /* Having two struct members at the same offset doesn't work,
12930 : so make sure we don't. (We're allowed to ignore this.
12931 : Should we report the error?) */
12932 : /*error_at (OMP_CLAUSE_LOCATION (grp_end),
12933 : "duplicate struct member %qE in map clauses",
12934 : OMP_CLAUSE_DECL (grp_end));*/
12935 : return NULL;
12936 : }
12937 2503 : if (maybe_lt (coffset, offset)
12938 4231 : || (known_eq (coffset, offset)
12939 20 : && maybe_lt (cbitpos, bitpos)))
12940 : {
12941 775 : if (attach_detach)
12942 : scp = sc;
12943 : else
12944 : break;
12945 : }
12946 : }
12947 :
12948 1603 : OMP_CLAUSE_SIZE (*osc)
12949 1603 : = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
12950 :
12951 1603 : if (reprocessing_struct)
12952 : {
12953 : /* If we're reprocessing a struct node, we don't want to do most of
12954 : the list manipulation below. We only need to handle the (pointer
12955 : or reference) attach/detach case. */
12956 8 : tree extra_node, alloc_node;
12957 8 : if (has_descriptor)
12958 0 : gcc_unreachable ();
12959 8 : else if (attach_detach)
12960 8 : alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
12961 : grp_end, &extra_node);
12962 : else
12963 : {
12964 : /* If we don't have an attach/detach node, this is a
12965 : "target data" directive or similar, not an offload region.
12966 : Synthesize an "alloc" node using just the initiating
12967 : GOMP_MAP_STRUCT decl. */
12968 0 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
12969 0 : || code == OACC_EXIT_DATA)
12970 0 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
12971 0 : alloc_node
12972 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12973 : OMP_CLAUSE_MAP);
12974 0 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
12975 0 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
12976 0 : OMP_CLAUSE_SIZE (alloc_node)
12977 0 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
12978 : }
12979 :
12980 8 : if (scp)
12981 0 : omp_siblist_insert_node_after (alloc_node, scp);
12982 : else
12983 : {
12984 8 : tree *new_end = omp_siblist_insert_node_after (alloc_node, sc);
12985 8 : if (sc == *added_tail)
12986 8 : *added_tail = new_end;
12987 : }
12988 :
12989 8 : return NULL;
12990 : }
12991 :
12992 1595 : if (has_descriptor)
12993 : {
12994 538 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
12995 538 : if (code == OMP_TARGET_EXIT_DATA
12996 538 : || code == OACC_EXIT_DATA)
12997 105 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
12998 1076 : omp_siblist_move_node_after (desc,
12999 538 : &OMP_CLAUSE_CHAIN (*grp_start_p),
13000 : scp ? scp : sc);
13001 : }
13002 1057 : else if (attach_detach)
13003 : {
13004 325 : tree cl = NULL_TREE, extra_node;
13005 325 : tree alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
13006 : grp_end, &extra_node);
13007 325 : tree *tail_chain = NULL;
13008 :
13009 325 : if (*fragile_p
13010 325 : || (openmp
13011 : && !target
13012 : && attach_detach
13013 62 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
13014 23 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
13015 : {
13016 6 : if (!lang_GNU_Fortran ())
13017 6 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
13018 6 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
13019 : }
13020 :
13021 : /* Here, we have:
13022 :
13023 : grp_end : the last (or only) node in this group.
13024 : grp_start_p : pointer to the first node in a pointer mapping group
13025 : up to and including GRP_END.
13026 : sc : pointer to the chain for the end of the struct component
13027 : list.
13028 : scp : pointer to the chain for the sorted position at which we
13029 : should insert in the middle of the struct component list
13030 : (else NULL to insert at end).
13031 : alloc_node : the "alloc" node for the structure (pointer-type)
13032 : component. We insert at SCP (if present), else SC
13033 : (the end of the struct component list).
13034 : extra_node : a newly-synthesized node for an additional indirect
13035 : pointer mapping or a Fortran pointer set, if needed.
13036 : cl : first node to prepend before grp_start_p.
13037 : tail_chain : pointer to chain of last prepended node.
13038 :
13039 : The general idea is we move the nodes for this struct mapping
13040 : together: the alloc node goes into the sorted list directly after
13041 : the struct mapping, and any extra nodes (together with the nodes
13042 : mapping arrays pointed to by struct components) get moved after
13043 : that list. When SCP is NULL, we insert the nodes at SC, i.e. at
13044 : the end of the struct component mapping list. It's important that
13045 : the alloc_node comes first in that case because it's part of the
13046 : sorted component mapping list (but subsequent nodes are not!). */
13047 :
13048 325 : if (scp)
13049 254 : omp_siblist_insert_node_after (alloc_node, scp);
13050 :
13051 : /* Make [cl,tail_chain] a list of the alloc node (if we haven't
13052 : already inserted it) and the extra_node (if it is present). The
13053 : list can be empty if we added alloc_node above and there is no
13054 : extra node. */
13055 254 : if (scp && extra_node)
13056 : {
13057 0 : cl = extra_node;
13058 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13059 : }
13060 325 : else if (extra_node)
13061 : {
13062 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
13063 0 : cl = alloc_node;
13064 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13065 : }
13066 325 : else if (!scp)
13067 : {
13068 71 : cl = alloc_node;
13069 71 : tail_chain = &OMP_CLAUSE_CHAIN (alloc_node);
13070 : }
13071 :
13072 325 : continue_at
13073 71 : = cl ? omp_siblist_move_concat_nodes_after (cl, tail_chain,
13074 : grp_start_p, grp_end,
13075 : sc)
13076 254 : : omp_siblist_move_nodes_after (grp_start_p, grp_end, sc);
13077 : }
13078 732 : else if (*sc != grp_end)
13079 : {
13080 692 : gcc_assert (*grp_start_p == grp_end);
13081 :
13082 : /* We are moving the current node back to a previous struct node:
13083 : the node that used to point to the current node will now point to
13084 : the next node. */
13085 692 : continue_at = grp_start_p;
13086 : /* In the non-pointer case, the mapping clause itself is moved into
13087 : the correct position in the struct component list, which in this
13088 : case is just SC. */
13089 692 : omp_siblist_move_node_after (*grp_start_p, grp_start_p, sc);
13090 : }
13091 : }
13092 : return continue_at;
13093 : }
13094 :
13095 : /* Scan through GROUPS, and create sorted structure sibling lists without
13096 : gimplifying. */
13097 :
13098 : static bool
13099 17977 : omp_build_struct_sibling_lists (enum tree_code code,
13100 : enum omp_region_type region_type,
13101 : vec<omp_mapping_group> *groups,
13102 : hash_map<tree_operand_hash_no_se,
13103 : omp_mapping_group *> **grpmap,
13104 : tree *list_p)
13105 : {
13106 17977 : using namespace omp_addr_tokenizer;
13107 17977 : unsigned i;
13108 17977 : omp_mapping_group *grp;
13109 17977 : hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
13110 17977 : bool success = true;
13111 17977 : tree *new_next = NULL;
13112 35954 : tree *tail = &OMP_CLAUSE_CHAIN ((*groups)[groups->length () - 1].grp_end);
13113 17977 : tree added_nodes = NULL_TREE;
13114 17977 : tree *added_tail = &added_nodes;
13115 17977 : auto_vec<omp_mapping_group> pre_hwm_groups;
13116 :
13117 67200 : FOR_EACH_VEC_ELT (*groups, i, grp)
13118 : {
13119 31246 : tree c = grp->grp_end;
13120 31246 : tree decl = OMP_CLAUSE_DECL (c);
13121 31246 : tree grp_end = grp->grp_end;
13122 31246 : auto_vec<omp_addr_token *> addr_tokens;
13123 31246 : tree sentinel = OMP_CLAUSE_CHAIN (grp_end);
13124 :
13125 31246 : if (new_next && !grp->reprocess_struct)
13126 622 : grp->grp_start = new_next;
13127 :
13128 31246 : new_next = NULL;
13129 :
13130 31246 : tree *grp_start_p = grp->grp_start;
13131 :
13132 31246 : if (DECL_P (decl))
13133 21114 : continue;
13134 :
13135 : /* Skip groups we marked for deletion in
13136 : {omp,oacc}_resolve_clause_dependencies. */
13137 10132 : if (grp->deleted)
13138 462 : continue;
13139 :
13140 9670 : if (OMP_CLAUSE_CHAIN (*grp_start_p)
13141 9670 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
13142 : {
13143 : /* Don't process an array descriptor that isn't inside a derived type
13144 : as a struct (the GOMP_MAP_POINTER following will have the form
13145 : "var.data", but such mappings are handled specially). */
13146 6111 : tree grpmid = OMP_CLAUSE_CHAIN (*grp_start_p);
13147 6111 : if (omp_map_clause_descriptor_p (grpmid)
13148 10262 : && DECL_P (OMP_CLAUSE_DECL (grpmid)))
13149 2807 : continue;
13150 : }
13151 :
13152 : tree expr = decl;
13153 :
13154 7876 : while (TREE_CODE (expr) == ARRAY_REF)
13155 1013 : expr = TREE_OPERAND (expr, 0);
13156 :
13157 6863 : if (!omp_parse_expr (addr_tokens, expr))
13158 0 : continue;
13159 :
13160 6863 : omp_addr_token *last_token
13161 6863 : = omp_first_chained_access_token (addr_tokens);
13162 :
13163 : /* A mapping of a reference to a pointer member that doesn't specify an
13164 : array section, etc., like this:
13165 : *mystruct.ref_to_ptr
13166 : should not be processed by the struct sibling-list handling code --
13167 : it just transfers the referenced pointer.
13168 :
13169 : In contrast, the quite similar-looking construct:
13170 : *mystruct.ptr
13171 : which is equivalent to e.g.
13172 : mystruct.ptr[0]
13173 : *does* trigger sibling-list processing.
13174 :
13175 : An exception for the former case is for "fragile" groups where the
13176 : reference itself is not handled otherwise; this is subject to special
13177 : handling in omp_accumulate_sibling_list also. */
13178 :
13179 6863 : if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
13180 3397 : && last_token->type == ACCESS_METHOD
13181 3397 : && last_token->u.access_kind == ACCESS_REF
13182 7145 : && !grp->fragile)
13183 217 : continue;
13184 :
13185 6646 : tree d = decl;
13186 6646 : if (TREE_CODE (d) == ARRAY_REF)
13187 : {
13188 1974 : while (TREE_CODE (d) == ARRAY_REF)
13189 998 : d = TREE_OPERAND (d, 0);
13190 976 : if (TREE_CODE (d) == COMPONENT_REF
13191 976 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
13192 : decl = d;
13193 : }
13194 6646 : if (d == decl
13195 5981 : && INDIRECT_REF_P (decl)
13196 734 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
13197 105 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
13198 : == REFERENCE_TYPE)
13199 6743 : && (OMP_CLAUSE_MAP_KIND (c)
13200 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
13201 97 : decl = TREE_OPERAND (decl, 0);
13202 :
13203 6646 : STRIP_NOPS (decl);
13204 :
13205 6646 : if (TREE_CODE (decl) != COMPONENT_REF)
13206 1343 : continue;
13207 :
13208 : /* If we're mapping the whole struct in another node, skip adding this
13209 : node to a sibling list. */
13210 5303 : omp_mapping_group *wholestruct;
13211 5303 : if (omp_mapped_by_containing_struct (*grpmap, OMP_CLAUSE_DECL (c),
13212 : &wholestruct))
13213 : {
13214 177 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
13215 160 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
13216 177 : continue;
13217 : }
13218 :
13219 5126 : if (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
13220 5126 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
13221 5023 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
13222 : && code != OACC_UPDATE
13223 10082 : && code != OMP_TARGET_UPDATE)
13224 : {
13225 4765 : if (error_operand_p (decl))
13226 : {
13227 0 : success = false;
13228 0 : goto error_out;
13229 : }
13230 :
13231 4765 : tree stype = TREE_TYPE (decl);
13232 4765 : if (TREE_CODE (stype) == REFERENCE_TYPE)
13233 768 : stype = TREE_TYPE (stype);
13234 4765 : if (TYPE_SIZE_UNIT (stype) == NULL
13235 4765 : || TREE_CODE (TYPE_SIZE_UNIT (stype)) != INTEGER_CST)
13236 : {
13237 0 : error_at (OMP_CLAUSE_LOCATION (c),
13238 : "mapping field %qE of variable length "
13239 0 : "structure", OMP_CLAUSE_DECL (c));
13240 0 : success = false;
13241 0 : goto error_out;
13242 : }
13243 :
13244 4765 : tree *inner = NULL;
13245 4765 : bool fragile_p = grp->fragile;
13246 :
13247 4765 : new_next
13248 9530 : = omp_accumulate_sibling_list (region_type, code,
13249 : struct_map_to_clause, *grpmap,
13250 : grp_start_p, grp_end, addr_tokens,
13251 : &inner, &fragile_p,
13252 4765 : grp->reprocess_struct, &added_tail);
13253 :
13254 4765 : if (inner)
13255 : {
13256 318 : omp_mapping_group newgrp;
13257 318 : newgrp.grp_start = inner;
13258 318 : if (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (*inner))
13259 : == GOMP_MAP_ATTACH_DETACH)
13260 286 : newgrp.grp_end = OMP_CLAUSE_CHAIN (*inner);
13261 : else
13262 32 : newgrp.grp_end = *inner;
13263 318 : newgrp.mark = UNVISITED;
13264 318 : newgrp.sibling = NULL;
13265 318 : newgrp.deleted = false;
13266 318 : newgrp.reprocess_struct = true;
13267 318 : newgrp.fragile = fragile_p;
13268 318 : newgrp.next = NULL;
13269 318 : groups->safe_push (newgrp);
13270 :
13271 : /* !!! Growing GROUPS might invalidate the pointers in the group
13272 : map. Rebuild it here. This is a bit inefficient, but
13273 : shouldn't happen very often. */
13274 636 : delete (*grpmap);
13275 318 : *grpmap
13276 318 : = omp_reindex_mapping_groups (list_p, groups, &pre_hwm_groups,
13277 : sentinel);
13278 : }
13279 : }
13280 31246 : }
13281 :
13282 : /* Delete groups marked for deletion above. At this point the order of the
13283 : groups may no longer correspond to the order of the underlying list,
13284 : which complicates this a little. First clear out OMP_CLAUSE_DECL for
13285 : deleted nodes... */
13286 :
13287 49223 : FOR_EACH_VEC_ELT (*groups, i, grp)
13288 31246 : if (grp->deleted)
13289 462 : for (tree d = *grp->grp_start;
13290 924 : d != OMP_CLAUSE_CHAIN (grp->grp_end);
13291 462 : d = OMP_CLAUSE_CHAIN (d))
13292 462 : OMP_CLAUSE_DECL (d) = NULL_TREE;
13293 :
13294 : /* ...then sweep through the list removing the now-empty nodes. */
13295 :
13296 : tail = list_p;
13297 95883 : while (*tail)
13298 : {
13299 77906 : if (OMP_CLAUSE_CODE (*tail) == OMP_CLAUSE_MAP
13300 77906 : && OMP_CLAUSE_DECL (*tail) == NULL_TREE)
13301 462 : *tail = OMP_CLAUSE_CHAIN (*tail);
13302 : else
13303 77444 : tail = &OMP_CLAUSE_CHAIN (*tail);
13304 : }
13305 :
13306 : /* Tack on the struct nodes added during nested struct reprocessing. */
13307 17977 : if (added_nodes)
13308 : {
13309 192 : *tail = added_nodes;
13310 192 : tail = added_tail;
13311 : }
13312 :
13313 : /* Find each attach node whose bias needs to be adjusted and move it to the
13314 : group containing its pointee, right after the struct node, so that it can
13315 : be picked up by the adjustment code further down in this function. */
13316 17977 : bool attach_bias_needs_adjustment;
13317 17977 : attach_bias_needs_adjustment = false;
13318 67200 : FOR_EACH_VEC_ELT_REVERSE (*groups, i, grp)
13319 : {
13320 31246 : tree c = *grp->grp_start;
13321 30307 : if (c != NULL && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13322 30292 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
13323 27221 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
13324 3351 : && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) == GOMP_MAP_TO_PSET
13325 560 : && OMP_CLAUSE_MAP_KIND (grp->grp_end) == GOMP_MAP_ATTACH_DETACH
13326 31806 : && OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end))
13327 : {
13328 90 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end) = 0;
13329 90 : attach_bias_needs_adjustment = true;
13330 90 : tree *cp;
13331 90 : for (cp = &OMP_CLAUSE_CHAIN (c); cp != NULL;
13332 206 : cp = &OMP_CLAUSE_CHAIN (*cp))
13333 296 : if (*cp == grp->grp_end)
13334 : {
13335 : c = *cp;
13336 : break;
13337 : }
13338 :
13339 90 : tree base = OMP_CLAUSE_DECL (c);
13340 90 : gcc_assert (TREE_CODE (base) == NOP_EXPR);
13341 90 : base = build_fold_indirect_ref (base);
13342 90 : tree *struct_node = struct_map_to_clause->get (base);
13343 90 : omp_siblist_move_node_after (c, cp, &OMP_CLAUSE_CHAIN (*struct_node));
13344 : }
13345 : }
13346 :
13347 : /* Now we have finished building the struct sibling lists, reprocess
13348 : newly-added "attach" nodes: we need the address of the first
13349 : mapped element of each struct sibling list for the bias of the attach
13350 : operation -- not necessarily the base address of the whole struct. */
13351 17977 : if (struct_map_to_clause)
13352 5553 : for (hash_map<tree_operand_hash, tree>::iterator iter
13353 2495 : = struct_map_to_clause->begin ();
13354 8048 : iter != struct_map_to_clause->end ();
13355 3058 : ++iter)
13356 : {
13357 3058 : tree struct_node = (*iter).second;
13358 3058 : gcc_assert (OMP_CLAUSE_CODE (struct_node) == OMP_CLAUSE_MAP);
13359 3058 : tree attach = OMP_CLAUSE_CHAIN (struct_node);
13360 :
13361 3058 : if (OMP_CLAUSE_CODE (attach) != OMP_CLAUSE_MAP
13362 3058 : || OMP_CLAUSE_MAP_KIND (attach) != GOMP_MAP_ATTACH_DETACH)
13363 2546 : continue;
13364 :
13365 512 : OMP_CLAUSE_SET_MAP_KIND (attach, GOMP_MAP_ATTACH);
13366 :
13367 : /* Sanity check: the standalone attach node will not work if we have
13368 : an "enter data" operation (because for those, variables need to be
13369 : mapped separately and attach nodes must be grouped together with the
13370 : base they attach to). We should only have created the
13371 : ATTACH_DETACH node either after GOMP_MAP_STRUCT for a target region
13372 : or for an intermediate descriptor that needs adjustment -- so this
13373 : should never be true. */
13374 512 : gcc_assert ((region_type & ORT_TARGET) != 0
13375 : || attach_bias_needs_adjustment);
13376 :
13377 : /* This is the first sorted node in the struct sibling list. Use it
13378 : to recalculate the correct bias to use.
13379 : (&first_node - attach_decl).
13380 : For GOMP_MAP_STRUCT_UNORD, we need e.g. the
13381 : min(min(min(first,second),third),fourth) element, because the
13382 : elements aren't in any particular order. */
13383 512 : tree lowest_addr;
13384 512 : if (OMP_CLAUSE_MAP_KIND (struct_node) == GOMP_MAP_STRUCT_UNORD)
13385 : {
13386 94 : tree first_node = OMP_CLAUSE_CHAIN (attach);
13387 94 : unsigned HOST_WIDE_INT num_mappings
13388 94 : = tree_to_uhwi (OMP_CLAUSE_SIZE (struct_node));
13389 94 : lowest_addr = OMP_CLAUSE_DECL (first_node);
13390 94 : lowest_addr = build_fold_addr_expr (lowest_addr);
13391 94 : lowest_addr = fold_convert (pointer_sized_int_node, lowest_addr);
13392 94 : tree next_node = OMP_CLAUSE_CHAIN (first_node);
13393 185 : while (num_mappings > 1)
13394 : {
13395 91 : tree tmp = OMP_CLAUSE_DECL (next_node);
13396 91 : tmp = build_fold_addr_expr (tmp);
13397 91 : tmp = fold_convert (pointer_sized_int_node, tmp);
13398 91 : lowest_addr = fold_build2 (MIN_EXPR, pointer_sized_int_node,
13399 : lowest_addr, tmp);
13400 91 : next_node = OMP_CLAUSE_CHAIN (next_node);
13401 91 : num_mappings--;
13402 : }
13403 94 : lowest_addr = fold_convert (ptrdiff_type_node, lowest_addr);
13404 : }
13405 : else
13406 : {
13407 418 : tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
13408 418 : first_node = build_fold_addr_expr (first_node);
13409 418 : lowest_addr = fold_convert (ptrdiff_type_node, first_node);
13410 : }
13411 512 : tree attach_decl = OMP_CLAUSE_DECL (attach);
13412 512 : attach_decl = fold_convert (ptrdiff_type_node, attach_decl);
13413 512 : OMP_CLAUSE_SIZE (attach)
13414 512 : = fold_build2 (MINUS_EXPR, ptrdiff_type_node, lowest_addr,
13415 : attach_decl);
13416 :
13417 : /* Remove GOMP_MAP_ATTACH node from after struct node. */
13418 512 : OMP_CLAUSE_CHAIN (struct_node) = OMP_CLAUSE_CHAIN (attach);
13419 : /* ...and re-insert it at the end of our clause list. */
13420 512 : *tail = attach;
13421 512 : OMP_CLAUSE_CHAIN (attach) = NULL_TREE;
13422 512 : tail = &OMP_CLAUSE_CHAIN (attach);
13423 : }
13424 :
13425 15482 : error_out:
13426 17977 : if (struct_map_to_clause)
13427 2495 : delete struct_map_to_clause;
13428 :
13429 17977 : return success;
13430 17977 : }
13431 :
13432 : struct instantiate_mapper_info
13433 : {
13434 : tree *mapper_clauses_p;
13435 : struct gimplify_omp_ctx *omp_ctx;
13436 : gimple_seq *pre_p;
13437 : };
13438 :
13439 : /* Helper function for omp_instantiate_mapper. */
13440 :
13441 : static tree
13442 1592 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
13443 : {
13444 1592 : copy_body_data *id = (copy_body_data *) data;
13445 :
13446 1592 : if (DECL_P (*tp))
13447 : {
13448 724 : tree replacement = remap_decl (*tp, id);
13449 724 : if (*tp != replacement)
13450 : {
13451 369 : *tp = unshare_expr (replacement);
13452 369 : *walk_subtrees = 0;
13453 : }
13454 : }
13455 :
13456 1592 : return NULL_TREE;
13457 : }
13458 :
13459 : /* A copy_decl implementation (for use with tree-inline.cc functions) that
13460 : only transform decls or SSA names that are part of a map we already
13461 : prepared. */
13462 :
13463 : static tree
13464 126 : omp_mapper_copy_decl (tree var, copy_body_data *cb)
13465 : {
13466 126 : tree *repl = cb->decl_map->get (var);
13467 :
13468 126 : if (repl)
13469 0 : return *repl;
13470 :
13471 126 : return var;
13472 : }
13473 :
13474 : static tree *
13475 90 : omp_instantiate_mapper (gimple_seq *pre_p,
13476 : hash_map<omp_name_type<tree>, tree> *implicit_mappers,
13477 : tree mapperfn, tree expr, enum gomp_map_kind outer_kind,
13478 : tree *mapper_clauses_p)
13479 : {
13480 90 : tree mapper_name = NULL_TREE;
13481 90 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapperfn);
13482 90 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
13483 :
13484 90 : tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
13485 90 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
13486 :
13487 : /* The "extraction map" is used to map the mapper variable in the "declare
13488 : mapper" directive, and also any temporary variables that have been created
13489 : as part of expanding the mapper function's body (which are expanded as a
13490 : "bind" expression in the pre_p sequence). */
13491 90 : hash_map<tree, tree> extraction_map;
13492 :
13493 90 : extraction_map.put (dummy_var, expr);
13494 90 : extraction_map.put (expr, expr);
13495 :
13496 : /* This copy_body_data is only used to remap the decls in the
13497 : OMP_DECLARE_MAPPER tree node expansion itself. All relevant decls should
13498 : already be in the current function. */
13499 90 : copy_body_data id;
13500 90 : memset (&id, 0, sizeof (id));
13501 90 : id.src_fn = current_function_decl;
13502 90 : id.dst_fn = current_function_decl;
13503 90 : id.src_cfun = cfun;
13504 90 : id.decl_map = &extraction_map;
13505 90 : id.copy_decl = omp_mapper_copy_decl;
13506 90 : id.transform_call_graph_edges = CB_CGE_DUPLICATE; // ???
13507 90 : id.transform_new_cfg = true; // ???
13508 :
13509 282 : for (; clause; clause = OMP_CLAUSE_CHAIN (clause))
13510 : {
13511 192 : enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (clause);
13512 192 : tree *nested_mapper_p = NULL;
13513 :
13514 192 : if (map_kind == GOMP_MAP_PUSH_MAPPER_NAME)
13515 : {
13516 0 : mapper_name = OMP_CLAUSE_DECL (clause);
13517 25 : continue;
13518 : }
13519 192 : else if (map_kind == GOMP_MAP_POP_MAPPER_NAME)
13520 : {
13521 0 : mapper_name = NULL_TREE;
13522 0 : continue;
13523 : }
13524 :
13525 192 : if (OMP_CLAUSE_HAS_ITERATORS (clause))
13526 : {
13527 2 : sorry_at (OMP_CLAUSE_LOCATION (clause),
13528 : "user-defined mapper that uses a %<map%> clause "
13529 : "with %<iterator%>");
13530 2 : continue;
13531 : }
13532 :
13533 190 : tree decl = OMP_CLAUSE_DECL (clause);
13534 190 : tree unshared, type;
13535 190 : bool nonunit_array_with_mapper = false;
13536 :
13537 190 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
13538 : {
13539 62 : location_t loc = OMP_CLAUSE_LOCATION (clause);
13540 62 : tree tmp = lang_hooks.decls.omp_map_array_section (loc, decl);
13541 62 : if (tmp == decl)
13542 : {
13543 48 : unshared = unshare_expr (clause);
13544 48 : nonunit_array_with_mapper = true;
13545 48 : type = TREE_TYPE (TREE_TYPE (decl));
13546 : }
13547 : else
13548 : {
13549 14 : unshared = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
13550 14 : OMP_CLAUSE_CODE (clause));
13551 14 : OMP_CLAUSE_DECL (unshared) = tmp;
13552 14 : OMP_CLAUSE_SIZE (unshared)
13553 28 : = DECL_P (tmp) ? DECL_SIZE_UNIT (tmp)
13554 14 : : TYPE_SIZE_UNIT (TREE_TYPE (tmp));
13555 14 : type = TREE_TYPE (tmp);
13556 : }
13557 : }
13558 : else
13559 : {
13560 128 : unshared = unshare_expr (clause);
13561 128 : type = TREE_TYPE (decl);
13562 : }
13563 :
13564 190 : walk_tree (&unshared, remap_mapper_decl_1, &id, NULL);
13565 :
13566 190 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
13567 28 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
13568 :
13569 190 : decl = OMP_CLAUSE_DECL (unshared);
13570 190 : type = TYPE_MAIN_VARIANT (type);
13571 :
13572 190 : nested_mapper_p = implicit_mappers->get ({ mapper_name, type });
13573 :
13574 190 : if (nested_mapper_p && *nested_mapper_p != mapperfn)
13575 : {
13576 23 : if (nonunit_array_with_mapper)
13577 : {
13578 8 : sorry ("user-defined mapper with non-unit length array section");
13579 8 : continue;
13580 : }
13581 :
13582 15 : if (map_kind == GOMP_MAP_UNSET)
13583 0 : map_kind = outer_kind;
13584 :
13585 15 : mapper_clauses_p
13586 15 : = omp_instantiate_mapper (pre_p, implicit_mappers,
13587 : *nested_mapper_p, decl, map_kind,
13588 : mapper_clauses_p);
13589 15 : continue;
13590 : }
13591 :
13592 167 : *mapper_clauses_p = unshared;
13593 167 : mapper_clauses_p = &OMP_CLAUSE_CHAIN (unshared);
13594 : }
13595 :
13596 90 : return mapper_clauses_p;
13597 90 : }
13598 :
13599 : static int
13600 138031 : omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
13601 : {
13602 138031 : tree decl = (tree) n->key;
13603 138031 : instantiate_mapper_info *im_info = (instantiate_mapper_info *) data;
13604 138031 : gimplify_omp_ctx *ctx = im_info->omp_ctx;
13605 138031 : tree *mapper_p = NULL;
13606 138031 : tree type = TREE_TYPE (decl);
13607 138031 : bool ref_p = false;
13608 138031 : unsigned flags = n->value;
13609 :
13610 138031 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
13611 : return 0;
13612 23626 : if ((flags & GOVD_SEEN) == 0)
13613 : return 0;
13614 : /* If we already have clauses pertaining to a struct variable, then we don't
13615 : want to implicitly invoke a user-defined mapper. */
13616 20096 : if ((flags & GOVD_EXPLICIT) != 0 && AGGREGATE_TYPE_P (TREE_TYPE (decl)))
13617 : return 0;
13618 :
13619 20096 : if (TREE_CODE (type) == REFERENCE_TYPE)
13620 : {
13621 900 : ref_p = true;
13622 900 : type = TREE_TYPE (type);
13623 : }
13624 :
13625 20096 : type = TYPE_MAIN_VARIANT (type);
13626 :
13627 20096 : if (DECL_P (decl) && type && AGGREGATE_TYPE_P (type))
13628 : {
13629 5298 : gcc_assert (ctx);
13630 5298 : mapper_p = ctx->implicit_mappers->get ({ NULL_TREE, type });
13631 : }
13632 :
13633 5298 : if (mapper_p)
13634 : {
13635 : /* If we have a reference, map the pointed-to object rather than the
13636 : reference itself. */
13637 75 : if (ref_p)
13638 2 : decl = build_fold_indirect_ref (decl);
13639 :
13640 75 : im_info->mapper_clauses_p
13641 75 : = omp_instantiate_mapper (im_info->pre_p, ctx->implicit_mappers,
13642 : *mapper_p, decl, GOMP_MAP_TOFROM,
13643 : im_info->mapper_clauses_p);
13644 : /* Make sure we don't map the same variable implicitly in
13645 : gimplify_adjust_omp_clauses_1 also. */
13646 75 : n->value |= GOVD_EXPLICIT;
13647 : }
13648 :
13649 : return 0;
13650 : }
13651 :
13652 : /* Scan the OMP clauses in *LIST_P, installing mappings into a new
13653 : and previous omp contexts. */
13654 :
13655 : static void
13656 130565 : gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
13657 : enum omp_region_type region_type,
13658 : enum tree_code code,
13659 : gimple_seq *loops_seq_p = NULL)
13660 : {
13661 130565 : using namespace omp_addr_tokenizer;
13662 130565 : struct gimplify_omp_ctx *ctx, *outer_ctx;
13663 130565 : tree c;
13664 130565 : tree *orig_list_p = list_p;
13665 130565 : int handled_depend_iterators = -1;
13666 130565 : int nowait = -1;
13667 :
13668 130565 : ctx = new_omp_context (region_type);
13669 130565 : ctx->code = code;
13670 130565 : outer_ctx = ctx->outer_context;
13671 130565 : if (code == OMP_TARGET)
13672 : {
13673 13492 : if (!lang_GNU_Fortran ())
13674 11146 : ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
13675 13492 : ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE;
13676 26984 : ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran ()
13677 13492 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
13678 : }
13679 130565 : if (!lang_GNU_Fortran ())
13680 99341 : switch (code)
13681 : {
13682 18590 : case OMP_TARGET:
13683 18590 : case OMP_TARGET_DATA:
13684 18590 : case OMP_TARGET_ENTER_DATA:
13685 18590 : case OMP_TARGET_EXIT_DATA:
13686 18590 : case OACC_DECLARE:
13687 18590 : case OACC_HOST_DATA:
13688 18590 : case OACC_PARALLEL:
13689 18590 : case OACC_KERNELS:
13690 18590 : ctx->target_firstprivatize_array_bases = true;
13691 : default:
13692 : break;
13693 : }
13694 :
13695 130565 : vec<omp_mapping_group> *groups = NULL;
13696 130565 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
13697 130565 : unsigned grpnum = 0;
13698 130565 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
13699 :
13700 130565 : if (code == OMP_TARGET
13701 130565 : || code == OMP_TARGET_DATA
13702 130565 : || code == OMP_TARGET_ENTER_DATA
13703 : || code == OMP_TARGET_EXIT_DATA
13704 : || code == OACC_DATA
13705 : || code == OACC_KERNELS
13706 : || code == OACC_PARALLEL
13707 : || code == OACC_SERIAL
13708 : || code == OACC_ENTER_DATA
13709 : || code == OACC_EXIT_DATA
13710 : || code == OACC_UPDATE
13711 : || code == OACC_DECLARE)
13712 : {
13713 33862 : if (!(region_type & ORT_ACC))
13714 17350 : *list_p = omp_remove_duplicate_maps (*list_p, false);
13715 33862 : groups = omp_gather_mapping_groups (list_p);
13716 :
13717 33862 : if (groups)
13718 18178 : grpmap = omp_index_mapping_groups (groups);
13719 : }
13720 :
13721 335975 : while ((c = *list_p) != NULL)
13722 : {
13723 205410 : bool remove = false;
13724 205410 : bool notice_outer = true;
13725 205410 : bool map_descriptor;
13726 205410 : const char *check_non_private = NULL;
13727 205410 : unsigned int flags;
13728 205410 : tree decl;
13729 205410 : auto_vec<omp_addr_token *, 10> addr_tokens;
13730 205410 : tree op = NULL_TREE;
13731 205410 : location_t loc = OMP_CLAUSE_LOCATION (c);
13732 :
13733 242899 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
13734 : {
13735 : grp_start_p = NULL;
13736 : grp_end = NULL_TREE;
13737 : }
13738 :
13739 205410 : if (code == OMP_TARGET
13740 : || code == OMP_TARGET_DATA
13741 : || code == OMP_TARGET_ENTER_DATA
13742 172823 : || code == OMP_TARGET_EXIT_DATA)
13743 : /* Do some target-specific type checks for map operands. */
13744 35011 : switch (OMP_CLAUSE_CODE (c))
13745 : {
13746 25612 : case OMP_CLAUSE_MAP:
13747 25612 : op = OMP_CLAUSE_OPERAND (c, 0);
13748 25612 : verify_type_context (loc, TCTX_OMP_MAP, TREE_TYPE (op));
13749 25612 : break;
13750 180 : case OMP_CLAUSE_PRIVATE:
13751 180 : op = OMP_CLAUSE_OPERAND (c, 0);
13752 180 : verify_type_context (loc, TCTX_OMP_PRIVATE, TREE_TYPE (op));
13753 180 : break;
13754 1362 : case OMP_CLAUSE_FIRSTPRIVATE:
13755 1362 : op = OMP_CLAUSE_OPERAND (c, 0);
13756 1362 : verify_type_context (loc, TCTX_OMP_FIRSTPRIVATE, TREE_TYPE (op));
13757 1362 : break;
13758 2922 : case OMP_CLAUSE_IS_DEVICE_PTR:
13759 2922 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13760 2922 : case OMP_CLAUSE_USE_DEVICE_PTR:
13761 2922 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13762 2922 : op = OMP_CLAUSE_OPERAND (c, 0);
13763 2922 : verify_type_context (loc, TCTX_OMP_DEVICE_ADDR, TREE_TYPE (op));
13764 2922 : break;
13765 : default:
13766 : break;
13767 : }
13768 :
13769 205410 : switch (OMP_CLAUSE_CODE (c))
13770 : {
13771 12231 : case OMP_CLAUSE_PRIVATE:
13772 12231 : flags = GOVD_PRIVATE | GOVD_EXPLICIT;
13773 12231 : if (lang_hooks.decls.omp_private_outer_ref (OMP_CLAUSE_DECL (c)))
13774 : {
13775 167 : flags |= GOVD_PRIVATE_OUTER_REF;
13776 167 : OMP_CLAUSE_PRIVATE_OUTER_REF (c) = 1;
13777 : }
13778 : else
13779 : notice_outer = false;
13780 12231 : goto do_add;
13781 5536 : case OMP_CLAUSE_SHARED:
13782 5536 : flags = GOVD_SHARED | GOVD_EXPLICIT;
13783 5536 : goto do_add;
13784 8023 : case OMP_CLAUSE_FIRSTPRIVATE:
13785 8023 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
13786 8023 : check_non_private = "firstprivate";
13787 8023 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13788 : {
13789 380 : gcc_assert (code == OMP_TARGET);
13790 : flags |= GOVD_FIRSTPRIVATE_IMPLICIT;
13791 : }
13792 8023 : goto do_add;
13793 7332 : case OMP_CLAUSE_LASTPRIVATE:
13794 7332 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13795 496 : switch (code)
13796 : {
13797 25 : case OMP_DISTRIBUTE:
13798 25 : error_at (OMP_CLAUSE_LOCATION (c),
13799 : "conditional %<lastprivate%> clause on "
13800 : "%qs construct", "distribute");
13801 25 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13802 25 : break;
13803 13 : case OMP_TASKLOOP:
13804 13 : error_at (OMP_CLAUSE_LOCATION (c),
13805 : "conditional %<lastprivate%> clause on "
13806 : "%qs construct", "taskloop");
13807 13 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13808 13 : break;
13809 : default:
13810 : break;
13811 : }
13812 7332 : flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
13813 7332 : if (code != OMP_LOOP)
13814 6981 : check_non_private = "lastprivate";
13815 7332 : decl = OMP_CLAUSE_DECL (c);
13816 7332 : if (error_operand_p (decl))
13817 0 : goto do_add;
13818 7332 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
13819 7332 : && !lang_hooks.decls.omp_scalar_p (decl, true))
13820 : {
13821 5 : error_at (OMP_CLAUSE_LOCATION (c),
13822 : "non-scalar variable %qD in conditional "
13823 : "%<lastprivate%> clause", decl);
13824 5 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13825 : }
13826 7332 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13827 453 : flags |= GOVD_LASTPRIVATE_CONDITIONAL;
13828 7332 : omp_lastprivate_for_combined_outer_constructs (outer_ctx, decl,
13829 : false);
13830 7332 : goto do_add;
13831 15220 : case OMP_CLAUSE_REDUCTION:
13832 15220 : if (OMP_CLAUSE_REDUCTION_TASK (c))
13833 : {
13834 595 : if (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
13835 : {
13836 408 : if (nowait == -1)
13837 293 : nowait = omp_find_clause (*list_p,
13838 293 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
13839 408 : if (nowait
13840 15 : && (outer_ctx == NULL
13841 0 : || outer_ctx->region_type != ORT_COMBINED_PARALLEL))
13842 : {
13843 15 : error_at (OMP_CLAUSE_LOCATION (c),
13844 : "%<task%> reduction modifier on a construct "
13845 : "with a %<nowait%> clause");
13846 15 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13847 : }
13848 : }
13849 187 : else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL)
13850 : {
13851 40 : error_at (OMP_CLAUSE_LOCATION (c),
13852 : "invalid %<task%> reduction modifier on construct "
13853 : "other than %<parallel%>, %qs, %<sections%> or "
13854 20 : "%<scope%>", lang_GNU_Fortran () ? "do" : "for");
13855 20 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13856 : }
13857 : }
13858 15220 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
13859 831 : switch (code)
13860 : {
13861 4 : case OMP_SECTIONS:
13862 4 : error_at (OMP_CLAUSE_LOCATION (c),
13863 : "%<inscan%> %<reduction%> clause on "
13864 : "%qs construct", "sections");
13865 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13866 4 : break;
13867 4 : case OMP_PARALLEL:
13868 4 : error_at (OMP_CLAUSE_LOCATION (c),
13869 : "%<inscan%> %<reduction%> clause on "
13870 : "%qs construct", "parallel");
13871 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13872 4 : break;
13873 4 : case OMP_TEAMS:
13874 4 : error_at (OMP_CLAUSE_LOCATION (c),
13875 : "%<inscan%> %<reduction%> clause on "
13876 : "%qs construct", "teams");
13877 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13878 4 : break;
13879 4 : case OMP_TASKLOOP:
13880 4 : error_at (OMP_CLAUSE_LOCATION (c),
13881 : "%<inscan%> %<reduction%> clause on "
13882 : "%qs construct", "taskloop");
13883 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13884 4 : break;
13885 4 : case OMP_SCOPE:
13886 4 : error_at (OMP_CLAUSE_LOCATION (c),
13887 : "%<inscan%> %<reduction%> clause on "
13888 : "%qs construct", "scope");
13889 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13890 4 : break;
13891 : default:
13892 : break;
13893 : }
13894 : /* FALLTHRU */
13895 17824 : case OMP_CLAUSE_IN_REDUCTION:
13896 17824 : case OMP_CLAUSE_TASK_REDUCTION:
13897 17824 : flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
13898 : /* OpenACC permits reductions on private variables. */
13899 17824 : if (!(region_type & ORT_ACC)
13900 : /* taskgroup is actually not a worksharing region. */
13901 12305 : && code != OMP_TASKGROUP)
13902 11775 : check_non_private = omp_clause_code_name[OMP_CLAUSE_CODE (c)];
13903 17824 : decl = OMP_CLAUSE_DECL (c);
13904 17824 : if (TREE_CODE (decl) == MEM_REF)
13905 : {
13906 2539 : tree type = TREE_TYPE (decl);
13907 2539 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
13908 2539 : gimplify_ctxp->into_ssa = false;
13909 2539 : if (gimplify_expr (&TYPE_MAX_VALUE (TYPE_DOMAIN (type)), pre_p,
13910 : NULL, is_gimple_val, fb_rvalue, false)
13911 : == GS_ERROR)
13912 : {
13913 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13914 0 : remove = true;
13915 0 : break;
13916 : }
13917 2539 : gimplify_ctxp->into_ssa = saved_into_ssa;
13918 2539 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
13919 2539 : if (DECL_P (v))
13920 : {
13921 571 : omp_firstprivatize_variable (ctx, v);
13922 571 : omp_notice_variable (ctx, v, true);
13923 : }
13924 2539 : decl = TREE_OPERAND (decl, 0);
13925 2539 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
13926 : {
13927 477 : gimplify_ctxp->into_ssa = false;
13928 477 : if (gimplify_expr (&TREE_OPERAND (decl, 1), pre_p,
13929 : NULL, is_gimple_val, fb_rvalue, false)
13930 : == GS_ERROR)
13931 : {
13932 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13933 0 : remove = true;
13934 0 : break;
13935 : }
13936 477 : gimplify_ctxp->into_ssa = saved_into_ssa;
13937 477 : v = TREE_OPERAND (decl, 1);
13938 477 : if (DECL_P (v))
13939 : {
13940 477 : omp_firstprivatize_variable (ctx, v);
13941 477 : omp_notice_variable (ctx, v, true);
13942 : }
13943 477 : decl = TREE_OPERAND (decl, 0);
13944 : }
13945 2539 : if (TREE_CODE (decl) == ADDR_EXPR
13946 1163 : || TREE_CODE (decl) == INDIRECT_REF)
13947 1474 : decl = TREE_OPERAND (decl, 0);
13948 : }
13949 17824 : goto do_add_decl;
13950 2668 : case OMP_CLAUSE_LINEAR:
13951 2668 : if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
13952 : is_gimple_val, fb_rvalue) == GS_ERROR)
13953 : {
13954 : remove = true;
13955 : break;
13956 : }
13957 : else
13958 : {
13959 2668 : if (code == OMP_SIMD
13960 2668 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
13961 : {
13962 1154 : struct gimplify_omp_ctx *octx = outer_ctx;
13963 1154 : if (octx
13964 741 : && octx->region_type == ORT_WORKSHARE
13965 500 : && octx->combined_loop
13966 500 : && !octx->distribute)
13967 : {
13968 492 : if (octx->outer_context
13969 430 : && (octx->outer_context->region_type
13970 : == ORT_COMBINED_PARALLEL))
13971 393 : octx = octx->outer_context->outer_context;
13972 : else
13973 : octx = octx->outer_context;
13974 : }
13975 905 : if (octx
13976 316 : && octx->region_type == ORT_WORKSHARE
13977 16 : && octx->combined_loop
13978 16 : && octx->distribute)
13979 : {
13980 16 : error_at (OMP_CLAUSE_LOCATION (c),
13981 : "%<linear%> clause for variable other than "
13982 : "loop iterator specified on construct "
13983 : "combined with %<distribute%>");
13984 16 : remove = true;
13985 16 : break;
13986 : }
13987 : }
13988 : /* For combined #pragma omp parallel for simd, need to put
13989 : lastprivate and perhaps firstprivate too on the
13990 : parallel. Similarly for #pragma omp for simd. */
13991 : struct gimplify_omp_ctx *octx = outer_ctx;
13992 : bool taskloop_seen = false;
13993 : decl = NULL_TREE;
13994 3443 : do
13995 : {
13996 3443 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
13997 3443 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
13998 : break;
13999 3383 : decl = OMP_CLAUSE_DECL (c);
14000 3383 : if (error_operand_p (decl))
14001 : {
14002 : decl = NULL_TREE;
14003 : break;
14004 : }
14005 3383 : flags = GOVD_SEEN;
14006 3383 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14007 1672 : flags |= GOVD_FIRSTPRIVATE;
14008 3383 : if (!OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14009 3383 : flags |= GOVD_LASTPRIVATE;
14010 3383 : if (octx
14011 2506 : && octx->region_type == ORT_WORKSHARE
14012 1213 : && octx->combined_loop)
14013 : {
14014 1207 : if (octx->outer_context
14015 1037 : && (octx->outer_context->region_type
14016 : == ORT_COMBINED_PARALLEL))
14017 : octx = octx->outer_context;
14018 476 : else if (omp_check_private (octx, decl, false))
14019 : break;
14020 : }
14021 : else if (octx
14022 1299 : && (octx->region_type & ORT_TASK) != 0
14023 307 : && octx->combined_loop)
14024 : taskloop_seen = true;
14025 : else if (octx
14026 996 : && octx->region_type == ORT_COMBINED_PARALLEL
14027 301 : && ((ctx->region_type == ORT_WORKSHARE
14028 201 : && octx == outer_ctx)
14029 100 : || taskloop_seen))
14030 : flags = GOVD_SEEN | GOVD_SHARED;
14031 : else if (octx
14032 695 : && ((octx->region_type & ORT_COMBINED_TEAMS)
14033 : == ORT_COMBINED_TEAMS))
14034 : flags = GOVD_SEEN | GOVD_SHARED;
14035 540 : else if (octx
14036 540 : && octx->region_type == ORT_COMBINED_TARGET)
14037 : {
14038 195 : if (flags & GOVD_LASTPRIVATE)
14039 195 : flags = GOVD_SEEN | GOVD_MAP;
14040 : }
14041 : else
14042 : break;
14043 2071 : splay_tree_node on
14044 2071 : = splay_tree_lookup (octx->variables,
14045 : (splay_tree_key) decl);
14046 2071 : if (on && (on->value & GOVD_DATA_SHARE_CLASS) != 0)
14047 : {
14048 : octx = NULL;
14049 : break;
14050 : }
14051 2067 : omp_add_variable (octx, decl, flags);
14052 2067 : if (octx->outer_context == NULL)
14053 : break;
14054 : octx = octx->outer_context;
14055 : }
14056 : while (1);
14057 2652 : if (octx
14058 2652 : && decl
14059 2652 : && (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14060 728 : || !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
14061 1711 : omp_notice_variable (octx, decl, true);
14062 : }
14063 2652 : flags = GOVD_LINEAR | GOVD_EXPLICIT;
14064 2652 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14065 2652 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14066 : {
14067 : notice_outer = false;
14068 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
14069 : }
14070 2652 : goto do_add;
14071 :
14072 51197 : case OMP_CLAUSE_MAP:
14073 51197 : if (!grp_start_p)
14074 : {
14075 31023 : grp_start_p = list_p;
14076 31023 : grp_end = (*groups)[grpnum].grp_end;
14077 31023 : grpnum++;
14078 : }
14079 51197 : decl = OMP_CLAUSE_DECL (c);
14080 :
14081 51197 : if (error_operand_p (decl))
14082 : {
14083 : remove = true;
14084 : break;
14085 : }
14086 :
14087 51197 : if (!omp_parse_expr (addr_tokens, decl))
14088 : {
14089 : remove = true;
14090 : break;
14091 : }
14092 :
14093 51197 : if (remove)
14094 : break;
14095 51197 : if (DECL_P (decl) && outer_ctx && (region_type & ORT_ACC))
14096 : {
14097 : struct gimplify_omp_ctx *octx;
14098 1167 : for (octx = outer_ctx; octx; octx = octx->outer_context)
14099 : {
14100 1167 : if (octx->region_type != ORT_ACC_HOST_DATA)
14101 : break;
14102 12 : splay_tree_node n2
14103 12 : = splay_tree_lookup (octx->variables,
14104 : (splay_tree_key) decl);
14105 12 : if (n2)
14106 4 : error_at (OMP_CLAUSE_LOCATION (c), "variable %qE "
14107 : "declared in enclosing %<host_data%> region",
14108 4 : DECL_NAME (decl));
14109 : }
14110 : }
14111 :
14112 51197 : map_descriptor = false;
14113 :
14114 : /* This condition checks if we're mapping an array descriptor that
14115 : isn't inside a derived type -- these have special handling, and
14116 : are not handled as structs in omp_build_struct_sibling_lists.
14117 : See that function for further details. */
14118 51197 : if (*grp_start_p != grp_end
14119 34170 : && OMP_CLAUSE_CHAIN (*grp_start_p)
14120 85367 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
14121 : {
14122 17096 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
14123 17096 : if (omp_map_clause_descriptor_p (grp_mid)
14124 32365 : && DECL_P (OMP_CLAUSE_DECL (grp_mid)))
14125 : map_descriptor = true;
14126 : }
14127 34101 : else if (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP
14128 34101 : && (OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_RELEASE
14129 33357 : || OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_DELETE)
14130 35023 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (grp_end))
14131 : map_descriptor = true;
14132 :
14133 : /* Adding the decl for a struct access: we haven't created
14134 : GOMP_MAP_STRUCT nodes yet, so this statement needs to predict
14135 : whether they will be created in gimplify_adjust_omp_clauses.
14136 : NOTE: Technically we should probably look through DECL_VALUE_EXPR
14137 : here because something that looks like a DECL_P may actually be a
14138 : struct access, e.g. variables in a lambda closure
14139 : (__closure->__foo) or class members (this->foo). Currently in both
14140 : those cases we map the whole of the containing object (directly in
14141 : the C++ FE) though, so struct nodes are not created. */
14142 51197 : if (c == grp_end
14143 31023 : && addr_tokens[0]->type == STRUCTURE_BASE
14144 8396 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14145 59593 : && !map_descriptor)
14146 : {
14147 5592 : gcc_assert (addr_tokens[1]->type == ACCESS_METHOD);
14148 : /* If we got to this struct via a chain of pointers, maybe we
14149 : want to map it implicitly instead. */
14150 5592 : if (omp_access_chain_p (addr_tokens, 1))
14151 : break;
14152 5431 : omp_mapping_group *wholestruct;
14153 5431 : if (!(region_type & ORT_ACC)
14154 9587 : && omp_mapped_by_containing_struct (grpmap,
14155 4156 : OMP_CLAUSE_DECL (c),
14156 : &wholestruct))
14157 : break;
14158 5195 : decl = addr_tokens[1]->expr;
14159 5195 : if (splay_tree_lookup (ctx->variables, (splay_tree_key) decl))
14160 : break;
14161 : /* Standalone attach or detach clauses for a struct element
14162 : should not inhibit implicit mapping of the whole struct. */
14163 2983 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
14164 2983 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
14165 : break;
14166 2833 : flags = GOVD_MAP | GOVD_EXPLICIT;
14167 :
14168 2833 : gcc_assert (addr_tokens[1]->u.access_kind != ACCESS_DIRECT
14169 : || TREE_ADDRESSABLE (decl));
14170 2833 : goto do_add_decl;
14171 : }
14172 :
14173 45605 : if (!DECL_P (decl))
14174 : {
14175 21080 : tree d = decl, *pd;
14176 21080 : if (TREE_CODE (d) == ARRAY_REF)
14177 : {
14178 5022 : while (TREE_CODE (d) == ARRAY_REF)
14179 2568 : d = TREE_OPERAND (d, 0);
14180 2454 : if (TREE_CODE (d) == COMPONENT_REF
14181 2454 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
14182 : decl = d;
14183 : }
14184 21080 : pd = &OMP_CLAUSE_DECL (c);
14185 21080 : if (d == decl
14186 18672 : && TREE_CODE (decl) == INDIRECT_REF
14187 13936 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
14188 1069 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
14189 : == REFERENCE_TYPE)
14190 21731 : && (OMP_CLAUSE_MAP_KIND (c)
14191 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
14192 : {
14193 647 : pd = &TREE_OPERAND (decl, 0);
14194 647 : decl = TREE_OPERAND (decl, 0);
14195 : }
14196 :
14197 21080 : if (addr_tokens[0]->type == STRUCTURE_BASE
14198 11439 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14199 11438 : && addr_tokens[1]->type == ACCESS_METHOD
14200 11438 : && (addr_tokens[1]->u.access_kind == ACCESS_POINTER
14201 10940 : || (addr_tokens[1]->u.access_kind
14202 : == ACCESS_POINTER_OFFSET))
14203 21660 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)))
14204 : {
14205 0 : tree base = addr_tokens[1]->expr;
14206 0 : splay_tree_node n
14207 0 : = splay_tree_lookup (ctx->variables,
14208 : (splay_tree_key) base);
14209 0 : n->value |= GOVD_SEEN;
14210 : }
14211 :
14212 21080 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
14213 : {
14214 : /* Don't gimplify *pd fully at this point, as the base
14215 : will need to be adjusted during omp lowering. */
14216 88 : auto_vec<tree, 10> expr_stack;
14217 88 : tree *p = pd;
14218 88 : while (handled_component_p (*p)
14219 : || TREE_CODE (*p) == INDIRECT_REF
14220 : || TREE_CODE (*p) == ADDR_EXPR
14221 : || TREE_CODE (*p) == MEM_REF
14222 224 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
14223 : {
14224 136 : expr_stack.safe_push (*p);
14225 136 : p = &TREE_OPERAND (*p, 0);
14226 : }
14227 312 : for (int i = expr_stack.length () - 1; i >= 0; i--)
14228 : {
14229 136 : tree t = expr_stack[i];
14230 136 : if (TREE_CODE (t) == ARRAY_REF
14231 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14232 : {
14233 56 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14234 : {
14235 56 : tree low = unshare_expr (array_ref_low_bound (t));
14236 56 : if (!is_gimple_min_invariant (low))
14237 : {
14238 0 : TREE_OPERAND (t, 2) = low;
14239 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14240 : pre_p, NULL,
14241 : is_gimple_reg,
14242 : fb_rvalue) == GS_ERROR)
14243 0 : remove = true;
14244 : }
14245 : }
14246 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14247 : NULL, is_gimple_reg,
14248 : fb_rvalue) == GS_ERROR)
14249 0 : remove = true;
14250 56 : if (TREE_OPERAND (t, 3) == NULL_TREE)
14251 : {
14252 56 : tree elmt_size = array_ref_element_size (t);
14253 56 : if (!is_gimple_min_invariant (elmt_size))
14254 : {
14255 0 : elmt_size = unshare_expr (elmt_size);
14256 0 : tree elmt_type
14257 0 : = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t,
14258 : 0)));
14259 0 : tree factor
14260 0 : = size_int (TYPE_ALIGN_UNIT (elmt_type));
14261 0 : elmt_size
14262 0 : = size_binop (EXACT_DIV_EXPR, elmt_size,
14263 : factor);
14264 0 : TREE_OPERAND (t, 3) = elmt_size;
14265 0 : if (gimplify_expr (&TREE_OPERAND (t, 3),
14266 : pre_p, NULL,
14267 : is_gimple_reg,
14268 : fb_rvalue) == GS_ERROR)
14269 0 : remove = true;
14270 : }
14271 : }
14272 0 : else if (gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
14273 : NULL, is_gimple_reg,
14274 : fb_rvalue) == GS_ERROR)
14275 0 : remove = true;
14276 : }
14277 80 : else if (TREE_CODE (t) == COMPONENT_REF)
14278 : {
14279 0 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14280 : {
14281 0 : tree offset = component_ref_field_offset (t);
14282 0 : if (!is_gimple_min_invariant (offset))
14283 : {
14284 0 : offset = unshare_expr (offset);
14285 0 : tree field = TREE_OPERAND (t, 1);
14286 0 : tree factor
14287 0 : = size_int (DECL_OFFSET_ALIGN (field)
14288 : / BITS_PER_UNIT);
14289 0 : offset = size_binop (EXACT_DIV_EXPR, offset,
14290 : factor);
14291 0 : TREE_OPERAND (t, 2) = offset;
14292 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14293 : pre_p, NULL,
14294 : is_gimple_reg,
14295 : fb_rvalue) == GS_ERROR)
14296 0 : remove = true;
14297 : }
14298 : }
14299 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14300 : NULL, is_gimple_reg,
14301 : fb_rvalue) == GS_ERROR)
14302 0 : remove = true;
14303 : }
14304 : }
14305 224 : for (; expr_stack.length () > 0; )
14306 : {
14307 136 : tree t = expr_stack.pop ();
14308 :
14309 136 : if (TREE_CODE (t) == ARRAY_REF
14310 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14311 : {
14312 56 : if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))
14313 56 : && gimplify_expr (&TREE_OPERAND (t, 1), pre_p,
14314 : NULL, is_gimple_val,
14315 : fb_rvalue) == GS_ERROR)
14316 144 : remove = true;
14317 : }
14318 : }
14319 88 : }
14320 : break;
14321 : }
14322 :
14323 24525 : if ((code == OMP_TARGET
14324 : || code == OMP_TARGET_DATA
14325 : || code == OMP_TARGET_ENTER_DATA
14326 14224 : || code == OMP_TARGET_EXIT_DATA)
14327 25162 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14328 : {
14329 : /* If we have attach/detach but the decl we have is a pointer to
14330 : pointer, we're probably mapping the "base level" array
14331 : implicitly. Make sure we don't add the decl as if we mapped
14332 : it explicitly. That is,
14333 :
14334 : int **arr;
14335 : [...]
14336 : #pragma omp target map(arr[a][b:c])
14337 :
14338 : should *not* map "arr" explicitly. That way we get a
14339 : zero-length "alloc" mapping for it, and assuming it's been
14340 : mapped by some previous directive, etc., things work as they
14341 : should. */
14342 :
14343 213 : tree basetype = TREE_TYPE (addr_tokens[0]->expr);
14344 :
14345 213 : if (TREE_CODE (basetype) == REFERENCE_TYPE)
14346 34 : basetype = TREE_TYPE (basetype);
14347 :
14348 213 : if (code == OMP_TARGET
14349 54 : && addr_tokens[0]->type == ARRAY_BASE
14350 54 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14351 54 : && TREE_CODE (basetype) == POINTER_TYPE
14352 267 : && TREE_CODE (TREE_TYPE (basetype)) == POINTER_TYPE)
14353 : break;
14354 : }
14355 :
14356 24503 : flags = GOVD_MAP | GOVD_EXPLICIT;
14357 24503 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
14358 24368 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM
14359 23864 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TO
14360 48337 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TOFROM)
14361 : flags |= GOVD_MAP_ALWAYS_TO;
14362 :
14363 24503 : goto do_add;
14364 :
14365 374 : case OMP_CLAUSE_AFFINITY:
14366 374 : gimplify_omp_affinity (list_p, pre_p);
14367 374 : remove = true;
14368 374 : break;
14369 8 : case OMP_CLAUSE_DOACROSS:
14370 8 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
14371 : {
14372 4 : tree deps = OMP_CLAUSE_DECL (c);
14373 8 : while (deps && TREE_CODE (deps) == TREE_LIST)
14374 : {
14375 4 : if (TREE_CODE (TREE_PURPOSE (deps)) == TRUNC_DIV_EXPR
14376 4 : && DECL_P (TREE_OPERAND (TREE_PURPOSE (deps), 1)))
14377 0 : gimplify_expr (&TREE_OPERAND (TREE_PURPOSE (deps), 1),
14378 : pre_p, NULL, is_gimple_val, fb_rvalue);
14379 4 : deps = TREE_CHAIN (deps);
14380 : }
14381 : }
14382 : else
14383 4 : gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
14384 : == OMP_CLAUSE_DOACROSS_SOURCE);
14385 : break;
14386 2207 : case OMP_CLAUSE_DEPEND:
14387 2207 : if (handled_depend_iterators == -1)
14388 1905 : handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
14389 2207 : if (handled_depend_iterators)
14390 : {
14391 348 : if (handled_depend_iterators == 2)
14392 0 : remove = true;
14393 : break;
14394 : }
14395 1859 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
14396 : {
14397 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
14398 : NULL, is_gimple_val, fb_rvalue);
14399 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
14400 : }
14401 1859 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
14402 : {
14403 : remove = true;
14404 : break;
14405 : }
14406 1859 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
14407 : {
14408 1828 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
14409 1828 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
14410 : is_gimple_val, fb_rvalue) == GS_ERROR)
14411 : {
14412 : remove = true;
14413 : break;
14414 : }
14415 : }
14416 1859 : if (code == OMP_TASK)
14417 1401 : ctx->has_depend = true;
14418 : break;
14419 :
14420 8333 : case OMP_CLAUSE_TO:
14421 8333 : case OMP_CLAUSE_FROM:
14422 8333 : case OMP_CLAUSE__CACHE_:
14423 8333 : decl = OMP_CLAUSE_DECL (c);
14424 8333 : if (error_operand_p (decl))
14425 : {
14426 : remove = true;
14427 : break;
14428 : }
14429 8333 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14430 7660 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
14431 796 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
14432 8333 : gimple_seq *seq_p;
14433 8333 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
14434 8333 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
14435 : is_gimple_val, fb_rvalue) == GS_ERROR)
14436 : {
14437 0 : remove = true;
14438 0 : exit_omp_iterator_loop_context (c);
14439 0 : break;
14440 : }
14441 8333 : if (!DECL_P (decl))
14442 : {
14443 2144 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
14444 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
14445 0 : remove = true;
14446 2144 : exit_omp_iterator_loop_context (c);
14447 2144 : break;
14448 : }
14449 6189 : exit_omp_iterator_loop_context (c);
14450 6189 : goto do_notice;
14451 :
14452 135 : case OMP_CLAUSE__MAPPER_BINDING_:
14453 135 : {
14454 135 : tree name = OMP_CLAUSE__MAPPER_BINDING__ID (c);
14455 135 : tree var = OMP_CLAUSE__MAPPER_BINDING__DECL (c);
14456 135 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (var));
14457 135 : tree fndecl = OMP_CLAUSE__MAPPER_BINDING__MAPPER (c);
14458 135 : ctx->implicit_mappers->put ({ name, type }, fndecl);
14459 135 : remove = true;
14460 135 : break;
14461 : }
14462 :
14463 2118 : case OMP_CLAUSE_USE_DEVICE_PTR:
14464 2118 : case OMP_CLAUSE_USE_DEVICE_ADDR:
14465 2118 : flags = GOVD_EXPLICIT;
14466 2118 : goto do_add;
14467 :
14468 557 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14469 557 : decl = OMP_CLAUSE_DECL (c);
14470 557 : while (TREE_CODE (decl) == INDIRECT_REF
14471 606 : || TREE_CODE (decl) == ARRAY_REF)
14472 49 : decl = TREE_OPERAND (decl, 0);
14473 557 : flags = GOVD_EXPLICIT;
14474 557 : goto do_add_decl;
14475 :
14476 500 : case OMP_CLAUSE_IS_DEVICE_PTR:
14477 500 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
14478 500 : goto do_add;
14479 :
14480 63085 : do_add:
14481 63085 : decl = OMP_CLAUSE_DECL (c);
14482 84299 : do_add_decl:
14483 84299 : if (error_operand_p (decl))
14484 : {
14485 : remove = true;
14486 : break;
14487 : }
14488 84291 : if (DECL_NAME (decl) == NULL_TREE && (flags & GOVD_SHARED) == 0)
14489 : {
14490 1755 : tree t = omp_member_access_dummy_var (decl);
14491 1755 : if (t)
14492 : {
14493 668 : tree v = DECL_VALUE_EXPR (decl);
14494 668 : DECL_NAME (decl) = DECL_NAME (TREE_OPERAND (v, 1));
14495 668 : if (outer_ctx)
14496 140 : omp_notice_variable (outer_ctx, t, true);
14497 : }
14498 : }
14499 84291 : if (code == OACC_DATA
14500 2402 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14501 86693 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14502 307 : flags |= GOVD_MAP_0LEN_ARRAY;
14503 84291 : omp_add_variable (ctx, decl, flags);
14504 84291 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14505 69071 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
14506 66997 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
14507 86895 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
14508 : {
14509 2093 : struct gimplify_omp_ctx *pctx
14510 2153 : = code == OMP_TARGET ? outer_ctx : ctx;
14511 2153 : if (pctx)
14512 2123 : omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
14513 : GOVD_LOCAL | GOVD_SEEN);
14514 2123 : if (pctx
14515 2123 : && OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
14516 632 : && walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
14517 : find_decl_expr,
14518 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14519 : NULL) == NULL_TREE)
14520 208 : omp_add_variable (pctx,
14521 208 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14522 : GOVD_LOCAL | GOVD_SEEN);
14523 2153 : gimplify_omp_ctxp = pctx;
14524 2153 : push_gimplify_context ();
14525 :
14526 2153 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
14527 2153 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
14528 :
14529 2153 : gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
14530 2153 : &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
14531 2153 : pop_gimplify_context
14532 2153 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)));
14533 2153 : push_gimplify_context ();
14534 4306 : gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
14535 2153 : &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
14536 2153 : pop_gimplify_context
14537 2153 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
14538 2153 : OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
14539 2153 : OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
14540 :
14541 2153 : gimplify_omp_ctxp = outer_ctx;
14542 : }
14543 82138 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
14544 82138 : && OMP_CLAUSE_LASTPRIVATE_STMT (c))
14545 : {
14546 303 : gimplify_omp_ctxp = ctx;
14547 303 : push_gimplify_context ();
14548 303 : if (TREE_CODE (OMP_CLAUSE_LASTPRIVATE_STMT (c)) != BIND_EXPR)
14549 : {
14550 303 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14551 : NULL, NULL);
14552 303 : TREE_SIDE_EFFECTS (bind) = 1;
14553 303 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LASTPRIVATE_STMT (c);
14554 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = bind;
14555 : }
14556 606 : gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c),
14557 303 : &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
14558 303 : pop_gimplify_context
14559 303 : (gimple_seq_first_stmt (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)));
14560 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL_TREE;
14561 :
14562 303 : gimplify_omp_ctxp = outer_ctx;
14563 : }
14564 81835 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14565 81835 : && OMP_CLAUSE_LINEAR_STMT (c))
14566 : {
14567 60 : gimplify_omp_ctxp = ctx;
14568 60 : push_gimplify_context ();
14569 60 : if (TREE_CODE (OMP_CLAUSE_LINEAR_STMT (c)) != BIND_EXPR)
14570 : {
14571 60 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14572 : NULL, NULL);
14573 60 : TREE_SIDE_EFFECTS (bind) = 1;
14574 60 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LINEAR_STMT (c);
14575 60 : OMP_CLAUSE_LINEAR_STMT (c) = bind;
14576 : }
14577 120 : gimplify_and_add (OMP_CLAUSE_LINEAR_STMT (c),
14578 60 : &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
14579 60 : pop_gimplify_context
14580 60 : (gimple_seq_first_stmt (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)));
14581 60 : OMP_CLAUSE_LINEAR_STMT (c) = NULL_TREE;
14582 :
14583 60 : gimplify_omp_ctxp = outer_ctx;
14584 : }
14585 84291 : if (notice_outer)
14586 72167 : goto do_notice;
14587 : break;
14588 :
14589 906 : case OMP_CLAUSE_COPYIN:
14590 906 : case OMP_CLAUSE_COPYPRIVATE:
14591 906 : decl = OMP_CLAUSE_DECL (c);
14592 906 : if (error_operand_p (decl))
14593 : {
14594 : remove = true;
14595 : break;
14596 : }
14597 906 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
14598 : && !remove
14599 906 : && !omp_check_private (ctx, decl, true))
14600 : {
14601 35 : remove = true;
14602 35 : if (is_global_var (decl))
14603 : {
14604 30 : if (DECL_THREAD_LOCAL_P (decl))
14605 : remove = false;
14606 10 : else if (DECL_HAS_VALUE_EXPR_P (decl))
14607 : {
14608 2 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
14609 :
14610 2 : if (value
14611 2 : && DECL_P (value)
14612 4 : && DECL_THREAD_LOCAL_P (value))
14613 : remove = false;
14614 : }
14615 : }
14616 : if (remove)
14617 13 : error_at (OMP_CLAUSE_LOCATION (c),
14618 : "copyprivate variable %qE is not threadprivate"
14619 13 : " or private in outer context", DECL_NAME (decl));
14620 : }
14621 79262 : do_notice:
14622 79262 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14623 64042 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
14624 56019 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
14625 30575 : && outer_ctx
14626 17547 : && ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
14627 16208 : || (region_type == ORT_WORKSHARE
14628 3884 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14629 1087 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
14630 912 : || code == OMP_LOOP)))
14631 81207 : && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
14632 857 : || (code == OMP_LOOP
14633 138 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14634 138 : && ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
14635 : == ORT_COMBINED_TEAMS))))
14636 : {
14637 1209 : splay_tree_node on
14638 1209 : = splay_tree_lookup (outer_ctx->variables,
14639 : (splay_tree_key)decl);
14640 1209 : if (on == NULL || (on->value & GOVD_DATA_SHARE_CLASS) == 0)
14641 : {
14642 891 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14643 705 : && TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14644 1003 : && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
14645 56 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
14646 0 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
14647 : == POINTER_TYPE))))
14648 56 : omp_firstprivatize_variable (outer_ctx, decl);
14649 : else
14650 : {
14651 835 : omp_add_variable (outer_ctx, decl,
14652 : GOVD_SEEN | GOVD_SHARED);
14653 835 : if (outer_ctx->outer_context)
14654 235 : omp_notice_variable (outer_ctx->outer_context, decl,
14655 : true);
14656 : }
14657 : }
14658 : }
14659 78662 : if (outer_ctx)
14660 29585 : omp_notice_variable (outer_ctx, decl, true);
14661 79262 : if (check_non_private
14662 26779 : && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
14663 4747 : && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
14664 1641 : || decl == OMP_CLAUSE_DECL (c)
14665 224 : || (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14666 224 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14667 : == ADDR_EXPR
14668 103 : || (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14669 : == POINTER_PLUS_EXPR
14670 22 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND
14671 : (OMP_CLAUSE_DECL (c), 0), 0))
14672 : == ADDR_EXPR)))))
14673 83921 : && omp_check_private (ctx, decl, false))
14674 : {
14675 58 : error ("%s variable %qE is private in outer context",
14676 29 : check_non_private, DECL_NAME (decl));
14677 29 : remove = true;
14678 : }
14679 : break;
14680 :
14681 190 : case OMP_CLAUSE_DETACH:
14682 190 : flags = GOVD_FIRSTPRIVATE | GOVD_SEEN;
14683 190 : goto do_add;
14684 :
14685 4108 : case OMP_CLAUSE_IF:
14686 4108 : if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK
14687 4108 : && OMP_CLAUSE_IF_MODIFIER (c) != code)
14688 : {
14689 : const char *p[2];
14690 168 : for (int i = 0; i < 2; i++)
14691 112 : switch (i ? OMP_CLAUSE_IF_MODIFIER (c) : code)
14692 : {
14693 8 : case VOID_CST: p[i] = "cancel"; break;
14694 24 : case OMP_PARALLEL: p[i] = "parallel"; break;
14695 4 : case OMP_SIMD: p[i] = "simd"; break;
14696 12 : case OMP_TASK: p[i] = "task"; break;
14697 12 : case OMP_TASKLOOP: p[i] = "taskloop"; break;
14698 8 : case OMP_TARGET_DATA: p[i] = "target data"; break;
14699 12 : case OMP_TARGET: p[i] = "target"; break;
14700 12 : case OMP_TARGET_UPDATE: p[i] = "target update"; break;
14701 8 : case OMP_TARGET_ENTER_DATA:
14702 8 : p[i] = "target enter data"; break;
14703 12 : case OMP_TARGET_EXIT_DATA: p[i] = "target exit data"; break;
14704 0 : default: gcc_unreachable ();
14705 : }
14706 56 : error_at (OMP_CLAUSE_LOCATION (c),
14707 : "expected %qs %<if%> clause modifier rather than %qs",
14708 : p[0], p[1]);
14709 56 : remove = true;
14710 : }
14711 : /* Fall through. */
14712 :
14713 4818 : case OMP_CLAUSE_SELF:
14714 4818 : case OMP_CLAUSE_FINAL:
14715 4818 : OMP_CLAUSE_OPERAND (c, 0)
14716 9636 : = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
14717 : /* Fall through. */
14718 :
14719 5721 : case OMP_CLAUSE_NUM_TEAMS:
14720 5721 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
14721 903 : && OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14722 5966 : && !is_gimple_min_invariant (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14723 : {
14724 208 : if (error_operand_p (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14725 : {
14726 : remove = true;
14727 : break;
14728 : }
14729 208 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14730 416 : = get_initialized_tmp_var (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c),
14731 : pre_p, NULL, true);
14732 : }
14733 : /* Fall through. */
14734 :
14735 21802 : case OMP_CLAUSE_SCHEDULE:
14736 21802 : case OMP_CLAUSE_NUM_THREADS:
14737 21802 : case OMP_CLAUSE_THREAD_LIMIT:
14738 21802 : case OMP_CLAUSE_DIST_SCHEDULE:
14739 21802 : case OMP_CLAUSE_DEVICE:
14740 21802 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14741 21802 : && OMP_CLAUSE_DEVICE_ANCESTOR (c))
14742 : {
14743 125 : if (code != OMP_TARGET)
14744 : {
14745 20 : error_at (OMP_CLAUSE_LOCATION (c),
14746 : "%<device%> clause with %<ancestor%> is only "
14747 : "allowed on %<target%> construct");
14748 20 : remove = true;
14749 20 : break;
14750 : }
14751 :
14752 105 : tree clauses = *orig_list_p;
14753 330 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
14754 236 : if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE
14755 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE
14756 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE
14757 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP
14758 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP
14759 : )
14760 : {
14761 11 : error_at (OMP_CLAUSE_LOCATION (c),
14762 : "with %<ancestor%>, only the %<device%>, "
14763 : "%<firstprivate%>, %<private%>, %<defaultmap%>, "
14764 : "and %<map%> clauses may appear on the "
14765 : "construct");
14766 11 : remove = true;
14767 11 : break;
14768 : }
14769 : }
14770 21677 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14771 21677 : && code == OMP_DISPATCH)
14772 : {
14773 272 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
14774 272 : gimplify_ctxp->into_ssa = false;
14775 272 : if (gimplify_expr (&OMP_CLAUSE_DEVICE_ID (c), pre_p, NULL,
14776 : is_gimple_val, fb_rvalue)
14777 : == GS_ERROR)
14778 : remove = true;
14779 272 : else if (DECL_P (OMP_CLAUSE_DEVICE_ID (c)))
14780 55 : omp_add_variable (ctx, OMP_CLAUSE_DEVICE_ID (c),
14781 : GOVD_SHARED | GOVD_SEEN);
14782 272 : gimplify_ctxp->into_ssa = saved_into_ssa;
14783 272 : break;
14784 : }
14785 : /* Fall through. */
14786 :
14787 31251 : case OMP_CLAUSE_PRIORITY:
14788 31251 : case OMP_CLAUSE_GRAINSIZE:
14789 31251 : case OMP_CLAUSE_NUM_TASKS:
14790 31251 : case OMP_CLAUSE_FILTER:
14791 31251 : case OMP_CLAUSE_HINT:
14792 31251 : case OMP_CLAUSE_ASYNC:
14793 31251 : case OMP_CLAUSE_WAIT:
14794 31251 : case OMP_CLAUSE_NUM_GANGS:
14795 31251 : case OMP_CLAUSE_NUM_WORKERS:
14796 31251 : case OMP_CLAUSE_VECTOR_LENGTH:
14797 31251 : case OMP_CLAUSE_WORKER:
14798 31251 : case OMP_CLAUSE_VECTOR:
14799 31251 : if (OMP_CLAUSE_OPERAND (c, 0)
14800 31251 : && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0)))
14801 : {
14802 7774 : if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0)))
14803 : {
14804 : remove = true;
14805 : break;
14806 : }
14807 : /* All these clauses care about value, not a particular decl,
14808 : so try to force it into a SSA_NAME or fresh temporary. */
14809 7767 : OMP_CLAUSE_OPERAND (c, 0)
14810 15534 : = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0),
14811 : pre_p, NULL, true);
14812 : }
14813 : break;
14814 :
14815 2332 : case OMP_CLAUSE_GANG:
14816 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
14817 : is_gimple_val, fb_rvalue) == GS_ERROR)
14818 0 : remove = true;
14819 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL,
14820 : is_gimple_val, fb_rvalue) == GS_ERROR)
14821 0 : remove = true;
14822 : break;
14823 :
14824 13095 : case OMP_CLAUSE_NOWAIT:
14825 13095 : nowait = 1;
14826 13095 : break;
14827 :
14828 72 : case OMP_CLAUSE_USES_ALLOCATORS:
14829 72 : sorry_at (OMP_CLAUSE_LOCATION (c), "%<uses_allocators%> clause");
14830 72 : remove = 1;
14831 72 : break;
14832 :
14833 : case OMP_CLAUSE_ORDERED:
14834 : case OMP_CLAUSE_UNTIED:
14835 : case OMP_CLAUSE_COLLAPSE:
14836 : case OMP_CLAUSE_TILE:
14837 : case OMP_CLAUSE_AUTO:
14838 : case OMP_CLAUSE_SEQ:
14839 : case OMP_CLAUSE_INDEPENDENT:
14840 : case OMP_CLAUSE_MERGEABLE:
14841 : case OMP_CLAUSE_PROC_BIND:
14842 : case OMP_CLAUSE_SAFELEN:
14843 : case OMP_CLAUSE_SIMDLEN:
14844 : case OMP_CLAUSE_NOGROUP:
14845 : case OMP_CLAUSE_THREADS:
14846 : case OMP_CLAUSE_SIMD:
14847 : case OMP_CLAUSE_BIND:
14848 : case OMP_CLAUSE_IF_PRESENT:
14849 : case OMP_CLAUSE_FINALIZE:
14850 : case OMP_CLAUSE_INTEROP:
14851 : case OMP_CLAUSE_INIT:
14852 : case OMP_CLAUSE_USE:
14853 : case OMP_CLAUSE_DESTROY:
14854 : case OMP_CLAUSE_DEVICE_TYPE:
14855 : break;
14856 :
14857 52 : case OMP_CLAUSE_DYN_GROUPPRIVATE:
14858 52 : remove = true;
14859 52 : sorry_at (OMP_CLAUSE_LOCATION (c),"%<dyn_groupprivate%> clause");
14860 52 : break;
14861 :
14862 3976 : case OMP_CLAUSE_ORDER:
14863 3976 : ctx->order_concurrent = true;
14864 3976 : break;
14865 :
14866 1010 : case OMP_CLAUSE_DEFAULTMAP:
14867 1010 : enum gimplify_defaultmap_kind gdmkmin, gdmkmax;
14868 1010 : switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c))
14869 : {
14870 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
14871 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
14872 : gdmkmin = GDMK_SCALAR;
14873 : gdmkmax = GDMK_POINTER;
14874 : break;
14875 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
14876 : gdmkmin = GDMK_SCALAR;
14877 : gdmkmax = GDMK_SCALAR_TARGET;
14878 : break;
14879 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
14880 : gdmkmin = gdmkmax = GDMK_AGGREGATE;
14881 : break;
14882 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE:
14883 : gdmkmin = gdmkmax = GDMK_ALLOCATABLE;
14884 : break;
14885 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
14886 : gdmkmin = gdmkmax = GDMK_POINTER;
14887 : break;
14888 0 : default:
14889 0 : gcc_unreachable ();
14890 : }
14891 4471 : for (int gdmk = gdmkmin; gdmk <= gdmkmax; gdmk++)
14892 3461 : switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (c))
14893 : {
14894 91 : case OMP_CLAUSE_DEFAULTMAP_ALLOC:
14895 91 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_ALLOC_ONLY;
14896 91 : break;
14897 96 : case OMP_CLAUSE_DEFAULTMAP_TO:
14898 96 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_TO_ONLY;
14899 96 : break;
14900 28 : case OMP_CLAUSE_DEFAULTMAP_FROM:
14901 28 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FROM_ONLY;
14902 28 : break;
14903 671 : case OMP_CLAUSE_DEFAULTMAP_TOFROM:
14904 671 : ctx->defaultmap[gdmk] = GOVD_MAP;
14905 671 : break;
14906 380 : case OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE:
14907 380 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14908 380 : break;
14909 2094 : case OMP_CLAUSE_DEFAULTMAP_NONE:
14910 2094 : ctx->defaultmap[gdmk] = 0;
14911 2094 : break;
14912 45 : case OMP_CLAUSE_DEFAULTMAP_PRESENT:
14913 45 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
14914 45 : break;
14915 56 : case OMP_CLAUSE_DEFAULTMAP_DEFAULT:
14916 56 : switch (gdmk)
14917 : {
14918 11 : case GDMK_SCALAR:
14919 11 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14920 11 : break;
14921 11 : case GDMK_SCALAR_TARGET:
14922 11 : ctx->defaultmap[gdmk] = (lang_GNU_Fortran ()
14923 11 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
14924 11 : break;
14925 14 : case GDMK_AGGREGATE:
14926 14 : case GDMK_ALLOCATABLE:
14927 14 : ctx->defaultmap[gdmk] = GOVD_MAP;
14928 14 : break;
14929 20 : case GDMK_POINTER:
14930 20 : ctx->defaultmap[gdmk] = GOVD_MAP;
14931 20 : if (!lang_GNU_Fortran ())
14932 12 : ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY;
14933 : break;
14934 : default:
14935 : gcc_unreachable ();
14936 : }
14937 : break;
14938 0 : default:
14939 0 : gcc_unreachable ();
14940 : }
14941 : break;
14942 :
14943 824 : case OMP_CLAUSE_ALIGNED:
14944 824 : decl = OMP_CLAUSE_DECL (c);
14945 824 : if (error_operand_p (decl))
14946 : {
14947 : remove = true;
14948 : break;
14949 : }
14950 824 : if (gimplify_expr (&OMP_CLAUSE_ALIGNED_ALIGNMENT (c), pre_p, NULL,
14951 : is_gimple_val, fb_rvalue) == GS_ERROR)
14952 : {
14953 : remove = true;
14954 : break;
14955 : }
14956 824 : if (!is_global_var (decl)
14957 824 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
14958 592 : omp_add_variable (ctx, decl, GOVD_ALIGNED);
14959 : break;
14960 :
14961 489 : case OMP_CLAUSE_NONTEMPORAL:
14962 489 : decl = OMP_CLAUSE_DECL (c);
14963 489 : if (error_operand_p (decl))
14964 : {
14965 : remove = true;
14966 : break;
14967 : }
14968 489 : omp_add_variable (ctx, decl, GOVD_NONTEMPORAL);
14969 489 : break;
14970 :
14971 3541 : case OMP_CLAUSE_ALLOCATE:
14972 3541 : decl = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
14973 3541 : if (decl
14974 1700 : && TREE_CODE (decl) == INTEGER_CST
14975 3570 : && wi::eq_p (wi::to_widest (decl), GOMP_OMP_PREDEF_ALLOC_THREAD)
14976 3570 : && (code == OMP_TARGET || code == OMP_TASK || code == OMP_TASKLOOP))
14977 35 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
14978 : "allocator with access trait set to %<thread%> "
14979 : "results in undefined behavior for %qs directive",
14980 : code == OMP_TARGET ? "target"
14981 : : (code == OMP_TASK
14982 15 : ? "task" : "taskloop"));
14983 3541 : decl = OMP_CLAUSE_DECL (c);
14984 3541 : if (error_operand_p (decl))
14985 : {
14986 : remove = true;
14987 : break;
14988 : }
14989 3541 : if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL,
14990 : is_gimple_val, fb_rvalue) == GS_ERROR)
14991 : {
14992 : remove = true;
14993 : break;
14994 : }
14995 3541 : else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
14996 3541 : || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
14997 : == INTEGER_CST))
14998 : ;
14999 503 : else if (code == OMP_TASKLOOP
15000 503 : || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
15001 66 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
15002 132 : = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
15003 : pre_p, NULL, false);
15004 : break;
15005 :
15006 4365 : case OMP_CLAUSE_DEFAULT:
15007 4365 : ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
15008 4365 : break;
15009 :
15010 640 : case OMP_CLAUSE_INCLUSIVE:
15011 640 : case OMP_CLAUSE_EXCLUSIVE:
15012 640 : decl = OMP_CLAUSE_DECL (c);
15013 640 : {
15014 640 : splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
15015 : (splay_tree_key) decl);
15016 640 : if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
15017 : {
15018 5 : error_at (OMP_CLAUSE_LOCATION (c),
15019 : "%qD specified in %qs clause but not in %<inscan%> "
15020 : "%<reduction%> clause on the containing construct",
15021 5 : decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
15022 5 : remove = true;
15023 : }
15024 : else
15025 : {
15026 635 : n->value |= GOVD_REDUCTION_INSCAN;
15027 635 : if (outer_ctx->region_type == ORT_SIMD
15028 520 : && outer_ctx->outer_context
15029 107 : && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
15030 : {
15031 107 : n = splay_tree_lookup (outer_ctx->outer_context->variables,
15032 : (splay_tree_key) decl);
15033 107 : if (n && (n->value & GOVD_REDUCTION) != 0)
15034 107 : n->value |= GOVD_REDUCTION_INSCAN;
15035 : }
15036 : }
15037 : }
15038 : break;
15039 :
15040 103 : case OMP_CLAUSE_NOVARIANTS:
15041 103 : OMP_CLAUSE_NOVARIANTS_EXPR (c)
15042 103 : = gimple_boolify (OMP_CLAUSE_NOVARIANTS_EXPR (c));
15043 103 : break;
15044 115 : case OMP_CLAUSE_NOCONTEXT:
15045 115 : OMP_CLAUSE_NOCONTEXT_EXPR (c)
15046 115 : = gimple_boolify (OMP_CLAUSE_NOCONTEXT_EXPR (c));
15047 115 : break;
15048 0 : case OMP_CLAUSE_NOHOST:
15049 0 : default:
15050 0 : gcc_unreachable ();
15051 : }
15052 :
15053 1401 : if (code == OACC_DATA
15054 5123 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15055 208820 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15056 4504 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15057 : remove = true;
15058 205103 : if (remove)
15059 1105 : *list_p = OMP_CLAUSE_CHAIN (c);
15060 : else
15061 204305 : list_p = &OMP_CLAUSE_CHAIN (c);
15062 205410 : }
15063 :
15064 130565 : if (groups)
15065 : {
15066 36356 : delete grpmap;
15067 18178 : delete groups;
15068 : }
15069 :
15070 130565 : ctx->clauses = *orig_list_p;
15071 130565 : gimplify_omp_ctxp = ctx;
15072 130565 : }
15073 :
15074 : /* Return true if DECL is a candidate for shared to firstprivate
15075 : optimization. We only consider non-addressable scalars, not
15076 : too big, and not references. */
15077 :
15078 : static bool
15079 405487 : omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
15080 : {
15081 405487 : if (TREE_ADDRESSABLE (decl))
15082 : return false;
15083 356370 : tree type = TREE_TYPE (decl);
15084 356370 : if (!is_gimple_reg_type (type)
15085 331606 : || TREE_CODE (type) == REFERENCE_TYPE
15086 683711 : || TREE_ADDRESSABLE (type))
15087 : return false;
15088 : /* Don't optimize too large decls, as each thread/task will have
15089 : its own. */
15090 327341 : HOST_WIDE_INT len = int_size_in_bytes (type);
15091 327341 : if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
15092 : return false;
15093 327324 : if (omp_privatize_by_reference (decl))
15094 : return false;
15095 : return true;
15096 : }
15097 :
15098 : /* Helper function of omp_find_stores_op and gimplify_adjust_omp_clauses*.
15099 : For omp_shared_to_firstprivate_optimizable_decl_p decl mark it as
15100 : GOVD_WRITTEN in outer contexts. */
15101 :
15102 : static void
15103 304428 : omp_mark_stores (struct gimplify_omp_ctx *ctx, tree decl)
15104 : {
15105 466623 : for (; ctx; ctx = ctx->outer_context)
15106 : {
15107 449617 : splay_tree_node n = splay_tree_lookup (ctx->variables,
15108 : (splay_tree_key) decl);
15109 449617 : if (n == NULL)
15110 158616 : continue;
15111 291001 : else if (n->value & GOVD_SHARED)
15112 : {
15113 9121 : n->value |= GOVD_WRITTEN;
15114 9121 : return;
15115 : }
15116 281880 : else if (n->value & GOVD_DATA_SHARE_CLASS)
15117 : return;
15118 : }
15119 : }
15120 :
15121 : /* Helper callback for walk_gimple_seq to discover possible stores
15122 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15123 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15124 : for those. */
15125 :
15126 : static tree
15127 1128238 : omp_find_stores_op (tree *tp, int *walk_subtrees, void *data)
15128 : {
15129 1128238 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15130 :
15131 1128238 : *walk_subtrees = 0;
15132 1128238 : if (!wi->is_lhs)
15133 : return NULL_TREE;
15134 :
15135 322238 : tree op = *tp;
15136 401032 : do
15137 : {
15138 401032 : if (handled_component_p (op))
15139 78794 : op = TREE_OPERAND (op, 0);
15140 322238 : else if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
15141 322238 : && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
15142 0 : op = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
15143 : else
15144 : break;
15145 : }
15146 : while (1);
15147 322238 : if (!DECL_P (op) || !omp_shared_to_firstprivate_optimizable_decl_p (op))
15148 58119 : return NULL_TREE;
15149 :
15150 264119 : omp_mark_stores (gimplify_omp_ctxp, op);
15151 264119 : return NULL_TREE;
15152 : }
15153 :
15154 : /* Helper callback for walk_gimple_seq to discover possible stores
15155 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15156 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15157 : for those. */
15158 :
15159 : static tree
15160 627182 : omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
15161 : bool *handled_ops_p,
15162 : struct walk_stmt_info *wi)
15163 : {
15164 627182 : gimple *stmt = gsi_stmt (*gsi_p);
15165 627182 : switch (gimple_code (stmt))
15166 : {
15167 : /* Don't recurse on OpenMP constructs for which
15168 : gimplify_adjust_omp_clauses already handled the bodies,
15169 : except handle gimple_omp_for_pre_body. */
15170 26691 : case GIMPLE_OMP_FOR:
15171 26691 : *handled_ops_p = true;
15172 26691 : if (gimple_omp_for_pre_body (stmt))
15173 1780 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15174 : omp_find_stores_stmt, omp_find_stores_op, wi);
15175 : break;
15176 8562 : case GIMPLE_OMP_PARALLEL:
15177 8562 : case GIMPLE_OMP_TASK:
15178 8562 : case GIMPLE_OMP_SECTIONS:
15179 8562 : case GIMPLE_OMP_SINGLE:
15180 8562 : case GIMPLE_OMP_SCOPE:
15181 8562 : case GIMPLE_OMP_TARGET:
15182 8562 : case GIMPLE_OMP_TEAMS:
15183 8562 : case GIMPLE_OMP_CRITICAL:
15184 8562 : *handled_ops_p = true;
15185 8562 : break;
15186 : default:
15187 : break;
15188 : }
15189 627182 : return NULL_TREE;
15190 : }
15191 :
15192 : struct gimplify_adjust_omp_clauses_data
15193 : {
15194 : tree *list_p;
15195 : gimple_seq *pre_p;
15196 : };
15197 :
15198 : /* For all variables that were not actually used within the context,
15199 : remove PRIVATE, SHARED, and FIRSTPRIVATE clauses. */
15200 :
15201 : static int
15202 677178 : gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
15203 : {
15204 677178 : tree *list_p = ((struct gimplify_adjust_omp_clauses_data *) data)->list_p;
15205 677178 : gimple_seq *pre_p
15206 : = ((struct gimplify_adjust_omp_clauses_data *) data)->pre_p;
15207 677178 : tree decl = (tree) n->key;
15208 677178 : unsigned flags = n->value;
15209 677178 : enum omp_clause_code code;
15210 677178 : tree clause;
15211 677178 : bool private_debug;
15212 :
15213 677178 : if (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
15214 132809 : && (flags & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
15215 : flags = GOVD_SHARED | GOVD_SEEN | GOVD_WRITTEN;
15216 677053 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
15217 : return 0;
15218 178684 : if ((flags & GOVD_SEEN) == 0)
15219 : return 0;
15220 157593 : if (flags & GOVD_DEBUG_PRIVATE)
15221 : {
15222 260 : gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_SHARED);
15223 : private_debug = true;
15224 : }
15225 157333 : else if (flags & GOVD_MAP)
15226 : private_debug = false;
15227 : else
15228 139151 : private_debug
15229 139151 : = lang_hooks.decls.omp_private_debug_clause (decl,
15230 139151 : !!(flags & GOVD_SHARED));
15231 139151 : if (private_debug)
15232 : code = OMP_CLAUSE_PRIVATE;
15233 157211 : else if (flags & GOVD_MAP)
15234 : {
15235 18182 : code = OMP_CLAUSE_MAP;
15236 18182 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15237 18182 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15238 : {
15239 2 : error ("%<_Atomic%> %qD in implicit %<map%> clause", decl);
15240 2 : return 0;
15241 : }
15242 18180 : if (VAR_P (decl)
15243 16242 : && DECL_IN_CONSTANT_POOL (decl)
15244 18181 : && !lookup_attribute ("omp declare target",
15245 1 : DECL_ATTRIBUTES (decl)))
15246 : {
15247 1 : tree id = get_identifier ("omp declare target");
15248 1 : DECL_ATTRIBUTES (decl)
15249 1 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
15250 1 : varpool_node *node = varpool_node::get (decl);
15251 1 : if (node)
15252 : {
15253 1 : node->offloadable = 1;
15254 1 : if (ENABLE_OFFLOADING)
15255 : g->have_offload = true;
15256 : }
15257 : }
15258 : }
15259 139029 : else if (flags & GOVD_SHARED)
15260 : {
15261 49059 : if (is_global_var (decl))
15262 : {
15263 16138 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15264 25325 : while (ctx != NULL)
15265 : {
15266 17604 : splay_tree_node on
15267 17604 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15268 17604 : if (on && (on->value & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
15269 : | GOVD_PRIVATE | GOVD_REDUCTION
15270 : | GOVD_LINEAR | GOVD_MAP)) != 0)
15271 : break;
15272 9187 : ctx = ctx->outer_context;
15273 : }
15274 16138 : if (ctx == NULL)
15275 : return 0;
15276 : }
15277 41338 : code = OMP_CLAUSE_SHARED;
15278 : /* Don't optimize shared into firstprivate for read-only vars
15279 : on tasks with depend clause, we shouldn't try to copy them
15280 : until the dependencies are satisfied. */
15281 41338 : if (gimplify_omp_ctxp->has_depend)
15282 350 : flags |= GOVD_WRITTEN;
15283 : }
15284 89970 : else if (flags & GOVD_PRIVATE)
15285 : code = OMP_CLAUSE_PRIVATE;
15286 31499 : else if (flags & GOVD_FIRSTPRIVATE)
15287 : {
15288 22098 : code = OMP_CLAUSE_FIRSTPRIVATE;
15289 22098 : if ((gimplify_omp_ctxp->region_type & ORT_TARGET)
15290 14027 : && (gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15291 32444 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15292 : {
15293 1 : error ("%<_Atomic%> %qD in implicit %<firstprivate%> clause on "
15294 : "%<target%> construct", decl);
15295 1 : return 0;
15296 : }
15297 : }
15298 9401 : else if (flags & GOVD_LASTPRIVATE)
15299 : code = OMP_CLAUSE_LASTPRIVATE;
15300 241 : else if (flags & (GOVD_ALIGNED | GOVD_NONTEMPORAL))
15301 : return 0;
15302 118 : else if (flags & GOVD_CONDTEMP)
15303 : {
15304 118 : code = OMP_CLAUSE__CONDTEMP_;
15305 118 : gimple_add_tmp_var (decl);
15306 : }
15307 : else
15308 0 : gcc_unreachable ();
15309 :
15310 140586 : if (((flags & GOVD_LASTPRIVATE)
15311 139896 : || (code == OMP_CLAUSE_SHARED && (flags & GOVD_WRITTEN)))
15312 155805 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15313 15205 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15314 :
15315 149746 : tree chain = *list_p;
15316 149746 : clause = build_omp_clause (input_location, code);
15317 149746 : OMP_CLAUSE_DECL (clause) = decl;
15318 149746 : OMP_CLAUSE_CHAIN (clause) = chain;
15319 149746 : if (private_debug)
15320 382 : OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
15321 149364 : else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
15322 6 : OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
15323 149358 : else if (code == OMP_CLAUSE_SHARED
15324 41338 : && (flags & GOVD_WRITTEN) == 0
15325 184637 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15326 21046 : OMP_CLAUSE_SHARED_READONLY (clause) = 1;
15327 128312 : else if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_EXPLICIT) == 0)
15328 22097 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clause) = 1;
15329 106215 : else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
15330 : {
15331 626 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
15332 626 : OMP_CLAUSE_DECL (nc) = decl;
15333 626 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
15334 626 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
15335 15 : OMP_CLAUSE_DECL (clause)
15336 30 : = build_fold_indirect_ref_loc (input_location, decl);
15337 626 : OMP_CLAUSE_DECL (clause)
15338 626 : = build2 (MEM_REF, char_type_node, OMP_CLAUSE_DECL (clause),
15339 : build_int_cst (build_pointer_type (char_type_node), 0));
15340 626 : OMP_CLAUSE_SIZE (clause) = size_zero_node;
15341 626 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15342 626 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
15343 626 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
15344 626 : tree dtype = TREE_TYPE (decl);
15345 626 : if (TREE_CODE (dtype) == REFERENCE_TYPE)
15346 15 : dtype = TREE_TYPE (dtype);
15347 : /* FIRSTPRIVATE_POINTER doesn't work well if we have a
15348 : multiply-indirected pointer. If we have a reference to a pointer to
15349 : a pointer, it's possible that this should really be
15350 : GOMP_MAP_FIRSTPRIVATE_REFERENCE -- but that also doesn't work at the
15351 : moment, so stick with this. (See PR113279 and testcases
15352 : baseptrs-{4,6}.C:ref2ptrptr_offset_decl_member_slice). */
15353 626 : if (TREE_CODE (dtype) == POINTER_TYPE
15354 626 : && TREE_CODE (TREE_TYPE (dtype)) == POINTER_TYPE)
15355 19 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15356 : else
15357 607 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15358 626 : OMP_CLAUSE_CHAIN (nc) = chain;
15359 626 : OMP_CLAUSE_CHAIN (clause) = nc;
15360 626 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15361 626 : gimplify_omp_ctxp = ctx->outer_context;
15362 626 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0),
15363 : pre_p, NULL, is_gimple_val, fb_rvalue);
15364 626 : gimplify_omp_ctxp = ctx;
15365 626 : }
15366 17554 : else if (code == OMP_CLAUSE_MAP)
15367 : {
15368 17554 : int kind;
15369 : /* Not all combinations of these GOVD_MAP flags are actually valid. */
15370 17554 : switch (flags & (GOVD_MAP_TO_ONLY
15371 : | GOVD_MAP_FORCE
15372 : | GOVD_MAP_FORCE_PRESENT
15373 : | GOVD_MAP_ALLOC_ONLY
15374 : | GOVD_MAP_FROM_ONLY))
15375 : {
15376 : case 0:
15377 : kind = GOMP_MAP_TOFROM;
15378 : break;
15379 1042 : case GOVD_MAP_FORCE:
15380 1042 : kind = GOMP_MAP_TOFROM | GOMP_MAP_FLAG_FORCE;
15381 1042 : break;
15382 1015 : case GOVD_MAP_TO_ONLY:
15383 1015 : kind = GOMP_MAP_TO;
15384 1015 : break;
15385 16 : case GOVD_MAP_FROM_ONLY:
15386 16 : kind = GOMP_MAP_FROM;
15387 16 : break;
15388 37 : case GOVD_MAP_ALLOC_ONLY:
15389 37 : kind = GOMP_MAP_ALLOC;
15390 37 : break;
15391 3 : case GOVD_MAP_TO_ONLY | GOVD_MAP_FORCE:
15392 3 : kind = GOMP_MAP_TO | GOMP_MAP_FLAG_FORCE;
15393 3 : break;
15394 : case GOVD_MAP_FORCE_PRESENT:
15395 326 : kind = GOMP_MAP_FORCE_PRESENT;
15396 : break;
15397 : case GOVD_MAP_FORCE_PRESENT | GOVD_MAP_ALLOC_ONLY:
15398 326 : kind = GOMP_MAP_FORCE_PRESENT;
15399 : break;
15400 0 : default:
15401 0 : gcc_unreachable ();
15402 : }
15403 17554 : OMP_CLAUSE_SET_MAP_KIND (clause, kind);
15404 : /* Setting of the implicit flag for the runtime is currently disabled for
15405 : OpenACC. */
15406 17554 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
15407 10020 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1;
15408 17554 : if (DECL_SIZE (decl)
15409 17554 : && !poly_int_tree_p (DECL_SIZE (decl)))
15410 : {
15411 535 : tree decl2 = DECL_VALUE_EXPR (decl);
15412 535 : gcc_assert (INDIRECT_REF_P (decl2));
15413 535 : decl2 = TREE_OPERAND (decl2, 0);
15414 535 : gcc_assert (DECL_P (decl2));
15415 535 : tree mem = build_simple_mem_ref (decl2);
15416 535 : OMP_CLAUSE_DECL (clause) = mem;
15417 535 : OMP_CLAUSE_SIZE (clause) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
15418 535 : if (gimplify_omp_ctxp->outer_context)
15419 : {
15420 446 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15421 446 : omp_notice_variable (ctx, decl2, true);
15422 446 : omp_notice_variable (ctx, OMP_CLAUSE_SIZE (clause), true);
15423 : }
15424 535 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15425 : OMP_CLAUSE_MAP);
15426 535 : OMP_CLAUSE_DECL (nc) = decl;
15427 535 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15428 535 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases)
15429 535 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15430 : else
15431 0 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15432 535 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15433 535 : OMP_CLAUSE_CHAIN (clause) = nc;
15434 : }
15435 17019 : else if (gimplify_omp_ctxp->target_firstprivatize_array_bases
15436 17019 : && omp_privatize_by_reference (decl))
15437 : {
15438 28 : OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl);
15439 28 : OMP_CLAUSE_SIZE (clause)
15440 28 : = unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))));
15441 28 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15442 28 : gimplify_omp_ctxp = ctx->outer_context;
15443 28 : gimplify_expr (&OMP_CLAUSE_SIZE (clause),
15444 : pre_p, NULL, is_gimple_val, fb_rvalue);
15445 28 : gimplify_omp_ctxp = ctx;
15446 28 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15447 : OMP_CLAUSE_MAP);
15448 28 : OMP_CLAUSE_DECL (nc) = decl;
15449 28 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15450 28 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
15451 28 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15452 28 : OMP_CLAUSE_CHAIN (clause) = nc;
15453 : }
15454 : else
15455 16991 : OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
15456 : }
15457 149746 : if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
15458 : {
15459 690 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
15460 690 : OMP_CLAUSE_DECL (nc) = decl;
15461 690 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
15462 690 : OMP_CLAUSE_CHAIN (nc) = chain;
15463 690 : OMP_CLAUSE_CHAIN (clause) = nc;
15464 690 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15465 690 : gimplify_omp_ctxp = ctx->outer_context;
15466 690 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
15467 690 : (ctx->region_type & ORT_ACC) != 0);
15468 690 : gimplify_omp_ctxp = ctx;
15469 : }
15470 149746 : *list_p = clause;
15471 149746 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15472 149746 : gimplify_omp_ctxp = ctx->outer_context;
15473 : /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
15474 : in simd. Those are only added for the local vars inside of simd body
15475 : and they don't need to be e.g. default constructible. */
15476 149746 : if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
15477 141696 : lang_hooks.decls.omp_finish_clause (clause, pre_p,
15478 141696 : (ctx->region_type & ORT_ACC) != 0);
15479 149746 : if (gimplify_omp_ctxp)
15480 184145 : for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
15481 93485 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
15482 93485 : && DECL_P (OMP_CLAUSE_SIZE (clause)))
15483 1241 : omp_notice_variable (gimplify_omp_ctxp, OMP_CLAUSE_SIZE (clause),
15484 : true);
15485 149746 : gimplify_omp_ctxp = ctx;
15486 149746 : return 0;
15487 : }
15488 :
15489 : static void
15490 129101 : gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
15491 : enum tree_code code,
15492 : gimple_seq *loops_seq_p = NULL)
15493 : {
15494 129101 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15495 129101 : tree *orig_list_p = list_p;
15496 129101 : tree c, decl;
15497 129101 : bool has_inscan_reductions = false;
15498 :
15499 129101 : if (body)
15500 : {
15501 : struct gimplify_omp_ctx *octx;
15502 224958 : for (octx = ctx; octx; octx = octx->outer_context)
15503 173645 : if ((octx->region_type & (ORT_PARALLEL | ORT_TASK | ORT_TEAMS)) != 0)
15504 : break;
15505 111523 : if (octx)
15506 : {
15507 60210 : struct walk_stmt_info wi;
15508 60210 : memset (&wi, 0, sizeof (wi));
15509 60210 : walk_gimple_seq (body, omp_find_stores_stmt,
15510 : omp_find_stores_op, &wi);
15511 : }
15512 : }
15513 :
15514 129101 : if (ctx->add_safelen1)
15515 : {
15516 : /* If there are VLAs in the body of simd loop, prevent
15517 : vectorization. */
15518 2 : gcc_assert (ctx->region_type == ORT_SIMD);
15519 2 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
15520 2 : OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node;
15521 2 : OMP_CLAUSE_CHAIN (c) = *list_p;
15522 2 : *list_p = c;
15523 2 : list_p = &OMP_CLAUSE_CHAIN (c);
15524 : }
15525 :
15526 129101 : if (ctx->region_type == ORT_WORKSHARE
15527 39685 : && ctx->outer_context
15528 27891 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
15529 : {
15530 24921 : for (c = ctx->outer_context->clauses; c; c = OMP_CLAUSE_CHAIN (c))
15531 12570 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15532 12570 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
15533 : {
15534 125 : decl = OMP_CLAUSE_DECL (c);
15535 125 : splay_tree_node n
15536 125 : = splay_tree_lookup (ctx->outer_context->variables,
15537 : (splay_tree_key) decl);
15538 125 : gcc_checking_assert (!splay_tree_lookup (ctx->variables,
15539 : (splay_tree_key) decl));
15540 125 : omp_add_variable (ctx, decl, n->value);
15541 125 : tree c2 = copy_node (c);
15542 125 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15543 125 : *list_p = c2;
15544 125 : if ((n->value & GOVD_FIRSTPRIVATE) == 0)
15545 103 : continue;
15546 22 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
15547 : OMP_CLAUSE_FIRSTPRIVATE);
15548 22 : OMP_CLAUSE_DECL (c2) = decl;
15549 22 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15550 22 : *list_p = c2;
15551 : }
15552 : }
15553 :
15554 129101 : if (code == OMP_TARGET
15555 129101 : || code == OMP_TARGET_DATA
15556 129101 : || code == OMP_TARGET_ENTER_DATA
15557 112791 : || code == OMP_TARGET_EXIT_DATA)
15558 : {
15559 17096 : tree mapper_clauses = NULL_TREE;
15560 17096 : instantiate_mapper_info im_info;
15561 :
15562 17096 : im_info.mapper_clauses_p = &mapper_clauses;
15563 17096 : im_info.omp_ctx = ctx;
15564 17096 : im_info.pre_p = pre_p;
15565 :
15566 17096 : splay_tree_foreach (ctx->variables,
15567 : omp_instantiate_implicit_mappers,
15568 : (void *) &im_info);
15569 :
15570 17096 : if (mapper_clauses)
15571 : {
15572 53 : mapper_clauses
15573 53 : = lang_hooks.decls.omp_finish_mapper_clauses (mapper_clauses);
15574 :
15575 : /* Stick the implicitly-expanded mapper clauses at the end of the
15576 : clause list. */
15577 53 : tree *tail = list_p;
15578 163 : while (*tail)
15579 110 : tail = &OMP_CLAUSE_CHAIN (*tail);
15580 53 : *tail = mapper_clauses;
15581 : }
15582 :
15583 17096 : vec<omp_mapping_group> *groups;
15584 17096 : groups = omp_gather_mapping_groups (list_p);
15585 17096 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
15586 :
15587 17096 : if (groups)
15588 : {
15589 8515 : grpmap = omp_index_mapping_groups (groups);
15590 :
15591 8515 : omp_resolve_clause_dependencies (code, groups, grpmap);
15592 8515 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15593 : &grpmap, list_p);
15594 :
15595 8515 : omp_mapping_group *outlist = NULL;
15596 :
15597 17030 : delete grpmap;
15598 8515 : delete groups;
15599 :
15600 : /* Rebuild now we have struct sibling lists. */
15601 8515 : groups = omp_gather_mapping_groups (list_p);
15602 8515 : grpmap = omp_index_mapping_groups (groups);
15603 :
15604 8515 : bool enter_exit = (code == OMP_TARGET_ENTER_DATA
15605 8515 : || code == OMP_TARGET_EXIT_DATA);
15606 :
15607 8515 : outlist = omp_tsort_mapping_groups (groups, grpmap, enter_exit);
15608 8515 : outlist = omp_segregate_mapping_groups (outlist);
15609 8515 : list_p = omp_reorder_mapping_groups (groups, outlist, list_p);
15610 :
15611 8515 : delete grpmap;
15612 8515 : delete groups;
15613 : }
15614 17096 : }
15615 112005 : else if (ctx->region_type & ORT_ACC)
15616 : {
15617 29847 : vec<omp_mapping_group> *groups;
15618 29847 : groups = omp_gather_mapping_groups (list_p);
15619 29847 : if (groups)
15620 : {
15621 9462 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap;
15622 9462 : grpmap = omp_index_mapping_groups (groups);
15623 :
15624 9462 : oacc_resolve_clause_dependencies (groups, grpmap);
15625 9462 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15626 : &grpmap, list_p);
15627 :
15628 9462 : delete groups;
15629 18924 : delete grpmap;
15630 : }
15631 : }
15632 :
15633 129101 : tree attach_list = NULL_TREE;
15634 129101 : tree *attach_tail = &attach_list;
15635 :
15636 129101 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
15637 :
15638 377941 : while ((c = *list_p) != NULL)
15639 : {
15640 248840 : splay_tree_node n;
15641 248840 : bool remove = false;
15642 248840 : bool move_attach = false;
15643 :
15644 291425 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
15645 : grp_end = NULL_TREE;
15646 :
15647 248840 : switch (OMP_CLAUSE_CODE (c))
15648 : {
15649 8039 : case OMP_CLAUSE_FIRSTPRIVATE:
15650 8039 : if ((ctx->region_type & ORT_TARGET)
15651 1968 : && (ctx->region_type & ORT_ACC) == 0
15652 9401 : && TYPE_ATOMIC (strip_array_types
15653 : (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
15654 : {
15655 4 : error_at (OMP_CLAUSE_LOCATION (c),
15656 : "%<_Atomic%> %qD in %<firstprivate%> clause on "
15657 2 : "%<target%> construct", OMP_CLAUSE_DECL (c));
15658 2 : remove = true;
15659 2 : break;
15660 : }
15661 8037 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
15662 : {
15663 380 : decl = OMP_CLAUSE_DECL (c);
15664 380 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15665 380 : if ((n->value & GOVD_MAP) != 0)
15666 : {
15667 : remove = true;
15668 : break;
15669 : }
15670 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0;
15671 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0;
15672 : }
15673 : /* FALLTHRU */
15674 36839 : case OMP_CLAUSE_PRIVATE:
15675 36839 : case OMP_CLAUSE_SHARED:
15676 36839 : case OMP_CLAUSE_LINEAR:
15677 36839 : decl = OMP_CLAUSE_DECL (c);
15678 36839 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15679 36839 : remove = !(n->value & GOVD_SEEN);
15680 36839 : if ((n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0
15681 48 : && code == OMP_PARALLEL
15682 36861 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15683 : remove = true;
15684 36817 : if (! remove)
15685 : {
15686 32215 : bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
15687 32215 : if ((n->value & GOVD_DEBUG_PRIVATE)
15688 32215 : || lang_hooks.decls.omp_private_debug_clause (decl, shared))
15689 : {
15690 87 : gcc_assert ((n->value & GOVD_DEBUG_PRIVATE) == 0
15691 : || ((n->value & GOVD_DATA_SHARE_CLASS)
15692 : == GOVD_SHARED));
15693 87 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
15694 87 : OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
15695 : }
15696 32215 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15697 4159 : && ctx->has_depend
15698 32773 : && DECL_P (decl))
15699 558 : n->value |= GOVD_WRITTEN;
15700 32215 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15701 4159 : && (n->value & GOVD_WRITTEN) == 0
15702 3042 : && DECL_P (decl)
15703 35257 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15704 526 : OMP_CLAUSE_SHARED_READONLY (c) = 1;
15705 31689 : else if (DECL_P (decl)
15706 31689 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15707 3633 : && (n->value & GOVD_WRITTEN) != 0)
15708 30572 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15709 9032 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
15710 38727 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15711 5734 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15712 : }
15713 : else
15714 4624 : n->value &= ~GOVD_EXPLICIT;
15715 : break;
15716 :
15717 13004 : case OMP_CLAUSE_LASTPRIVATE:
15718 : /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
15719 : accurately reflect the presence of a FIRSTPRIVATE clause. */
15720 13004 : decl = OMP_CLAUSE_DECL (c);
15721 13004 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15722 13004 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
15723 13004 : = (n->value & GOVD_FIRSTPRIVATE) != 0;
15724 13004 : if (code == OMP_DISTRIBUTE
15725 13004 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
15726 : {
15727 4 : remove = true;
15728 4 : error_at (OMP_CLAUSE_LOCATION (c),
15729 : "same variable used in %<firstprivate%> and "
15730 : "%<lastprivate%> clauses on %<distribute%> "
15731 : "construct");
15732 : }
15733 13004 : if (!remove
15734 13000 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15735 13000 : && DECL_P (decl)
15736 13000 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15737 11407 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15738 13004 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && code == OMP_PARALLEL)
15739 : remove = true;
15740 : break;
15741 :
15742 824 : case OMP_CLAUSE_ALIGNED:
15743 824 : decl = OMP_CLAUSE_DECL (c);
15744 824 : if (!is_global_var (decl))
15745 : {
15746 738 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15747 738 : remove = n == NULL || !(n->value & GOVD_SEEN);
15748 88 : if (!remove && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
15749 : {
15750 88 : struct gimplify_omp_ctx *octx;
15751 88 : if (n != NULL
15752 88 : && (n->value & (GOVD_DATA_SHARE_CLASS
15753 : & ~GOVD_FIRSTPRIVATE)))
15754 : remove = true;
15755 : else
15756 100 : for (octx = ctx->outer_context; octx;
15757 12 : octx = octx->outer_context)
15758 : {
15759 24 : n = splay_tree_lookup (octx->variables,
15760 : (splay_tree_key) decl);
15761 24 : if (n == NULL)
15762 12 : continue;
15763 12 : if (n->value & GOVD_LOCAL)
15764 : break;
15765 : /* We have to avoid assigning a shared variable
15766 : to itself when trying to add
15767 : __builtin_assume_aligned. */
15768 12 : if (n->value & GOVD_SHARED)
15769 : {
15770 : remove = true;
15771 : break;
15772 : }
15773 : }
15774 : }
15775 : }
15776 86 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
15777 : {
15778 86 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15779 86 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
15780 : remove = true;
15781 : }
15782 : break;
15783 :
15784 552 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
15785 552 : decl = OMP_CLAUSE_DECL (c);
15786 552 : while (INDIRECT_REF_P (decl)
15787 601 : || TREE_CODE (decl) == ARRAY_REF)
15788 49 : decl = TREE_OPERAND (decl, 0);
15789 552 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15790 552 : remove = n == NULL || !(n->value & GOVD_SEEN);
15791 : break;
15792 :
15793 900 : case OMP_CLAUSE_IS_DEVICE_PTR:
15794 900 : case OMP_CLAUSE_NONTEMPORAL:
15795 900 : decl = OMP_CLAUSE_DECL (c);
15796 900 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15797 900 : remove = n == NULL || !(n->value & GOVD_SEEN);
15798 : break;
15799 :
15800 56661 : case OMP_CLAUSE_MAP:
15801 56661 : if (OMP_CLAUSE_MAP_GIMPLE_ONLY (c))
15802 : {
15803 90 : remove = true;
15804 90 : goto end_adjust_omp_map_clause;
15805 : }
15806 56571 : decl = OMP_CLAUSE_DECL (c);
15807 56571 : if (!grp_end)
15808 : {
15809 31684 : grp_start_p = list_p;
15810 31684 : grp_end = *omp_group_last (grp_start_p);
15811 : }
15812 56571 : switch (OMP_CLAUSE_MAP_KIND (c))
15813 : {
15814 181 : case GOMP_MAP_PRESENT_ALLOC:
15815 181 : case GOMP_MAP_PRESENT_TO:
15816 181 : case GOMP_MAP_PRESENT_FROM:
15817 181 : case GOMP_MAP_PRESENT_TOFROM:
15818 181 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_PRESENT);
15819 181 : break;
15820 : default:
15821 : break;
15822 : }
15823 56571 : switch (code)
15824 : {
15825 4563 : case OACC_DATA:
15826 4563 : if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
15827 : break;
15828 : /* Fallthrough. */
15829 19219 : case OACC_HOST_DATA:
15830 19219 : case OACC_ENTER_DATA:
15831 19219 : case OACC_EXIT_DATA:
15832 19219 : case OMP_TARGET_DATA:
15833 19219 : case OMP_TARGET_ENTER_DATA:
15834 19219 : case OMP_TARGET_EXIT_DATA:
15835 19219 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15836 19219 : || (OMP_CLAUSE_MAP_KIND (c)
15837 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15838 : /* For target {,enter ,exit }data only the array slice is
15839 : mapped, but not the pointer to it. */
15840 : remove = true;
15841 19219 : if (code == OMP_TARGET_EXIT_DATA
15842 19219 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
15843 2794 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER))
15844 : remove = true;
15845 : break;
15846 : case OMP_TARGET:
15847 : break;
15848 : default:
15849 : break;
15850 : }
15851 19217 : if (remove)
15852 : break;
15853 56236 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
15854 : {
15855 : /* Sanity check: attach/detach map kinds use the size as a bias,
15856 : and it's never right to use the decl size for such
15857 : mappings. */
15858 17706 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
15859 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
15860 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DETACH
15861 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
15862 : && (OMP_CLAUSE_MAP_KIND (c)
15863 : != GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
15864 21762 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
15865 4056 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
15866 : }
15867 56236 : gimplify_omp_ctxp = ctx->outer_context;
15868 56236 : gimple_seq *seq_p;
15869 56236 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
15870 56236 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
15871 : is_gimple_val, fb_rvalue) == GS_ERROR)
15872 : {
15873 0 : gimplify_omp_ctxp = ctx;
15874 0 : remove = true;
15875 0 : goto end_adjust_omp_map_clause;
15876 : }
15877 56236 : else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15878 53341 : || (OMP_CLAUSE_MAP_KIND (c)
15879 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15880 52928 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15881 62848 : && TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
15882 : {
15883 912 : OMP_CLAUSE_SIZE (c)
15884 912 : = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), seq_p, NULL,
15885 : false);
15886 912 : if ((ctx->region_type & ORT_TARGET) != 0)
15887 703 : omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
15888 : GOVD_FIRSTPRIVATE | GOVD_SEEN);
15889 : }
15890 56236 : gimplify_omp_ctxp = ctx;
15891 : /* Data clauses associated with reductions must be
15892 : compatible with present_or_copy. Warn and adjust the clause
15893 : if that is not the case. */
15894 56236 : if (ctx->region_type == ORT_ACC_PARALLEL
15895 47257 : || ctx->region_type == ORT_ACC_SERIAL)
15896 : {
15897 9535 : tree t = DECL_P (decl) ? decl : TREE_OPERAND (decl, 0);
15898 9535 : n = NULL;
15899 :
15900 9535 : if (DECL_P (t))
15901 7770 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
15902 :
15903 7770 : if (n && (n->value & GOVD_REDUCTION))
15904 : {
15905 809 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
15906 :
15907 809 : OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1;
15908 809 : if ((kind & GOMP_MAP_TOFROM) != GOMP_MAP_TOFROM
15909 159 : && kind != GOMP_MAP_FORCE_PRESENT
15910 159 : && kind != GOMP_MAP_POINTER)
15911 : {
15912 120 : warning_at (OMP_CLAUSE_LOCATION (c), 0,
15913 : "incompatible data clause with reduction "
15914 : "on %qE; promoting to %<present_or_copy%>",
15915 120 : DECL_NAME (t));
15916 120 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
15917 : }
15918 : }
15919 : }
15920 56236 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
15921 53452 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
15922 56510 : && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
15923 : {
15924 534 : remove = true;
15925 534 : goto end_adjust_omp_map_clause;
15926 : }
15927 : /* If we have a DECL_VALUE_EXPR (e.g. this is a class member and/or
15928 : a variable captured in a lambda closure), look through that now
15929 : before the DECL_P check below. (A code other than COMPONENT_REF,
15930 : i.e. INDIRECT_REF, will be a VLA/variable-length array
15931 : section. A global var may be a variable in a common block. We
15932 : don't want to do this here for either of those.) */
15933 55702 : if ((ctx->region_type & ORT_ACC) == 0
15934 29495 : && DECL_P (decl)
15935 12608 : && !is_global_var (decl)
15936 11216 : && DECL_HAS_VALUE_EXPR_P (decl)
15937 55892 : && TREE_CODE (DECL_VALUE_EXPR (decl)) == COMPONENT_REF)
15938 0 : decl = OMP_CLAUSE_DECL (c) = DECL_VALUE_EXPR (decl);
15939 55702 : if (TREE_CODE (decl) == TARGET_EXPR)
15940 : {
15941 0 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
15942 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
15943 26167 : remove = true;
15944 : }
15945 55702 : else if (!DECL_P (decl))
15946 : {
15947 29535 : if ((ctx->region_type & ORT_TARGET) != 0
15948 29535 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15949 : {
15950 24 : if (INDIRECT_REF_P (decl)
15951 0 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
15952 24 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
15953 : == REFERENCE_TYPE))
15954 0 : decl = TREE_OPERAND (decl, 0);
15955 24 : if (TREE_CODE (decl) == COMPONENT_REF)
15956 : {
15957 0 : while (TREE_CODE (decl) == COMPONENT_REF)
15958 0 : decl = TREE_OPERAND (decl, 0);
15959 0 : if (DECL_P (decl))
15960 : {
15961 0 : n = splay_tree_lookup (ctx->variables,
15962 : (splay_tree_key) decl);
15963 0 : if (!(n->value & GOVD_SEEN))
15964 29535 : remove = true;
15965 : }
15966 : }
15967 : }
15968 :
15969 29535 : tree d = decl, *pd;
15970 29535 : if (TREE_CODE (d) == ARRAY_REF)
15971 : {
15972 5726 : while (TREE_CODE (d) == ARRAY_REF)
15973 2923 : d = TREE_OPERAND (d, 0);
15974 2803 : if (TREE_CODE (d) == COMPONENT_REF
15975 2803 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
15976 : decl = d;
15977 : }
15978 29535 : pd = &OMP_CLAUSE_DECL (c);
15979 29535 : if (d == decl
15980 27089 : && TREE_CODE (decl) == INDIRECT_REF
15981 15450 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
15982 1470 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
15983 : == REFERENCE_TYPE)
15984 30335 : && (OMP_CLAUSE_MAP_KIND (c)
15985 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
15986 : {
15987 796 : pd = &TREE_OPERAND (decl, 0);
15988 796 : decl = TREE_OPERAND (decl, 0);
15989 : }
15990 :
15991 29535 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15992 3066 : switch (code)
15993 : {
15994 427 : case OACC_ENTER_DATA:
15995 427 : case OACC_EXIT_DATA:
15996 427 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
15997 : == ARRAY_TYPE)
15998 : remove = true;
15999 417 : else if (code == OACC_ENTER_DATA)
16000 263 : goto change_to_attach;
16001 : /* Fallthrough. */
16002 605 : case OMP_TARGET_EXIT_DATA:
16003 605 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DETACH);
16004 605 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
16005 605 : break;
16006 71 : case OACC_UPDATE:
16007 : /* An "attach/detach" operation on an update directive
16008 : should behave as a GOMP_MAP_ALWAYS_POINTER. Note that
16009 : both GOMP_MAP_ATTACH_DETACH and GOMP_MAP_ALWAYS_POINTER
16010 : kinds depend on the previous mapping (for non-TARGET
16011 : regions). */
16012 71 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
16013 71 : break;
16014 2390 : default:
16015 2390 : change_to_attach:
16016 2390 : gcc_assert (!OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c));
16017 2390 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH);
16018 2390 : if ((ctx->region_type & ORT_TARGET) != 0)
16019 1803 : move_attach = true;
16020 : }
16021 26469 : else if ((ctx->region_type & ORT_TARGET) != 0
16022 26469 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16023 11798 : || (OMP_CLAUSE_MAP_KIND (c)
16024 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16025 : move_attach = true;
16026 :
16027 : /* If we have e.g. map(struct: *var), don't gimplify the
16028 : argument since omp-low.cc wants to see the decl itself. */
16029 29535 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
16030 1136 : goto end_adjust_omp_map_clause;
16031 :
16032 : /* We've already partly gimplified this in
16033 : gimplify_scan_omp_clauses. Don't do any more. */
16034 28399 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
16035 88 : goto end_adjust_omp_map_clause;
16036 :
16037 28311 : gimplify_omp_ctxp = ctx->outer_context;
16038 28311 : if (gimplify_expr (pd, seq_p, NULL, is_gimple_lvalue,
16039 : fb_lvalue) == GS_ERROR)
16040 0 : remove = true;
16041 28311 : gimplify_omp_ctxp = ctx;
16042 28311 : goto end_adjust_omp_map_clause;
16043 : }
16044 :
16045 26167 : if ((code == OMP_TARGET
16046 : || code == OMP_TARGET_DATA
16047 : || code == OMP_TARGET_ENTER_DATA
16048 14448 : || code == OMP_TARGET_EXIT_DATA)
16049 26794 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16050 : {
16051 238 : bool firstprivatize = false;
16052 :
16053 243 : for (struct gimplify_omp_ctx *octx = ctx->outer_context; octx;
16054 5 : octx = octx->outer_context)
16055 : {
16056 6 : splay_tree_node n
16057 12 : = splay_tree_lookup (octx->variables,
16058 6 : (splay_tree_key) OMP_CLAUSE_DECL (c));
16059 : /* If this is contained in an outer OpenMP region as a
16060 : firstprivate value, remove the attach/detach. */
16061 6 : if (n && (n->value & GOVD_FIRSTPRIVATE))
16062 : {
16063 : firstprivatize = true;
16064 : break;
16065 : }
16066 : }
16067 :
16068 238 : enum gomp_map_kind map_kind;
16069 238 : if (firstprivatize)
16070 : map_kind = GOMP_MAP_FIRSTPRIVATE_POINTER;
16071 237 : else if (code == OMP_TARGET_EXIT_DATA)
16072 : map_kind = GOMP_MAP_DETACH;
16073 : else
16074 186 : map_kind = GOMP_MAP_ATTACH;
16075 238 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16076 : }
16077 25929 : else if ((ctx->region_type & ORT_ACC) != 0
16078 25929 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16079 : {
16080 0 : enum gomp_map_kind map_kind = (code == OACC_EXIT_DATA
16081 0 : ? GOMP_MAP_DETACH
16082 : : GOMP_MAP_ATTACH);
16083 0 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16084 : }
16085 :
16086 26167 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16087 26167 : if ((ctx->region_type & ORT_TARGET) != 0
16088 16254 : && !(n->value & GOVD_SEEN)
16089 1487 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) == 0
16090 27407 : && (!is_global_var (decl)
16091 75 : || !lookup_attribute ("omp declare target link",
16092 75 : DECL_ATTRIBUTES (decl))))
16093 : {
16094 1228 : remove = true;
16095 : /* For struct element mapping, if struct is never referenced
16096 : in target block and none of the mapping has always modifier,
16097 : remove all the struct element mappings, which immediately
16098 : follow the GOMP_MAP_STRUCT map clause. */
16099 1228 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
16100 1228 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
16101 : {
16102 30 : HOST_WIDE_INT cnt = tree_to_shwi (OMP_CLAUSE_SIZE (c));
16103 80 : while (cnt--)
16104 50 : OMP_CLAUSE_CHAIN (c)
16105 50 : = OMP_CLAUSE_CHAIN (OMP_CLAUSE_CHAIN (c));
16106 : }
16107 : }
16108 24939 : else if (DECL_SIZE (decl)
16109 24915 : && !poly_int_tree_p (DECL_SIZE (decl))
16110 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER
16111 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
16112 24990 : && (OMP_CLAUSE_MAP_KIND (c)
16113 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
16114 : {
16115 : /* For GOMP_MAP_FORCE_DEVICEPTR, we'll never enter here, because
16116 : for these, TREE_CODE (DECL_SIZE (decl)) will always be
16117 : INTEGER_CST. */
16118 51 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
16119 :
16120 51 : tree decl2 = DECL_VALUE_EXPR (decl);
16121 51 : gcc_assert (INDIRECT_REF_P (decl2));
16122 51 : decl2 = TREE_OPERAND (decl2, 0);
16123 51 : gcc_assert (DECL_P (decl2));
16124 51 : tree mem = build_simple_mem_ref (decl2);
16125 51 : OMP_CLAUSE_DECL (c) = mem;
16126 51 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16127 51 : if (ctx->outer_context)
16128 : {
16129 15 : omp_notice_variable (ctx->outer_context, decl2, true);
16130 30 : omp_notice_variable (ctx->outer_context,
16131 15 : OMP_CLAUSE_SIZE (c), true);
16132 : }
16133 51 : if (((ctx->region_type & ORT_TARGET) != 0
16134 24 : || !ctx->target_firstprivatize_array_bases)
16135 34 : && ((n->value & GOVD_SEEN) == 0
16136 30 : || (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0))
16137 : {
16138 34 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16139 : OMP_CLAUSE_MAP);
16140 34 : OMP_CLAUSE_DECL (nc) = decl;
16141 34 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
16142 34 : if (ctx->target_firstprivatize_array_bases)
16143 27 : OMP_CLAUSE_SET_MAP_KIND (nc,
16144 : GOMP_MAP_FIRSTPRIVATE_POINTER);
16145 : else
16146 7 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
16147 34 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
16148 34 : OMP_CLAUSE_CHAIN (c) = nc;
16149 34 : c = nc;
16150 : }
16151 : }
16152 : else
16153 : {
16154 24888 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16155 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16156 24888 : gcc_assert ((n->value & GOVD_SEEN) == 0
16157 : || ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16158 : == 0));
16159 : }
16160 :
16161 : /* If we have a target region, we can push all the attaches to the
16162 : end of the list (we may have standalone "attach" operations
16163 : synthesized for GOMP_MAP_STRUCT nodes that must be processed after
16164 : the attachment point AND the pointed-to block have been mapped).
16165 : If we have something else, e.g. "enter data", we need to keep
16166 : "attach" nodes together with the previous node they attach to so
16167 : that separate "exit data" operations work properly (see
16168 : libgomp/target.c). */
16169 26167 : if ((ctx->region_type & ORT_TARGET) != 0
16170 26167 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16171 16138 : || (OMP_CLAUSE_MAP_KIND (c)
16172 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16173 : move_attach = true;
16174 :
16175 56326 : end_adjust_omp_map_clause:
16176 56326 : exit_omp_iterator_loop_context (c);
16177 56326 : break;
16178 :
16179 8333 : case OMP_CLAUSE_TO:
16180 8333 : case OMP_CLAUSE_FROM:
16181 8333 : case OMP_CLAUSE__CACHE_:
16182 8333 : decl = OMP_CLAUSE_DECL (c);
16183 8333 : if (!DECL_P (decl))
16184 : break;
16185 6189 : if (DECL_SIZE (decl)
16186 6189 : && !poly_int_tree_p (DECL_SIZE (decl)))
16187 : {
16188 4 : tree decl2 = DECL_VALUE_EXPR (decl);
16189 4 : gcc_assert (INDIRECT_REF_P (decl2));
16190 4 : decl2 = TREE_OPERAND (decl2, 0);
16191 4 : gcc_assert (DECL_P (decl2));
16192 4 : tree mem = build_simple_mem_ref (decl2);
16193 4 : OMP_CLAUSE_DECL (c) = mem;
16194 4 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16195 4 : if (ctx->outer_context)
16196 : {
16197 4 : omp_notice_variable (ctx->outer_context, decl2, true);
16198 4 : omp_notice_variable (ctx->outer_context,
16199 4 : OMP_CLAUSE_SIZE (c), true);
16200 : }
16201 : }
16202 6185 : else if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16203 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16204 : break;
16205 :
16206 15215 : case OMP_CLAUSE_REDUCTION:
16207 15215 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
16208 : {
16209 811 : decl = OMP_CLAUSE_DECL (c);
16210 811 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16211 811 : if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
16212 : {
16213 69 : remove = true;
16214 69 : error_at (OMP_CLAUSE_LOCATION (c),
16215 : "%qD specified in %<inscan%> %<reduction%> clause "
16216 : "but not in %<scan%> directive clause", decl);
16217 69 : break;
16218 : }
16219 : has_inscan_reductions = true;
16220 : }
16221 : /* FALLTHRU */
16222 17750 : case OMP_CLAUSE_IN_REDUCTION:
16223 17750 : case OMP_CLAUSE_TASK_REDUCTION:
16224 17750 : decl = OMP_CLAUSE_DECL (c);
16225 : /* OpenACC reductions need a present_or_copy data clause.
16226 : Add one if necessary. Emit error when the reduction is private. */
16227 17750 : if (ctx->region_type == ORT_ACC_PARALLEL
16228 17218 : || ctx->region_type == ORT_ACC_SERIAL)
16229 : {
16230 803 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16231 803 : if (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16232 : {
16233 13 : remove = true;
16234 13 : error_at (OMP_CLAUSE_LOCATION (c), "invalid private "
16235 13 : "reduction on %qE", DECL_NAME (decl));
16236 : }
16237 790 : else if ((n->value & GOVD_MAP) == 0)
16238 : {
16239 524 : tree next = OMP_CLAUSE_CHAIN (c);
16240 524 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP);
16241 524 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM);
16242 524 : OMP_CLAUSE_DECL (nc) = decl;
16243 524 : OMP_CLAUSE_CHAIN (c) = nc;
16244 524 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
16245 524 : (ctx->region_type
16246 : & ORT_ACC) != 0);
16247 550 : while (1)
16248 : {
16249 537 : OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1;
16250 537 : if (OMP_CLAUSE_CHAIN (nc) == NULL)
16251 : break;
16252 13 : nc = OMP_CLAUSE_CHAIN (nc);
16253 : }
16254 524 : OMP_CLAUSE_CHAIN (nc) = next;
16255 524 : n->value |= GOVD_MAP;
16256 : }
16257 : }
16258 17750 : if (DECL_P (decl)
16259 17750 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
16260 7963 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
16261 : break;
16262 :
16263 3541 : case OMP_CLAUSE_ALLOCATE:
16264 3541 : decl = OMP_CLAUSE_DECL (c);
16265 3541 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16266 3541 : if (n != NULL && !(n->value & GOVD_SEEN))
16267 : {
16268 1176 : if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
16269 : != 0
16270 1176 : && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
16271 : remove = true;
16272 : }
16273 : if (!remove
16274 2365 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
16275 1273 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
16276 483 : && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
16277 347 : || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
16278 287 : || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
16279 : {
16280 214 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
16281 214 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
16282 214 : if (n == NULL)
16283 : {
16284 92 : enum omp_clause_default_kind default_kind
16285 : = ctx->default_kind;
16286 92 : ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
16287 92 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16288 : true);
16289 92 : ctx->default_kind = default_kind;
16290 : }
16291 : else
16292 122 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16293 : true);
16294 : }
16295 : break;
16296 :
16297 : case OMP_CLAUSE_COPYIN:
16298 : case OMP_CLAUSE_COPYPRIVATE:
16299 : case OMP_CLAUSE_IF:
16300 : case OMP_CLAUSE_SELF:
16301 : case OMP_CLAUSE_NUM_THREADS:
16302 : case OMP_CLAUSE_NUM_TEAMS:
16303 : case OMP_CLAUSE_THREAD_LIMIT:
16304 : case OMP_CLAUSE_DIST_SCHEDULE:
16305 : case OMP_CLAUSE_DEVICE:
16306 : case OMP_CLAUSE_SCHEDULE:
16307 : case OMP_CLAUSE_NOWAIT:
16308 : case OMP_CLAUSE_ORDERED:
16309 : case OMP_CLAUSE_DEFAULT:
16310 : case OMP_CLAUSE_UNTIED:
16311 : case OMP_CLAUSE_COLLAPSE:
16312 : case OMP_CLAUSE_FINAL:
16313 : case OMP_CLAUSE_MERGEABLE:
16314 : case OMP_CLAUSE_PROC_BIND:
16315 : case OMP_CLAUSE_SAFELEN:
16316 : case OMP_CLAUSE_SIMDLEN:
16317 : case OMP_CLAUSE_DEPEND:
16318 : case OMP_CLAUSE_DOACROSS:
16319 : case OMP_CLAUSE_PRIORITY:
16320 : case OMP_CLAUSE_GRAINSIZE:
16321 : case OMP_CLAUSE_NUM_TASKS:
16322 : case OMP_CLAUSE_NOGROUP:
16323 : case OMP_CLAUSE_THREADS:
16324 : case OMP_CLAUSE_SIMD:
16325 : case OMP_CLAUSE_FILTER:
16326 : case OMP_CLAUSE_HINT:
16327 : case OMP_CLAUSE_DEFAULTMAP:
16328 : case OMP_CLAUSE_ORDER:
16329 : case OMP_CLAUSE_BIND:
16330 : case OMP_CLAUSE_DETACH:
16331 : case OMP_CLAUSE_USE_DEVICE_PTR:
16332 : case OMP_CLAUSE_USE_DEVICE_ADDR:
16333 : case OMP_CLAUSE_ASYNC:
16334 : case OMP_CLAUSE_WAIT:
16335 : case OMP_CLAUSE_INDEPENDENT:
16336 : case OMP_CLAUSE_NUM_GANGS:
16337 : case OMP_CLAUSE_NUM_WORKERS:
16338 : case OMP_CLAUSE_VECTOR_LENGTH:
16339 : case OMP_CLAUSE_GANG:
16340 : case OMP_CLAUSE_WORKER:
16341 : case OMP_CLAUSE_VECTOR:
16342 : case OMP_CLAUSE_AUTO:
16343 : case OMP_CLAUSE_SEQ:
16344 : case OMP_CLAUSE_TILE:
16345 : case OMP_CLAUSE_IF_PRESENT:
16346 : case OMP_CLAUSE_FINALIZE:
16347 : case OMP_CLAUSE_INCLUSIVE:
16348 : case OMP_CLAUSE_EXCLUSIVE:
16349 : case OMP_CLAUSE_USES_ALLOCATORS:
16350 : case OMP_CLAUSE_DEVICE_TYPE:
16351 : break;
16352 :
16353 0 : case OMP_CLAUSE_NOHOST:
16354 0 : default:
16355 0 : gcc_unreachable ();
16356 : }
16357 :
16358 129600 : if (remove)
16359 9911 : *list_p = OMP_CLAUSE_CHAIN (c);
16360 238929 : else if (move_attach)
16361 : {
16362 : /* Remove attach node from here, separate out into its own list. */
16363 2360 : *attach_tail = c;
16364 2360 : *list_p = OMP_CLAUSE_CHAIN (c);
16365 2360 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
16366 2360 : attach_tail = &OMP_CLAUSE_CHAIN (c);
16367 : }
16368 : else
16369 236569 : list_p = &OMP_CLAUSE_CHAIN (c);
16370 : }
16371 :
16372 : /* Splice attach nodes at the end of the list. */
16373 129101 : if (attach_list)
16374 : {
16375 1127 : *list_p = attach_list;
16376 1127 : list_p = attach_tail;
16377 : }
16378 :
16379 : /* Add in any implicit data sharing. */
16380 129101 : struct gimplify_adjust_omp_clauses_data data;
16381 129101 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
16382 : {
16383 : /* OpenMP. Implicit clauses are added at the start of the clause list,
16384 : but after any non-map clauses. */
16385 : tree *implicit_add_list_p = orig_list_p;
16386 252488 : while (*implicit_add_list_p
16387 252488 : && OMP_CLAUSE_CODE (*implicit_add_list_p) != OMP_CLAUSE_MAP)
16388 153234 : implicit_add_list_p = &OMP_CLAUSE_CHAIN (*implicit_add_list_p);
16389 99254 : data.list_p = implicit_add_list_p;
16390 : }
16391 : else
16392 : /* OpenACC. */
16393 29847 : data.list_p = list_p;
16394 129101 : data.pre_p = pre_p;
16395 129101 : splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
16396 :
16397 129101 : if (has_inscan_reductions)
16398 2431 : for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
16399 1822 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
16400 1822 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
16401 : {
16402 5 : error_at (OMP_CLAUSE_LOCATION (c),
16403 : "%<inscan%> %<reduction%> clause used together with "
16404 : "%<linear%> clause for a variable other than loop "
16405 : "iterator");
16406 5 : break;
16407 : }
16408 :
16409 129101 : gimplify_omp_ctxp = ctx->outer_context;
16410 129101 : delete_omp_context (ctx);
16411 129101 : }
16412 :
16413 : /* Try to evaluate a novariants clause. Return 1 if true, 0 if false or absent,
16414 : * -1 if run-time evaluation is needed. */
16415 :
16416 : int
16417 250896 : omp_has_novariants (void)
16418 : {
16419 250896 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16420 250896 : if (ctx != NULL && ctx->code == OMP_DISPATCH && !ctx->in_call_args)
16421 : {
16422 3290 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOVARIANTS);
16423 3290 : if (c != NULL_TREE)
16424 : {
16425 299 : if (integer_nonzerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16426 : return 1;
16427 171 : else if (integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16428 : return 0;
16429 : else
16430 : return -1;
16431 : }
16432 : return 0;
16433 : }
16434 : return 0;
16435 : }
16436 :
16437 : /* Try to evaluate a nocontext clause. Return 1 if true, 0 if false or absent,
16438 : * -1 if run-time evaluation is needed. */
16439 :
16440 : static int
16441 1903 : omp_has_nocontext (void)
16442 : {
16443 1903 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16444 1903 : if (ctx != NULL && ctx->code == OMP_DISPATCH)
16445 : {
16446 1903 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOCONTEXT);
16447 1903 : if (c != NULL_TREE)
16448 : {
16449 256 : if (integer_nonzerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16450 : return 1;
16451 94 : else if (integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16452 : return 0;
16453 : else
16454 : return -1;
16455 : }
16456 : return 0;
16457 : }
16458 : return 0;
16459 : }
16460 :
16461 : /* Collect a list of traits for enclosing constructs in the current
16462 : OpenMP context. The list is in the same format as the trait selector
16463 : list of construct trait sets built by the front ends.
16464 :
16465 : Per the OpenMP specification, the construct trait set includes constructs
16466 : up to an enclosing "target" construct. If there is no "target" construct,
16467 : then additional things may be added to the construct trait set (simd for
16468 : simd clones, additional constructs associated with "declare variant",
16469 : the target trait for "declare target"); those are not handled here.
16470 : In particular simd clones are not known during gimplification so
16471 : matching/scoring of context selectors that might involve them needs
16472 : to be deferred to the omp_device_lower pass. */
16473 :
16474 : tree
16475 2213 : omp_get_construct_context (void)
16476 : {
16477 2213 : tree result = NULL_TREE;
16478 4184 : for (struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; ctx;)
16479 : {
16480 2092 : if (((ctx->region_type & (ORT_TARGET | ORT_IMPLICIT_TARGET | ORT_ACC))
16481 : == ORT_TARGET)
16482 121 : && ctx->code == OMP_TARGET)
16483 : {
16484 121 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TARGET,
16485 : NULL_TREE, NULL_TREE, result);
16486 : /* We're not interested in any outer constructs. */
16487 121 : break;
16488 : }
16489 1971 : else if ((ctx->region_type & ORT_PARALLEL) && ctx->code == OMP_PARALLEL)
16490 214 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_PARALLEL,
16491 : NULL_TREE, NULL_TREE, result);
16492 1757 : else if ((ctx->region_type & ORT_TEAMS) && ctx->code == OMP_TEAMS)
16493 75 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TEAMS,
16494 : NULL_TREE, NULL_TREE, result);
16495 1682 : else if (ctx->region_type == ORT_WORKSHARE && ctx->code == OMP_FOR)
16496 164 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_FOR,
16497 : NULL_TREE, NULL_TREE, result);
16498 1518 : else if (ctx->code == OMP_DISPATCH && omp_has_nocontext () != 1)
16499 1279 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_DISPATCH,
16500 : NULL_TREE, NULL_TREE, result);
16501 239 : else if (ctx->region_type == ORT_SIMD
16502 32 : && ctx->code == OMP_SIMD
16503 271 : && !omp_find_clause (ctx->clauses, OMP_CLAUSE_BIND))
16504 : {
16505 32 : tree props = NULL_TREE;
16506 32 : tree *last = &props;
16507 72 : for (tree c = ctx->clauses; c; c = OMP_CLAUSE_CHAIN (c))
16508 40 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMDLEN
16509 32 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INBRANCH
16510 72 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOTINBRANCH)
16511 : {
16512 8 : *last = unshare_expr (c);
16513 8 : last = &(OMP_CLAUSE_CHAIN (c));
16514 : }
16515 32 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_SIMD,
16516 : NULL_TREE, props, result);
16517 : }
16518 207 : else if (ctx->region_type == ORT_WORKSHARE
16519 5 : && ctx->code == OMP_LOOP
16520 0 : && ctx->outer_context
16521 0 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL
16522 0 : && ctx->outer_context->outer_context
16523 0 : && ctx->outer_context->outer_context->code == OMP_LOOP
16524 0 : && ctx->outer_context->outer_context->distribute)
16525 1971 : ctx = ctx->outer_context->outer_context;
16526 1971 : ctx = ctx->outer_context;
16527 : }
16528 :
16529 2213 : return result;
16530 : }
16531 :
16532 : /* Gimplify OACC_CACHE. */
16533 :
16534 : static void
16535 665 : gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
16536 : {
16537 665 : tree expr = *expr_p;
16538 :
16539 665 : gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_ACC,
16540 : OACC_CACHE);
16541 665 : gimplify_adjust_omp_clauses (pre_p, NULL, &OACC_CACHE_CLAUSES (expr),
16542 : OACC_CACHE);
16543 :
16544 : /* TODO: Do something sensible with this information. */
16545 :
16546 665 : *expr_p = NULL_TREE;
16547 665 : }
16548 :
16549 : /* Helper function of gimplify_oacc_declare. The helper's purpose is to,
16550 : if required, translate 'kind' in CLAUSE into an 'entry' kind and 'exit'
16551 : kind. The entry kind will replace the one in CLAUSE, while the exit
16552 : kind will be used in a new omp_clause and returned to the caller. */
16553 :
16554 : static tree
16555 190 : gimplify_oacc_declare_1 (tree clause)
16556 : {
16557 190 : HOST_WIDE_INT kind, new_op;
16558 190 : bool ret = false;
16559 190 : tree c = NULL;
16560 :
16561 190 : kind = OMP_CLAUSE_MAP_KIND (clause);
16562 :
16563 190 : switch (kind)
16564 : {
16565 : case GOMP_MAP_ALLOC:
16566 : new_op = GOMP_MAP_RELEASE;
16567 : ret = true;
16568 : break;
16569 :
16570 29 : case GOMP_MAP_FROM:
16571 29 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_ALLOC);
16572 29 : new_op = GOMP_MAP_FROM;
16573 29 : ret = true;
16574 29 : break;
16575 :
16576 40 : case GOMP_MAP_TOFROM:
16577 40 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_TO);
16578 40 : new_op = GOMP_MAP_FROM;
16579 40 : ret = true;
16580 40 : break;
16581 :
16582 : case GOMP_MAP_DEVICE_RESIDENT:
16583 : case GOMP_MAP_FORCE_DEVICEPTR:
16584 : case GOMP_MAP_FORCE_PRESENT:
16585 : case GOMP_MAP_LINK:
16586 : case GOMP_MAP_POINTER:
16587 : case GOMP_MAP_TO:
16588 : break;
16589 :
16590 0 : default:
16591 0 : gcc_unreachable ();
16592 69 : break;
16593 : }
16594 :
16595 69 : if (ret)
16596 : {
16597 116 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clause), OMP_CLAUSE_MAP);
16598 116 : OMP_CLAUSE_SET_MAP_KIND (c, new_op);
16599 116 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clause);
16600 : }
16601 :
16602 190 : return c;
16603 : }
16604 :
16605 : /* Gimplify OACC_DECLARE. */
16606 :
16607 : static void
16608 254 : gimplify_oacc_declare (tree *expr_p, gimple_seq *pre_p)
16609 : {
16610 254 : tree expr = *expr_p;
16611 254 : gomp_target *stmt;
16612 254 : tree clauses, t, decl;
16613 :
16614 254 : clauses = OACC_DECLARE_CLAUSES (expr);
16615 :
16616 254 : gimplify_scan_omp_clauses (&clauses, pre_p, ORT_TARGET_DATA, OACC_DECLARE);
16617 254 : gimplify_adjust_omp_clauses (pre_p, NULL, &clauses, OACC_DECLARE);
16618 :
16619 516 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16620 : {
16621 262 : decl = OMP_CLAUSE_DECL (t);
16622 :
16623 262 : if (TREE_CODE (decl) == MEM_REF)
16624 8 : decl = TREE_OPERAND (decl, 0);
16625 :
16626 262 : if (VAR_P (decl) && !is_oacc_declared (decl))
16627 : {
16628 262 : tree attr = get_identifier ("oacc declare target");
16629 262 : DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE,
16630 262 : DECL_ATTRIBUTES (decl));
16631 : }
16632 :
16633 262 : if (VAR_P (decl)
16634 262 : && !is_global_var (decl)
16635 452 : && DECL_CONTEXT (decl) == current_function_decl)
16636 : {
16637 190 : tree c = gimplify_oacc_declare_1 (t);
16638 190 : if (c)
16639 : {
16640 116 : if (oacc_declare_returns == NULL)
16641 40 : oacc_declare_returns = new hash_map<tree, tree>;
16642 :
16643 116 : oacc_declare_returns->put (decl, c);
16644 : }
16645 : }
16646 :
16647 262 : if (gimplify_omp_ctxp)
16648 72 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_SEEN);
16649 : }
16650 :
16651 254 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
16652 : clauses);
16653 :
16654 254 : gimplify_seq_add_stmt (pre_p, stmt);
16655 :
16656 254 : *expr_p = NULL_TREE;
16657 254 : }
16658 :
16659 : /* Gimplify the contents of an OMP_PARALLEL statement. This involves
16660 : gimplification of the body, as well as scanning the body for used
16661 : variables. We need to do this scan now, because variable-sized
16662 : decls will be decomposed during gimplification. */
16663 :
16664 : static void
16665 18244 : gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
16666 : {
16667 18244 : tree expr = *expr_p;
16668 18244 : gimple *g;
16669 18244 : gimple_seq body = NULL;
16670 :
16671 36488 : gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
16672 18244 : OMP_PARALLEL_COMBINED (expr)
16673 : ? ORT_COMBINED_PARALLEL
16674 : : ORT_PARALLEL, OMP_PARALLEL);
16675 :
16676 18244 : push_gimplify_context ();
16677 :
16678 18244 : g = gimplify_and_return_first (OMP_PARALLEL_BODY (expr), &body);
16679 18244 : if (gimple_code (g) == GIMPLE_BIND)
16680 18244 : pop_gimplify_context (g);
16681 : else
16682 0 : pop_gimplify_context (NULL);
16683 :
16684 18244 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_PARALLEL_CLAUSES (expr),
16685 : OMP_PARALLEL);
16686 :
16687 36488 : g = gimple_build_omp_parallel (body,
16688 18244 : OMP_PARALLEL_CLAUSES (expr),
16689 : NULL_TREE, NULL_TREE);
16690 18244 : if (OMP_PARALLEL_COMBINED (expr))
16691 12538 : gimple_omp_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
16692 18244 : gimplify_seq_add_stmt (pre_p, g);
16693 18244 : *expr_p = NULL_TREE;
16694 18244 : }
16695 :
16696 : /* Gimplify the contents of an OMP_TASK statement. This involves
16697 : gimplification of the body, as well as scanning the body for used
16698 : variables. We need to do this scan now, because variable-sized
16699 : decls will be decomposed during gimplification. */
16700 :
16701 : static void
16702 3855 : gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
16703 : {
16704 3855 : tree expr = *expr_p;
16705 3855 : gimple *g;
16706 3855 : gimple_seq body = NULL;
16707 3855 : bool nowait = false;
16708 3855 : bool has_depend = false;
16709 :
16710 3855 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16711 : {
16712 242 : for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
16713 153 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
16714 : {
16715 111 : has_depend = true;
16716 111 : if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
16717 : {
16718 9 : error_at (OMP_CLAUSE_LOCATION (c),
16719 : "%<mutexinoutset%> kind in %<depend%> clause on a "
16720 : "%<taskwait%> construct");
16721 9 : break;
16722 : }
16723 : }
16724 42 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT)
16725 42 : nowait = true;
16726 98 : if (nowait && !has_depend)
16727 : {
16728 5 : error_at (EXPR_LOCATION (expr),
16729 : "%<taskwait%> construct with %<nowait%> clause but no "
16730 : "%<depend%> clauses");
16731 5 : *expr_p = NULL_TREE;
16732 5 : return;
16733 : }
16734 : }
16735 :
16736 11550 : gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
16737 3850 : omp_find_clause (OMP_TASK_CLAUSES (expr),
16738 : OMP_CLAUSE_UNTIED)
16739 : ? ORT_UNTIED_TASK : ORT_TASK, OMP_TASK);
16740 :
16741 3850 : if (OMP_TASK_BODY (expr))
16742 : {
16743 3757 : push_gimplify_context ();
16744 :
16745 3757 : g = gimplify_and_return_first (OMP_TASK_BODY (expr), &body);
16746 3757 : if (gimple_code (g) == GIMPLE_BIND)
16747 3757 : pop_gimplify_context (g);
16748 : else
16749 0 : pop_gimplify_context (NULL);
16750 : }
16751 :
16752 3850 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_TASK_CLAUSES (expr),
16753 : OMP_TASK);
16754 :
16755 7700 : g = gimple_build_omp_task (body,
16756 3850 : OMP_TASK_CLAUSES (expr),
16757 : NULL_TREE, NULL_TREE,
16758 : NULL_TREE, NULL_TREE, NULL_TREE);
16759 3850 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16760 93 : gimple_omp_task_set_taskwait_p (g, true);
16761 3850 : gimplify_seq_add_stmt (pre_p, g);
16762 3850 : *expr_p = NULL_TREE;
16763 : }
16764 :
16765 : /* Helper function for gimplify_omp_for. If *TP is not a gimple constant,
16766 : force it into a temporary initialized in PRE_P and add firstprivate clause
16767 : to ORIG_FOR_STMT. */
16768 :
16769 : static void
16770 4399 : gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p,
16771 : tree orig_for_stmt)
16772 : {
16773 4399 : if (*tp == NULL || is_gimple_constant (*tp))
16774 : return;
16775 :
16776 779 : if (TREE_CODE (*tp) == SAVE_EXPR)
16777 135 : gimplify_save_expr (tp, pre_p, NULL);
16778 : else
16779 644 : *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false);
16780 : /* Reference to pointer conversion is considered useless,
16781 : but is significant for firstprivate clause. Force it
16782 : here. */
16783 779 : if (type
16784 687 : && TREE_CODE (type) == POINTER_TYPE
16785 869 : && TREE_CODE (TREE_TYPE (*tp)) == REFERENCE_TYPE)
16786 : {
16787 2 : tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
16788 2 : tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, *tp);
16789 2 : gimplify_and_add (m, pre_p);
16790 2 : *tp = v;
16791 : }
16792 :
16793 779 : tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
16794 779 : OMP_CLAUSE_DECL (c) = *tp;
16795 779 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (orig_for_stmt);
16796 779 : OMP_FOR_CLAUSES (orig_for_stmt) = c;
16797 : }
16798 :
16799 : /* Helper function of gimplify_omp_for, find OMP_ORDERED with
16800 : null OMP_ORDERED_BODY inside of OMP_FOR's body. */
16801 :
16802 : static tree
16803 16496 : find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
16804 : {
16805 16496 : switch (TREE_CODE (*tp))
16806 : {
16807 901 : case OMP_ORDERED:
16808 901 : if (OMP_ORDERED_BODY (*tp) == NULL_TREE)
16809 : return *tp;
16810 : break;
16811 23 : case OMP_SIMD:
16812 23 : case OMP_PARALLEL:
16813 23 : case OMP_TARGET:
16814 23 : *walk_subtrees = 0;
16815 23 : break;
16816 : default:
16817 : break;
16818 : }
16819 : return NULL_TREE;
16820 : }
16821 :
16822 : /* Gimplify standalone loop transforming directive which has the
16823 : transformations applied already. So, all that is needed is gimplify
16824 : the remaining loops as normal loops. */
16825 :
16826 : static enum gimplify_status
16827 2264 : gimplify_omp_loop_xform (tree *expr_p, gimple_seq *pre_p)
16828 : {
16829 2264 : tree for_stmt = *expr_p;
16830 :
16831 2264 : if (OMP_FOR_PRE_BODY (for_stmt))
16832 759 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), pre_p);
16833 :
16834 2264 : gimple_seq pre_body = NULL, post_body = NULL;
16835 5203 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16836 : {
16837 2939 : if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE)
16838 1707 : continue;
16839 1283 : tree iters = NULL_TREE;
16840 1283 : if (i == 0
16841 826 : && TREE_CODE (for_stmt) == OMP_UNROLL
16842 1771 : && !omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_PARTIAL))
16843 : {
16844 311 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL))
16845 269 : iters = omp_loop_number_of_iterations (for_stmt, 0, NULL);
16846 : else
16847 42 : iters = build_int_cst (integer_type_node, 8);
16848 : }
16849 1283 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
16850 1283 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
16851 1283 : tree decl = TREE_OPERAND (t, 0);
16852 1283 : gcc_assert (DECL_P (decl));
16853 1283 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
16854 : || POINTER_TYPE_P (TREE_TYPE (decl)));
16855 1283 : if (DECL_ARTIFICIAL (decl)
16856 876 : && TREE_PRIVATE (t)
16857 867 : && gimplify_omp_ctxp
16858 1613 : && gimplify_omp_ctxp->region_type != ORT_NONE)
16859 : {
16860 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16861 504 : do
16862 : {
16863 504 : splay_tree_node n
16864 504 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16865 504 : if (n != NULL)
16866 : break;
16867 346 : else if (ctx->region_type != ORT_WORKSHARE
16868 : && ctx->region_type != ORT_TASKGROUP
16869 62 : && ctx->region_type != ORT_SIMD
16870 38 : && ctx->region_type != ORT_ACC
16871 38 : && !(ctx->region_type & ORT_TARGET_DATA))
16872 : {
16873 38 : omp_add_variable (ctx, decl, GOVD_PRIVATE);
16874 38 : break;
16875 : }
16876 308 : ctx = ctx->outer_context;
16877 : }
16878 308 : while (ctx);
16879 : }
16880 1283 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16881 : {
16882 23 : gcc_assert (seen_error ());
16883 23 : continue;
16884 : }
16885 1260 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16886 : fb_rvalue);
16887 1260 : gimplify_and_add (t, &pre_body);
16888 1260 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16889 1260 : gcc_assert (TREE_OPERAND (t, 0) == decl);
16890 1260 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16891 : {
16892 28 : gcc_assert (seen_error ());
16893 28 : continue;
16894 : }
16895 1232 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16896 : fb_rvalue);
16897 1232 : tree l1 = create_artificial_label (UNKNOWN_LOCATION);
16898 1232 : tree l2 = create_artificial_label (UNKNOWN_LOCATION);
16899 1232 : tree l3 = create_artificial_label (UNKNOWN_LOCATION);
16900 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_goto (l2));
16901 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_label (l1));
16902 1232 : gimple_seq this_post_body = NULL;
16903 1232 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
16904 1232 : if (TREE_CODE (t) == MODIFY_EXPR)
16905 : {
16906 975 : t = TREE_OPERAND (t, 1);
16907 975 : if (TREE_CODE (t) == PLUS_EXPR
16908 975 : && TREE_OPERAND (t, 1) == decl)
16909 : {
16910 0 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
16911 0 : TREE_OPERAND (t, 0) = decl;
16912 : }
16913 975 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16914 : fb_rvalue);
16915 : }
16916 1232 : gimplify_and_add (TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i),
16917 : &this_post_body);
16918 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l2));
16919 1232 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16920 1232 : gcond *cond = NULL;
16921 1232 : tree d = decl;
16922 1232 : gimplify_expr (&d, &this_post_body, NULL, is_gimple_val, fb_rvalue);
16923 1232 : if (iters && tree_fits_uhwi_p (iters))
16924 : {
16925 299 : unsigned HOST_WIDE_INT niters = tree_to_uhwi (iters);
16926 299 : if ((unsigned HOST_WIDE_INT) (int) niters == niters
16927 299 : && (int) niters > 0)
16928 : {
16929 299 : t = build2 (TREE_CODE (t), boolean_type_node, d,
16930 299 : TREE_OPERAND (t, 1));
16931 299 : t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t,
16932 : build_int_cst (integer_type_node,
16933 : annot_expr_unroll_kind),
16934 299 : build_int_cst (integer_type_node, niters));
16935 299 : gimplify_expr (&t, &this_post_body, NULL, is_gimple_val,
16936 : fb_rvalue);
16937 299 : cond = gimple_build_cond (NE_EXPR, t, boolean_false_node,
16938 : l1, l3);
16939 : }
16940 : }
16941 299 : if (cond == NULL)
16942 933 : cond = gimple_build_cond (TREE_CODE (t), d, TREE_OPERAND (t, 1),
16943 : l1, l3);
16944 1232 : gimplify_seq_add_stmt (&this_post_body, cond);
16945 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l3));
16946 1232 : gimplify_seq_add_seq (&this_post_body, post_body);
16947 1232 : post_body = this_post_body;
16948 : }
16949 2264 : gimplify_seq_add_seq (pre_p, pre_body);
16950 2264 : gimplify_and_add (OMP_FOR_BODY (for_stmt), pre_p);
16951 2264 : gimplify_seq_add_seq (pre_p, post_body);
16952 :
16953 2264 : *expr_p = NULL_TREE;
16954 2264 : return GS_ALL_DONE;
16955 : }
16956 :
16957 : /* Gimplify the gross structure of an OMP_FOR statement. */
16958 :
16959 : static enum gimplify_status
16960 58086 : gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
16961 : {
16962 58086 : tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t;
16963 58086 : enum gimplify_status ret = GS_ALL_DONE;
16964 58086 : enum gimplify_status tret;
16965 58086 : gomp_for *gfor;
16966 58086 : gimple_seq for_body, for_pre_body;
16967 58086 : int i;
16968 58086 : bitmap has_decl_expr = NULL;
16969 58086 : enum omp_region_type ort = ORT_WORKSHARE;
16970 58086 : bool openacc = TREE_CODE (*expr_p) == OACC_LOOP;
16971 :
16972 58086 : orig_for_stmt = for_stmt = *expr_p;
16973 :
16974 58086 : bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND)
16975 58086 : != NULL_TREE);
16976 58157 : while (OMP_FOR_INIT (for_stmt) == NULL_TREE)
16977 : {
16978 17738 : tree *data[4] = { NULL, NULL, NULL, NULL };
16979 17738 : gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
16980 17738 : inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt),
16981 : find_combined_omp_for, data, NULL);
16982 17738 : if (inner_for_stmt == NULL_TREE)
16983 : {
16984 36 : gcc_assert (seen_error ());
16985 36 : *expr_p = NULL_TREE;
16986 3741 : return GS_ERROR;
16987 : }
16988 17702 : gcc_assert (inner_for_stmt == *data[3]);
16989 17702 : omp_maybe_apply_loop_xforms (data[3],
16990 17702 : data[2]
16991 4279 : ? OMP_FOR_CLAUSES (*data[2])
16992 13423 : : TREE_CODE (for_stmt) == OMP_FOR
16993 13423 : ? OMP_FOR_CLAUSES (for_stmt)
16994 : : NULL_TREE);
16995 17702 : if (inner_for_stmt != *data[3])
16996 71 : continue;
16997 17631 : if (data[2] && OMP_FOR_PRE_BODY (*data[2]))
16998 : {
16999 2 : append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]),
17000 : &OMP_FOR_PRE_BODY (for_stmt));
17001 2 : OMP_FOR_PRE_BODY (*data[2]) = NULL_TREE;
17002 : }
17003 17631 : if (OMP_FOR_PRE_BODY (inner_for_stmt))
17004 : {
17005 7193 : append_to_statement_list_force (OMP_FOR_PRE_BODY (inner_for_stmt),
17006 : &OMP_FOR_PRE_BODY (for_stmt));
17007 7193 : OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
17008 : }
17009 :
17010 17631 : if (data[0])
17011 : {
17012 : /* We have some statements or variable declarations in between
17013 : the composite construct directives. Move them around the
17014 : inner_for_stmt. */
17015 3705 : data[0] = expr_p;
17016 14820 : for (i = 0; i < 3; i++)
17017 11115 : if (data[i])
17018 : {
17019 7028 : tree t = *data[i];
17020 7028 : if (i < 2 && data[i + 1] == &OMP_BODY (t))
17021 1005 : data[i + 1] = data[i];
17022 7028 : *data[i] = OMP_BODY (t);
17023 7028 : tree body = build3 (BIND_EXPR, void_type_node, NULL_TREE,
17024 : NULL_TREE, make_node (BLOCK));
17025 7028 : OMP_BODY (t) = body;
17026 7028 : append_to_statement_list_force (inner_for_stmt,
17027 : &BIND_EXPR_BODY (body));
17028 7028 : *data[3] = t;
17029 7028 : data[3] = tsi_stmt_ptr (tsi_start (BIND_EXPR_BODY (body)));
17030 7028 : gcc_assert (*data[3] == inner_for_stmt);
17031 : }
17032 : return GS_OK;
17033 : }
17034 :
17035 36734 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17036 22808 : if (!loop_p
17037 21927 : && OMP_FOR_ORIG_DECLS (inner_for_stmt)
17038 11098 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17039 : i)) == TREE_LIST
17040 22876 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17041 : i)))
17042 : {
17043 40 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17044 : /* Class iterators aren't allowed on OMP_SIMD, so the only
17045 : case we need to solve is distribute parallel for. They are
17046 : allowed on the loop construct, but that is already handled
17047 : in gimplify_omp_loop. */
17048 40 : gcc_assert (TREE_CODE (inner_for_stmt) == OMP_FOR
17049 : && TREE_CODE (for_stmt) == OMP_DISTRIBUTE
17050 : && data[1]);
17051 40 : tree orig_decl = TREE_PURPOSE (orig);
17052 40 : tree last = TREE_VALUE (orig);
17053 40 : tree *pc;
17054 40 : for (pc = &OMP_FOR_CLAUSES (inner_for_stmt);
17055 74 : *pc; pc = &OMP_CLAUSE_CHAIN (*pc))
17056 42 : if ((OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE
17057 35 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE)
17058 43 : && OMP_CLAUSE_DECL (*pc) == orig_decl)
17059 : break;
17060 40 : if (*pc == NULL_TREE)
17061 : {
17062 32 : tree *spc;
17063 32 : for (spc = &OMP_PARALLEL_CLAUSES (*data[1]);
17064 98 : *spc; spc = &OMP_CLAUSE_CHAIN (*spc))
17065 67 : if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE
17066 67 : && OMP_CLAUSE_DECL (*spc) == orig_decl)
17067 : break;
17068 32 : if (*spc)
17069 : {
17070 1 : tree c = *spc;
17071 1 : *spc = OMP_CLAUSE_CHAIN (c);
17072 1 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
17073 1 : *pc = c;
17074 : }
17075 : }
17076 40 : if (*pc == NULL_TREE)
17077 : ;
17078 9 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE)
17079 : {
17080 : /* private clause will appear only on inner_for_stmt.
17081 : Change it into firstprivate, and add private clause
17082 : on for_stmt. */
17083 8 : tree c = copy_node (*pc);
17084 8 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17085 8 : OMP_FOR_CLAUSES (for_stmt) = c;
17086 8 : OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE;
17087 8 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17088 : }
17089 : else
17090 : {
17091 : /* lastprivate clause will appear on both inner_for_stmt
17092 : and for_stmt. Add firstprivate clause to
17093 : inner_for_stmt. */
17094 1 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (*pc),
17095 : OMP_CLAUSE_FIRSTPRIVATE);
17096 1 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc);
17097 1 : OMP_CLAUSE_CHAIN (c) = *pc;
17098 1 : *pc = c;
17099 1 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17100 : }
17101 40 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17102 : OMP_CLAUSE_FIRSTPRIVATE);
17103 40 : OMP_CLAUSE_DECL (c) = last;
17104 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17105 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17106 40 : c = build_omp_clause (UNKNOWN_LOCATION,
17107 40 : *pc ? OMP_CLAUSE_SHARED
17108 : : OMP_CLAUSE_FIRSTPRIVATE);
17109 40 : OMP_CLAUSE_DECL (c) = orig_decl;
17110 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17111 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17112 : }
17113 : /* Similarly, take care of C++ range for temporaries, those should
17114 : be firstprivate on OMP_PARALLEL if any. */
17115 13926 : if (data[1])
17116 17503 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17117 11108 : if (OMP_FOR_ORIG_DECLS (inner_for_stmt)
17118 5733 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17119 : i)) == TREE_LIST
17120 11184 : && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17121 : i)))
17122 : {
17123 49 : tree orig
17124 49 : = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17125 49 : tree v = TREE_CHAIN (orig);
17126 49 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17127 : OMP_CLAUSE_FIRSTPRIVATE);
17128 : /* First add firstprivate clause for the __for_end artificial
17129 : decl. */
17130 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 1);
17131 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17132 : == REFERENCE_TYPE)
17133 0 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17134 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17135 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17136 49 : if (TREE_VEC_ELT (v, 0))
17137 : {
17138 : /* And now the same for __for_range artificial decl if it
17139 : exists. */
17140 49 : c = build_omp_clause (UNKNOWN_LOCATION,
17141 : OMP_CLAUSE_FIRSTPRIVATE);
17142 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 0);
17143 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17144 : == REFERENCE_TYPE)
17145 49 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17146 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17147 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17148 : }
17149 : }
17150 13926 : break;
17151 : }
17152 54345 : if (OMP_FOR_INIT (for_stmt) != NULL_TREE)
17153 : {
17154 40419 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
17155 40419 : if (*expr_p != for_stmt)
17156 : return GS_OK;
17157 : }
17158 :
17159 53463 : switch (TREE_CODE (for_stmt))
17160 : {
17161 18189 : case OMP_FOR:
17162 30409 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17163 : {
17164 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17165 : OMP_CLAUSE_SCHEDULE))
17166 47 : error_at (EXPR_LOCATION (for_stmt),
17167 : "%qs clause may not appear on non-rectangular %qs",
17168 27 : "schedule", lang_GNU_Fortran () ? "do" : "for");
17169 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED))
17170 34 : error_at (EXPR_LOCATION (for_stmt),
17171 : "%qs clause may not appear on non-rectangular %qs",
17172 18 : "ordered", lang_GNU_Fortran () ? "do" : "for");
17173 : }
17174 : break;
17175 8219 : case OMP_DISTRIBUTE:
17176 9130 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)
17177 8219 : && omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17178 : OMP_CLAUSE_DIST_SCHEDULE))
17179 29 : error_at (EXPR_LOCATION (for_stmt),
17180 : "%qs clause may not appear on non-rectangular %qs",
17181 : "dist_schedule", "distribute");
17182 : break;
17183 : case OACC_LOOP:
17184 : ort = ORT_ACC;
17185 : break;
17186 1586 : case OMP_TASKLOOP:
17187 2523 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17188 : {
17189 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17190 : OMP_CLAUSE_GRAINSIZE))
17191 11 : error_at (EXPR_LOCATION (for_stmt),
17192 : "%qs clause may not appear on non-rectangular %qs",
17193 : "grainsize", "taskloop");
17194 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17195 : OMP_CLAUSE_NUM_TASKS))
17196 6 : error_at (EXPR_LOCATION (for_stmt),
17197 : "%qs clause may not appear on non-rectangular %qs",
17198 : "num_tasks", "taskloop");
17199 : }
17200 1586 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED))
17201 : ort = ORT_UNTIED_TASKLOOP;
17202 : else
17203 : ort = ORT_TASKLOOP;
17204 : break;
17205 10653 : case OMP_SIMD:
17206 10653 : ort = ORT_SIMD;
17207 10653 : break;
17208 2264 : case OMP_TILE:
17209 2264 : case OMP_UNROLL:
17210 2264 : gcc_assert (inner_for_stmt == NULL_TREE);
17211 2264 : return gimplify_omp_loop_xform (expr_p, pre_p);
17212 0 : default:
17213 0 : gcc_unreachable ();
17214 : }
17215 :
17216 : /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear
17217 : clause for the IV. */
17218 10700 : if (ort == ORT_SIMD && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17219 : {
17220 7825 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0);
17221 7825 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17222 7825 : decl = TREE_OPERAND (t, 0);
17223 18635 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
17224 11924 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17225 11924 : && OMP_CLAUSE_DECL (c) == decl)
17226 : {
17227 1114 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17228 1114 : break;
17229 : }
17230 : }
17231 :
17232 51199 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP)
17233 51523 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort,
17234 1910 : loop_p && TREE_CODE (for_stmt) != OMP_SIMD
17235 : ? OMP_LOOP : TREE_CODE (for_stmt));
17236 :
17237 51199 : if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE)
17238 8219 : gimplify_omp_ctxp->distribute = true;
17239 :
17240 : /* Handle OMP_FOR_INIT. */
17241 51199 : for_pre_body = NULL;
17242 51199 : if ((ort == ORT_SIMD
17243 40546 : || (inner_for_stmt && TREE_CODE (inner_for_stmt) == OMP_SIMD))
17244 61939 : && OMP_FOR_PRE_BODY (for_stmt))
17245 : {
17246 6784 : has_decl_expr = BITMAP_ALLOC (NULL);
17247 6784 : if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR
17248 6784 : && VAR_P (DECL_EXPR_DECL (OMP_FOR_PRE_BODY (for_stmt))))
17249 : {
17250 18 : t = OMP_FOR_PRE_BODY (for_stmt);
17251 18 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17252 : }
17253 6766 : else if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == STATEMENT_LIST)
17254 : {
17255 6764 : tree_stmt_iterator si;
17256 11234 : for (si = tsi_start (OMP_FOR_PRE_BODY (for_stmt)); !tsi_end_p (si);
17257 4470 : tsi_next (&si))
17258 : {
17259 4470 : t = tsi_stmt (si);
17260 4470 : if (TREE_CODE (t) == DECL_EXPR
17261 4470 : && VAR_P (DECL_EXPR_DECL (t)))
17262 4397 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17263 : }
17264 : }
17265 : }
17266 51199 : if (OMP_FOR_PRE_BODY (for_stmt))
17267 : {
17268 20979 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp)
17269 20254 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17270 : else
17271 : {
17272 725 : struct gimplify_omp_ctx ctx;
17273 725 : memset (&ctx, 0, sizeof (ctx));
17274 725 : ctx.region_type = ORT_NONE;
17275 725 : gimplify_omp_ctxp = &ctx;
17276 725 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17277 725 : gimplify_omp_ctxp = NULL;
17278 : }
17279 : }
17280 51199 : OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
17281 :
17282 51199 : if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
17283 13926 : for_stmt = inner_for_stmt;
17284 :
17285 : /* For taskloop, need to gimplify the start, end and step before the
17286 : taskloop, outside of the taskloop omp context. */
17287 51199 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17288 : {
17289 3458 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17290 : {
17291 1872 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17292 1872 : gimple_seq *for_pre_p = (gimple_seq_empty_p (for_pre_body)
17293 1872 : ? pre_p : &for_pre_body);
17294 1872 : tree type = TREE_TYPE (TREE_OPERAND (t, 0));
17295 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17296 : {
17297 34 : tree v = TREE_OPERAND (t, 1);
17298 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17299 : for_pre_p, orig_for_stmt);
17300 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17301 : for_pre_p, orig_for_stmt);
17302 : }
17303 : else
17304 1838 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17305 : orig_for_stmt);
17306 :
17307 : /* Handle OMP_FOR_COND. */
17308 1872 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17309 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17310 : {
17311 31 : tree v = TREE_OPERAND (t, 1);
17312 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17313 : for_pre_p, orig_for_stmt);
17314 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17315 : for_pre_p, orig_for_stmt);
17316 : }
17317 : else
17318 1841 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17319 : orig_for_stmt);
17320 :
17321 : /* Handle OMP_FOR_INCR. */
17322 1872 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17323 1872 : if (TREE_CODE (t) == MODIFY_EXPR)
17324 : {
17325 590 : decl = TREE_OPERAND (t, 0);
17326 590 : t = TREE_OPERAND (t, 1);
17327 590 : tree *tp = &TREE_OPERAND (t, 1);
17328 590 : if (TREE_CODE (t) == PLUS_EXPR && *tp == decl)
17329 22 : tp = &TREE_OPERAND (t, 0);
17330 :
17331 590 : gimplify_omp_taskloop_expr (NULL_TREE, tp, for_pre_p,
17332 : orig_for_stmt);
17333 : }
17334 : }
17335 :
17336 1586 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort,
17337 : OMP_TASKLOOP);
17338 : }
17339 :
17340 51199 : if (orig_for_stmt != for_stmt)
17341 13926 : gimplify_omp_ctxp->combined_loop = true;
17342 :
17343 51199 : for_body = NULL;
17344 51199 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17345 : == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
17346 51199 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17347 : == TREE_VEC_LENGTH (OMP_FOR_INCR (for_stmt)));
17348 :
17349 51199 : tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
17350 51199 : bool is_doacross = false;
17351 51199 : if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
17352 : find_standalone_omp_ordered, NULL))
17353 : {
17354 531 : OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
17355 531 : is_doacross = true;
17356 531 : int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
17357 531 : gimplify_omp_ctxp->loop_iter_var.create (len * 2);
17358 2200 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
17359 1669 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
17360 : {
17361 10 : error_at (OMP_CLAUSE_LOCATION (*pc),
17362 : "%<linear%> clause may not be specified together "
17363 : "with %<ordered%> clause if stand-alone %<ordered%> "
17364 : "construct is nested in it");
17365 10 : *pc = OMP_CLAUSE_CHAIN (*pc);
17366 : }
17367 : else
17368 1659 : pc = &OMP_CLAUSE_CHAIN (*pc);
17369 : }
17370 51199 : int collapse = 1, tile = 0;
17371 51199 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
17372 51199 : if (c)
17373 13727 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
17374 51199 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
17375 51199 : if (c)
17376 384 : tile = list_length (OMP_CLAUSE_TILE_LIST (c));
17377 51199 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
17378 51199 : hash_set<tree> *allocate_uids = NULL;
17379 51199 : if (c)
17380 : {
17381 275 : allocate_uids = new hash_set<tree>;
17382 1682 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17383 1132 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
17384 478 : allocate_uids->add (OMP_CLAUSE_DECL (c));
17385 : }
17386 124144 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17387 : {
17388 72945 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17389 72945 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17390 72945 : decl = TREE_OPERAND (t, 0);
17391 72945 : gcc_assert (DECL_P (decl));
17392 72945 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
17393 : || POINTER_TYPE_P (TREE_TYPE (decl)));
17394 72945 : if (is_doacross)
17395 : {
17396 1654 : if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt))
17397 : {
17398 960 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17399 960 : if (TREE_CODE (orig_decl) == TREE_LIST)
17400 : {
17401 15 : orig_decl = TREE_PURPOSE (orig_decl);
17402 15 : if (!orig_decl)
17403 0 : orig_decl = decl;
17404 : }
17405 960 : gimplify_omp_ctxp->loop_iter_var.quick_push (orig_decl);
17406 : }
17407 : else
17408 694 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17409 1654 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17410 : }
17411 :
17412 72945 : if (for_stmt == orig_for_stmt)
17413 : {
17414 50137 : tree orig_decl = decl;
17415 50137 : if (OMP_FOR_ORIG_DECLS (for_stmt))
17416 : {
17417 23916 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17418 23916 : if (TREE_CODE (orig_decl) == TREE_LIST)
17419 : {
17420 : orig_decl = TREE_PURPOSE (orig_decl);
17421 : if (!orig_decl)
17422 : orig_decl = decl;
17423 : }
17424 : }
17425 50137 : if (is_global_var (orig_decl) && DECL_THREAD_LOCAL_P (orig_decl))
17426 36 : error_at (EXPR_LOCATION (for_stmt),
17427 : "threadprivate iteration variable %qD", orig_decl);
17428 : }
17429 :
17430 : /* Make sure the iteration variable is private. */
17431 72945 : tree c = NULL_TREE;
17432 72945 : tree c2 = NULL_TREE;
17433 72945 : if (orig_for_stmt != for_stmt)
17434 : {
17435 : /* Preserve this information until we gimplify the inner simd. */
17436 22808 : if (has_decl_expr
17437 22808 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17438 3413 : TREE_PRIVATE (t) = 1;
17439 : }
17440 50137 : else if (ort == ORT_SIMD)
17441 : {
17442 15726 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17443 : (splay_tree_key) decl);
17444 15726 : omp_is_private (gimplify_omp_ctxp, decl,
17445 15726 : 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17446 : != 1));
17447 15726 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
17448 : {
17449 2518 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17450 2518 : if (n->value & GOVD_LASTPRIVATE_CONDITIONAL)
17451 0 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17452 : OMP_CLAUSE_LASTPRIVATE);
17453 0 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17454 : OMP_CLAUSE_LASTPRIVATE))
17455 0 : if (OMP_CLAUSE_DECL (c3) == decl)
17456 : {
17457 0 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17458 : "conditional %<lastprivate%> on loop "
17459 : "iterator %qD ignored", decl);
17460 0 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17461 0 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17462 : }
17463 : }
17464 13208 : else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1 && !loop_p)
17465 : {
17466 5637 : c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17467 5637 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17468 5637 : unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN;
17469 5637 : if ((has_decl_expr
17470 1309 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17471 6321 : || TREE_PRIVATE (t))
17472 : {
17473 2281 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17474 2281 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17475 : }
17476 5637 : struct gimplify_omp_ctx *outer
17477 5637 : = gimplify_omp_ctxp->outer_context;
17478 5637 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17479 : {
17480 2433 : if (outer->region_type == ORT_WORKSHARE
17481 2193 : && outer->combined_loop)
17482 : {
17483 2142 : n = splay_tree_lookup (outer->variables,
17484 : (splay_tree_key)decl);
17485 2142 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17486 : {
17487 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17488 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17489 : }
17490 : else
17491 : {
17492 2142 : struct gimplify_omp_ctx *octx = outer->outer_context;
17493 2142 : if (octx
17494 1714 : && octx->region_type == ORT_COMBINED_PARALLEL
17495 1476 : && octx->outer_context
17496 1209 : && (octx->outer_context->region_type
17497 : == ORT_WORKSHARE)
17498 1079 : && octx->outer_context->combined_loop)
17499 : {
17500 1079 : octx = octx->outer_context;
17501 1079 : n = splay_tree_lookup (octx->variables,
17502 : (splay_tree_key)decl);
17503 1079 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17504 : {
17505 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17506 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17507 : }
17508 : }
17509 : }
17510 : }
17511 : }
17512 :
17513 5637 : OMP_CLAUSE_DECL (c) = decl;
17514 5637 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17515 5637 : OMP_FOR_CLAUSES (for_stmt) = c;
17516 5637 : omp_add_variable (gimplify_omp_ctxp, decl, flags);
17517 5637 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17518 2433 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17519 : true);
17520 : }
17521 : else
17522 : {
17523 7571 : bool lastprivate
17524 : = (!has_decl_expr
17525 7571 : || !bitmap_bit_p (has_decl_expr, DECL_UID (decl)));
17526 7571 : if (TREE_PRIVATE (t))
17527 1787 : lastprivate = false;
17528 7571 : if (loop_p && OMP_FOR_ORIG_DECLS (for_stmt))
17529 : {
17530 509 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17531 509 : if (TREE_CODE (elt) == TREE_LIST && TREE_PURPOSE (elt))
17532 : lastprivate = false;
17533 : }
17534 :
17535 7571 : struct gimplify_omp_ctx *outer
17536 7571 : = gimplify_omp_ctxp->outer_context;
17537 7571 : if (outer && lastprivate)
17538 4887 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17539 : true);
17540 :
17541 9577 : c = build_omp_clause (input_location,
17542 : lastprivate ? OMP_CLAUSE_LASTPRIVATE
17543 : : OMP_CLAUSE_PRIVATE);
17544 7571 : OMP_CLAUSE_DECL (c) = decl;
17545 7571 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17546 7571 : OMP_FOR_CLAUSES (for_stmt) = c;
17547 7571 : omp_add_variable (gimplify_omp_ctxp, decl,
17548 : (lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE)
17549 : | GOVD_EXPLICIT | GOVD_SEEN);
17550 7571 : c = NULL_TREE;
17551 : }
17552 : }
17553 34411 : else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
17554 : {
17555 8735 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17556 8735 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17557 : (splay_tree_key) decl);
17558 8735 : if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL))
17559 80 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17560 : OMP_CLAUSE_LASTPRIVATE);
17561 80 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17562 : OMP_CLAUSE_LASTPRIVATE))
17563 40 : if (OMP_CLAUSE_DECL (c3) == decl)
17564 : {
17565 40 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17566 : "conditional %<lastprivate%> on loop "
17567 : "iterator %qD ignored", decl);
17568 40 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17569 40 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17570 : }
17571 : }
17572 : else
17573 25676 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
17574 :
17575 : /* If DECL is not a gimple register, create a temporary variable to act
17576 : as an iteration counter. This is valid, since DECL cannot be
17577 : modified in the body of the loop. Similarly for any iteration vars
17578 : in simd with collapse > 1 where the iterator vars must be
17579 : lastprivate. And similarly for vars mentioned in allocate clauses. */
17580 72945 : if (orig_for_stmt != for_stmt)
17581 22808 : var = decl;
17582 50137 : else if (!is_gimple_reg (decl)
17583 46870 : || (ort == ORT_SIMD
17584 14125 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
17585 89937 : || (allocate_uids && allocate_uids->contains (decl)))
17586 : {
17587 10369 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17588 : /* Make sure omp_add_variable is not called on it prematurely.
17589 : We call it ourselves a few lines later. */
17590 10369 : gimplify_omp_ctxp = NULL;
17591 10369 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17592 10369 : gimplify_omp_ctxp = ctx;
17593 10369 : TREE_OPERAND (t, 0) = var;
17594 :
17595 10369 : gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
17596 :
17597 10369 : if (ort == ORT_SIMD
17598 10369 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17599 : {
17600 770 : c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17601 770 : OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1;
17602 770 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1;
17603 770 : OMP_CLAUSE_DECL (c2) = var;
17604 770 : OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt);
17605 770 : OMP_FOR_CLAUSES (for_stmt) = c2;
17606 770 : omp_add_variable (gimplify_omp_ctxp, var,
17607 : GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
17608 770 : if (c == NULL_TREE)
17609 : {
17610 518 : c = c2;
17611 518 : c2 = NULL_TREE;
17612 : }
17613 : }
17614 : else
17615 9599 : omp_add_variable (gimplify_omp_ctxp, var,
17616 : GOVD_PRIVATE | GOVD_SEEN);
17617 : }
17618 : else
17619 : var = decl;
17620 :
17621 72945 : gimplify_omp_ctxp->in_for_exprs = true;
17622 72945 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17623 : {
17624 719 : tree lb = TREE_OPERAND (t, 1);
17625 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL,
17626 : is_gimple_val, fb_rvalue, false);
17627 719 : ret = MIN (ret, tret);
17628 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL,
17629 : is_gimple_val, fb_rvalue, false);
17630 : }
17631 : else
17632 72226 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17633 : is_gimple_val, fb_rvalue, false);
17634 72945 : gimplify_omp_ctxp->in_for_exprs = false;
17635 72945 : ret = MIN (ret, tret);
17636 72945 : if (ret == GS_ERROR)
17637 : return ret;
17638 :
17639 : /* Handle OMP_FOR_COND. */
17640 72945 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17641 72945 : gcc_assert (COMPARISON_CLASS_P (t));
17642 72945 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17643 :
17644 72945 : gimplify_omp_ctxp->in_for_exprs = true;
17645 72945 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17646 : {
17647 599 : tree ub = TREE_OPERAND (t, 1);
17648 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL,
17649 : is_gimple_val, fb_rvalue, false);
17650 599 : ret = MIN (ret, tret);
17651 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL,
17652 : is_gimple_val, fb_rvalue, false);
17653 : }
17654 : else
17655 72346 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17656 : is_gimple_val, fb_rvalue, false);
17657 72945 : gimplify_omp_ctxp->in_for_exprs = false;
17658 72945 : ret = MIN (ret, tret);
17659 :
17660 : /* Handle OMP_FOR_INCR. */
17661 72945 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17662 72945 : switch (TREE_CODE (t))
17663 : {
17664 35676 : case PREINCREMENT_EXPR:
17665 35676 : case POSTINCREMENT_EXPR:
17666 35676 : {
17667 35676 : tree decl = TREE_OPERAND (t, 0);
17668 : /* c_omp_for_incr_canonicalize_ptr() should have been
17669 : called to massage things appropriately. */
17670 35676 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17671 :
17672 35676 : if (orig_for_stmt != for_stmt)
17673 : break;
17674 25291 : t = build_int_cst (TREE_TYPE (decl), 1);
17675 25291 : if (c)
17676 4470 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17677 25291 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17678 25291 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17679 25291 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17680 25291 : break;
17681 : }
17682 :
17683 3830 : case PREDECREMENT_EXPR:
17684 3830 : case POSTDECREMENT_EXPR:
17685 : /* c_omp_for_incr_canonicalize_ptr() should have been
17686 : called to massage things appropriately. */
17687 3830 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17688 3830 : if (orig_for_stmt != for_stmt)
17689 : break;
17690 1992 : t = build_int_cst (TREE_TYPE (decl), -1);
17691 1992 : if (c)
17692 112 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17693 1992 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17694 1992 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17695 1992 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17696 1992 : break;
17697 :
17698 33439 : case MODIFY_EXPR:
17699 33439 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17700 33439 : TREE_OPERAND (t, 0) = var;
17701 :
17702 33439 : t = TREE_OPERAND (t, 1);
17703 33439 : switch (TREE_CODE (t))
17704 : {
17705 26507 : case PLUS_EXPR:
17706 26507 : if (TREE_OPERAND (t, 1) == decl)
17707 : {
17708 215 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
17709 215 : TREE_OPERAND (t, 0) = var;
17710 215 : break;
17711 : }
17712 :
17713 : /* Fallthru. */
17714 33224 : case MINUS_EXPR:
17715 33224 : case POINTER_PLUS_EXPR:
17716 33224 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17717 33224 : TREE_OPERAND (t, 0) = var;
17718 33224 : break;
17719 0 : default:
17720 0 : gcc_unreachable ();
17721 : }
17722 :
17723 33439 : gimplify_omp_ctxp->in_for_exprs = true;
17724 33439 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17725 : is_gimple_val, fb_rvalue, false);
17726 33439 : ret = MIN (ret, tret);
17727 33439 : if (c)
17728 : {
17729 1573 : tree step = TREE_OPERAND (t, 1);
17730 1573 : tree stept = TREE_TYPE (decl);
17731 1573 : if (POINTER_TYPE_P (stept))
17732 280 : stept = sizetype;
17733 1573 : step = fold_convert (stept, step);
17734 1573 : if (TREE_CODE (t) == MINUS_EXPR)
17735 295 : step = fold_build1 (NEGATE_EXPR, stept, step);
17736 1573 : OMP_CLAUSE_LINEAR_STEP (c) = step;
17737 1573 : if (step != TREE_OPERAND (t, 1))
17738 : {
17739 295 : tret = gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c),
17740 : &for_pre_body, NULL,
17741 : is_gimple_val, fb_rvalue, false);
17742 295 : ret = MIN (ret, tret);
17743 : }
17744 : }
17745 33439 : gimplify_omp_ctxp->in_for_exprs = false;
17746 33439 : break;
17747 :
17748 0 : default:
17749 0 : gcc_unreachable ();
17750 : }
17751 :
17752 72945 : if (c2)
17753 : {
17754 252 : gcc_assert (c);
17755 252 : OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
17756 : }
17757 :
17758 72945 : if ((var != decl || collapse > 1 || tile) && orig_for_stmt == for_stmt)
17759 : {
17760 86698 : for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
17761 65136 : if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
17762 16218 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
17763 56127 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17764 2159 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)
17765 1373 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
17766 75496 : && OMP_CLAUSE_DECL (c) == decl)
17767 : {
17768 7535 : if (is_doacross && (collapse == 1 || i >= collapse))
17769 : t = var;
17770 : else
17771 : {
17772 7462 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17773 7462 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17774 7462 : gcc_assert (TREE_OPERAND (t, 0) == var);
17775 7462 : t = TREE_OPERAND (t, 1);
17776 7462 : gcc_assert (TREE_CODE (t) == PLUS_EXPR
17777 : || TREE_CODE (t) == MINUS_EXPR
17778 : || TREE_CODE (t) == POINTER_PLUS_EXPR);
17779 7462 : gcc_assert (TREE_OPERAND (t, 0) == var);
17780 14822 : t = build2 (TREE_CODE (t), TREE_TYPE (decl),
17781 : is_doacross ? var : decl,
17782 7462 : TREE_OPERAND (t, 1));
17783 : }
17784 7535 : gimple_seq *seq;
17785 7535 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
17786 6939 : seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
17787 : else
17788 596 : seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c);
17789 7535 : push_gimplify_context ();
17790 7535 : gimplify_assign (decl, t, seq);
17791 7535 : gimple *bind = NULL;
17792 7535 : if (gimplify_ctxp->temps)
17793 : {
17794 2072 : bind = gimple_build_bind (NULL_TREE, *seq, NULL_TREE);
17795 2072 : *seq = NULL;
17796 2072 : gimplify_seq_add_stmt (seq, bind);
17797 : }
17798 7535 : pop_gimplify_context (bind);
17799 : }
17800 : }
17801 72945 : if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl)
17802 2609 : for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17803 : {
17804 1197 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17805 1197 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17806 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17807 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17808 336 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17809 1197 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17810 1197 : gcc_assert (COMPARISON_CLASS_P (t));
17811 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17812 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17813 343 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17814 : }
17815 : }
17816 :
17817 51199 : BITMAP_FREE (has_decl_expr);
17818 51474 : delete allocate_uids;
17819 :
17820 51199 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17821 49613 : || (loop_p && orig_for_stmt == for_stmt))
17822 : {
17823 2642 : push_gimplify_context ();
17824 2642 : if (TREE_CODE (OMP_FOR_BODY (orig_for_stmt)) != BIND_EXPR)
17825 : {
17826 1891 : OMP_FOR_BODY (orig_for_stmt)
17827 1891 : = build3 (BIND_EXPR, void_type_node, NULL,
17828 1891 : OMP_FOR_BODY (orig_for_stmt), NULL);
17829 1891 : TREE_SIDE_EFFECTS (OMP_FOR_BODY (orig_for_stmt)) = 1;
17830 : }
17831 : }
17832 :
17833 51199 : gimple *g = gimplify_and_return_first (OMP_FOR_BODY (orig_for_stmt),
17834 : &for_body);
17835 :
17836 51199 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17837 49613 : || (loop_p && orig_for_stmt == for_stmt))
17838 : {
17839 2642 : if (gimple_code (g) == GIMPLE_BIND)
17840 2642 : pop_gimplify_context (g);
17841 : else
17842 0 : pop_gimplify_context (NULL);
17843 : }
17844 :
17845 51199 : if (orig_for_stmt != for_stmt)
17846 36734 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17847 : {
17848 22808 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17849 22808 : decl = TREE_OPERAND (t, 0);
17850 22808 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17851 22808 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17852 772 : gimplify_omp_ctxp = ctx->outer_context;
17853 22808 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17854 22808 : gimplify_omp_ctxp = ctx;
17855 22808 : omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
17856 22808 : TREE_OPERAND (t, 0) = var;
17857 22808 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17858 22808 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17859 22808 : TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
17860 22808 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
17861 791 : for (int j = i + 1;
17862 791 : j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17863 : {
17864 377 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17865 377 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17866 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17867 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17868 : {
17869 133 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17870 133 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17871 : }
17872 377 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17873 377 : gcc_assert (COMPARISON_CLASS_P (t));
17874 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17875 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17876 : {
17877 67 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17878 67 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17879 : }
17880 : }
17881 : }
17882 :
17883 51199 : gimplify_adjust_omp_clauses (pre_p, for_body,
17884 : &OMP_FOR_CLAUSES (orig_for_stmt),
17885 51199 : TREE_CODE (orig_for_stmt));
17886 :
17887 51199 : int kind;
17888 51199 : switch (TREE_CODE (orig_for_stmt))
17889 : {
17890 : case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
17891 10653 : case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
17892 8219 : case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
17893 1586 : case OMP_TASKLOOP: kind = GF_OMP_FOR_KIND_TASKLOOP; break;
17894 12552 : case OACC_LOOP: kind = GF_OMP_FOR_KIND_OACC_LOOP; break;
17895 0 : default:
17896 0 : gcc_unreachable ();
17897 : }
17898 51199 : if (loop_p && kind == GF_OMP_FOR_KIND_SIMD)
17899 : {
17900 1056 : gimplify_seq_add_seq (pre_p, for_pre_body);
17901 1056 : for_pre_body = NULL;
17902 : }
17903 51199 : gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
17904 51199 : TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
17905 : for_pre_body);
17906 51199 : if (orig_for_stmt != for_stmt)
17907 13926 : gimple_omp_for_set_combined_p (gfor, true);
17908 51199 : if (gimplify_omp_ctxp
17909 42571 : && (gimplify_omp_ctxp->combined_loop
17910 35040 : || (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
17911 12301 : && gimplify_omp_ctxp->outer_context
17912 7858 : && gimplify_omp_ctxp->outer_context->combined_loop)))
17913 : {
17914 13926 : gimple_omp_for_set_combined_into_p (gfor, true);
17915 13926 : if (gimplify_omp_ctxp->combined_loop)
17916 7531 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_SIMD);
17917 : else
17918 6395 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_FOR);
17919 : }
17920 :
17921 124144 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17922 : {
17923 72945 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17924 72945 : gimple_omp_for_set_index (gfor, i, TREE_OPERAND (t, 0));
17925 72945 : gimple_omp_for_set_initial (gfor, i, TREE_OPERAND (t, 1));
17926 72945 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17927 72945 : gimple_omp_for_set_cond (gfor, i, TREE_CODE (t));
17928 72945 : gimple_omp_for_set_final (gfor, i, TREE_OPERAND (t, 1));
17929 72945 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17930 72945 : gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1));
17931 : }
17932 :
17933 : /* OMP_TASKLOOP is gimplified as two GIMPLE_OMP_FOR taskloop
17934 : constructs with GIMPLE_OMP_TASK sandwiched in between them.
17935 : The outer taskloop stands for computing the number of iterations,
17936 : counts for collapsed loops and holding taskloop specific clauses.
17937 : The task construct stands for the effect of data sharing on the
17938 : explicit task it creates and the inner taskloop stands for expansion
17939 : of the static loop inside of the explicit task construct. */
17940 51199 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17941 : {
17942 1586 : tree *gfor_clauses_ptr = gimple_omp_for_clauses_ptr (gfor);
17943 1586 : tree task_clauses = NULL_TREE;
17944 1586 : tree c = *gfor_clauses_ptr;
17945 1586 : tree *gtask_clauses_ptr = &task_clauses;
17946 1586 : tree outer_for_clauses = NULL_TREE;
17947 1586 : tree *gforo_clauses_ptr = &outer_for_clauses;
17948 1586 : bitmap lastprivate_uids = NULL;
17949 1586 : if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
17950 : {
17951 36 : c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
17952 36 : if (c)
17953 : {
17954 18 : lastprivate_uids = BITMAP_ALLOC (NULL);
17955 54 : for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
17956 : OMP_CLAUSE_LASTPRIVATE))
17957 18 : bitmap_set_bit (lastprivate_uids,
17958 18 : DECL_UID (OMP_CLAUSE_DECL (c)));
17959 : }
17960 36 : c = *gfor_clauses_ptr;
17961 : }
17962 12252 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17963 10666 : switch (OMP_CLAUSE_CODE (c))
17964 : {
17965 : /* These clauses are allowed on task, move them there. */
17966 6228 : case OMP_CLAUSE_SHARED:
17967 6228 : case OMP_CLAUSE_FIRSTPRIVATE:
17968 6228 : case OMP_CLAUSE_DEFAULT:
17969 6228 : case OMP_CLAUSE_IF:
17970 6228 : case OMP_CLAUSE_UNTIED:
17971 6228 : case OMP_CLAUSE_FINAL:
17972 6228 : case OMP_CLAUSE_MERGEABLE:
17973 6228 : case OMP_CLAUSE_PRIORITY:
17974 6228 : case OMP_CLAUSE_REDUCTION:
17975 6228 : case OMP_CLAUSE_IN_REDUCTION:
17976 6228 : *gtask_clauses_ptr = c;
17977 6228 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17978 6228 : break;
17979 2068 : case OMP_CLAUSE_PRIVATE:
17980 2068 : if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
17981 : {
17982 : /* We want private on outer for and firstprivate
17983 : on task. */
17984 26 : *gtask_clauses_ptr
17985 26 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
17986 : OMP_CLAUSE_FIRSTPRIVATE);
17987 26 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
17988 26 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
17989 : openacc);
17990 26 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
17991 26 : *gforo_clauses_ptr = c;
17992 26 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17993 : }
17994 : else
17995 : {
17996 2042 : *gtask_clauses_ptr = c;
17997 2042 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17998 : }
17999 : break;
18000 : /* These clauses go into outer taskloop clauses. */
18001 533 : case OMP_CLAUSE_GRAINSIZE:
18002 533 : case OMP_CLAUSE_NUM_TASKS:
18003 533 : case OMP_CLAUSE_NOGROUP:
18004 533 : *gforo_clauses_ptr = c;
18005 533 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18006 533 : break;
18007 : /* Collapse clause we duplicate on both taskloops. */
18008 584 : case OMP_CLAUSE_COLLAPSE:
18009 584 : *gfor_clauses_ptr = c;
18010 584 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18011 584 : *gforo_clauses_ptr = copy_node (c);
18012 584 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18013 584 : break;
18014 : /* For lastprivate, keep the clause on inner taskloop, and add
18015 : a shared clause on task. If the same decl is also firstprivate,
18016 : add also firstprivate clause on the inner taskloop. */
18017 1191 : case OMP_CLAUSE_LASTPRIVATE:
18018 1191 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18019 : {
18020 : /* For taskloop C++ lastprivate IVs, we want:
18021 : 1) private on outer taskloop
18022 : 2) firstprivate and shared on task
18023 : 3) lastprivate on inner taskloop */
18024 38 : *gtask_clauses_ptr
18025 38 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18026 : OMP_CLAUSE_FIRSTPRIVATE);
18027 38 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18028 38 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
18029 : openacc);
18030 38 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18031 38 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
18032 38 : *gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18033 : OMP_CLAUSE_PRIVATE);
18034 38 : OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
18035 38 : OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
18036 38 : TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
18037 38 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18038 : }
18039 1191 : *gfor_clauses_ptr = c;
18040 1191 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18041 1191 : *gtask_clauses_ptr
18042 1191 : = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_SHARED);
18043 1191 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18044 1191 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
18045 312 : OMP_CLAUSE_SHARED_FIRSTPRIVATE (*gtask_clauses_ptr) = 1;
18046 1191 : gtask_clauses_ptr
18047 1191 : = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18048 1191 : break;
18049 : /* Allocate clause we duplicate on task and inner taskloop
18050 : if the decl is lastprivate, otherwise just put on task. */
18051 62 : case OMP_CLAUSE_ALLOCATE:
18052 62 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
18053 62 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
18054 : {
18055 : /* Additionally, put firstprivate clause on task
18056 : for the allocator if it is not constant. */
18057 34 : *gtask_clauses_ptr
18058 34 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18059 : OMP_CLAUSE_FIRSTPRIVATE);
18060 34 : OMP_CLAUSE_DECL (*gtask_clauses_ptr)
18061 34 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
18062 34 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18063 : }
18064 62 : if (lastprivate_uids
18065 97 : && bitmap_bit_p (lastprivate_uids,
18066 35 : DECL_UID (OMP_CLAUSE_DECL (c))))
18067 : {
18068 17 : *gfor_clauses_ptr = c;
18069 17 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18070 17 : *gtask_clauses_ptr = copy_node (c);
18071 17 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18072 : }
18073 : else
18074 : {
18075 45 : *gtask_clauses_ptr = c;
18076 45 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18077 : }
18078 : break;
18079 0 : default:
18080 0 : gcc_unreachable ();
18081 : }
18082 1586 : *gfor_clauses_ptr = NULL_TREE;
18083 1586 : *gtask_clauses_ptr = NULL_TREE;
18084 1586 : *gforo_clauses_ptr = NULL_TREE;
18085 1586 : BITMAP_FREE (lastprivate_uids);
18086 1586 : gimple_set_location (gfor, input_location);
18087 1586 : g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
18088 1586 : g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
18089 : NULL_TREE, NULL_TREE, NULL_TREE);
18090 1586 : gimple_set_location (g, input_location);
18091 1586 : gimple_omp_task_set_taskloop_p (g, true);
18092 1586 : g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
18093 1586 : gomp_for *gforo
18094 1586 : = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
18095 : gimple_omp_for_collapse (gfor),
18096 : gimple_omp_for_pre_body (gfor));
18097 1586 : gimple_omp_for_set_pre_body (gfor, NULL);
18098 1586 : gimple_omp_for_set_combined_p (gforo, true);
18099 1586 : gimple_omp_for_set_combined_into_p (gfor, true);
18100 3458 : for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
18101 : {
18102 1872 : tree type = TREE_TYPE (gimple_omp_for_index (gfor, i));
18103 1872 : tree v = create_tmp_var (type);
18104 1872 : gimple_omp_for_set_index (gforo, i, v);
18105 1872 : t = unshare_expr (gimple_omp_for_initial (gfor, i));
18106 1872 : gimple_omp_for_set_initial (gforo, i, t);
18107 1872 : gimple_omp_for_set_cond (gforo, i,
18108 : gimple_omp_for_cond (gfor, i));
18109 1872 : t = unshare_expr (gimple_omp_for_final (gfor, i));
18110 1872 : gimple_omp_for_set_final (gforo, i, t);
18111 1872 : t = unshare_expr (gimple_omp_for_incr (gfor, i));
18112 1872 : gcc_assert (TREE_OPERAND (t, 0) == gimple_omp_for_index (gfor, i));
18113 1872 : TREE_OPERAND (t, 0) = v;
18114 1872 : gimple_omp_for_set_incr (gforo, i, t);
18115 1872 : t = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
18116 1872 : OMP_CLAUSE_DECL (t) = v;
18117 1872 : OMP_CLAUSE_CHAIN (t) = gimple_omp_for_clauses (gforo);
18118 1872 : gimple_omp_for_set_clauses (gforo, t);
18119 1872 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
18120 : {
18121 90 : tree *p1 = NULL, *p2 = NULL;
18122 90 : t = gimple_omp_for_initial (gforo, i);
18123 90 : if (TREE_CODE (t) == TREE_VEC)
18124 34 : p1 = &TREE_VEC_ELT (t, 0);
18125 90 : t = gimple_omp_for_final (gforo, i);
18126 90 : if (TREE_CODE (t) == TREE_VEC)
18127 : {
18128 31 : if (p1)
18129 23 : p2 = &TREE_VEC_ELT (t, 0);
18130 : else
18131 8 : p1 = &TREE_VEC_ELT (t, 0);
18132 : }
18133 90 : if (p1)
18134 : {
18135 : int j;
18136 58 : for (j = 0; j < i; j++)
18137 58 : if (*p1 == gimple_omp_for_index (gfor, j))
18138 : {
18139 42 : *p1 = gimple_omp_for_index (gforo, j);
18140 42 : if (p2)
18141 23 : *p2 = *p1;
18142 : break;
18143 : }
18144 42 : gcc_assert (j < i);
18145 : }
18146 : }
18147 : }
18148 1586 : gimplify_seq_add_stmt (pre_p, gforo);
18149 : }
18150 : else
18151 49613 : gimplify_seq_add_stmt (pre_p, gfor);
18152 :
18153 51199 : if (TREE_CODE (orig_for_stmt) == OMP_FOR)
18154 : {
18155 18189 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
18156 18189 : unsigned lastprivate_conditional = 0;
18157 18189 : while (ctx
18158 18225 : && (ctx->region_type == ORT_TARGET_DATA
18159 14187 : || ctx->region_type == ORT_TASKGROUP))
18160 36 : ctx = ctx->outer_context;
18161 18189 : if (ctx && (ctx->region_type & ORT_PARALLEL) != 0)
18162 13927 : for (tree c = gimple_omp_for_clauses (gfor);
18163 63183 : c; c = OMP_CLAUSE_CHAIN (c))
18164 49256 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18165 49256 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18166 158 : ++lastprivate_conditional;
18167 13927 : if (lastprivate_conditional)
18168 : {
18169 118 : struct omp_for_data fd;
18170 118 : omp_extract_for_data (gfor, &fd, NULL);
18171 118 : tree type = build_array_type_nelts (unsigned_type_for (fd.iter_type),
18172 118 : lastprivate_conditional);
18173 118 : tree var = create_tmp_var_raw (type);
18174 118 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
18175 118 : OMP_CLAUSE_DECL (c) = var;
18176 118 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18177 118 : gimple_omp_for_set_clauses (gfor, c);
18178 118 : omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
18179 : }
18180 : }
18181 33010 : else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
18182 : {
18183 10653 : unsigned lastprivate_conditional = 0;
18184 49159 : for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
18185 38506 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18186 38506 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18187 119 : ++lastprivate_conditional;
18188 10653 : if (lastprivate_conditional)
18189 : {
18190 91 : struct omp_for_data fd;
18191 91 : omp_extract_for_data (gfor, &fd, NULL);
18192 91 : tree type = unsigned_type_for (fd.iter_type);
18193 301 : while (lastprivate_conditional--)
18194 : {
18195 119 : tree c = build_omp_clause (UNKNOWN_LOCATION,
18196 : OMP_CLAUSE__CONDTEMP_);
18197 119 : OMP_CLAUSE_DECL (c) = create_tmp_var (type);
18198 119 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18199 119 : gimple_omp_for_set_clauses (gfor, c);
18200 : }
18201 : }
18202 : }
18203 :
18204 51199 : if (ret != GS_ALL_DONE)
18205 : return GS_ERROR;
18206 51199 : *expr_p = NULL_TREE;
18207 51199 : return GS_ALL_DONE;
18208 : }
18209 :
18210 : /* Helper for gimplify_omp_loop, called through walk_tree. */
18211 :
18212 : static tree
18213 294 : note_no_context_vars (tree *tp, int *, void *data)
18214 : {
18215 294 : if (VAR_P (*tp)
18216 56 : && DECL_CONTEXT (*tp) == NULL_TREE
18217 309 : && !is_global_var (*tp))
18218 : {
18219 15 : vec<tree> *d = (vec<tree> *) data;
18220 15 : d->safe_push (*tp);
18221 15 : DECL_CONTEXT (*tp) = current_function_decl;
18222 : }
18223 294 : return NULL_TREE;
18224 : }
18225 :
18226 : /* Gimplify the gross structure of an OMP_LOOP statement. */
18227 :
18228 : static enum gimplify_status
18229 1056 : gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
18230 : {
18231 1056 : tree for_stmt = *expr_p;
18232 1056 : tree clauses = OMP_FOR_CLAUSES (for_stmt);
18233 1056 : struct gimplify_omp_ctx *octx = gimplify_omp_ctxp;
18234 1056 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18235 1056 : int i;
18236 :
18237 1056 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
18238 1056 : if (*expr_p != for_stmt)
18239 : return GS_OK;
18240 :
18241 : /* If order is not present, the behavior is as if order(concurrent)
18242 : appeared. */
18243 1056 : tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER);
18244 1056 : if (order == NULL_TREE)
18245 : {
18246 799 : order = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_ORDER);
18247 799 : OMP_CLAUSE_CHAIN (order) = clauses;
18248 799 : OMP_FOR_CLAUSES (for_stmt) = clauses = order;
18249 : }
18250 :
18251 1056 : tree bind = omp_find_clause (clauses, OMP_CLAUSE_BIND);
18252 1056 : if (bind == NULL_TREE)
18253 : {
18254 574 : if (!flag_openmp) /* flag_openmp_simd */
18255 : ;
18256 557 : else if (octx && (octx->region_type & ORT_TEAMS) != 0)
18257 : kind = OMP_CLAUSE_BIND_TEAMS;
18258 327 : else if (octx && (octx->region_type & ORT_PARALLEL) != 0)
18259 : kind = OMP_CLAUSE_BIND_PARALLEL;
18260 : else
18261 : {
18262 187 : for (; octx; octx = octx->outer_context)
18263 : {
18264 79 : if ((octx->region_type & ORT_ACC) != 0
18265 79 : || octx->region_type == ORT_NONE
18266 79 : || octx->region_type == ORT_IMPLICIT_TARGET)
18267 0 : continue;
18268 : break;
18269 : }
18270 187 : if (octx == NULL && !in_omp_construct)
18271 4 : error_at (EXPR_LOCATION (for_stmt),
18272 : "%<bind%> clause not specified on a %<loop%> "
18273 : "construct not nested inside another OpenMP construct");
18274 : }
18275 574 : bind = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_BIND);
18276 574 : OMP_CLAUSE_CHAIN (bind) = clauses;
18277 574 : OMP_CLAUSE_BIND_KIND (bind) = kind;
18278 574 : OMP_FOR_CLAUSES (for_stmt) = bind;
18279 : }
18280 : else
18281 482 : switch (OMP_CLAUSE_BIND_KIND (bind))
18282 : {
18283 : case OMP_CLAUSE_BIND_THREAD:
18284 : break;
18285 166 : case OMP_CLAUSE_BIND_PARALLEL:
18286 166 : if (!flag_openmp) /* flag_openmp_simd */
18287 : {
18288 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18289 0 : break;
18290 : }
18291 240 : for (; octx; octx = octx->outer_context)
18292 78 : if (octx->region_type == ORT_SIMD
18293 78 : && omp_find_clause (octx->clauses, OMP_CLAUSE_BIND) == NULL_TREE)
18294 : {
18295 4 : error_at (EXPR_LOCATION (for_stmt),
18296 : "%<bind(parallel)%> on a %<loop%> construct nested "
18297 : "inside %<simd%> construct");
18298 4 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18299 4 : break;
18300 : }
18301 : kind = OMP_CLAUSE_BIND_PARALLEL;
18302 : break;
18303 162 : case OMP_CLAUSE_BIND_TEAMS:
18304 162 : if (!flag_openmp) /* flag_openmp_simd */
18305 : {
18306 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18307 0 : break;
18308 : }
18309 162 : if ((octx
18310 128 : && octx->region_type != ORT_IMPLICIT_TARGET
18311 111 : && octx->region_type != ORT_NONE
18312 111 : && (octx->region_type & ORT_TEAMS) == 0)
18313 110 : || in_omp_construct)
18314 : {
18315 64 : error_at (EXPR_LOCATION (for_stmt),
18316 : "%<bind(teams)%> on a %<loop%> region not strictly "
18317 : "nested inside of a %<teams%> region");
18318 64 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18319 64 : break;
18320 : }
18321 : kind = OMP_CLAUSE_BIND_TEAMS;
18322 : break;
18323 0 : default:
18324 0 : gcc_unreachable ();
18325 : }
18326 :
18327 4280 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
18328 3224 : switch (OMP_CLAUSE_CODE (*pc))
18329 : {
18330 343 : case OMP_CLAUSE_REDUCTION:
18331 343 : if (OMP_CLAUSE_REDUCTION_INSCAN (*pc))
18332 : {
18333 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18334 : "%<inscan%> %<reduction%> clause on "
18335 : "%qs construct", "loop");
18336 4 : OMP_CLAUSE_REDUCTION_INSCAN (*pc) = 0;
18337 : }
18338 343 : if (OMP_CLAUSE_REDUCTION_TASK (*pc))
18339 : {
18340 8 : error_at (OMP_CLAUSE_LOCATION (*pc),
18341 : "invalid %<task%> reduction modifier on construct "
18342 : "other than %<parallel%>, %qs or %<sections%>",
18343 4 : lang_GNU_Fortran () ? "do" : "for");
18344 4 : OMP_CLAUSE_REDUCTION_TASK (*pc) = 0;
18345 : }
18346 343 : pc = &OMP_CLAUSE_CHAIN (*pc);
18347 343 : break;
18348 : case OMP_CLAUSE_LASTPRIVATE:
18349 293 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18350 : {
18351 289 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
18352 289 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
18353 289 : if (OMP_CLAUSE_DECL (*pc) == TREE_OPERAND (t, 0))
18354 : break;
18355 26 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18356 25 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18357 : i)) == TREE_LIST
18358 48 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18359 : i)))
18360 : {
18361 22 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18362 22 : if (OMP_CLAUSE_DECL (*pc) == TREE_PURPOSE (orig))
18363 : break;
18364 : }
18365 : }
18366 289 : if (i == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
18367 : {
18368 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18369 : "%<lastprivate%> clause on a %<loop%> construct refers "
18370 : "to a variable %qD which is not the loop iterator",
18371 4 : OMP_CLAUSE_DECL (*pc));
18372 4 : *pc = OMP_CLAUSE_CHAIN (*pc);
18373 4 : break;
18374 : }
18375 285 : pc = &OMP_CLAUSE_CHAIN (*pc);
18376 285 : break;
18377 2592 : default:
18378 2592 : pc = &OMP_CLAUSE_CHAIN (*pc);
18379 2592 : break;
18380 : }
18381 :
18382 1056 : TREE_SET_CODE (for_stmt, OMP_SIMD);
18383 :
18384 1056 : int last;
18385 1056 : switch (kind)
18386 : {
18387 : case OMP_CLAUSE_BIND_THREAD: last = 0; break;
18388 414 : case OMP_CLAUSE_BIND_PARALLEL: last = 1; break;
18389 220 : case OMP_CLAUSE_BIND_TEAMS: last = 2; break;
18390 : }
18391 1910 : for (int pass = 1; pass <= last; pass++)
18392 : {
18393 854 : if (pass == 2)
18394 : {
18395 220 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL,
18396 : make_node (BLOCK));
18397 220 : append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind));
18398 220 : *expr_p = make_node (OMP_PARALLEL);
18399 220 : TREE_TYPE (*expr_p) = void_type_node;
18400 220 : OMP_PARALLEL_BODY (*expr_p) = bind;
18401 220 : OMP_PARALLEL_COMBINED (*expr_p) = 1;
18402 220 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (for_stmt));
18403 220 : tree *pc = &OMP_PARALLEL_CLAUSES (*expr_p);
18404 452 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18405 232 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18406 232 : && (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i))
18407 : == TREE_LIST))
18408 : {
18409 16 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18410 16 : if (TREE_PURPOSE (elt) && TREE_VALUE (elt))
18411 : {
18412 13 : *pc = build_omp_clause (UNKNOWN_LOCATION,
18413 : OMP_CLAUSE_FIRSTPRIVATE);
18414 13 : OMP_CLAUSE_DECL (*pc) = TREE_VALUE (elt);
18415 13 : pc = &OMP_CLAUSE_CHAIN (*pc);
18416 : }
18417 : }
18418 : }
18419 854 : tree t = make_node (pass == 2 ? OMP_DISTRIBUTE : OMP_FOR);
18420 854 : tree *pc = &OMP_FOR_CLAUSES (t);
18421 854 : TREE_TYPE (t) = void_type_node;
18422 854 : OMP_FOR_BODY (t) = *expr_p;
18423 854 : SET_EXPR_LOCATION (t, EXPR_LOCATION (for_stmt));
18424 3968 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
18425 3114 : switch (OMP_CLAUSE_CODE (c))
18426 : {
18427 1992 : case OMP_CLAUSE_BIND:
18428 1992 : case OMP_CLAUSE_ORDER:
18429 1992 : case OMP_CLAUSE_COLLAPSE:
18430 1992 : *pc = copy_node (c);
18431 1992 : pc = &OMP_CLAUSE_CHAIN (*pc);
18432 1992 : break;
18433 : case OMP_CLAUSE_PRIVATE:
18434 : case OMP_CLAUSE_FIRSTPRIVATE:
18435 : /* Only needed on innermost. */
18436 : break;
18437 351 : case OMP_CLAUSE_LASTPRIVATE:
18438 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) && pass != last)
18439 : {
18440 7 : *pc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18441 : OMP_CLAUSE_FIRSTPRIVATE);
18442 7 : OMP_CLAUSE_DECL (*pc) = OMP_CLAUSE_DECL (c);
18443 7 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18444 7 : pc = &OMP_CLAUSE_CHAIN (*pc);
18445 : }
18446 351 : *pc = copy_node (c);
18447 351 : OMP_CLAUSE_LASTPRIVATE_STMT (*pc) = NULL_TREE;
18448 351 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18449 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18450 : {
18451 22 : if (pass != last)
18452 7 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (*pc) = 1;
18453 : else
18454 15 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18455 22 : OMP_CLAUSE_LASTPRIVATE_LOOP_IV (*pc) = 0;
18456 : }
18457 351 : pc = &OMP_CLAUSE_CHAIN (*pc);
18458 351 : break;
18459 463 : case OMP_CLAUSE_REDUCTION:
18460 463 : *pc = copy_node (c);
18461 463 : OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c));
18462 463 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18463 463 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc))
18464 : {
18465 15 : auto_vec<tree> no_context_vars;
18466 15 : int walk_subtrees = 0;
18467 15 : note_no_context_vars (&OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18468 : &walk_subtrees, &no_context_vars);
18469 15 : if (tree p = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c))
18470 0 : note_no_context_vars (&p, &walk_subtrees, &no_context_vars);
18471 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (c),
18472 : note_no_context_vars,
18473 : &no_context_vars);
18474 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (c),
18475 : note_no_context_vars,
18476 : &no_context_vars);
18477 :
18478 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)
18479 15 : = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
18480 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18481 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)
18482 0 : = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c));
18483 :
18484 15 : hash_map<tree, tree> decl_map;
18485 15 : decl_map.put (OMP_CLAUSE_DECL (c), OMP_CLAUSE_DECL (c));
18486 15 : decl_map.put (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18487 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc));
18488 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18489 0 : decl_map.put (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
18490 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc));
18491 :
18492 15 : copy_body_data id;
18493 15 : memset (&id, 0, sizeof (id));
18494 15 : id.src_fn = current_function_decl;
18495 15 : id.dst_fn = current_function_decl;
18496 15 : id.src_cfun = cfun;
18497 15 : id.decl_map = &decl_map;
18498 15 : id.copy_decl = copy_decl_no_change;
18499 15 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
18500 15 : id.transform_new_cfg = true;
18501 15 : id.transform_return_to_modify = false;
18502 15 : id.eh_lp_nr = 0;
18503 15 : walk_tree (&OMP_CLAUSE_REDUCTION_INIT (*pc), copy_tree_body_r,
18504 : &id, NULL);
18505 15 : walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (*pc), copy_tree_body_r,
18506 : &id, NULL);
18507 :
18508 60 : for (tree d : no_context_vars)
18509 : {
18510 15 : DECL_CONTEXT (d) = NULL_TREE;
18511 15 : DECL_CONTEXT (*decl_map.get (d)) = NULL_TREE;
18512 : }
18513 15 : }
18514 : else
18515 : {
18516 448 : OMP_CLAUSE_REDUCTION_INIT (*pc)
18517 448 : = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c));
18518 448 : OMP_CLAUSE_REDUCTION_MERGE (*pc)
18519 896 : = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c));
18520 : }
18521 463 : pc = &OMP_CLAUSE_CHAIN (*pc);
18522 463 : break;
18523 0 : default:
18524 0 : gcc_unreachable ();
18525 : }
18526 854 : *pc = NULL_TREE;
18527 854 : *expr_p = t;
18528 : }
18529 1056 : return gimplify_expr (expr_p, pre_p, NULL, is_gimple_stmt, fb_none);
18530 : }
18531 :
18532 :
18533 : /* Helper function of optimize_target_teams, find OMP_TEAMS inside
18534 : of OMP_TARGET's body. */
18535 :
18536 : static tree
18537 98520 : find_omp_teams (tree *tp, int *walk_subtrees, void *)
18538 : {
18539 98520 : *walk_subtrees = 0;
18540 98520 : switch (TREE_CODE (*tp))
18541 : {
18542 : case OMP_TEAMS:
18543 : return *tp;
18544 27281 : case BIND_EXPR:
18545 27281 : case STATEMENT_LIST:
18546 27281 : *walk_subtrees = 1;
18547 27281 : break;
18548 : default:
18549 : break;
18550 : }
18551 : return NULL_TREE;
18552 : }
18553 :
18554 : /* Helper function of optimize_target_teams, determine if the expression
18555 : can be computed safely before the target construct on the host. */
18556 :
18557 : static tree
18558 1311 : computable_teams_clause (tree *tp, int *walk_subtrees, void *)
18559 : {
18560 1831 : splay_tree_node n;
18561 :
18562 1831 : if (TYPE_P (*tp))
18563 : {
18564 0 : *walk_subtrees = 0;
18565 0 : return NULL_TREE;
18566 : }
18567 1831 : switch (TREE_CODE (*tp))
18568 : {
18569 990 : case VAR_DECL:
18570 990 : case PARM_DECL:
18571 990 : case RESULT_DECL:
18572 990 : *walk_subtrees = 0;
18573 990 : if (error_operand_p (*tp)
18574 990 : || !INTEGRAL_TYPE_P (TREE_TYPE (*tp))
18575 990 : || DECL_HAS_VALUE_EXPR_P (*tp)
18576 990 : || DECL_THREAD_LOCAL_P (*tp)
18577 990 : || TREE_SIDE_EFFECTS (*tp)
18578 1980 : || TREE_THIS_VOLATILE (*tp))
18579 0 : return *tp;
18580 990 : if (is_global_var (*tp)
18581 990 : && (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (*tp))
18582 0 : || lookup_attribute ("omp declare target link",
18583 0 : DECL_ATTRIBUTES (*tp))))
18584 16 : return *tp;
18585 974 : if (VAR_P (*tp)
18586 668 : && !DECL_SEEN_IN_BIND_EXPR_P (*tp)
18587 50 : && !is_global_var (*tp)
18588 1024 : && decl_function_context (*tp) == current_function_decl)
18589 50 : return *tp;
18590 1848 : n = splay_tree_lookup (gimplify_omp_ctxp->variables,
18591 924 : (splay_tree_key) *tp);
18592 924 : if (n == NULL)
18593 : {
18594 292 : if (gimplify_omp_ctxp->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
18595 : return NULL_TREE;
18596 24 : return *tp;
18597 : }
18598 632 : else if (n->value & GOVD_LOCAL)
18599 0 : return *tp;
18600 632 : else if (n->value & GOVD_FIRSTPRIVATE)
18601 : return NULL_TREE;
18602 112 : else if ((n->value & (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18603 : == (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18604 : return NULL_TREE;
18605 96 : return *tp;
18606 76 : case INTEGER_CST:
18607 76 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18608 : return *tp;
18609 : return NULL_TREE;
18610 520 : case TARGET_EXPR:
18611 520 : if (TARGET_EXPR_INITIAL (*tp)
18612 520 : || TREE_CODE (TARGET_EXPR_SLOT (*tp)) != VAR_DECL)
18613 : return *tp;
18614 520 : return computable_teams_clause (&TARGET_EXPR_SLOT (*tp),
18615 520 : walk_subtrees, NULL);
18616 : /* Allow some reasonable subset of integral arithmetics. */
18617 193 : case PLUS_EXPR:
18618 193 : case MINUS_EXPR:
18619 193 : case MULT_EXPR:
18620 193 : case TRUNC_DIV_EXPR:
18621 193 : case CEIL_DIV_EXPR:
18622 193 : case FLOOR_DIV_EXPR:
18623 193 : case ROUND_DIV_EXPR:
18624 193 : case TRUNC_MOD_EXPR:
18625 193 : case CEIL_MOD_EXPR:
18626 193 : case FLOOR_MOD_EXPR:
18627 193 : case ROUND_MOD_EXPR:
18628 193 : case RDIV_EXPR:
18629 193 : case EXACT_DIV_EXPR:
18630 193 : case MIN_EXPR:
18631 193 : case MAX_EXPR:
18632 193 : case LSHIFT_EXPR:
18633 193 : case RSHIFT_EXPR:
18634 193 : case BIT_IOR_EXPR:
18635 193 : case BIT_XOR_EXPR:
18636 193 : case BIT_AND_EXPR:
18637 193 : case NEGATE_EXPR:
18638 193 : case ABS_EXPR:
18639 193 : case BIT_NOT_EXPR:
18640 193 : case NON_LVALUE_EXPR:
18641 193 : CASE_CONVERT:
18642 193 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18643 : return *tp;
18644 : return NULL_TREE;
18645 : /* And disallow anything else, except for comparisons. */
18646 52 : default:
18647 52 : if (COMPARISON_CLASS_P (*tp))
18648 : return NULL_TREE;
18649 : return *tp;
18650 : }
18651 : }
18652 :
18653 : /* Try to determine if the num_teams and/or thread_limit expressions
18654 : can have their values determined already before entering the
18655 : target construct.
18656 : INTEGER_CSTs trivially are,
18657 : integral decls that are firstprivate (explicitly or implicitly)
18658 : or explicitly map(always, to:) or map(always, tofrom:) on the target
18659 : region too, and expressions involving simple arithmetics on those
18660 : too, function calls are not ok, dereferencing something neither etc.
18661 : Add NUM_TEAMS and THREAD_LIMIT clauses to the OMP_CLAUSES of
18662 : EXPR based on what we find:
18663 : 0 stands for clause not specified at all, use implementation default
18664 : -1 stands for value that can't be determined easily before entering
18665 : the target construct.
18666 : -2 means that no explicit teams construct was specified
18667 : If teams construct is not present at all, use 1 for num_teams
18668 : and 0 for thread_limit (only one team is involved, and the thread
18669 : limit is implementation defined. */
18670 :
18671 : static void
18672 13492 : optimize_target_teams (tree target, gimple_seq *pre_p)
18673 : {
18674 13492 : tree body = OMP_BODY (target);
18675 13492 : tree teams = walk_tree (&body, find_omp_teams, NULL, NULL);
18676 13492 : tree num_teams_lower = NULL_TREE;
18677 13492 : tree num_teams_upper = integer_zero_node;
18678 13492 : tree thread_limit = integer_zero_node;
18679 13492 : location_t num_teams_loc = EXPR_LOCATION (target);
18680 13492 : location_t thread_limit_loc = EXPR_LOCATION (target);
18681 13492 : tree c, *p, expr;
18682 13492 : struct gimplify_omp_ctx *target_ctx = gimplify_omp_ctxp;
18683 :
18684 13492 : if (teams == NULL_TREE)
18685 7371 : num_teams_upper = build_int_cst (integer_type_node, -2);
18686 : else
18687 10587 : for (c = OMP_TEAMS_CLAUSES (teams); c; c = OMP_CLAUSE_CHAIN (c))
18688 : {
18689 4466 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS)
18690 : {
18691 617 : p = &num_teams_upper;
18692 617 : num_teams_loc = OMP_CLAUSE_LOCATION (c);
18693 617 : if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c))
18694 : {
18695 148 : expr = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c);
18696 148 : if (TREE_CODE (expr) == INTEGER_CST)
18697 21 : num_teams_lower = expr;
18698 127 : else if (walk_tree (&expr, computable_teams_clause,
18699 : NULL, NULL))
18700 19 : num_teams_lower = integer_minus_one_node;
18701 : else
18702 : {
18703 108 : num_teams_lower = expr;
18704 108 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18705 108 : if (gimplify_expr (&num_teams_lower, pre_p, NULL,
18706 : is_gimple_val, fb_rvalue, false)
18707 : == GS_ERROR)
18708 : {
18709 0 : gimplify_omp_ctxp = target_ctx;
18710 0 : num_teams_lower = integer_minus_one_node;
18711 : }
18712 : else
18713 : {
18714 108 : gimplify_omp_ctxp = target_ctx;
18715 108 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18716 28 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
18717 56 : = num_teams_lower;
18718 : }
18719 : }
18720 : }
18721 : }
18722 3849 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
18723 : {
18724 471 : p = &thread_limit;
18725 471 : thread_limit_loc = OMP_CLAUSE_LOCATION (c);
18726 : }
18727 : else
18728 3378 : continue;
18729 1088 : expr = OMP_CLAUSE_OPERAND (c, 0);
18730 1088 : if (TREE_CODE (expr) == INTEGER_CST)
18731 : {
18732 173 : *p = expr;
18733 173 : continue;
18734 : }
18735 915 : if (walk_tree (&expr, computable_teams_clause, NULL, NULL))
18736 : {
18737 219 : *p = integer_minus_one_node;
18738 219 : continue;
18739 : }
18740 696 : *p = expr;
18741 696 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18742 696 : if (gimplify_expr (p, pre_p, NULL, is_gimple_val, fb_rvalue, false)
18743 : == GS_ERROR)
18744 : {
18745 0 : gimplify_omp_ctxp = target_ctx;
18746 0 : *p = integer_minus_one_node;
18747 0 : continue;
18748 : }
18749 696 : gimplify_omp_ctxp = target_ctx;
18750 696 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18751 48 : OMP_CLAUSE_OPERAND (c, 0) = *p;
18752 : }
18753 13492 : if (!omp_find_clause (OMP_TARGET_CLAUSES (target), OMP_CLAUSE_THREAD_LIMIT))
18754 : {
18755 13224 : c = build_omp_clause (thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
18756 13224 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
18757 13224 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18758 13224 : OMP_TARGET_CLAUSES (target) = c;
18759 : }
18760 13492 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
18761 13492 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
18762 13492 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
18763 13492 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18764 13492 : OMP_TARGET_CLAUSES (target) = c;
18765 13492 : }
18766 :
18767 : /* Gimplify the gross structure of several OMP constructs. */
18768 :
18769 : static void
18770 39824 : gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
18771 : {
18772 39824 : tree expr = *expr_p;
18773 39824 : gimple *stmt;
18774 39824 : gimple_seq body = NULL;
18775 39824 : enum omp_region_type ort;
18776 :
18777 39824 : switch (TREE_CODE (expr))
18778 : {
18779 : case OMP_SECTIONS:
18780 : case OMP_SINGLE:
18781 : ort = ORT_WORKSHARE;
18782 : break;
18783 214 : case OMP_SCOPE:
18784 214 : ort = ORT_TASKGROUP;
18785 214 : break;
18786 13492 : case OMP_TARGET:
18787 13492 : ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET;
18788 : break;
18789 2543 : case OACC_KERNELS:
18790 2543 : ort = ORT_ACC_KERNELS;
18791 2543 : break;
18792 7901 : case OACC_PARALLEL:
18793 7901 : ort = ORT_ACC_PARALLEL;
18794 7901 : break;
18795 1040 : case OACC_SERIAL:
18796 1040 : ort = ORT_ACC_SERIAL;
18797 1040 : break;
18798 1950 : case OACC_DATA:
18799 1950 : ort = ORT_ACC_DATA;
18800 1950 : break;
18801 1872 : case OMP_TARGET_DATA:
18802 1872 : ort = ORT_TARGET_DATA;
18803 1872 : break;
18804 8793 : case OMP_TEAMS:
18805 8793 : ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS;
18806 8793 : if (gimplify_omp_ctxp == NULL
18807 6161 : || gimplify_omp_ctxp->region_type == ORT_IMPLICIT_TARGET)
18808 2632 : ort = (enum omp_region_type) (ort | ORT_HOST_TEAMS);
18809 : break;
18810 118 : case OACC_HOST_DATA:
18811 118 : ort = ORT_ACC_HOST_DATA;
18812 118 : break;
18813 0 : default:
18814 0 : gcc_unreachable ();
18815 : }
18816 :
18817 39824 : gimple_seq iterator_loops_seq = NULL;
18818 39824 : if (TREE_CODE (expr) == OMP_TARGET || TREE_CODE (expr) == OMP_TARGET_DATA)
18819 : {
18820 15364 : remove_unused_omp_iterator_vars (&OMP_CLAUSES (expr));
18821 15364 : build_omp_iterators_loops (&OMP_CLAUSES (expr), &iterator_loops_seq);
18822 : }
18823 :
18824 39824 : bool save_in_omp_construct = in_omp_construct;
18825 39824 : if ((ort & ORT_ACC) == 0)
18826 26272 : in_omp_construct = false;
18827 39824 : gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
18828 39824 : TREE_CODE (expr), &iterator_loops_seq);
18829 39824 : if (TREE_CODE (expr) == OMP_TARGET)
18830 13492 : optimize_target_teams (expr, pre_p);
18831 39824 : if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
18832 10908 : || (ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18833 : {
18834 31548 : push_gimplify_context ();
18835 31548 : gimple *g = gimplify_and_return_first (OMP_BODY (expr), &body);
18836 31548 : if (gimple_code (g) == GIMPLE_BIND)
18837 31548 : pop_gimplify_context (g);
18838 : else
18839 0 : pop_gimplify_context (NULL);
18840 31548 : if ((ort & ORT_TARGET_DATA) != 0)
18841 : {
18842 3940 : enum built_in_function end_ix;
18843 3940 : switch (TREE_CODE (expr))
18844 : {
18845 : case OACC_DATA:
18846 : case OACC_HOST_DATA:
18847 : end_ix = BUILT_IN_GOACC_DATA_END;
18848 : break;
18849 1872 : case OMP_TARGET_DATA:
18850 1872 : end_ix = BUILT_IN_GOMP_TARGET_END_DATA;
18851 1872 : break;
18852 0 : default:
18853 0 : gcc_unreachable ();
18854 : }
18855 3940 : tree fn = builtin_decl_explicit (end_ix);
18856 3940 : g = gimple_build_call (fn, 0);
18857 3940 : gimple_seq cleanup = NULL;
18858 3940 : gimple_seq_add_stmt (&cleanup, g);
18859 3940 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
18860 3940 : body = NULL;
18861 3940 : gimple_seq_add_stmt (&body, g);
18862 : }
18863 : }
18864 : else
18865 8276 : gimplify_and_add (OMP_BODY (expr), &body);
18866 39824 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
18867 39824 : TREE_CODE (expr), &iterator_loops_seq);
18868 39824 : in_omp_construct = save_in_omp_construct;
18869 :
18870 39824 : switch (TREE_CODE (expr))
18871 : {
18872 1950 : case OACC_DATA:
18873 3900 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_DATA,
18874 1950 : OMP_CLAUSES (expr));
18875 1950 : break;
18876 118 : case OACC_HOST_DATA:
18877 118 : if (omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT))
18878 : {
18879 128 : for (tree c = OMP_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18880 95 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
18881 57 : OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c) = 1;
18882 : }
18883 :
18884 236 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_HOST_DATA,
18885 118 : OMP_CLAUSES (expr));
18886 118 : break;
18887 2543 : case OACC_KERNELS:
18888 5086 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS,
18889 2543 : OMP_CLAUSES (expr));
18890 2543 : break;
18891 7901 : case OACC_PARALLEL:
18892 15802 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_PARALLEL,
18893 7901 : OMP_CLAUSES (expr));
18894 7901 : break;
18895 1040 : case OACC_SERIAL:
18896 2080 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_SERIAL,
18897 1040 : OMP_CLAUSES (expr));
18898 1040 : break;
18899 626 : case OMP_SECTIONS:
18900 626 : stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
18901 626 : break;
18902 1275 : case OMP_SINGLE:
18903 1275 : stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
18904 1275 : break;
18905 214 : case OMP_SCOPE:
18906 214 : stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
18907 214 : break;
18908 13492 : case OMP_TARGET:
18909 26984 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
18910 13492 : OMP_CLAUSES (expr), iterator_loops_seq);
18911 13492 : break;
18912 1872 : case OMP_TARGET_DATA:
18913 : /* Put use_device_{ptr,addr} clauses last, as map clauses are supposed
18914 : to be evaluated before the use_device_{ptr,addr} clauses if they
18915 : refer to the same variables. */
18916 1872 : {
18917 1872 : tree use_device_clauses;
18918 1872 : tree *pc, *uc = &use_device_clauses;
18919 9968 : for (pc = &OMP_CLAUSES (expr); *pc; )
18920 8096 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
18921 8096 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
18922 : {
18923 1959 : *uc = *pc;
18924 1959 : *pc = OMP_CLAUSE_CHAIN (*pc);
18925 1959 : uc = &OMP_CLAUSE_CHAIN (*uc);
18926 : }
18927 : else
18928 6137 : pc = &OMP_CLAUSE_CHAIN (*pc);
18929 1872 : *uc = NULL_TREE;
18930 1872 : *pc = use_device_clauses;
18931 1872 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_DATA,
18932 1872 : OMP_CLAUSES (expr), iterator_loops_seq);
18933 : }
18934 1872 : break;
18935 8793 : case OMP_TEAMS:
18936 8793 : stmt = gimple_build_omp_teams (body, OMP_CLAUSES (expr));
18937 8793 : if ((ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18938 2632 : gimple_omp_teams_set_host (as_a <gomp_teams *> (stmt), true);
18939 : break;
18940 0 : default:
18941 0 : gcc_unreachable ();
18942 : }
18943 :
18944 39824 : gimplify_seq_add_stmt (pre_p, stmt);
18945 39824 : *expr_p = NULL_TREE;
18946 39824 : }
18947 :
18948 : /* Gimplify the gross structure of OpenACC enter/exit data, update, and OpenMP
18949 : target update constructs. */
18950 :
18951 : static void
18952 12297 : gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
18953 : {
18954 12297 : tree expr = *expr_p;
18955 12297 : int kind;
18956 12297 : gomp_target *stmt;
18957 12297 : enum omp_region_type ort = ORT_WORKSHARE;
18958 :
18959 12297 : switch (TREE_CODE (expr))
18960 : {
18961 : case OACC_ENTER_DATA:
18962 : kind = GF_OMP_TARGET_KIND_OACC_ENTER_DATA;
18963 : ort = ORT_ACC;
18964 : break;
18965 : case OACC_EXIT_DATA:
18966 : kind = GF_OMP_TARGET_KIND_OACC_EXIT_DATA;
18967 : ort = ORT_ACC;
18968 : break;
18969 : case OACC_UPDATE:
18970 : kind = GF_OMP_TARGET_KIND_OACC_UPDATE;
18971 : ort = ORT_ACC;
18972 : break;
18973 : case OMP_TARGET_UPDATE:
18974 : kind = GF_OMP_TARGET_KIND_UPDATE;
18975 : break;
18976 : case OMP_TARGET_ENTER_DATA:
18977 : kind = GF_OMP_TARGET_KIND_ENTER_DATA;
18978 : break;
18979 : case OMP_TARGET_EXIT_DATA:
18980 : kind = GF_OMP_TARGET_KIND_EXIT_DATA;
18981 : break;
18982 0 : default:
18983 0 : gcc_unreachable ();
18984 : }
18985 :
18986 12297 : gimple_seq iterator_loops_seq = NULL;
18987 12297 : remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr));
18988 12297 : build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr),
18989 : &iterator_loops_seq);
18990 :
18991 12297 : gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
18992 12297 : ort, TREE_CODE (expr), &iterator_loops_seq);
18993 12297 : gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
18994 12297 : TREE_CODE (expr), &iterator_loops_seq);
18995 12297 : if (TREE_CODE (expr) == OACC_UPDATE
18996 12297 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
18997 : OMP_CLAUSE_IF_PRESENT))
18998 : {
18999 : /* The runtime uses GOMP_MAP_{TO,FROM} to denote the if_present
19000 : clause. */
19001 123 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19002 97 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
19003 47 : switch (OMP_CLAUSE_MAP_KIND (c))
19004 : {
19005 14 : case GOMP_MAP_FORCE_TO:
19006 14 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
19007 14 : break;
19008 24 : case GOMP_MAP_FORCE_FROM:
19009 24 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FROM);
19010 24 : break;
19011 : default:
19012 : break;
19013 : }
19014 : }
19015 12271 : else if (TREE_CODE (expr) == OACC_EXIT_DATA
19016 12271 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
19017 : OMP_CLAUSE_FINALIZE))
19018 : {
19019 : /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote "finalize"
19020 : semantics. */
19021 75 : bool have_clause = false;
19022 275 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19023 200 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
19024 117 : switch (OMP_CLAUSE_MAP_KIND (c))
19025 : {
19026 45 : case GOMP_MAP_FROM:
19027 45 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
19028 45 : have_clause = true;
19029 45 : break;
19030 47 : case GOMP_MAP_RELEASE:
19031 47 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
19032 47 : have_clause = true;
19033 47 : break;
19034 : case GOMP_MAP_TO_PSET:
19035 : /* Fortran arrays with descriptors must map that descriptor when
19036 : doing standalone "attach" operations (in OpenACC). In that
19037 : case GOMP_MAP_TO_PSET appears by itself with no preceding
19038 : clause (see trans-openmp.cc:gfc_trans_omp_clauses). */
19039 : break;
19040 2 : case GOMP_MAP_POINTER:
19041 : /* TODO PR92929: we may see these here, but they'll always follow
19042 : one of the clauses above, and will be handled by libgomp as
19043 : one group, so no handling required here. */
19044 2 : gcc_assert (have_clause);
19045 : break;
19046 22 : case GOMP_MAP_DETACH:
19047 22 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_DETACH);
19048 22 : have_clause = false;
19049 22 : break;
19050 : case GOMP_MAP_STRUCT:
19051 : case GOMP_MAP_STRUCT_UNORD:
19052 22 : have_clause = false;
19053 : break;
19054 0 : default:
19055 0 : gcc_unreachable ();
19056 : }
19057 : }
19058 12297 : stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr),
19059 : iterator_loops_seq);
19060 :
19061 12297 : gimplify_seq_add_stmt (pre_p, stmt);
19062 12297 : *expr_p = NULL_TREE;
19063 12297 : }
19064 :
19065 : /* A subroutine of gimplify_omp_atomic. The front end is supposed to have
19066 : stabilized the lhs of the atomic operation as *ADDR. Return true if
19067 : EXPR is this stabilized form. */
19068 :
19069 : static bool
19070 36791 : goa_lhs_expr_p (tree expr, tree addr)
19071 : {
19072 : /* Also include casts to other type variants. The C front end is fond
19073 : of adding these for e.g. volatile variables. This is like
19074 : STRIP_TYPE_NOPS but includes the main variant lookup. */
19075 36791 : STRIP_USELESS_TYPE_CONVERSION (expr);
19076 :
19077 36791 : if (INDIRECT_REF_P (expr))
19078 : {
19079 5011 : expr = TREE_OPERAND (expr, 0);
19080 5011 : while (expr != addr
19081 92 : && (CONVERT_EXPR_P (expr)
19082 92 : || TREE_CODE (expr) == NON_LVALUE_EXPR)
19083 0 : && TREE_CODE (expr) == TREE_CODE (addr)
19084 5011 : && types_compatible_p (TREE_TYPE (expr), TREE_TYPE (addr)))
19085 : {
19086 0 : expr = TREE_OPERAND (expr, 0);
19087 0 : addr = TREE_OPERAND (addr, 0);
19088 : }
19089 5011 : if (expr == addr)
19090 : return true;
19091 92 : return (TREE_CODE (addr) == ADDR_EXPR
19092 62 : && TREE_CODE (expr) == ADDR_EXPR
19093 92 : && TREE_OPERAND (addr, 0) == TREE_OPERAND (expr, 0));
19094 : }
19095 31780 : if (TREE_CODE (addr) == ADDR_EXPR && expr == TREE_OPERAND (addr, 0))
19096 : return true;
19097 : return false;
19098 : }
19099 :
19100 : /* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR. If an
19101 : expression does not involve the lhs, evaluate it into a temporary.
19102 : Return 1 if the lhs appeared as a subexpression, 0 if it did not,
19103 : or -1 if an error was encountered. */
19104 :
19105 : static int
19106 36791 : goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
19107 : tree lhs_var, tree &target_expr, bool rhs, int depth)
19108 : {
19109 36791 : tree expr = *expr_p;
19110 36791 : int saw_lhs = 0;
19111 :
19112 36791 : if (goa_lhs_expr_p (expr, lhs_addr))
19113 : {
19114 9183 : if (pre_p)
19115 8525 : *expr_p = lhs_var;
19116 9183 : return 1;
19117 : }
19118 27608 : if (is_gimple_val (expr))
19119 : return 0;
19120 :
19121 : /* Maximum depth of lhs in expression is for the
19122 : __builtin_clear_padding (...), __builtin_clear_padding (...),
19123 : __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs; */
19124 17276 : if (++depth > 7)
19125 16 : goto finish;
19126 :
19127 17260 : switch (TREE_CODE_CLASS (TREE_CODE (expr)))
19128 : {
19129 9652 : case tcc_binary:
19130 9652 : case tcc_comparison:
19131 9652 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
19132 : lhs_var, target_expr, true, depth);
19133 : /* FALLTHRU */
19134 11699 : case tcc_unary:
19135 11699 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
19136 : lhs_var, target_expr, true, depth);
19137 11699 : break;
19138 2982 : case tcc_expression:
19139 2982 : switch (TREE_CODE (expr))
19140 : {
19141 836 : case TRUTH_ANDIF_EXPR:
19142 836 : case TRUTH_ORIF_EXPR:
19143 836 : case TRUTH_AND_EXPR:
19144 836 : case TRUTH_OR_EXPR:
19145 836 : case TRUTH_XOR_EXPR:
19146 836 : case BIT_INSERT_EXPR:
19147 836 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19148 : lhs_addr, lhs_var, target_expr, true,
19149 : depth);
19150 : /* FALLTHRU */
19151 888 : case TRUTH_NOT_EXPR:
19152 888 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19153 : lhs_addr, lhs_var, target_expr, true,
19154 : depth);
19155 888 : break;
19156 550 : case MODIFY_EXPR:
19157 550 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19158 : target_expr, true, depth))
19159 : break;
19160 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19161 : lhs_addr, lhs_var, target_expr, true,
19162 : depth);
19163 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19164 : lhs_addr, lhs_var, target_expr, false,
19165 : depth);
19166 544 : break;
19167 : /* FALLTHRU */
19168 164 : case ADDR_EXPR:
19169 164 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19170 : target_expr, true, depth))
19171 : break;
19172 138 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19173 : lhs_addr, lhs_var, target_expr, false,
19174 : depth);
19175 138 : break;
19176 : case COMPOUND_EXPR:
19177 : /* Break out any preevaluations from cp_build_modify_expr. */
19178 76 : for (; TREE_CODE (expr) == COMPOUND_EXPR;
19179 38 : expr = TREE_OPERAND (expr, 1))
19180 : {
19181 : /* Special-case __builtin_clear_padding call before
19182 : __builtin_memcmp. */
19183 38 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
19184 : {
19185 2 : tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
19186 2 : if (fndecl
19187 2 : && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
19188 0 : && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
19189 2 : && (!pre_p
19190 0 : || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
19191 : lhs_addr, lhs_var,
19192 : target_expr, true, depth)))
19193 : {
19194 0 : if (pre_p)
19195 0 : *expr_p = expr;
19196 0 : saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
19197 : pre_p, lhs_addr, lhs_var,
19198 : target_expr, true, depth);
19199 0 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
19200 : pre_p, lhs_addr, lhs_var,
19201 : target_expr, rhs, depth);
19202 0 : return saw_lhs;
19203 : }
19204 : }
19205 :
19206 38 : if (pre_p)
19207 35 : gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
19208 : }
19209 38 : if (!pre_p)
19210 3 : return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
19211 3 : target_expr, rhs, depth);
19212 35 : *expr_p = expr;
19213 35 : return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
19214 35 : target_expr, rhs, depth);
19215 441 : case COND_EXPR:
19216 441 : if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
19217 : lhs_var, target_expr, true, depth))
19218 : break;
19219 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19220 : lhs_addr, lhs_var, target_expr, true,
19221 : depth);
19222 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19223 : lhs_addr, lhs_var, target_expr, true,
19224 : depth);
19225 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
19226 : lhs_addr, lhs_var, target_expr, true,
19227 : depth);
19228 428 : break;
19229 880 : case TARGET_EXPR:
19230 880 : if (TARGET_EXPR_INITIAL (expr))
19231 : {
19232 880 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
19233 : lhs_var, target_expr, true,
19234 : depth))
19235 : break;
19236 702 : if (expr == target_expr)
19237 : saw_lhs = 1;
19238 : else
19239 : {
19240 702 : saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
19241 : pre_p, lhs_addr, lhs_var,
19242 : target_expr, true, depth);
19243 702 : if (saw_lhs && target_expr == NULL_TREE && pre_p)
19244 26 : target_expr = expr;
19245 : }
19246 : }
19247 : break;
19248 : default:
19249 : break;
19250 : }
19251 : break;
19252 556 : case tcc_reference:
19253 556 : if (TREE_CODE (expr) == BIT_FIELD_REF
19254 490 : || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
19255 362 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19256 : lhs_addr, lhs_var, target_expr, true,
19257 : depth);
19258 : break;
19259 58 : case tcc_vl_exp:
19260 58 : if (TREE_CODE (expr) == CALL_EXPR)
19261 : {
19262 58 : if (tree fndecl = get_callee_fndecl (expr))
19263 58 : if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING,
19264 : BUILT_IN_MEMCMP))
19265 : {
19266 56 : int nargs = call_expr_nargs (expr);
19267 224 : for (int i = 0; i < nargs; i++)
19268 168 : saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
19269 : pre_p, lhs_addr, lhs_var,
19270 : target_expr, true, depth);
19271 : }
19272 : }
19273 : break;
19274 : default:
19275 : break;
19276 : }
19277 :
19278 17238 : finish:
19279 17238 : if (saw_lhs == 0 && pre_p)
19280 : {
19281 3485 : enum gimplify_status gs;
19282 3485 : if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
19283 : {
19284 0 : gimplify_stmt (&expr, pre_p);
19285 0 : return saw_lhs;
19286 : }
19287 3485 : else if (rhs)
19288 3307 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
19289 : else
19290 178 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
19291 3485 : if (gs != GS_ALL_DONE)
19292 36791 : saw_lhs = -1;
19293 : }
19294 :
19295 : return saw_lhs;
19296 : }
19297 :
19298 : /* Gimplify an OMP_ATOMIC statement. */
19299 :
19300 : static enum gimplify_status
19301 10236 : gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
19302 : {
19303 10236 : tree addr = TREE_OPERAND (*expr_p, 0);
19304 10236 : tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
19305 10236 : ? NULL : TREE_OPERAND (*expr_p, 1);
19306 10236 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
19307 10236 : tree tmp_load;
19308 10236 : gomp_atomic_load *loadstmt;
19309 10236 : gomp_atomic_store *storestmt;
19310 10236 : tree target_expr = NULL_TREE;
19311 :
19312 10236 : tmp_load = create_tmp_reg (type);
19313 10236 : if (rhs
19314 10236 : && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
19315 : true, 0) < 0)
19316 : return GS_ERROR;
19317 :
19318 10236 : if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
19319 : != GS_ALL_DONE)
19320 : return GS_ERROR;
19321 :
19322 10236 : loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
19323 10236 : OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19324 10236 : gimplify_seq_add_stmt (pre_p, loadstmt);
19325 10236 : if (rhs)
19326 : {
19327 : /* BIT_INSERT_EXPR is not valid for non-integral bitfield
19328 : representatives. Use BIT_FIELD_REF on the lhs instead. */
19329 9055 : tree rhsarg = rhs;
19330 9055 : if (TREE_CODE (rhs) == COND_EXPR)
19331 428 : rhsarg = TREE_OPERAND (rhs, 1);
19332 9055 : if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
19333 9055 : && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
19334 : {
19335 32 : tree bitpos = TREE_OPERAND (rhsarg, 2);
19336 32 : tree op1 = TREE_OPERAND (rhsarg, 1);
19337 32 : tree bitsize;
19338 32 : tree tmp_store = tmp_load;
19339 32 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
19340 12 : tmp_store = get_initialized_tmp_var (tmp_load, pre_p);
19341 32 : if (INTEGRAL_TYPE_P (TREE_TYPE (op1)))
19342 32 : bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
19343 : else
19344 0 : bitsize = TYPE_SIZE (TREE_TYPE (op1));
19345 32 : gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
19346 32 : tree t = build2_loc (EXPR_LOCATION (rhsarg),
19347 : MODIFY_EXPR, void_type_node,
19348 32 : build3_loc (EXPR_LOCATION (rhsarg),
19349 32 : BIT_FIELD_REF, TREE_TYPE (op1),
19350 : tmp_store, bitsize, bitpos), op1);
19351 32 : if (TREE_CODE (rhs) == COND_EXPR)
19352 16 : t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
19353 16 : TREE_OPERAND (rhs, 0), t, void_node);
19354 32 : gimplify_and_add (t, pre_p);
19355 32 : rhs = tmp_store;
19356 : }
19357 9055 : bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
19358 9055 : if (TREE_CODE (rhs) == COND_EXPR)
19359 412 : gimplify_ctxp->allow_rhs_cond_expr = true;
19360 9055 : enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
19361 : is_gimple_val, fb_rvalue);
19362 9055 : gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
19363 9055 : if (gs != GS_ALL_DONE)
19364 : return GS_ERROR;
19365 : }
19366 :
19367 10236 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
19368 1181 : rhs = tmp_load;
19369 10236 : storestmt
19370 10236 : = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19371 10236 : if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
19372 : {
19373 37 : gimple_omp_atomic_set_weak (loadstmt);
19374 37 : gimple_omp_atomic_set_weak (storestmt);
19375 : }
19376 10236 : gimplify_seq_add_stmt (pre_p, storestmt);
19377 10236 : switch (TREE_CODE (*expr_p))
19378 : {
19379 2065 : case OMP_ATOMIC_READ:
19380 2065 : case OMP_ATOMIC_CAPTURE_OLD:
19381 2065 : *expr_p = tmp_load;
19382 2065 : gimple_omp_atomic_set_need_value (loadstmt);
19383 2065 : break;
19384 868 : case OMP_ATOMIC_CAPTURE_NEW:
19385 868 : *expr_p = rhs;
19386 868 : gimple_omp_atomic_set_need_value (storestmt);
19387 868 : break;
19388 7303 : default:
19389 7303 : *expr_p = NULL;
19390 7303 : break;
19391 : }
19392 :
19393 : return GS_ALL_DONE;
19394 : }
19395 :
19396 : /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
19397 : body, and adding some EH bits. */
19398 :
19399 : static enum gimplify_status
19400 478 : gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
19401 : {
19402 478 : tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
19403 478 : gimple *body_stmt;
19404 478 : gtransaction *trans_stmt;
19405 478 : gimple_seq body = NULL;
19406 478 : int subcode = 0;
19407 :
19408 : /* Wrap the transaction body in a BIND_EXPR so we have a context
19409 : where to put decls for OMP. */
19410 478 : if (TREE_CODE (tbody) != BIND_EXPR)
19411 : {
19412 439 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
19413 439 : TREE_SIDE_EFFECTS (bind) = 1;
19414 439 : SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
19415 439 : TRANSACTION_EXPR_BODY (expr) = bind;
19416 : }
19417 :
19418 478 : push_gimplify_context ();
19419 478 : temp = voidify_wrapper_expr (*expr_p, NULL);
19420 :
19421 478 : body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
19422 478 : pop_gimplify_context (body_stmt);
19423 :
19424 478 : trans_stmt = gimple_build_transaction (body);
19425 478 : if (TRANSACTION_EXPR_OUTER (expr))
19426 : subcode = GTMA_IS_OUTER;
19427 447 : else if (TRANSACTION_EXPR_RELAXED (expr))
19428 81 : subcode = GTMA_IS_RELAXED;
19429 478 : gimple_transaction_set_subcode (trans_stmt, subcode);
19430 :
19431 478 : gimplify_seq_add_stmt (pre_p, trans_stmt);
19432 :
19433 478 : if (temp)
19434 : {
19435 76 : *expr_p = temp;
19436 76 : return GS_OK;
19437 : }
19438 :
19439 402 : *expr_p = NULL_TREE;
19440 402 : return GS_ALL_DONE;
19441 : }
19442 :
19443 : /* Gimplify an OMP_ORDERED construct. EXPR is the tree version. BODY
19444 : is the OMP_BODY of the original EXPR (which has already been
19445 : gimplified so it's not present in the EXPR).
19446 :
19447 : Return the gimplified GIMPLE_OMP_ORDERED tuple. */
19448 :
19449 : static gimple *
19450 1950 : gimplify_omp_ordered (tree expr, gimple_seq body)
19451 : {
19452 1950 : tree c, decls;
19453 1950 : int failures = 0;
19454 1950 : unsigned int i;
19455 1950 : tree source_c = NULL_TREE;
19456 1950 : tree sink_c = NULL_TREE;
19457 :
19458 1950 : if (gimplify_omp_ctxp)
19459 : {
19460 3291 : for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19461 1515 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19462 1515 : && gimplify_omp_ctxp->loop_iter_var.is_empty ())
19463 : {
19464 74 : error_at (OMP_CLAUSE_LOCATION (c),
19465 : "%<ordered%> construct with %qs clause must be "
19466 : "closely nested inside a loop with %<ordered%> clause",
19467 74 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
19468 74 : failures++;
19469 : }
19470 1441 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19471 1441 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
19472 : {
19473 642 : bool fail = false;
19474 642 : sink_c = c;
19475 642 : if (OMP_CLAUSE_DECL (c) == NULL_TREE)
19476 72 : continue; /* omp_cur_iteration - 1 */
19477 570 : for (decls = OMP_CLAUSE_DECL (c), i = 0;
19478 3201 : decls && TREE_CODE (decls) == TREE_LIST;
19479 2631 : decls = TREE_CHAIN (decls), ++i)
19480 2631 : if (i >= gimplify_omp_ctxp->loop_iter_var.length () / 2)
19481 4 : continue;
19482 5254 : else if (TREE_VALUE (decls)
19483 2627 : != gimplify_omp_ctxp->loop_iter_var[2 * i])
19484 : {
19485 8 : error_at (OMP_CLAUSE_LOCATION (c),
19486 : "variable %qE is not an iteration "
19487 : "of outermost loop %d, expected %qE",
19488 8 : TREE_VALUE (decls), i + 1,
19489 8 : gimplify_omp_ctxp->loop_iter_var[2 * i]);
19490 8 : fail = true;
19491 8 : failures++;
19492 : }
19493 : else
19494 5238 : TREE_VALUE (decls)
19495 2619 : = gimplify_omp_ctxp->loop_iter_var[2 * i + 1];
19496 1136 : if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
19497 : {
19498 16 : error_at (OMP_CLAUSE_LOCATION (c),
19499 : "number of variables in %qs clause with "
19500 : "%<sink%> modifier does not match number of "
19501 : "iteration variables",
19502 16 : OMP_CLAUSE_DOACROSS_DEPEND (c)
19503 : ? "depend" : "doacross");
19504 16 : failures++;
19505 : }
19506 : }
19507 799 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19508 799 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
19509 : {
19510 475 : if (source_c)
19511 : {
19512 4 : error_at (OMP_CLAUSE_LOCATION (c),
19513 : "more than one %qs clause with %<source%> "
19514 : "modifier on an %<ordered%> construct",
19515 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c)
19516 : ? "depend" : "doacross");
19517 4 : failures++;
19518 : }
19519 : else
19520 : source_c = c;
19521 : }
19522 : }
19523 1950 : if (source_c && sink_c)
19524 : {
19525 4 : error_at (OMP_CLAUSE_LOCATION (source_c),
19526 : "%qs clause with %<source%> modifier specified "
19527 : "together with %qs clauses with %<sink%> modifier "
19528 : "on the same construct",
19529 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
19530 4 : OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
19531 4 : failures++;
19532 : }
19533 :
19534 1950 : if (failures)
19535 102 : return gimple_build_nop ();
19536 1848 : return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
19537 : }
19538 :
19539 : /* Gimplify an OMP_INTEROP statement. */
19540 :
19541 : static enum gimplify_status
19542 612 : gimplify_omp_interop (tree *expr_p, gimple_seq *pre_p)
19543 : {
19544 612 : tree expr = *expr_p;
19545 :
19546 612 : gimplify_scan_omp_clauses (&OMP_INTEROP_CLAUSES (expr), pre_p, ORT_TASK,
19547 : OMP_INTEROP);
19548 612 : gimple *stmt = gimple_build_omp_interop (OMP_INTEROP_CLAUSES (expr));
19549 612 : gimplify_seq_add_stmt (pre_p, stmt);
19550 612 : *expr_p = NULL_TREE;
19551 612 : return GS_ALL_DONE;
19552 : }
19553 :
19554 : /* Callback for walk_tree to find an IFN_GOMP_DISPATCH. */
19555 :
19556 : static tree
19557 3100 : find_ifn_gomp_dispatch (tree *tp, int *, void *modify)
19558 : {
19559 3100 : tree t = *tp;
19560 :
19561 3100 : if (TREE_CODE (t) == CALL_EXPR && CALL_EXPR_IFN (t) == IFN_GOMP_DISPATCH)
19562 1414 : return *(tree *) modify ? *(tree *) modify : *tp;
19563 :
19564 2248 : if (TREE_CODE (t) == MODIFY_EXPR)
19565 513 : *(tree *) modify = *tp;
19566 :
19567 : return NULL_TREE;
19568 : }
19569 :
19570 : /* Gimplify an OMP_DISPATCH construct. */
19571 :
19572 : static enum gimplify_status
19573 852 : gimplify_omp_dispatch (tree *expr_p, gimple_seq *pre_p)
19574 : {
19575 852 : tree expr = *expr_p;
19576 852 : gimple_seq body = NULL;
19577 :
19578 852 : gimplify_scan_omp_clauses (&OMP_DISPATCH_CLAUSES (expr), pre_p, ORT_DISPATCH,
19579 : OMP_DISPATCH);
19580 852 : push_gimplify_context ();
19581 :
19582 : // If device clause, adjust ICV
19583 852 : tree device
19584 852 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_DEVICE);
19585 : // If no device clause exists but an interop clause with a single list
19586 : // item, use it to obtain the device number.
19587 852 : if (device)
19588 272 : device = OMP_CLAUSE_DEVICE_ID (device);
19589 : else
19590 : {
19591 580 : tree first_interop_obj
19592 580 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_INTEROP);
19593 580 : if (first_interop_obj)
19594 96 : for (tree c = TREE_CHAIN (first_interop_obj); c; c = TREE_CHAIN (c))
19595 8 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INTEROP)
19596 : {
19597 : first_interop_obj = NULL_TREE;
19598 : break;
19599 : }
19600 95 : if (first_interop_obj)
19601 : {
19602 88 : device = create_tmp_var (integer_type_node);
19603 88 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (first_interop_obj),
19604 : OMP_CLAUSE_DEVICE);
19605 88 : OMP_CLAUSE_DEVICE_ID (c) = device;
19606 88 : TREE_CHAIN (c) = TREE_CHAIN (first_interop_obj);
19607 88 : TREE_CHAIN (first_interop_obj) = c;
19608 88 : first_interop_obj = OMP_CLAUSE_DECL (first_interop_obj);
19609 : /* device = omp_get_interop_int (obj, omp_ipr_device_num, NULL); */
19610 88 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_INTEROP_INT);
19611 88 : fn = build_call_expr (fn, 3, first_interop_obj,
19612 : build_int_cst (integer_type_node, -5),
19613 : null_pointer_node);
19614 88 : gimplify_assign (device, fold_convert (integer_type_node, fn), &body);
19615 : }
19616 : }
19617 852 : tree saved_device_icv = NULL_TREE;
19618 852 : if (device
19619 852 : && (TREE_CODE (device) != INTEGER_CST
19620 709 : || !wi::eq_p (wi::to_wide (device), -1 /* omp_initial_device */)))
19621 : {
19622 : // Save current default-device-var ICV
19623 360 : saved_device_icv = create_tmp_var (integer_type_node);
19624 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
19625 360 : gcall *call = gimple_build_call (fn, 0);
19626 360 : gimple_call_set_lhs (call, saved_device_icv);
19627 360 : gimplify_seq_add_stmt (&body, call);
19628 :
19629 : // Set default device
19630 360 : fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19631 360 : call = gimple_build_call (fn, 1, device);
19632 360 : gimplify_seq_add_stmt (&body, call);
19633 : }
19634 :
19635 : // If the novariants and nocontext clauses are not compile-time constants,
19636 : // we need to generate code for all possible cases:
19637 : // if (novariants) // implies nocontext
19638 : // base()
19639 : // else if (nocontext)
19640 : // variant1()
19641 : // else
19642 : // variant2()
19643 852 : tree *dispatch_body_p = &OMP_DISPATCH_BODY (expr);
19644 852 : if (TREE_CODE (*dispatch_body_p) == BIND_EXPR)
19645 28 : dispatch_body_p = &BIND_EXPR_BODY (*dispatch_body_p);
19646 852 : tree dispatch_body = *dispatch_body_p;
19647 :
19648 : // Look for IFN_GOMP_DISPATCH and extract the base function call
19649 852 : tree base_call_expr = NULL_TREE;
19650 852 : if (TREE_CODE (dispatch_body) == STATEMENT_LIST)
19651 243 : for (tree_stmt_iterator tsi = tsi_start (dispatch_body); !tsi_end_p (tsi);
19652 187 : tsi_next (&tsi))
19653 : {
19654 243 : tree modify = NULL_TREE;
19655 243 : tree stmt = tsi_stmt (tsi);
19656 243 : base_call_expr
19657 243 : = walk_tree (&stmt, find_ifn_gomp_dispatch, &modify, NULL);
19658 243 : if (base_call_expr != NULL_TREE)
19659 : break;
19660 : }
19661 : else
19662 : {
19663 796 : tree modify = NULL_TREE;
19664 796 : base_call_expr
19665 796 : = walk_tree (dispatch_body_p, find_ifn_gomp_dispatch, &modify, NULL);
19666 : }
19667 852 : gcc_assert (base_call_expr != NULL_TREE);
19668 :
19669 852 : tree dst = NULL_TREE;
19670 852 : if (TREE_CODE (base_call_expr) == MODIFY_EXPR)
19671 : {
19672 290 : dst = TREE_OPERAND (base_call_expr, 0);
19673 290 : base_call_expr = TREE_OPERAND (base_call_expr, 1);
19674 : }
19675 :
19676 880 : while (TREE_CODE (base_call_expr) == FLOAT_EXPR
19677 : || TREE_CODE (base_call_expr) == CONVERT_EXPR
19678 : || TREE_CODE (base_call_expr) == COMPLEX_EXPR
19679 : || TREE_CODE (base_call_expr) == INDIRECT_REF
19680 880 : || TREE_CODE (base_call_expr) == NOP_EXPR)
19681 28 : base_call_expr = TREE_OPERAND (base_call_expr, 0);
19682 :
19683 852 : gcc_assert (CALL_EXPR_IFN (base_call_expr) == IFN_GOMP_DISPATCH);
19684 852 : base_call_expr = CALL_EXPR_ARG (base_call_expr, 0);
19685 :
19686 852 : tree base_fndecl = get_callee_fndecl (base_call_expr);
19687 852 : if (base_fndecl != NULL_TREE)
19688 : {
19689 844 : if (DECL_VIRTUAL_P (base_fndecl))
19690 : {
19691 6 : error_at (
19692 3 : EXPR_LOCATION (base_call_expr),
19693 : "%qD is a virtual function but only a direct call is allowed "
19694 : "in a dispatch construct",
19695 3 : DECL_NAME (base_fndecl));
19696 : }
19697 :
19698 : /* We are not actually going to expand the variant call or use
19699 : the result of omp_get_dynamic candidates here; only check that
19700 : it does not trivially resolve to a call to the base function
19701 : so that we can avoid some extra work in building code that's
19702 : not needed in that case. */
19703 844 : tree construct_context = omp_get_construct_context ();
19704 844 : vec<struct omp_variant> all_candidates
19705 844 : = omp_declare_variant_candidates (base_fndecl, construct_context);
19706 844 : gcc_assert (!all_candidates.is_empty ());
19707 844 : vec<struct omp_variant> candidates
19708 844 : = omp_get_dynamic_candidates (all_candidates, construct_context);
19709 844 : tree variant_fndecl
19710 1676 : = (candidates.length () == 1 ? candidates[0].alternative : NULL_TREE);
19711 :
19712 844 : if (base_fndecl != variant_fndecl
19713 844 : && (omp_has_novariants () == -1 || omp_has_nocontext () == -1))
19714 : {
19715 22 : tree novariants_clause = NULL_TREE, nocontext_clause = NULL_TREE,
19716 22 : novariants_cond = NULL_TREE, nocontext_cond = NULL_TREE;
19717 59 : for (tree c = OMP_DISPATCH_CLAUSES (expr); c; c = TREE_CHAIN (c))
19718 : {
19719 37 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOVARIANTS
19720 37 : && !integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
19721 : {
19722 16 : gcc_assert (novariants_cond == NULL_TREE);
19723 16 : novariants_clause = c;
19724 16 : novariants_cond = OMP_CLAUSE_NOVARIANTS_EXPR (c);
19725 : }
19726 21 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOCONTEXT
19727 21 : && !integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
19728 : {
19729 16 : gcc_assert (nocontext_cond == NULL_TREE);
19730 16 : nocontext_clause = c;
19731 16 : nocontext_cond = OMP_CLAUSE_NOCONTEXT_EXPR (c);
19732 : }
19733 : }
19734 22 : gcc_assert (novariants_cond != NULL_TREE
19735 : || nocontext_cond != NULL_TREE);
19736 :
19737 22 : enum gimplify_status ret
19738 22 : = gimplify_expr (&novariants_cond, &body, NULL, is_gimple_val,
19739 : fb_rvalue);
19740 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19741 0 : return ret;
19742 22 : ret = gimplify_expr (&nocontext_cond, &body, NULL, is_gimple_val,
19743 : fb_rvalue);
19744 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19745 : return ret;
19746 :
19747 22 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19748 :
19749 22 : if (novariants_cond != NULL_TREE)
19750 : {
19751 16 : tree base_label = create_artificial_label (UNKNOWN_LOCATION);
19752 16 : tree cond_label = create_artificial_label (UNKNOWN_LOCATION);
19753 16 : gcond *novariants_cond_stmt
19754 16 : = gimple_build_cond_from_tree (novariants_cond, base_label,
19755 : cond_label);
19756 16 : gimplify_seq_add_stmt (&body, novariants_cond_stmt);
19757 :
19758 16 : gimplify_seq_add_stmt (&body, gimple_build_label (base_label));
19759 16 : tree base_call_expr2 = copy_node (base_call_expr);
19760 16 : base_call_expr2
19761 16 : = build_call_expr_internal_loc (EXPR_LOCATION (base_call_expr2),
19762 : IFN_GOMP_DISPATCH,
19763 16 : TREE_TYPE (base_call_expr2), 1,
19764 : base_call_expr2);
19765 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19766 : {
19767 16 : base_call_expr2 = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19768 : base_call_expr2);
19769 : }
19770 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19771 16 : = boolean_true_node;
19772 16 : gimplify_and_add (base_call_expr2, &body);
19773 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19774 :
19775 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19776 16 : = boolean_false_node;
19777 16 : gimplify_seq_add_stmt (&body, gimple_build_label (cond_label));
19778 : }
19779 :
19780 22 : if (nocontext_cond != NULL_TREE)
19781 : {
19782 16 : tree variant1_label = create_artificial_label (UNKNOWN_LOCATION);
19783 16 : tree variant2_label = create_artificial_label (UNKNOWN_LOCATION);
19784 16 : gcond *nocontext_cond_stmt
19785 16 : = gimple_build_cond_from_tree (nocontext_cond, variant1_label,
19786 : variant2_label);
19787 16 : gimplify_seq_add_stmt (&body, nocontext_cond_stmt);
19788 :
19789 32 : gimplify_seq_add_stmt (&body,
19790 16 : gimple_build_label (variant1_label));
19791 16 : tree variant_call_expr = copy_node (base_call_expr);
19792 32 : variant_call_expr = build_call_expr_internal_loc (
19793 16 : EXPR_LOCATION (variant_call_expr), IFN_GOMP_DISPATCH,
19794 16 : TREE_TYPE (variant_call_expr), 1, variant_call_expr);
19795 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19796 : {
19797 16 : variant_call_expr = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19798 : variant_call_expr);
19799 : }
19800 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_true_node;
19801 16 : gimplify_and_add (variant_call_expr, &body);
19802 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19803 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_false_node;
19804 32 : gimplify_seq_add_stmt (&body,
19805 16 : gimple_build_label (variant2_label));
19806 : }
19807 :
19808 22 : tree variant_call_expr = base_call_expr;
19809 22 : variant_call_expr
19810 22 : = build_call_expr_internal_loc (EXPR_LOCATION (variant_call_expr),
19811 : IFN_GOMP_DISPATCH,
19812 22 : TREE_TYPE (variant_call_expr), 1,
19813 : variant_call_expr);
19814 22 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19815 : {
19816 22 : variant_call_expr
19817 22 : = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, variant_call_expr);
19818 : }
19819 22 : gimplify_and_add (variant_call_expr, &body);
19820 22 : gimplify_seq_add_stmt (&body, gimple_build_label (end_label));
19821 : }
19822 : else
19823 822 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19824 : }
19825 : else
19826 8 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19827 :
19828 : // Restore default-device-var ICV
19829 852 : if (saved_device_icv != NULL_TREE)
19830 : {
19831 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19832 360 : gcall *call = gimple_build_call (fn, 1, saved_device_icv);
19833 360 : gimplify_seq_add_stmt (&body, call);
19834 : }
19835 :
19836 : // Wrap dispatch body into a bind
19837 852 : gimple *bind = gimple_build_bind (NULL_TREE, body, NULL_TREE);
19838 852 : pop_gimplify_context (bind);
19839 :
19840 : // Manually tear down context created by gimplify_scan_omp_clauses to avoid a
19841 : // call to gimplify_adjust_omp_clauses
19842 852 : gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
19843 852 : if (ctx != NULL)
19844 : {
19845 852 : gcc_assert (ctx->code == OMP_DISPATCH);
19846 852 : gimplify_omp_ctxp = ctx->outer_context;
19847 852 : delete_omp_context (ctx);
19848 : }
19849 :
19850 : // Remove nowait as it has no effect on dispatch (OpenMP 5.2), device as it
19851 : // has been handled above, and depend as the front end handled it by inserting
19852 : // taskwait.
19853 852 : tree *dispatch_clauses_ptr = &OMP_DISPATCH_CLAUSES (expr);
19854 1445 : for (tree c = *dispatch_clauses_ptr; c; c = *dispatch_clauses_ptr)
19855 : {
19856 991 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT
19857 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
19858 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE)
19859 : {
19860 398 : *dispatch_clauses_ptr = OMP_CLAUSE_CHAIN (c);
19861 398 : break;
19862 : }
19863 : else
19864 593 : dispatch_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
19865 : }
19866 :
19867 852 : gimple *stmt = gimple_build_omp_dispatch (bind, OMP_DISPATCH_CLAUSES (expr));
19868 852 : gimplify_seq_add_stmt (pre_p, stmt);
19869 852 : *expr_p = NULL_TREE;
19870 852 : return GS_ALL_DONE;
19871 : }
19872 :
19873 : /* Expand a metadirective that has been resolved at gimplification time
19874 : into the candidate directive variants in CANDIDATES. */
19875 :
19876 : static enum gimplify_status
19877 170 : expand_omp_metadirective (vec<struct omp_variant> &candidates,
19878 : gimple_seq *pre_p)
19879 : {
19880 170 : auto_vec<tree> selectors;
19881 170 : auto_vec<tree> directive_labels;
19882 170 : auto_vec<gimple_seq> directive_bodies;
19883 170 : tree body_label = NULL_TREE;
19884 170 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19885 :
19886 : /* Construct bodies for each candidate. */
19887 415 : for (unsigned i = 0; i < candidates.length(); i++)
19888 : {
19889 245 : struct omp_variant &candidate = candidates[i];
19890 245 : gimple_seq body = NULL;
19891 :
19892 245 : selectors.safe_push (omp_dynamic_cond (candidate.selector,
19893 : find_supercontext ()));
19894 245 : directive_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
19895 :
19896 245 : gimplify_seq_add_stmt (&body,
19897 245 : gimple_build_label (directive_labels.last ()));
19898 245 : if (candidate.alternative != NULL_TREE)
19899 245 : gimplify_stmt (&candidate.alternative, &body);
19900 245 : if (candidate.body != NULL_TREE)
19901 : {
19902 35 : if (body_label != NULL_TREE)
19903 0 : gimplify_seq_add_stmt (&body, gimple_build_goto (body_label));
19904 : else
19905 : {
19906 35 : body_label = create_artificial_label (UNKNOWN_LOCATION);
19907 35 : gimplify_seq_add_stmt (&body, gimple_build_label (body_label));
19908 35 : gimplify_stmt (&candidate.body, &body);
19909 : }
19910 : }
19911 :
19912 245 : directive_bodies.safe_push (body);
19913 : }
19914 :
19915 170 : auto_vec<tree> cond_labels;
19916 :
19917 170 : cond_labels.safe_push (NULL_TREE);
19918 376 : for (unsigned i = 1; i < candidates.length () - 1; i++)
19919 18 : cond_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
19920 170 : if (candidates.length () > 1)
19921 57 : cond_labels.safe_push (directive_labels.last ());
19922 :
19923 : /* Generate conditionals to test each dynamic selector in turn, executing
19924 : the directive candidate if successful. */
19925 490 : for (unsigned i = 0; i < candidates.length () - 1; i++)
19926 : {
19927 75 : if (i != 0)
19928 18 : gimplify_seq_add_stmt (pre_p, gimple_build_label (cond_labels [i]));
19929 :
19930 75 : enum gimplify_status ret = gimplify_expr (&selectors[i], pre_p, NULL,
19931 : is_gimple_val, fb_rvalue);
19932 75 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19933 : return ret;
19934 :
19935 75 : gcond *cond_stmt
19936 75 : = gimple_build_cond_from_tree (selectors[i], directive_labels[i],
19937 75 : cond_labels[i + 1]);
19938 :
19939 75 : gimplify_seq_add_stmt (pre_p, cond_stmt);
19940 75 : gimplify_seq_add_seq (pre_p, directive_bodies[i]);
19941 75 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (end_label));
19942 : }
19943 :
19944 170 : gimplify_seq_add_seq (pre_p, directive_bodies.last ());
19945 170 : gimplify_seq_add_stmt (pre_p, gimple_build_label (end_label));
19946 :
19947 170 : return GS_ALL_DONE;
19948 170 : }
19949 :
19950 : /* Expand a variant construct that requires late resolution in the ompdevlow
19951 : pass. It's a bit easier to do this in tree form and then gimplify that,
19952 : than to emit gimple. The output is going to look something like:
19953 :
19954 : switch_var = OMP_NEXT_VARIANT (0, state);
19955 : loop_label:
19956 : switch (switch_var)
19957 : {
19958 : case 1:
19959 : if (dynamic_selector_predicate_1)
19960 : {
19961 : alternative_1;
19962 : goto end_label;
19963 : }
19964 : else
19965 : {
19966 : switch_var = OMP_NEXT_VARIANT (1, state);
19967 : goto loop_label;
19968 : }
19969 : case 2:
19970 : ...
19971 : }
19972 : end_label:
19973 :
19974 : OMP_NEXT_VARIANT is a magic cookie that is replaced with the switch variable
19975 : index of the next variant to try, after late resolution. */
19976 :
19977 : static tree
19978 16 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
19979 : tree construct_context)
19980 : {
19981 16 : tree body_label = NULL_TREE;
19982 16 : tree standalone_body = NULL_TREE;
19983 16 : tree loop_label = create_artificial_label (UNKNOWN_LOCATION);
19984 16 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19985 32 : tree selectors = make_tree_vec (all_candidates.length ());
19986 16 : tree switch_body = NULL_TREE;
19987 16 : tree switch_var = create_tmp_var (integer_type_node, "variant");
19988 16 : tree state = tree_cons (NULL_TREE, construct_context, selectors);
19989 :
19990 92 : for (unsigned int i = 0; i < all_candidates.length (); i++)
19991 : {
19992 76 : tree selector = all_candidates[i].selector;
19993 76 : tree alternative = all_candidates[i].alternative;
19994 76 : tree body = all_candidates[i].body;
19995 76 : TREE_VEC_ELT (selectors, i) = selector;
19996 :
19997 : /* Case label. Numbering is 1-based. */
19998 76 : tree case_val = build_int_cst (integer_type_node, i + 1);
19999 76 : tree case_label
20000 76 : = build_case_label (case_val, NULL_TREE,
20001 : create_artificial_label (UNKNOWN_LOCATION));
20002 76 : append_to_statement_list (case_label, &switch_body);
20003 :
20004 : /* The actual body of the variant. */
20005 76 : tree variant_body = NULL_TREE;
20006 76 : append_to_statement_list (alternative, &variant_body);
20007 :
20008 76 : if (body != NULL_TREE)
20009 : {
20010 0 : if (standalone_body == NULL)
20011 : {
20012 0 : standalone_body = body;
20013 0 : body_label = create_artificial_label (UNKNOWN_LOCATION);
20014 : }
20015 0 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20016 : body_label),
20017 : &variant_body);
20018 : }
20019 : else
20020 76 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20021 : end_label),
20022 : &variant_body);
20023 :
20024 : /* If this is a dynamic selector, wrap variant_body with a conditional.
20025 : If the predicate doesn't match, the else clause sets switch_var and
20026 : jumps to loop_var to try again. */
20027 76 : tree dynamic_selector = omp_dynamic_cond (selector, find_supercontext ());
20028 76 : if (dynamic_selector)
20029 : {
20030 20 : tree else_stmt = NULL_TREE;
20031 20 : tree next = build2 (OMP_NEXT_VARIANT, integer_type_node,
20032 : case_val, state);
20033 20 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20034 : switch_var, next),
20035 : &else_stmt);
20036 20 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20037 : loop_label),
20038 : &else_stmt);
20039 20 : variant_body = build3 (COND_EXPR, void_type_node, dynamic_selector,
20040 : variant_body, else_stmt);
20041 : }
20042 76 : append_to_statement_list (variant_body, &switch_body);
20043 : }
20044 :
20045 : /* Put it all together. */
20046 16 : tree result = NULL_TREE;
20047 16 : tree first = build2 (OMP_NEXT_VARIANT, integer_type_node, integer_zero_node,
20048 : state);
20049 16 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20050 : switch_var, first),
20051 : &result);
20052 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, loop_label),
20053 : &result);
20054 16 : append_to_statement_list (build2 (SWITCH_EXPR, integer_type_node,
20055 : switch_var, switch_body),
20056 : &result);
20057 16 : if (standalone_body)
20058 : {
20059 0 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
20060 : body_label),
20061 : &result);
20062 0 : append_to_statement_list (standalone_body, &result);
20063 : }
20064 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, end_label),
20065 : &result);
20066 16 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
20067 16 : return result;
20068 : }
20069 :
20070 :
20071 : /* Gimplify an OMP_METADIRECTIVE construct. EXPR is the tree version.
20072 : The metadirective will be resolved at this point if possible, otherwise
20073 : a GIMPLE_OMP_VARIANT_CONSTRUCT is created. */
20074 :
20075 : static enum gimplify_status
20076 174 : gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *,
20077 : bool (*) (tree), fallback_t)
20078 : {
20079 : /* Try to resolve the metadirective. */
20080 174 : tree construct_context = omp_get_construct_context ();
20081 174 : vec<struct omp_variant> all_candidates
20082 174 : = omp_metadirective_candidates (*expr_p, construct_context);
20083 174 : vec<struct omp_variant> candidates
20084 174 : = omp_get_dynamic_candidates (all_candidates, construct_context);
20085 174 : if (!candidates.is_empty ())
20086 170 : return expand_omp_metadirective (candidates, pre_p);
20087 :
20088 : /* The metadirective cannot be resolved yet. Turn it into a loop with
20089 : a nested switch statement, using OMP_NEXT_VARIANT to set the control
20090 : variable for the switch. */
20091 4 : *expr_p = expand_late_variant_directive (all_candidates, construct_context);
20092 4 : return GS_OK;
20093 : }
20094 :
20095 : /* Gimplify an OMP_DECLARE_MAPPER node (by just removing it). */
20096 :
20097 : static enum gimplify_status
20098 0 : gimplify_omp_declare_mapper (tree *expr_p)
20099 : {
20100 0 : *expr_p = NULL_TREE;
20101 0 : return GS_ALL_DONE;
20102 : }
20103 :
20104 : /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
20105 : expression produces a value to be used as an operand inside a GIMPLE
20106 : statement, the value will be stored back in *EXPR_P. This value will
20107 : be a tree of class tcc_declaration, tcc_constant, tcc_reference or
20108 : an SSA_NAME. The corresponding sequence of GIMPLE statements is
20109 : emitted in PRE_P and POST_P.
20110 :
20111 : Additionally, this process may overwrite parts of the input
20112 : expression during gimplification. Ideally, it should be
20113 : possible to do non-destructive gimplification.
20114 :
20115 : EXPR_P points to the GENERIC expression to convert to GIMPLE. If
20116 : the expression needs to evaluate to a value to be used as
20117 : an operand in a GIMPLE statement, this value will be stored in
20118 : *EXPR_P on exit. This happens when the caller specifies one
20119 : of fb_lvalue or fb_rvalue fallback flags.
20120 :
20121 : PRE_P will contain the sequence of GIMPLE statements corresponding
20122 : to the evaluation of EXPR and all the side-effects that must
20123 : be executed before the main expression. On exit, the last
20124 : statement of PRE_P is the core statement being gimplified. For
20125 : instance, when gimplifying 'if (++a)' the last statement in
20126 : PRE_P will be 'if (t.1)' where t.1 is the result of
20127 : pre-incrementing 'a'.
20128 :
20129 : POST_P will contain the sequence of GIMPLE statements corresponding
20130 : to the evaluation of all the side-effects that must be executed
20131 : after the main expression. If this is NULL, the post
20132 : side-effects are stored at the end of PRE_P.
20133 :
20134 : The reason why the output is split in two is to handle post
20135 : side-effects explicitly. In some cases, an expression may have
20136 : inner and outer post side-effects which need to be emitted in
20137 : an order different from the one given by the recursive
20138 : traversal. For instance, for the expression (*p--)++ the post
20139 : side-effects of '--' must actually occur *after* the post
20140 : side-effects of '++'. However, gimplification will first visit
20141 : the inner expression, so if a separate POST sequence was not
20142 : used, the resulting sequence would be:
20143 :
20144 : 1 t.1 = *p
20145 : 2 p = p - 1
20146 : 3 t.2 = t.1 + 1
20147 : 4 *p = t.2
20148 :
20149 : However, the post-decrement operation in line #2 must not be
20150 : evaluated until after the store to *p at line #4, so the
20151 : correct sequence should be:
20152 :
20153 : 1 t.1 = *p
20154 : 2 t.2 = t.1 + 1
20155 : 3 *p = t.2
20156 : 4 p = p - 1
20157 :
20158 : So, by specifying a separate post queue, it is possible
20159 : to emit the post side-effects in the correct order.
20160 : If POST_P is NULL, an internal queue will be used. Before
20161 : returning to the caller, the sequence POST_P is appended to
20162 : the main output sequence PRE_P.
20163 :
20164 : GIMPLE_TEST_F points to a function that takes a tree T and
20165 : returns nonzero if T is in the GIMPLE form requested by the
20166 : caller. The GIMPLE predicates are in gimple.cc.
20167 :
20168 : FALLBACK tells the function what sort of a temporary we want if
20169 : gimplification cannot produce an expression that complies with
20170 : GIMPLE_TEST_F.
20171 :
20172 : fb_none means that no temporary should be generated
20173 : fb_rvalue means that an rvalue is OK to generate
20174 : fb_lvalue means that an lvalue is OK to generate
20175 : fb_either means that either is OK, but an lvalue is preferable.
20176 : fb_mayfail means that gimplification may fail (in which case
20177 : GS_ERROR will be returned)
20178 :
20179 : The return value is either GS_ERROR or GS_ALL_DONE, since this
20180 : function iterates until EXPR is completely gimplified or an error
20181 : occurs. */
20182 :
20183 : enum gimplify_status
20184 514139856 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
20185 : bool (*gimple_test_f) (tree), fallback_t fallback)
20186 : {
20187 514139856 : tree tmp;
20188 514139856 : gimple_seq internal_pre = NULL;
20189 514139856 : gimple_seq internal_post = NULL;
20190 514139856 : tree save_expr;
20191 514139856 : bool is_statement;
20192 514139856 : location_t saved_location;
20193 514139856 : enum gimplify_status ret;
20194 514139856 : gimple_stmt_iterator pre_last_gsi, post_last_gsi;
20195 514139856 : tree label;
20196 :
20197 514139856 : save_expr = *expr_p;
20198 514139856 : if (save_expr == NULL_TREE)
20199 : return GS_ALL_DONE;
20200 :
20201 : /* If we are gimplifying a top-level statement, PRE_P must be valid. */
20202 462292913 : is_statement = gimple_test_f == is_gimple_stmt;
20203 462292913 : if (is_statement)
20204 100380726 : gcc_assert (pre_p);
20205 :
20206 : /* Consistency checks. */
20207 462292913 : if (gimple_test_f == is_gimple_reg)
20208 6219072 : gcc_assert (fallback & (fb_rvalue | fb_lvalue));
20209 456073841 : else if (gimple_test_f == is_gimple_val
20210 336277208 : || gimple_test_f == is_gimple_call_addr
20211 320132746 : || gimple_test_f == is_gimple_condexpr_for_cond
20212 314563629 : || gimple_test_f == is_gimple_mem_rhs
20213 314419805 : || gimple_test_f == is_gimple_mem_rhs_or_call
20214 303267902 : || gimple_test_f == is_gimple_reg_rhs
20215 302658207 : || gimple_test_f == is_gimple_reg_rhs_or_call
20216 231157112 : || gimple_test_f == is_gimple_asm_val
20217 231117426 : || gimple_test_f == is_gimple_mem_ref_addr)
20218 240124708 : gcc_assert (fallback & fb_rvalue);
20219 215949133 : else if (gimple_test_f == is_gimple_min_lval
20220 185991507 : || gimple_test_f == is_gimple_lvalue)
20221 83126709 : gcc_assert (fallback & fb_lvalue);
20222 132822424 : else if (gimple_test_f == is_gimple_addressable)
20223 32441698 : gcc_assert (fallback & fb_either);
20224 100380726 : else if (gimple_test_f == is_gimple_stmt)
20225 100380726 : gcc_assert (fallback == fb_none);
20226 : else
20227 : {
20228 : /* We should have recognized the GIMPLE_TEST_F predicate to
20229 : know what kind of fallback to use in case a temporary is
20230 : needed to hold the value or address of *EXPR_P. */
20231 0 : gcc_unreachable ();
20232 : }
20233 :
20234 : /* We used to check the predicate here and return immediately if it
20235 : succeeds. This is wrong; the design is for gimplification to be
20236 : idempotent, and for the predicates to only test for valid forms, not
20237 : whether they are fully simplified. */
20238 462292913 : if (pre_p == NULL)
20239 0 : pre_p = &internal_pre;
20240 :
20241 462292913 : if (post_p == NULL)
20242 185706736 : post_p = &internal_post;
20243 :
20244 : /* Remember the last statements added to PRE_P and POST_P. Every
20245 : new statement added by the gimplification helpers needs to be
20246 : annotated with location information. To centralize the
20247 : responsibility, we remember the last statement that had been
20248 : added to both queues before gimplifying *EXPR_P. If
20249 : gimplification produces new statements in PRE_P and POST_P, those
20250 : statements will be annotated with the same location information
20251 : as *EXPR_P. */
20252 462292913 : pre_last_gsi = gsi_last (*pre_p);
20253 462292913 : post_last_gsi = gsi_last (*post_p);
20254 :
20255 462292913 : saved_location = input_location;
20256 462292913 : if (save_expr != error_mark_node
20257 462292913 : && EXPR_HAS_LOCATION (*expr_p))
20258 173015986 : input_location = EXPR_LOCATION (*expr_p);
20259 :
20260 : /* Loop over the specific gimplifiers until the toplevel node
20261 : remains the same. */
20262 480203642 : do
20263 : {
20264 : /* Strip away as many useless type conversions as possible
20265 : at the toplevel. */
20266 480203642 : STRIP_USELESS_TYPE_CONVERSION (*expr_p);
20267 :
20268 : /* Remember the expr. */
20269 480203642 : save_expr = *expr_p;
20270 :
20271 : /* Die, die, die, my darling. */
20272 480203642 : if (error_operand_p (save_expr))
20273 : {
20274 : ret = GS_ERROR;
20275 : break;
20276 : }
20277 :
20278 : /* Do any language-specific gimplification. */
20279 480199974 : ret = ((enum gimplify_status)
20280 480199974 : lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
20281 480199974 : if (ret == GS_OK)
20282 : {
20283 27756025 : if (*expr_p == NULL_TREE)
20284 : break;
20285 27756025 : if (*expr_p != save_expr)
20286 4645252 : continue;
20287 : }
20288 452443949 : else if (ret != GS_UNHANDLED)
20289 : break;
20290 :
20291 : /* Make sure that all the cases set 'ret' appropriately. */
20292 474988470 : ret = GS_UNHANDLED;
20293 474988470 : switch (TREE_CODE (*expr_p))
20294 : {
20295 : /* First deal with the special cases. */
20296 :
20297 1125563 : case POSTINCREMENT_EXPR:
20298 1125563 : case POSTDECREMENT_EXPR:
20299 1125563 : case PREINCREMENT_EXPR:
20300 1125563 : case PREDECREMENT_EXPR:
20301 2251126 : ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
20302 : fallback != fb_none,
20303 1125563 : TREE_TYPE (*expr_p));
20304 1125563 : break;
20305 :
20306 589180 : case VIEW_CONVERT_EXPR:
20307 589180 : if ((fallback & fb_rvalue)
20308 589054 : && is_gimple_reg_type (TREE_TYPE (*expr_p))
20309 1002731 : && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
20310 : {
20311 401801 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20312 : post_p, is_gimple_val, fb_rvalue);
20313 401801 : recalculate_side_effects (*expr_p);
20314 401801 : break;
20315 : }
20316 : /* Fallthru. */
20317 :
20318 29894761 : case ARRAY_REF:
20319 29894761 : case ARRAY_RANGE_REF:
20320 29894761 : case REALPART_EXPR:
20321 29894761 : case IMAGPART_EXPR:
20322 29894761 : case COMPONENT_REF:
20323 29894761 : ret = gimplify_compound_lval (expr_p, pre_p, post_p,
20324 : fallback ? fallback : fb_rvalue);
20325 29894761 : break;
20326 :
20327 6186388 : case COND_EXPR:
20328 6186388 : ret = gimplify_cond_expr (expr_p, pre_p, fallback);
20329 :
20330 : /* C99 code may assign to an array in a structure value of a
20331 : conditional expression, and this has undefined behavior
20332 : only on execution, so create a temporary if an lvalue is
20333 : required. */
20334 6186388 : if (fallback == fb_lvalue)
20335 : {
20336 7 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20337 7 : mark_addressable (*expr_p);
20338 7 : ret = GS_OK;
20339 : }
20340 : break;
20341 :
20342 16669640 : case CALL_EXPR:
20343 16669640 : ret = gimplify_call_expr (expr_p, pre_p, fallback);
20344 :
20345 : /* C99 code may assign to an array in a structure returned
20346 : from a function, and this has undefined behavior only on
20347 : execution, so create a temporary if an lvalue is
20348 : required. */
20349 16669640 : if (fallback == fb_lvalue)
20350 : {
20351 17299 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20352 17299 : mark_addressable (*expr_p);
20353 17299 : ret = GS_OK;
20354 : }
20355 : break;
20356 :
20357 0 : case TREE_LIST:
20358 0 : gcc_unreachable ();
20359 :
20360 0 : case OMP_ARRAY_SECTION:
20361 0 : gcc_unreachable ();
20362 :
20363 478764 : case COMPOUND_EXPR:
20364 478764 : ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
20365 478764 : break;
20366 :
20367 37190 : case COMPOUND_LITERAL_EXPR:
20368 37190 : ret = gimplify_compound_literal_expr (expr_p, pre_p,
20369 : gimple_test_f, fallback);
20370 37190 : break;
20371 :
20372 49865939 : case MODIFY_EXPR:
20373 49865939 : case INIT_EXPR:
20374 49865939 : ret = gimplify_modify_expr (expr_p, pre_p, post_p,
20375 : fallback != fb_none);
20376 49865939 : break;
20377 :
20378 112201 : case TRUTH_ANDIF_EXPR:
20379 112201 : case TRUTH_ORIF_EXPR:
20380 112201 : {
20381 : /* Preserve the original type of the expression and the
20382 : source location of the outer expression. */
20383 112201 : tree org_type = TREE_TYPE (*expr_p);
20384 112201 : *expr_p = gimple_boolify (*expr_p);
20385 112201 : *expr_p = build3_loc (input_location, COND_EXPR,
20386 : org_type, *expr_p,
20387 : fold_convert_loc
20388 : (input_location,
20389 : org_type, boolean_true_node),
20390 : fold_convert_loc
20391 : (input_location,
20392 : org_type, boolean_false_node));
20393 112201 : ret = GS_OK;
20394 112201 : break;
20395 : }
20396 :
20397 229981 : case TRUTH_NOT_EXPR:
20398 229981 : {
20399 229981 : tree type = TREE_TYPE (*expr_p);
20400 : /* The parsers are careful to generate TRUTH_NOT_EXPR
20401 : only with operands that are always zero or one.
20402 : We do not fold here but handle the only interesting case
20403 : manually, as fold may re-introduce the TRUTH_NOT_EXPR. */
20404 229981 : *expr_p = gimple_boolify (*expr_p);
20405 229981 : if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
20406 229981 : *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
20407 229981 : TREE_TYPE (*expr_p),
20408 229981 : TREE_OPERAND (*expr_p, 0));
20409 : else
20410 0 : *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
20411 0 : TREE_TYPE (*expr_p),
20412 0 : TREE_OPERAND (*expr_p, 0),
20413 0 : build_int_cst (TREE_TYPE (*expr_p), 1));
20414 229981 : if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
20415 4905 : *expr_p = fold_convert_loc (input_location, type, *expr_p);
20416 : ret = GS_OK;
20417 : break;
20418 : }
20419 :
20420 32518792 : case ADDR_EXPR:
20421 32518792 : ret = gimplify_addr_expr (expr_p, pre_p, post_p);
20422 32518792 : break;
20423 :
20424 5521 : case ANNOTATE_EXPR:
20425 5521 : {
20426 5521 : tree cond = TREE_OPERAND (*expr_p, 0);
20427 5521 : tree kind = TREE_OPERAND (*expr_p, 1);
20428 5521 : tree data = TREE_OPERAND (*expr_p, 2);
20429 5521 : tree type = TREE_TYPE (cond);
20430 5521 : if (!INTEGRAL_TYPE_P (type))
20431 : {
20432 0 : *expr_p = cond;
20433 0 : ret = GS_OK;
20434 0 : break;
20435 : }
20436 5521 : tree tmp = create_tmp_var (type);
20437 5521 : gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
20438 5521 : gcall *call
20439 5521 : = gimple_build_call_internal (IFN_ANNOTATE, 3, cond, kind, data);
20440 5521 : gimple_call_set_lhs (call, tmp);
20441 5521 : gimplify_seq_add_stmt (pre_p, call);
20442 5521 : *expr_p = tmp;
20443 5521 : ret = GS_ALL_DONE;
20444 5521 : break;
20445 : }
20446 :
20447 51131 : case VA_ARG_EXPR:
20448 51131 : ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
20449 51131 : break;
20450 :
20451 17119553 : CASE_CONVERT:
20452 17119553 : if (IS_EMPTY_STMT (*expr_p))
20453 : {
20454 : ret = GS_ALL_DONE;
20455 : break;
20456 : }
20457 :
20458 15407451 : if (VOID_TYPE_P (TREE_TYPE (*expr_p))
20459 15407451 : || fallback == fb_none)
20460 : {
20461 : /* Just strip a conversion to void (or in void context) and
20462 : try again. */
20463 2582776 : *expr_p = TREE_OPERAND (*expr_p, 0);
20464 2582776 : ret = GS_OK;
20465 2582776 : break;
20466 : }
20467 :
20468 12824675 : ret = gimplify_conversion (expr_p);
20469 12824675 : if (ret == GS_ERROR)
20470 : break;
20471 12824675 : if (*expr_p != save_expr)
20472 : break;
20473 : /* FALLTHRU */
20474 :
20475 12951073 : case FIX_TRUNC_EXPR:
20476 : /* unary_expr: ... | '(' cast ')' val | ... */
20477 12951073 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20478 : is_gimple_val, fb_rvalue);
20479 12951073 : recalculate_side_effects (*expr_p);
20480 12951073 : break;
20481 :
20482 6148330 : case INDIRECT_REF:
20483 6148330 : {
20484 6148330 : bool volatilep = TREE_THIS_VOLATILE (*expr_p);
20485 6148330 : bool notrap = TREE_THIS_NOTRAP (*expr_p);
20486 6148330 : tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
20487 :
20488 6148330 : *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
20489 6148330 : if (*expr_p != save_expr)
20490 : {
20491 : ret = GS_OK;
20492 : break;
20493 : }
20494 :
20495 6130482 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20496 : is_gimple_reg, fb_rvalue);
20497 6130482 : if (ret == GS_ERROR)
20498 : break;
20499 :
20500 6130479 : recalculate_side_effects (*expr_p);
20501 12260958 : *expr_p = fold_build2_loc (input_location, MEM_REF,
20502 6130479 : TREE_TYPE (*expr_p),
20503 6130479 : TREE_OPERAND (*expr_p, 0),
20504 : build_int_cst (saved_ptr_type, 0));
20505 6130479 : TREE_THIS_VOLATILE (*expr_p) = volatilep;
20506 6130479 : TREE_THIS_NOTRAP (*expr_p) = notrap;
20507 6130479 : ret = GS_OK;
20508 6130479 : break;
20509 : }
20510 :
20511 : /* We arrive here through the various re-gimplifcation paths. */
20512 15642207 : case MEM_REF:
20513 : /* First try re-folding the whole thing. */
20514 15642207 : tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
20515 : TREE_OPERAND (*expr_p, 0),
20516 : TREE_OPERAND (*expr_p, 1));
20517 15642207 : if (tmp)
20518 : {
20519 6578 : REF_REVERSE_STORAGE_ORDER (tmp)
20520 3289 : = REF_REVERSE_STORAGE_ORDER (*expr_p);
20521 3289 : *expr_p = tmp;
20522 3289 : recalculate_side_effects (*expr_p);
20523 3289 : ret = GS_OK;
20524 3289 : break;
20525 : }
20526 : /* Avoid re-gimplifying the address operand if it is already
20527 : in suitable form. Re-gimplifying would mark the address
20528 : operand addressable. Always gimplify when not in SSA form
20529 : as we still may have to gimplify decls with value-exprs. */
20530 15638918 : if (!gimplify_ctxp || !gimple_in_ssa_p (cfun)
20531 16648569 : || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
20532 : {
20533 14684378 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20534 : is_gimple_mem_ref_addr, fb_rvalue);
20535 14684378 : if (ret == GS_ERROR)
20536 : break;
20537 : }
20538 15638918 : recalculate_side_effects (*expr_p);
20539 15638918 : ret = GS_ALL_DONE;
20540 15638918 : break;
20541 :
20542 : /* Constants need not be gimplified. */
20543 43921159 : case INTEGER_CST:
20544 43921159 : case REAL_CST:
20545 43921159 : case FIXED_CST:
20546 43921159 : case STRING_CST:
20547 43921159 : case COMPLEX_CST:
20548 43921159 : case VECTOR_CST:
20549 : /* Drop the overflow flag on constants, we do not want
20550 : that in the GIMPLE IL. */
20551 43921159 : if (TREE_OVERFLOW_P (*expr_p))
20552 900 : *expr_p = drop_tree_overflow (*expr_p);
20553 : ret = GS_ALL_DONE;
20554 : break;
20555 :
20556 117197 : case CONST_DECL:
20557 : /* If we require an lvalue, such as for ADDR_EXPR, retain the
20558 : CONST_DECL node. Otherwise the decl is replaceable by its
20559 : value. */
20560 : /* ??? Should be == fb_lvalue, but ADDR_EXPR passes fb_either. */
20561 117197 : if (fallback & fb_lvalue)
20562 : ret = GS_ALL_DONE;
20563 : else
20564 : {
20565 3236 : *expr_p = DECL_INITIAL (*expr_p);
20566 3236 : ret = GS_OK;
20567 : }
20568 : break;
20569 :
20570 6523205 : case DECL_EXPR:
20571 6523205 : ret = gimplify_decl_expr (expr_p, pre_p);
20572 6523205 : break;
20573 :
20574 5927825 : case BIND_EXPR:
20575 5927825 : ret = gimplify_bind_expr (expr_p, pre_p);
20576 5927825 : break;
20577 :
20578 203308 : case LOOP_EXPR:
20579 203308 : ret = gimplify_loop_expr (expr_p, pre_p);
20580 203308 : break;
20581 :
20582 49515 : case SWITCH_EXPR:
20583 49515 : ret = gimplify_switch_expr (expr_p, pre_p);
20584 49515 : break;
20585 :
20586 3069 : case EXIT_EXPR:
20587 3069 : ret = gimplify_exit_expr (expr_p);
20588 3069 : break;
20589 :
20590 1097331 : case GOTO_EXPR:
20591 : /* If the target is not LABEL, then it is a computed jump
20592 : and the target needs to be gimplified. */
20593 1097331 : if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
20594 : {
20595 1118 : ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
20596 : NULL, is_gimple_val, fb_rvalue);
20597 1118 : if (ret == GS_ERROR)
20598 : break;
20599 : }
20600 2194660 : gimplify_seq_add_stmt (pre_p,
20601 1097330 : gimple_build_goto (GOTO_DESTINATION (*expr_p)));
20602 1097330 : ret = GS_ALL_DONE;
20603 1097330 : break;
20604 :
20605 102465 : case PREDICT_EXPR:
20606 409860 : gimplify_seq_add_stmt (pre_p,
20607 102465 : gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
20608 102465 : PREDICT_EXPR_OUTCOME (*expr_p)));
20609 102465 : ret = GS_ALL_DONE;
20610 102465 : break;
20611 :
20612 2544320 : case LABEL_EXPR:
20613 2544320 : ret = gimplify_label_expr (expr_p, pre_p);
20614 2544320 : label = LABEL_EXPR_LABEL (*expr_p);
20615 2544320 : gcc_assert (decl_function_context (label) == current_function_decl);
20616 :
20617 : /* If the label is used in a goto statement, or address of the label
20618 : is taken, we need to unpoison all variables that were seen so far.
20619 : Doing so would prevent us from reporting a false positives. */
20620 2544320 : if (asan_poisoned_variables
20621 4391 : && asan_used_labels != NULL
20622 1325 : && asan_used_labels->contains (label)
20623 2545232 : && !gimplify_omp_ctxp)
20624 904 : asan_poison_variables (asan_poisoned_variables, false, pre_p);
20625 : break;
20626 :
20627 1034044 : case CASE_LABEL_EXPR:
20628 1034044 : ret = gimplify_case_label_expr (expr_p, pre_p);
20629 :
20630 1034044 : if (gimplify_ctxp->live_switch_vars)
20631 1033857 : asan_poison_variables (gimplify_ctxp->live_switch_vars, false,
20632 : pre_p);
20633 : break;
20634 :
20635 2201605 : case RETURN_EXPR:
20636 2201605 : ret = gimplify_return_expr (*expr_p, pre_p);
20637 2201605 : break;
20638 :
20639 950341 : case CONSTRUCTOR:
20640 : /* Don't reduce this in place; let gimplify_init_constructor work its
20641 : magic. Buf if we're just elaborating this for side effects, just
20642 : gimplify any element that has side-effects. */
20643 950341 : if (fallback == fb_none)
20644 : {
20645 358 : unsigned HOST_WIDE_INT ix;
20646 358 : tree val;
20647 358 : tree temp = NULL_TREE;
20648 375 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
20649 17 : if (TREE_SIDE_EFFECTS (val))
20650 4 : append_to_statement_list (val, &temp);
20651 :
20652 358 : *expr_p = temp;
20653 358 : ret = temp ? GS_OK : GS_ALL_DONE;
20654 : }
20655 : /* C99 code may assign to an array in a constructed
20656 : structure or union, and this has undefined behavior only
20657 : on execution, so create a temporary if an lvalue is
20658 : required. */
20659 949983 : else if (fallback == fb_lvalue)
20660 : {
20661 11 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20662 11 : mark_addressable (*expr_p);
20663 11 : ret = GS_OK;
20664 : }
20665 : else
20666 : ret = GS_ALL_DONE;
20667 : break;
20668 :
20669 : /* The following are special cases that are not handled by the
20670 : original GIMPLE grammar. */
20671 :
20672 : /* SAVE_EXPR nodes are converted into a GIMPLE identifier and
20673 : eliminated. */
20674 439210 : case SAVE_EXPR:
20675 439210 : ret = gimplify_save_expr (expr_p, pre_p, post_p);
20676 439210 : break;
20677 :
20678 377723 : case BIT_FIELD_REF:
20679 377723 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20680 : post_p, is_gimple_lvalue, fb_either);
20681 377723 : recalculate_side_effects (*expr_p);
20682 377723 : break;
20683 :
20684 2475 : case TARGET_MEM_REF:
20685 2475 : {
20686 2475 : enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
20687 :
20688 2475 : if (TMR_BASE (*expr_p))
20689 2475 : r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
20690 : post_p, is_gimple_mem_ref_addr, fb_either);
20691 2475 : if (TMR_INDEX (*expr_p))
20692 1203 : r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
20693 : post_p, is_gimple_val, fb_rvalue);
20694 2475 : if (TMR_INDEX2 (*expr_p))
20695 78 : r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
20696 : post_p, is_gimple_val, fb_rvalue);
20697 : /* TMR_STEP and TMR_OFFSET are always integer constants. */
20698 2475 : ret = MIN (r0, r1);
20699 : }
20700 : break;
20701 :
20702 0 : case NON_LVALUE_EXPR:
20703 : /* This should have been stripped above. */
20704 0 : gcc_unreachable ();
20705 :
20706 98207 : case ASM_EXPR:
20707 98207 : ret = gimplify_asm_expr (expr_p, pre_p, post_p);
20708 98207 : break;
20709 :
20710 484720 : case TRY_FINALLY_EXPR:
20711 484720 : case TRY_CATCH_EXPR:
20712 484720 : {
20713 484720 : gimple_seq eval, cleanup;
20714 484720 : gtry *try_;
20715 :
20716 : /* Calls to destructors are generated automatically in FINALLY/CATCH
20717 : block. They should have location as UNKNOWN_LOCATION. However,
20718 : gimplify_call_expr will reset these call stmts to input_location
20719 : if it finds stmt's location is unknown. To prevent resetting for
20720 : destructors, we set the input_location to unknown.
20721 : Note that this only affects the destructor calls in FINALLY/CATCH
20722 : block, and will automatically reset to its original value by the
20723 : end of gimplify_expr. */
20724 484720 : input_location = UNKNOWN_LOCATION;
20725 484720 : eval = cleanup = NULL;
20726 484720 : gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
20727 484720 : bool save_in_handler_expr = gimplify_ctxp->in_handler_expr;
20728 484720 : if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20729 484720 : && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR)
20730 : {
20731 226 : gimple_seq n = NULL, e = NULL;
20732 226 : gimplify_ctxp->in_handler_expr = true;
20733 226 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20734 : 0), &n);
20735 226 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20736 : 1), &e);
20737 226 : if (!gimple_seq_empty_p (n) || !gimple_seq_empty_p (e))
20738 : {
20739 220 : geh_else *stmt = gimple_build_eh_else (n, e);
20740 220 : gimple_seq_add_stmt (&cleanup, stmt);
20741 : }
20742 : }
20743 : else
20744 : {
20745 484494 : gimplify_ctxp->in_handler_expr = true;
20746 484494 : gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
20747 : }
20748 484720 : gimplify_ctxp->in_handler_expr = save_in_handler_expr;
20749 : /* Don't create bogus GIMPLE_TRY with empty cleanup. */
20750 484720 : if (gimple_seq_empty_p (cleanup))
20751 : {
20752 26989 : gimple_seq_add_seq (pre_p, eval);
20753 26989 : ret = GS_ALL_DONE;
20754 26989 : break;
20755 : }
20756 457731 : try_ = gimple_build_try (eval, cleanup,
20757 457731 : TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20758 : ? GIMPLE_TRY_FINALLY
20759 : : GIMPLE_TRY_CATCH);
20760 457731 : if (EXPR_HAS_LOCATION (save_expr))
20761 837408 : gimple_set_location (try_, EXPR_LOCATION (save_expr));
20762 39027 : else if (LOCATION_LOCUS (saved_location) != UNKNOWN_LOCATION)
20763 28580 : gimple_set_location (try_, saved_location);
20764 457731 : if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
20765 163920 : gimple_try_set_catch_is_cleanup (try_,
20766 163920 : TRY_CATCH_IS_CLEANUP (*expr_p));
20767 457731 : gimplify_seq_add_stmt (pre_p, try_);
20768 457731 : ret = GS_ALL_DONE;
20769 457731 : break;
20770 : }
20771 :
20772 5105785 : case CLEANUP_POINT_EXPR:
20773 5105785 : ret = gimplify_cleanup_point_expr (expr_p, pre_p);
20774 5105785 : break;
20775 :
20776 790742 : case TARGET_EXPR:
20777 790742 : ret = gimplify_target_expr (expr_p, pre_p, post_p);
20778 790742 : break;
20779 :
20780 39954 : case CATCH_EXPR:
20781 39954 : {
20782 39954 : gimple *c;
20783 39954 : gimple_seq handler = NULL;
20784 39954 : gimplify_and_add (CATCH_BODY (*expr_p), &handler);
20785 39954 : c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
20786 39954 : gimplify_seq_add_stmt (pre_p, c);
20787 39954 : ret = GS_ALL_DONE;
20788 39954 : break;
20789 : }
20790 :
20791 4632 : case EH_FILTER_EXPR:
20792 4632 : {
20793 4632 : gimple *ehf;
20794 4632 : gimple_seq failure = NULL;
20795 :
20796 4632 : gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
20797 4632 : ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
20798 4632 : copy_warning (ehf, *expr_p);
20799 4632 : gimplify_seq_add_stmt (pre_p, ehf);
20800 4632 : ret = GS_ALL_DONE;
20801 4632 : break;
20802 : }
20803 :
20804 49032 : case OBJ_TYPE_REF:
20805 49032 : {
20806 49032 : enum gimplify_status r0, r1;
20807 49032 : r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p,
20808 : post_p, is_gimple_val, fb_rvalue);
20809 49032 : r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p,
20810 : post_p, is_gimple_val, fb_rvalue);
20811 49032 : TREE_SIDE_EFFECTS (*expr_p) = 0;
20812 49032 : ret = MIN (r0, r1);
20813 : }
20814 : break;
20815 :
20816 40854 : case LABEL_DECL:
20817 : /* We get here when taking the address of a label. We mark
20818 : the label as "forced"; meaning it can never be removed and
20819 : it is a potential target for any computed goto. */
20820 40854 : FORCED_LABEL (*expr_p) = 1;
20821 40854 : ret = GS_ALL_DONE;
20822 40854 : break;
20823 :
20824 8453338 : case STATEMENT_LIST:
20825 8453338 : ret = gimplify_statement_list (expr_p, pre_p);
20826 8453338 : break;
20827 :
20828 1740 : case WITH_SIZE_EXPR:
20829 1740 : {
20830 2022 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20831 : post_p == &internal_post ? NULL : post_p,
20832 : gimple_test_f, fallback);
20833 1740 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
20834 : is_gimple_val, fb_rvalue);
20835 1740 : ret = GS_ALL_DONE;
20836 : }
20837 1740 : break;
20838 :
20839 107873281 : case VAR_DECL:
20840 107873281 : case PARM_DECL:
20841 107873281 : ret = gimplify_var_or_parm_decl (expr_p);
20842 107873281 : break;
20843 :
20844 335402 : case RESULT_DECL:
20845 : /* When within an OMP context, notice uses of variables. */
20846 335402 : if (gimplify_omp_ctxp)
20847 1412 : omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
20848 : /* Handlers can refer to the function result; if that has been
20849 : moved, we need to track it. */
20850 335402 : if (gimplify_ctxp->in_handler_expr && gimplify_ctxp->return_temp)
20851 64 : *expr_p = gimplify_ctxp->return_temp;
20852 : ret = GS_ALL_DONE;
20853 : break;
20854 :
20855 0 : case DEBUG_EXPR_DECL:
20856 0 : gcc_unreachable ();
20857 :
20858 2434223 : case DEBUG_BEGIN_STMT:
20859 4868446 : gimplify_seq_add_stmt (pre_p,
20860 : gimple_build_debug_begin_stmt
20861 2434223 : (TREE_BLOCK (*expr_p),
20862 2434223 : EXPR_LOCATION (*expr_p)));
20863 2434223 : ret = GS_ALL_DONE;
20864 2434223 : *expr_p = NULL;
20865 2434223 : break;
20866 :
20867 : case SSA_NAME:
20868 : /* Allow callbacks into the gimplifier during optimization. */
20869 : ret = GS_ALL_DONE;
20870 : break;
20871 :
20872 18244 : case OMP_PARALLEL:
20873 18244 : gimplify_omp_parallel (expr_p, pre_p);
20874 18244 : ret = GS_ALL_DONE;
20875 18244 : break;
20876 :
20877 3855 : case OMP_TASK:
20878 3855 : gimplify_omp_task (expr_p, pre_p);
20879 3855 : ret = GS_ALL_DONE;
20880 3855 : break;
20881 :
20882 10683 : case OMP_SIMD:
20883 10683 : {
20884 : /* Temporarily disable into_ssa, as scan_omp_simd
20885 : which calls copy_gimple_seq_and_replace_locals can't deal
20886 : with SSA_NAMEs defined outside of the body properly. */
20887 10683 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
20888 10683 : gimplify_ctxp->into_ssa = false;
20889 10683 : ret = gimplify_omp_for (expr_p, pre_p);
20890 10683 : gimplify_ctxp->into_ssa = saved_into_ssa;
20891 10683 : break;
20892 : }
20893 :
20894 47403 : case OMP_FOR:
20895 47403 : case OMP_DISTRIBUTE:
20896 47403 : case OMP_TASKLOOP:
20897 47403 : case OMP_TILE:
20898 47403 : case OMP_UNROLL:
20899 47403 : case OACC_LOOP:
20900 47403 : ret = gimplify_omp_for (expr_p, pre_p);
20901 47403 : break;
20902 :
20903 1056 : case OMP_LOOP:
20904 1056 : ret = gimplify_omp_loop (expr_p, pre_p);
20905 1056 : break;
20906 :
20907 665 : case OACC_CACHE:
20908 665 : gimplify_oacc_cache (expr_p, pre_p);
20909 665 : ret = GS_ALL_DONE;
20910 665 : break;
20911 :
20912 254 : case OACC_DECLARE:
20913 254 : gimplify_oacc_declare (expr_p, pre_p);
20914 254 : ret = GS_ALL_DONE;
20915 254 : break;
20916 :
20917 39824 : case OACC_HOST_DATA:
20918 39824 : case OACC_DATA:
20919 39824 : case OACC_KERNELS:
20920 39824 : case OACC_PARALLEL:
20921 39824 : case OACC_SERIAL:
20922 39824 : case OMP_SCOPE:
20923 39824 : case OMP_SECTIONS:
20924 39824 : case OMP_SINGLE:
20925 39824 : case OMP_TARGET:
20926 39824 : case OMP_TARGET_DATA:
20927 39824 : case OMP_TEAMS:
20928 39824 : gimplify_omp_workshare (expr_p, pre_p);
20929 39824 : ret = GS_ALL_DONE;
20930 39824 : break;
20931 :
20932 12297 : case OACC_ENTER_DATA:
20933 12297 : case OACC_EXIT_DATA:
20934 12297 : case OACC_UPDATE:
20935 12297 : case OMP_TARGET_UPDATE:
20936 12297 : case OMP_TARGET_ENTER_DATA:
20937 12297 : case OMP_TARGET_EXIT_DATA:
20938 12297 : gimplify_omp_target_update (expr_p, pre_p);
20939 12297 : ret = GS_ALL_DONE;
20940 12297 : break;
20941 :
20942 7043 : case OMP_SECTION:
20943 7043 : case OMP_STRUCTURED_BLOCK:
20944 7043 : case OMP_MASTER:
20945 7043 : case OMP_MASKED:
20946 7043 : case OMP_ORDERED:
20947 7043 : case OMP_CRITICAL:
20948 7043 : case OMP_SCAN:
20949 7043 : {
20950 7043 : gimple_seq body = NULL;
20951 7043 : gimple *g;
20952 7043 : bool saved_in_omp_construct = in_omp_construct;
20953 :
20954 7043 : in_omp_construct = true;
20955 7043 : gimplify_and_add (OMP_BODY (*expr_p), &body);
20956 7043 : in_omp_construct = saved_in_omp_construct;
20957 7043 : switch (TREE_CODE (*expr_p))
20958 : {
20959 1271 : case OMP_SECTION:
20960 1271 : g = gimple_build_omp_section (body);
20961 1271 : break;
20962 791 : case OMP_STRUCTURED_BLOCK:
20963 791 : g = gimple_build_omp_structured_block (body);
20964 791 : break;
20965 874 : case OMP_MASTER:
20966 874 : g = gimple_build_omp_master (body);
20967 874 : break;
20968 1950 : case OMP_ORDERED:
20969 1950 : g = gimplify_omp_ordered (*expr_p, body);
20970 1950 : if (OMP_BODY (*expr_p) == NULL_TREE
20971 1950 : && gimple_code (g) == GIMPLE_OMP_ORDERED)
20972 1025 : gimple_omp_ordered_standalone (g);
20973 : break;
20974 493 : case OMP_MASKED:
20975 493 : gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p),
20976 : pre_p, ORT_WORKSHARE, OMP_MASKED);
20977 493 : gimplify_adjust_omp_clauses (pre_p, body,
20978 : &OMP_MASKED_CLAUSES (*expr_p),
20979 : OMP_MASKED);
20980 986 : g = gimple_build_omp_masked (body,
20981 493 : OMP_MASKED_CLAUSES (*expr_p));
20982 493 : break;
20983 546 : case OMP_CRITICAL:
20984 546 : gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
20985 : pre_p, ORT_WORKSHARE, OMP_CRITICAL);
20986 546 : gimplify_adjust_omp_clauses (pre_p, body,
20987 : &OMP_CRITICAL_CLAUSES (*expr_p),
20988 : OMP_CRITICAL);
20989 1638 : g = gimple_build_omp_critical (body,
20990 546 : OMP_CRITICAL_NAME (*expr_p),
20991 546 : OMP_CRITICAL_CLAUSES (*expr_p));
20992 546 : break;
20993 1118 : case OMP_SCAN:
20994 1118 : gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
20995 : pre_p, ORT_WORKSHARE, OMP_SCAN);
20996 1118 : gimplify_adjust_omp_clauses (pre_p, body,
20997 : &OMP_SCAN_CLAUSES (*expr_p),
20998 : OMP_SCAN);
20999 1118 : g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
21000 1118 : break;
21001 0 : default:
21002 0 : gcc_unreachable ();
21003 : }
21004 7043 : gimplify_seq_add_stmt (pre_p, g);
21005 7043 : ret = GS_ALL_DONE;
21006 7043 : break;
21007 : }
21008 :
21009 611 : case OMP_TASKGROUP:
21010 611 : {
21011 611 : gimple_seq body = NULL;
21012 :
21013 611 : tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p);
21014 611 : bool saved_in_omp_construct = in_omp_construct;
21015 611 : gimplify_scan_omp_clauses (pclauses, pre_p, ORT_TASKGROUP,
21016 : OMP_TASKGROUP);
21017 611 : gimplify_adjust_omp_clauses (pre_p, NULL, pclauses, OMP_TASKGROUP);
21018 :
21019 611 : in_omp_construct = true;
21020 611 : gimplify_and_add (OMP_BODY (*expr_p), &body);
21021 611 : in_omp_construct = saved_in_omp_construct;
21022 611 : gimple_seq cleanup = NULL;
21023 611 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END);
21024 611 : gimple *g = gimple_build_call (fn, 0);
21025 611 : gimple_seq_add_stmt (&cleanup, g);
21026 611 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
21027 611 : body = NULL;
21028 611 : gimple_seq_add_stmt (&body, g);
21029 611 : g = gimple_build_omp_taskgroup (body, *pclauses);
21030 611 : gimplify_seq_add_stmt (pre_p, g);
21031 611 : ret = GS_ALL_DONE;
21032 611 : break;
21033 : }
21034 :
21035 612 : case OMP_INTEROP:
21036 612 : ret = gimplify_omp_interop (expr_p, pre_p);
21037 612 : break;
21038 10236 : case OMP_ATOMIC:
21039 10236 : case OMP_ATOMIC_READ:
21040 10236 : case OMP_ATOMIC_CAPTURE_OLD:
21041 10236 : case OMP_ATOMIC_CAPTURE_NEW:
21042 10236 : ret = gimplify_omp_atomic (expr_p, pre_p);
21043 10236 : break;
21044 :
21045 852 : case OMP_DISPATCH:
21046 852 : ret = gimplify_omp_dispatch (expr_p, pre_p);
21047 852 : break;
21048 :
21049 174 : case OMP_METADIRECTIVE:
21050 174 : ret = gimplify_omp_metadirective (expr_p, pre_p, post_p,
21051 : gimple_test_f, fallback);
21052 174 : break;
21053 :
21054 36 : case OMP_NEXT_VARIANT:
21055 36 : case OMP_TARGET_DEVICE_MATCHES:
21056 : /* These are placeholders for constants. There's nothing to do with
21057 : them here but we must mark the containing function as needing
21058 : to run the ompdevlow pass to resolve them. Note that
21059 : OMP_TARGET_DEVICE_MATCHES, in particular, may be inserted by
21060 : the front ends. */
21061 36 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
21062 36 : ret = GS_ALL_DONE;
21063 36 : break;
21064 :
21065 0 : case OMP_DECLARE_MAPPER:
21066 0 : ret = gimplify_omp_declare_mapper (expr_p);
21067 0 : break;
21068 :
21069 478 : case TRANSACTION_EXPR:
21070 478 : ret = gimplify_transaction (expr_p, pre_p);
21071 478 : break;
21072 :
21073 288345 : case TRUTH_AND_EXPR:
21074 288345 : case TRUTH_OR_EXPR:
21075 288345 : case TRUTH_XOR_EXPR:
21076 288345 : {
21077 288345 : tree orig_type = TREE_TYPE (*expr_p);
21078 288345 : tree new_type, xop0, xop1;
21079 288345 : *expr_p = gimple_boolify (*expr_p);
21080 288345 : new_type = TREE_TYPE (*expr_p);
21081 288345 : if (!useless_type_conversion_p (orig_type, new_type))
21082 : {
21083 1146 : *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
21084 1146 : ret = GS_OK;
21085 1146 : break;
21086 : }
21087 :
21088 : /* Boolified binary truth expressions are semantically equivalent
21089 : to bitwise binary expressions. Canonicalize them to the
21090 : bitwise variant. */
21091 287199 : switch (TREE_CODE (*expr_p))
21092 : {
21093 170544 : case TRUTH_AND_EXPR:
21094 170544 : TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
21095 170544 : break;
21096 116052 : case TRUTH_OR_EXPR:
21097 116052 : TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
21098 116052 : break;
21099 603 : case TRUTH_XOR_EXPR:
21100 603 : TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
21101 603 : break;
21102 : default:
21103 : break;
21104 : }
21105 : /* Now make sure that operands have compatible type to
21106 : expression's new_type. */
21107 287199 : xop0 = TREE_OPERAND (*expr_p, 0);
21108 287199 : xop1 = TREE_OPERAND (*expr_p, 1);
21109 287199 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
21110 326 : TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
21111 : new_type,
21112 : xop0);
21113 287199 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
21114 366 : TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
21115 : new_type,
21116 : xop1);
21117 : /* Continue classified as tcc_binary. */
21118 287199 : goto expr_2;
21119 : }
21120 :
21121 10495 : case VEC_COND_EXPR:
21122 10495 : goto expr_3;
21123 :
21124 133421 : case VEC_PERM_EXPR:
21125 : /* Classified as tcc_expression. */
21126 133421 : goto expr_3;
21127 :
21128 48 : case BIT_INSERT_EXPR:
21129 : /* Argument 3 is a constant. */
21130 48 : goto expr_2;
21131 :
21132 3816518 : case POINTER_PLUS_EXPR:
21133 3816518 : {
21134 3816518 : enum gimplify_status r0, r1;
21135 3816518 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21136 : post_p, is_gimple_val, fb_rvalue);
21137 3816518 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21138 : post_p, is_gimple_val, fb_rvalue);
21139 3816518 : recalculate_side_effects (*expr_p);
21140 3816518 : ret = MIN (r0, r1);
21141 : break;
21142 : }
21143 :
21144 44061201 : default:
21145 44061201 : switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
21146 : {
21147 6952528 : case tcc_comparison:
21148 : /* Handle comparison of objects of non scalar mode aggregates
21149 : with a call to memcmp. It would be nice to only have to do
21150 : this for variable-sized objects, but then we'd have to allow
21151 : the same nest of reference nodes we allow for MODIFY_EXPR and
21152 : that's too complex.
21153 :
21154 : Compare scalar mode aggregates as scalar mode values. Using
21155 : memcmp for them would be very inefficient at best, and is
21156 : plain wrong if bitfields are involved. */
21157 6952528 : if (error_operand_p (TREE_OPERAND (*expr_p, 1)))
21158 : ret = GS_ERROR;
21159 : else
21160 : {
21161 6952528 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
21162 :
21163 : /* Vector comparisons need no boolification. */
21164 6952528 : if (TREE_CODE (type) == VECTOR_TYPE)
21165 12585 : goto expr_2;
21166 6939943 : else if (!AGGREGATE_TYPE_P (type))
21167 : {
21168 6939927 : tree org_type = TREE_TYPE (*expr_p);
21169 6939927 : *expr_p = gimple_boolify (*expr_p);
21170 6939927 : if (!useless_type_conversion_p (org_type,
21171 6939927 : TREE_TYPE (*expr_p)))
21172 : {
21173 56437 : *expr_p = fold_convert_loc (input_location,
21174 : org_type, *expr_p);
21175 56437 : ret = GS_OK;
21176 : }
21177 : else
21178 6883490 : goto expr_2;
21179 : }
21180 16 : else if (SCALAR_INT_MODE_P (TYPE_MODE (type)))
21181 16 : ret = gimplify_scalar_mode_aggregate_compare (expr_p);
21182 : else
21183 0 : ret = gimplify_variable_sized_compare (expr_p);
21184 : }
21185 : break;
21186 :
21187 : /* If *EXPR_P does not need to be special-cased, handle it
21188 : according to its class. */
21189 1590150 : case tcc_unary:
21190 1590150 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21191 : post_p, is_gimple_val, fb_rvalue);
21192 1590150 : break;
21193 :
21194 26298005 : case tcc_binary:
21195 26298005 : expr_2:
21196 26298005 : {
21197 26298005 : enum gimplify_status r0, r1;
21198 :
21199 26298005 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21200 : post_p, is_gimple_val, fb_rvalue);
21201 26298005 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21202 : post_p, is_gimple_val, fb_rvalue);
21203 :
21204 26298005 : ret = MIN (r0, r1);
21205 : break;
21206 : }
21207 :
21208 143916 : expr_3:
21209 143916 : {
21210 143916 : enum gimplify_status r0, r1, r2;
21211 :
21212 143916 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21213 : post_p, is_gimple_val, fb_rvalue);
21214 143916 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21215 : post_p, is_gimple_val, fb_rvalue);
21216 143916 : r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
21217 : post_p, is_gimple_val, fb_rvalue);
21218 :
21219 143916 : ret = MIN (MIN (r0, r1), r2);
21220 : break;
21221 : }
21222 :
21223 16403840 : case tcc_declaration:
21224 16403840 : case tcc_constant:
21225 16403840 : ret = GS_ALL_DONE;
21226 16403840 : goto dont_recalculate;
21227 :
21228 0 : default:
21229 0 : gcc_unreachable ();
21230 : }
21231 :
21232 28088524 : recalculate_side_effects (*expr_p);
21233 :
21234 474988470 : dont_recalculate:
21235 : break;
21236 : }
21237 :
21238 474988470 : gcc_assert (*expr_p || ret != GS_OK);
21239 : }
21240 479633722 : while (ret == GS_OK);
21241 :
21242 : /* If we encountered an error_mark somewhere nested inside, either
21243 : stub out the statement or propagate the error back out. */
21244 462292913 : if (ret == GS_ERROR)
21245 : {
21246 5309 : if (is_statement)
21247 4074 : *expr_p = NULL;
21248 5309 : goto out;
21249 : }
21250 :
21251 : /* This was only valid as a return value from the langhook, which
21252 : we handled. Make sure it doesn't escape from any other context. */
21253 462287604 : gcc_assert (ret != GS_UNHANDLED);
21254 :
21255 462287604 : if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
21256 : {
21257 : /* We aren't looking for a value, and we don't have a valid
21258 : statement. If it doesn't have side-effects, throw it away.
21259 : We can also get here with code such as "*&&L;", where L is
21260 : a LABEL_DECL that is marked as FORCED_LABEL. */
21261 1175324 : if (TREE_CODE (*expr_p) == LABEL_DECL
21262 1175324 : || !TREE_SIDE_EFFECTS (*expr_p))
21263 1174308 : *expr_p = NULL;
21264 1016 : else if (!TREE_THIS_VOLATILE (*expr_p))
21265 : {
21266 : /* This is probably a _REF that contains something nested that
21267 : has side effects. Recurse through the operands to find it. */
21268 0 : enum tree_code code = TREE_CODE (*expr_p);
21269 :
21270 0 : switch (code)
21271 : {
21272 0 : case COMPONENT_REF:
21273 0 : case REALPART_EXPR:
21274 0 : case IMAGPART_EXPR:
21275 0 : case VIEW_CONVERT_EXPR:
21276 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21277 : gimple_test_f, fallback);
21278 0 : break;
21279 :
21280 0 : case ARRAY_REF:
21281 0 : case ARRAY_RANGE_REF:
21282 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21283 : gimple_test_f, fallback);
21284 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
21285 : gimple_test_f, fallback);
21286 0 : break;
21287 :
21288 0 : default:
21289 : /* Anything else with side-effects must be converted to
21290 : a valid statement before we get here. */
21291 0 : gcc_unreachable ();
21292 : }
21293 :
21294 0 : *expr_p = NULL;
21295 : }
21296 1016 : else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
21297 966 : && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode
21298 1969 : && !is_empty_type (TREE_TYPE (*expr_p)))
21299 : {
21300 : /* Historically, the compiler has treated a bare reference
21301 : to a non-BLKmode volatile lvalue as forcing a load. */
21302 893 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
21303 :
21304 : /* Normally, we do not want to create a temporary for a
21305 : TREE_ADDRESSABLE type because such a type should not be
21306 : copied by bitwise-assignment. However, we make an
21307 : exception here, as all we are doing here is ensuring that
21308 : we read the bytes that make up the type. We use
21309 : create_tmp_var_raw because create_tmp_var will abort when
21310 : given a TREE_ADDRESSABLE type. */
21311 893 : tree tmp = create_tmp_var_raw (type, "vol");
21312 893 : gimple_add_tmp_var (tmp);
21313 893 : gimplify_assign (tmp, *expr_p, pre_p);
21314 893 : *expr_p = NULL;
21315 : }
21316 : else
21317 : /* We can't do anything useful with a volatile reference to
21318 : an incomplete type, so just throw it away. Likewise for
21319 : a BLKmode type, since any implicit inner load should
21320 : already have been turned into an explicit one by the
21321 : gimplification process. */
21322 123 : *expr_p = NULL;
21323 : }
21324 :
21325 : /* If we are gimplifying at the statement level, we're done. Tack
21326 : everything together and return. */
21327 462287604 : if (fallback == fb_none || is_statement)
21328 : {
21329 : /* Since *EXPR_P has been converted into a GIMPLE tuple, clear
21330 : it out for GC to reclaim it. */
21331 100376652 : *expr_p = NULL_TREE;
21332 :
21333 100376652 : if (!gimple_seq_empty_p (internal_pre)
21334 100376652 : || !gimple_seq_empty_p (internal_post))
21335 : {
21336 19 : gimplify_seq_add_seq (&internal_pre, internal_post);
21337 19 : gimplify_seq_add_seq (pre_p, internal_pre);
21338 : }
21339 :
21340 : /* The result of gimplifying *EXPR_P is going to be the last few
21341 : statements in *PRE_P and *POST_P. Add location information
21342 : to all the statements that were added by the gimplification
21343 : helpers. */
21344 100376652 : if (!gimple_seq_empty_p (*pre_p))
21345 97898463 : annotate_all_with_location_after (*pre_p, pre_last_gsi, input_location);
21346 :
21347 100376652 : if (!gimple_seq_empty_p (*post_p))
21348 19 : annotate_all_with_location_after (*post_p, post_last_gsi,
21349 : input_location);
21350 :
21351 100376652 : goto out;
21352 : }
21353 :
21354 : #ifdef ENABLE_GIMPLE_CHECKING
21355 361910952 : if (*expr_p)
21356 : {
21357 361910952 : enum tree_code code = TREE_CODE (*expr_p);
21358 : /* These expressions should already be in gimple IR form. */
21359 361910952 : gcc_assert (code != MODIFY_EXPR
21360 : && code != ASM_EXPR
21361 : && code != BIND_EXPR
21362 : && code != CATCH_EXPR
21363 : && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
21364 : && code != EH_FILTER_EXPR
21365 : && code != GOTO_EXPR
21366 : && code != LABEL_EXPR
21367 : && code != LOOP_EXPR
21368 : && code != SWITCH_EXPR
21369 : && code != TRY_FINALLY_EXPR
21370 : && code != EH_ELSE_EXPR
21371 : && code != OACC_PARALLEL
21372 : && code != OACC_KERNELS
21373 : && code != OACC_SERIAL
21374 : && code != OACC_DATA
21375 : && code != OACC_HOST_DATA
21376 : && code != OACC_DECLARE
21377 : && code != OACC_UPDATE
21378 : && code != OACC_ENTER_DATA
21379 : && code != OACC_EXIT_DATA
21380 : && code != OACC_CACHE
21381 : && code != OMP_CRITICAL
21382 : && code != OMP_FOR
21383 : && code != OACC_LOOP
21384 : && code != OMP_MASTER
21385 : && code != OMP_MASKED
21386 : && code != OMP_TASKGROUP
21387 : && code != OMP_ORDERED
21388 : && code != OMP_PARALLEL
21389 : && code != OMP_SCAN
21390 : && code != OMP_SECTIONS
21391 : && code != OMP_SECTION
21392 : && code != OMP_STRUCTURED_BLOCK
21393 : && code != OMP_SINGLE
21394 : && code != OMP_SCOPE
21395 : && code != OMP_DISPATCH);
21396 : }
21397 : #endif
21398 :
21399 : /* Otherwise we're gimplifying a subexpression, so the resulting
21400 : value is interesting. If it's a valid operand that matches
21401 : GIMPLE_TEST_F, we're done. Unless we are handling some
21402 : post-effects internally; if that's the case, we need to copy into
21403 : a temporary before adding the post-effects to POST_P. */
21404 361910952 : if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
21405 336057452 : goto out;
21406 :
21407 : /* Otherwise, we need to create a new temporary for the gimplified
21408 : expression. */
21409 :
21410 : /* We can't return an lvalue if we have an internal postqueue. The
21411 : object the lvalue refers to would (probably) be modified by the
21412 : postqueue; we need to copy the value out first, which means an
21413 : rvalue. */
21414 25853500 : if ((fallback & fb_lvalue)
21415 575905 : && gimple_seq_empty_p (internal_post)
21416 26429405 : && is_gimple_addressable (*expr_p))
21417 : {
21418 : /* An lvalue will do. Take the address of the expression, store it
21419 : in a temporary, and replace the expression with an INDIRECT_REF of
21420 : that temporary. */
21421 15 : tree ref_alias_type = reference_alias_ptr_type (*expr_p);
21422 15 : unsigned int ref_align = get_object_alignment (*expr_p);
21423 15 : tree ref_type = TREE_TYPE (*expr_p);
21424 15 : tmp = build_fold_addr_expr_loc (input_location, *expr_p);
21425 15 : gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
21426 15 : if (TYPE_ALIGN (ref_type) != ref_align)
21427 1 : ref_type = build_aligned_type (ref_type, ref_align);
21428 15 : *expr_p = build2 (MEM_REF, ref_type,
21429 : tmp, build_zero_cst (ref_alias_type));
21430 : }
21431 25853485 : else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
21432 : {
21433 : /* An rvalue will do. Assign the gimplified expression into a
21434 : new temporary TMP and replace the original expression with
21435 : TMP. First, make sure that the expression has a type so that
21436 : it can be assigned into a temporary. */
21437 25853477 : gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
21438 25853477 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
21439 : }
21440 : else
21441 : {
21442 : #ifdef ENABLE_GIMPLE_CHECKING
21443 8 : if (!(fallback & fb_mayfail))
21444 : {
21445 0 : fprintf (stderr, "gimplification failed:\n");
21446 0 : print_generic_expr (stderr, *expr_p);
21447 0 : debug_tree (*expr_p);
21448 0 : internal_error ("gimplification failed");
21449 : }
21450 : #endif
21451 8 : gcc_assert (fallback & fb_mayfail);
21452 :
21453 : /* If this is an asm statement, and the user asked for the
21454 : impossible, don't die. Fail and let gimplify_asm_expr
21455 : issue an error. */
21456 8 : ret = GS_ERROR;
21457 8 : goto out;
21458 : }
21459 :
21460 : /* Make sure the temporary matches our predicate. */
21461 25853492 : gcc_assert ((*gimple_test_f) (*expr_p));
21462 :
21463 25853492 : if (!gimple_seq_empty_p (internal_post))
21464 : {
21465 0 : annotate_all_with_location (internal_post, input_location);
21466 0 : gimplify_seq_add_seq (pre_p, internal_post);
21467 : }
21468 :
21469 25853492 : out:
21470 462292913 : input_location = saved_location;
21471 462292913 : return ret;
21472 : }
21473 :
21474 : /* Like gimplify_expr but make sure the gimplified result is not itself
21475 : a SSA name (but a decl if it were). Temporaries required by
21476 : evaluating *EXPR_P may be still SSA names. */
21477 :
21478 : static enum gimplify_status
21479 33268639 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
21480 : bool (*gimple_test_f) (tree), fallback_t fallback,
21481 : bool allow_ssa)
21482 : {
21483 33268639 : enum gimplify_status ret = gimplify_expr (expr_p, pre_p, post_p,
21484 : gimple_test_f, fallback);
21485 33268639 : if (! allow_ssa
21486 266280 : && TREE_CODE (*expr_p) == SSA_NAME)
21487 68670 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false);
21488 33268639 : return ret;
21489 : }
21490 :
21491 : /* Look through TYPE for variable-sized objects and gimplify each such
21492 : size that we find. Add to LIST_P any statements generated. */
21493 :
21494 : void
21495 8091205 : gimplify_type_sizes (tree type, gimple_seq *list_p)
21496 : {
21497 8091205 : if (type == NULL || type == error_mark_node)
21498 : return;
21499 :
21500 8090959 : const bool ignored_p
21501 8090959 : = TYPE_NAME (type)
21502 4064645 : && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
21503 11924028 : && DECL_IGNORED_P (TYPE_NAME (type));
21504 8090959 : tree t;
21505 :
21506 : /* We first do the main variant, then copy into any other variants. */
21507 8090959 : type = TYPE_MAIN_VARIANT (type);
21508 :
21509 : /* Avoid infinite recursion. */
21510 8090959 : if (TYPE_SIZES_GIMPLIFIED (type))
21511 : return;
21512 :
21513 2409130 : TYPE_SIZES_GIMPLIFIED (type) = 1;
21514 :
21515 2409130 : switch (TREE_CODE (type))
21516 : {
21517 489078 : case INTEGER_TYPE:
21518 489078 : case ENUMERAL_TYPE:
21519 489078 : case BOOLEAN_TYPE:
21520 489078 : case REAL_TYPE:
21521 489078 : case FIXED_POINT_TYPE:
21522 489078 : gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
21523 489078 : gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
21524 :
21525 9717228 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21526 : {
21527 9228150 : TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
21528 9228150 : TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
21529 : }
21530 : break;
21531 :
21532 179726 : case ARRAY_TYPE:
21533 : /* These types may not have declarations, so handle them here. */
21534 179726 : gimplify_type_sizes (TREE_TYPE (type), list_p);
21535 179726 : gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
21536 : /* Ensure VLA bounds aren't removed, for -O0 they should be variables
21537 : with assigned stack slots, for -O1+ -g they should be tracked
21538 : by VTA. */
21539 179726 : if (!ignored_p
21540 179726 : && TYPE_DOMAIN (type)
21541 359227 : && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
21542 : {
21543 179501 : t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
21544 179501 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21545 0 : DECL_IGNORED_P (t) = 0;
21546 179501 : t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
21547 179501 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21548 19018 : DECL_IGNORED_P (t) = 0;
21549 : }
21550 : break;
21551 :
21552 484298 : case RECORD_TYPE:
21553 484298 : case UNION_TYPE:
21554 484298 : case QUAL_UNION_TYPE:
21555 10386446 : for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
21556 9902148 : if (TREE_CODE (field) == FIELD_DECL)
21557 : {
21558 1063665 : gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
21559 : /* Likewise, ensure variable offsets aren't removed. */
21560 1063665 : if (!ignored_p
21561 1063665 : && (t = DECL_FIELD_OFFSET (field))
21562 1063653 : && VAR_P (t)
21563 1063827 : && DECL_ARTIFICIAL (t))
21564 162 : DECL_IGNORED_P (t) = 0;
21565 1063665 : gimplify_one_sizepos (&DECL_SIZE (field), list_p);
21566 1063665 : gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
21567 1063665 : gimplify_type_sizes (TREE_TYPE (field), list_p);
21568 : }
21569 : break;
21570 :
21571 : case POINTER_TYPE:
21572 : case REFERENCE_TYPE:
21573 : /* We used to recurse on the pointed-to type here, which turned out to
21574 : be incorrect because its definition might refer to variables not
21575 : yet initialized at this point if a forward declaration is involved.
21576 :
21577 : It was actually useful for anonymous pointed-to types to ensure
21578 : that the sizes evaluation dominates every possible later use of the
21579 : values. Restricting to such types here would be safe since there
21580 : is no possible forward declaration around, but would introduce an
21581 : undesirable middle-end semantic to anonymity. We then defer to
21582 : front-ends the responsibility of ensuring that the sizes are
21583 : evaluated both early and late enough, e.g. by attaching artificial
21584 : type declarations to the tree. */
21585 : break;
21586 :
21587 : default:
21588 : break;
21589 : }
21590 :
21591 2409130 : gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
21592 2409130 : gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
21593 :
21594 15960436 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21595 : {
21596 13551306 : TYPE_SIZE (t) = TYPE_SIZE (type);
21597 13551306 : TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
21598 13551306 : TYPE_SIZES_GIMPLIFIED (t) = 1;
21599 : }
21600 : }
21601 :
21602 : /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
21603 : a size or position, has had all of its SAVE_EXPRs evaluated.
21604 : We add any required statements to *STMT_P. */
21605 :
21606 : void
21607 9005529 : gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
21608 : {
21609 9005529 : tree expr = *expr_p;
21610 :
21611 : /* We don't do anything if the value isn't there, is constant, or contains
21612 : A PLACEHOLDER_EXPR. We also don't want to do anything if it's already
21613 : a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
21614 : will want to replace it with a new variable, but that will cause problems
21615 : if this type is from outside the function. It's OK to have that here. */
21616 9005529 : if (expr == NULL_TREE
21617 9009420 : || is_gimple_constant (expr)
21618 80956 : || VAR_P (expr)
21619 9082594 : || CONTAINS_PLACEHOLDER_P (expr))
21620 8928464 : return;
21621 :
21622 77065 : *expr_p = unshare_expr (expr);
21623 :
21624 : /* SSA names in decl/type fields are a bad idea - they'll get reclaimed
21625 : if the def vanishes. */
21626 77065 : gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false);
21627 :
21628 : /* If expr wasn't already is_gimple_sizepos or is_gimple_constant from the
21629 : FE, ensure that it is a VAR_DECL, otherwise we might handle some decls
21630 : as gimplify_vla_decl even when they would have all sizes INTEGER_CSTs. */
21631 77065 : if (is_gimple_constant (*expr_p))
21632 548 : *expr_p = get_initialized_tmp_var (*expr_p, stmt_p, NULL, false);
21633 : }
21634 :
21635 : /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
21636 : containing the sequence of corresponding GIMPLE statements. If DO_PARMS
21637 : is true, also gimplify the parameters. */
21638 :
21639 : gbind *
21640 2881248 : gimplify_body (tree fndecl, bool do_parms)
21641 : {
21642 2881248 : location_t saved_location = input_location;
21643 2881248 : gimple_seq parm_stmts, parm_cleanup = NULL, seq;
21644 2881248 : gimple *outer_stmt;
21645 2881248 : gbind *outer_bind;
21646 :
21647 2881248 : timevar_push (TV_TREE_GIMPLIFY);
21648 :
21649 2881248 : init_tree_ssa (cfun);
21650 :
21651 : /* Initialize for optimize_insn_for_s{ize,peed}_p possibly called during
21652 : gimplification. */
21653 2881248 : default_rtl_profile ();
21654 :
21655 2881248 : gcc_assert (gimplify_ctxp == NULL);
21656 2881248 : push_gimplify_context (true);
21657 :
21658 2881248 : if (flag_openacc || flag_openmp)
21659 : {
21660 54898 : gcc_assert (gimplify_omp_ctxp == NULL);
21661 54898 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)))
21662 9733 : gimplify_omp_ctxp = new_omp_context (ORT_IMPLICIT_TARGET);
21663 : }
21664 :
21665 : /* Unshare most shared trees in the body and in that of any nested functions.
21666 : It would seem we don't have to do this for nested functions because
21667 : they are supposed to be output and then the outer function gimplified
21668 : first, but the g++ front end doesn't always do it that way. */
21669 2881248 : unshare_body (fndecl);
21670 2881248 : unvisit_body (fndecl);
21671 :
21672 : /* Make sure input_location isn't set to something weird. */
21673 2881248 : input_location = DECL_SOURCE_LOCATION (fndecl);
21674 :
21675 : /* Resolve callee-copies. This has to be done before processing
21676 : the body so that DECL_VALUE_EXPR gets processed correctly. */
21677 2881248 : parm_stmts = do_parms ? gimplify_parameters (&parm_cleanup) : NULL;
21678 :
21679 : /* Gimplify the function's body. */
21680 2881248 : seq = NULL;
21681 2881248 : gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
21682 2881248 : outer_stmt = gimple_seq_first_nondebug_stmt (seq);
21683 2881248 : if (!outer_stmt)
21684 : {
21685 26516 : outer_stmt = gimple_build_nop ();
21686 26516 : gimplify_seq_add_stmt (&seq, outer_stmt);
21687 : }
21688 :
21689 : /* The body must contain exactly one statement, a GIMPLE_BIND. If this is
21690 : not the case, wrap everything in a GIMPLE_BIND to make it so. */
21691 2881248 : if (gimple_code (outer_stmt) == GIMPLE_BIND
21692 2881248 : && (gimple_seq_first_nondebug_stmt (seq)
21693 1681643 : == gimple_seq_last_nondebug_stmt (seq)))
21694 : {
21695 1615339 : outer_bind = as_a <gbind *> (outer_stmt);
21696 1615339 : if (gimple_seq_first_stmt (seq) != outer_stmt
21697 1615339 : || gimple_seq_last_stmt (seq) != outer_stmt)
21698 : {
21699 : /* If there are debug stmts before or after outer_stmt, move them
21700 : inside of outer_bind body. */
21701 1 : gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq);
21702 1 : gimple_seq second_seq = NULL;
21703 1 : if (gimple_seq_first_stmt (seq) != outer_stmt
21704 2 : && gimple_seq_last_stmt (seq) != outer_stmt)
21705 : {
21706 0 : second_seq = gsi_split_seq_after (gsi);
21707 0 : gsi_remove (&gsi, false);
21708 : }
21709 1 : else if (gimple_seq_first_stmt (seq) != outer_stmt)
21710 1 : gsi_remove (&gsi, false);
21711 : else
21712 : {
21713 0 : gsi_remove (&gsi, false);
21714 0 : second_seq = seq;
21715 0 : seq = NULL;
21716 : }
21717 1 : gimple_seq_add_seq_without_update (&seq,
21718 : gimple_bind_body (outer_bind));
21719 1 : gimple_seq_add_seq_without_update (&seq, second_seq);
21720 1 : gimple_bind_set_body (outer_bind, seq);
21721 : }
21722 : }
21723 : else
21724 1265909 : outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
21725 :
21726 2881248 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
21727 :
21728 : /* If we had callee-copies statements, insert them at the beginning
21729 : of the function and clear DECL_HAS_VALUE_EXPR_P on the parameters. */
21730 2881248 : if (!gimple_seq_empty_p (parm_stmts))
21731 : {
21732 41 : tree parm;
21733 :
21734 41 : gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
21735 41 : if (parm_cleanup)
21736 : {
21737 0 : gtry *g = gimple_build_try (parm_stmts, parm_cleanup,
21738 : GIMPLE_TRY_FINALLY);
21739 0 : parm_stmts = NULL;
21740 0 : gimple_seq_add_stmt (&parm_stmts, g);
21741 : }
21742 41 : gimple_bind_set_body (outer_bind, parm_stmts);
21743 :
21744 41 : for (parm = DECL_ARGUMENTS (current_function_decl);
21745 101 : parm; parm = DECL_CHAIN (parm))
21746 60 : if (DECL_HAS_VALUE_EXPR_P (parm))
21747 : {
21748 0 : DECL_HAS_VALUE_EXPR_P (parm) = 0;
21749 0 : DECL_IGNORED_P (parm) = 0;
21750 : }
21751 : }
21752 :
21753 2881248 : if ((flag_openacc || flag_openmp || flag_openmp_simd)
21754 57154 : && gimplify_omp_ctxp)
21755 : {
21756 9786 : delete_omp_context (gimplify_omp_ctxp);
21757 9786 : gimplify_omp_ctxp = NULL;
21758 : }
21759 :
21760 2881248 : pop_gimplify_context (outer_bind);
21761 2881248 : gcc_assert (gimplify_ctxp == NULL);
21762 :
21763 2881248 : if (flag_checking && !seen_error ())
21764 2831687 : verify_gimple_in_seq (gimple_bind_body (outer_bind));
21765 :
21766 2881248 : timevar_pop (TV_TREE_GIMPLIFY);
21767 2881248 : input_location = saved_location;
21768 :
21769 2881248 : return outer_bind;
21770 : }
21771 :
21772 : typedef char *char_p; /* For DEF_VEC_P. */
21773 :
21774 : /* Return whether we should exclude FNDECL from instrumentation. */
21775 :
21776 : static bool
21777 43 : flag_instrument_functions_exclude_p (tree fndecl)
21778 : {
21779 43 : vec<char_p> *v;
21780 :
21781 43 : v = (vec<char_p> *) flag_instrument_functions_exclude_functions;
21782 44 : if (v && v->length () > 0)
21783 : {
21784 1 : const char *name;
21785 1 : int i;
21786 1 : char *s;
21787 :
21788 1 : name = lang_hooks.decl_printable_name (fndecl, 1);
21789 2 : FOR_EACH_VEC_ELT (*v, i, s)
21790 1 : if (strstr (name, s) != NULL)
21791 2 : return true;
21792 : }
21793 :
21794 42 : v = (vec<char_p> *) flag_instrument_functions_exclude_files;
21795 43 : if (v && v->length () > 0)
21796 : {
21797 1 : const char *name;
21798 1 : int i;
21799 1 : char *s;
21800 :
21801 1 : name = DECL_SOURCE_FILE (fndecl);
21802 1 : FOR_EACH_VEC_ELT (*v, i, s)
21803 1 : if (strstr (name, s) != NULL)
21804 2 : return true;
21805 : }
21806 :
21807 : return false;
21808 : }
21809 :
21810 : /* Build a call to the instrumentation function FNCODE and add it to SEQ.
21811 : If COND_VAR is not NULL, it is a boolean variable guarding the call to
21812 : the instrumentation function. IF STMT is not NULL, it is a statement
21813 : to be executed just before the call to the instrumentation function. */
21814 :
21815 : static void
21816 82 : build_instrumentation_call (gimple_seq *seq, enum built_in_function fncode,
21817 : tree cond_var, gimple *stmt)
21818 : {
21819 : /* The instrumentation hooks aren't going to call the instrumented
21820 : function and the address they receive is expected to be matchable
21821 : against symbol addresses. Make sure we don't create a trampoline,
21822 : in case the current function is nested. */
21823 82 : tree this_fn_addr = build_fold_addr_expr (current_function_decl);
21824 82 : TREE_NO_TRAMPOLINE (this_fn_addr) = 1;
21825 :
21826 82 : tree label_true, label_false;
21827 82 : if (cond_var)
21828 : {
21829 20 : label_true = create_artificial_label (UNKNOWN_LOCATION);
21830 20 : label_false = create_artificial_label (UNKNOWN_LOCATION);
21831 20 : gcond *cond = gimple_build_cond (EQ_EXPR, cond_var, boolean_false_node,
21832 : label_true, label_false);
21833 20 : gimplify_seq_add_stmt (seq, cond);
21834 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_true));
21835 20 : gimplify_seq_add_stmt (seq, gimple_build_predict (PRED_COLD_LABEL,
21836 : NOT_TAKEN));
21837 : }
21838 :
21839 82 : if (stmt)
21840 10 : gimplify_seq_add_stmt (seq, stmt);
21841 :
21842 82 : tree x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
21843 82 : gcall *call = gimple_build_call (x, 1, integer_zero_node);
21844 82 : tree tmp_var = create_tmp_var (ptr_type_node, "return_addr");
21845 82 : gimple_call_set_lhs (call, tmp_var);
21846 82 : gimplify_seq_add_stmt (seq, call);
21847 82 : x = builtin_decl_implicit (fncode);
21848 82 : call = gimple_build_call (x, 2, this_fn_addr, tmp_var);
21849 82 : gimplify_seq_add_stmt (seq, call);
21850 :
21851 82 : if (cond_var)
21852 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_false));
21853 82 : }
21854 :
21855 : /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
21856 : node for the function we want to gimplify.
21857 :
21858 : Return the sequence of GIMPLE statements corresponding to the body
21859 : of FNDECL. */
21860 :
21861 : void
21862 2880744 : gimplify_function_tree (tree fndecl)
21863 : {
21864 2880744 : gimple_seq seq;
21865 2880744 : gbind *bind;
21866 :
21867 2880744 : gcc_assert (!gimple_body (fndecl));
21868 :
21869 2880744 : if (DECL_STRUCT_FUNCTION (fndecl))
21870 2876347 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
21871 : else
21872 4397 : push_struct_function (fndecl);
21873 :
21874 2880744 : reset_cond_uid ();
21875 2880744 : if (cond_uids)
21876 : {
21877 65 : delete cond_uids;
21878 65 : cond_uids = NULL;
21879 : }
21880 :
21881 : /* Tentatively set PROP_gimple_lva here, and reset it in gimplify_va_arg_expr
21882 : if necessary. */
21883 2880744 : cfun->curr_properties |= PROP_gimple_lva;
21884 :
21885 2880744 : if (asan_sanitize_use_after_scope ())
21886 8634 : asan_poisoned_variables = new hash_set<tree> ();
21887 2880744 : if (flag_openmp)
21888 47224 : omp_resolved_variant_calls = new hash_set<tree> ();
21889 :
21890 2880744 : bind = gimplify_body (fndecl, true);
21891 :
21892 2880744 : if (omp_resolved_variant_calls)
21893 : {
21894 47224 : delete omp_resolved_variant_calls;
21895 47224 : omp_resolved_variant_calls = NULL;
21896 : }
21897 2880744 : if (asan_poisoned_variables)
21898 : {
21899 8634 : delete asan_poisoned_variables;
21900 8634 : asan_poisoned_variables = NULL;
21901 : }
21902 :
21903 : /* The tree body of the function is no longer needed, replace it
21904 : with the new GIMPLE body. */
21905 2880744 : seq = NULL;
21906 2880744 : gimple_seq_add_stmt (&seq, bind);
21907 2880744 : gimple_set_body (fndecl, seq);
21908 :
21909 : /* If we're instrumenting function entry/exit, then prepend the call to
21910 : the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
21911 : catch the exit hook. */
21912 : /* ??? Add some way to ignore exceptions for this TFE. */
21913 2880744 : if (flag_instrument_function_entry_exit
21914 97 : && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
21915 : /* Do not instrument extern inline functions. */
21916 44 : && !(DECL_DECLARED_INLINE_P (fndecl)
21917 6 : && DECL_EXTERNAL (fndecl)
21918 1 : && DECL_DISREGARD_INLINE_LIMITS (fndecl))
21919 2880787 : && !flag_instrument_functions_exclude_p (fndecl))
21920 : {
21921 41 : gimple_seq body = NULL, cleanup = NULL;
21922 41 : gassign *assign;
21923 41 : tree cond_var;
21924 :
21925 : /* If -finstrument-functions-once is specified, generate:
21926 :
21927 : static volatile bool C.0 = false;
21928 : bool tmp_called;
21929 :
21930 : tmp_called = C.0;
21931 : if (!tmp_called)
21932 : {
21933 : C.0 = true;
21934 : [call profiling enter function]
21935 : }
21936 :
21937 : without specific protection for data races. */
21938 41 : if (flag_instrument_function_entry_exit > 1)
21939 : {
21940 10 : tree first_var
21941 10 : = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
21942 : VAR_DECL,
21943 : create_tmp_var_name ("C"),
21944 : boolean_type_node);
21945 10 : DECL_ARTIFICIAL (first_var) = 1;
21946 10 : DECL_IGNORED_P (first_var) = 1;
21947 10 : TREE_STATIC (first_var) = 1;
21948 10 : TREE_THIS_VOLATILE (first_var) = 1;
21949 10 : TREE_USED (first_var) = 1;
21950 10 : DECL_INITIAL (first_var) = boolean_false_node;
21951 10 : varpool_node::add (first_var);
21952 :
21953 10 : cond_var = create_tmp_var (boolean_type_node, "tmp_called");
21954 10 : assign = gimple_build_assign (cond_var, first_var);
21955 10 : gimplify_seq_add_stmt (&body, assign);
21956 :
21957 10 : assign = gimple_build_assign (first_var, boolean_true_node);
21958 : }
21959 :
21960 : else
21961 : {
21962 : cond_var = NULL_TREE;
21963 : assign = NULL;
21964 : }
21965 :
21966 41 : build_instrumentation_call (&body, BUILT_IN_PROFILE_FUNC_ENTER,
21967 : cond_var, assign);
21968 :
21969 : /* If -finstrument-functions-once is specified, generate:
21970 :
21971 : if (!tmp_called)
21972 : [call profiling exit function]
21973 :
21974 : without specific protection for data races. */
21975 41 : build_instrumentation_call (&cleanup, BUILT_IN_PROFILE_FUNC_EXIT,
21976 : cond_var, NULL);
21977 :
21978 41 : gimple *tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
21979 41 : gimplify_seq_add_stmt (&body, tf);
21980 41 : gbind *new_bind = gimple_build_bind (NULL, body, NULL);
21981 :
21982 : /* Replace the current function body with the body
21983 : wrapped in the try/finally TF. */
21984 41 : seq = NULL;
21985 41 : gimple_seq_add_stmt (&seq, new_bind);
21986 41 : gimple_set_body (fndecl, seq);
21987 41 : bind = new_bind;
21988 : }
21989 :
21990 2880744 : if (sanitize_flags_p (SANITIZE_THREAD)
21991 2880744 : && param_tsan_instrument_func_entry_exit)
21992 : {
21993 1147 : gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
21994 1147 : gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
21995 1147 : gbind *new_bind = gimple_build_bind (NULL, tf, NULL);
21996 : /* Replace the current function body with the body
21997 : wrapped in the try/finally TF. */
21998 1147 : seq = NULL;
21999 1147 : gimple_seq_add_stmt (&seq, new_bind);
22000 1147 : gimple_set_body (fndecl, seq);
22001 : }
22002 :
22003 2880744 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
22004 2880744 : cfun->curr_properties |= PROP_gimple_any;
22005 :
22006 2880744 : pop_cfun ();
22007 :
22008 2880744 : dump_function (TDI_gimple, fndecl);
22009 2880744 : }
22010 :
22011 : /* Return a dummy expression of type TYPE in order to keep going after an
22012 : error. */
22013 :
22014 : static tree
22015 30 : dummy_object (tree type)
22016 : {
22017 30 : tree t = build_int_cst (build_pointer_type (type), 0);
22018 30 : return build2 (MEM_REF, type, t, t);
22019 : }
22020 :
22021 : /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
22022 : builtin function, but a very special sort of operator. */
22023 :
22024 : enum gimplify_status
22025 51131 : gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
22026 : gimple_seq *post_p ATTRIBUTE_UNUSED)
22027 : {
22028 51131 : tree promoted_type, have_va_type;
22029 51131 : tree valist = TREE_OPERAND (*expr_p, 0);
22030 51131 : tree type = TREE_TYPE (*expr_p);
22031 51131 : tree t, tag, aptag;
22032 51131 : location_t loc = EXPR_LOCATION (*expr_p);
22033 :
22034 : /* Verify that valist is of the proper type. */
22035 51131 : have_va_type = TREE_TYPE (valist);
22036 51131 : if (have_va_type == error_mark_node)
22037 : return GS_ERROR;
22038 51112 : have_va_type = targetm.canonical_va_list_type (have_va_type);
22039 51112 : if (have_va_type == NULL_TREE
22040 51112 : && POINTER_TYPE_P (TREE_TYPE (valist)))
22041 : /* Handle 'Case 1: Not an array type' from c-common.cc/build_va_arg. */
22042 258 : have_va_type
22043 258 : = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
22044 51112 : gcc_assert (have_va_type != NULL_TREE);
22045 :
22046 : /* Generate a diagnostic for requesting data of a type that cannot
22047 : be passed through `...' due to type promotion at the call site. */
22048 51112 : if ((promoted_type = lang_hooks.types.type_promotes_to (type))
22049 : != type)
22050 : {
22051 30 : static bool gave_help;
22052 30 : bool warned;
22053 : /* Use the expansion point to handle cases such as passing bool (defined
22054 : in a system header) through `...'. */
22055 30 : location_t xloc
22056 30 : = expansion_point_location_if_in_system_header (loc);
22057 :
22058 : /* Unfortunately, this is merely undefined, rather than a constraint
22059 : violation, so we cannot make this an error. If this call is never
22060 : executed, the program is still strictly conforming. */
22061 30 : auto_diagnostic_group d;
22062 30 : warned = warning_at (xloc, 0,
22063 : "%qT is promoted to %qT when passed through %<...%>",
22064 : type, promoted_type);
22065 30 : if (!gave_help && warned)
22066 : {
22067 15 : gave_help = true;
22068 15 : inform (xloc, "(so you should pass %qT not %qT to %<va_arg%>)",
22069 : promoted_type, type);
22070 : }
22071 :
22072 : /* We can, however, treat "undefined" any way we please.
22073 : Call abort to encourage the user to fix the program. */
22074 23 : if (warned)
22075 23 : inform (xloc, "if this code is reached, the program will abort");
22076 : /* Before the abort, allow the evaluation of the va_list
22077 : expression to exit or longjmp. */
22078 30 : gimplify_and_add (valist, pre_p);
22079 60 : t = build_call_expr_loc (loc,
22080 : builtin_decl_implicit (BUILT_IN_TRAP), 0);
22081 30 : gimplify_and_add (t, pre_p);
22082 :
22083 : /* This is dead code, but go ahead and finish so that the
22084 : mode of the result comes out right. */
22085 30 : *expr_p = dummy_object (type);
22086 30 : return GS_ALL_DONE;
22087 30 : }
22088 :
22089 51082 : tag = build_int_cst (build_pointer_type (type), 0);
22090 51082 : aptag = build_int_cst (TREE_TYPE (valist), 0);
22091 :
22092 51082 : *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3,
22093 : valist, tag, aptag);
22094 :
22095 : /* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
22096 : needs to be expanded. */
22097 51082 : cfun->curr_properties &= ~PROP_gimple_lva;
22098 :
22099 51082 : return GS_OK;
22100 : }
22101 :
22102 : /* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P.
22103 :
22104 : DST/SRC are the destination and source respectively. You can pass
22105 : ungimplified trees in DST or SRC, in which case they will be
22106 : converted to a gimple operand if necessary.
22107 :
22108 : This function returns the newly created GIMPLE_ASSIGN tuple. */
22109 :
22110 : gimple *
22111 875161 : gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
22112 : {
22113 875161 : tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
22114 875161 : gimplify_and_add (t, seq_p);
22115 875161 : ggc_free (t);
22116 875161 : return gimple_seq_last_stmt (*seq_p);
22117 : }
22118 :
22119 : inline hashval_t
22120 1584541 : gimplify_hasher::hash (const elt_t *p)
22121 : {
22122 1584541 : tree t = p->val;
22123 1584541 : return iterative_hash_expr (t, 0);
22124 : }
22125 :
22126 : inline bool
22127 594997 : gimplify_hasher::equal (const elt_t *p1, const elt_t *p2)
22128 : {
22129 594997 : tree t1 = p1->val;
22130 594997 : tree t2 = p2->val;
22131 594997 : enum tree_code code = TREE_CODE (t1);
22132 :
22133 594997 : if (TREE_CODE (t2) != code
22134 594997 : || TREE_TYPE (t1) != TREE_TYPE (t2))
22135 : return false;
22136 :
22137 364599 : if (!operand_equal_p (t1, t2, 0))
22138 : return false;
22139 :
22140 : return true;
22141 : }
|