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 :
79 : /* Identifier for a basic condition, mapping it to other basic conditions of
80 : its Boolean expression. Basic conditions given the same uid (in the same
81 : function) are parts of the same ANDIF/ORIF expression. Used for condition
82 : coverage. */
83 : static unsigned nextconduid = 1;
84 :
85 : /* Annotated gconds so that basic conditions in the same expression map to
86 : the same uid. This is used for condition coverage. */
87 : static hash_map <tree, unsigned> *cond_uids;
88 :
89 : /* Get a fresh identifier for a new condition expression. This is used for
90 : condition coverage. */
91 : static unsigned
92 5779533 : next_cond_uid ()
93 : {
94 5779533 : return nextconduid++;
95 : }
96 :
97 : /* Reset the condition uid to the value it should have when compiling a new
98 : function. 0 is already the default/untouched value, so start at non-zero.
99 : A valid and set id should always be > 0. This is used for condition
100 : coverage. */
101 : static void
102 2900388 : reset_cond_uid ()
103 : {
104 2900388 : nextconduid = 1;
105 0 : }
106 :
107 : /* Associate the condition STMT with the discriminator UID. STMTs that are
108 : broken down with ANDIF/ORIF from the same Boolean expression should be given
109 : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
110 : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
111 : for condition coverage. */
112 : static void
113 1207058 : tree_associate_condition_with_expr (tree stmt, unsigned uid)
114 : {
115 1207058 : if (!condition_coverage_flag)
116 : return;
117 :
118 527 : if (!cond_uids)
119 65 : cond_uids = new hash_map <tree, unsigned> ();
120 :
121 527 : cond_uids->put (stmt, uid);
122 : }
123 :
124 : /* Hash set of poisoned variables in a bind expr. */
125 : static hash_set<tree> *asan_poisoned_variables = NULL;
126 :
127 : /* Hash set of already-resolved calls to OpenMP "declare variant"
128 : functions. A call can resolve to the original function and
129 : we don't want to repeat the resolution multiple times. */
130 : static hash_set<tree> *omp_resolved_variant_calls = NULL;
131 :
132 : enum gimplify_omp_var_data
133 : {
134 : GOVD_SEEN = 0x000001,
135 : GOVD_EXPLICIT = 0x000002,
136 : GOVD_SHARED = 0x000004,
137 : GOVD_PRIVATE = 0x000008,
138 : GOVD_FIRSTPRIVATE = 0x000010,
139 : GOVD_LASTPRIVATE = 0x000020,
140 : GOVD_REDUCTION = 0x000040,
141 : GOVD_LOCAL = 0x00080,
142 : GOVD_MAP = 0x000100,
143 : GOVD_DEBUG_PRIVATE = 0x000200,
144 : GOVD_PRIVATE_OUTER_REF = 0x000400,
145 : GOVD_LINEAR = 0x000800,
146 : GOVD_ALIGNED = 0x001000,
147 :
148 : /* Flag for GOVD_MAP: don't copy back. */
149 : GOVD_MAP_TO_ONLY = 0x002000,
150 :
151 : /* Flag for GOVD_LINEAR or GOVD_LASTPRIVATE: no outer reference. */
152 : GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 0x004000,
153 :
154 : GOVD_MAP_0LEN_ARRAY = 0x008000,
155 :
156 : /* Flag for GOVD_MAP, if it is always, to or always, tofrom mapping. */
157 : GOVD_MAP_ALWAYS_TO = 0x010000,
158 :
159 : /* Flag for shared vars that are or might be stored to in the region. */
160 : GOVD_WRITTEN = 0x020000,
161 :
162 : /* Flag for GOVD_MAP, if it is a forced mapping. */
163 : GOVD_MAP_FORCE = 0x040000,
164 :
165 : /* Flag for GOVD_MAP: must be present already. */
166 : GOVD_MAP_FORCE_PRESENT = 0x080000,
167 :
168 : /* Flag for GOVD_MAP: only allocate. */
169 : GOVD_MAP_ALLOC_ONLY = 0x100000,
170 :
171 : /* Flag for GOVD_MAP: only copy back. */
172 : GOVD_MAP_FROM_ONLY = 0x200000,
173 :
174 : GOVD_NONTEMPORAL = 0x400000,
175 :
176 : /* Flag for GOVD_LASTPRIVATE: conditional modifier. */
177 : GOVD_LASTPRIVATE_CONDITIONAL = 0x800000,
178 :
179 : GOVD_CONDTEMP = 0x1000000,
180 :
181 : /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */
182 : GOVD_REDUCTION_INSCAN = 0x2000000,
183 :
184 : /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. */
185 : GOVD_FIRSTPRIVATE_IMPLICIT = 0x4000000,
186 :
187 : GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
188 : | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
189 : | GOVD_LOCAL)
190 : };
191 :
192 :
193 : enum omp_region_type
194 : {
195 : ORT_WORKSHARE = 0x00,
196 : ORT_TASKGROUP = 0x01,
197 : ORT_DISPATCH = 0x02,
198 : ORT_SIMD = 0x04,
199 :
200 : ORT_PARALLEL = 0x08,
201 : ORT_COMBINED_PARALLEL = ORT_PARALLEL | 1,
202 :
203 : ORT_TASK = 0x10,
204 : ORT_UNTIED_TASK = ORT_TASK | 1,
205 : ORT_TASKLOOP = ORT_TASK | 2,
206 : ORT_UNTIED_TASKLOOP = ORT_UNTIED_TASK | 2,
207 :
208 : ORT_TEAMS = 0x20,
209 : ORT_COMBINED_TEAMS = ORT_TEAMS | 1,
210 : ORT_HOST_TEAMS = ORT_TEAMS | 2,
211 : ORT_COMBINED_HOST_TEAMS = ORT_COMBINED_TEAMS | 2,
212 :
213 : /* Data region. */
214 : ORT_TARGET_DATA = 0x40,
215 :
216 : /* Data region with offloading. */
217 : ORT_TARGET = 0x80,
218 : ORT_COMBINED_TARGET = ORT_TARGET | 1,
219 : ORT_IMPLICIT_TARGET = ORT_TARGET | 2,
220 :
221 : /* OpenACC variants. */
222 : ORT_ACC = 0x100, /* A generic OpenACC region. */
223 : ORT_ACC_DATA = ORT_ACC | ORT_TARGET_DATA, /* Data construct. */
224 : ORT_ACC_PARALLEL = ORT_ACC | ORT_TARGET, /* Parallel construct */
225 : ORT_ACC_KERNELS = ORT_ACC | ORT_TARGET | 2, /* Kernels construct. */
226 : ORT_ACC_SERIAL = ORT_ACC | ORT_TARGET | 4, /* Serial construct. */
227 : ORT_ACC_HOST_DATA = ORT_ACC | ORT_TARGET_DATA | 2, /* Host data. */
228 :
229 : /* Dummy OpenMP region, used to disable expansion of
230 : DECL_VALUE_EXPRs in taskloop pre body. */
231 : ORT_NONE = 0x200
232 : };
233 :
234 : /* Gimplify hashtable helper. */
235 :
236 : struct gimplify_hasher : free_ptr_hash <elt_t>
237 : {
238 : static inline hashval_t hash (const elt_t *);
239 : static inline bool equal (const elt_t *, const elt_t *);
240 : };
241 :
242 : struct gimplify_ctx
243 : {
244 : struct gimplify_ctx *prev_context;
245 :
246 : vec<gbind *> bind_expr_stack;
247 : tree temps;
248 : gimple_seq conditional_cleanups;
249 : tree exit_label;
250 : tree return_temp;
251 :
252 : vec<tree> case_labels;
253 : hash_set<tree> *live_switch_vars;
254 : /* The formal temporary table. Should this be persistent? */
255 : hash_table<gimplify_hasher> *temp_htab;
256 :
257 : int conditions;
258 : unsigned into_ssa : 1;
259 : unsigned allow_rhs_cond_expr : 1;
260 : unsigned in_cleanup_point_expr : 1;
261 : unsigned keep_stack : 1;
262 : unsigned save_stack : 1;
263 : unsigned in_switch_expr : 1;
264 : unsigned in_handler_expr : 1;
265 : };
266 :
267 : enum gimplify_defaultmap_kind
268 : {
269 : GDMK_SCALAR,
270 : GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only. */
271 : GDMK_AGGREGATE,
272 : GDMK_ALLOCATABLE,
273 : GDMK_POINTER
274 : };
275 :
276 : struct gimplify_omp_ctx
277 : {
278 : struct gimplify_omp_ctx *outer_context;
279 : splay_tree variables;
280 : hash_map<omp_name_type<tree>, tree> *implicit_mappers;
281 : hash_set<tree> *privatized_types;
282 : tree clauses;
283 : /* Iteration variables in an OMP_FOR. */
284 : vec<tree> loop_iter_var;
285 : location_t location;
286 : enum omp_clause_default_kind default_kind;
287 : enum omp_region_type region_type;
288 : enum tree_code code;
289 : bool combined_loop;
290 : bool distribute;
291 : bool target_firstprivatize_array_bases;
292 : bool add_safelen1;
293 : bool order_concurrent;
294 : bool has_depend;
295 : bool in_for_exprs;
296 : bool in_call_args;
297 : int defaultmap[5];
298 : };
299 :
300 : static struct gimplify_ctx *gimplify_ctxp;
301 : static struct gimplify_omp_ctx *gimplify_omp_ctxp;
302 : static bool in_omp_construct;
303 :
304 : /* Forward declaration. */
305 : static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
306 : static hash_map<tree, tree> *oacc_declare_returns;
307 : static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
308 : bool (*) (tree), fallback_t, bool);
309 : static void prepare_gimple_addressable (tree *, gimple_seq *);
310 :
311 : /* Shorter alias name for the above function for use in gimplify.cc
312 : only. */
313 :
314 : static inline void
315 92359935 : gimplify_seq_add_stmt (gimple_seq *seq_p, gimple *gs)
316 : {
317 92359935 : gimple_seq_add_stmt_without_update (seq_p, gs);
318 6647405 : }
319 :
320 : /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
321 : NULL, a new sequence is allocated. This function is
322 : similar to gimple_seq_add_seq, but does not scan the operands.
323 : During gimplification, we need to manipulate statement sequences
324 : before the def/use vectors have been constructed. */
325 :
326 : static void
327 9217012 : gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
328 : {
329 9217012 : gimple_stmt_iterator si;
330 :
331 9217012 : if (src == NULL)
332 4027990 : return;
333 :
334 5189022 : si = gsi_last (*dst_p);
335 5189022 : gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
336 : }
337 :
338 :
339 : /* Pointer to a list of allocated gimplify_ctx structs to be used for pushing
340 : and popping gimplify contexts. */
341 :
342 : static struct gimplify_ctx *ctx_pool = NULL;
343 :
344 : /* Return a gimplify context struct from the pool. */
345 :
346 : static inline struct gimplify_ctx *
347 8902599 : ctx_alloc (void)
348 : {
349 8902599 : struct gimplify_ctx * c = ctx_pool;
350 :
351 8902599 : if (c)
352 8637222 : ctx_pool = c->prev_context;
353 : else
354 265377 : c = XNEW (struct gimplify_ctx);
355 :
356 8902599 : memset (c, '\0', sizeof (*c));
357 8902599 : return c;
358 : }
359 :
360 : /* Put gimplify context C back into the pool. */
361 :
362 : static inline void
363 8902595 : ctx_free (struct gimplify_ctx *c)
364 : {
365 8902595 : c->prev_context = ctx_pool;
366 8902595 : ctx_pool = c;
367 : }
368 :
369 : /* Free allocated ctx stack memory. */
370 :
371 : void
372 232916 : free_gimplify_stack (void)
373 : {
374 232916 : struct gimplify_ctx *c;
375 :
376 468494 : while ((c = ctx_pool))
377 : {
378 235578 : ctx_pool = c->prev_context;
379 235578 : free (c);
380 : }
381 232916 : }
382 :
383 :
384 : /* Set up a context for the gimplifier. */
385 :
386 : void
387 8902599 : push_gimplify_context (bool in_ssa, bool rhs_cond_ok)
388 : {
389 8902599 : struct gimplify_ctx *c = ctx_alloc ();
390 :
391 8902599 : c->prev_context = gimplify_ctxp;
392 8902599 : gimplify_ctxp = c;
393 8902599 : gimplify_ctxp->into_ssa = in_ssa;
394 8902599 : gimplify_ctxp->allow_rhs_cond_expr = rhs_cond_ok;
395 8902599 : }
396 :
397 : /* Tear down a context for the gimplifier. If BODY is non-null, then
398 : put the temporaries into the outer BIND_EXPR. Otherwise, put them
399 : in the local_decls.
400 :
401 : BODY is not a sequence, but the first tuple in a sequence. */
402 :
403 : void
404 8902595 : pop_gimplify_context (gimple *body)
405 : {
406 8902595 : struct gimplify_ctx *c = gimplify_ctxp;
407 :
408 8902595 : gcc_assert (c
409 : && (!c->bind_expr_stack.exists ()
410 : || c->bind_expr_stack.is_empty ()));
411 8902595 : c->bind_expr_stack.release ();
412 8902595 : gimplify_ctxp = c->prev_context;
413 :
414 8902595 : if (body)
415 3024785 : declare_vars (c->temps, body, false);
416 : else
417 5877810 : record_vars (c->temps);
418 :
419 8902595 : delete c->temp_htab;
420 8902595 : c->temp_htab = NULL;
421 8902595 : ctx_free (c);
422 8902595 : }
423 :
424 : /* Push a GIMPLE_BIND tuple onto the stack of bindings. */
425 :
426 : static void
427 5931135 : gimple_push_bind_expr (gbind *bind_stmt)
428 : {
429 5931135 : gimplify_ctxp->bind_expr_stack.reserve (8);
430 5931135 : gimplify_ctxp->bind_expr_stack.safe_push (bind_stmt);
431 5931135 : }
432 :
433 : /* Pop the first element off the stack of bindings. */
434 :
435 : static void
436 5931135 : gimple_pop_bind_expr (void)
437 : {
438 0 : gimplify_ctxp->bind_expr_stack.pop ();
439 1301 : }
440 :
441 : /* Return the first element of the stack of bindings. */
442 :
443 : gbind *
444 0 : gimple_current_bind_expr (void)
445 : {
446 0 : return gimplify_ctxp->bind_expr_stack.last ();
447 : }
448 :
449 : /* Return the stack of bindings created during gimplification. */
450 :
451 : vec<gbind *>
452 359 : gimple_bind_expr_stack (void)
453 : {
454 359 : return gimplify_ctxp->bind_expr_stack;
455 : }
456 :
457 : /* Return true iff there is a COND_EXPR between us and the innermost
458 : CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
459 :
460 : static bool
461 2812535 : gimple_conditional_context (void)
462 : {
463 2812535 : return gimplify_ctxp->conditions > 0;
464 : }
465 :
466 : /* Note that we've entered a COND_EXPR. */
467 :
468 : static void
469 5779968 : gimple_push_condition (void)
470 : {
471 : #ifdef ENABLE_GIMPLE_CHECKING
472 5779968 : if (gimplify_ctxp->conditions == 0)
473 3806730 : gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
474 : #endif
475 5779968 : ++(gimplify_ctxp->conditions);
476 5779968 : }
477 :
478 : /* Note that we've left a COND_EXPR. If we're back at unconditional scope
479 : now, add any conditional cleanups we've seen to the prequeue. */
480 :
481 : static void
482 5779968 : gimple_pop_condition (gimple_seq *pre_p)
483 : {
484 5779968 : int conds = --(gimplify_ctxp->conditions);
485 :
486 5779968 : gcc_assert (conds >= 0);
487 5779968 : if (conds == 0)
488 : {
489 3806730 : gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
490 3806730 : gimplify_ctxp->conditional_cleanups = NULL;
491 : }
492 5779968 : }
493 :
494 : /* A stable comparison routine for use with splay trees and DECLs. */
495 :
496 : static int
497 18266053 : splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
498 : {
499 18266053 : tree a = (tree) xa;
500 18266053 : tree b = (tree) xb;
501 :
502 18266053 : return DECL_UID (a) - DECL_UID (b);
503 : }
504 :
505 : /* Create a new omp construct that deals with variable remapping. */
506 :
507 : static struct gimplify_omp_ctx *
508 140175 : new_omp_context (enum omp_region_type region_type)
509 : {
510 140175 : struct gimplify_omp_ctx *c;
511 :
512 140175 : c = XCNEW (struct gimplify_omp_ctx);
513 140175 : c->outer_context = gimplify_omp_ctxp;
514 140175 : c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
515 140175 : c->implicit_mappers = new hash_map<omp_name_type<tree>, tree>;
516 140175 : c->privatized_types = new hash_set<tree>;
517 140175 : c->location = input_location;
518 140175 : c->region_type = region_type;
519 140175 : if ((region_type & ORT_TASK) == 0)
520 134129 : c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
521 : else
522 6046 : c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
523 140175 : c->defaultmap[GDMK_SCALAR] = GOVD_MAP;
524 140175 : c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP;
525 140175 : c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP;
526 140175 : c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP;
527 140175 : c->defaultmap[GDMK_POINTER] = GOVD_MAP;
528 :
529 140175 : return c;
530 : }
531 :
532 : /* Destroy an omp construct that deals with variable remapping. */
533 :
534 : static void
535 139616 : delete_omp_context (struct gimplify_omp_ctx *c)
536 : {
537 139616 : splay_tree_delete (c->variables);
538 279232 : delete c->privatized_types;
539 279232 : delete c->implicit_mappers;
540 139616 : c->loop_iter_var.release ();
541 139616 : XDELETE (c);
542 139616 : }
543 :
544 : static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
545 : static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
546 :
547 : /* Both gimplify the statement T and append it to *SEQ_P. This function
548 : behaves exactly as gimplify_stmt, but you don't have to pass T as a
549 : reference. */
550 :
551 : void
552 37987332 : gimplify_and_add (tree t, gimple_seq *seq_p)
553 : {
554 37987332 : gimplify_stmt (&t, seq_p);
555 37987332 : }
556 :
557 : /* Gimplify statement T into sequence *SEQ_P, and return the first
558 : tuple in the sequence of generated tuples for this statement.
559 : Return NULL if gimplifying T produced no tuples. */
560 :
561 : static gimple *
562 105265 : gimplify_and_return_first (tree t, gimple_seq *seq_p)
563 : {
564 105265 : gimple_stmt_iterator last = gsi_last (*seq_p);
565 :
566 105265 : gimplify_and_add (t, seq_p);
567 :
568 105265 : if (!gsi_end_p (last))
569 : {
570 4881 : gsi_next (&last);
571 4881 : return gsi_stmt (last);
572 : }
573 : else
574 100384 : return gimple_seq_first_stmt (*seq_p);
575 : }
576 :
577 : /* Returns true iff T is a valid RHS for an assignment to an un-renamed
578 : LHS, or for a call argument. */
579 :
580 : static bool
581 237381 : is_gimple_mem_rhs (tree t)
582 : {
583 : /* If we're dealing with a renamable type, either source or dest must be
584 : a renamed variable. */
585 237381 : if (is_gimple_reg_type (TREE_TYPE (t)))
586 234016 : return is_gimple_val (t);
587 : else
588 3365 : return is_gimple_val (t) || is_gimple_lvalue (t);
589 : }
590 :
591 : /* Return true if T is a CALL_EXPR or an expression that can be
592 : assigned to a temporary. Note that this predicate should only be
593 : used during gimplification. See the rationale for this in
594 : gimplify_modify_expr. */
595 :
596 : static bool
597 97523941 : is_gimple_reg_rhs_or_call (tree t)
598 : {
599 71620272 : return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
600 97523941 : || TREE_CODE (t) == CALL_EXPR);
601 : }
602 :
603 : /* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
604 : this predicate should only be used during gimplification. See the
605 : rationale for this in gimplify_modify_expr. */
606 :
607 : static bool
608 14247380 : is_gimple_mem_rhs_or_call (tree t)
609 : {
610 : /* If we're dealing with a renamable type, either source or dest must be
611 : a renamed variable. */
612 14247380 : if (is_gimple_reg_type (TREE_TYPE (t)))
613 10906110 : return is_gimple_val (t);
614 : else
615 3341270 : return (is_gimple_val (t)
616 1672748 : || is_gimple_lvalue (t)
617 1156509 : || (TREE_CODE (t) == CONSTRUCTOR && CONSTRUCTOR_NELTS (t) == 0)
618 4497389 : || TREE_CODE (t) == CALL_EXPR);
619 : }
620 :
621 : /* Create a temporary with a name derived from VAL. Subroutine of
622 : lookup_tmp_var; nobody else should call this function. */
623 :
624 : static inline tree
625 2142803 : create_tmp_from_val (tree val)
626 : {
627 : /* Drop all qualifiers and address-space information from the value type. */
628 2142803 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
629 2142803 : tree var = create_tmp_var (type, get_name (val));
630 2142803 : return var;
631 : }
632 :
633 : /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
634 : an existing expression temporary. If NOT_GIMPLE_REG, mark it as such. */
635 :
636 : static tree
637 2377910 : lookup_tmp_var (tree val, bool is_formal, bool not_gimple_reg)
638 : {
639 2377910 : tree ret;
640 :
641 : /* We cannot mark a formal temporary with DECL_NOT_GIMPLE_REG_P. */
642 2377910 : gcc_assert (!is_formal || !not_gimple_reg);
643 :
644 : /* If not optimizing, never really reuse a temporary. local-alloc
645 : won't allocate any variable that is used in more than one basic
646 : block, which means it will go into memory, causing much extra
647 : work in reload and final and poorer code generation, outweighing
648 : the extra memory allocation here. */
649 2377910 : if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
650 : {
651 1088711 : ret = create_tmp_from_val (val);
652 1088711 : DECL_NOT_GIMPLE_REG_P (ret) = not_gimple_reg;
653 : }
654 : else
655 : {
656 1289199 : elt_t elt, *elt_p;
657 1289199 : elt_t **slot;
658 :
659 1289199 : elt.val = val;
660 1289199 : if (!gimplify_ctxp->temp_htab)
661 395021 : gimplify_ctxp->temp_htab = new hash_table<gimplify_hasher> (1000);
662 1289199 : slot = gimplify_ctxp->temp_htab->find_slot (&elt, INSERT);
663 1289199 : if (*slot == NULL)
664 : {
665 1054092 : elt_p = XNEW (elt_t);
666 1054092 : elt_p->val = val;
667 1054092 : elt_p->temp = ret = create_tmp_from_val (val);
668 1054092 : *slot = elt_p;
669 : }
670 : else
671 : {
672 235107 : elt_p = *slot;
673 235107 : ret = elt_p->temp;
674 : }
675 : }
676 :
677 2377910 : return ret;
678 : }
679 :
680 : /* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
681 :
682 : static tree
683 26441031 : internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
684 : bool is_formal, bool allow_ssa, bool not_gimple_reg)
685 : {
686 26441031 : tree t, mod;
687 :
688 : /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
689 : can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
690 26441031 : gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
691 : fb_rvalue);
692 :
693 26441031 : if (allow_ssa
694 26172985 : && gimplify_ctxp->into_ssa
695 51173044 : && is_gimple_reg_type (TREE_TYPE (val)))
696 : {
697 24063122 : t = make_ssa_name (TYPE_MAIN_VARIANT (TREE_TYPE (val)));
698 24063122 : if (! gimple_in_ssa_p (cfun))
699 : {
700 20723244 : const char *name = get_name (val);
701 20723244 : if (name)
702 6763746 : SET_SSA_NAME_VAR_OR_IDENTIFIER (t, create_tmp_var_name (name));
703 : }
704 : }
705 : else
706 2377909 : t = lookup_tmp_var (val, is_formal, not_gimple_reg);
707 :
708 26441031 : mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
709 :
710 26441031 : SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location));
711 :
712 : /* gimplify_modify_expr might want to reduce this further. */
713 26441031 : gimplify_and_add (mod, pre_p);
714 26441031 : ggc_free (mod);
715 :
716 : /* If we failed to gimplify VAL then we can end up with the temporary
717 : SSA name not having a definition. In this case return a decl. */
718 26441031 : if (TREE_CODE (t) == SSA_NAME && ! SSA_NAME_DEF_STMT (t))
719 1 : return lookup_tmp_var (val, is_formal, not_gimple_reg);
720 :
721 : return t;
722 : }
723 :
724 : /* Return a formal temporary variable initialized with VAL. PRE_P is as
725 : in gimplify_expr. Only use this function if:
726 :
727 : 1) The value of the unfactored expression represented by VAL will not
728 : change between the initialization and use of the temporary, and
729 : 2) The temporary will not be otherwise modified.
730 :
731 : For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
732 : and #2 means it is inappropriate for && temps.
733 :
734 : For other cases, use get_initialized_tmp_var instead. */
735 :
736 : tree
737 25942225 : get_formal_tmp_var (tree val, gimple_seq *pre_p)
738 : {
739 25942225 : return internal_get_tmp_var (val, pre_p, NULL, true, true, false);
740 : }
741 :
742 : /* Return a temporary variable initialized with VAL. PRE_P and POST_P
743 : are as in gimplify_expr. */
744 :
745 : tree
746 486792 : get_initialized_tmp_var (tree val, gimple_seq *pre_p,
747 : gimple_seq *post_p /* = NULL */,
748 : bool allow_ssa /* = true */)
749 : {
750 486792 : return internal_get_tmp_var (val, pre_p, post_p, false, allow_ssa, false);
751 : }
752 :
753 : /* Declare all the variables in VARS in SCOPE. If DEBUG_INFO is true,
754 : generate debug info for them; otherwise don't. */
755 :
756 : void
757 3032687 : declare_vars (tree vars, gimple *gs, bool debug_info)
758 : {
759 3032687 : tree last = vars;
760 3032687 : if (last)
761 : {
762 1898591 : tree temps, block;
763 :
764 1898591 : gbind *scope = as_a <gbind *> (gs);
765 :
766 1898591 : temps = nreverse (last);
767 :
768 1898591 : block = gimple_bind_block (scope);
769 1898591 : gcc_assert (!block || TREE_CODE (block) == BLOCK);
770 1898591 : if (!block || !debug_info)
771 : {
772 1894913 : DECL_CHAIN (last) = gimple_bind_vars (scope);
773 1894913 : gimple_bind_set_vars (scope, temps);
774 : }
775 : else
776 : {
777 : /* We need to attach the nodes both to the BIND_EXPR and to its
778 : associated BLOCK for debugging purposes. The key point here
779 : is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
780 : is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
781 3678 : if (BLOCK_VARS (block))
782 3485 : BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
783 : else
784 : {
785 193 : gimple_bind_set_vars (scope,
786 : chainon (gimple_bind_vars (scope), temps));
787 193 : BLOCK_VARS (block) = temps;
788 : }
789 : }
790 : }
791 3032687 : }
792 :
793 : /* For VAR a VAR_DECL of variable size, try to find a constant upper bound
794 : for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
795 : no such upper bound can be obtained. */
796 :
797 : static void
798 0 : force_constant_size (tree var)
799 : {
800 : /* The only attempt we make is by querying the maximum size of objects
801 : of the variable's type. */
802 :
803 0 : HOST_WIDE_INT max_size;
804 :
805 0 : gcc_assert (VAR_P (var));
806 :
807 0 : max_size = max_int_size_in_bytes (TREE_TYPE (var));
808 :
809 0 : gcc_assert (max_size >= 0);
810 :
811 0 : DECL_SIZE_UNIT (var)
812 0 : = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
813 0 : DECL_SIZE (var)
814 0 : = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
815 0 : }
816 :
817 : /* Push the temporary variable TMP into the current binding. */
818 :
819 : void
820 23810 : gimple_add_tmp_var_fn (struct function *fn, tree tmp)
821 : {
822 23810 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
823 :
824 : /* Later processing assumes that the object size is constant, which might
825 : not be true at this point. Force the use of a constant upper bound in
826 : this case. */
827 23810 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
828 0 : force_constant_size (tmp);
829 :
830 23810 : DECL_CONTEXT (tmp) = fn->decl;
831 23810 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
832 :
833 23810 : record_vars_into (tmp, fn->decl);
834 23810 : }
835 :
836 : /* Push the temporary variable TMP into the current binding. */
837 :
838 : void
839 16319424 : gimple_add_tmp_var (tree tmp)
840 : {
841 16319424 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
842 :
843 : /* Later processing assumes that the object size is constant, which might
844 : not be true at this point. Force the use of a constant upper bound in
845 : this case. */
846 16319424 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
847 0 : force_constant_size (tmp);
848 :
849 16319424 : DECL_CONTEXT (tmp) = current_function_decl;
850 16319424 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
851 :
852 16319424 : if (gimplify_ctxp)
853 : {
854 5601169 : DECL_CHAIN (tmp) = gimplify_ctxp->temps;
855 5601169 : gimplify_ctxp->temps = tmp;
856 :
857 : /* Mark temporaries local within the nearest enclosing parallel. */
858 5601169 : if (gimplify_omp_ctxp)
859 : {
860 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
861 552167 : int flag = GOVD_LOCAL | GOVD_SEEN;
862 : while (ctx
863 552167 : && (ctx->region_type == ORT_WORKSHARE
864 : || ctx->region_type == ORT_TASKGROUP
865 404638 : || ctx->region_type == ORT_SIMD
866 354447 : || ctx->region_type == ORT_ACC))
867 : {
868 204578 : if (ctx->region_type == ORT_SIMD
869 50191 : && TREE_ADDRESSABLE (tmp)
870 95 : && !TREE_STATIC (tmp))
871 : {
872 95 : if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST)
873 0 : ctx->add_safelen1 = true;
874 95 : else if (ctx->in_for_exprs)
875 : flag = GOVD_PRIVATE;
876 : else
877 : flag = GOVD_PRIVATE | GOVD_SEEN;
878 : break;
879 : }
880 204483 : ctx = ctx->outer_context;
881 : }
882 347589 : if (ctx)
883 320503 : omp_add_variable (ctx, tmp, flag);
884 : }
885 : }
886 10718255 : else if (cfun)
887 10718255 : record_vars (tmp);
888 : else
889 : {
890 0 : gimple_seq body_seq;
891 :
892 : /* This case is for nested functions. We need to expose the locals
893 : they create. */
894 0 : body_seq = gimple_body (current_function_decl);
895 0 : declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
896 : }
897 16319424 : }
898 :
899 : /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
900 : any nested functions. */
901 :
902 : static void
903 2926903 : unshare_body (tree fndecl)
904 : {
905 2926903 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
906 : /* If the language requires deep unsharing, we need a pointer set to make
907 : sure we don't repeatedly unshare subtrees of unshareable nodes. */
908 2926903 : hash_set<tree> *visited
909 2926903 : = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
910 :
911 2926903 : copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
912 2926903 : copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
913 2926903 : copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
914 :
915 2930234 : delete visited;
916 :
917 2926903 : if (cgn)
918 5899124 : for (cgn = first_nested_function (cgn); cgn;
919 26011 : cgn = next_nested_function (cgn))
920 26011 : unshare_body (cgn->decl);
921 2926903 : }
922 :
923 : /* Callback for walk_tree to unmark the visited trees rooted at *TP.
924 : Subtrees are walked until the first unvisited node is encountered. */
925 :
926 : static tree
927 279133945 : unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
928 : {
929 279133945 : tree t = *tp;
930 :
931 : /* If this node has been visited, unmark it and keep looking. */
932 279133945 : if (TREE_VISITED (t))
933 195714354 : TREE_VISITED (t) = 0;
934 :
935 : /* Otherwise, don't look any deeper. */
936 : else
937 83419591 : *walk_subtrees = 0;
938 :
939 279133945 : return NULL_TREE;
940 : }
941 :
942 : /* Unmark the visited trees rooted at *TP. */
943 :
944 : static inline void
945 8780709 : unmark_visited (tree *tp)
946 : {
947 8780709 : walk_tree (tp, unmark_visited_r, NULL, NULL);
948 8780709 : }
949 :
950 : /* Likewise, but mark all trees as not visited. */
951 :
952 : static void
953 2926903 : unvisit_body (tree fndecl)
954 : {
955 2926903 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
956 :
957 2926903 : unmark_visited (&DECL_SAVED_TREE (fndecl));
958 2926903 : unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
959 2926903 : unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
960 :
961 2926903 : if (cgn)
962 2949562 : for (cgn = first_nested_function (cgn);
963 2949562 : cgn; cgn = next_nested_function (cgn))
964 26011 : unvisit_body (cgn->decl);
965 2926903 : }
966 :
967 : /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
968 : one, OR_ELSE otherwise. The location of a STATEMENT_LISTs
969 : comprising at least one DEBUG_BEGIN_STMT followed by exactly one
970 : EXPR is the location of the EXPR. */
971 :
972 : static location_t
973 1162476 : rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
974 : {
975 1162476 : if (!expr)
976 : return or_else;
977 :
978 1162476 : if (EXPR_HAS_LOCATION (expr))
979 811567 : return EXPR_LOCATION (expr);
980 :
981 350909 : if (TREE_CODE (expr) != STATEMENT_LIST)
982 : return or_else;
983 :
984 0 : tree_stmt_iterator i = tsi_start (expr);
985 :
986 0 : bool found = false;
987 0 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
988 : {
989 0 : found = true;
990 0 : tsi_next (&i);
991 : }
992 :
993 350909 : if (!found || !tsi_one_before_end_p (i))
994 : return or_else;
995 :
996 0 : return rexpr_location (tsi_stmt (i), or_else);
997 : }
998 :
999 : /* Return TRUE iff EXPR (maybe recursively) has a location; see
1000 : rexpr_location for the potential recursion. */
1001 :
1002 : static inline bool
1003 503915 : rexpr_has_location (tree expr)
1004 : {
1005 299963 : return rexpr_location (expr) != UNKNOWN_LOCATION;
1006 : }
1007 :
1008 :
1009 : /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
1010 : contain statements and have a value. Assign its value to a temporary
1011 : and give it void_type_node. Return the temporary, or NULL_TREE if
1012 : WRAPPER was already void. */
1013 :
1014 : tree
1015 20126124 : voidify_wrapper_expr (tree wrapper, tree temp)
1016 : {
1017 20126124 : tree type = TREE_TYPE (wrapper);
1018 20126124 : if (type && !VOID_TYPE_P (type))
1019 : {
1020 : tree *p;
1021 :
1022 : /* Set p to point to the body of the wrapper. Loop until we find
1023 : something that isn't a wrapper. */
1024 777279 : for (p = &wrapper; p && *p; )
1025 : {
1026 777279 : switch (TREE_CODE (*p))
1027 : {
1028 3144 : case BIND_EXPR:
1029 3144 : TREE_SIDE_EFFECTS (*p) = 1;
1030 3144 : TREE_TYPE (*p) = void_type_node;
1031 : /* For a BIND_EXPR, the body is operand 1. */
1032 3144 : p = &BIND_EXPR_BODY (*p);
1033 3144 : break;
1034 :
1035 358499 : case CLEANUP_POINT_EXPR:
1036 358499 : case TRY_FINALLY_EXPR:
1037 358499 : case TRY_CATCH_EXPR:
1038 358499 : TREE_SIDE_EFFECTS (*p) = 1;
1039 358499 : TREE_TYPE (*p) = void_type_node;
1040 358499 : p = &TREE_OPERAND (*p, 0);
1041 358499 : break;
1042 :
1043 18376 : case STATEMENT_LIST:
1044 18376 : {
1045 18376 : tree_stmt_iterator i = tsi_last (*p);
1046 18376 : TREE_SIDE_EFFECTS (*p) = 1;
1047 18376 : TREE_TYPE (*p) = void_type_node;
1048 18376 : p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
1049 : }
1050 18376 : break;
1051 :
1052 : case COMPOUND_EXPR:
1053 : /* Advance to the last statement. Set all container types to
1054 : void. */
1055 64292 : for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
1056 : {
1057 32149 : TREE_SIDE_EFFECTS (*p) = 1;
1058 32149 : TREE_TYPE (*p) = void_type_node;
1059 : }
1060 : break;
1061 :
1062 76 : case TRANSACTION_EXPR:
1063 76 : TREE_SIDE_EFFECTS (*p) = 1;
1064 76 : TREE_TYPE (*p) = void_type_node;
1065 76 : p = &TRANSACTION_EXPR_BODY (*p);
1066 76 : break;
1067 :
1068 365041 : default:
1069 : /* Assume that any tree upon which voidify_wrapper_expr is
1070 : directly called is a wrapper, and that its body is op0. */
1071 365041 : if (p == &wrapper)
1072 : {
1073 33 : TREE_SIDE_EFFECTS (*p) = 1;
1074 33 : TREE_TYPE (*p) = void_type_node;
1075 33 : p = &TREE_OPERAND (*p, 0);
1076 33 : break;
1077 : }
1078 365008 : goto out;
1079 : }
1080 : }
1081 :
1082 0 : out:
1083 365008 : if (p == NULL || IS_EMPTY_STMT (*p))
1084 : temp = NULL_TREE;
1085 365008 : else if (temp)
1086 : {
1087 : /* The wrapper is on the RHS of an assignment that we're pushing
1088 : down. */
1089 1864 : gcc_assert (TREE_CODE (temp) == INIT_EXPR
1090 : || TREE_CODE (temp) == MODIFY_EXPR);
1091 1864 : TREE_OPERAND (temp, 1) = *p;
1092 1864 : *p = temp;
1093 : }
1094 : else
1095 : {
1096 363144 : temp = create_tmp_var (type, "retval");
1097 363144 : *p = build2 (INIT_EXPR, type, temp, *p);
1098 : }
1099 :
1100 365008 : return temp;
1101 : }
1102 :
1103 : return NULL_TREE;
1104 : }
1105 :
1106 : /* Prepare calls to builtins to SAVE and RESTORE the stack as well as
1107 : a temporary through which they communicate. */
1108 :
1109 : static void
1110 7870 : build_stack_save_restore (gcall **save, gcall **restore)
1111 : {
1112 7870 : tree tmp_var;
1113 :
1114 15740 : *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
1115 7870 : tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
1116 7870 : gimple_call_set_lhs (*save, tmp_var);
1117 :
1118 7870 : *restore
1119 7870 : = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1120 : 1, tmp_var);
1121 7870 : }
1122 :
1123 : /* Generate IFN_ASAN_MARK call that poisons shadow memory of the DECL
1124 : variable. */
1125 :
1126 : static tree
1127 478 : build_asan_poison_call_expr (tree decl)
1128 : {
1129 : /* Do not poison variables that have size equal to zero. */
1130 478 : tree unit_size = DECL_SIZE_UNIT (decl);
1131 478 : if (zerop (unit_size))
1132 : return NULL_TREE;
1133 :
1134 478 : tree base = build_fold_addr_expr (decl);
1135 :
1136 478 : return build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_ASAN_MARK,
1137 : void_type_node, 3,
1138 : build_int_cst (integer_type_node,
1139 : ASAN_MARK_POISON),
1140 : base, unit_size);
1141 : }
1142 :
1143 : /* Generate IFN_ASAN_MARK call that would poison or unpoison, depending
1144 : on POISON flag, shadow memory of a DECL variable. The call will be
1145 : put on location identified by IT iterator, where BEFORE flag drives
1146 : position where the stmt will be put. */
1147 :
1148 : static void
1149 5059 : asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
1150 : bool before)
1151 : {
1152 5059 : tree unit_size = DECL_SIZE_UNIT (decl);
1153 5059 : tree base = build_fold_addr_expr (decl);
1154 :
1155 : /* Do not poison variables that have size equal to zero. */
1156 5059 : if (zerop (unit_size))
1157 5059 : return;
1158 :
1159 : /* It's necessary to have all stack variables aligned to ASAN granularity
1160 : bytes. */
1161 5045 : gcc_assert (!hwassist_sanitize_p () || hwassist_sanitize_stack_p ());
1162 5045 : unsigned shadow_granularity
1163 5045 : = (hwassist_sanitize_p ()
1164 5045 : ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY);
1165 5045 : if (DECL_ALIGN_UNIT (decl) <= shadow_granularity)
1166 4843 : SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity);
1167 :
1168 5045 : HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON;
1169 :
1170 5045 : gimple *g
1171 5045 : = gimple_build_call_internal (IFN_ASAN_MARK, 3,
1172 5045 : build_int_cst (integer_type_node, flags),
1173 : base, unit_size);
1174 :
1175 5045 : if (before)
1176 2642 : gsi_insert_before (it, g, GSI_NEW_STMT);
1177 : else
1178 2403 : gsi_insert_after (it, g, GSI_NEW_STMT);
1179 : }
1180 :
1181 : /* Generate IFN_ASAN_MARK internal call that depending on POISON flag
1182 : either poisons or unpoisons a DECL. Created statement is appended
1183 : to SEQ_P gimple sequence. */
1184 :
1185 : static void
1186 4581 : asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
1187 : {
1188 4581 : gimple_stmt_iterator it = gsi_last (*seq_p);
1189 4581 : bool before = false;
1190 :
1191 4581 : if (gsi_end_p (it))
1192 2427 : before = true;
1193 :
1194 4581 : asan_poison_variable (decl, poison, &it, before);
1195 4581 : }
1196 :
1197 : /* Sort pair of VAR_DECLs A and B by DECL_UID. */
1198 :
1199 : static int
1200 135 : sort_by_decl_uid (const void *a, const void *b)
1201 : {
1202 135 : const tree *t1 = (const tree *)a;
1203 135 : const tree *t2 = (const tree *)b;
1204 :
1205 135 : int uid1 = DECL_UID (*t1);
1206 135 : int uid2 = DECL_UID (*t2);
1207 :
1208 135 : if (uid1 < uid2)
1209 : return -1;
1210 50 : else if (uid1 > uid2)
1211 : return 1;
1212 : else
1213 0 : return 0;
1214 : }
1215 :
1216 : /* Generate IFN_ASAN_MARK internal call for all VARIABLES
1217 : depending on POISON flag. Created statement is appended
1218 : to SEQ_P gimple sequence. */
1219 :
1220 : static void
1221 1034108 : asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p)
1222 : {
1223 1034108 : unsigned c = variables->elements ();
1224 1034108 : if (c == 0)
1225 1033834 : return;
1226 :
1227 274 : auto_vec<tree> sorted_variables (c);
1228 :
1229 274 : for (hash_set<tree>::iterator it = variables->begin ();
1230 864 : it != variables->end (); ++it)
1231 295 : sorted_variables.safe_push (*it);
1232 :
1233 274 : sorted_variables.qsort (sort_by_decl_uid);
1234 :
1235 : unsigned i;
1236 : tree var;
1237 843 : FOR_EACH_VEC_ELT (sorted_variables, i, var)
1238 : {
1239 295 : asan_poison_variable (var, poison, seq_p);
1240 :
1241 : /* Add use_after_scope_memory attribute for the variable in order
1242 : to prevent re-written into SSA. */
1243 295 : if (!lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
1244 295 : DECL_ATTRIBUTES (var)))
1245 97 : DECL_ATTRIBUTES (var)
1246 194 : = tree_cons (get_identifier (ASAN_USE_AFTER_SCOPE_ATTRIBUTE),
1247 : integer_one_node,
1248 97 : DECL_ATTRIBUTES (var));
1249 : }
1250 274 : }
1251 :
1252 : /* Gimplify a BIND_EXPR. Just voidify and recurse. */
1253 :
1254 : static enum gimplify_status
1255 5929834 : gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
1256 : {
1257 5929834 : tree bind_expr = *expr_p;
1258 5929834 : bool old_keep_stack = gimplify_ctxp->keep_stack;
1259 5929834 : bool old_save_stack = gimplify_ctxp->save_stack;
1260 5929834 : tree t;
1261 5929834 : gbind *bind_stmt;
1262 5929834 : gimple_seq body, cleanup;
1263 5929834 : gcall *stack_save;
1264 5929834 : location_t start_locus = 0, end_locus = 0;
1265 5929834 : tree ret_clauses = NULL;
1266 :
1267 5929834 : tree temp = voidify_wrapper_expr (bind_expr, NULL);
1268 :
1269 : /* Mark variables seen in this bind expr. */
1270 12713149 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1271 : {
1272 6783315 : if (VAR_P (t))
1273 : {
1274 6145573 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1275 6145573 : tree attr;
1276 :
1277 6145573 : if (flag_openmp
1278 256446 : && !is_global_var (t)
1279 247722 : && !TREE_STATIC (t)
1280 247722 : && DECL_CONTEXT (t) == current_function_decl
1281 247722 : && TREE_USED (t)
1282 6391688 : && (attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1283 : != NULL_TREE)
1284 : {
1285 76 : gcc_assert (!DECL_HAS_VALUE_EXPR_P (t));
1286 76 : tree alloc = TREE_PURPOSE (TREE_VALUE (attr));
1287 76 : tree align = TREE_VALUE (TREE_VALUE (attr));
1288 : /* Allocate directives that appear in a target region must specify
1289 : an allocator clause unless a requires directive with the
1290 : dynamic_allocators clause is present in the same compilation
1291 : unit. */
1292 76 : bool missing_dyn_alloc = false;
1293 76 : if (alloc == NULL_TREE
1294 48 : && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS)
1295 : == 0))
1296 : {
1297 : /* This comes too early for omp_discover_declare_target...,
1298 : but should at least catch the most common cases. */
1299 42 : missing_dyn_alloc
1300 42 : = cgraph_node::get (current_function_decl)->offloadable;
1301 42 : for (struct gimplify_omp_ctx *ctx2 = ctx;
1302 48 : ctx2 && !missing_dyn_alloc; ctx2 = ctx2->outer_context)
1303 6 : if (ctx2->code == OMP_TARGET)
1304 2 : missing_dyn_alloc = true;
1305 : }
1306 42 : if (missing_dyn_alloc)
1307 4 : error_at (DECL_SOURCE_LOCATION (t),
1308 : "%<allocate%> directive for %qD inside a target "
1309 : "region must specify an %<allocator%> clause", t);
1310 : /* Skip for omp_default_mem_alloc (= 1),
1311 : unless align is present. For C/C++, there should be always a
1312 : statement list following if TREE_USED, except for, e.g., using
1313 : this decl in a static_assert; in that case, only a single
1314 : DECL_EXPR remains, which can be skipped here. */
1315 72 : else if (!errorcount
1316 57 : && (align != NULL_TREE
1317 57 : || alloc == NULL_TREE
1318 12 : || !integer_onep (alloc))
1319 127 : && (lang_GNU_Fortran ()
1320 27 : || (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1321 : != DECL_EXPR)))
1322 : {
1323 : /* Fortran might already use a pointer type internally;
1324 : use that pointer except for type(C_ptr) and type(C_funptr);
1325 : note that normal proc pointers are rejected. */
1326 55 : tree type = TREE_TYPE (t);
1327 55 : tree tmp, v;
1328 55 : if (lang_GNU_Fortran ()
1329 28 : && POINTER_TYPE_P (type)
1330 8 : && TREE_TYPE (type) != void_type_node
1331 61 : && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
1332 : {
1333 6 : type = TREE_TYPE (type);
1334 6 : v = t;
1335 : }
1336 : else
1337 : {
1338 49 : tmp = build_pointer_type (type);
1339 49 : v = create_tmp_var (tmp, get_name (t));
1340 49 : DECL_IGNORED_P (v) = 0;
1341 49 : DECL_ATTRIBUTES (v)
1342 49 : = tree_cons (get_identifier ("omp allocate var"),
1343 : build_tree_list (NULL_TREE, t),
1344 : remove_attribute ("omp allocate",
1345 49 : DECL_ATTRIBUTES (t)));
1346 49 : tmp = build_fold_indirect_ref (v);
1347 49 : TREE_THIS_NOTRAP (tmp) = 1;
1348 49 : SET_DECL_VALUE_EXPR (t, tmp);
1349 49 : DECL_HAS_VALUE_EXPR_P (t) = 1;
1350 : }
1351 55 : tree sz = TYPE_SIZE_UNIT (type);
1352 : /* The size to use in Fortran might not match TYPE_SIZE_UNIT;
1353 : hence, for some decls, a size variable is saved in the
1354 : attributes; use it, if available. */
1355 55 : if (TREE_CHAIN (TREE_VALUE (attr))
1356 28 : && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))
1357 61 : && TREE_PURPOSE (
1358 : TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))))
1359 : {
1360 6 : sz = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1361 6 : sz = TREE_PURPOSE (sz);
1362 : }
1363 55 : if (alloc == NULL_TREE)
1364 36 : alloc = build_zero_cst (ptr_type_node);
1365 55 : if (align == NULL_TREE)
1366 44 : align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (t));
1367 : else
1368 11 : align = build_int_cst (size_type_node,
1369 11 : MAX (tree_to_uhwi (align),
1370 : DECL_ALIGN_UNIT (t)));
1371 55 : location_t loc = DECL_SOURCE_LOCATION (t);
1372 55 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
1373 55 : tmp = build_call_expr_loc (loc, tmp, 3, align, sz, alloc);
1374 55 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1375 55 : fold_convert (TREE_TYPE (v), tmp));
1376 55 : gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE);
1377 : /* Ensure that either TREE_CHAIN (TREE_VALUE (attr) is set
1378 : and GOMP_FREE added here or that DECL_HAS_VALUE_EXPR_P (t)
1379 : is set, using in a condition much further below. */
1380 61 : gcc_assert (DECL_HAS_VALUE_EXPR_P (t)
1381 : || TREE_CHAIN (TREE_VALUE (attr)));
1382 55 : if (TREE_CHAIN (TREE_VALUE (attr)))
1383 : {
1384 : /* Fortran is special as it does not have properly nest
1385 : declarations in blocks. And as there is no
1386 : initializer, there is also no expression to look for.
1387 : Hence, the FE makes the statement list of the
1388 : try-finally block available. We can put the GOMP_alloc
1389 : at the top, unless an allocator or size expression
1390 : requires to put it afterward; note that the size is
1391 : always later in generated code; for strings, no
1392 : size expr but still an expr might be available.
1393 : As LTO does not handle a statement list, 'sl' has
1394 : to be removed; done so by removing the attribute. */
1395 28 : DECL_ATTRIBUTES (t)
1396 28 : = remove_attribute ("omp allocate",
1397 28 : DECL_ATTRIBUTES (t));
1398 28 : tree sl = TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)));
1399 28 : tree_stmt_iterator e = tsi_start (sl);
1400 28 : tree needle = NULL_TREE;
1401 28 : if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1402 : {
1403 6 : needle = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1404 6 : needle = (TREE_VALUE (needle) ? TREE_VALUE (needle)
1405 : : sz);
1406 : }
1407 22 : else if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1408 : needle = sz;
1409 22 : else if (DECL_P (alloc) && DECL_ARTIFICIAL (alloc))
1410 : needle = alloc;
1411 :
1412 10 : if (needle != NULL_TREE)
1413 : {
1414 49 : while (!tsi_end_p (e))
1415 : {
1416 49 : if (*e == needle
1417 49 : || (TREE_CODE (*e) == MODIFY_EXPR
1418 49 : && TREE_OPERAND (*e, 0) == needle))
1419 : break;
1420 39 : ++e;
1421 : }
1422 10 : gcc_assert (!tsi_end_p (e));
1423 : }
1424 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1425 :
1426 : /* As the cleanup is in BIND_EXPR_BODY, GOMP_free is added
1427 : here; for C/C++ it will be added in the 'cleanup'
1428 : section after gimplification. But Fortran already has
1429 : a try-finally block. */
1430 28 : sl = TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)));
1431 28 : e = tsi_last (sl);
1432 28 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1433 28 : tmp = build_call_expr_loc (EXPR_LOCATION (*e), tmp, 2, v,
1434 : build_zero_cst (ptr_type_node));
1435 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1436 28 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1437 28 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1438 28 : fold_convert (TREE_TYPE (v), tmp));
1439 28 : ++e;
1440 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1441 : }
1442 : else
1443 : {
1444 27 : gcc_assert (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1445 : == STATEMENT_LIST);
1446 27 : tree_stmt_iterator e;
1447 27 : e = tsi_start (BIND_EXPR_BODY (bind_expr));
1448 117 : while (!tsi_end_p (e))
1449 : {
1450 90 : if ((TREE_CODE (*e) == DECL_EXPR
1451 60 : && TREE_OPERAND (*e, 0) == t)
1452 123 : || (TREE_CODE (*e) == CLEANUP_POINT_EXPR
1453 0 : && (TREE_CODE (TREE_OPERAND (*e, 0))
1454 : == DECL_EXPR)
1455 0 : && (TREE_OPERAND (TREE_OPERAND (*e, 0), 0)
1456 : == t)))
1457 : break;
1458 63 : ++e;
1459 : }
1460 27 : gcc_assert (!tsi_end_p (e));
1461 27 : tsi_link_before (&e, tmp, TSI_SAME_STMT);
1462 : }
1463 : }
1464 : }
1465 :
1466 : /* Mark variable as local. */
1467 6145573 : if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t))
1468 : {
1469 99991 : if (! DECL_SEEN_IN_BIND_EXPR_P (t)
1470 99991 : || splay_tree_lookup (ctx->variables,
1471 : (splay_tree_key) t) == NULL)
1472 : {
1473 99991 : int flag = GOVD_LOCAL;
1474 99991 : if (ctx->region_type == ORT_SIMD
1475 4374 : && TREE_ADDRESSABLE (t)
1476 81 : && !TREE_STATIC (t))
1477 : {
1478 69 : if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST)
1479 2 : ctx->add_safelen1 = true;
1480 : else
1481 : flag = GOVD_PRIVATE;
1482 : }
1483 99991 : omp_add_variable (ctx, t, flag | GOVD_SEEN);
1484 : }
1485 : /* Static locals inside of target construct or offloaded
1486 : routines need to be "omp declare target". */
1487 99991 : if (TREE_STATIC (t))
1488 1308 : for (; ctx; ctx = ctx->outer_context)
1489 1153 : if ((ctx->region_type & ORT_TARGET) != 0)
1490 : {
1491 940 : if (!lookup_attribute ("omp declare target",
1492 940 : DECL_ATTRIBUTES (t)))
1493 : {
1494 928 : tree id = get_identifier ("omp declare target");
1495 928 : DECL_ATTRIBUTES (t)
1496 928 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
1497 928 : varpool_node *node = varpool_node::get (t);
1498 928 : if (node)
1499 : {
1500 33 : node->offloadable = 1;
1501 33 : if (ENABLE_OFFLOADING && !DECL_EXTERNAL (t))
1502 : {
1503 : g->have_offload = true;
1504 : if (!in_lto_p)
1505 : vec_safe_push (offload_vars, t);
1506 : }
1507 : }
1508 : }
1509 : break;
1510 : }
1511 : }
1512 :
1513 6145573 : DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
1514 :
1515 6145573 : if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
1516 1088 : cfun->has_local_explicit_reg_vars = true;
1517 : }
1518 : }
1519 :
1520 11859668 : bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
1521 5929834 : BIND_EXPR_BLOCK (bind_expr));
1522 5929834 : gimple_push_bind_expr (bind_stmt);
1523 :
1524 5929834 : gimplify_ctxp->keep_stack = false;
1525 5929834 : gimplify_ctxp->save_stack = false;
1526 :
1527 : /* Gimplify the body into the GIMPLE_BIND tuple's body. */
1528 5929834 : body = NULL;
1529 5929834 : gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
1530 5929834 : gimple_bind_set_body (bind_stmt, body);
1531 :
1532 : /* Source location wise, the cleanup code (stack_restore and clobbers)
1533 : belongs to the end of the block, so propagate what we have. The
1534 : stack_save operation belongs to the beginning of block, which we can
1535 : infer from the bind_expr directly if the block has no explicit
1536 : assignment. */
1537 5929834 : if (BIND_EXPR_BLOCK (bind_expr))
1538 : {
1539 5798672 : end_locus = BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1540 5798672 : start_locus = BLOCK_SOURCE_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1541 : }
1542 5798672 : if (start_locus == 0)
1543 5929834 : start_locus = EXPR_LOCATION (bind_expr);
1544 :
1545 5929834 : cleanup = NULL;
1546 5929834 : stack_save = NULL;
1547 :
1548 : /* Add clobbers for all variables that go out of scope. */
1549 12713149 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1550 : {
1551 6783315 : if (VAR_P (t)
1552 6145573 : && !is_global_var (t)
1553 12711512 : && DECL_CONTEXT (t) == current_function_decl)
1554 : {
1555 5928197 : if (flag_openmp
1556 247707 : && DECL_HAS_VALUE_EXPR_P (t)
1557 1087 : && TREE_USED (t)
1558 5929265 : && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1559 : {
1560 : /* For Fortran, TREE_CHAIN (TREE_VALUE (attr)) is set, which
1561 : causes that the GOMP_free call is already added above;
1562 : and "omp allocate" is removed from DECL_ATTRIBUTES. */
1563 27 : tree v = TREE_OPERAND (DECL_VALUE_EXPR (t), 0);
1564 27 : tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1565 27 : tmp = build_call_expr_loc (end_locus, tmp, 2, v,
1566 : build_zero_cst (ptr_type_node));
1567 27 : gimplify_and_add (tmp, &cleanup);
1568 27 : gimple *clobber_stmt;
1569 27 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1570 27 : clobber_stmt = gimple_build_assign (v, tmp);
1571 27 : gimple_set_location (clobber_stmt, end_locus);
1572 27 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1573 : }
1574 5928197 : if (!DECL_HARD_REGISTER (t)
1575 5927109 : && !TREE_THIS_VOLATILE (t)
1576 5888214 : && !DECL_HAS_VALUE_EXPR_P (t)
1577 : /* Only care for variables that have to be in memory. Others
1578 : will be rewritten into SSA names, hence moved to the
1579 : top-level. */
1580 5785193 : && !is_gimple_reg (t)
1581 7166162 : && flag_stack_reuse != SR_NONE)
1582 : {
1583 1234713 : tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_STORAGE_END);
1584 1234713 : gimple *clobber_stmt;
1585 1234713 : clobber_stmt = gimple_build_assign (t, clobber);
1586 1234713 : gimple_set_location (clobber_stmt, end_locus);
1587 1234713 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1588 : }
1589 :
1590 5928197 : if (flag_openacc && oacc_declare_returns != NULL)
1591 : {
1592 207 : tree key = t;
1593 207 : if (DECL_HAS_VALUE_EXPR_P (key))
1594 : {
1595 8 : key = DECL_VALUE_EXPR (key);
1596 8 : if (INDIRECT_REF_P (key))
1597 8 : key = TREE_OPERAND (key, 0);
1598 : }
1599 207 : tree *c = oacc_declare_returns->get (key);
1600 207 : if (c != NULL)
1601 : {
1602 116 : if (ret_clauses)
1603 64 : OMP_CLAUSE_CHAIN (*c) = ret_clauses;
1604 :
1605 116 : ret_clauses = unshare_expr (*c);
1606 :
1607 116 : oacc_declare_returns->remove (key);
1608 :
1609 116 : if (oacc_declare_returns->is_empty ())
1610 : {
1611 40 : delete oacc_declare_returns;
1612 40 : oacc_declare_returns = NULL;
1613 : }
1614 : }
1615 : }
1616 : }
1617 :
1618 6783315 : if (asan_poisoned_variables != NULL
1619 6783315 : && asan_poisoned_variables->contains (t))
1620 : {
1621 2143 : asan_poisoned_variables->remove (t);
1622 2143 : asan_poison_variable (t, true, &cleanup);
1623 : }
1624 :
1625 6783315 : if (gimplify_ctxp->live_switch_vars != NULL
1626 6783315 : && gimplify_ctxp->live_switch_vars->contains (t))
1627 55 : gimplify_ctxp->live_switch_vars->remove (t);
1628 : }
1629 :
1630 : /* If the code both contains VLAs and calls alloca, then we cannot reclaim
1631 : the stack space allocated to the VLAs. */
1632 5929834 : if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack)
1633 : {
1634 7870 : gcall *stack_restore;
1635 :
1636 : /* Save stack on entry and restore it on exit. Add a try_finally
1637 : block to achieve this. */
1638 7870 : build_stack_save_restore (&stack_save, &stack_restore);
1639 :
1640 7870 : gimple_set_location (stack_save, start_locus);
1641 7870 : gimple_set_location (stack_restore, end_locus);
1642 :
1643 7870 : gimplify_seq_add_stmt (&cleanup, stack_restore);
1644 : }
1645 :
1646 5929834 : if (ret_clauses)
1647 : {
1648 52 : gomp_target *stmt;
1649 52 : gimple_stmt_iterator si = gsi_start (cleanup);
1650 :
1651 52 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
1652 : ret_clauses);
1653 52 : gsi_insert_seq_before_without_update (&si, stmt, GSI_NEW_STMT);
1654 : }
1655 :
1656 5929834 : if (cleanup)
1657 : {
1658 764145 : gtry *gs;
1659 764145 : gimple_seq new_body;
1660 :
1661 764145 : new_body = NULL;
1662 764145 : gs = gimple_build_try (gimple_bind_body (bind_stmt), cleanup,
1663 : GIMPLE_TRY_FINALLY);
1664 :
1665 764145 : if (stack_save)
1666 7870 : gimplify_seq_add_stmt (&new_body, stack_save);
1667 764145 : gimplify_seq_add_stmt (&new_body, gs);
1668 764145 : gimple_bind_set_body (bind_stmt, new_body);
1669 : }
1670 :
1671 : /* keep_stack propagates all the way up to the outermost BIND_EXPR. */
1672 5929834 : if (!gimplify_ctxp->keep_stack)
1673 5914732 : gimplify_ctxp->keep_stack = old_keep_stack;
1674 5929834 : gimplify_ctxp->save_stack = old_save_stack;
1675 :
1676 5929834 : gimple_pop_bind_expr ();
1677 :
1678 5929834 : gimplify_seq_add_stmt (pre_p, bind_stmt);
1679 :
1680 5929834 : if (temp)
1681 : {
1682 1709 : *expr_p = temp;
1683 1709 : return GS_OK;
1684 : }
1685 :
1686 5928125 : *expr_p = NULL_TREE;
1687 5928125 : return GS_ALL_DONE;
1688 : }
1689 :
1690 : /* Maybe add early return predict statement to PRE_P sequence. */
1691 :
1692 : static void
1693 2211440 : maybe_add_early_return_predict_stmt (gimple_seq *pre_p)
1694 : {
1695 : /* If we are not in a conditional context, add PREDICT statement. */
1696 2211440 : if (gimple_conditional_context ())
1697 : {
1698 442471 : gimple *predict = gimple_build_predict (PRED_TREE_EARLY_RETURN,
1699 : NOT_TAKEN);
1700 442471 : gimplify_seq_add_stmt (pre_p, predict);
1701 : }
1702 2211440 : }
1703 :
1704 : /* Gimplify a RETURN_EXPR. If the expression to be returned is not a
1705 : GIMPLE value, it is assigned to a new temporary and the statement is
1706 : re-written to return the temporary.
1707 :
1708 : PRE_P points to the sequence where side effects that must happen before
1709 : STMT should be stored. */
1710 :
1711 : static enum gimplify_status
1712 2211446 : gimplify_return_expr (tree stmt, gimple_seq *pre_p)
1713 : {
1714 2211446 : greturn *ret;
1715 2211446 : tree ret_expr = TREE_OPERAND (stmt, 0);
1716 2211446 : tree result_decl, result;
1717 :
1718 2211446 : if (ret_expr == error_mark_node)
1719 : return GS_ERROR;
1720 :
1721 2211440 : if (!ret_expr
1722 2124671 : || TREE_CODE (ret_expr) == RESULT_DECL)
1723 : {
1724 100454 : maybe_add_early_return_predict_stmt (pre_p);
1725 100454 : greturn *ret = gimple_build_return (ret_expr);
1726 100454 : copy_warning (ret, stmt);
1727 100454 : gimplify_seq_add_stmt (pre_p, ret);
1728 100454 : return GS_ALL_DONE;
1729 : }
1730 :
1731 2110986 : if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
1732 : result_decl = NULL_TREE;
1733 2110661 : else if (TREE_CODE (ret_expr) == COMPOUND_EXPR)
1734 : {
1735 : /* Used in C++ for handling EH cleanup of the return value if a local
1736 : cleanup throws. Assume the front-end knows what it's doing. */
1737 4998 : result_decl = DECL_RESULT (current_function_decl);
1738 : /* But crash if we end up trying to modify ret_expr below. */
1739 4998 : ret_expr = NULL_TREE;
1740 : }
1741 : else
1742 : {
1743 2105663 : result_decl = TREE_OPERAND (ret_expr, 0);
1744 :
1745 : /* See through a return by reference. */
1746 2105663 : if (INDIRECT_REF_P (result_decl))
1747 42648 : result_decl = TREE_OPERAND (result_decl, 0);
1748 :
1749 2105663 : gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
1750 : || TREE_CODE (ret_expr) == INIT_EXPR)
1751 : && TREE_CODE (result_decl) == RESULT_DECL);
1752 : }
1753 :
1754 : /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
1755 : Recall that aggregate_value_p is FALSE for any aggregate type that is
1756 : returned in registers. If we're returning values in registers, then
1757 : we don't want to extend the lifetime of the RESULT_DECL, particularly
1758 : across another call. In addition, for those aggregates for which
1759 : hard_function_value generates a PARALLEL, we'll die during normal
1760 : expansion of structure assignments; there's special code in expand_return
1761 : to handle this case that does not exist in expand_expr. */
1762 4998 : if (!result_decl)
1763 : result = NULL_TREE;
1764 2110661 : else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
1765 : {
1766 178780 : if (!poly_int_tree_p (DECL_SIZE (result_decl)))
1767 : {
1768 48 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
1769 0 : gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
1770 : /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
1771 : should be effectively allocated by the caller, i.e. all calls to
1772 : this function must be subject to the Return Slot Optimization. */
1773 48 : gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
1774 48 : gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
1775 : }
1776 : result = result_decl;
1777 : }
1778 1931881 : else if (gimplify_ctxp->return_temp)
1779 : result = gimplify_ctxp->return_temp;
1780 : else
1781 : {
1782 1444239 : result = create_tmp_reg (TREE_TYPE (result_decl));
1783 :
1784 : /* ??? With complex control flow (usually involving abnormal edges),
1785 : we can wind up warning about an uninitialized value for this. Due
1786 : to how this variable is constructed and initialized, this is never
1787 : true. Give up and never warn. */
1788 1444239 : suppress_warning (result, OPT_Wuninitialized);
1789 :
1790 1444239 : gimplify_ctxp->return_temp = result;
1791 : }
1792 :
1793 : /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
1794 : Then gimplify the whole thing. */
1795 2110986 : if (result != result_decl)
1796 1931881 : TREE_OPERAND (ret_expr, 0) = result;
1797 :
1798 2110986 : gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
1799 :
1800 2110986 : maybe_add_early_return_predict_stmt (pre_p);
1801 2110986 : ret = gimple_build_return (result);
1802 2110986 : copy_warning (ret, stmt);
1803 2110986 : gimplify_seq_add_stmt (pre_p, ret);
1804 :
1805 2110986 : return GS_ALL_DONE;
1806 : }
1807 :
1808 : /* Gimplify a variable-length array DECL. */
1809 :
1810 : static void
1811 8970 : gimplify_vla_decl (tree decl, gimple_seq *seq_p)
1812 : {
1813 : /* This is a variable-sized decl. Simplify its size and mark it
1814 : for deferred expansion. */
1815 8970 : tree t, addr, ptr_type;
1816 :
1817 8970 : gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
1818 8970 : gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
1819 :
1820 : /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */
1821 8970 : if (DECL_HAS_VALUE_EXPR_P (decl))
1822 : return;
1823 :
1824 : /* All occurrences of this decl in final gimplified code will be
1825 : replaced by indirection. Setting DECL_VALUE_EXPR does two
1826 : things: First, it lets the rest of the gimplifier know what
1827 : replacement to use. Second, it lets the debug info know
1828 : where to find the value. */
1829 8965 : ptr_type = build_pointer_type (TREE_TYPE (decl));
1830 8965 : addr = create_tmp_var (ptr_type, get_name (decl));
1831 8965 : DECL_IGNORED_P (addr) = 0;
1832 8965 : t = build_fold_indirect_ref (addr);
1833 8965 : TREE_THIS_NOTRAP (t) = 1;
1834 8965 : SET_DECL_VALUE_EXPR (decl, t);
1835 8965 : DECL_HAS_VALUE_EXPR_P (decl) = 1;
1836 :
1837 8965 : t = build_alloca_call_expr (DECL_SIZE_UNIT (decl), DECL_ALIGN (decl),
1838 8965 : max_int_size_in_bytes (TREE_TYPE (decl)));
1839 : /* The call has been built for a variable-sized object. */
1840 8965 : CALL_ALLOCA_FOR_VAR_P (t) = 1;
1841 8965 : t = fold_convert (ptr_type, t);
1842 8965 : t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
1843 :
1844 8965 : gimplify_and_add (t, seq_p);
1845 :
1846 : /* Record the dynamic allocation associated with DECL if requested. */
1847 8965 : if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
1848 0 : record_dynamic_alloc (decl);
1849 : }
1850 :
1851 : /* A helper function to be called via walk_tree. Mark all labels under *TP
1852 : as being forced. To be called for DECL_INITIAL of static variables. */
1853 :
1854 : static tree
1855 856954 : force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1856 : {
1857 856954 : if (TYPE_P (*tp))
1858 0 : *walk_subtrees = 0;
1859 856954 : if (TREE_CODE (*tp) == LABEL_DECL)
1860 : {
1861 926 : FORCED_LABEL (*tp) = 1;
1862 926 : cfun->has_forced_label_in_static = 1;
1863 : }
1864 :
1865 856954 : return NULL_TREE;
1866 : }
1867 :
1868 : /* Generate an initialization to automatic variable DECL based on INIT_TYPE.
1869 : Build a call to internal const function DEFERRED_INIT:
1870 : 1st argument: SIZE of the DECL;
1871 : 2nd argument: INIT_TYPE;
1872 : 3rd argument: NAME of the DECL;
1873 :
1874 : as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL). */
1875 :
1876 : static void
1877 121265 : gimple_add_init_for_auto_var (tree decl,
1878 : enum auto_init_type init_type,
1879 : gimple_seq *seq_p)
1880 : {
1881 121265 : gcc_assert (auto_var_p (decl));
1882 121265 : gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
1883 :
1884 121265 : const location_t loc = DECL_SOURCE_LOCATION (decl);
1885 121265 : tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
1886 121265 : tree init_type_node = build_int_cst (integer_type_node, (int) init_type);
1887 121265 : tree decl_name;
1888 :
1889 121265 : if (DECL_NAME (decl))
1890 67999 : decl_name = build_string_literal (DECL_NAME (decl));
1891 : else
1892 : {
1893 53266 : char decl_name_anonymous[3 + (HOST_BITS_PER_INT + 2) / 3];
1894 53266 : sprintf (decl_name_anonymous, "D.%u", DECL_UID (decl));
1895 53266 : decl_name = build_string_literal (decl_name_anonymous);
1896 : }
1897 :
1898 121265 : tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT,
1899 121265 : TREE_TYPE (decl), 3,
1900 : decl_size, init_type_node,
1901 : decl_name);
1902 :
1903 121265 : gimplify_assign (decl, call, seq_p);
1904 121265 : }
1905 :
1906 : /* Generate padding initialization for automatic variable DECL.
1907 : C guarantees that brace-init with fewer initializers than members
1908 : aggregate will initialize the rest of the aggregate as-if it were
1909 : static initialization. In turn static initialization guarantees
1910 : that padding is initialized to zero. So, we always initialize paddings
1911 : to zeroes regardless INIT_TYPE.
1912 : To do the padding initialization, we insert a call to
1913 : __builtin_clear_padding (&decl, 0, for_auto_init = true).
1914 : Note, we add an additional dummy argument for __builtin_clear_padding,
1915 : 'for_auto_init' to distinguish whether this call is for automatic
1916 : variable initialization or not.
1917 : */
1918 : static void
1919 115 : gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
1920 : gimple_seq *seq_p)
1921 : {
1922 115 : tree addr_of_decl = NULL_TREE;
1923 115 : tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
1924 :
1925 115 : if (is_vla)
1926 : {
1927 : /* The temporary address variable for this vla should be
1928 : created in gimplify_vla_decl. */
1929 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
1930 0 : gcc_assert (INDIRECT_REF_P (DECL_VALUE_EXPR (decl)));
1931 0 : addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
1932 : }
1933 : else
1934 : {
1935 115 : mark_addressable (decl);
1936 115 : addr_of_decl = build_fold_addr_expr (decl);
1937 : }
1938 :
1939 115 : gimple *call = gimple_build_call (fn, 2, addr_of_decl,
1940 115 : build_one_cst (TREE_TYPE (addr_of_decl)));
1941 115 : gimplify_seq_add_stmt (seq_p, call);
1942 115 : }
1943 :
1944 : /* Return true if the DECL need to be automatically initialized by the
1945 : compiler. */
1946 : static bool
1947 4201169 : var_needs_auto_init_p (tree decl)
1948 : {
1949 4201169 : if (auto_var_p (decl)
1950 4105889 : && (TREE_CODE (decl) != VAR_DECL || !DECL_HARD_REGISTER (decl))
1951 4105181 : && flag_auto_var_init > AUTO_INIT_UNINITIALIZED
1952 243844 : && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
1953 243836 : && !lookup_attribute ("indeterminate", DECL_ATTRIBUTES (decl))
1954 243827 : && !OPAQUE_TYPE_P (TREE_TYPE (decl))
1955 4444996 : && !is_empty_type (TREE_TYPE (decl)))
1956 : return true;
1957 : return false;
1958 : }
1959 :
1960 : /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
1961 : and initialization explicit. */
1962 :
1963 : static enum gimplify_status
1964 6515579 : gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
1965 : {
1966 6515579 : tree stmt = *stmt_p;
1967 6515579 : tree decl = DECL_EXPR_DECL (stmt);
1968 :
1969 6515579 : *stmt_p = NULL_TREE;
1970 :
1971 6515579 : if (TREE_TYPE (decl) == error_mark_node)
1972 : return GS_ERROR;
1973 :
1974 6515501 : if ((TREE_CODE (decl) == TYPE_DECL
1975 6472365 : || VAR_P (decl))
1976 12984811 : && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
1977 : {
1978 696562 : gimplify_type_sizes (TREE_TYPE (decl), seq_p);
1979 696562 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1980 21495 : gimplify_type_sizes (TREE_TYPE (TREE_TYPE (decl)), seq_p);
1981 : }
1982 :
1983 : /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
1984 : in case its size expressions contain problematic nodes like CALL_EXPR. */
1985 6515501 : if (TREE_CODE (decl) == TYPE_DECL
1986 43136 : && DECL_ORIGINAL_TYPE (decl)
1987 6520822 : && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
1988 : {
1989 0 : gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
1990 0 : if (TREE_CODE (DECL_ORIGINAL_TYPE (decl)) == REFERENCE_TYPE)
1991 0 : gimplify_type_sizes (TREE_TYPE (DECL_ORIGINAL_TYPE (decl)), seq_p);
1992 : }
1993 :
1994 6515501 : if (VAR_P (decl) && !DECL_EXTERNAL (decl))
1995 : {
1996 6469310 : tree init = DECL_INITIAL (decl);
1997 6469310 : bool is_vla = false;
1998 : /* Check whether a decl has FE created VALUE_EXPR here BEFORE
1999 : gimplify_vla_decl creates VALUE_EXPR for a vla decl.
2000 : If the decl has VALUE_EXPR that was created by FE (usually
2001 : C++FE), it's a proxy variable, and FE already initialized
2002 : the VALUE_EXPR of it, we should not initialize it anymore. */
2003 6469310 : bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
2004 :
2005 6469310 : poly_uint64 size;
2006 6469310 : if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
2007 6469310 : || (!TREE_STATIC (decl)
2008 6344840 : && flag_stack_check == GENERIC_STACK_CHECK
2009 234 : && maybe_gt (size,
2010 : (unsigned HOST_WIDE_INT) STACK_CHECK_MAX_VAR_SIZE)))
2011 : {
2012 8844 : gimplify_vla_decl (decl, seq_p);
2013 8844 : is_vla = true;
2014 : }
2015 :
2016 6469310 : if (asan_poisoned_variables
2017 5159 : && !is_vla
2018 4973 : && TREE_ADDRESSABLE (decl)
2019 2438 : && !TREE_STATIC (decl)
2020 2228 : && !DECL_HAS_VALUE_EXPR_P (decl)
2021 2151 : && DECL_ALIGN (decl) <= MAX_SUPPORTED_STACK_ALIGNMENT
2022 2151 : && dbg_cnt (asan_use_after_scope)
2023 2151 : && !gimplify_omp_ctxp
2024 : /* GNAT introduces temporaries to hold return values of calls in
2025 : initializers of variables defined in other units, so the
2026 : declaration of the variable is discarded completely. We do not
2027 : want to issue poison calls for such dropped variables. */
2028 6471453 : && (DECL_SEEN_IN_BIND_EXPR_P (decl)
2029 0 : || (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)))
2030 : {
2031 2143 : asan_poisoned_variables->add (decl);
2032 2143 : asan_poison_variable (decl, false, seq_p);
2033 2143 : if (!DECL_ARTIFICIAL (decl) && gimplify_ctxp->live_switch_vars)
2034 55 : gimplify_ctxp->live_switch_vars->add (decl);
2035 : }
2036 :
2037 : /* Some front ends do not explicitly declare all anonymous
2038 : artificial variables. We compensate here by declaring the
2039 : variables, though it would be better if the front ends would
2040 : explicitly declare them. */
2041 6469310 : if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
2042 6469310 : && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
2043 16904 : gimple_add_tmp_var (decl);
2044 :
2045 6469310 : if (init && init != error_mark_node)
2046 : {
2047 3690768 : if (!TREE_STATIC (decl))
2048 : {
2049 3661118 : DECL_INITIAL (decl) = NULL_TREE;
2050 3661118 : init = build2 (INIT_EXPR, void_type_node, decl, init);
2051 3661118 : gimplify_and_add (init, seq_p);
2052 3661118 : ggc_free (init);
2053 : /* Clear TREE_READONLY if we really have an initialization. */
2054 3661118 : if (!DECL_INITIAL (decl)
2055 3661118 : && !omp_privatize_by_reference (decl))
2056 3643034 : TREE_READONLY (decl) = 0;
2057 : }
2058 : else
2059 : /* We must still examine initializers for static variables
2060 : as they may contain a label address. */
2061 29650 : walk_tree (&init, force_labels_r, NULL, NULL);
2062 : }
2063 : /* When there is no explicit initializer, if the user requested,
2064 : We should insert an artifical initializer for this automatic
2065 : variable. */
2066 2778542 : else if (var_needs_auto_init_p (decl)
2067 2778542 : && !decl_had_value_expr_p)
2068 : {
2069 73688 : gimple_add_init_for_auto_var (decl,
2070 : flag_auto_var_init,
2071 : seq_p);
2072 : /* The expanding of a call to the above .DEFERRED_INIT will apply
2073 : block initialization to the whole space covered by this variable.
2074 : As a result, all the paddings will be initialized to zeroes
2075 : for zero initialization and 0xFE byte-repeatable patterns for
2076 : pattern initialization.
2077 : In order to make the paddings as zeroes for pattern init, We
2078 : should add a call to __builtin_clear_padding to clear the
2079 : paddings to zero in compatible with CLANG.
2080 : We cannot insert this call if the variable is a gimple register
2081 : since __builtin_clear_padding will take the address of the
2082 : variable. As a result, if a long double/_Complex long double
2083 : variable will spilled into stack later, its padding is 0XFE. */
2084 73688 : if (flag_auto_var_init == AUTO_INIT_PATTERN
2085 183 : && !is_gimple_reg (decl)
2086 73785 : && clear_padding_type_may_have_padding_p (TREE_TYPE (decl)))
2087 74 : gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
2088 : }
2089 : }
2090 :
2091 : return GS_ALL_DONE;
2092 : }
2093 :
2094 : /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
2095 : and replacing the LOOP_EXPR with goto, but if the loop contains an
2096 : EXIT_EXPR, we need to append a label for it to jump to. */
2097 :
2098 : static enum gimplify_status
2099 202742 : gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
2100 : {
2101 202742 : tree saved_label = gimplify_ctxp->exit_label;
2102 202742 : tree start_label = create_artificial_label (UNKNOWN_LOCATION);
2103 :
2104 202742 : gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
2105 :
2106 202742 : gimplify_ctxp->exit_label = NULL_TREE;
2107 :
2108 202742 : gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
2109 :
2110 202742 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
2111 :
2112 202742 : if (gimplify_ctxp->exit_label)
2113 6440 : gimplify_seq_add_stmt (pre_p,
2114 3220 : gimple_build_label (gimplify_ctxp->exit_label));
2115 :
2116 202742 : gimplify_ctxp->exit_label = saved_label;
2117 :
2118 202742 : *expr_p = NULL;
2119 202742 : return GS_ALL_DONE;
2120 : }
2121 :
2122 : /* Gimplify a statement list onto a sequence. These may be created either
2123 : by an enlightened front-end, or by shortcut_cond_expr. */
2124 :
2125 : static enum gimplify_status
2126 8477107 : gimplify_statement_list (tree *expr_p, gimple_seq *pre_p)
2127 : {
2128 8477107 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
2129 :
2130 8477107 : tree_stmt_iterator i = tsi_start (*expr_p);
2131 :
2132 54685191 : while (!tsi_end_p (i))
2133 : {
2134 37730977 : gimplify_stmt (tsi_stmt_ptr (i), pre_p);
2135 37730977 : tsi_delink (&i);
2136 : }
2137 :
2138 8477107 : if (temp)
2139 : {
2140 15232 : *expr_p = temp;
2141 15232 : return GS_OK;
2142 : }
2143 :
2144 : return GS_ALL_DONE;
2145 : }
2146 :
2147 :
2148 : /* Emit warning for the unreachable statement STMT if needed.
2149 : Return the gimple itself when the warning is emitted, otherwise
2150 : return NULL. */
2151 : static gimple *
2152 181 : emit_warn_switch_unreachable (gimple *stmt)
2153 : {
2154 181 : if (gimple_code (stmt) == GIMPLE_GOTO
2155 50 : && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL
2156 231 : && DECL_ARTIFICIAL (gimple_goto_dest (stmt)))
2157 : /* Don't warn for compiler-generated gotos. These occur
2158 : in Duff's devices, for example. */
2159 : return NULL;
2160 : else
2161 131 : warning_at (gimple_location (stmt), OPT_Wswitch_unreachable,
2162 : "statement will never be executed");
2163 131 : return stmt;
2164 : }
2165 :
2166 : /* Callback for walk_gimple_seq. */
2167 :
2168 : static tree
2169 48519 : warn_switch_unreachable_and_auto_init_r (gimple_stmt_iterator *gsi_p,
2170 : bool *handled_ops_p,
2171 : struct walk_stmt_info *wi)
2172 : {
2173 48519 : gimple *stmt = gsi_stmt (*gsi_p);
2174 48519 : bool unreachable_issued = wi->info != NULL;
2175 :
2176 48519 : *handled_ops_p = true;
2177 48519 : switch (gimple_code (stmt))
2178 : {
2179 155 : case GIMPLE_TRY:
2180 : /* A compiler-generated cleanup or a user-written try block.
2181 : If it's empty, don't dive into it--that would result in
2182 : worse location info. */
2183 155 : if (gimple_try_eval (stmt) == NULL)
2184 : {
2185 3 : if (warn_switch_unreachable && !unreachable_issued)
2186 3 : wi->info = emit_warn_switch_unreachable (stmt);
2187 :
2188 : /* Stop when auto var init warning is not on. */
2189 3 : if (!warn_trivial_auto_var_init)
2190 3 : return integer_zero_node;
2191 : }
2192 : /* Fall through. */
2193 1788 : case GIMPLE_BIND:
2194 1788 : case GIMPLE_CATCH:
2195 1788 : case GIMPLE_EH_FILTER:
2196 1788 : case GIMPLE_TRANSACTION:
2197 : /* Walk the sub-statements. */
2198 1788 : *handled_ops_p = false;
2199 1788 : break;
2200 :
2201 : case GIMPLE_DEBUG:
2202 : /* Ignore these. We may generate them before declarations that
2203 : are never executed. If there's something to warn about,
2204 : there will be non-debug stmts too, and we'll catch those. */
2205 : break;
2206 :
2207 60 : case GIMPLE_ASSIGN:
2208 : /* See comment below in the GIMPLE_CALL case. */
2209 60 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2210 20 : && gimple_assign_single_p (stmt)
2211 79 : && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
2212 : {
2213 6 : gimple *g = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
2214 6 : if (gimple_call_internal_p (g, IFN_DEFERRED_INIT))
2215 : break;
2216 : }
2217 54 : goto do_default;
2218 :
2219 45390 : case GIMPLE_LABEL:
2220 : /* Stop till the first Label. */
2221 45390 : return integer_zero_node;
2222 62 : case GIMPLE_CALL:
2223 62 : if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2224 : {
2225 8 : *handled_ops_p = false;
2226 8 : break;
2227 : }
2228 : /* Don't warn for compiler-generated initializations for
2229 : -ftrivial-auto-var-init for -Wswitch-unreachable. Though
2230 : do warn for -Wtrivial-auto-var-init.
2231 : There are 3 cases:
2232 : case 1: a call to .DEFERRED_INIT;
2233 : case 2: a call to __builtin_clear_padding with the 2nd argument is
2234 : present and non-zero;
2235 : case 3: a gimple assign store right after the call to .DEFERRED_INIT
2236 : that has the LHS of .DEFERRED_INIT as the RHS as following:
2237 : _1 = .DEFERRED_INIT (4, 2, &"i1"[0]);
2238 : i1 = _1.
2239 : case 3 is handled above in the GIMPLE_ASSIGN case. */
2240 54 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2241 54 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2242 : {
2243 33 : if (warn_trivial_auto_var_init)
2244 : {
2245 : /* Get the variable name from the 3rd argument of call. */
2246 12 : tree var_name = gimple_call_arg (stmt, 2);
2247 12 : var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0);
2248 12 : const char *var_name_str = TREE_STRING_POINTER (var_name);
2249 :
2250 12 : warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init,
2251 : "%qs cannot be initialized with "
2252 : "%<-ftrivial-auto-var_init%>", var_name_str);
2253 : }
2254 : break;
2255 : }
2256 21 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2257 7 : && gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
2258 24 : && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
2259 : break;
2260 : /* Fall through. */
2261 178 : default:
2262 178 : do_default:
2263 : /* check the first "real" statement (not a decl/lexical scope/...), issue
2264 : warning if needed. */
2265 178 : if (warn_switch_unreachable && !unreachable_issued)
2266 178 : wi->info = emit_warn_switch_unreachable (stmt);
2267 : /* Stop when auto var init warning is not on. */
2268 178 : if (!warn_trivial_auto_var_init)
2269 178 : return integer_zero_node;
2270 : break;
2271 : }
2272 : return NULL_TREE;
2273 : }
2274 :
2275 :
2276 : /* Possibly warn about unreachable statements between switch's controlling
2277 : expression and the first case. Also warn about -ftrivial-auto-var-init
2278 : cannot initialize the auto variable under such situation.
2279 : SEQ is the body of a switch expression. */
2280 :
2281 : static void
2282 49454 : maybe_warn_switch_unreachable_and_auto_init (gimple_seq seq)
2283 : {
2284 60 : if ((!warn_switch_unreachable && !warn_trivial_auto_var_init)
2285 : /* This warning doesn't play well with Fortran when optimizations
2286 : are on. */
2287 49394 : || lang_GNU_Fortran ()
2288 95198 : || seq == NULL)
2289 3880 : return;
2290 :
2291 45574 : struct walk_stmt_info wi;
2292 :
2293 45574 : memset (&wi, 0, sizeof (wi));
2294 45574 : walk_gimple_seq (seq, warn_switch_unreachable_and_auto_init_r, NULL, &wi);
2295 : }
2296 :
2297 :
2298 : /* A label entry that pairs label and a location. */
2299 : struct label_entry
2300 : {
2301 : tree label;
2302 : location_t loc;
2303 : };
2304 :
2305 : /* Find LABEL in vector of label entries VEC. */
2306 :
2307 : static struct label_entry *
2308 12122 : find_label_entry (const auto_vec<struct label_entry> *vec, tree label)
2309 : {
2310 12122 : unsigned int i;
2311 12122 : struct label_entry *l;
2312 :
2313 23226 : FOR_EACH_VEC_ELT (*vec, i, l)
2314 19880 : if (l->label == label)
2315 : return l;
2316 : return NULL;
2317 : }
2318 :
2319 : /* Return true if LABEL, a LABEL_DECL, represents a case label
2320 : in a vector of labels CASES. */
2321 :
2322 : static bool
2323 16305 : case_label_p (const vec<tree> *cases, tree label)
2324 : {
2325 16305 : unsigned int i;
2326 16305 : tree l;
2327 :
2328 163670 : FOR_EACH_VEC_ELT (*cases, i, l)
2329 163344 : if (CASE_LABEL (l) == label)
2330 : return true;
2331 : return false;
2332 : }
2333 :
2334 : /* Find the last nondebug statement in a scope STMT. */
2335 :
2336 : static gimple *
2337 2265 : last_stmt_in_scope (gimple *stmt)
2338 : {
2339 4200 : if (!stmt)
2340 : return NULL;
2341 :
2342 6838 : auto last_stmt_in_seq = [] (gimple_seq s)
2343 : {
2344 2649 : gimple_seq_node n;
2345 2649 : for (n = gimple_seq_last (s);
2346 2654 : n && (is_gimple_debug (n)
2347 2641 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2348 110 : && gimple_call_internal_p (n, IFN_DEFERRED_INIT)));
2349 5 : n = n->prev)
2350 7 : if (n == s)
2351 : return (gimple *) NULL;
2352 : return (gimple *) n;
2353 : };
2354 :
2355 4189 : switch (gimple_code (stmt))
2356 : {
2357 1387 : case GIMPLE_BIND:
2358 1387 : {
2359 1387 : gbind *bind = as_a <gbind *> (stmt);
2360 1387 : stmt = last_stmt_in_seq (gimple_bind_body (bind));
2361 1387 : return last_stmt_in_scope (stmt);
2362 : }
2363 :
2364 714 : case GIMPLE_TRY:
2365 714 : {
2366 714 : gtry *try_stmt = as_a <gtry *> (stmt);
2367 714 : stmt = last_stmt_in_seq (gimple_try_eval (try_stmt));
2368 714 : gimple *last_eval = last_stmt_in_scope (stmt);
2369 714 : if (gimple_stmt_may_fallthru (last_eval)
2370 567 : && (last_eval == NULL
2371 564 : || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH))
2372 1274 : && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
2373 : {
2374 548 : stmt = last_stmt_in_seq (gimple_try_cleanup (try_stmt));
2375 548 : return last_stmt_in_scope (stmt);
2376 : }
2377 : else
2378 : return last_eval;
2379 : }
2380 :
2381 0 : case GIMPLE_DEBUG:
2382 0 : gcc_unreachable ();
2383 :
2384 : default:
2385 : return stmt;
2386 : }
2387 : }
2388 :
2389 : /* Collect labels that may fall through into LABELS and return the statement
2390 : preceding another case label, or a user-defined label. Store a location
2391 : useful to give warnings at *PREVLOC (usually the location of the returned
2392 : statement or of its surrounding scope). */
2393 :
2394 : static gimple *
2395 20880 : collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
2396 : auto_vec <struct label_entry> *labels,
2397 : location_t *prevloc)
2398 : {
2399 20880 : gimple *prev = NULL;
2400 :
2401 20880 : *prevloc = UNKNOWN_LOCATION;
2402 101009 : do
2403 : {
2404 101009 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND)
2405 : {
2406 : /* Recognize the special GIMPLE_BIND added by gimplify_switch_expr,
2407 : which starts on a GIMPLE_SWITCH and ends with a break label.
2408 : Handle that as a single statement that can fall through. */
2409 1448 : gbind *bind = as_a <gbind *> (gsi_stmt (*gsi_p));
2410 1448 : gimple *first = gimple_seq_first_stmt (gimple_bind_body (bind));
2411 1448 : gimple *last = gimple_seq_last_stmt (gimple_bind_body (bind));
2412 1442 : if (last
2413 1442 : && gimple_code (first) == GIMPLE_SWITCH
2414 1544 : && gimple_code (last) == GIMPLE_LABEL)
2415 : {
2416 102 : tree label = gimple_label_label (as_a <glabel *> (last));
2417 102 : if (SWITCH_BREAK_LABEL_P (label))
2418 : {
2419 102 : prev = bind;
2420 102 : gsi_next (gsi_p);
2421 102 : continue;
2422 : }
2423 : }
2424 : }
2425 100907 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
2426 100907 : || gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
2427 : {
2428 : /* Nested scope. Only look at the last statement of
2429 : the innermost scope. */
2430 1551 : location_t bind_loc = gimple_location (gsi_stmt (*gsi_p));
2431 1551 : gimple *last = last_stmt_in_scope (gsi_stmt (*gsi_p));
2432 1551 : if (last)
2433 : {
2434 1543 : prev = last;
2435 : /* It might be a label without a location. Use the
2436 : location of the scope then. */
2437 1543 : if (!gimple_has_location (prev))
2438 671 : *prevloc = bind_loc;
2439 : }
2440 1551 : gsi_next (gsi_p);
2441 1551 : continue;
2442 1551 : }
2443 :
2444 : /* Ifs are tricky. */
2445 99356 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
2446 : {
2447 7116 : gcond *cond_stmt = as_a <gcond *> (gsi_stmt (*gsi_p));
2448 7116 : tree false_lab = gimple_cond_false_label (cond_stmt);
2449 7116 : location_t if_loc = gimple_location (cond_stmt);
2450 :
2451 : /* If we have e.g.
2452 : if (i > 1) goto <D.2259>; else goto D;
2453 : we can't do much with the else-branch. */
2454 7116 : if (!DECL_ARTIFICIAL (false_lab))
2455 : break;
2456 :
2457 : /* Go on until the false label, then one step back. */
2458 54282 : for (; !gsi_end_p (*gsi_p); gsi_next (gsi_p))
2459 : {
2460 54282 : gimple *stmt = gsi_stmt (*gsi_p);
2461 54282 : if (gimple_code (stmt) == GIMPLE_LABEL
2462 54282 : && gimple_label_label (as_a <glabel *> (stmt)) == false_lab)
2463 : break;
2464 : }
2465 :
2466 : /* Not found? Oops. */
2467 7116 : if (gsi_end_p (*gsi_p))
2468 : break;
2469 :
2470 : /* A dead label can't fall through. */
2471 7116 : if (!UNUSED_LABEL_P (false_lab))
2472 : {
2473 7069 : struct label_entry l = { false_lab, if_loc };
2474 7069 : labels->safe_push (l);
2475 : }
2476 :
2477 : /* Go to the last statement of the then branch. */
2478 7116 : gsi_prev (gsi_p);
2479 :
2480 : /* if (i != 0) goto <D.1759>; else goto <D.1760>;
2481 : <D.1759>:
2482 : <stmt>;
2483 : goto <D.1761>;
2484 : <D.1760>:
2485 : */
2486 7116 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2487 7116 : && !gimple_has_location (gsi_stmt (*gsi_p)))
2488 : {
2489 : /* Look at the statement before, it might be
2490 : attribute fallthrough, in which case don't warn. */
2491 1566 : gsi_prev (gsi_p);
2492 1566 : bool fallthru_before_dest
2493 1566 : = gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
2494 1566 : gsi_next (gsi_p);
2495 1566 : tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
2496 1566 : if (!fallthru_before_dest)
2497 : {
2498 1509 : struct label_entry l = { goto_dest, if_loc };
2499 1509 : labels->safe_push (l);
2500 : }
2501 : }
2502 : /* This case is about
2503 : if (1 != 0) goto <D.2022>; else goto <D.2023>;
2504 : <D.2022>:
2505 : n = n + 1; // #1
2506 : <D.2023>: // #2
2507 : <D.1988>: // #3
2508 : where #2 is UNUSED_LABEL_P and we want to warn about #1 falling
2509 : through to #3. So set PREV to #1. */
2510 5550 : else if (UNUSED_LABEL_P (false_lab))
2511 47 : prev = gsi_stmt (*gsi_p);
2512 :
2513 : /* And move back. */
2514 7116 : gsi_next (gsi_p);
2515 : }
2516 :
2517 99356 : tree lab;
2518 : /* Remember the last statement. Skip labels that are of no interest
2519 : to us. */
2520 99356 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2521 : {
2522 11904 : tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (*gsi_p)));
2523 11904 : if (find_label_entry (labels, label))
2524 74714 : prev = gsi_stmt (*gsi_p);
2525 : }
2526 87452 : else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
2527 : ;
2528 87452 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2529 87452 : && gimple_call_internal_p (gsi_stmt (*gsi_p),
2530 : IFN_DEFERRED_INIT))
2531 : ;
2532 87452 : else if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_PREDICT)
2533 : ;
2534 86244 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2535 2072 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2536 316 : && (lab = gimple_goto_dest (gsi_stmt (*gsi_p)))
2537 316 : && TREE_CODE (lab) == LABEL_DECL
2538 86559 : && VACUOUS_INIT_LABEL_P (lab))
2539 : ;
2540 86244 : else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
2541 74714 : prev = gsi_stmt (*gsi_p);
2542 99356 : gsi_next (gsi_p);
2543 : }
2544 101009 : while (!gsi_end_p (*gsi_p)
2545 : /* Stop if we find a case or a user-defined label. */
2546 202018 : && (gimple_code (gsi_stmt (*gsi_p)) != GIMPLE_LABEL
2547 21613 : || !gimple_has_location (gsi_stmt (*gsi_p))));
2548 :
2549 20880 : if (prev && gimple_has_location (prev))
2550 20439 : *prevloc = gimple_location (prev);
2551 20880 : return prev;
2552 : }
2553 :
2554 : /* Return true if the switch fallthrough warning should occur. LABEL is
2555 : the label statement that we're falling through to. */
2556 :
2557 : static bool
2558 16818 : should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
2559 : {
2560 16818 : gimple_stmt_iterator gsi = *gsi_p;
2561 :
2562 : /* Don't warn if the label is marked with a "falls through" comment. */
2563 16818 : if (FALLTHROUGH_LABEL_P (label))
2564 : return false;
2565 :
2566 : /* Don't warn for non-case labels followed by a statement:
2567 : case 0:
2568 : foo ();
2569 : label:
2570 : bar ();
2571 : as these are likely intentional. */
2572 16050 : if (!case_label_p (&gimplify_ctxp->case_labels, label))
2573 : {
2574 : tree l;
2575 326 : while (!gsi_end_p (gsi)
2576 326 : && ((gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2577 255 : && (l
2578 255 : = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi))))
2579 255 : && !case_label_p (&gimplify_ctxp->case_labels, l))
2580 149 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2581 31 : && gimple_call_internal_p (gsi_stmt (gsi),
2582 : IFN_DEFERRED_INIT))))
2583 169 : gsi_next_nondebug (&gsi);
2584 157 : if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
2585 : return false;
2586 : }
2587 :
2588 : /* Don't warn for terminated branches, i.e. when the subsequent case labels
2589 : immediately breaks. */
2590 15979 : gsi = *gsi_p;
2591 :
2592 : /* Skip all immediately following labels. */
2593 35478 : while (!gsi_end_p (gsi)
2594 35478 : && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2595 16114 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT
2596 15913 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2597 714 : && gimple_call_internal_p (gsi_stmt (gsi),
2598 : IFN_DEFERRED_INIT))))
2599 19499 : gsi_next_nondebug (&gsi);
2600 :
2601 : /* { ... something; default:; } */
2602 15979 : if (gsi_end_p (gsi)
2603 : /* { ... something; default: break; } or
2604 : { ... something; default: goto L; } */
2605 15913 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
2606 : /* { ... something; default: return; } */
2607 30801 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
2608 : return false;
2609 :
2610 : return true;
2611 : }
2612 :
2613 : /* Callback for walk_gimple_seq. */
2614 :
2615 : static tree
2616 21836 : warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2617 : struct walk_stmt_info *)
2618 : {
2619 21836 : gimple *stmt = gsi_stmt (*gsi_p);
2620 :
2621 21836 : *handled_ops_p = true;
2622 21836 : switch (gimple_code (stmt))
2623 : {
2624 267 : case GIMPLE_TRY:
2625 267 : case GIMPLE_BIND:
2626 267 : case GIMPLE_CATCH:
2627 267 : case GIMPLE_EH_FILTER:
2628 267 : case GIMPLE_TRANSACTION:
2629 : /* Walk the sub-statements. */
2630 267 : *handled_ops_p = false;
2631 267 : break;
2632 :
2633 : /* Find a sequence of form:
2634 :
2635 : GIMPLE_LABEL
2636 : [...]
2637 : <may fallthru stmt>
2638 : GIMPLE_LABEL
2639 :
2640 : and possibly warn. */
2641 : case GIMPLE_LABEL:
2642 : {
2643 : /* Found a label. Skip all immediately following labels. */
2644 48935 : while (!gsi_end_p (*gsi_p)
2645 48935 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2646 27821 : gsi_next_nondebug (gsi_p);
2647 :
2648 : /* There might be no more statements. */
2649 21114 : if (gsi_end_p (*gsi_p))
2650 4289 : return integer_zero_node;
2651 :
2652 : /* Vector of labels that fall through. */
2653 20880 : auto_vec <struct label_entry> labels;
2654 20880 : location_t prevloc;
2655 20880 : gimple *prev = collect_fallthrough_labels (gsi_p, &labels, &prevloc);
2656 :
2657 : /* There might be no more statements. */
2658 20880 : if (gsi_end_p (*gsi_p))
2659 4055 : return integer_zero_node;
2660 :
2661 16825 : gimple *next = gsi_stmt (*gsi_p);
2662 16825 : tree label;
2663 : /* If what follows is a label, then we may have a fallthrough. */
2664 16825 : if (gimple_code (next) == GIMPLE_LABEL
2665 16825 : && gimple_has_location (next)
2666 16825 : && (label = gimple_label_label (as_a <glabel *> (next)))
2667 33650 : && prev != NULL)
2668 : {
2669 16818 : struct label_entry *l;
2670 16818 : bool warned_p = false;
2671 16818 : auto_diagnostic_group d;
2672 16818 : if (!should_warn_for_implicit_fallthrough (gsi_p, label))
2673 : /* Quiet. */;
2674 14795 : else if (gimple_code (prev) == GIMPLE_LABEL
2675 218 : && (label = gimple_label_label (as_a <glabel *> (prev)))
2676 15013 : && (l = find_label_entry (&labels, label)))
2677 198 : warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough_,
2678 : "this statement may fall through");
2679 14597 : else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH)
2680 : /* Try to be clever and don't warn when the statement
2681 : can't actually fall through. */
2682 14061 : && gimple_stmt_may_fallthru (prev)
2683 14898 : && prevloc != UNKNOWN_LOCATION)
2684 301 : warned_p = warning_at (prevloc,
2685 301 : OPT_Wimplicit_fallthrough_,
2686 : "this statement may fall through");
2687 499 : if (warned_p)
2688 499 : inform (gimple_location (next), "here");
2689 :
2690 : /* Mark this label as processed so as to prevent multiple
2691 : warnings in nested switches. */
2692 16818 : FALLTHROUGH_LABEL_P (label) = true;
2693 :
2694 : /* So that next warn_implicit_fallthrough_r will start looking for
2695 : a new sequence starting with this label. */
2696 16818 : gsi_prev (gsi_p);
2697 16818 : }
2698 4055 : }
2699 16825 : break;
2700 : default:
2701 : break;
2702 : }
2703 : return NULL_TREE;
2704 : }
2705 :
2706 : /* Warn when a switch case falls through. */
2707 :
2708 : static void
2709 49454 : maybe_warn_implicit_fallthrough (gimple_seq seq)
2710 : {
2711 49454 : if (!warn_implicit_fallthrough)
2712 45306 : return;
2713 :
2714 : /* This warning is meant for C/C++/ObjC/ObjC++ only. */
2715 4148 : if (!(lang_GNU_C ()
2716 1224 : || lang_GNU_CXX ()
2717 0 : || lang_GNU_OBJC ()))
2718 : return;
2719 :
2720 4148 : struct walk_stmt_info wi;
2721 4148 : memset (&wi, 0, sizeof (wi));
2722 4148 : walk_gimple_seq (seq, warn_implicit_fallthrough_r, NULL, &wi);
2723 : }
2724 :
2725 : /* Callback for walk_gimple_seq. */
2726 :
2727 : static tree
2728 3208376 : expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2729 : struct walk_stmt_info *wi)
2730 : {
2731 3208376 : gimple *stmt = gsi_stmt (*gsi_p);
2732 :
2733 3208376 : *handled_ops_p = true;
2734 3208376 : switch (gimple_code (stmt))
2735 : {
2736 146819 : case GIMPLE_TRY:
2737 146819 : case GIMPLE_BIND:
2738 146819 : case GIMPLE_CATCH:
2739 146819 : case GIMPLE_EH_FILTER:
2740 146819 : case GIMPLE_TRANSACTION:
2741 : /* Walk the sub-statements. */
2742 146819 : *handled_ops_p = false;
2743 146819 : break;
2744 246697 : case GIMPLE_CALL:
2745 246697 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2746 246697 : if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
2747 : {
2748 2539 : location_t loc = gimple_location (stmt);
2749 2539 : gsi_remove (gsi_p, true);
2750 2539 : wi->removed_stmt = true;
2751 :
2752 : /* nothrow flag is added by genericize_c_loop to mark fallthrough
2753 : statement at the end of some loop's body. Those should be
2754 : always diagnosed, either because they indeed don't precede
2755 : a case label or default label, or because the next statement
2756 : is not within the same iteration statement. */
2757 2539 : if ((stmt->subcode & GF_CALL_NOTHROW) != 0)
2758 : {
2759 12 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2760 : "a case label or default label");
2761 12 : break;
2762 : }
2763 :
2764 2527 : if (gsi_end_p (*gsi_p))
2765 : {
2766 32 : static_cast<location_t *>(wi->info)[0] = BUILTINS_LOCATION;
2767 32 : static_cast<location_t *>(wi->info)[1] = loc;
2768 32 : break;
2769 : }
2770 :
2771 2495 : bool found = false;
2772 :
2773 2495 : gimple_stmt_iterator gsi2 = *gsi_p;
2774 2495 : stmt = gsi_stmt (gsi2);
2775 2495 : tree lab;
2776 2495 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2777 910 : && gimple_code (stmt) == GIMPLE_GOTO
2778 20 : && (lab = gimple_goto_dest (stmt))
2779 20 : && TREE_CODE (lab) == LABEL_DECL
2780 2515 : && VACUOUS_INIT_LABEL_P (lab))
2781 : {
2782 : /* Handle for C++ artificial -ftrivial-auto-var-init=
2783 : sequences. Those look like:
2784 : goto lab1;
2785 : lab2:;
2786 : v1 = .DEFERRED_INIT (...);
2787 : v2 = .DEFERRED_INIT (...);
2788 : lab3:;
2789 : v3 = .DEFERRED_INIT (...);
2790 : lab1:;
2791 : In this case, a case/default label can be either in between
2792 : the GIMPLE_GOTO and the corresponding GIMPLE_LABEL, if jumps
2793 : from the switch condition to the case/default label cross
2794 : vacuous initialization of some variables, or after the
2795 : corresponding GIMPLE_LABEL, if those jumps don't cross
2796 : any such initialization but there is an adjacent named label
2797 : which crosses such initialization. So, for the purpose of
2798 : this function, just ignore the goto but until reaching the
2799 : corresponding GIMPLE_LABEL allow also .DEFERRED_INIT
2800 : calls. */
2801 5 : gsi_next (&gsi2);
2802 : }
2803 2490 : else if (gimple_code (stmt) == GIMPLE_GOTO
2804 2490 : && !gimple_has_location (stmt))
2805 : {
2806 : /* Go on until the artificial label. */
2807 57 : tree goto_dest = gimple_goto_dest (stmt);
2808 414 : for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
2809 : {
2810 357 : if (gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL
2811 357 : && gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)))
2812 : == goto_dest)
2813 : break;
2814 : }
2815 :
2816 : /* Not found? Stop. */
2817 57 : if (gsi_end_p (gsi2))
2818 : break;
2819 :
2820 : /* Look one past it. */
2821 57 : gsi_next (&gsi2);
2822 : }
2823 :
2824 : /* We're looking for a case label or default label here. */
2825 2593 : while (!gsi_end_p (gsi2))
2826 : {
2827 2593 : stmt = gsi_stmt (gsi2);
2828 2593 : if (gimple_code (stmt) == GIMPLE_LABEL)
2829 : {
2830 2550 : tree label = gimple_label_label (as_a <glabel *> (stmt));
2831 2550 : if (gimple_has_location (stmt) && DECL_ARTIFICIAL (label))
2832 : {
2833 : found = true;
2834 : break;
2835 : }
2836 : }
2837 43 : else if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2838 : ;
2839 43 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2840 43 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2841 : ;
2842 43 : else if (!is_gimple_debug (stmt))
2843 : /* Anything else is not expected. */
2844 : break;
2845 98 : gsi_next (&gsi2);
2846 : }
2847 2495 : if (!found)
2848 23 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2849 : "a case label or default label");
2850 : }
2851 : break;
2852 2814860 : default:
2853 2814860 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2854 2814860 : break;
2855 : }
2856 3208376 : return NULL_TREE;
2857 : }
2858 :
2859 : /* Expand all FALLTHROUGH () calls in SEQ. */
2860 :
2861 : static void
2862 47770 : expand_FALLTHROUGH (gimple_seq *seq_p)
2863 : {
2864 47770 : auto_urlify_attributes sentinel;
2865 :
2866 47770 : struct walk_stmt_info wi;
2867 47770 : location_t loc[2];
2868 47770 : memset (&wi, 0, sizeof (wi));
2869 47770 : loc[0] = UNKNOWN_LOCATION;
2870 47770 : loc[1] = UNKNOWN_LOCATION;
2871 47770 : wi.info = (void *) &loc[0];
2872 47770 : walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
2873 47770 : if (loc[0] != UNKNOWN_LOCATION)
2874 : /* We've found [[fallthrough]]; at the end of a switch, which the C++
2875 : standard says is ill-formed; see [dcl.attr.fallthrough]. */
2876 8 : pedwarn (loc[1], 0, "attribute %<fallthrough%> not preceding "
2877 : "a case label or default label");
2878 47770 : }
2879 :
2880 :
2881 : /* Gimplify a SWITCH_EXPR, and collect the vector of labels it can
2882 : branch to. */
2883 :
2884 : static enum gimplify_status
2885 49454 : gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
2886 : {
2887 49454 : tree switch_expr = *expr_p;
2888 49454 : gimple_seq switch_body_seq = NULL;
2889 49454 : enum gimplify_status ret;
2890 49454 : tree index_type = TREE_TYPE (switch_expr);
2891 49454 : if (index_type == NULL_TREE)
2892 11396 : index_type = TREE_TYPE (SWITCH_COND (switch_expr));
2893 :
2894 49454 : ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
2895 : fb_rvalue);
2896 49454 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
2897 : return ret;
2898 :
2899 49454 : if (SWITCH_BODY (switch_expr))
2900 : {
2901 49454 : vec<tree> labels;
2902 49454 : vec<tree> saved_labels;
2903 49454 : hash_set<tree> *saved_live_switch_vars = NULL;
2904 49454 : tree default_case = NULL_TREE;
2905 49454 : gswitch *switch_stmt;
2906 :
2907 : /* Save old labels, get new ones from body, then restore the old
2908 : labels. Save all the things from the switch body to append after. */
2909 49454 : saved_labels = gimplify_ctxp->case_labels;
2910 49454 : gimplify_ctxp->case_labels.create (8);
2911 :
2912 : /* Do not create live_switch_vars if SWITCH_BODY is not a BIND_EXPR. */
2913 49454 : saved_live_switch_vars = gimplify_ctxp->live_switch_vars;
2914 49454 : tree_code body_type = TREE_CODE (SWITCH_BODY (switch_expr));
2915 49454 : if (body_type == BIND_EXPR || body_type == STATEMENT_LIST)
2916 49172 : gimplify_ctxp->live_switch_vars = new hash_set<tree> (4);
2917 : else
2918 282 : gimplify_ctxp->live_switch_vars = NULL;
2919 :
2920 49454 : bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
2921 49454 : gimplify_ctxp->in_switch_expr = true;
2922 :
2923 49454 : gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
2924 :
2925 49454 : gimplify_ctxp->in_switch_expr = old_in_switch_expr;
2926 49454 : maybe_warn_switch_unreachable_and_auto_init (switch_body_seq);
2927 49454 : maybe_warn_implicit_fallthrough (switch_body_seq);
2928 : /* Only do this for the outermost GIMPLE_SWITCH. */
2929 49454 : if (!gimplify_ctxp->in_switch_expr)
2930 47770 : expand_FALLTHROUGH (&switch_body_seq);
2931 :
2932 49454 : labels = gimplify_ctxp->case_labels;
2933 49454 : gimplify_ctxp->case_labels = saved_labels;
2934 :
2935 49454 : if (gimplify_ctxp->live_switch_vars)
2936 : {
2937 49172 : gcc_assert (gimplify_ctxp->live_switch_vars->is_empty ());
2938 49172 : delete gimplify_ctxp->live_switch_vars;
2939 : }
2940 49454 : gimplify_ctxp->live_switch_vars = saved_live_switch_vars;
2941 :
2942 49454 : preprocess_case_label_vec_for_gimple (labels, index_type,
2943 : &default_case);
2944 :
2945 49454 : bool add_bind = false;
2946 49454 : if (!default_case)
2947 : {
2948 14776 : glabel *new_default;
2949 :
2950 14776 : default_case
2951 14776 : = build_case_label (NULL_TREE, NULL_TREE,
2952 : create_artificial_label (UNKNOWN_LOCATION));
2953 14776 : if (old_in_switch_expr)
2954 : {
2955 1081 : SWITCH_BREAK_LABEL_P (CASE_LABEL (default_case)) = 1;
2956 1081 : add_bind = true;
2957 : }
2958 14776 : new_default = gimple_build_label (CASE_LABEL (default_case));
2959 14776 : gimplify_seq_add_stmt (&switch_body_seq, new_default);
2960 : }
2961 34678 : else if (old_in_switch_expr)
2962 : {
2963 603 : gimple *last = gimple_seq_last_stmt (switch_body_seq);
2964 603 : if (last && gimple_code (last) == GIMPLE_LABEL)
2965 : {
2966 338 : tree label = gimple_label_label (as_a <glabel *> (last));
2967 338 : if (SWITCH_BREAK_LABEL_P (label))
2968 49454 : add_bind = true;
2969 : }
2970 : }
2971 :
2972 49454 : switch_stmt = gimple_build_switch (SWITCH_COND (switch_expr),
2973 : default_case, labels);
2974 49454 : gimple_set_location (switch_stmt, EXPR_LOCATION (switch_expr));
2975 : /* For the benefit of -Wimplicit-fallthrough, if switch_body_seq
2976 : ends with a GIMPLE_LABEL holding SWITCH_BREAK_LABEL_P LABEL_DECL,
2977 : wrap the GIMPLE_SWITCH up to that GIMPLE_LABEL into a GIMPLE_BIND,
2978 : so that we can easily find the start and end of the switch
2979 : statement. */
2980 49454 : if (add_bind)
2981 : {
2982 1418 : gimple_seq bind_body = NULL;
2983 1418 : gimplify_seq_add_stmt (&bind_body, switch_stmt);
2984 1418 : gimple_seq_add_seq (&bind_body, switch_body_seq);
2985 1418 : gbind *bind = gimple_build_bind (NULL_TREE, bind_body, NULL_TREE);
2986 1418 : gimple_set_location (bind, EXPR_LOCATION (switch_expr));
2987 1418 : gimplify_seq_add_stmt (pre_p, bind);
2988 : }
2989 : else
2990 : {
2991 48036 : gimplify_seq_add_stmt (pre_p, switch_stmt);
2992 48036 : gimplify_seq_add_seq (pre_p, switch_body_seq);
2993 : }
2994 49454 : labels.release ();
2995 : }
2996 : else
2997 0 : gcc_unreachable ();
2998 :
2999 49454 : return GS_ALL_DONE;
3000 : }
3001 :
3002 : /* Gimplify the LABEL_EXPR pointed to by EXPR_P. */
3003 :
3004 : static enum gimplify_status
3005 2542478 : gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
3006 : {
3007 2542478 : gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
3008 : == current_function_decl);
3009 :
3010 2542478 : tree label = LABEL_EXPR_LABEL (*expr_p);
3011 2542478 : glabel *label_stmt = gimple_build_label (label);
3012 2542478 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3013 2542478 : gimplify_seq_add_stmt (pre_p, label_stmt);
3014 :
3015 2542478 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3016 21 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3017 : NOT_TAKEN));
3018 2542457 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3019 11 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3020 : TAKEN));
3021 :
3022 2542478 : return GS_ALL_DONE;
3023 : }
3024 :
3025 : /* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
3026 :
3027 : static enum gimplify_status
3028 1033391 : gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
3029 : {
3030 1033391 : struct gimplify_ctx *ctxp;
3031 1033391 : glabel *label_stmt;
3032 :
3033 : /* Invalid programs can play Duff's Device type games with, for example,
3034 : #pragma omp parallel. At least in the C front end, we don't
3035 : detect such invalid branches until after gimplification, in the
3036 : diagnose_omp_blocks pass. */
3037 1033401 : for (ctxp = gimplify_ctxp; ; ctxp = ctxp->prev_context)
3038 1033401 : if (ctxp->case_labels.exists ())
3039 : break;
3040 :
3041 1033391 : tree label = CASE_LABEL (*expr_p);
3042 1033391 : label_stmt = gimple_build_label (label);
3043 1033391 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3044 1033391 : ctxp->case_labels.safe_push (*expr_p);
3045 1033391 : gimplify_seq_add_stmt (pre_p, label_stmt);
3046 :
3047 1033391 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3048 16 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3049 : NOT_TAKEN));
3050 1033375 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3051 20 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3052 : TAKEN));
3053 :
3054 1033391 : return GS_ALL_DONE;
3055 : }
3056 :
3057 : /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first
3058 : if necessary. */
3059 :
3060 : tree
3061 1773066 : build_and_jump (tree *label_p)
3062 : {
3063 1773066 : if (label_p == NULL)
3064 : /* If there's nowhere to jump, just fall through. */
3065 : return NULL_TREE;
3066 :
3067 1202413 : if (*label_p == NULL_TREE)
3068 : {
3069 688127 : tree label = create_artificial_label (UNKNOWN_LOCATION);
3070 688127 : *label_p = label;
3071 : }
3072 :
3073 1202413 : return build1 (GOTO_EXPR, void_type_node, *label_p);
3074 : }
3075 :
3076 : /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
3077 : This also involves building a label to jump to and communicating it to
3078 : gimplify_loop_expr through gimplify_ctxp->exit_label. */
3079 :
3080 : static enum gimplify_status
3081 3223 : gimplify_exit_expr (tree *expr_p)
3082 : {
3083 3223 : tree cond = TREE_OPERAND (*expr_p, 0);
3084 3223 : tree expr;
3085 :
3086 3223 : expr = build_and_jump (&gimplify_ctxp->exit_label);
3087 3223 : expr = build3 (COND_EXPR, void_type_node, cond, expr, NULL_TREE);
3088 3223 : *expr_p = expr;
3089 :
3090 3223 : return GS_OK;
3091 : }
3092 :
3093 : /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is
3094 : different from its canonical type, wrap the whole thing inside a
3095 : NOP_EXPR and force the type of the COMPONENT_REF to be the canonical
3096 : type.
3097 :
3098 : The canonical type of a COMPONENT_REF is the type of the field being
3099 : referenced--unless the field is a bit-field which can be read directly
3100 : in a smaller mode, in which case the canonical type is the
3101 : sign-appropriate type corresponding to that mode. */
3102 :
3103 : static void
3104 18512613 : canonicalize_component_ref (tree *expr_p)
3105 : {
3106 18512613 : tree expr = *expr_p;
3107 18512613 : tree type;
3108 :
3109 18512613 : gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
3110 :
3111 18512613 : if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
3112 7514861 : type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
3113 : else
3114 10997752 : type = TREE_TYPE (TREE_OPERAND (expr, 1));
3115 :
3116 : /* One could argue that all the stuff below is not necessary for
3117 : the non-bitfield case and declare it a FE error if type
3118 : adjustment would be needed. */
3119 18512613 : if (TREE_TYPE (expr) != type)
3120 : {
3121 : #ifdef ENABLE_TYPES_CHECKING
3122 749765 : tree old_type = TREE_TYPE (expr);
3123 : #endif
3124 749765 : int type_quals;
3125 :
3126 : /* We need to preserve qualifiers and propagate them from
3127 : operand 0. */
3128 749765 : type_quals = TYPE_QUALS (type)
3129 749765 : | TYPE_QUALS (TREE_TYPE (TREE_OPERAND (expr, 0)));
3130 749765 : if (TYPE_QUALS (type) != type_quals)
3131 749603 : type = build_qualified_type (TYPE_MAIN_VARIANT (type), type_quals);
3132 :
3133 : /* Set the type of the COMPONENT_REF to the underlying type. */
3134 749765 : TREE_TYPE (expr) = type;
3135 :
3136 : #ifdef ENABLE_TYPES_CHECKING
3137 : /* It is now a FE error, if the conversion from the canonical
3138 : type to the original expression type is not useless. */
3139 749765 : gcc_assert (useless_type_conversion_p (old_type, type));
3140 : #endif
3141 : }
3142 18512613 : }
3143 :
3144 : /* If a NOP conversion is changing a pointer to array of foo to a pointer
3145 : to foo, embed that change in the ADDR_EXPR by converting
3146 : T array[U];
3147 : (T *)&array
3148 : ==>
3149 : &array[L]
3150 : where L is the lower bound. For simplicity, only do this for constant
3151 : lower bound.
3152 : The constraint is that the type of &array[L] is trivially convertible
3153 : to T *. */
3154 :
3155 : static void
3156 525820 : canonicalize_addr_expr (tree *expr_p)
3157 : {
3158 525820 : tree expr = *expr_p;
3159 525820 : tree addr_expr = TREE_OPERAND (expr, 0);
3160 525820 : tree datype, ddatype, pddatype;
3161 :
3162 : /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
3163 1051294 : if (!POINTER_TYPE_P (TREE_TYPE (expr))
3164 525820 : || TREE_CODE (addr_expr) != ADDR_EXPR)
3165 : return;
3166 :
3167 : /* The addr_expr type should be a pointer to an array. */
3168 346 : datype = TREE_TYPE (TREE_TYPE (addr_expr));
3169 346 : if (TREE_CODE (datype) != ARRAY_TYPE)
3170 : return;
3171 :
3172 : /* The pointer to element type shall be trivially convertible to
3173 : the expression pointer type. */
3174 28 : ddatype = TREE_TYPE (datype);
3175 28 : pddatype = build_pointer_type (ddatype);
3176 28 : if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
3177 : pddatype))
3178 : return;
3179 :
3180 : /* The lower bound and element sizes must be constant. */
3181 0 : if (!TYPE_SIZE_UNIT (ddatype)
3182 0 : || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
3183 0 : || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
3184 0 : || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
3185 : return;
3186 :
3187 : /* All checks succeeded. Build a new node to merge the cast. */
3188 0 : *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
3189 0 : TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
3190 : NULL_TREE, NULL_TREE);
3191 0 : *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
3192 :
3193 : /* We can have stripped a required restrict qualifier above. */
3194 0 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
3195 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
3196 : }
3197 :
3198 : /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
3199 : underneath as appropriate. */
3200 :
3201 : static enum gimplify_status
3202 12859484 : gimplify_conversion (tree *expr_p)
3203 : {
3204 12859484 : location_t loc = EXPR_LOCATION (*expr_p);
3205 12859484 : gcc_assert (CONVERT_EXPR_P (*expr_p));
3206 :
3207 : /* Then strip away all but the outermost conversion. */
3208 12859484 : STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
3209 :
3210 : /* And remove the outermost conversion if it's useless. */
3211 12859484 : if (tree_ssa_useless_type_conversion (*expr_p))
3212 0 : *expr_p = TREE_OPERAND (*expr_p, 0);
3213 :
3214 : /* If we still have a conversion at the toplevel,
3215 : then canonicalize some constructs. */
3216 12859484 : if (CONVERT_EXPR_P (*expr_p))
3217 : {
3218 12859484 : tree sub = TREE_OPERAND (*expr_p, 0);
3219 :
3220 : /* If a NOP conversion is changing the type of a COMPONENT_REF
3221 : expression, then canonicalize its type now in order to expose more
3222 : redundant conversions. */
3223 12859484 : if (TREE_CODE (sub) == COMPONENT_REF)
3224 272081 : canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0));
3225 :
3226 : /* If a NOP conversion is changing a pointer to array of foo
3227 : to a pointer to foo, embed that change in the ADDR_EXPR. */
3228 12587403 : else if (TREE_CODE (sub) == ADDR_EXPR)
3229 525820 : canonicalize_addr_expr (expr_p);
3230 : }
3231 :
3232 : /* If we have a conversion to a non-register type force the
3233 : use of a VIEW_CONVERT_EXPR instead. */
3234 12859484 : if (CONVERT_EXPR_P (*expr_p) && !is_gimple_reg_type (TREE_TYPE (*expr_p)))
3235 90 : *expr_p = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p),
3236 90 : TREE_OPERAND (*expr_p, 0));
3237 :
3238 : /* Canonicalize CONVERT_EXPR to NOP_EXPR. */
3239 12859484 : if (TREE_CODE (*expr_p) == CONVERT_EXPR)
3240 228071 : TREE_SET_CODE (*expr_p, NOP_EXPR);
3241 :
3242 12859484 : return GS_OK;
3243 : }
3244 :
3245 : /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
3246 : DECL_VALUE_EXPR, and it's worth re-examining things. */
3247 :
3248 : static enum gimplify_status
3249 126523063 : gimplify_var_or_parm_decl (tree *expr_p)
3250 : {
3251 126523063 : tree decl = *expr_p;
3252 :
3253 : /* ??? If this is a local variable, and it has not been seen in any
3254 : outer BIND_EXPR, then it's probably the result of a duplicate
3255 : declaration, for which we've already issued an error. It would
3256 : be really nice if the front end wouldn't leak these at all.
3257 : Currently the only known culprit is C++ destructors, as seen
3258 : in g++.old-deja/g++.jason/binding.C.
3259 : Another possible culpit are size expressions for variably modified
3260 : types which are lost in the FE or not gimplified correctly. */
3261 126523063 : if (VAR_P (decl)
3262 98750911 : && !DECL_SEEN_IN_BIND_EXPR_P (decl)
3263 17062342 : && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
3264 126583009 : && decl_function_context (decl) == current_function_decl)
3265 : {
3266 75 : gcc_assert (seen_error ());
3267 : return GS_ERROR;
3268 : }
3269 :
3270 : /* When within an OMP context, notice uses of variables. */
3271 126522988 : if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
3272 : return GS_ALL_DONE;
3273 :
3274 : /* If the decl is an alias for another expression, substitute it now. */
3275 126517168 : if (DECL_HAS_VALUE_EXPR_P (decl))
3276 : {
3277 430787 : *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
3278 430787 : return GS_OK;
3279 : }
3280 :
3281 : return GS_ALL_DONE;
3282 : }
3283 :
3284 : /* Recalculate the value of the TREE_SIDE_EFFECTS flag for T. */
3285 :
3286 : static void
3287 110410107 : recalculate_side_effects (tree t)
3288 : {
3289 110410107 : enum tree_code code = TREE_CODE (t);
3290 110410107 : int len = TREE_OPERAND_LENGTH (t);
3291 110410107 : int i;
3292 :
3293 110410107 : switch (TREE_CODE_CLASS (code))
3294 : {
3295 661550 : case tcc_expression:
3296 661550 : switch (code)
3297 : {
3298 : case INIT_EXPR:
3299 : case MODIFY_EXPR:
3300 : case VA_ARG_EXPR:
3301 : case PREDECREMENT_EXPR:
3302 : case PREINCREMENT_EXPR:
3303 : case POSTDECREMENT_EXPR:
3304 : case POSTINCREMENT_EXPR:
3305 : /* All of these have side-effects, no matter what their
3306 : operands are. */
3307 : return;
3308 :
3309 : default:
3310 : break;
3311 : }
3312 : /* Fall through. */
3313 :
3314 110410105 : case tcc_comparison: /* a comparison expression */
3315 110410105 : case tcc_unary: /* a unary arithmetic expression */
3316 110410105 : case tcc_binary: /* a binary arithmetic expression */
3317 110410105 : case tcc_reference: /* a reference */
3318 110410105 : case tcc_vl_exp: /* a function call */
3319 110410105 : TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
3320 359995825 : for (i = 0; i < len; ++i)
3321 : {
3322 249585720 : tree op = TREE_OPERAND (t, i);
3323 249585720 : if (op && TREE_SIDE_EFFECTS (op))
3324 1278357 : TREE_SIDE_EFFECTS (t) = 1;
3325 : }
3326 : break;
3327 :
3328 : case tcc_constant:
3329 : /* No side-effects. */
3330 : return;
3331 :
3332 2 : default:
3333 2 : if (code == SSA_NAME)
3334 : /* No side-effects. */
3335 : return;
3336 0 : gcc_unreachable ();
3337 : }
3338 : }
3339 :
3340 : /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
3341 : node *EXPR_P.
3342 :
3343 : compound_lval
3344 : : min_lval '[' val ']'
3345 : | min_lval '.' ID
3346 : | compound_lval '[' val ']'
3347 : | compound_lval '.' ID
3348 :
3349 : This is not part of the original SIMPLE definition, which separates
3350 : array and member references, but it seems reasonable to handle them
3351 : together. Also, this way we don't run into problems with union
3352 : aliasing; gcc requires that for accesses through a union to alias, the
3353 : union reference must be explicit, which was not always the case when we
3354 : were splitting up array and member refs.
3355 :
3356 : PRE_P points to the sequence where side effects that must happen before
3357 : *EXPR_P should be stored.
3358 :
3359 : POST_P points to the sequence where side effects that must happen after
3360 : *EXPR_P should be stored. */
3361 :
3362 : static enum gimplify_status
3363 29933758 : gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3364 : fallback_t fallback)
3365 : {
3366 29933758 : tree *p;
3367 29933758 : enum gimplify_status ret = GS_ALL_DONE, tret;
3368 29933758 : int i;
3369 29933758 : location_t loc = EXPR_LOCATION (*expr_p);
3370 29933758 : tree expr = *expr_p;
3371 :
3372 : /* Create a stack of the subexpressions so later we can walk them in
3373 : order from inner to outer. */
3374 29933758 : auto_vec<tree, 10> expr_stack;
3375 :
3376 : /* We can handle anything that get_inner_reference can deal with. */
3377 72263017 : for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
3378 : {
3379 42329259 : restart:
3380 : /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
3381 72328713 : if (TREE_CODE (*p) == INDIRECT_REF)
3382 3900330 : *p = fold_indirect_ref_loc (loc, *p);
3383 :
3384 72328713 : if (handled_component_p (*p))
3385 : ;
3386 : /* Expand DECL_VALUE_EXPR now. In some cases that may expose
3387 : additional COMPONENT_REFs. */
3388 13123657 : else if ((VAR_P (*p) || TREE_CODE (*p) == PARM_DECL)
3389 31442131 : && gimplify_var_or_parm_decl (p) == GS_OK)
3390 65696 : goto restart;
3391 : else
3392 : break;
3393 :
3394 42329259 : expr_stack.safe_push (*p);
3395 : }
3396 :
3397 29933758 : gcc_assert (expr_stack.length ());
3398 :
3399 : /* Now EXPR_STACK is a stack of pointers to all the refs we've
3400 : walked through and P points to the innermost expression.
3401 :
3402 : Java requires that we elaborated nodes in source order. That
3403 : means we must gimplify the inner expression followed by each of
3404 : the indices, in order. But we can't gimplify the inner
3405 : expression until we deal with any variable bounds, sizes, or
3406 : positions in order to deal with PLACEHOLDER_EXPRs.
3407 :
3408 : The base expression may contain a statement expression that
3409 : has declarations used in size expressions, so has to be
3410 : gimplified before gimplifying the size expressions.
3411 :
3412 : So we do this in three steps. First we deal with variable
3413 : bounds, sizes, and positions, then we gimplify the base and
3414 : ensure it is memory if needed, then we deal with the annotations
3415 : for any variables in the components and any indices, from left
3416 : to right. */
3417 :
3418 29933758 : bool need_non_reg = false;
3419 72263014 : for (i = expr_stack.length () - 1; i >= 0; i--)
3420 : {
3421 42329259 : tree t = expr_stack[i];
3422 :
3423 42329259 : if (error_operand_p (TREE_OPERAND (t, 0)))
3424 : return GS_ERROR;
3425 :
3426 42329256 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3427 : {
3428 : /* Deal with the low bound and element type size and put them into
3429 : the ARRAY_REF. If these values are set, they have already been
3430 : gimplified. */
3431 8937304 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3432 : {
3433 8872465 : tree low = unshare_expr (array_ref_low_bound (t));
3434 8872465 : if (!is_gimple_min_invariant (low))
3435 : {
3436 0 : TREE_OPERAND (t, 2) = low;
3437 : }
3438 : }
3439 :
3440 8937304 : if (TREE_OPERAND (t, 3) == NULL_TREE)
3441 : {
3442 8923779 : tree elmt_size = array_ref_element_size (t);
3443 8923779 : if (!is_gimple_min_invariant (elmt_size))
3444 : {
3445 8497 : elmt_size = unshare_expr (elmt_size);
3446 8497 : tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
3447 8497 : tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
3448 :
3449 : /* Divide the element size by the alignment of the element
3450 : type (above). */
3451 8497 : elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR,
3452 : elmt_size, factor);
3453 :
3454 8497 : TREE_OPERAND (t, 3) = elmt_size;
3455 : }
3456 : }
3457 : need_non_reg = true;
3458 : }
3459 33391952 : else if (TREE_CODE (t) == COMPONENT_REF)
3460 : {
3461 : /* Set the field offset into T and gimplify it. */
3462 32212386 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3463 : {
3464 32212007 : tree offset = component_ref_field_offset (t);
3465 32212007 : if (!is_gimple_min_invariant (offset))
3466 : {
3467 287 : offset = unshare_expr (offset);
3468 287 : tree field = TREE_OPERAND (t, 1);
3469 287 : tree factor
3470 287 : = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
3471 :
3472 : /* Divide the offset by its alignment. */
3473 287 : offset = size_binop_loc (loc, EXACT_DIV_EXPR,
3474 : offset, factor);
3475 :
3476 287 : TREE_OPERAND (t, 2) = offset;
3477 : }
3478 : }
3479 : need_non_reg = true;
3480 : }
3481 1179566 : else if (!is_gimple_reg_type (TREE_TYPE (t)))
3482 : /* When the result of an operation, in particular a VIEW_CONVERT_EXPR
3483 : is a non-register type then require the base object to be a
3484 : non-register as well. */
3485 41427729 : need_non_reg = true;
3486 : }
3487 :
3488 : /* Step 2 is to gimplify the base expression. Make sure lvalue is set
3489 : so as to match the min_lval predicate. Failure to do so may result
3490 : in the creation of large aggregate temporaries. */
3491 29933755 : tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
3492 : fallback | fb_lvalue);
3493 29933755 : ret = MIN (ret, tret);
3494 29933755 : if (ret == GS_ERROR)
3495 : return GS_ERROR;
3496 :
3497 : /* Step 2a: if we have component references we do not support on
3498 : registers then make sure the base isn't a register. Of course
3499 : we can only do so if an rvalue is OK. */
3500 29933755 : if (need_non_reg && (fallback & fb_rvalue))
3501 22367162 : prepare_gimple_addressable (p, pre_p);
3502 :
3503 :
3504 : /* Step 3: gimplify size expressions and the indices and operands of
3505 : ARRAY_REF. During this loop we also remove any useless conversions.
3506 : If we operate on a register also make sure to properly gimplify
3507 : to individual operations. */
3508 :
3509 29933755 : bool reg_operations = is_gimple_reg (*p);
3510 72263011 : for (; expr_stack.length () > 0; )
3511 : {
3512 42329256 : tree t = expr_stack.pop ();
3513 :
3514 42329256 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3515 : {
3516 8937304 : gcc_assert (!reg_operations);
3517 :
3518 : /* Gimplify the low bound and element type size. */
3519 8937304 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3520 : is_gimple_reg, fb_rvalue);
3521 8937304 : ret = MIN (ret, tret);
3522 :
3523 8937304 : tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
3524 : is_gimple_reg, fb_rvalue);
3525 8937304 : ret = MIN (ret, tret);
3526 :
3527 : /* Gimplify the dimension. */
3528 8937304 : tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
3529 : is_gimple_val, fb_rvalue);
3530 8937304 : ret = MIN (ret, tret);
3531 : }
3532 33391952 : else if (TREE_CODE (t) == COMPONENT_REF)
3533 : {
3534 32212386 : gcc_assert (!reg_operations);
3535 :
3536 32212386 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3537 : is_gimple_reg, fb_rvalue);
3538 32212386 : ret = MIN (ret, tret);
3539 : }
3540 1179566 : else if (reg_operations)
3541 : {
3542 782925 : tret = gimplify_expr (&TREE_OPERAND (t, 0), pre_p, post_p,
3543 : is_gimple_val, fb_rvalue);
3544 1179566 : ret = MIN (ret, tret);
3545 : }
3546 :
3547 42329256 : STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
3548 :
3549 : /* The innermost expression P may have originally had
3550 : TREE_SIDE_EFFECTS set which would have caused all the outer
3551 : expressions in *EXPR_P leading to P to also have had
3552 : TREE_SIDE_EFFECTS set. */
3553 42329256 : recalculate_side_effects (t);
3554 : }
3555 :
3556 : /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */
3557 29933755 : if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
3558 : {
3559 18240532 : canonicalize_component_ref (expr_p);
3560 : }
3561 :
3562 29933755 : expr_stack.release ();
3563 :
3564 29933755 : gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
3565 :
3566 : return ret;
3567 29933758 : }
3568 :
3569 : /* Gimplify the self modifying expression pointed to by EXPR_P
3570 : (++, --, +=, -=).
3571 :
3572 : PRE_P points to the list where side effects that must happen before
3573 : *EXPR_P should be stored.
3574 :
3575 : POST_P points to the list where side effects that must happen after
3576 : *EXPR_P should be stored.
3577 :
3578 : WANT_VALUE is nonzero iff we want to use the value of this expression
3579 : in another expression.
3580 :
3581 : ARITH_TYPE is the type the computation should be performed in. */
3582 :
3583 : enum gimplify_status
3584 1140600 : gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3585 : bool want_value, tree arith_type)
3586 : {
3587 1140600 : enum tree_code code;
3588 1140600 : tree lhs, lvalue, rhs, t1;
3589 1140600 : gimple_seq post = NULL, *orig_post_p = post_p;
3590 1140600 : bool postfix;
3591 1140600 : enum tree_code arith_code;
3592 1140600 : enum gimplify_status ret;
3593 1140600 : location_t loc = EXPR_LOCATION (*expr_p);
3594 :
3595 1140600 : code = TREE_CODE (*expr_p);
3596 :
3597 1140600 : gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
3598 : || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
3599 :
3600 : /* Prefix or postfix? */
3601 1140600 : if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
3602 : /* Faster to treat as prefix if result is not used. */
3603 : postfix = want_value;
3604 : else
3605 : postfix = false;
3606 :
3607 : /* For postfix, make sure the inner expression's post side effects
3608 : are executed after side effects from this expression. */
3609 399662 : if (postfix)
3610 1140600 : post_p = &post;
3611 :
3612 : /* Add or subtract? */
3613 1140600 : if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
3614 : arith_code = PLUS_EXPR;
3615 : else
3616 47813 : arith_code = MINUS_EXPR;
3617 :
3618 : /* Gimplify the LHS into a GIMPLE lvalue. */
3619 1140600 : lvalue = TREE_OPERAND (*expr_p, 0);
3620 1140600 : ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
3621 1140600 : if (ret == GS_ERROR)
3622 : return ret;
3623 :
3624 : /* Extract the operands to the arithmetic operation. */
3625 1140596 : lhs = lvalue;
3626 1140596 : rhs = TREE_OPERAND (*expr_p, 1);
3627 :
3628 : /* For postfix operator, we evaluate the LHS to an rvalue and then use
3629 : that as the result value and in the postqueue operation. */
3630 1140596 : if (postfix)
3631 : {
3632 188101 : ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
3633 188101 : if (ret == GS_ERROR)
3634 : return ret;
3635 :
3636 188101 : lhs = get_initialized_tmp_var (lhs, pre_p);
3637 : }
3638 :
3639 : /* For POINTERs increment, use POINTER_PLUS_EXPR. */
3640 1140596 : if (POINTER_TYPE_P (TREE_TYPE (lhs)))
3641 : {
3642 236163 : rhs = convert_to_ptrofftype_loc (loc, rhs);
3643 236163 : if (arith_code == MINUS_EXPR)
3644 9662 : rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
3645 236163 : t1 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
3646 : }
3647 : else
3648 904433 : t1 = fold_convert (TREE_TYPE (*expr_p),
3649 : fold_build2 (arith_code, arith_type,
3650 : fold_convert (arith_type, lhs),
3651 : fold_convert (arith_type, rhs)));
3652 :
3653 1140596 : if (postfix)
3654 : {
3655 188101 : gimplify_assign (lvalue, t1, pre_p);
3656 188101 : gimplify_seq_add_seq (orig_post_p, post);
3657 188101 : *expr_p = lhs;
3658 188101 : return GS_ALL_DONE;
3659 : }
3660 : else
3661 : {
3662 952495 : *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
3663 952495 : return GS_OK;
3664 : }
3665 : }
3666 :
3667 : /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
3668 :
3669 : static void
3670 80778230 : maybe_with_size_expr (tree *expr_p)
3671 : {
3672 80778230 : tree expr = *expr_p;
3673 80778230 : tree type = TREE_TYPE (expr);
3674 80778230 : tree size;
3675 :
3676 : /* If we've already wrapped this or the type is error_mark_node, we can't do
3677 : anything. */
3678 80778230 : if (TREE_CODE (expr) == WITH_SIZE_EXPR
3679 80778105 : || type == error_mark_node)
3680 : return;
3681 :
3682 : /* If the size isn't known or is a constant, we have nothing to do. */
3683 80777957 : size = TYPE_SIZE_UNIT (type);
3684 80777957 : if (!size || poly_int_tree_p (size))
3685 : return;
3686 :
3687 : /* Otherwise, make a WITH_SIZE_EXPR. */
3688 1687 : size = unshare_expr (size);
3689 1687 : size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
3690 1687 : *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
3691 : }
3692 :
3693 : /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P
3694 : Store any side-effects in PRE_P. CALL_LOCATION is the location of
3695 : the CALL_EXPR. If ALLOW_SSA is set the actual parameter may be
3696 : gimplified to an SSA name. */
3697 :
3698 : enum gimplify_status
3699 33279216 : gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
3700 : bool allow_ssa)
3701 : {
3702 33279216 : bool (*test) (tree);
3703 33279216 : fallback_t fb;
3704 :
3705 : /* In general, we allow lvalues for function arguments to avoid
3706 : extra overhead of copying large aggregates out of even larger
3707 : aggregates into temporaries only to copy the temporaries to
3708 : the argument list. Make optimizers happy by pulling out to
3709 : temporaries those types that fit in registers. */
3710 33279216 : if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
3711 : test = is_gimple_val, fb = fb_rvalue;
3712 : else
3713 : {
3714 1551427 : test = is_gimple_lvalue, fb = fb_either;
3715 : /* Also strip a TARGET_EXPR that would force an extra copy. */
3716 1551427 : if (TREE_CODE (*arg_p) == TARGET_EXPR)
3717 : {
3718 302673 : tree init = TARGET_EXPR_INITIAL (*arg_p);
3719 302673 : if (init
3720 302670 : && !VOID_TYPE_P (TREE_TYPE (init))
3721 : /* Currently, due to c++/116015, it is not desirable to
3722 : strip a TARGET_EXPR whose initializer is a {}. The
3723 : problem is that if we do elide it, we also have to
3724 : replace all the occurrences of the slot temporary in the
3725 : initializer with the temporary created for the argument.
3726 : But we do not have that temporary yet so the replacement
3727 : would be quite awkward and it might be needed to resort
3728 : back to a PLACEHOLDER_EXPR. Note that stripping the
3729 : TARGET_EXPR wouldn't help anyway, as gimplify_expr would
3730 : just allocate a temporary to store the CONSTRUCTOR into.
3731 : (FIXME PR116375.)
3732 :
3733 : See convert_for_arg_passing for the C++ code that marks
3734 : the TARGET_EXPR as eliding or not. */
3735 566560 : && TREE_CODE (init) != CONSTRUCTOR)
3736 233573 : *arg_p = init;
3737 : }
3738 : }
3739 :
3740 : /* If this is a variable sized type, we must remember the size. */
3741 33279216 : maybe_with_size_expr (arg_p);
3742 :
3743 : /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */
3744 : /* Make sure arguments have the same location as the function call
3745 : itself. */
3746 33279216 : protected_set_expr_location (*arg_p, call_location);
3747 :
3748 : /* There is a sequence point before a function call. Side effects in
3749 : the argument list must occur before the actual call. So, when
3750 : gimplifying arguments, force gimplify_expr to use an internal
3751 : post queue which is then appended to the end of PRE_P. */
3752 33279216 : return gimplify_expr (arg_p, pre_p, NULL, test, fb, allow_ssa);
3753 : }
3754 :
3755 : /* Don't fold inside offloading or taskreg regions: it can break code by
3756 : adding decl references that weren't in the source. We'll do it during
3757 : omplower pass instead. */
3758 :
3759 : static bool
3760 58975303 : maybe_fold_stmt (gimple_stmt_iterator *gsi)
3761 : {
3762 58975303 : struct gimplify_omp_ctx *ctx;
3763 59503353 : for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
3764 1195606 : if ((ctx->region_type & (ORT_TARGET | ORT_PARALLEL | ORT_TASK)) != 0)
3765 : return false;
3766 532999 : else if ((ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
3767 : return false;
3768 : /* Delay folding of builtins until the IL is in consistent state
3769 : so the diagnostic machinery can do a better job. */
3770 58307747 : if (gimple_call_builtin_p (gsi_stmt (*gsi)))
3771 : return false;
3772 55953152 : return fold_stmt (gsi);
3773 : }
3774 :
3775 : static tree
3776 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
3777 : tree construct_context);
3778 :
3779 :
3780 : /* Helper function for calls to omp_dynamic_cond: find the current
3781 : enclosing block in the gimplification context. */
3782 : static tree
3783 359 : find_supercontext (void)
3784 : {
3785 359 : vec<gbind *>stack = gimple_bind_expr_stack ();
3786 686 : for (int i = stack.length () - 1; i >= 0; i++)
3787 : {
3788 327 : gbind *b = stack[i];
3789 327 : if (b->block)
3790 : return b->block;
3791 : }
3792 : return NULL_TREE;
3793 : }
3794 :
3795 : /* OpenMP: Handle the append_args and adjust_args clauses of
3796 : declare_variant for EXPR, which is a CALL_EXPR whose CALL_EXPR_FN
3797 : is the variant, within a dispatch construct with clauses DISPATCH_CLAUSES.
3798 : WANT_VALUE and POINTERIZE are as for expand_variant_call_expr.
3799 :
3800 : 'append_args' causes interop objects are added after the last regular
3801 : (nonhidden, nonvariadic) arguments of the variant function.
3802 : 'adjust_args' with need_device_{addr,ptr} converts the pointer target of
3803 : a pointer from a host to a device address. This uses either the default
3804 : device or the passed device number, which then sets the default device
3805 : address. */
3806 : static tree
3807 471 : modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
3808 : bool want_value, bool pointerize)
3809 : {
3810 471 : location_t loc = EXPR_LOCATION (expr);
3811 471 : tree fndecl = get_callee_fndecl (expr);
3812 :
3813 : /* Skip processing if we don't get the expected call form. */
3814 471 : if (!fndecl)
3815 : return expr;
3816 :
3817 471 : tree init_code = NULL_TREE;
3818 471 : tree cleanup = NULL_TREE;
3819 471 : tree clobbers = NULL_TREE;
3820 471 : int nargs = call_expr_nargs (expr);
3821 471 : tree dispatch_device_num = NULL_TREE;
3822 471 : tree dispatch_interop = NULL_TREE;
3823 471 : tree dispatch_append_args = NULL_TREE;
3824 471 : int nfirst_args = 0;
3825 471 : tree dispatch_adjust_args_list
3826 471 : = lookup_attribute ("omp declare variant variant args",
3827 471 : DECL_ATTRIBUTES (fndecl));
3828 :
3829 471 : if (dispatch_adjust_args_list)
3830 : {
3831 389 : dispatch_adjust_args_list = TREE_VALUE (dispatch_adjust_args_list);
3832 389 : dispatch_append_args = TREE_CHAIN (dispatch_adjust_args_list);
3833 389 : if (TREE_PURPOSE (dispatch_adjust_args_list) == NULL_TREE
3834 389 : && TREE_VALUE (dispatch_adjust_args_list) == NULL_TREE)
3835 : dispatch_adjust_args_list = NULL_TREE;
3836 : }
3837 389 : if (dispatch_append_args)
3838 : {
3839 245 : nfirst_args = tree_to_shwi (TREE_PURPOSE (dispatch_append_args));
3840 245 : dispatch_append_args = TREE_VALUE (dispatch_append_args);
3841 : }
3842 471 : dispatch_device_num = omp_find_clause (dispatch_clauses, OMP_CLAUSE_DEVICE);
3843 471 : if (dispatch_device_num)
3844 287 : dispatch_device_num = OMP_CLAUSE_DEVICE_ID (dispatch_device_num);
3845 471 : dispatch_interop = omp_find_clause (dispatch_clauses, OMP_CLAUSE_INTEROP);
3846 471 : int nappend = 0, ninterop = 0;
3847 880 : for (tree t = dispatch_append_args; t; t = TREE_CHAIN (t))
3848 409 : nappend++;
3849 :
3850 : /* FIXME: error checking should be taken out of this function and
3851 : handled before any attempt at filtering or resolution happens.
3852 : Otherwise whether or not diagnostics appear is determined by
3853 : GCC internals, how good the front ends are at constant-folding,
3854 : the split between early/late resolution, etc instead of the code
3855 : as written by the user. */
3856 471 : if (dispatch_interop)
3857 861 : for (tree t = dispatch_interop; t; t = TREE_CHAIN (t))
3858 605 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3859 409 : ninterop++;
3860 471 : if (dispatch_interop && !dispatch_device_num)
3861 : {
3862 7 : gcc_checking_assert (ninterop > 1);
3863 7 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3864 : "the %<device%> clause must be present if the %<interop%> "
3865 : "clause has more than one list item");
3866 : }
3867 471 : if (nappend < ninterop)
3868 : {
3869 48 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3870 : "number of list items in %<interop%> clause (%d) "
3871 : "exceeds the number of %<append_args%> items (%d) for "
3872 : "%<declare variant%> candidate %qD", ninterop, nappend, fndecl);
3873 88 : inform (dispatch_append_args
3874 8 : ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args))
3875 40 : : DECL_SOURCE_LOCATION (fndecl),
3876 : "%<declare variant%> candidate %qD declared here", fndecl);
3877 48 : ninterop = nappend;
3878 : }
3879 471 : if (dispatch_append_args)
3880 : {
3881 245 : tree *buffer = XALLOCAVEC (tree, nargs + nappend);
3882 245 : tree arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
3883 : /* Copy the first arguments; insert then the interop objects,
3884 : and then copy the rest (nargs - nfirst_args) args. */
3885 245 : int i;
3886 679 : for (i = 0; i < nfirst_args; i++)
3887 : {
3888 434 : arg = TREE_CHAIN (arg);
3889 434 : buffer[i] = CALL_EXPR_ARG (expr, i);
3890 : }
3891 : int j = ninterop;
3892 583 : for (tree t = dispatch_interop; t && j > 0; t = TREE_CHAIN (t))
3893 338 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3894 338 : buffer[i + --j] = OMP_CLAUSE_DECL (t);
3895 245 : gcc_checking_assert (j == 0);
3896 :
3897 : /* Do we need to create additional interop objects? */
3898 245 : if (ninterop < nappend)
3899 : {
3900 56 : if (dispatch_device_num == NULL_TREE)
3901 : /* Not remapping device number. */
3902 22 : dispatch_device_num = build_int_cst (integer_type_node,
3903 : GOMP_DEVICE_DEFAULT_OMP_61);
3904 56 : int nnew = nappend - ninterop;
3905 56 : tree nobjs = build_int_cst (integer_type_node, nnew);
3906 56 : tree a, t;
3907 :
3908 : /* Skip to the append_args clause for the first constructed
3909 : interop argument. */
3910 56 : tree apparg = dispatch_append_args;
3911 83 : for (j = 0; j < ninterop; j++)
3912 27 : apparg = TREE_CHAIN (apparg);
3913 :
3914 : /* omp_interop_t *objs[n]; */
3915 56 : tree objtype = build_pointer_type (pointer_sized_int_node);
3916 56 : t = build_array_type_nelts (objtype, nnew);
3917 56 : tree objs = create_tmp_var (t, "interopobjs");
3918 :
3919 : /* int target_tgtsync[n]; */
3920 56 : t = build_array_type_nelts (integer_type_node, nnew);
3921 56 : tree target_tgtsync = create_tmp_var (t, "tgt_tgtsync");
3922 :
3923 : /* Scan first to determine if we need a prefer_type array. */
3924 56 : tree prefer_type = NULL_TREE;
3925 56 : tree prefer_type_type = NULL_TREE;
3926 141 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3927 64 : if (TREE_VALUE (a) != NULL_TREE)
3928 : {
3929 : /* const char *prefer_type[n]; */
3930 35 : t = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
3931 35 : prefer_type_type = build_pointer_type (t);
3932 35 : t = build_array_type_nelts (prefer_type_type, nnew);
3933 35 : prefer_type = create_tmp_var (t, "pref_type");
3934 35 : break;
3935 : }
3936 :
3937 : /* Initialize the arrays, generating temp vars and clobbers for
3938 : the interop objects. (The constructed array holding the
3939 : pointers to these objects shouldn't need clobbering as there's
3940 : no reason for GOMP_interop to modify its contents.) */
3941 127 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3942 : {
3943 : /* The allocated temporaries for the interop objects
3944 : have type omp_interop_t, which is an integer type that
3945 : can encode a pointer. */
3946 71 : tree objvar = create_tmp_var (pointer_sized_int_node, "interop");
3947 71 : buffer[i + j] = objvar;
3948 71 : TREE_ADDRESSABLE (objvar) = 1;
3949 : /* Generate a clobber for the temporary for when we're done
3950 : with it. */
3951 71 : tree c = build_clobber (pointer_sized_int_node,
3952 : CLOBBER_OBJECT_END);
3953 71 : c = build2 (MODIFY_EXPR, pointer_sized_int_node, objvar, c);
3954 71 : if (clobbers)
3955 15 : clobbers = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
3956 : c, clobbers);
3957 : else
3958 : clobbers = c;
3959 :
3960 : /* objs[offset] = &objvar; */
3961 71 : tree offset = build_int_cst (integer_type_node, j - ninterop);
3962 71 : tree init = build4 (ARRAY_REF, objtype, objs, offset,
3963 : NULL_TREE, NULL_TREE);
3964 71 : init = build2 (MODIFY_EXPR, objtype, init,
3965 : build_fold_addr_expr (objvar));
3966 71 : if (init_code)
3967 15 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
3968 : init_code, init);
3969 : else
3970 : init_code = init;
3971 :
3972 : /* target_tgtsync[offset] = tgt;
3973 : (Don't blame me, I didn't design the encoding of this
3974 : info into the dispatch interop clause data structure,
3975 : but the runtime wants a bit mask.) */
3976 71 : tree tree_tgt = TREE_OPERAND (TREE_PURPOSE (a), 0);
3977 71 : int tgt = 0;
3978 71 : if (TREE_PURPOSE (tree_tgt) == boolean_true_node)
3979 42 : tgt |= GOMP_INTEROP_TARGET;
3980 71 : if (TREE_VALUE (tree_tgt) == boolean_true_node)
3981 36 : tgt |= GOMP_INTEROP_TARGETSYNC;
3982 71 : init = build4 (ARRAY_REF, integer_type_node,
3983 : target_tgtsync, offset, NULL_TREE, NULL_TREE);
3984 71 : init = build2 (MODIFY_EXPR, integer_type_node, init,
3985 71 : build_int_cst (integer_type_node, tgt));
3986 71 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
3987 : init_code, init);
3988 :
3989 71 : if (prefer_type)
3990 : {
3991 45 : tree pref = TREE_VALUE (a);
3992 45 : if (pref == NULL_TREE)
3993 6 : pref = null_pointer_node;
3994 : else
3995 39 : pref = build_fold_addr_expr (pref);
3996 45 : init = build4 (ARRAY_REF, prefer_type_type, prefer_type,
3997 : offset, NULL_TREE, NULL_TREE);
3998 45 : init = build2 (MODIFY_EXPR, prefer_type_type, init,
3999 : pref);
4000 45 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4001 : init_code, init);
4002 : }
4003 : }
4004 :
4005 56 : objs = build_fold_addr_expr (objs);
4006 56 : target_tgtsync = build_fold_addr_expr (target_tgtsync);
4007 56 : prefer_type = prefer_type ? build_fold_addr_expr (prefer_type)
4008 : : null_pointer_node;
4009 56 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
4010 56 : tree create
4011 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4012 : nobjs, objs, target_tgtsync, prefer_type,
4013 : integer_zero_node, null_pointer_node,
4014 : integer_zero_node, null_pointer_node,
4015 : integer_zero_node, null_pointer_node);
4016 56 : if (init_code)
4017 56 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (create),
4018 : init_code, create);
4019 : else
4020 : init_code = create;
4021 :
4022 56 : cleanup
4023 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4024 : integer_zero_node, null_pointer_node,
4025 : null_pointer_node, null_pointer_node,
4026 : integer_zero_node, null_pointer_node,
4027 : nobjs, objs,
4028 : integer_zero_node, null_pointer_node);
4029 56 : if (clobbers)
4030 56 : cleanup = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
4031 : cleanup, clobbers);
4032 : }
4033 :
4034 654 : for (j = 0; j < nappend; j++)
4035 : {
4036 : /* Fortran permits by-reference or by-value for the dummy arg
4037 : and by-value, by-reference, ptr by-reference as actual
4038 : argument. Handle this. */
4039 409 : tree obj = buffer[i + j]; // interop object
4040 409 : tree a2 = TREE_VALUE (arg); // parameter type
4041 766 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4042 436 : && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (obj))))
4043 : {
4044 32 : tree t = TREE_TYPE (TREE_TYPE (obj));
4045 32 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (t)));
4046 32 : obj = fold_build1 (INDIRECT_REF, t, obj);
4047 : }
4048 750 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4049 420 : && INTEGRAL_TYPE_P (a2))
4050 : {
4051 43 : tree t = TREE_TYPE (TREE_TYPE (obj));
4052 43 : gcc_checking_assert (INTEGRAL_TYPE_P (t));
4053 43 : obj = fold_build1 (INDIRECT_REF, t, obj);
4054 : }
4055 497 : else if (INTEGRAL_TYPE_P (TREE_TYPE (obj))
4056 461 : && POINTER_TYPE_P (a2))
4057 : {
4058 18 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4059 18 : obj = build_fold_addr_expr (obj);
4060 : }
4061 348 : else if (!INTEGRAL_TYPE_P (a2)
4062 348 : || !INTEGRAL_TYPE_P (TREE_TYPE (obj)))
4063 : {
4064 36 : tree t = TREE_TYPE (obj);
4065 36 : gcc_checking_assert (POINTER_TYPE_P (t)
4066 : && POINTER_TYPE_P (a2)
4067 : && INTEGRAL_TYPE_P (TREE_TYPE (t))
4068 : && INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4069 : }
4070 409 : buffer[i + j] = obj;
4071 409 : arg = TREE_CHAIN (arg);
4072 : }
4073 245 : i += nappend;
4074 534 : for (j = nfirst_args; j < nargs; j++)
4075 289 : buffer[i++] = CALL_EXPR_ARG (expr, j);
4076 245 : nargs += nappend;
4077 245 : tree call = expr;
4078 490 : expr = build_call_array_loc (EXPR_LOCATION (expr), TREE_TYPE (call),
4079 245 : CALL_EXPR_FN (call), nargs, buffer);
4080 :
4081 : /* Copy all CALL_EXPR flags. */
4082 245 : CALL_EXPR_STATIC_CHAIN (expr) = CALL_EXPR_STATIC_CHAIN (call);
4083 245 : CALL_EXPR_TAILCALL (expr) = CALL_EXPR_TAILCALL (call);
4084 245 : CALL_EXPR_RETURN_SLOT_OPT (expr)
4085 245 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4086 245 : CALL_FROM_THUNK_P (expr) = CALL_FROM_THUNK_P (call);
4087 245 : SET_EXPR_LOCATION (expr, EXPR_LOCATION (call));
4088 245 : CALL_EXPR_VA_ARG_PACK (expr) = CALL_EXPR_VA_ARG_PACK (call);
4089 : }
4090 :
4091 : /* Nothing to do for adjust_args? */
4092 471 : if (!dispatch_adjust_args_list || !TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
4093 260 : goto add_cleanup;
4094 :
4095 : /* Handle adjust_args. */
4096 966 : for (int i = 0; i < nargs; i++)
4097 : {
4098 755 : tree *arg_p = &CALL_EXPR_ARG (expr, i);
4099 :
4100 : /* Nothing to do if arg is constant null pointer. */
4101 755 : if (integer_zerop (*arg_p))
4102 6 : continue;
4103 :
4104 : bool need_device_ptr = false;
4105 : bool need_device_addr = false;
4106 2247 : for (int need_addr = 0; need_addr <= 1; need_addr++)
4107 2301 : for (tree arg = (need_addr
4108 1498 : ? TREE_VALUE (dispatch_adjust_args_list)
4109 1498 : : TREE_PURPOSE (dispatch_adjust_args_list));
4110 2301 : arg != NULL; arg = TREE_CHAIN (arg))
4111 : {
4112 1152 : if (TREE_VALUE (arg)
4113 1152 : && TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST
4114 2304 : && wi::eq_p (i, wi::to_wide (TREE_VALUE (arg))))
4115 : {
4116 349 : if (need_addr)
4117 : need_device_addr = true;
4118 : else
4119 349 : need_device_ptr = true;
4120 : break;
4121 : }
4122 : }
4123 :
4124 749 : if (need_device_ptr || need_device_addr)
4125 : {
4126 740 : bool is_device_ptr = false;
4127 740 : bool has_device_addr = false;
4128 :
4129 740 : for (tree c = dispatch_clauses; c; c = TREE_CHAIN (c))
4130 : {
4131 454 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
4132 454 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
4133 : {
4134 164 : tree decl1 = DECL_NAME (OMP_CLAUSE_DECL (c));
4135 164 : tree decl2 = tree_strip_nop_conversions (*arg_p);
4136 164 : if (TREE_CODE (decl2) == ADDR_EXPR)
4137 19 : decl2 = TREE_OPERAND (decl2, 0);
4138 164 : if (VAR_P (decl2) || TREE_CODE (decl2) == PARM_DECL)
4139 : {
4140 140 : decl2 = DECL_NAME (decl2);
4141 140 : if (decl1 == decl2
4142 203 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
4143 : {
4144 58 : if (need_device_addr)
4145 0 : warning_at (OMP_CLAUSE_LOCATION (c),
4146 0 : OPT_Wopenmp,
4147 : "%<is_device_ptr%> for %qD does"
4148 : " not imply %<has_device_addr%> "
4149 : "required for %<need_device_addr%>",
4150 0 : OMP_CLAUSE_DECL (c));
4151 : is_device_ptr = true;
4152 : break;
4153 : }
4154 82 : else if (decl1 == decl2)
4155 : {
4156 5 : if (need_device_ptr)
4157 10 : warning_at (OMP_CLAUSE_LOCATION (c),
4158 5 : OPT_Wopenmp,
4159 : "%<has_device_addr%> for %qD does"
4160 : " not imply %<is_device_ptr%> "
4161 : "required for %<need_device_ptr%>",
4162 5 : OMP_CLAUSE_DECL (c));
4163 : has_device_addr = true;
4164 : break;
4165 : }
4166 : }
4167 : }
4168 : }
4169 :
4170 349 : if ((need_device_ptr && !is_device_ptr)
4171 58 : || (need_device_addr && !has_device_addr))
4172 : {
4173 291 : if (dispatch_device_num == NULL_TREE)
4174 : {
4175 : // device_num = omp_get_default_device ()
4176 105 : tree fn
4177 105 : = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
4178 105 : tree call = build_call_expr (fn, 0);
4179 105 : dispatch_device_num = create_tmp_var_raw (TREE_TYPE (call));
4180 105 : tree init
4181 105 : = build4 (TARGET_EXPR, TREE_TYPE (call),
4182 : dispatch_device_num, call, NULL_TREE, NULL_TREE);
4183 105 : if (init_code)
4184 0 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4185 : init_code, init);
4186 : else
4187 : init_code = init;
4188 : }
4189 :
4190 : // We want to emit the following statement:
4191 : // mapped_arg = omp_get_mapped_ptr (arg,
4192 : // device_num)
4193 : // but arg has to be the actual pointer, not a
4194 : // reference or a conversion expression.
4195 291 : tree actual_ptr
4196 291 : = ((TREE_CODE (*arg_p) == ADDR_EXPR)
4197 291 : ? TREE_OPERAND (*arg_p, 0)
4198 38 : : *arg_p);
4199 291 : if (TREE_CODE (actual_ptr) == NOP_EXPR
4200 291 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (actual_ptr, 0)))
4201 : == REFERENCE_TYPE))
4202 : {
4203 6 : actual_ptr = TREE_OPERAND (actual_ptr, 0);
4204 6 : actual_ptr = build1 (INDIRECT_REF,
4205 6 : TREE_TYPE (actual_ptr),
4206 : actual_ptr);
4207 : }
4208 291 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_MAPPED_PTR);
4209 291 : tree mapped_arg = build_call_expr_loc (loc, fn, 2, actual_ptr,
4210 : dispatch_device_num);
4211 :
4212 291 : if (TREE_CODE (*arg_p) == ADDR_EXPR
4213 291 : || (TREE_CODE (TREE_TYPE (actual_ptr)) == REFERENCE_TYPE))
4214 47 : mapped_arg = build_fold_addr_expr (mapped_arg);
4215 244 : else if (TREE_CODE (*arg_p) == NOP_EXPR)
4216 35 : mapped_arg = build1 (NOP_EXPR, TREE_TYPE (*arg_p),
4217 : mapped_arg);
4218 291 : *arg_p = mapped_arg;
4219 : }
4220 : }
4221 : }
4222 :
4223 471 : add_cleanup:
4224 471 : if (cleanup)
4225 : {
4226 56 : tree result = NULL_TREE;
4227 56 : if (want_value && pointerize)
4228 : {
4229 0 : tree tmp = create_tmp_var (build_pointer_type (TREE_TYPE (expr)),
4230 : "cleanuptmp");
4231 0 : result = build_simple_mem_ref (tmp);
4232 0 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp,
4233 : build_fold_addr_expr (expr));
4234 : }
4235 56 : else if (want_value)
4236 : {
4237 18 : tree tmp = create_tmp_var (TREE_TYPE (expr), "cleanuptmp");
4238 18 : result = tmp;
4239 18 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp, expr);
4240 : }
4241 56 : if (init_code)
4242 56 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4243 56 : expr = build2 (TRY_FINALLY_EXPR, void_type_node, expr, cleanup);
4244 :
4245 56 : if (result)
4246 18 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (result), expr, result);
4247 : }
4248 415 : else if (init_code)
4249 105 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4250 :
4251 : return expr;
4252 : }
4253 :
4254 : /* Helper function for gimplify_call_expr: handle "declare variant"
4255 : resolution and expansion of the CALL_EXPR EXPR. WANT_VALUE is true
4256 : if the result value of the call is needed; POINTERIZE is true if it
4257 : also needs to be pointerized. If OMP_DISPATCH_P is true, apply
4258 : associated transformations using DISPATCH_CLAUSES.
4259 : This function may return either the original call or some other
4260 : expression such as a conditional to select one of multiple calls.
4261 :
4262 : FIXME: this function is written to be independent of gimplifier internals
4263 : so that it could be moved to omp-general.cc and invoked from the
4264 : front ends instead, per PR115076. */
4265 :
4266 : static tree
4267 1326 : expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
4268 : bool omp_dispatch_p, tree dispatch_clauses)
4269 : {
4270 : /* If we've already processed this call, stop now. This can happen
4271 : if the variant call resolves to the original function, or to
4272 : a dynamic conditional that includes the default call to the original
4273 : function. */
4274 1326 : gcc_assert (omp_resolved_variant_calls != NULL);
4275 1326 : if (omp_resolved_variant_calls->contains (expr))
4276 131 : return expr;
4277 :
4278 1195 : tree fndecl = get_callee_fndecl (expr);
4279 1195 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (expr));
4280 1195 : location_t loc = EXPR_LOCATION (expr);
4281 1195 : tree construct_context = omp_get_construct_context ();
4282 1195 : vec<struct omp_variant> all_candidates
4283 1195 : = omp_declare_variant_candidates (fndecl, construct_context);
4284 1195 : gcc_assert (!all_candidates.is_empty ());
4285 1195 : vec<struct omp_variant> candidates
4286 1195 : = omp_get_dynamic_candidates (all_candidates, construct_context);
4287 :
4288 : /* If the variant call could be resolved now, build a nest of COND_EXPRs
4289 : if there are dynamic candidates, and/or a new CALL_EXPR for each
4290 : candidate call. */
4291 1195 : if (!candidates.is_empty ())
4292 : {
4293 1183 : int n = candidates.length ();
4294 1183 : tree tail = NULL_TREE;
4295 :
4296 2404 : for (int i = n - 1; i >= 0; i--)
4297 : {
4298 1221 : if (tail)
4299 38 : gcc_assert (candidates[i].dynamic_selector);
4300 : else
4301 1183 : gcc_assert (!candidates[i].dynamic_selector);
4302 1221 : if (candidates[i].alternative == fndecl)
4303 : {
4304 : /* We should only get the original function back as the
4305 : default. */
4306 261 : gcc_assert (!tail);
4307 261 : omp_resolved_variant_calls->add (expr);
4308 261 : tail = expr;
4309 : }
4310 : else
4311 : {
4312 : /* For the final static selector, we can re-use the old
4313 : CALL_EXPR and just replace the function, unless it may
4314 : need dispatch argument modification. Otherwise,
4315 : make a copy of it. */
4316 960 : tree thiscall = (tail || omp_dispatch_p
4317 960 : ? unshare_expr (expr) : expr);
4318 960 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype,
4319 960 : candidates[i].alternative);
4320 960 : if (omp_dispatch_p)
4321 471 : thiscall = modify_call_for_omp_dispatch (thiscall,
4322 : dispatch_clauses,
4323 : want_value,
4324 : pointerize);
4325 960 : if (!tail)
4326 : tail = thiscall;
4327 : else
4328 76 : tail = build3 (COND_EXPR, TREE_TYPE (expr),
4329 38 : omp_dynamic_cond (candidates[i].selector,
4330 : find_supercontext ()),
4331 : thiscall, tail);
4332 : }
4333 : }
4334 : return tail;
4335 : }
4336 :
4337 : /* If we couldn't resolve the variant call now, expand it into a loop using
4338 : a switch and OMP_NEXT_VARIANT for dispatch. The ompdevlow pass will
4339 : handle OMP_NEXT_VARIANT expansion. */
4340 : else
4341 : {
4342 : /* If we need a usable return value, we need a temporary
4343 : and an assignment in each alternative. This logic was borrowed
4344 : from gimplify_cond_expr. */
4345 12 : tree type = TREE_TYPE (expr);
4346 12 : tree tmp = NULL_TREE, result = NULL_TREE;
4347 :
4348 12 : if (want_value)
4349 : {
4350 12 : if (pointerize)
4351 : {
4352 0 : type = build_pointer_type (type);
4353 0 : tmp = create_tmp_var (type, "iftmp");
4354 0 : result = build_simple_mem_ref_loc (loc, tmp);
4355 : }
4356 : else
4357 : {
4358 12 : tmp = create_tmp_var (type, "iftmp");
4359 12 : result = tmp;
4360 : }
4361 : }
4362 :
4363 : /* Preprocess the all_candidates array so that the alternative field of
4364 : each element holds the actual function call expression and possible
4365 : assignment, instead of just the decl for the variant function. */
4366 60 : for (unsigned int i = 0; i < all_candidates.length (); i++)
4367 : {
4368 48 : tree decl = all_candidates[i].alternative;
4369 48 : tree thiscall;
4370 :
4371 : /* We need to turn the decl from the candidate into a function
4372 : call and possible assignment, and stuff that in
4373 : the directive seq of the gomp_variant. */
4374 48 : if (decl == fndecl)
4375 : {
4376 12 : thiscall = expr;
4377 12 : omp_resolved_variant_calls->add (expr);
4378 : }
4379 : else
4380 : {
4381 36 : thiscall = unshare_expr (expr);
4382 36 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype, decl);
4383 36 : if (omp_dispatch_p)
4384 0 : thiscall = modify_call_for_omp_dispatch (thiscall,
4385 : dispatch_clauses,
4386 : want_value,
4387 : pointerize);
4388 : }
4389 48 : if (pointerize)
4390 0 : thiscall = build_fold_addr_expr_loc (loc, thiscall);
4391 48 : if (want_value)
4392 48 : thiscall = build2 (INIT_EXPR, type, tmp, thiscall);
4393 48 : all_candidates[i].alternative = thiscall;
4394 : }
4395 :
4396 12 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
4397 12 : tree expansion = expand_late_variant_directive (all_candidates,
4398 : construct_context);
4399 12 : if (result)
4400 12 : expansion = build2 (COMPOUND_EXPR, TREE_TYPE (result),
4401 : expansion, result);
4402 12 : return expansion;
4403 : }
4404 : }
4405 :
4406 : /* Wrapper around expand_variant_call_expr to interface with gimplifier
4407 : state. EXPR and OMP_DISPATCH_P are as for expand_variant_call_expr,
4408 : FALLBACK is used to compute the WANT_VALUE and POINTERIZE arguments. */
4409 : static tree
4410 1326 : gimplify_variant_call_expr (tree expr, fallback_t fallback,
4411 : bool omp_dispatch_p)
4412 : {
4413 1326 : tree type = TREE_TYPE (expr);
4414 1326 : bool want_value = (fallback != fb_none && !VOID_TYPE_P (type));
4415 673 : bool pointerize = false;
4416 : /* If the result value must be an lvalue or the result type must
4417 : live in memory, then we have to pointerize it if we need a temporary. */
4418 673 : if (want_value
4419 673 : && ((!(fallback & fb_rvalue) && (fallback & fb_lvalue))
4420 673 : || TREE_ADDRESSABLE (type)))
4421 0 : pointerize = true;
4422 :
4423 1838 : return expand_variant_call_expr (expr, want_value, pointerize,
4424 : omp_dispatch_p,
4425 : (omp_dispatch_p
4426 512 : ? gimplify_omp_ctxp->clauses
4427 1326 : : NULL_TREE));
4428 : }
4429 :
4430 :
4431 : /* Helper function for gimplify_call_expr, called via walk_tree.
4432 : Find used user labels. */
4433 :
4434 : static tree
4435 766 : find_used_user_labels (tree *tp, int *, void *)
4436 : {
4437 766 : if (TREE_CODE (*tp) == LABEL_EXPR
4438 15 : && !DECL_ARTIFICIAL (LABEL_EXPR_LABEL (*tp))
4439 15 : && DECL_NAME (LABEL_EXPR_LABEL (*tp))
4440 781 : && TREE_USED (LABEL_EXPR_LABEL (*tp)))
4441 15 : return *tp;
4442 : return NULL_TREE;
4443 : }
4444 :
4445 :
4446 : /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
4447 : WANT_VALUE is true if the result of the call is desired. */
4448 :
4449 : static enum gimplify_status
4450 16791386 : gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
4451 : {
4452 16791386 : bool want_value = (fallback != fb_none);
4453 16791386 : tree fndecl, parms, p, fnptrtype;
4454 16791386 : enum gimplify_status ret;
4455 16791386 : int i, nargs;
4456 16791386 : gcall *call;
4457 16791386 : bool builtin_va_start_p = false, omp_dispatch_p = false;
4458 16791386 : location_t loc = EXPR_LOCATION (*expr_p);
4459 :
4460 16791386 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4461 :
4462 : /* For reliable diagnostics during inlining, it is necessary that
4463 : every call_expr be annotated with file and line. */
4464 16791386 : if (! EXPR_HAS_LOCATION (*expr_p))
4465 567912 : SET_EXPR_LOCATION (*expr_p, input_location);
4466 :
4467 : /* Gimplify internal functions created in the FEs. */
4468 16791386 : if (CALL_EXPR_FN (*expr_p) == NULL_TREE)
4469 : {
4470 562161 : enum internal_fn ifn = CALL_EXPR_IFN (*expr_p);
4471 562161 : if (ifn == IFN_GOMP_DISPATCH)
4472 : {
4473 884 : gcc_assert (flag_openmp
4474 : && gimplify_omp_ctxp
4475 : && gimplify_omp_ctxp->code == OMP_DISPATCH);
4476 884 : *expr_p = CALL_EXPR_ARG (*expr_p, 0);
4477 884 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4478 884 : if (! EXPR_HAS_LOCATION (*expr_p))
4479 94 : SET_EXPR_LOCATION (*expr_p, input_location);
4480 : omp_dispatch_p = true;
4481 : }
4482 : else
4483 : {
4484 561277 : if (want_value)
4485 : return GS_ALL_DONE;
4486 :
4487 19478 : nargs = call_expr_nargs (*expr_p);
4488 19478 : auto_vec<tree> vargs (nargs);
4489 :
4490 19478 : if (ifn == IFN_ASSUME)
4491 : {
4492 511 : if (simple_condition_p (CALL_EXPR_ARG (*expr_p, 0)))
4493 : {
4494 : /* If the [[assume (cond)]]; condition is simple
4495 : enough and can be evaluated unconditionally
4496 : without side-effects, expand it as
4497 : if (!cond) __builtin_unreachable (); */
4498 293 : tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
4499 293 : *expr_p
4500 586 : = build3 (COND_EXPR, void_type_node,
4501 293 : CALL_EXPR_ARG (*expr_p, 0), void_node,
4502 293 : build_call_expr_loc (EXPR_LOCATION (*expr_p),
4503 : fndecl, 0));
4504 293 : return GS_OK;
4505 : }
4506 : /* If not optimizing, ignore the assumptions unless there
4507 : are used user labels in it. */
4508 218 : if ((!optimize
4509 98 : && !walk_tree_without_duplicates (&CALL_EXPR_ARG (*expr_p,
4510 : 0),
4511 : find_used_user_labels,
4512 : NULL))
4513 233 : || seen_error ())
4514 : {
4515 94 : *expr_p = NULL_TREE;
4516 94 : return GS_ALL_DONE;
4517 : }
4518 : /* Temporarily, until gimple lowering, transform
4519 : .ASSUME (cond);
4520 : into:
4521 : [[assume (guard)]]
4522 : {
4523 : guard = cond;
4524 : }
4525 : such that gimple lowering can outline the condition into
4526 : a separate function easily. */
4527 124 : tree guard = create_tmp_var (boolean_type_node);
4528 124 : *expr_p = build2 (MODIFY_EXPR, void_type_node, guard,
4529 124 : gimple_boolify (CALL_EXPR_ARG (*expr_p, 0)));
4530 124 : *expr_p = build3 (BIND_EXPR, void_type_node, NULL, *expr_p, NULL);
4531 124 : push_gimplify_context ();
4532 124 : gimple_seq body = NULL;
4533 124 : gimple *g = gimplify_and_return_first (*expr_p, &body);
4534 124 : pop_gimplify_context (g);
4535 124 : g = gimple_build_assume (guard, body);
4536 124 : gimple_set_location (g, loc);
4537 124 : gimplify_seq_add_stmt (pre_p, g);
4538 124 : *expr_p = NULL_TREE;
4539 124 : return GS_ALL_DONE;
4540 : }
4541 18967 : else if (ifn == IFN_UBSAN_BOUNDS
4542 18967 : && nargs == 3
4543 18967 : && integer_onep (CALL_EXPR_ARG (*expr_p, 0)))
4544 : {
4545 : /* If first argument is one, add TYPE_MAX_VALUE (TYPE_DOMAIN (t))
4546 : to 3rd argument and change first argument to 0. This is
4547 : done by ubsan_instrument_bounds so that we can use the
4548 : max value from gimplify_type_sizes here instead of original
4549 : expression for VLAs. */
4550 406 : tree type = TREE_TYPE (CALL_EXPR_ARG (*expr_p, 0));
4551 406 : CALL_EXPR_ARG (*expr_p, 0) = build_int_cst (type, 0);
4552 406 : gcc_assert (TREE_CODE (type) == POINTER_TYPE);
4553 406 : type = TREE_TYPE (type);
4554 406 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4555 406 : tree maxv = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4556 406 : gcc_assert (maxv);
4557 406 : tree arg3 = CALL_EXPR_ARG (*expr_p, 2);
4558 406 : CALL_EXPR_ARG (*expr_p, 2)
4559 812 : = fold_build2 (PLUS_EXPR, TREE_TYPE (arg3), maxv, arg3);
4560 : }
4561 :
4562 44522 : for (i = 0; i < nargs; i++)
4563 : {
4564 25555 : gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
4565 25555 : EXPR_LOCATION (*expr_p));
4566 25555 : vargs.quick_push (CALL_EXPR_ARG (*expr_p, i));
4567 : }
4568 :
4569 18967 : gcall *call = gimple_build_call_internal_vec (ifn, vargs);
4570 18967 : gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p));
4571 18967 : gimplify_seq_add_stmt (pre_p, call);
4572 18967 : return GS_ALL_DONE;
4573 19478 : }
4574 : }
4575 :
4576 : /* This may be a call to a builtin function.
4577 :
4578 : Builtin function calls may be transformed into different
4579 : (and more efficient) builtin function calls under certain
4580 : circumstances. Unfortunately, gimplification can muck things
4581 : up enough that the builtin expanders are not aware that certain
4582 : transformations are still valid.
4583 :
4584 : So we attempt transformation/gimplification of the call before
4585 : we gimplify the CALL_EXPR. At this time we do not manage to
4586 : transform all calls in the same manner as the expanders do, but
4587 : we do transform most of them. */
4588 16230109 : fndecl = get_callee_fndecl (*expr_p);
4589 16230109 : if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
4590 3952603 : switch (DECL_FUNCTION_CODE (fndecl))
4591 : {
4592 94786 : CASE_BUILT_IN_ALLOCA:
4593 : /* If the call has been built for a variable-sized object, then we
4594 : want to restore the stack level when the enclosing BIND_EXPR is
4595 : exited to reclaim the allocated space; otherwise, we precisely
4596 : need to do the opposite and preserve the latest stack level. */
4597 94786 : if (CALL_ALLOCA_FOR_VAR_P (*expr_p))
4598 8965 : gimplify_ctxp->save_stack = true;
4599 : else
4600 85821 : gimplify_ctxp->keep_stack = true;
4601 : break;
4602 :
4603 20800 : case BUILT_IN_VA_START:
4604 20800 : {
4605 20800 : builtin_va_start_p = true;
4606 20800 : if (call_expr_nargs (*expr_p) < 2)
4607 : {
4608 1 : error ("too few arguments to function %<va_start%>");
4609 1 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4610 1 : return GS_OK;
4611 : }
4612 :
4613 20799 : if (fold_builtin_next_arg (*expr_p, true))
4614 : {
4615 8 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4616 8 : return GS_OK;
4617 : }
4618 : break;
4619 : }
4620 :
4621 30 : case BUILT_IN_EH_RETURN:
4622 30 : cfun->calls_eh_return = true;
4623 30 : break;
4624 :
4625 1030 : case BUILT_IN_CLEAR_PADDING:
4626 1030 : if (call_expr_nargs (*expr_p) == 1)
4627 : {
4628 : /* Remember the original type of the argument in an internal
4629 : dummy second argument, as in GIMPLE pointer conversions are
4630 : useless. Also mark this call as not for automatic
4631 : initialization in the internal dummy third argument. */
4632 515 : p = CALL_EXPR_ARG (*expr_p, 0);
4633 515 : *expr_p
4634 515 : = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
4635 515 : build_zero_cst (TREE_TYPE (p)));
4636 515 : return GS_OK;
4637 : }
4638 : break;
4639 :
4640 : default:
4641 : ;
4642 : }
4643 16229585 : if (fndecl && fndecl_built_in_p (fndecl))
4644 : {
4645 4187376 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4646 4187376 : if (new_tree && new_tree != *expr_p)
4647 : {
4648 : /* There was a transformation of this call which computes the
4649 : same value, but in a more efficient way. Return and try
4650 : again. */
4651 717 : *expr_p = new_tree;
4652 717 : return GS_OK;
4653 : }
4654 : }
4655 :
4656 : /* Remember the original function pointer type. */
4657 16228868 : fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
4658 :
4659 : /* Handle "declare variant" resolution and arglist processing. */
4660 16228868 : if (flag_openmp
4661 447285 : && fndecl
4662 446604 : && cfun
4663 446604 : && (cfun->curr_properties & PROP_gimple_any) == 0
4664 249507 : && !omp_has_novariants ()
4665 16478263 : && lookup_attribute ("omp declare variant base",
4666 249395 : DECL_ATTRIBUTES (fndecl)))
4667 : {
4668 1326 : tree orig = *expr_p;
4669 1326 : *expr_p = gimplify_variant_call_expr (*expr_p, fallback,
4670 : omp_dispatch_p);
4671 :
4672 : /* This may resolve to the same call, or the call expr with just
4673 : the function replaced, in which case we should just continue to
4674 : gimplify it normally. Otherwise, if we get something else back,
4675 : stop here and re-gimplify the whole replacement expr. */
4676 1326 : if (*expr_p != orig)
4677 : return GS_OK;
4678 : }
4679 :
4680 : /* There is a sequence point before the call, so any side effects in
4681 : the calling expression must occur before the actual call. Force
4682 : gimplify_expr to use an internal post queue. */
4683 16228379 : ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
4684 : is_gimple_call_addr, fb_rvalue);
4685 :
4686 16228379 : if (ret == GS_ERROR)
4687 : return GS_ERROR;
4688 :
4689 16228377 : nargs = call_expr_nargs (*expr_p);
4690 :
4691 : /* Get argument types for verification. */
4692 16228377 : fndecl = get_callee_fndecl (*expr_p);
4693 16228377 : parms = NULL_TREE;
4694 16228377 : if (fndecl)
4695 16007042 : parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
4696 : else
4697 221335 : parms = TYPE_ARG_TYPES (TREE_TYPE (fnptrtype));
4698 :
4699 32235419 : if (fndecl && DECL_ARGUMENTS (fndecl))
4700 : p = DECL_ARGUMENTS (fndecl);
4701 7317524 : else if (parms)
4702 : p = parms;
4703 : else
4704 : p = NULL_TREE;
4705 43078723 : for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
4706 : ;
4707 :
4708 : /* If the last argument is __builtin_va_arg_pack () and it is not
4709 : passed as a named argument, decrease the number of CALL_EXPR
4710 : arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */
4711 16228377 : if (!p
4712 16228377 : && i < nargs
4713 16228377 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR)
4714 : {
4715 5931 : tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1);
4716 5931 : tree last_arg_fndecl = get_callee_fndecl (last_arg);
4717 :
4718 5931 : if (last_arg_fndecl
4719 5931 : && fndecl_built_in_p (last_arg_fndecl, BUILT_IN_VA_ARG_PACK))
4720 : {
4721 131 : tree call = *expr_p;
4722 :
4723 131 : --nargs;
4724 262 : *expr_p = build_call_array_loc (loc, TREE_TYPE (call),
4725 131 : CALL_EXPR_FN (call),
4726 131 : nargs, CALL_EXPR_ARGP (call));
4727 :
4728 : /* Copy all CALL_EXPR flags, location and block, except
4729 : CALL_EXPR_VA_ARG_PACK flag. */
4730 131 : CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call);
4731 131 : CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call);
4732 131 : CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
4733 131 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4734 131 : CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
4735 131 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
4736 :
4737 : /* Set CALL_EXPR_VA_ARG_PACK. */
4738 131 : CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
4739 : }
4740 : }
4741 :
4742 : /* If the call returns twice then after building the CFG the call
4743 : argument computations will no longer dominate the call because
4744 : we add an abnormal incoming edge to the call. So do not use SSA
4745 : vars there. */
4746 16228377 : bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE;
4747 :
4748 :
4749 : /* Gimplify the function arguments. */
4750 16228377 : if (nargs > 0)
4751 : {
4752 14059817 : for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
4753 42346012 : PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
4754 28286195 : PUSH_ARGS_REVERSED ? i-- : i++)
4755 : {
4756 28286195 : enum gimplify_status t;
4757 :
4758 : /* Avoid gimplifying the second argument to va_start, which needs to
4759 : be the plain PARM_DECL. */
4760 28286195 : if ((i != 1) || !builtin_va_start_p)
4761 : {
4762 28265404 : tree *arg_p = &CALL_EXPR_ARG (*expr_p, i);
4763 :
4764 28265404 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4765 6687 : gimplify_omp_ctxp->in_call_args = true;
4766 28265404 : t = gimplify_arg (arg_p, pre_p, EXPR_LOCATION (*expr_p),
4767 28265404 : !returns_twice);
4768 28265404 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4769 6687 : gimplify_omp_ctxp->in_call_args = false;
4770 :
4771 28265404 : if (t == GS_ERROR)
4772 28286195 : ret = GS_ERROR;
4773 : }
4774 : }
4775 : }
4776 :
4777 : /* Gimplify the static chain. */
4778 16228377 : if (CALL_EXPR_STATIC_CHAIN (*expr_p))
4779 : {
4780 28852 : if (fndecl && !DECL_STATIC_CHAIN (fndecl))
4781 3 : CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL;
4782 : else
4783 : {
4784 28173 : enum gimplify_status t;
4785 28173 : t = gimplify_arg (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p,
4786 28173 : EXPR_LOCATION (*expr_p), ! returns_twice);
4787 28173 : if (t == GS_ERROR)
4788 16228377 : ret = GS_ERROR;
4789 : }
4790 : }
4791 :
4792 : /* Verify the function result. */
4793 16228377 : if (want_value && fndecl
4794 16228377 : && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
4795 : {
4796 0 : error_at (loc, "using result of function returning %<void%>");
4797 0 : ret = GS_ERROR;
4798 : }
4799 :
4800 : /* Try this again in case gimplification exposed something. */
4801 16228377 : if (ret != GS_ERROR)
4802 : {
4803 16228229 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4804 :
4805 16228229 : if (new_tree && new_tree != *expr_p)
4806 : {
4807 : /* There was a transformation of this call which computes the
4808 : same value, but in a more efficient way. Return and try
4809 : again. */
4810 11513 : *expr_p = new_tree;
4811 11513 : return GS_OK;
4812 : }
4813 : }
4814 : else
4815 : {
4816 148 : *expr_p = error_mark_node;
4817 148 : return GS_ERROR;
4818 : }
4819 :
4820 : /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
4821 : decl. This allows us to eliminate redundant or useless
4822 : calls to "const" functions. */
4823 16216716 : if (TREE_CODE (*expr_p) == CALL_EXPR)
4824 : {
4825 16216716 : int flags = call_expr_flags (*expr_p);
4826 16216716 : if (flags & (ECF_CONST | ECF_PURE)
4827 : /* An infinite loop is considered a side effect. */
4828 2451679 : && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
4829 2073311 : TREE_SIDE_EFFECTS (*expr_p) = 0;
4830 : }
4831 :
4832 : /* If the value is not needed by the caller, emit a new GIMPLE_CALL
4833 : and clear *EXPR_P. Otherwise, leave *EXPR_P in its gimplified
4834 : form and delegate the creation of a GIMPLE_CALL to
4835 : gimplify_modify_expr. This is always possible because when
4836 : WANT_VALUE is true, the caller wants the result of this call into
4837 : a temporary, which means that we will emit an INIT_EXPR in
4838 : internal_get_tmp_var which will then be handled by
4839 : gimplify_modify_expr. */
4840 16216716 : if (!want_value)
4841 : {
4842 : /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
4843 : have to do is replicate it as a GIMPLE_CALL tuple. */
4844 6192218 : gimple_stmt_iterator gsi;
4845 6192218 : call = gimple_build_call_from_tree (*expr_p, fnptrtype);
4846 6192218 : notice_special_calls (call);
4847 6192218 : gimplify_seq_add_stmt (pre_p, call);
4848 6192218 : gsi = gsi_last (*pre_p);
4849 6192218 : maybe_fold_stmt (&gsi);
4850 6192218 : *expr_p = NULL_TREE;
4851 : }
4852 : else
4853 : /* Remember the original function type. */
4854 10024498 : CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
4855 10024498 : CALL_EXPR_FN (*expr_p));
4856 :
4857 : return ret;
4858 : }
4859 :
4860 : /* Handle shortcut semantics in the predicate operand of a COND_EXPR by
4861 : rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs.
4862 :
4863 : TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the
4864 : condition is true or false, respectively. If null, we should generate
4865 : our own to skip over the evaluation of this specific expression.
4866 :
4867 : LOCUS is the source location of the COND_EXPR.
4868 :
4869 : The condition_uid is a discriminator tag for condition coverage used to map
4870 : conditions to its corresponding full Boolean function.
4871 :
4872 : This function is the tree equivalent of do_jump.
4873 :
4874 : shortcut_cond_r should only be called by shortcut_cond_expr. */
4875 :
4876 : static tree
4877 1309906 : shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
4878 : location_t locus, unsigned condition_uid)
4879 : {
4880 1309906 : tree local_label = NULL_TREE;
4881 1309906 : tree t, expr = NULL;
4882 :
4883 : /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
4884 : retain the shortcut semantics. Just insert the gotos here;
4885 : shortcut_cond_expr will append the real blocks later. */
4886 1309906 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
4887 : {
4888 121387 : location_t new_locus;
4889 :
4890 : /* Turn if (a && b) into
4891 :
4892 : if (a); else goto no;
4893 : if (b) goto yes; else goto no;
4894 : (no:) */
4895 :
4896 121387 : if (false_label_p == NULL)
4897 3978 : false_label_p = &local_label;
4898 :
4899 : /* Keep the original source location on the first 'if'. */
4900 121387 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus,
4901 : condition_uid);
4902 121387 : append_to_statement_list (t, &expr);
4903 :
4904 : /* Set the source location of the && on the second 'if'. */
4905 121387 : new_locus = rexpr_location (pred, locus);
4906 121387 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4907 : new_locus, condition_uid);
4908 121387 : append_to_statement_list (t, &expr);
4909 : }
4910 1188519 : else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
4911 : {
4912 380722 : location_t new_locus;
4913 :
4914 : /* Turn if (a || b) into
4915 :
4916 : if (a) goto yes;
4917 : if (b) goto yes; else goto no;
4918 : (yes:) */
4919 :
4920 380722 : if (true_label_p == NULL)
4921 227709 : true_label_p = &local_label;
4922 :
4923 : /* Keep the original source location on the first 'if'. */
4924 380722 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus,
4925 : condition_uid);
4926 380722 : append_to_statement_list (t, &expr);
4927 :
4928 : /* Set the source location of the || on the second 'if'. */
4929 380722 : new_locus = rexpr_location (pred, locus);
4930 380722 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4931 : new_locus, condition_uid);
4932 380722 : append_to_statement_list (t, &expr);
4933 : }
4934 807797 : else if (TREE_CODE (pred) == COND_EXPR
4935 856 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
4936 808653 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
4937 : {
4938 850 : location_t new_locus;
4939 :
4940 : /* As long as we're messing with gotos, turn if (a ? b : c) into
4941 : if (a)
4942 : if (b) goto yes; else goto no;
4943 : else
4944 : if (c) goto yes; else goto no;
4945 :
4946 : Don't do this if one of the arms has void type, which can happen
4947 : in C++ when the arm is throw. */
4948 :
4949 : /* Keep the original source location on the first 'if'. Set the source
4950 : location of the ? on the second 'if'. */
4951 850 : new_locus = rexpr_location (pred, locus);
4952 1700 : expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
4953 850 : shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
4954 : false_label_p, locus, condition_uid),
4955 850 : shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
4956 : false_label_p, new_locus,
4957 : condition_uid));
4958 850 : tree_associate_condition_with_expr (expr, condition_uid);
4959 : }
4960 : else
4961 : {
4962 806947 : expr = build3 (COND_EXPR, void_type_node, pred,
4963 : build_and_jump (true_label_p),
4964 : build_and_jump (false_label_p));
4965 806947 : SET_EXPR_LOCATION (expr, locus);
4966 806947 : tree_associate_condition_with_expr (expr, condition_uid);
4967 : }
4968 :
4969 1309906 : if (local_label)
4970 : {
4971 231687 : t = build1 (LABEL_EXPR, void_type_node, local_label);
4972 231687 : append_to_statement_list (t, &expr);
4973 : }
4974 :
4975 1309906 : return expr;
4976 : }
4977 :
4978 : /* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip
4979 : any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
4980 : statement, if it is the last one. Otherwise, return NULL. */
4981 :
4982 : static tree
4983 11472354 : find_goto (tree expr)
4984 : {
4985 11800967 : if (!expr)
4986 : return NULL_TREE;
4987 :
4988 9860405 : if (TREE_CODE (expr) == GOTO_EXPR)
4989 : return expr;
4990 :
4991 7876061 : if (TREE_CODE (expr) != STATEMENT_LIST)
4992 : return NULL_TREE;
4993 :
4994 1028652 : tree_stmt_iterator i = tsi_start (expr);
4995 :
4996 1386211 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
4997 357559 : tsi_next (&i);
4998 :
4999 10416351 : if (!tsi_one_before_end_p (i))
5000 : return NULL_TREE;
5001 :
5002 328613 : return find_goto (tsi_stmt (i));
5003 : }
5004 :
5005 : /* Same as find_goto, except that it returns NULL if the destination
5006 : is not a LABEL_DECL. */
5007 :
5008 : static inline tree
5009 11472354 : find_goto_label (tree expr)
5010 : {
5011 11472354 : tree dest = find_goto (expr);
5012 13456698 : if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
5013 1984233 : return dest;
5014 : return NULL_TREE;
5015 : }
5016 :
5017 :
5018 : /* Given a multi-term condition (ANDIF, ORIF), walk the predicate PRED and tag
5019 : every basic condition with CONDITION_UID. Two basic conditions share the
5020 : CONDITION_UID discriminator when they belong to the same predicate, which is
5021 : used by the condition coverage. Doing this as an explicit step makes for a
5022 : simpler implementation than weaving it into the splitting code as the
5023 : splitting code eventually calls the entry point gimplfiy_expr which makes
5024 : bookkeeping complicated. */
5025 : static void
5026 565602 : tag_shortcut_cond (tree pred, unsigned condition_uid)
5027 : {
5028 604433 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR
5029 604433 : || TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5030 : {
5031 555327 : tree fst = TREE_OPERAND (pred, 0);
5032 555327 : tree lst = TREE_OPERAND (pred, 1);
5033 :
5034 555327 : if (TREE_CODE (fst) == TRUTH_ANDIF_EXPR
5035 555327 : || TREE_CODE (fst) == TRUTH_ORIF_EXPR)
5036 167031 : tag_shortcut_cond (fst, condition_uid);
5037 388296 : else if (TREE_CODE (fst) == COND_EXPR)
5038 244 : tree_associate_condition_with_expr (fst, condition_uid);
5039 :
5040 555327 : if (TREE_CODE (lst) == TRUTH_ANDIF_EXPR
5041 555327 : || TREE_CODE (lst) == TRUTH_ORIF_EXPR)
5042 : tag_shortcut_cond (lst, condition_uid);
5043 516496 : else if (TREE_CODE (lst) == COND_EXPR)
5044 446 : tree_associate_condition_with_expr (lst, condition_uid);
5045 : }
5046 565602 : }
5047 :
5048 : /* Given a conditional expression EXPR with short-circuit boolean
5049 : predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
5050 : predicate apart into the equivalent sequence of conditionals. CONDITION_UID
5051 : is a the tag/discriminator for this EXPR - all basic conditions in the
5052 : expression will be given the same CONDITION_UID. */
5053 : static tree
5054 398571 : shortcut_cond_expr (tree expr, unsigned condition_uid)
5055 : {
5056 398571 : tree pred = TREE_OPERAND (expr, 0);
5057 398571 : tree then_ = TREE_OPERAND (expr, 1);
5058 398571 : tree else_ = TREE_OPERAND (expr, 2);
5059 398571 : tree true_label, false_label, end_label, t;
5060 398571 : tree *true_label_p;
5061 398571 : tree *false_label_p;
5062 398571 : bool emit_end, emit_false, jump_over_else;
5063 398571 : bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
5064 398571 : bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
5065 :
5066 398571 : tag_shortcut_cond (pred, condition_uid);
5067 :
5068 : /* First do simple transformations. */
5069 398571 : if (!else_se)
5070 : {
5071 : /* If there is no 'else', turn
5072 : if (a && b) then c
5073 : into
5074 : if (a) if (b) then c. */
5075 287906 : while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
5076 : {
5077 : /* Keep the original source location on the first 'if'. */
5078 49997 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5079 49997 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5080 : /* Set the source location of the && on the second 'if'. */
5081 49997 : if (rexpr_has_location (pred))
5082 48977 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5083 49997 : then_ = shortcut_cond_expr (expr, condition_uid);
5084 49997 : then_se = then_ && TREE_SIDE_EFFECTS (then_);
5085 49997 : pred = TREE_OPERAND (pred, 0);
5086 49997 : expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
5087 49997 : SET_EXPR_LOCATION (expr, locus);
5088 : }
5089 : }
5090 :
5091 398571 : if (!then_se)
5092 : {
5093 : /* If there is no 'then', turn
5094 : if (a || b); else d
5095 : into
5096 : if (a); else if (b); else d. */
5097 25281 : while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5098 : {
5099 : /* Keep the original source location on the first 'if'. */
5100 795 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5101 795 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5102 : /* Set the source location of the || on the second 'if'. */
5103 795 : if (rexpr_has_location (pred))
5104 794 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5105 795 : else_ = shortcut_cond_expr (expr, condition_uid);
5106 795 : else_se = else_ && TREE_SIDE_EFFECTS (else_);
5107 795 : pred = TREE_OPERAND (pred, 0);
5108 795 : expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
5109 795 : SET_EXPR_LOCATION (expr, locus);
5110 : }
5111 : }
5112 :
5113 : /* The expr tree should also have the expression id set. */
5114 398571 : tree_associate_condition_with_expr (expr, condition_uid);
5115 :
5116 : /* If we're done, great. */
5117 398571 : if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR
5118 398571 : && TREE_CODE (pred) != TRUTH_ORIF_EXPR)
5119 94583 : return expr;
5120 :
5121 : /* Otherwise we need to mess with gotos. Change
5122 : if (a) c; else d;
5123 : to
5124 : if (a); else goto no;
5125 : c; goto end;
5126 : no: d; end:
5127 : and recursively gimplify the condition. */
5128 :
5129 303988 : true_label = false_label = end_label = NULL_TREE;
5130 :
5131 : /* If our arms just jump somewhere, hijack those labels so we don't
5132 : generate jumps to jumps. */
5133 :
5134 303988 : if (tree then_goto = find_goto_label (then_))
5135 : {
5136 4531 : true_label = GOTO_DESTINATION (then_goto);
5137 4531 : then_ = NULL;
5138 4531 : then_se = false;
5139 : }
5140 :
5141 303988 : if (tree else_goto = find_goto_label (else_))
5142 : {
5143 4124 : false_label = GOTO_DESTINATION (else_goto);
5144 4124 : else_ = NULL;
5145 4124 : else_se = false;
5146 : }
5147 :
5148 : /* If we aren't hijacking a label for the 'then' branch, it falls through. */
5149 303988 : if (true_label)
5150 : true_label_p = &true_label;
5151 : else
5152 299457 : true_label_p = NULL;
5153 :
5154 : /* The 'else' branch also needs a label if it contains interesting code. */
5155 303988 : if (false_label || else_se)
5156 : false_label_p = &false_label;
5157 : else
5158 : false_label_p = NULL;
5159 :
5160 : /* If there was nothing else in our arms, just forward the label(s). */
5161 148417 : if (!then_se && !else_se)
5162 8392 : return shortcut_cond_r (pred, true_label_p, false_label_p,
5163 12588 : EXPR_LOC_OR_LOC (expr, input_location), condition_uid);
5164 :
5165 : /* If our last subexpression already has a terminal label, reuse it. */
5166 299792 : if (else_se)
5167 155571 : t = expr_last (else_);
5168 144221 : else if (then_se)
5169 144221 : t = expr_last (then_);
5170 : else
5171 : t = NULL;
5172 299792 : if (t && TREE_CODE (t) == LABEL_EXPR)
5173 997 : end_label = LABEL_EXPR_LABEL (t);
5174 :
5175 : /* If we don't care about jumping to the 'else' branch, jump to the end
5176 : if the condition is false. */
5177 299792 : if (!false_label_p)
5178 143979 : false_label_p = &end_label;
5179 :
5180 : /* We only want to emit these labels if we aren't hijacking them. */
5181 299792 : emit_end = (end_label == NULL_TREE);
5182 299792 : emit_false = (false_label == NULL_TREE);
5183 :
5184 : /* We only emit the jump over the else clause if we have to--if the
5185 : then clause may fall through. Otherwise we can wind up with a
5186 : useless jump and a useless label at the end of gimplified code,
5187 : which will cause us to think that this conditional as a whole
5188 : falls through even if it doesn't. If we then inline a function
5189 : which ends with such a condition, that can cause us to issue an
5190 : inappropriate warning about control reaching the end of a
5191 : non-void function. */
5192 299792 : jump_over_else = block_may_fallthru (then_);
5193 :
5194 598961 : pred = shortcut_cond_r (pred, true_label_p, false_label_p,
5195 598961 : EXPR_LOC_OR_LOC (expr, input_location),
5196 : condition_uid);
5197 :
5198 299792 : expr = NULL;
5199 299792 : append_to_statement_list (pred, &expr);
5200 :
5201 299792 : append_to_statement_list (then_, &expr);
5202 299792 : if (else_se)
5203 : {
5204 155571 : if (jump_over_else)
5205 : {
5206 153160 : tree last = expr_last (expr);
5207 153160 : t = build_and_jump (&end_label);
5208 153160 : if (rexpr_has_location (last))
5209 37107 : SET_EXPR_LOCATION (t, rexpr_location (last));
5210 153160 : append_to_statement_list (t, &expr);
5211 : }
5212 155571 : if (emit_false)
5213 : {
5214 155571 : t = build1 (LABEL_EXPR, void_type_node, false_label);
5215 155571 : append_to_statement_list (t, &expr);
5216 : }
5217 155571 : append_to_statement_list (else_, &expr);
5218 : }
5219 299792 : if (emit_end && end_label)
5220 : {
5221 296147 : t = build1 (LABEL_EXPR, void_type_node, end_label);
5222 296147 : append_to_statement_list (t, &expr);
5223 : }
5224 :
5225 299792 : return expr;
5226 : }
5227 :
5228 : /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */
5229 :
5230 : tree
5231 16387791 : gimple_boolify (tree expr)
5232 : {
5233 16387791 : tree type = TREE_TYPE (expr);
5234 16387791 : location_t loc = EXPR_LOCATION (expr);
5235 :
5236 16387791 : if (TREE_CODE (expr) == NE_EXPR
5237 5672112 : && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
5238 17327602 : && integer_zerop (TREE_OPERAND (expr, 1)))
5239 : {
5240 486903 : tree call = TREE_OPERAND (expr, 0);
5241 486903 : tree fn = get_callee_fndecl (call);
5242 :
5243 : /* For __builtin_expect ((long) (x), y) recurse into x as well
5244 : if x is truth_value_p. */
5245 486903 : if (fn
5246 485932 : && fndecl_built_in_p (fn, BUILT_IN_EXPECT)
5247 621374 : && call_expr_nargs (call) == 2)
5248 : {
5249 134471 : tree arg = CALL_EXPR_ARG (call, 0);
5250 134471 : if (arg)
5251 : {
5252 134471 : if (TREE_CODE (arg) == NOP_EXPR
5253 134471 : && TREE_TYPE (arg) == TREE_TYPE (call))
5254 63221 : arg = TREE_OPERAND (arg, 0);
5255 134471 : if (truth_value_p (TREE_CODE (arg)))
5256 : {
5257 111353 : arg = gimple_boolify (arg);
5258 111353 : CALL_EXPR_ARG (call, 0)
5259 222706 : = fold_convert_loc (loc, TREE_TYPE (call), arg);
5260 : }
5261 : }
5262 : }
5263 : }
5264 :
5265 16387791 : switch (TREE_CODE (expr))
5266 : {
5267 1217864 : case TRUTH_AND_EXPR:
5268 1217864 : case TRUTH_OR_EXPR:
5269 1217864 : case TRUTH_XOR_EXPR:
5270 1217864 : case TRUTH_ANDIF_EXPR:
5271 1217864 : case TRUTH_ORIF_EXPR:
5272 : /* Also boolify the arguments of truth exprs. */
5273 1217864 : TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
5274 : /* FALLTHRU */
5275 :
5276 1638511 : case TRUTH_NOT_EXPR:
5277 1638511 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5278 :
5279 : /* These expressions always produce boolean results. */
5280 1638511 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5281 305846 : TREE_TYPE (expr) = boolean_type_node;
5282 : return expr;
5283 :
5284 5243 : case ANNOTATE_EXPR:
5285 5243 : switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)))
5286 : {
5287 5243 : case annot_expr_ivdep_kind:
5288 5243 : case annot_expr_unroll_kind:
5289 5243 : case annot_expr_no_vector_kind:
5290 5243 : case annot_expr_vector_kind:
5291 5243 : case annot_expr_parallel_kind:
5292 5243 : case annot_expr_maybe_infinite_kind:
5293 5243 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5294 5243 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5295 3323 : TREE_TYPE (expr) = boolean_type_node;
5296 : return expr;
5297 0 : default:
5298 0 : gcc_unreachable ();
5299 : }
5300 :
5301 14744037 : default:
5302 14744037 : if (COMPARISON_CLASS_P (expr))
5303 : {
5304 : /* These expressions always produce boolean results. */
5305 12895987 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5306 1580682 : TREE_TYPE (expr) = boolean_type_node;
5307 12895987 : return expr;
5308 : }
5309 : /* Other expressions that get here must have boolean values, but
5310 : might need to be converted to the appropriate mode. */
5311 1848050 : if (TREE_CODE (type) == BOOLEAN_TYPE)
5312 : return expr;
5313 202020 : return fold_convert_loc (loc, boolean_type_node, expr);
5314 : }
5315 : }
5316 :
5317 : /* Given a conditional expression *EXPR_P without side effects, gimplify
5318 : its operands. New statements are inserted to PRE_P. */
5319 :
5320 : static enum gimplify_status
5321 46251 : gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
5322 : {
5323 46251 : tree expr = *expr_p, cond;
5324 46251 : enum gimplify_status ret, tret;
5325 46251 : enum tree_code code;
5326 :
5327 46251 : cond = gimple_boolify (COND_EXPR_COND (expr));
5328 :
5329 : /* We need to handle && and || specially, as their gimplification
5330 : creates pure cond_expr, thus leading to an infinite cycle otherwise. */
5331 46251 : code = TREE_CODE (cond);
5332 46251 : if (code == TRUTH_ANDIF_EXPR)
5333 33 : TREE_SET_CODE (cond, TRUTH_AND_EXPR);
5334 46218 : else if (code == TRUTH_ORIF_EXPR)
5335 4640 : TREE_SET_CODE (cond, TRUTH_OR_EXPR);
5336 46251 : ret = gimplify_expr (&cond, pre_p, NULL, is_gimple_val, fb_rvalue);
5337 46251 : COND_EXPR_COND (*expr_p) = cond;
5338 :
5339 46251 : tret = gimplify_expr (&COND_EXPR_THEN (expr), pre_p, NULL,
5340 : is_gimple_val, fb_rvalue);
5341 46251 : ret = MIN (ret, tret);
5342 46251 : tret = gimplify_expr (&COND_EXPR_ELSE (expr), pre_p, NULL,
5343 : is_gimple_val, fb_rvalue);
5344 :
5345 46251 : return MIN (ret, tret);
5346 : }
5347 :
5348 : /* Return true if evaluating EXPR could trap.
5349 : EXPR is GENERIC, while tree_could_trap_p can be called
5350 : only on GIMPLE. */
5351 :
5352 : bool
5353 16070717 : generic_expr_could_trap_p (tree expr)
5354 : {
5355 16070717 : unsigned i, n;
5356 :
5357 16070717 : if (!expr || is_gimple_val (expr))
5358 7175630 : return false;
5359 :
5360 8895087 : if (!EXPR_P (expr) || tree_could_trap_p (expr))
5361 2340520 : return true;
5362 :
5363 6554567 : n = TREE_OPERAND_LENGTH (expr);
5364 15795054 : for (i = 0; i < n; i++)
5365 11419934 : if (generic_expr_could_trap_p (TREE_OPERAND (expr, i)))
5366 : return true;
5367 :
5368 : return false;
5369 : }
5370 :
5371 : /* Associate the condition STMT with the discriminator UID. STMTs that are
5372 : broken down with ANDIF/ORIF from the same Boolean expression should be given
5373 : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
5374 : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
5375 : for condition coverage. */
5376 : static void
5377 5432189 : gimple_associate_condition_with_expr (struct function *fn, gcond *stmt,
5378 : unsigned uid)
5379 : {
5380 5432189 : if (!condition_coverage_flag)
5381 : return;
5382 :
5383 641 : if (!fn->cond_uids)
5384 139 : fn->cond_uids = new hash_map <gcond*, unsigned> ();
5385 :
5386 641 : fn->cond_uids->put (stmt, uid);
5387 : }
5388 :
5389 : /* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
5390 : into
5391 :
5392 : if (p) if (p)
5393 : t1 = a; a;
5394 : else or else
5395 : t1 = b; b;
5396 : t1;
5397 :
5398 : The second form is used when *EXPR_P is of type void.
5399 :
5400 : PRE_P points to the list where side effects that must happen before
5401 : *EXPR_P should be stored. */
5402 :
5403 : static enum gimplify_status
5404 6195772 : gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
5405 : {
5406 6195772 : tree expr = *expr_p;
5407 6195772 : tree type = TREE_TYPE (expr);
5408 6195772 : location_t loc = EXPR_LOCATION (expr);
5409 6195772 : tree tmp, arm1, arm2;
5410 6195772 : enum gimplify_status ret;
5411 6195772 : tree label_true, label_false, label_cont;
5412 6195772 : bool have_then_clause_p, have_else_clause_p;
5413 6195772 : gcond *cond_stmt;
5414 6195772 : enum tree_code pred_code;
5415 6195772 : gimple_seq seq = NULL;
5416 :
5417 : /* If this COND_EXPR has a value, copy the values into a temporary within
5418 : the arms. */
5419 6195772 : if (!VOID_TYPE_P (type))
5420 : {
5421 415034 : tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
5422 415034 : tree result;
5423 :
5424 : /* If either an rvalue is ok or we do not require an lvalue, create the
5425 : temporary. But we cannot do that if the type is addressable. */
5426 415034 : if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
5427 415027 : && !TREE_ADDRESSABLE (type))
5428 : {
5429 415027 : if (gimplify_ctxp->allow_rhs_cond_expr
5430 : /* If either branch has side effects or could trap, it can't be
5431 : evaluated unconditionally. */
5432 46251 : && !TREE_SIDE_EFFECTS (then_)
5433 46251 : && !generic_expr_could_trap_p (then_)
5434 46251 : && !TREE_SIDE_EFFECTS (else_)
5435 461278 : && !generic_expr_could_trap_p (else_))
5436 46251 : return gimplify_pure_cond_expr (expr_p, pre_p);
5437 :
5438 368776 : tmp = create_tmp_var (type, "iftmp");
5439 368776 : result = tmp;
5440 : }
5441 :
5442 : /* Otherwise, only create and copy references to the values. */
5443 : else
5444 : {
5445 7 : type = build_pointer_type (type);
5446 :
5447 7 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5448 7 : then_ = build_fold_addr_expr_loc (loc, then_);
5449 :
5450 7 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5451 7 : else_ = build_fold_addr_expr_loc (loc, else_);
5452 :
5453 7 : expr
5454 7 : = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
5455 :
5456 7 : tmp = create_tmp_var (type, "iftmp");
5457 7 : result = build_simple_mem_ref_loc (loc, tmp);
5458 : }
5459 :
5460 : /* Build the new then clause, `tmp = then_;'. But don't build the
5461 : assignment if the value is void; in C++ it can be if it's a throw. */
5462 368783 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5463 287223 : TREE_OPERAND (expr, 1) = build2 (INIT_EXPR, type, tmp, then_);
5464 :
5465 : /* Similarly, build the new else clause, `tmp = else_;'. */
5466 368783 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5467 358156 : TREE_OPERAND (expr, 2) = build2 (INIT_EXPR, type, tmp, else_);
5468 :
5469 368783 : TREE_TYPE (expr) = void_type_node;
5470 368783 : recalculate_side_effects (expr);
5471 :
5472 : /* Move the COND_EXPR to the prequeue. */
5473 368783 : gimplify_stmt (&expr, pre_p);
5474 :
5475 368783 : *expr_p = result;
5476 368783 : return GS_ALL_DONE;
5477 : }
5478 :
5479 : /* Remove any COMPOUND_EXPR so the following cases will be caught. */
5480 5795669 : STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
5481 5780738 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
5482 80958 : gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
5483 :
5484 : /* Make sure the condition has BOOLEAN_TYPE. */
5485 5780738 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5486 :
5487 : /* Break apart && and || conditions. */
5488 5780738 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
5489 5780738 : || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
5490 : {
5491 347779 : expr = shortcut_cond_expr (expr, next_cond_uid ());
5492 :
5493 347779 : if (expr != *expr_p)
5494 : {
5495 347779 : *expr_p = expr;
5496 :
5497 : /* We can't rely on gimplify_expr to re-gimplify the expanded
5498 : form properly, as cleanups might cause the target labels to be
5499 : wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to
5500 : set up a conditional context. */
5501 347779 : gimple_push_condition ();
5502 347779 : gimplify_stmt (expr_p, &seq);
5503 347779 : gimple_pop_condition (pre_p);
5504 347779 : gimple_seq_add_seq (pre_p, seq);
5505 :
5506 347779 : return GS_ALL_DONE;
5507 : }
5508 : }
5509 :
5510 : /* Now do the normal gimplification. */
5511 :
5512 : /* Gimplify condition. */
5513 5432959 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
5514 : is_gimple_condexpr_for_cond, fb_rvalue);
5515 5432959 : if (ret == GS_ERROR)
5516 : return GS_ERROR;
5517 5432189 : gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
5518 :
5519 5432189 : gimple_push_condition ();
5520 :
5521 5432189 : have_then_clause_p = have_else_clause_p = false;
5522 5432189 : label_true = find_goto_label (TREE_OPERAND (expr, 1));
5523 5432189 : if (label_true
5524 1265646 : && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
5525 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5526 : have different locations, otherwise we end up with incorrect
5527 : location information on the branches. */
5528 6697835 : && (optimize
5529 227124 : || !EXPR_HAS_LOCATION (expr)
5530 200311 : || !rexpr_has_location (label_true)
5531 68611 : || EXPR_LOCATION (expr) == rexpr_location (label_true)))
5532 : {
5533 1264492 : have_then_clause_p = true;
5534 1264492 : label_true = GOTO_DESTINATION (label_true);
5535 : }
5536 : else
5537 4167697 : label_true = create_artificial_label (UNKNOWN_LOCATION);
5538 5432189 : label_false = find_goto_label (TREE_OPERAND (expr, 2));
5539 5432189 : if (label_false
5540 709932 : && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
5541 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5542 : have different locations, otherwise we end up with incorrect
5543 : location information on the branches. */
5544 6142121 : && (optimize
5545 100529 : || !EXPR_HAS_LOCATION (expr)
5546 99652 : || !rexpr_has_location (label_false)
5547 113 : || EXPR_LOCATION (expr) == rexpr_location (label_false)))
5548 : {
5549 709831 : have_else_clause_p = true;
5550 709831 : label_false = GOTO_DESTINATION (label_false);
5551 : }
5552 : else
5553 4722358 : label_false = create_artificial_label (UNKNOWN_LOCATION);
5554 :
5555 5432189 : unsigned cond_uid = 0;
5556 5432189 : if (cond_uids)
5557 455 : if (unsigned *v = cond_uids->get (expr))
5558 435 : cond_uid = *v;
5559 435 : if (cond_uid == 0)
5560 5431754 : cond_uid = next_cond_uid ();
5561 :
5562 5432189 : gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
5563 : &arm2);
5564 5432189 : cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
5565 : label_false);
5566 5432189 : gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
5567 5432189 : gimple_associate_condition_with_expr (cfun, cond_stmt, cond_uid);
5568 5432189 : copy_warning (cond_stmt, COND_EXPR_COND (expr));
5569 5432189 : gimplify_seq_add_stmt (&seq, cond_stmt);
5570 5432189 : gimple_stmt_iterator gsi = gsi_last (seq);
5571 5432189 : maybe_fold_stmt (&gsi);
5572 :
5573 5432189 : label_cont = NULL_TREE;
5574 5432189 : if (!have_then_clause_p)
5575 : {
5576 : /* For if (...) {} else { code; } put label_true after
5577 : the else block. */
5578 4167697 : if (TREE_OPERAND (expr, 1) == NULL_TREE
5579 195247 : && !have_else_clause_p
5580 4168465 : && TREE_OPERAND (expr, 2) != NULL_TREE)
5581 : {
5582 : /* For if (0) {} else { code; } tell -Wimplicit-fallthrough
5583 : handling that label_cont == label_true can be only reached
5584 : through fallthrough from { code; }. */
5585 768 : if (integer_zerop (COND_EXPR_COND (expr)))
5586 0 : UNUSED_LABEL_P (label_true) = 1;
5587 : label_cont = label_true;
5588 : }
5589 : else
5590 : {
5591 4166929 : bool then_side_effects
5592 4166929 : = (TREE_OPERAND (expr, 1)
5593 4166929 : && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)));
5594 4166929 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
5595 4166929 : have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
5596 : /* For if (...) { code; } else {} or
5597 : if (...) { code; } else goto label; or
5598 : if (...) { code; return; } else { ... }
5599 : label_cont isn't needed. */
5600 4166929 : if (!have_else_clause_p
5601 3971304 : && TREE_OPERAND (expr, 2) != NULL_TREE
5602 6922166 : && gimple_seq_may_fallthru (seq))
5603 : {
5604 1917909 : gimple *g;
5605 1917909 : label_cont = create_artificial_label (UNKNOWN_LOCATION);
5606 :
5607 : /* For if (0) { non-side-effect-code } else { code }
5608 : tell -Wimplicit-fallthrough handling that label_cont can
5609 : be only reached through fallthrough from { code }. */
5610 1917909 : if (integer_zerop (COND_EXPR_COND (expr)))
5611 : {
5612 73295 : UNUSED_LABEL_P (label_true) = 1;
5613 73295 : if (!then_side_effects)
5614 12066 : UNUSED_LABEL_P (label_cont) = 1;
5615 : }
5616 :
5617 1917909 : g = gimple_build_goto (label_cont);
5618 :
5619 : /* GIMPLE_COND's are very low level; they have embedded
5620 : gotos. This particular embedded goto should not be marked
5621 : with the location of the original COND_EXPR, as it would
5622 : correspond to the COND_EXPR's condition, not the ELSE or the
5623 : THEN arms. To avoid marking it with the wrong location, flag
5624 : it as "no location". */
5625 1917909 : gimple_set_do_not_emit_location (g);
5626 :
5627 1917909 : gimplify_seq_add_stmt (&seq, g);
5628 : }
5629 : }
5630 : }
5631 5432189 : if (!have_else_clause_p)
5632 : {
5633 : /* For if (1) { code } or if (1) { code } else { non-side-effect-code }
5634 : tell -Wimplicit-fallthrough handling that label_false can be only
5635 : reached through fallthrough from { code }. */
5636 4722358 : if (integer_nonzerop (COND_EXPR_COND (expr))
5637 4722358 : && (TREE_OPERAND (expr, 2) == NULL_TREE
5638 56750 : || !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2))))
5639 7038 : UNUSED_LABEL_P (label_false) = 1;
5640 4722358 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_false));
5641 4722358 : have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq);
5642 : }
5643 5432189 : if (label_cont)
5644 1918677 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_cont));
5645 :
5646 5432189 : gimple_pop_condition (pre_p);
5647 5432189 : gimple_seq_add_seq (pre_p, seq);
5648 :
5649 5432189 : if (ret == GS_ERROR)
5650 : ; /* Do nothing. */
5651 5432189 : else if (have_then_clause_p || have_else_clause_p)
5652 : ret = GS_ALL_DONE;
5653 : else
5654 : {
5655 : /* Both arms are empty; replace the COND_EXPR with its predicate. */
5656 2763 : expr = TREE_OPERAND (expr, 0);
5657 2763 : gimplify_stmt (&expr, pre_p);
5658 : }
5659 :
5660 5432189 : *expr_p = NULL;
5661 5432189 : return ret;
5662 : }
5663 :
5664 : /* Prepare the node pointed to by EXPR_P, an is_gimple_addressable expression,
5665 : to be marked addressable.
5666 :
5667 : We cannot rely on such an expression being directly markable if a temporary
5668 : has been created by the gimplification. In this case, we create another
5669 : temporary and initialize it with a copy, which will become a store after we
5670 : mark it addressable. This can happen if the front-end passed us something
5671 : that it could not mark addressable yet, like a Fortran pass-by-reference
5672 : parameter (int) floatvar. */
5673 :
5674 : static void
5675 55057824 : prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
5676 : {
5677 60371743 : while (handled_component_p (*expr_p))
5678 5313919 : expr_p = &TREE_OPERAND (*expr_p, 0);
5679 :
5680 : /* Do not allow an SSA name as the temporary. */
5681 55057824 : if (is_gimple_reg (*expr_p))
5682 12014 : *expr_p = internal_get_tmp_var (*expr_p, seq_p, NULL, false, false, true);
5683 55057824 : }
5684 :
5685 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5686 : a call to __builtin_memcpy. */
5687 :
5688 : static enum gimplify_status
5689 1094 : gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
5690 : gimple_seq *seq_p)
5691 : {
5692 1094 : tree t, to, to_ptr, from, from_ptr;
5693 1094 : gcall *gs;
5694 1094 : location_t loc = EXPR_LOCATION (*expr_p);
5695 :
5696 1094 : to = TREE_OPERAND (*expr_p, 0);
5697 1094 : from = TREE_OPERAND (*expr_p, 1);
5698 1094 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to)))
5699 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))));
5700 :
5701 : /* Mark the RHS addressable. Beware that it may not be possible to do so
5702 : directly if a temporary has been created by the gimplification. */
5703 1094 : prepare_gimple_addressable (&from, seq_p);
5704 :
5705 1094 : mark_addressable (from);
5706 1094 : from_ptr = build_fold_addr_expr_loc (loc, from);
5707 1094 : gimplify_arg (&from_ptr, seq_p, loc);
5708 :
5709 1094 : mark_addressable (to);
5710 1094 : to_ptr = build_fold_addr_expr_loc (loc, to);
5711 1094 : gimplify_arg (&to_ptr, seq_p, loc);
5712 :
5713 1094 : t = builtin_decl_implicit (BUILT_IN_MEMCPY);
5714 :
5715 1094 : gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
5716 1094 : gimple_call_set_alloca_for_var (gs, true);
5717 :
5718 1094 : if (want_value)
5719 : {
5720 : /* tmp = memcpy() */
5721 8 : t = create_tmp_var (TREE_TYPE (to_ptr));
5722 8 : gimple_call_set_lhs (gs, t);
5723 8 : gimplify_seq_add_stmt (seq_p, gs);
5724 :
5725 8 : *expr_p = build_simple_mem_ref (t);
5726 8 : return GS_ALL_DONE;
5727 : }
5728 :
5729 1086 : gimplify_seq_add_stmt (seq_p, gs);
5730 1086 : *expr_p = NULL;
5731 1086 : return GS_ALL_DONE;
5732 : }
5733 :
5734 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5735 : a call to __builtin_memset. In this case we know that the RHS is
5736 : a CONSTRUCTOR with an empty element list. */
5737 :
5738 : static enum gimplify_status
5739 84 : gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
5740 : gimple_seq *seq_p)
5741 : {
5742 84 : tree t, from, to, to_ptr;
5743 84 : gcall *gs;
5744 84 : location_t loc = EXPR_LOCATION (*expr_p);
5745 :
5746 : /* Assert our assumptions, to abort instead of producing wrong code
5747 : silently if they are not met. Beware that the RHS CONSTRUCTOR might
5748 : not be immediately exposed. */
5749 84 : from = TREE_OPERAND (*expr_p, 1);
5750 84 : if (TREE_CODE (from) == WITH_SIZE_EXPR)
5751 84 : from = TREE_OPERAND (from, 0);
5752 :
5753 84 : gcc_assert (TREE_CODE (from) == CONSTRUCTOR
5754 : && vec_safe_is_empty (CONSTRUCTOR_ELTS (from)));
5755 :
5756 : /* Now proceed. */
5757 84 : to = TREE_OPERAND (*expr_p, 0);
5758 84 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to))));
5759 :
5760 84 : to_ptr = build_fold_addr_expr_loc (loc, to);
5761 84 : gimplify_arg (&to_ptr, seq_p, loc);
5762 84 : t = builtin_decl_implicit (BUILT_IN_MEMSET);
5763 :
5764 84 : gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
5765 :
5766 84 : if (want_value)
5767 : {
5768 : /* tmp = memset() */
5769 0 : t = create_tmp_var (TREE_TYPE (to_ptr));
5770 0 : gimple_call_set_lhs (gs, t);
5771 0 : gimplify_seq_add_stmt (seq_p, gs);
5772 :
5773 0 : *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
5774 0 : return GS_ALL_DONE;
5775 : }
5776 :
5777 84 : gimplify_seq_add_stmt (seq_p, gs);
5778 84 : *expr_p = NULL;
5779 84 : return GS_ALL_DONE;
5780 : }
5781 :
5782 : /* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
5783 : determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
5784 : assignment. Return non-null if we detect a potential overlap. */
5785 :
5786 : struct gimplify_init_ctor_preeval_data
5787 : {
5788 : /* The base decl of the lhs object. May be NULL, in which case we
5789 : have to assume the lhs is indirect. */
5790 : tree lhs_base_decl;
5791 :
5792 : /* The alias set of the lhs object. */
5793 : alias_set_type lhs_alias_set;
5794 : };
5795 :
5796 : static tree
5797 116062 : gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
5798 : {
5799 116062 : struct gimplify_init_ctor_preeval_data *data
5800 : = (struct gimplify_init_ctor_preeval_data *) xdata;
5801 116062 : tree t = *tp;
5802 :
5803 : /* If we find the base object, obviously we have overlap. */
5804 116062 : if (data->lhs_base_decl == t)
5805 : return t;
5806 :
5807 : /* If the constructor component is indirect, determine if we have a
5808 : potential overlap with the lhs. The only bits of information we
5809 : have to go on at this point are addressability and alias sets. */
5810 116061 : if ((INDIRECT_REF_P (t)
5811 116061 : || TREE_CODE (t) == MEM_REF)
5812 651 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5813 116577 : && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
5814 : return t;
5815 :
5816 : /* If the constructor component is a call, determine if it can hide a
5817 : potential overlap with the lhs through an INDIRECT_REF like above.
5818 : ??? Ugh - this is completely broken. In fact this whole analysis
5819 : doesn't look conservative. */
5820 115545 : if (TREE_CODE (t) == CALL_EXPR)
5821 : {
5822 0 : tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
5823 :
5824 0 : for (type = TYPE_ARG_TYPES (fntype); type; type = TREE_CHAIN (type))
5825 0 : if (POINTER_TYPE_P (TREE_VALUE (type))
5826 0 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5827 0 : && alias_sets_conflict_p (data->lhs_alias_set,
5828 : get_alias_set
5829 0 : (TREE_TYPE (TREE_VALUE (type)))))
5830 : return t;
5831 : }
5832 :
5833 115545 : if (IS_TYPE_OR_DECL_P (t))
5834 10968 : *walk_subtrees = 0;
5835 : return NULL;
5836 : }
5837 :
5838 : /* A subroutine of gimplify_init_constructor. Pre-evaluate EXPR,
5839 : force values that overlap with the lhs (as described by *DATA)
5840 : into temporaries. */
5841 :
5842 : static void
5843 412662 : gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
5844 : struct gimplify_init_ctor_preeval_data *data)
5845 : {
5846 412662 : enum gimplify_status one;
5847 :
5848 : /* If the value is constant, then there's nothing to pre-evaluate. */
5849 412662 : if (TREE_CONSTANT (*expr_p))
5850 : {
5851 : /* Ensure it does not have side effects, it might contain a reference to
5852 : the object we're initializing. */
5853 195254 : gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
5854 : return;
5855 : }
5856 :
5857 : /* If the type has non-trivial constructors, we can't pre-evaluate. */
5858 217408 : if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
5859 : return;
5860 :
5861 : /* Recurse for nested constructors. */
5862 217408 : if (TREE_CODE (*expr_p) == CONSTRUCTOR)
5863 : {
5864 73604 : unsigned HOST_WIDE_INT ix;
5865 73604 : constructor_elt *ce;
5866 73604 : vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (*expr_p);
5867 :
5868 270938 : FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
5869 197334 : gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
5870 :
5871 : return;
5872 : }
5873 :
5874 : /* If this is a variable sized type, we must remember the size. */
5875 143804 : maybe_with_size_expr (expr_p);
5876 :
5877 : /* Gimplify the constructor element to something appropriate for the rhs
5878 : of a MODIFY_EXPR. Given that we know the LHS is an aggregate, we know
5879 : the gimplifier will consider this a store to memory. Doing this
5880 : gimplification now means that we won't have to deal with complicated
5881 : language-specific trees, nor trees like SAVE_EXPR that can induce
5882 : exponential search behavior. */
5883 143804 : one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
5884 143804 : if (one == GS_ERROR)
5885 : {
5886 0 : *expr_p = NULL;
5887 0 : return;
5888 : }
5889 :
5890 : /* If we gimplified to a bare decl, we can be sure that it doesn't overlap
5891 : with the lhs, since "a = { .x=a }" doesn't make sense. This will
5892 : always be true for all scalars, since is_gimple_mem_rhs insists on a
5893 : temporary variable for them. */
5894 143804 : if (DECL_P (*expr_p))
5895 : return;
5896 :
5897 : /* If this is of variable size, we have no choice but to assume it doesn't
5898 : overlap since we can't make a temporary for it. */
5899 104498 : if (TREE_CODE (TYPE_SIZE (TREE_TYPE (*expr_p))) != INTEGER_CST)
5900 : return;
5901 :
5902 : /* Otherwise, we must search for overlap ... */
5903 104498 : if (!walk_tree (expr_p, gimplify_init_ctor_preeval_1, data, NULL))
5904 : return;
5905 :
5906 : /* ... and if found, force the value into a temporary. */
5907 517 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
5908 : }
5909 :
5910 : /* A subroutine of gimplify_init_ctor_eval. Create a loop for
5911 : a RANGE_EXPR in a CONSTRUCTOR for an array.
5912 :
5913 : var = lower;
5914 : loop_entry:
5915 : object[var] = value;
5916 : if (var == upper)
5917 : goto loop_exit;
5918 : var = var + 1;
5919 : goto loop_entry;
5920 : loop_exit:
5921 :
5922 : We increment var _after_ the loop exit check because we might otherwise
5923 : fail if upper == TYPE_MAX_VALUE (type for upper).
5924 :
5925 : Note that we never have to deal with SAVE_EXPRs here, because this has
5926 : already been taken care of for us, in gimplify_init_ctor_preeval(). */
5927 :
5928 : static void gimplify_init_ctor_eval (tree, vec<constructor_elt, va_gc> *,
5929 : gimple_seq *, bool);
5930 :
5931 : static void
5932 437 : gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
5933 : tree value, tree array_elt_type,
5934 : gimple_seq *pre_p, bool cleared)
5935 : {
5936 437 : tree loop_entry_label, loop_exit_label, fall_thru_label;
5937 437 : tree var, var_type, cref, tmp;
5938 :
5939 437 : loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
5940 437 : loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
5941 437 : fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
5942 :
5943 : /* Create and initialize the index variable. */
5944 437 : var_type = TREE_TYPE (upper);
5945 437 : var = create_tmp_var (var_type);
5946 437 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
5947 :
5948 : /* Add the loop entry label. */
5949 437 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
5950 :
5951 : /* Build the reference. */
5952 437 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
5953 : var, NULL_TREE, NULL_TREE);
5954 :
5955 : /* If we are a constructor, just call gimplify_init_ctor_eval to do
5956 : the store. Otherwise just assign value to the reference. */
5957 :
5958 437 : if (TREE_CODE (value) == CONSTRUCTOR)
5959 : /* NB we might have to call ourself recursively through
5960 : gimplify_init_ctor_eval if the value is a constructor. */
5961 120 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
5962 : pre_p, cleared);
5963 : else
5964 : {
5965 317 : if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue)
5966 : != GS_ERROR)
5967 317 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
5968 : }
5969 :
5970 : /* We exit the loop when the index var is equal to the upper bound. */
5971 874 : gimplify_seq_add_stmt (pre_p,
5972 437 : gimple_build_cond (EQ_EXPR, var, upper,
5973 : loop_exit_label, fall_thru_label));
5974 :
5975 437 : gimplify_seq_add_stmt (pre_p, gimple_build_label (fall_thru_label));
5976 :
5977 : /* Otherwise, increment the index var... */
5978 437 : tmp = build2 (PLUS_EXPR, var_type, var,
5979 : fold_convert (var_type, integer_one_node));
5980 437 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
5981 :
5982 : /* ...and jump back to the loop entry. */
5983 437 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
5984 :
5985 : /* Add the loop exit label. */
5986 437 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
5987 437 : }
5988 :
5989 : /* A subroutine of gimplify_init_constructor. Generate individual
5990 : MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the
5991 : assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the
5992 : CONSTRUCTOR. CLEARED is true if the entire LHS object has been
5993 : zeroed first. */
5994 :
5995 : static void
5996 1234024 : gimplify_init_ctor_eval (tree object, vec<constructor_elt, va_gc> *elts,
5997 : gimple_seq *pre_p, bool cleared)
5998 : {
5999 1234024 : tree array_elt_type = NULL;
6000 1234024 : unsigned HOST_WIDE_INT ix;
6001 1234024 : tree purpose, value;
6002 :
6003 1234024 : if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
6004 139236 : array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
6005 :
6006 4587314 : FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
6007 : {
6008 3353290 : tree cref;
6009 :
6010 : /* NULL values are created above for gimplification errors. */
6011 3353290 : if (value == NULL)
6012 317103 : continue;
6013 :
6014 3353290 : if (cleared && initializer_zerop (value))
6015 316500 : continue;
6016 :
6017 : /* ??? Here's to hoping the front end fills in all of the indices,
6018 : so we don't have to figure out what's missing ourselves. */
6019 3036790 : gcc_assert (purpose);
6020 :
6021 : /* Skip zero-sized fields, unless value has side-effects. This can
6022 : happen with calls to functions returning a empty type, which
6023 : we shouldn't discard. As a number of downstream passes don't
6024 : expect sets of empty type fields, we rely on the gimplification of
6025 : the MODIFY_EXPR we make below to drop the assignment statement. */
6026 3036790 : if (!TREE_SIDE_EFFECTS (value)
6027 2744173 : && TREE_CODE (purpose) == FIELD_DECL
6028 5316535 : && is_empty_type (TREE_TYPE (purpose)))
6029 166 : continue;
6030 :
6031 : /* If we have a RANGE_EXPR, we have to build a loop to assign the
6032 : whole range. */
6033 3036624 : if (TREE_CODE (purpose) == RANGE_EXPR)
6034 : {
6035 447 : tree lower = TREE_OPERAND (purpose, 0);
6036 447 : tree upper = TREE_OPERAND (purpose, 1);
6037 :
6038 : /* If the lower bound is equal to upper, just treat it as if
6039 : upper was the index. */
6040 447 : if (simple_cst_equal (lower, upper))
6041 : purpose = upper;
6042 : else
6043 : {
6044 437 : gimplify_init_ctor_eval_range (object, lower, upper, value,
6045 : array_elt_type, pre_p, cleared);
6046 437 : continue;
6047 : }
6048 : }
6049 :
6050 3036187 : if (array_elt_type)
6051 : {
6052 : /* Do not use bitsizetype for ARRAY_REF indices. */
6053 554433 : if (TYPE_DOMAIN (TREE_TYPE (object)))
6054 554433 : purpose
6055 554433 : = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
6056 : purpose);
6057 554433 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
6058 : purpose, NULL_TREE, NULL_TREE);
6059 : }
6060 : else
6061 : {
6062 2481754 : gcc_assert (TREE_CODE (purpose) == FIELD_DECL);
6063 2481754 : cref = build3 (COMPONENT_REF, TREE_TYPE (purpose),
6064 : unshare_expr (object), purpose, NULL_TREE);
6065 : }
6066 :
6067 3036187 : if (TREE_CODE (value) == CONSTRUCTOR
6068 3036187 : && TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE)
6069 291032 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
6070 : pre_p, cleared);
6071 2745155 : else if (TREE_CODE (value) == RAW_DATA_CST)
6072 : {
6073 43 : if (RAW_DATA_LENGTH (value) <= 32)
6074 : {
6075 13 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value);
6076 : ++i)
6077 12 : if (!cleared || RAW_DATA_POINTER (value)[i])
6078 : {
6079 12 : if (i)
6080 : {
6081 11 : tree p
6082 11 : = fold_build2 (PLUS_EXPR, TREE_TYPE (purpose),
6083 : purpose,
6084 : build_int_cst (TREE_TYPE (purpose),
6085 : i));
6086 11 : cref = build4 (ARRAY_REF, array_elt_type,
6087 : unshare_expr (object), p, NULL_TREE,
6088 : NULL_TREE);
6089 : }
6090 12 : tree init
6091 12 : = build2 (INIT_EXPR, TREE_TYPE (cref), cref,
6092 12 : build_int_cst (TREE_TYPE (value),
6093 12 : RAW_DATA_UCHAR_ELT (value, i)));
6094 12 : gimplify_and_add (init, pre_p);
6095 12 : ggc_free (init);
6096 : }
6097 : }
6098 : else
6099 : {
6100 42 : tree rtype = build_array_type_nelts (TREE_TYPE (value),
6101 42 : RAW_DATA_LENGTH (value));
6102 42 : tree rctor = build_constructor_single (rtype, bitsize_zero_node,
6103 : value);
6104 42 : tree addr = build_fold_addr_expr (cref);
6105 42 : cref = build2 (MEM_REF, rtype, addr,
6106 : build_int_cst (ptr_type_node, 0));
6107 42 : rctor = tree_output_constant_def (rctor);
6108 42 : if (!useless_type_conversion_p (rtype, TREE_TYPE (rctor)))
6109 4 : rctor = build1 (VIEW_CONVERT_EXPR, rtype, rctor);
6110 42 : if (gimplify_expr (&cref, pre_p, NULL, is_gimple_lvalue,
6111 : fb_lvalue) != GS_ERROR)
6112 84 : gimplify_seq_add_stmt (pre_p,
6113 42 : gimple_build_assign (cref, rctor));
6114 : }
6115 : }
6116 : else
6117 : {
6118 2745112 : tree init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
6119 2745112 : gimplify_and_add (init, pre_p);
6120 2745112 : ggc_free (init);
6121 : }
6122 : }
6123 1234024 : }
6124 :
6125 : /* Return the appropriate RHS predicate for this LHS. */
6126 :
6127 : gimple_predicate
6128 48487021 : rhs_predicate_for (tree lhs)
6129 : {
6130 48487021 : if (is_gimple_reg (lhs))
6131 : return is_gimple_reg_rhs_or_call;
6132 : else
6133 11393591 : return is_gimple_mem_rhs_or_call;
6134 : }
6135 :
6136 : /* Return the initial guess for an appropriate RHS predicate for this LHS,
6137 : before the LHS has been gimplified. */
6138 :
6139 : static gimple_predicate
6140 47355126 : initial_rhs_predicate_for (tree lhs)
6141 : {
6142 47355126 : if (is_gimple_reg_type (TREE_TYPE (lhs)))
6143 : return is_gimple_reg_rhs_or_call;
6144 : else
6145 2357923 : return is_gimple_mem_rhs_or_call;
6146 : }
6147 :
6148 : /* Gimplify a C99 compound literal expression. This just means adding
6149 : the DECL_EXPR before the current statement and using its anonymous
6150 : decl instead. */
6151 :
6152 : static enum gimplify_status
6153 37190 : gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
6154 : bool (*gimple_test_f) (tree),
6155 : fallback_t fallback)
6156 : {
6157 37190 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
6158 37190 : tree decl = DECL_EXPR_DECL (decl_s);
6159 37190 : tree init = DECL_INITIAL (decl);
6160 : /* Mark the decl as addressable if the compound literal
6161 : expression is addressable now, otherwise it is marked too late
6162 : after we gimplify the initialization expression. */
6163 37190 : if (TREE_ADDRESSABLE (*expr_p))
6164 542 : TREE_ADDRESSABLE (decl) = 1;
6165 : /* Otherwise, if we don't need an lvalue and have a literal directly
6166 : substitute it. Check if it matches the gimple predicate, as
6167 : otherwise we'd generate a new temporary, and we can as well just
6168 : use the decl we already have. */
6169 36648 : else if (!TREE_ADDRESSABLE (decl)
6170 36648 : && !TREE_THIS_VOLATILE (decl)
6171 36643 : && init
6172 36635 : && (fallback & fb_lvalue) == 0
6173 73131 : && gimple_test_f (init))
6174 : {
6175 35395 : *expr_p = init;
6176 35395 : return GS_OK;
6177 : }
6178 :
6179 : /* If the decl is not addressable, then it is being used in some
6180 : expression or on the right hand side of a statement, and it can
6181 : be put into a readonly data section. */
6182 1795 : if (!TREE_ADDRESSABLE (decl) && (fallback & fb_lvalue) == 0)
6183 1093 : TREE_READONLY (decl) = 1;
6184 :
6185 : /* This decl isn't mentioned in the enclosing block, so add it to the
6186 : list of temps. FIXME it seems a bit of a kludge to say that
6187 : anonymous artificial vars aren't pushed, but everything else is. */
6188 1795 : if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
6189 2 : gimple_add_tmp_var (decl);
6190 :
6191 1795 : gimplify_and_add (decl_s, pre_p);
6192 1795 : *expr_p = decl;
6193 1795 : return GS_OK;
6194 : }
6195 :
6196 : /* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
6197 : return a new CONSTRUCTOR if something changed. */
6198 :
6199 : static tree
6200 1835845 : optimize_compound_literals_in_ctor (tree orig_ctor)
6201 : {
6202 1835845 : tree ctor = orig_ctor;
6203 1835845 : vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
6204 1835845 : unsigned int idx, num = vec_safe_length (elts);
6205 :
6206 6137605 : for (idx = 0; idx < num; idx++)
6207 : {
6208 4301760 : tree value = (*elts)[idx].value;
6209 4301760 : tree newval = value;
6210 4301760 : if (TREE_CODE (value) == CONSTRUCTOR)
6211 528240 : newval = optimize_compound_literals_in_ctor (value);
6212 3773520 : else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
6213 : {
6214 103 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
6215 103 : tree decl = DECL_EXPR_DECL (decl_s);
6216 103 : tree init = DECL_INITIAL (decl);
6217 :
6218 103 : if (!TREE_ADDRESSABLE (value)
6219 103 : && !TREE_ADDRESSABLE (decl)
6220 103 : && init
6221 103 : && TREE_CODE (init) == CONSTRUCTOR)
6222 52 : newval = optimize_compound_literals_in_ctor (init);
6223 : }
6224 4301760 : if (newval == value)
6225 4301700 : continue;
6226 :
6227 60 : if (ctor == orig_ctor)
6228 : {
6229 49 : ctor = copy_node (orig_ctor);
6230 98 : CONSTRUCTOR_ELTS (ctor) = vec_safe_copy (elts);
6231 49 : elts = CONSTRUCTOR_ELTS (ctor);
6232 : }
6233 60 : (*elts)[idx].value = newval;
6234 : }
6235 1835845 : return ctor;
6236 : }
6237 :
6238 : /* A subroutine of gimplify_modify_expr. Break out elements of a
6239 : CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
6240 :
6241 : Note that we still need to clear any elements that don't have explicit
6242 : initializers, so if not all elements are initialized we keep the
6243 : original MODIFY_EXPR, we just remove all of the constructor elements.
6244 :
6245 : If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
6246 : GS_ERROR if we would have to create a temporary when gimplifying
6247 : this constructor. Otherwise, return GS_OK.
6248 :
6249 : If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
6250 :
6251 : static enum gimplify_status
6252 1307553 : gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
6253 : bool want_value, bool notify_temp_creation)
6254 : {
6255 1307553 : tree object, ctor, type;
6256 1307553 : enum gimplify_status ret;
6257 1307553 : vec<constructor_elt, va_gc> *elts;
6258 1307553 : bool cleared = false;
6259 1307553 : bool is_empty_ctor = false;
6260 1307553 : bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR);
6261 :
6262 1307553 : gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
6263 :
6264 1307553 : if (!notify_temp_creation)
6265 : {
6266 1299384 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
6267 : is_gimple_lvalue, fb_lvalue);
6268 1299384 : if (ret == GS_ERROR)
6269 : return ret;
6270 : }
6271 :
6272 1307553 : object = TREE_OPERAND (*expr_p, 0);
6273 1307553 : ctor = TREE_OPERAND (*expr_p, 1)
6274 1307553 : = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
6275 1307553 : type = TREE_TYPE (ctor);
6276 1307553 : elts = CONSTRUCTOR_ELTS (ctor);
6277 1307553 : ret = GS_ALL_DONE;
6278 :
6279 1307553 : switch (TREE_CODE (type))
6280 : {
6281 1300289 : case RECORD_TYPE:
6282 1300289 : case UNION_TYPE:
6283 1300289 : case QUAL_UNION_TYPE:
6284 1300289 : case ARRAY_TYPE:
6285 1300289 : {
6286 : /* Use readonly data for initializers of this or smaller size
6287 : regardless of the num_nonzero_elements / num_unique_nonzero_elements
6288 : ratio. */
6289 1300289 : const HOST_WIDE_INT min_unique_size = 64;
6290 : /* If num_nonzero_elements / num_unique_nonzero_elements ratio
6291 : is smaller than this, use readonly data. */
6292 1300289 : const int unique_nonzero_ratio = 8;
6293 : /* True if a single access of the object must be ensured. This is the
6294 : case if the target is volatile, the type is non-addressable and more
6295 : than one field need to be assigned. */
6296 1300289 : const bool ensure_single_access
6297 1300289 : = TREE_THIS_VOLATILE (object)
6298 255 : && !TREE_ADDRESSABLE (type)
6299 1300492 : && vec_safe_length (elts) > 1;
6300 1300289 : struct gimplify_init_ctor_preeval_data preeval_data;
6301 1300289 : HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
6302 1300289 : HOST_WIDE_INT num_unique_nonzero_elements;
6303 1300289 : ctor_completeness complete_p;
6304 1300289 : bool valid_const_initializer;
6305 :
6306 : /* Aggregate types must lower constructors to initialization of
6307 : individual elements. The exception is that a CONSTRUCTOR node
6308 : with no elements indicates zero-initialization of the whole. */
6309 1300289 : if (vec_safe_is_empty (elts))
6310 : {
6311 327693 : if (notify_temp_creation)
6312 9752 : return GS_OK;
6313 :
6314 : /* The var will be initialized and so appear on lhs of
6315 : assignment, it can't be TREE_READONLY anymore. */
6316 327645 : if (VAR_P (object))
6317 182939 : TREE_READONLY (object) = 0;
6318 :
6319 : is_empty_ctor = true;
6320 330220 : break;
6321 : }
6322 :
6323 : /* Fetch information about the constructor to direct later processing.
6324 : We might want to make static versions of it in various cases, and
6325 : can only do so if it known to be a valid constant initializer. */
6326 972596 : valid_const_initializer
6327 972596 : = categorize_ctor_elements (ctor, &num_nonzero_elements,
6328 : &num_unique_nonzero_elements,
6329 : &num_ctor_elements, &complete_p);
6330 :
6331 : /* If a const aggregate variable is being initialized, then it
6332 : should never be a lose to promote the variable to be static. */
6333 972596 : if (valid_const_initializer
6334 595410 : && num_nonzero_elements > 1
6335 443065 : && TREE_READONLY (object)
6336 5181 : && VAR_P (object)
6337 4804 : && !DECL_REGISTER (object)
6338 4797 : && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)
6339 3823 : || DECL_MERGEABLE (object))
6340 : /* For ctors that have many repeated nonzero elements
6341 : represented through RANGE_EXPRs, prefer initializing
6342 : those through runtime loops over copies of large amounts
6343 : of data from readonly data section. */
6344 972596 : && (num_unique_nonzero_elements
6345 2575 : > num_nonzero_elements / unique_nonzero_ratio
6346 0 : || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
6347 : <= (unsigned HOST_WIDE_INT) min_unique_size)))
6348 : {
6349 2575 : if (notify_temp_creation)
6350 : return GS_ERROR;
6351 :
6352 2575 : DECL_INITIAL (object) = ctor;
6353 2575 : TREE_STATIC (object) = 1;
6354 2575 : if (!DECL_NAME (object) || DECL_NAMELESS (object))
6355 2118 : DECL_NAME (object) = create_tmp_var_name ("C");
6356 2575 : walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL);
6357 :
6358 : /* ??? C++ doesn't automatically append a .<number> to the
6359 : assembler name, and even when it does, it looks at FE private
6360 : data structures to figure out what that number should be,
6361 : which are not set for this variable. I suppose this is
6362 : important for local statics for inline functions, which aren't
6363 : "local" in the object file sense. So in order to get a unique
6364 : TU-local symbol, we must invoke the lhd version now. */
6365 2575 : lhd_set_decl_assembler_name (object);
6366 :
6367 2575 : *expr_p = NULL_TREE;
6368 2575 : break;
6369 : }
6370 :
6371 : /* The var will be initialized and so appear on lhs of
6372 : assignment, it can't be TREE_READONLY anymore. */
6373 970021 : if (VAR_P (object) && !notify_temp_creation)
6374 765347 : TREE_READONLY (object) = 0;
6375 :
6376 : /* If there are "lots" of initialized elements, even discounting
6377 : those that are not address constants (and thus *must* be
6378 : computed at runtime), then partition the constructor into
6379 : constant and non-constant parts. Block copy the constant
6380 : parts in, then generate code for the non-constant parts. */
6381 : /* TODO. There's code in cp/typeck.cc to do this. */
6382 :
6383 970021 : if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
6384 : /* store_constructor will ignore the clearing of variable-sized
6385 : objects. Initializers for such objects must explicitly set
6386 : every field that needs to be set. */
6387 : cleared = false;
6388 970001 : else if (complete_p.sparse)
6389 : /* If the constructor isn't complete, clear the whole object
6390 : beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
6391 :
6392 : ??? This ought not to be needed. For any element not present
6393 : in the initializer, we should simply set them to zero. Except
6394 : we'd need to *find* the elements that are not present, and that
6395 : requires trickery to avoid quadratic compile-time behavior in
6396 : large cases or excessive memory use in small cases. */
6397 182737 : cleared = !CONSTRUCTOR_NO_CLEARING (ctor);
6398 787264 : else if (num_ctor_elements - num_nonzero_elements
6399 787264 : > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
6400 787264 : && num_nonzero_elements < num_ctor_elements / 4)
6401 : /* If there are "lots" of zeros, it's more efficient to clear
6402 : the memory and then set the nonzero elements. */
6403 : cleared = true;
6404 786396 : else if (ensure_single_access && num_nonzero_elements == 0)
6405 : /* If a single access to the target must be ensured and all elements
6406 : are zero, then it's optimal to clear whatever their number. */
6407 : cleared = true;
6408 : /* If the object is small enough to go in registers, and it's
6409 : not required to be constructed in memory, clear it first.
6410 : That will avoid wasting cycles preserving any padding bits
6411 : that might be there, and if there aren't any, the compiler
6412 : is smart enough to optimize the clearing out. */
6413 786387 : else if ((complete_p.sparse || complete_p.padded_union
6414 786169 : || complete_p.padded_non_union)
6415 13780 : && !TREE_ADDRESSABLE (ctor)
6416 13694 : && !TREE_THIS_VOLATILE (object)
6417 13691 : && (TYPE_MODE (type) != BLKmode || TYPE_NO_FORCE_BLK (type))
6418 793138 : && optimize)
6419 : cleared = true;
6420 : else
6421 : cleared = false;
6422 :
6423 : /* If there are "lots" of initialized elements, and all of them
6424 : are valid address constants, then the entire initializer can
6425 : be dropped to memory, and then memcpy'd out. Don't do this
6426 : for sparse arrays, though, as it's more efficient to follow
6427 : the standard CONSTRUCTOR behavior of memset followed by
6428 : individual element initialization. Also don't do this for small
6429 : all-zero initializers (which aren't big enough to merit
6430 : clearing), and don't try to make bitwise copies of
6431 : TREE_ADDRESSABLE types. */
6432 970021 : if (valid_const_initializer
6433 592835 : && !complete_p.sparse
6434 425094 : && !(cleared || num_nonzero_elements == 0)
6435 331924 : && !TREE_ADDRESSABLE (type))
6436 : {
6437 330393 : HOST_WIDE_INT size = int_size_in_bytes (type);
6438 330393 : unsigned int align;
6439 :
6440 : /* ??? We can still get unbounded array types, at least
6441 : from the C++ front end. This seems wrong, but attempt
6442 : to work around it for now. */
6443 330393 : if (size < 0)
6444 : {
6445 9 : size = int_size_in_bytes (TREE_TYPE (object));
6446 9 : if (size >= 0)
6447 0 : TREE_TYPE (ctor) = type = TREE_TYPE (object);
6448 : }
6449 :
6450 : /* Find the maximum alignment we can assume for the object. */
6451 : /* ??? Make use of DECL_OFFSET_ALIGN. */
6452 330393 : if (DECL_P (object))
6453 316619 : align = DECL_ALIGN (object);
6454 : else
6455 13774 : align = TYPE_ALIGN (type);
6456 :
6457 : /* Do a block move either if the size is so small as to make
6458 : each individual move a sub-unit move on average, or if it
6459 : is so large as to make individual moves inefficient. */
6460 330393 : if (size > 0
6461 330384 : && num_nonzero_elements > 1
6462 : /* For ctors that have many repeated nonzero elements
6463 : represented through RANGE_EXPRs, prefer initializing
6464 : those through runtime loops over copies of large amounts
6465 : of data from readonly data section. */
6466 298027 : && (num_unique_nonzero_elements
6467 298027 : > num_nonzero_elements / unique_nonzero_ratio
6468 56 : || size <= min_unique_size)
6469 628364 : && (size < num_nonzero_elements
6470 297865 : || !can_move_by_pieces (size, align)))
6471 : {
6472 2840 : if (notify_temp_creation)
6473 : return GS_ERROR;
6474 :
6475 1422 : walk_tree (&ctor, force_labels_r, NULL, NULL);
6476 1422 : ctor = tree_output_constant_def (ctor);
6477 1422 : if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
6478 0 : ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
6479 1422 : TREE_OPERAND (*expr_p, 1) = ctor;
6480 :
6481 : /* This is no longer an assignment of a CONSTRUCTOR, but
6482 : we still may have processing to do on the LHS. So
6483 : pretend we didn't do anything here to let that happen. */
6484 1422 : return GS_UNHANDLED;
6485 : }
6486 : }
6487 :
6488 962757 : if (!cleared)
6489 : {
6490 777512 : if (complete_p.padded_non_union
6491 7108 : && warn_zero_init_padding_bits >= ZERO_INIT_PADDING_BITS_ALL)
6492 12 : warning (OPT_Wzero_init_padding_bits_,
6493 : "padding might not be initialized to zero; "
6494 : "if code relies on it being zero, consider "
6495 : "using %<-fzero-init-padding-bits=all%>");
6496 777500 : else if (complete_p.padded_union
6497 110 : && warn_zero_init_padding_bits
6498 : >= ZERO_INIT_PADDING_BITS_UNIONS)
6499 14 : warning (OPT_Wzero_init_padding_bits_,
6500 : "padding might not be initialized to zero; "
6501 : "if code relies on it being zero, consider "
6502 : "using %<-fzero-init-padding-bits=unions%> "
6503 : "or %<-fzero-init-padding-bits=all%>");
6504 : }
6505 :
6506 : /* If a single access to the target must be ensured and there are
6507 : nonzero elements or the zero elements are not assigned en masse,
6508 : initialize the target from a temporary. */
6509 967181 : if (ensure_single_access && (num_nonzero_elements > 0 || !cleared))
6510 : {
6511 167 : if (notify_temp_creation)
6512 : return GS_ERROR;
6513 :
6514 161 : tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type));
6515 161 : TREE_OPERAND (*expr_p, 0) = temp;
6516 161 : *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
6517 : *expr_p,
6518 : build2 (MODIFY_EXPR, void_type_node,
6519 : object, temp));
6520 161 : return GS_OK;
6521 : }
6522 :
6523 967014 : if (notify_temp_creation)
6524 : return GS_OK;
6525 :
6526 : /* If there are nonzero elements and if needed, pre-evaluate to capture
6527 : elements overlapping with the lhs into temporaries. We must do this
6528 : before clearing to fetch the values before they are zeroed-out. */
6529 960317 : if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
6530 : {
6531 215328 : preeval_data.lhs_base_decl = get_base_address (object);
6532 215328 : if (!DECL_P (preeval_data.lhs_base_decl))
6533 41121 : preeval_data.lhs_base_decl = NULL;
6534 215328 : preeval_data.lhs_alias_set = get_alias_set (object);
6535 :
6536 215328 : gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
6537 : pre_p, post_p, &preeval_data);
6538 : }
6539 :
6540 960317 : bool ctor_has_side_effects_p
6541 960317 : = TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1));
6542 :
6543 960317 : if (cleared)
6544 : {
6545 : /* Zap the CONSTRUCTOR element list, which simplifies this case.
6546 : Note that we still have to gimplify, in order to handle the
6547 : case of variable sized types. Avoid shared tree structures. */
6548 189468 : CONSTRUCTOR_ELTS (ctor) = NULL;
6549 189468 : TREE_SIDE_EFFECTS (ctor) = 0;
6550 189468 : object = unshare_expr (object);
6551 189468 : gimplify_stmt (expr_p, pre_p);
6552 : }
6553 :
6554 : /* If we have not block cleared the object, or if there are nonzero
6555 : elements in the constructor, or if the constructor has side effects,
6556 : add assignments to the individual scalar fields of the object. */
6557 189468 : if (!cleared
6558 189468 : || num_nonzero_elements > 0
6559 17840 : || ctor_has_side_effects_p)
6560 942872 : gimplify_init_ctor_eval (object, elts, pre_p, cleared);
6561 :
6562 960317 : *expr_p = NULL_TREE;
6563 : }
6564 960317 : break;
6565 :
6566 0 : case COMPLEX_TYPE:
6567 0 : {
6568 0 : tree r, i;
6569 :
6570 0 : if (notify_temp_creation)
6571 : return GS_OK;
6572 :
6573 : /* Extract the real and imaginary parts out of the ctor. */
6574 0 : gcc_assert (elts->length () == 2);
6575 0 : r = (*elts)[0].value;
6576 0 : i = (*elts)[1].value;
6577 0 : if (r == NULL || i == NULL)
6578 : {
6579 0 : tree zero = build_zero_cst (TREE_TYPE (type));
6580 0 : if (r == NULL)
6581 0 : r = zero;
6582 0 : if (i == NULL)
6583 0 : i = zero;
6584 : }
6585 :
6586 : /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to
6587 : represent creation of a complex value. */
6588 0 : if (TREE_CONSTANT (r) && TREE_CONSTANT (i))
6589 : {
6590 0 : ctor = build_complex (type, r, i);
6591 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6592 : }
6593 : else
6594 : {
6595 0 : ctor = build2 (COMPLEX_EXPR, type, r, i);
6596 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6597 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1),
6598 : pre_p,
6599 : post_p,
6600 0 : rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
6601 : fb_rvalue);
6602 : }
6603 : }
6604 : break;
6605 :
6606 7264 : case VECTOR_TYPE:
6607 7264 : {
6608 7264 : unsigned HOST_WIDE_INT ix;
6609 7264 : constructor_elt *ce;
6610 :
6611 7264 : if (notify_temp_creation)
6612 1307553 : return GS_OK;
6613 :
6614 : /* Vector types use CONSTRUCTOR all the way through gimple
6615 : compilation as a general initializer. */
6616 67122 : FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
6617 : {
6618 59858 : enum gimplify_status tret;
6619 59858 : tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
6620 : fb_rvalue);
6621 59858 : if (tret == GS_ERROR)
6622 : ret = GS_ERROR;
6623 59857 : else if (TREE_STATIC (ctor)
6624 59889 : && !initializer_constant_valid_p (ce->value,
6625 32 : TREE_TYPE (ce->value)))
6626 32 : TREE_STATIC (ctor) = 0;
6627 : }
6628 7264 : recompute_constructor_flags (ctor);
6629 :
6630 : /* Go ahead and simplify constant constructors to VECTOR_CST. */
6631 7264 : if (TREE_CONSTANT (ctor))
6632 : {
6633 2505 : bool constant_p = true;
6634 : tree value;
6635 :
6636 : /* Even when ctor is constant, it might contain non-*_CST
6637 : elements, such as addresses or trapping values like
6638 : 1.0/0.0 - 1.0/0.0. Such expressions don't belong
6639 : in VECTOR_CST nodes. */
6640 2505 : FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
6641 2323 : if (!CONSTANT_CLASS_P (value))
6642 : {
6643 : constant_p = false;
6644 : break;
6645 : }
6646 :
6647 182 : if (constant_p)
6648 : {
6649 182 : TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts);
6650 182 : break;
6651 : }
6652 : }
6653 :
6654 7082 : if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
6655 918 : TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
6656 : }
6657 : break;
6658 :
6659 0 : default:
6660 : /* So how did we get a CONSTRUCTOR for a scalar type? */
6661 0 : gcc_unreachable ();
6662 : }
6663 :
6664 1297801 : if (ret == GS_ERROR)
6665 : return GS_ERROR;
6666 : /* If we have gimplified both sides of the initializer but have
6667 : not emitted an assignment, do so now. */
6668 1297800 : if (*expr_p
6669 : /* If the type is an empty type, we don't need to emit the
6670 : assignment. */
6671 1297800 : && !is_empty_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
6672 : {
6673 331078 : tree lhs = TREE_OPERAND (*expr_p, 0);
6674 331078 : tree rhs = TREE_OPERAND (*expr_p, 1);
6675 331078 : if (want_value && object == lhs)
6676 12 : lhs = unshare_expr (lhs);
6677 331078 : gassign *init = gimple_build_assign (lhs, rhs);
6678 331078 : gimplify_seq_add_stmt (pre_p, init);
6679 : }
6680 1297800 : if (want_value)
6681 : {
6682 19 : *expr_p = object;
6683 19 : ret = GS_OK;
6684 : }
6685 : else
6686 : {
6687 1297781 : *expr_p = NULL;
6688 1297781 : ret = GS_ALL_DONE;
6689 : }
6690 :
6691 : /* If the user requests to initialize automatic variables, we
6692 : should initialize paddings inside the variable. Add a call to
6693 : __builtin_clear_pading (&object, 0, for_auto_init = true) to
6694 : initialize paddings of object always to zero regardless of
6695 : INIT_TYPE. Note, we will not insert this call if the aggregate
6696 : variable has be completely cleared already or it's initialized
6697 : with an empty constructor. We cannot insert this call if the
6698 : variable is a gimple register since __builtin_clear_padding will take
6699 : the address of the variable. As a result, if a long double/_Complex long
6700 : double variable will be spilled into stack later, its padding cannot
6701 : be cleared with __builtin_clear_padding. We should clear its padding
6702 : when it is spilled into memory. */
6703 1297800 : if (is_init_expr
6704 920132 : && !is_gimple_reg (object)
6705 915590 : && clear_padding_type_may_have_padding_p (type)
6706 873167 : && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
6707 217381 : || !AGGREGATE_TYPE_P (type))
6708 655786 : && var_needs_auto_init_p (object)
6709 1317567 : && flag_auto_var_init != AUTO_INIT_CXX26)
6710 41 : gimple_add_padding_init_for_auto_var (object, false, pre_p);
6711 :
6712 : return ret;
6713 : }
6714 :
6715 : /* Given a pointer value OP0, return a simplified version of an
6716 : indirection through OP0, or NULL_TREE if no simplification is
6717 : possible. This may only be applied to a rhs of an expression.
6718 : Note that the resulting type may be different from the type pointed
6719 : to in the sense that it is still compatible from the langhooks
6720 : point of view. */
6721 :
6722 : static tree
6723 516242 : gimple_fold_indirect_ref_rhs (tree t)
6724 : {
6725 0 : return gimple_fold_indirect_ref (t);
6726 : }
6727 :
6728 : /* Subroutine of gimplify_modify_expr to do simplifications of
6729 : MODIFY_EXPRs based on the code of the RHS. We loop for as long as
6730 : something changes. */
6731 :
6732 : static enum gimplify_status
6733 96715861 : gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
6734 : gimple_seq *pre_p, gimple_seq *post_p,
6735 : bool want_value)
6736 : {
6737 96715861 : enum gimplify_status ret = GS_UNHANDLED;
6738 97340813 : bool changed;
6739 :
6740 95893506 : do
6741 : {
6742 97340813 : changed = false;
6743 97340813 : switch (TREE_CODE (*from_p))
6744 : {
6745 11873031 : case VAR_DECL:
6746 : /* If we're assigning from a read-only variable initialized with
6747 : a constructor and not volatile, do the direct assignment from
6748 : the constructor, but only if the target is not volatile either
6749 : since this latter assignment might end up being done on a per
6750 : field basis. However, if the target is volatile and the type
6751 : is aggregate and non-addressable, gimplify_init_constructor
6752 : knows that it needs to ensure a single access to the target
6753 : and it will return GS_OK only in this case. */
6754 11873031 : if (TREE_READONLY (*from_p)
6755 92209 : && DECL_INITIAL (*from_p)
6756 61050 : && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR
6757 8169 : && !TREE_THIS_VOLATILE (*from_p)
6758 11881200 : && (!TREE_THIS_VOLATILE (*to_p)
6759 6 : || (AGGREGATE_TYPE_P (TREE_TYPE (*to_p))
6760 6 : && !TREE_ADDRESSABLE (TREE_TYPE (*to_p)))))
6761 : {
6762 8169 : tree old_from = *from_p;
6763 8169 : enum gimplify_status subret;
6764 :
6765 : /* Move the constructor into the RHS. */
6766 8169 : *from_p = unshare_expr (DECL_INITIAL (*from_p));
6767 :
6768 : /* Let's see if gimplify_init_constructor will need to put
6769 : it in memory. */
6770 8169 : subret = gimplify_init_constructor (expr_p, NULL, NULL,
6771 : false, true);
6772 8169 : if (subret == GS_ERROR)
6773 : {
6774 : /* If so, revert the change. */
6775 1424 : *from_p = old_from;
6776 : }
6777 : else
6778 : {
6779 : ret = GS_OK;
6780 : changed = true;
6781 : }
6782 : }
6783 : break;
6784 524059 : case INDIRECT_REF:
6785 524059 : if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
6786 : /* If we have code like
6787 :
6788 : *(const A*)(A*)&x
6789 :
6790 : where the type of "x" is a (possibly cv-qualified variant
6791 : of "A"), treat the entire expression as identical to "x".
6792 : This kind of code arises in C++ when an object is bound
6793 : to a const reference, and if "x" is a TARGET_EXPR we want
6794 : to take advantage of the optimization below. But not if
6795 : the type is TREE_ADDRESSABLE; then C++17 says that the
6796 : TARGET_EXPR needs to be a temporary. */
6797 1032484 : if (tree t
6798 516242 : = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)))
6799 : {
6800 121129 : bool volatile_p = TREE_THIS_VOLATILE (*from_p);
6801 121129 : if (TREE_THIS_VOLATILE (t) != volatile_p)
6802 : {
6803 5 : if (DECL_P (t))
6804 0 : t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
6805 : build_fold_addr_expr (t));
6806 5 : if (REFERENCE_CLASS_P (t))
6807 5 : TREE_THIS_VOLATILE (t) = volatile_p;
6808 : }
6809 121129 : *from_p = t;
6810 121129 : ret = GS_OK;
6811 121129 : changed = true;
6812 : }
6813 : break;
6814 :
6815 180167 : case TARGET_EXPR:
6816 180167 : {
6817 : /* If we are initializing something from a TARGET_EXPR, strip the
6818 : TARGET_EXPR and initialize it directly, if possible. This can't
6819 : be done if the initializer is void, since that implies that the
6820 : temporary is set in some non-trivial way.
6821 :
6822 : ??? What about code that pulls out the temp and uses it
6823 : elsewhere? I think that such code never uses the TARGET_EXPR as
6824 : an initializer. If I'm wrong, we'll die because the temp won't
6825 : have any RTL. In that case, I guess we'll need to replace
6826 : references somehow. */
6827 180167 : tree init = TARGET_EXPR_INITIAL (*from_p);
6828 :
6829 180167 : if (init
6830 179451 : && (TREE_CODE (*expr_p) != MODIFY_EXPR
6831 46747 : || !TARGET_EXPR_NO_ELIDE (*from_p))
6832 359412 : && !VOID_TYPE_P (TREE_TYPE (init)))
6833 : {
6834 165655 : *from_p = init;
6835 165655 : ret = GS_OK;
6836 165655 : changed = true;
6837 : }
6838 : }
6839 : break;
6840 :
6841 331059 : case COMPOUND_EXPR:
6842 : /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
6843 : caught. */
6844 331059 : gimplify_compound_expr (from_p, pre_p, true);
6845 331059 : ret = GS_OK;
6846 331059 : changed = true;
6847 331059 : break;
6848 :
6849 1320741 : case CONSTRUCTOR:
6850 : /* If we already made some changes, let the front end have a
6851 : crack at this before we break it down. */
6852 1320741 : if (ret != GS_UNHANDLED)
6853 : break;
6854 :
6855 : /* If we're initializing from a CONSTRUCTOR, break this into
6856 : individual MODIFY_EXPRs. */
6857 1299384 : ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
6858 : false);
6859 1299384 : return ret;
6860 :
6861 223322 : case COND_EXPR:
6862 : /* If we're assigning to a non-register type, push the assignment
6863 : down into the branches. This is mandatory for ADDRESSABLE types,
6864 : since we cannot generate temporaries for such, but it saves a
6865 : copy in other cases as well.
6866 : Also avoid an extra temporary and copy when assigning to
6867 : a register. */
6868 223322 : if (!is_gimple_reg_type (TREE_TYPE (*from_p))
6869 223322 : || (is_gimple_reg (*to_p) && !gimplify_ctxp->allow_rhs_cond_expr))
6870 : {
6871 : /* This code should mirror the code in gimplify_cond_expr. */
6872 141633 : enum tree_code code = TREE_CODE (*expr_p);
6873 141633 : tree cond = *from_p;
6874 141633 : tree result = *to_p;
6875 :
6876 141633 : ret = gimplify_expr (&result, pre_p, post_p,
6877 : is_gimple_lvalue, fb_lvalue);
6878 141633 : if (ret != GS_ERROR)
6879 141633 : ret = GS_OK;
6880 :
6881 : /* If we are going to write RESULT more than once, clear
6882 : TREE_READONLY flag, otherwise we might incorrectly promote
6883 : the variable to static const and initialize it at compile
6884 : time in one of the branches. */
6885 141633 : if (VAR_P (result)
6886 140603 : && TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node
6887 273163 : && TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6888 131438 : TREE_READONLY (result) = 0;
6889 141633 : if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
6890 132424 : TREE_OPERAND (cond, 1)
6891 264848 : = build2 (code, void_type_node, result,
6892 132424 : TREE_OPERAND (cond, 1));
6893 141633 : if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6894 141541 : TREE_OPERAND (cond, 2)
6895 283082 : = build2 (code, void_type_node, unshare_expr (result),
6896 141541 : TREE_OPERAND (cond, 2));
6897 :
6898 141633 : TREE_TYPE (cond) = void_type_node;
6899 141633 : recalculate_side_effects (cond);
6900 :
6901 141633 : if (want_value)
6902 : {
6903 68 : gimplify_and_add (cond, pre_p);
6904 68 : *expr_p = unshare_expr (result);
6905 : }
6906 : else
6907 141565 : *expr_p = cond;
6908 141633 : return ret;
6909 : }
6910 : break;
6911 :
6912 9819269 : case CALL_EXPR:
6913 : /* For calls that return in memory, give *to_p as the CALL_EXPR's
6914 : return slot so that we don't generate a temporary. */
6915 9819269 : if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
6916 9819269 : && aggregate_value_p (*from_p, *from_p))
6917 : {
6918 248795 : bool use_target;
6919 :
6920 248795 : if (!(rhs_predicate_for (*to_p))(*from_p))
6921 : /* If we need a temporary, *to_p isn't accurate. */
6922 : use_target = false;
6923 : /* It's OK to use the return slot directly unless it's an NRV. */
6924 248023 : else if (TREE_CODE (*to_p) == RESULT_DECL
6925 5649 : && DECL_NAME (*to_p) == NULL_TREE
6926 253528 : && needs_to_live_in_memory (*to_p))
6927 : use_target = true;
6928 242518 : else if (is_gimple_reg_type (TREE_TYPE (*to_p))
6929 242518 : || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
6930 : /* Don't force regs into memory. */
6931 : use_target = false;
6932 228227 : else if (TREE_CODE (*expr_p) == INIT_EXPR)
6933 : /* It's OK to use the target directly if it's being
6934 : initialized. */
6935 : use_target = true;
6936 14291 : else if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p)))
6937 : != INTEGER_CST)
6938 : /* Always use the target and thus RSO for variable-sized types.
6939 : GIMPLE cannot deal with a variable-sized assignment
6940 : embedded in a call statement. */
6941 : use_target = true;
6942 14263 : else if (TREE_CODE (*to_p) != SSA_NAME
6943 14263 : && (!is_gimple_variable (*to_p)
6944 11025 : || needs_to_live_in_memory (*to_p)))
6945 : /* Don't use the original target if it's already addressable;
6946 : if its address escapes, and the called function uses the
6947 : NRV optimization, a conforming program could see *to_p
6948 : change before the called function returns; see c++/19317.
6949 : When optimizing, the return_slot pass marks more functions
6950 : as safe after we have escape info. */
6951 : use_target = false;
6952 : else
6953 : use_target = true;
6954 :
6955 : if (use_target)
6956 : {
6957 221567 : CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
6958 221567 : mark_addressable (*to_p);
6959 : }
6960 : }
6961 : break;
6962 :
6963 1549 : case WITH_SIZE_EXPR:
6964 : /* Likewise for calls that return an aggregate of non-constant size,
6965 : since we would not be able to generate a temporary at all. */
6966 1549 : if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
6967 : {
6968 351 : *from_p = TREE_OPERAND (*from_p, 0);
6969 : /* We don't change ret in this case because the
6970 : WITH_SIZE_EXPR might have been added in
6971 : gimplify_modify_expr, so returning GS_OK would lead to an
6972 : infinite loop. */
6973 351 : changed = true;
6974 : }
6975 : break;
6976 :
6977 : /* If we're initializing from a container, push the initialization
6978 : inside it. */
6979 1864 : case CLEANUP_POINT_EXPR:
6980 1864 : case BIND_EXPR:
6981 1864 : case STATEMENT_LIST:
6982 1864 : {
6983 1864 : tree wrap = *from_p;
6984 1864 : tree t;
6985 :
6986 1864 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
6987 : fb_lvalue);
6988 1864 : if (ret != GS_ERROR)
6989 1864 : ret = GS_OK;
6990 :
6991 1864 : t = voidify_wrapper_expr (wrap, *expr_p);
6992 1864 : gcc_assert (t == *expr_p);
6993 :
6994 1864 : if (want_value)
6995 : {
6996 6 : gimplify_and_add (wrap, pre_p);
6997 6 : *expr_p = unshare_expr (*to_p);
6998 : }
6999 : else
7000 1858 : *expr_p = wrap;
7001 : return GS_OK;
7002 : }
7003 :
7004 9495619 : case NOP_EXPR:
7005 : /* Pull out compound literal expressions from a NOP_EXPR.
7006 : Those are created in the C FE to drop qualifiers during
7007 : lvalue conversion. */
7008 9495619 : if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR)
7009 9495619 : && tree_ssa_useless_type_conversion (*from_p))
7010 : {
7011 13 : *from_p = TREE_OPERAND (*from_p, 0);
7012 13 : ret = GS_OK;
7013 13 : changed = true;
7014 : }
7015 : break;
7016 :
7017 4426 : case COMPOUND_LITERAL_EXPR:
7018 4426 : {
7019 4426 : tree complit = TREE_OPERAND (*expr_p, 1);
7020 4426 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
7021 4426 : tree decl = DECL_EXPR_DECL (decl_s);
7022 4426 : tree init = DECL_INITIAL (decl);
7023 :
7024 : /* struct T x = (struct T) { 0, 1, 2 } can be optimized
7025 : into struct T x = { 0, 1, 2 } if the address of the
7026 : compound literal has never been taken. */
7027 4426 : if (!TREE_ADDRESSABLE (complit)
7028 4426 : && !TREE_ADDRESSABLE (decl)
7029 4426 : && init)
7030 : {
7031 4426 : *expr_p = copy_node (*expr_p);
7032 4426 : TREE_OPERAND (*expr_p, 1) = init;
7033 4426 : return GS_OK;
7034 : }
7035 : }
7036 :
7037 : default:
7038 : break;
7039 : }
7040 : }
7041 : while (changed);
7042 :
7043 : return ret;
7044 : }
7045 :
7046 :
7047 : /* Return true if T looks like a valid GIMPLE statement. */
7048 :
7049 : static bool
7050 19085228 : is_gimple_stmt (tree t)
7051 : {
7052 19085228 : const enum tree_code code = TREE_CODE (t);
7053 :
7054 19085228 : switch (code)
7055 : {
7056 1720189 : case NOP_EXPR:
7057 : /* The only valid NOP_EXPR is the empty statement. */
7058 1720189 : return IS_EMPTY_STMT (t);
7059 :
7060 0 : case BIND_EXPR:
7061 0 : case COND_EXPR:
7062 : /* These are only valid if they're void. */
7063 0 : return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
7064 :
7065 : case SWITCH_EXPR:
7066 : case GOTO_EXPR:
7067 : case RETURN_EXPR:
7068 : case LABEL_EXPR:
7069 : case CASE_LABEL_EXPR:
7070 : case TRY_CATCH_EXPR:
7071 : case TRY_FINALLY_EXPR:
7072 : case EH_FILTER_EXPR:
7073 : case CATCH_EXPR:
7074 : case ASM_EXPR:
7075 : case STATEMENT_LIST:
7076 : case OACC_PARALLEL:
7077 : case OACC_KERNELS:
7078 : case OACC_SERIAL:
7079 : case OACC_DATA:
7080 : case OACC_HOST_DATA:
7081 : case OACC_DECLARE:
7082 : case OACC_UPDATE:
7083 : case OACC_ENTER_DATA:
7084 : case OACC_EXIT_DATA:
7085 : case OACC_CACHE:
7086 : case OMP_PARALLEL:
7087 : case OMP_FOR:
7088 : case OMP_SIMD:
7089 : case OMP_DISTRIBUTE:
7090 : case OMP_LOOP:
7091 : case OMP_TILE:
7092 : case OMP_UNROLL:
7093 : case OACC_LOOP:
7094 : case OMP_SCAN:
7095 : case OMP_SCOPE:
7096 : case OMP_DISPATCH:
7097 : case OMP_SECTIONS:
7098 : case OMP_SECTION:
7099 : case OMP_STRUCTURED_BLOCK:
7100 : case OMP_SINGLE:
7101 : case OMP_MASTER:
7102 : case OMP_MASKED:
7103 : case OMP_TASKGROUP:
7104 : case OMP_ORDERED:
7105 : case OMP_CRITICAL:
7106 : case OMP_METADIRECTIVE:
7107 : case OMP_TASK:
7108 : case OMP_TARGET:
7109 : case OMP_TARGET_DATA:
7110 : case OMP_TARGET_UPDATE:
7111 : case OMP_TARGET_ENTER_DATA:
7112 : case OMP_TARGET_EXIT_DATA:
7113 : case OMP_TASKLOOP:
7114 : case OMP_TEAMS:
7115 : /* These are always void. */
7116 : return true;
7117 :
7118 : case CALL_EXPR:
7119 : case MODIFY_EXPR:
7120 : case PREDICT_EXPR:
7121 : /* These are valid regardless of their type. */
7122 : return true;
7123 :
7124 : default:
7125 : return false;
7126 : }
7127 : }
7128 :
7129 :
7130 : /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
7131 : a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
7132 :
7133 : IMPORTANT NOTE: This promotion is performed by introducing a load of the
7134 : other, unmodified part of the complex object just before the total store.
7135 : As a consequence, if the object is still uninitialized, an undefined value
7136 : will be loaded into a register, which may result in a spurious exception
7137 : if the register is floating-point and the value happens to be a signaling
7138 : NaN for example. Then the fully-fledged complex operations lowering pass
7139 : followed by a DCE pass are necessary in order to fix things up. */
7140 :
7141 : static enum gimplify_status
7142 1942 : gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
7143 : bool want_value)
7144 : {
7145 1942 : enum tree_code code, ocode;
7146 1942 : tree lhs, rhs, new_rhs, other, realpart, imagpart;
7147 :
7148 1942 : lhs = TREE_OPERAND (*expr_p, 0);
7149 1942 : rhs = TREE_OPERAND (*expr_p, 1);
7150 1942 : code = TREE_CODE (lhs);
7151 1942 : lhs = TREE_OPERAND (lhs, 0);
7152 :
7153 1942 : ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
7154 1942 : other = build1 (ocode, TREE_TYPE (rhs), lhs);
7155 1942 : suppress_warning (other);
7156 1942 : other = get_formal_tmp_var (other, pre_p);
7157 :
7158 1942 : realpart = code == REALPART_EXPR ? rhs : other;
7159 957 : imagpart = code == REALPART_EXPR ? other : rhs;
7160 :
7161 1942 : if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
7162 0 : new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
7163 : else
7164 1942 : new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
7165 :
7166 1942 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
7167 1942 : *expr_p = (want_value) ? rhs : NULL_TREE;
7168 :
7169 1942 : return GS_ALL_DONE;
7170 : }
7171 :
7172 : /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
7173 :
7174 : modify_expr
7175 : : varname '=' rhs
7176 : | '*' ID '=' rhs
7177 :
7178 : PRE_P points to the list where side effects that must happen before
7179 : *EXPR_P should be stored.
7180 :
7181 : POST_P points to the list where side effects that must happen after
7182 : *EXPR_P should be stored.
7183 :
7184 : WANT_VALUE is nonzero iff we want to use the value of this expression
7185 : in another expression. */
7186 :
7187 : static enum gimplify_status
7188 49932830 : gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
7189 : bool want_value)
7190 : {
7191 49932830 : tree *from_p = &TREE_OPERAND (*expr_p, 1);
7192 49932830 : tree *to_p = &TREE_OPERAND (*expr_p, 0);
7193 49932830 : enum gimplify_status ret = GS_UNHANDLED;
7194 49932830 : gimple *assign;
7195 49932830 : location_t loc = EXPR_LOCATION (*expr_p);
7196 49932830 : gimple_stmt_iterator gsi;
7197 :
7198 49932830 : if (error_operand_p (*from_p) || error_operand_p (*to_p))
7199 : return GS_ERROR;
7200 :
7201 49932802 : gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
7202 : || TREE_CODE (*expr_p) == INIT_EXPR);
7203 :
7204 : /* Trying to simplify a clobber using normal logic doesn't work,
7205 : so handle it here. */
7206 49932802 : if (TREE_CLOBBER_P (*from_p))
7207 : {
7208 571752 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7209 571752 : if (ret == GS_ERROR)
7210 : return ret;
7211 571752 : gcc_assert (!want_value);
7212 571752 : if (!VAR_P (*to_p) && TREE_CODE (*to_p) != MEM_REF)
7213 : {
7214 199 : tree addr = get_initialized_tmp_var (build_fold_addr_expr (*to_p),
7215 : pre_p, post_p);
7216 199 : *to_p = build_simple_mem_ref_loc (EXPR_LOCATION (*to_p), addr);
7217 : }
7218 571752 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
7219 571752 : *expr_p = NULL;
7220 571752 : return GS_ALL_DONE;
7221 : }
7222 :
7223 : /* Convert initialization from an empty variable-size CONSTRUCTOR to
7224 : memset. */
7225 49361050 : if (TREE_TYPE (*from_p) != error_mark_node
7226 49361050 : && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
7227 49361050 : && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
7228 1582 : && TREE_CODE (*from_p) == CONSTRUCTOR
7229 49361154 : && CONSTRUCTOR_NELTS (*from_p) == 0)
7230 : {
7231 84 : maybe_with_size_expr (from_p);
7232 84 : gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
7233 84 : return gimplify_modify_expr_to_memset (expr_p,
7234 84 : TREE_OPERAND (*from_p, 1),
7235 84 : want_value, pre_p);
7236 : }
7237 :
7238 : /* Insert pointer conversions required by the middle-end that are not
7239 : required by the frontend. This fixes middle-end type checking for
7240 : for example gcc.dg/redecl-6.c. */
7241 49360966 : if (POINTER_TYPE_P (TREE_TYPE (*to_p)))
7242 : {
7243 13376559 : STRIP_USELESS_TYPE_CONVERSION (*from_p);
7244 13376559 : if (!useless_type_conversion_p (TREE_TYPE (*to_p), TREE_TYPE (*from_p)))
7245 521 : *from_p = fold_convert_loc (loc, TREE_TYPE (*to_p), *from_p);
7246 : }
7247 :
7248 : /* See if any simplifications can be done based on what the RHS is. */
7249 49360966 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7250 : want_value);
7251 49360966 : if (ret != GS_UNHANDLED)
7252 : return ret;
7253 :
7254 : /* For empty types only gimplify the left hand side and right hand
7255 : side as statements and throw away the assignment. Do this after
7256 : gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable
7257 : types properly. */
7258 47357227 : if (is_empty_type (TREE_TYPE (*from_p))
7259 13527 : && !want_value
7260 : /* Don't do this for calls that return addressable types, expand_call
7261 : relies on those having a lhs. */
7262 47370747 : && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
7263 11419 : && TREE_CODE (*from_p) == CALL_EXPR))
7264 : {
7265 2101 : suppress_warning (*from_p, OPT_Wunused_result);
7266 2101 : gimplify_stmt (from_p, pre_p);
7267 2101 : gimplify_stmt (to_p, pre_p);
7268 2101 : *expr_p = NULL_TREE;
7269 2101 : return GS_ALL_DONE;
7270 : }
7271 :
7272 : /* If the value being copied is of variable width, compute the length
7273 : of the copy into a WITH_SIZE_EXPR. Note that we need to do this
7274 : before gimplifying any of the operands so that we can resolve any
7275 : PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
7276 : the size of the expression to be copied, not of the destination, so
7277 : that is what we must do here. */
7278 47355126 : maybe_with_size_expr (from_p);
7279 :
7280 : /* As a special case, we have to temporarily allow for assignments
7281 : with a CALL_EXPR on the RHS. Since in GIMPLE a function call is
7282 : a toplevel statement, when gimplifying the GENERIC expression
7283 : MODIFY_EXPR <a, CALL_EXPR <foo>>, we cannot create the tuple
7284 : GIMPLE_ASSIGN <a, GIMPLE_CALL <foo>>.
7285 :
7286 : Instead, we need to create the tuple GIMPLE_CALL <a, foo>. To
7287 : prevent gimplify_expr from trying to create a new temporary for
7288 : foo's LHS, we tell it that it should only gimplify until it
7289 : reaches the CALL_EXPR. On return from gimplify_expr, the newly
7290 : created GIMPLE_CALL <foo> will be the last statement in *PRE_P
7291 : and all we need to do here is set 'a' to be its LHS. */
7292 :
7293 : /* Gimplify the RHS first for C++17 and bug 71104. */
7294 47355126 : gimple_predicate initial_pred = initial_rhs_predicate_for (*to_p);
7295 47355126 : ret = gimplify_expr (from_p, pre_p, post_p, initial_pred, fb_rvalue);
7296 47355126 : if (ret == GS_ERROR)
7297 : return ret;
7298 :
7299 : /* Then gimplify the LHS. */
7300 : /* If we gimplified the RHS to a CALL_EXPR and that call may return
7301 : twice we have to make sure to gimplify into non-SSA as otherwise
7302 : the abnormal edge added later will make those defs not dominate
7303 : their uses.
7304 : ??? Technically this applies only to the registers used in the
7305 : resulting non-register *TO_P. */
7306 47354970 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
7307 47354970 : if (saved_into_ssa
7308 45001769 : && TREE_CODE (*from_p) == CALL_EXPR
7309 52346465 : && call_expr_flags (*from_p) & ECF_RETURNS_TWICE)
7310 1523 : gimplify_ctxp->into_ssa = false;
7311 47354970 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7312 47354970 : gimplify_ctxp->into_ssa = saved_into_ssa;
7313 47354970 : if (ret == GS_ERROR)
7314 : return ret;
7315 :
7316 : /* Now that the LHS is gimplified, re-gimplify the RHS if our initial
7317 : guess for the predicate was wrong. */
7318 47354895 : gimple_predicate final_pred = rhs_predicate_for (*to_p);
7319 47354895 : if (final_pred != initial_pred)
7320 : {
7321 8083514 : ret = gimplify_expr (from_p, pre_p, post_p, final_pred, fb_rvalue);
7322 8083514 : if (ret == GS_ERROR)
7323 : return ret;
7324 : }
7325 :
7326 : /* In case of va_arg internal fn wrappped in a WITH_SIZE_EXPR, add the type
7327 : size as argument to the call. */
7328 47354895 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7329 : {
7330 1446 : tree call = TREE_OPERAND (*from_p, 0);
7331 1446 : tree vlasize = TREE_OPERAND (*from_p, 1);
7332 :
7333 1446 : if (TREE_CODE (call) == CALL_EXPR
7334 1446 : && CALL_EXPR_IFN (call) == IFN_VA_ARG)
7335 : {
7336 95 : int nargs = call_expr_nargs (call);
7337 95 : tree type = TREE_TYPE (call);
7338 95 : tree ap = CALL_EXPR_ARG (call, 0);
7339 95 : tree tag = CALL_EXPR_ARG (call, 1);
7340 95 : tree aptag = CALL_EXPR_ARG (call, 2);
7341 95 : tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
7342 : IFN_VA_ARG, type,
7343 : nargs + 1, ap, tag,
7344 : aptag, vlasize);
7345 95 : TREE_OPERAND (*from_p, 0) = newcall;
7346 : }
7347 : }
7348 :
7349 : /* Now see if the above changed *from_p to something we handle specially. */
7350 47354895 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7351 : want_value);
7352 47354895 : if (ret != GS_UNHANDLED)
7353 : return ret;
7354 :
7355 : /* If we've got a variable sized assignment between two lvalues (i.e. does
7356 : not involve a call), then we can make things a bit more straightforward
7357 : by converting the assignment to memcpy or memset. */
7358 47353932 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7359 : {
7360 1095 : tree from = TREE_OPERAND (*from_p, 0);
7361 1095 : tree size = TREE_OPERAND (*from_p, 1);
7362 :
7363 1095 : if (TREE_CODE (from) == CONSTRUCTOR)
7364 0 : return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
7365 1095 : else if (is_gimple_addressable (from)
7366 1095 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (*to_p)))
7367 2189 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))))
7368 : {
7369 1094 : *from_p = from;
7370 1094 : return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
7371 1094 : pre_p);
7372 : }
7373 : }
7374 :
7375 : /* Transform partial stores to non-addressable complex variables into
7376 : total stores. This allows us to use real instead of virtual operands
7377 : for these variables, which improves optimization. */
7378 47352838 : if ((TREE_CODE (*to_p) == REALPART_EXPR
7379 47352838 : || TREE_CODE (*to_p) == IMAGPART_EXPR)
7380 47352838 : && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
7381 1942 : return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
7382 :
7383 : /* Try to alleviate the effects of the gimplification creating artificial
7384 : temporaries (see for example is_gimple_reg_rhs) on the debug info, but
7385 : make sure not to create DECL_DEBUG_EXPR links across functions. */
7386 47350896 : if (!gimplify_ctxp->into_ssa
7387 2352287 : && VAR_P (*from_p)
7388 469528 : && DECL_IGNORED_P (*from_p)
7389 348876 : && DECL_P (*to_p)
7390 137521 : && !DECL_IGNORED_P (*to_p)
7391 37973 : && decl_function_context (*to_p) == current_function_decl
7392 47383309 : && decl_function_context (*from_p) == current_function_decl)
7393 : {
7394 32408 : if (!DECL_NAME (*from_p) && DECL_NAME (*to_p))
7395 27158 : DECL_NAME (*from_p)
7396 54316 : = create_tmp_var_name (IDENTIFIER_POINTER (DECL_NAME (*to_p)));
7397 32408 : DECL_HAS_DEBUG_EXPR_P (*from_p) = 1;
7398 32408 : SET_DECL_DEBUG_EXPR (*from_p, *to_p);
7399 : }
7400 :
7401 47350896 : if (want_value && TREE_THIS_VOLATILE (*to_p))
7402 526 : *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
7403 :
7404 47350896 : if (TREE_CODE (*from_p) == CALL_EXPR)
7405 : {
7406 : /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
7407 : instead of a GIMPLE_ASSIGN. */
7408 4700624 : gcall *call_stmt;
7409 4700624 : if (CALL_EXPR_FN (*from_p) == NULL_TREE)
7410 : {
7411 : /* Gimplify internal functions created in the FEs. */
7412 305699 : int nargs = call_expr_nargs (*from_p), i;
7413 305699 : enum internal_fn ifn = CALL_EXPR_IFN (*from_p);
7414 305699 : auto_vec<tree> vargs (nargs);
7415 :
7416 1540960 : for (i = 0; i < nargs; i++)
7417 : {
7418 929562 : gimplify_arg (&CALL_EXPR_ARG (*from_p, i), pre_p,
7419 929562 : EXPR_LOCATION (*from_p));
7420 929562 : vargs.quick_push (CALL_EXPR_ARG (*from_p, i));
7421 : }
7422 305699 : call_stmt = gimple_build_call_internal_vec (ifn, vargs);
7423 305699 : gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p));
7424 611398 : gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p));
7425 305699 : }
7426 : else
7427 : {
7428 4394925 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
7429 4394925 : CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
7430 4394925 : STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
7431 4394925 : tree fndecl = get_callee_fndecl (*from_p);
7432 4394925 : if (fndecl
7433 4280171 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
7434 4529319 : && call_expr_nargs (*from_p) == 3)
7435 66447 : call_stmt = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3,
7436 66447 : CALL_EXPR_ARG (*from_p, 0),
7437 66447 : CALL_EXPR_ARG (*from_p, 1),
7438 66447 : CALL_EXPR_ARG (*from_p, 2));
7439 : else
7440 : {
7441 4328478 : call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
7442 : }
7443 : }
7444 4700624 : notice_special_calls (call_stmt);
7445 4700624 : if (!gimple_call_noreturn_p (call_stmt) || !should_remove_lhs_p (*to_p))
7446 4700443 : gimple_call_set_lhs (call_stmt, *to_p);
7447 181 : else if (TREE_CODE (*to_p) == SSA_NAME)
7448 : /* The above is somewhat premature, avoid ICEing later for a
7449 : SSA name w/o a definition. We may have uses in the GIMPLE IL.
7450 : ??? This doesn't make it a default-def. */
7451 86 : SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop ();
7452 :
7453 : assign = call_stmt;
7454 : }
7455 : else
7456 : {
7457 42650272 : assign = gimple_build_assign (*to_p, *from_p);
7458 42650272 : gimple_set_location (assign, EXPR_LOCATION (*expr_p));
7459 42650272 : if (COMPARISON_CLASS_P (*from_p))
7460 1222960 : copy_warning (assign, *from_p);
7461 : }
7462 :
7463 47350896 : if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
7464 : {
7465 : /* We should have got an SSA name from the start. */
7466 35033828 : gcc_assert (TREE_CODE (*to_p) == SSA_NAME
7467 : || ! gimple_in_ssa_p (cfun));
7468 : }
7469 :
7470 47350896 : gimplify_seq_add_stmt (pre_p, assign);
7471 47350896 : gsi = gsi_last (*pre_p);
7472 47350896 : maybe_fold_stmt (&gsi);
7473 :
7474 47350896 : if (want_value)
7475 : {
7476 657814 : *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
7477 657814 : return GS_OK;
7478 : }
7479 : else
7480 46693082 : *expr_p = NULL;
7481 :
7482 46693082 : return GS_ALL_DONE;
7483 : }
7484 :
7485 : /* Gimplify a comparison between two variable-sized objects. Do this
7486 : with a call to BUILT_IN_MEMCMP. */
7487 :
7488 : static enum gimplify_status
7489 0 : gimplify_variable_sized_compare (tree *expr_p)
7490 : {
7491 0 : location_t loc = EXPR_LOCATION (*expr_p);
7492 0 : tree op0 = TREE_OPERAND (*expr_p, 0);
7493 0 : tree op1 = TREE_OPERAND (*expr_p, 1);
7494 0 : tree t, arg, dest, src, expr;
7495 :
7496 0 : arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
7497 0 : arg = unshare_expr (arg);
7498 0 : arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
7499 0 : src = build_fold_addr_expr_loc (loc, op1);
7500 0 : dest = build_fold_addr_expr_loc (loc, op0);
7501 0 : t = builtin_decl_implicit (BUILT_IN_MEMCMP);
7502 0 : t = build_call_expr_loc (loc, t, 3, dest, src, arg);
7503 :
7504 0 : expr
7505 0 : = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
7506 0 : SET_EXPR_LOCATION (expr, loc);
7507 0 : *expr_p = expr;
7508 :
7509 0 : return GS_OK;
7510 : }
7511 :
7512 : /* Gimplify a comparison between two aggregate objects of integral scalar
7513 : mode as a comparison between the bitwise equivalent scalar values. */
7514 :
7515 : static enum gimplify_status
7516 16 : gimplify_scalar_mode_aggregate_compare (tree *expr_p)
7517 : {
7518 16 : const location_t loc = EXPR_LOCATION (*expr_p);
7519 16 : const enum tree_code code = TREE_CODE (*expr_p);
7520 16 : tree op0 = TREE_OPERAND (*expr_p, 0);
7521 16 : tree op1 = TREE_OPERAND (*expr_p, 1);
7522 16 : tree type = TREE_TYPE (op0);
7523 16 : tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
7524 :
7525 16 : op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
7526 16 : op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
7527 :
7528 : /* We need to perform ordering comparisons in memory order like memcmp and,
7529 : therefore, may need to byte-swap operands for little-endian targets. */
7530 16 : if (code != EQ_EXPR && code != NE_EXPR)
7531 : {
7532 0 : gcc_assert (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN);
7533 0 : gcc_assert (TREE_CODE (scalar_type) == INTEGER_TYPE);
7534 0 : tree fndecl;
7535 :
7536 0 : if (BYTES_BIG_ENDIAN)
7537 : fndecl = NULL_TREE;
7538 : else
7539 0 : switch (int_size_in_bytes (scalar_type))
7540 : {
7541 : case 1:
7542 : fndecl = NULL_TREE;
7543 : break;
7544 0 : case 2:
7545 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP16);
7546 0 : break;
7547 0 : case 4:
7548 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP32);
7549 0 : break;
7550 0 : case 8:
7551 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP64);
7552 0 : break;
7553 0 : case 16:
7554 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP128);
7555 0 : break;
7556 0 : default:
7557 0 : gcc_unreachable ();
7558 : }
7559 :
7560 0 : if (fndecl)
7561 : {
7562 0 : op0 = build_call_expr_loc (loc, fndecl, 1, op0);
7563 0 : op1 = build_call_expr_loc (loc, fndecl, 1, op1);
7564 : }
7565 : }
7566 :
7567 16 : *expr_p = fold_build2_loc (loc, code, TREE_TYPE (*expr_p), op0, op1);
7568 :
7569 16 : return GS_OK;
7570 : }
7571 :
7572 : /* Gimplify an expression sequence. This function gimplifies each
7573 : expression and rewrites the original expression with the last
7574 : expression of the sequence in GIMPLE form.
7575 :
7576 : PRE_P points to the list where the side effects for all the
7577 : expressions in the sequence will be emitted.
7578 :
7579 : WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
7580 :
7581 : static enum gimplify_status
7582 1096753 : gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
7583 : {
7584 1096753 : tree t = *expr_p;
7585 :
7586 1183986 : do
7587 : {
7588 1183986 : tree *sub_p = &TREE_OPERAND (t, 0);
7589 :
7590 1183986 : if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
7591 204782 : gimplify_compound_expr (sub_p, pre_p, false);
7592 : else
7593 979204 : gimplify_stmt (sub_p, pre_p);
7594 :
7595 1183986 : t = TREE_OPERAND (t, 1);
7596 : }
7597 1183986 : while (TREE_CODE (t) == COMPOUND_EXPR);
7598 :
7599 1096753 : *expr_p = t;
7600 1096753 : if (want_value)
7601 : return GS_OK;
7602 : else
7603 : {
7604 599887 : gimplify_stmt (expr_p, pre_p);
7605 599887 : return GS_ALL_DONE;
7606 : }
7607 : }
7608 :
7609 : /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
7610 : gimplify. After gimplification, EXPR_P will point to a new temporary
7611 : that holds the original value of the SAVE_EXPR node.
7612 :
7613 : PRE_P points to the list where side effects that must happen before
7614 : *EXPR_P should be stored. */
7615 :
7616 : static enum gimplify_status
7617 440002 : gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7618 : {
7619 440002 : enum gimplify_status ret = GS_ALL_DONE;
7620 440002 : tree val;
7621 :
7622 440002 : gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
7623 440002 : val = TREE_OPERAND (*expr_p, 0);
7624 :
7625 440002 : if (val && TREE_TYPE (val) == error_mark_node)
7626 : return GS_ERROR;
7627 :
7628 : /* If the SAVE_EXPR has not been resolved, then evaluate it once. */
7629 440000 : if (!SAVE_EXPR_RESOLVED_P (*expr_p))
7630 : {
7631 : /* The operand may be a void-valued expression. It is
7632 : being executed only for its side-effects. */
7633 168733 : if (TREE_TYPE (val) == void_type_node)
7634 : {
7635 750 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7636 : is_gimple_stmt, fb_none);
7637 750 : val = NULL;
7638 : }
7639 : else
7640 : /* The temporary may not be an SSA name as later abnormal and EH
7641 : control flow may invalidate use/def domination. When in SSA
7642 : form then assume there are no such issues and SAVE_EXPRs only
7643 : appear via GENERIC foldings. */
7644 335966 : val = get_initialized_tmp_var (val, pre_p, post_p,
7645 335966 : gimple_in_ssa_p (cfun));
7646 :
7647 168733 : TREE_OPERAND (*expr_p, 0) = val;
7648 168733 : SAVE_EXPR_RESOLVED_P (*expr_p) = 1;
7649 : }
7650 :
7651 440000 : *expr_p = val;
7652 :
7653 440000 : return ret;
7654 : }
7655 :
7656 : /* Rewrite the ADDR_EXPR node pointed to by EXPR_P
7657 :
7658 : unary_expr
7659 : : ...
7660 : | '&' varname
7661 : ...
7662 :
7663 : PRE_P points to the list where side effects that must happen before
7664 : *EXPR_P should be stored.
7665 :
7666 : POST_P points to the list where side effects that must happen after
7667 : *EXPR_P should be stored. */
7668 :
7669 : static enum gimplify_status
7670 32770926 : gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7671 : {
7672 32770926 : tree expr = *expr_p;
7673 32770926 : tree op0 = TREE_OPERAND (expr, 0);
7674 32770926 : enum gimplify_status ret;
7675 32770926 : location_t loc = EXPR_LOCATION (*expr_p);
7676 :
7677 32770926 : switch (TREE_CODE (op0))
7678 : {
7679 98604 : case INDIRECT_REF:
7680 98604 : do_indirect_ref:
7681 : /* Check if we are dealing with an expression of the form '&*ptr'.
7682 : While the front end folds away '&*ptr' into 'ptr', these
7683 : expressions may be generated internally by the compiler (e.g.,
7684 : builtins like __builtin_va_end). */
7685 : /* Caution: the silent array decomposition semantics we allow for
7686 : ADDR_EXPR means we can't always discard the pair. */
7687 : /* Gimplification of the ADDR_EXPR operand may drop
7688 : cv-qualification conversions, so make sure we add them if
7689 : needed. */
7690 98604 : {
7691 98604 : tree op00 = TREE_OPERAND (op0, 0);
7692 98604 : tree t_expr = TREE_TYPE (expr);
7693 98604 : tree t_op00 = TREE_TYPE (op00);
7694 :
7695 98604 : if (!useless_type_conversion_p (t_expr, t_op00))
7696 0 : op00 = fold_convert_loc (loc, TREE_TYPE (expr), op00);
7697 98604 : *expr_p = op00;
7698 98604 : ret = GS_OK;
7699 : }
7700 98604 : break;
7701 :
7702 0 : case VIEW_CONVERT_EXPR:
7703 : /* Take the address of our operand and then convert it to the type of
7704 : this ADDR_EXPR.
7705 :
7706 : ??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
7707 : all clear. The impact of this transformation is even less clear. */
7708 :
7709 : /* If the operand is a useless conversion, look through it. Doing so
7710 : guarantees that the ADDR_EXPR and its operand will remain of the
7711 : same type. */
7712 0 : if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
7713 0 : op0 = TREE_OPERAND (op0, 0);
7714 :
7715 0 : *expr_p = fold_convert_loc (loc, TREE_TYPE (expr),
7716 : build_fold_addr_expr_loc (loc,
7717 0 : TREE_OPERAND (op0, 0)));
7718 0 : ret = GS_OK;
7719 0 : break;
7720 :
7721 65199 : case MEM_REF:
7722 65199 : if (integer_zerop (TREE_OPERAND (op0, 1)))
7723 36675 : goto do_indirect_ref;
7724 :
7725 : /* fall through */
7726 :
7727 32689553 : default:
7728 : /* If we see a call to a declared builtin or see its address
7729 : being taken (we can unify those cases here) then we can mark
7730 : the builtin for implicit generation by GCC. */
7731 32689553 : if (TREE_CODE (op0) == FUNCTION_DECL
7732 16347558 : && fndecl_built_in_p (op0, BUILT_IN_NORMAL)
7733 36641686 : && builtin_decl_declared_p (DECL_FUNCTION_CODE (op0)))
7734 1281824 : set_builtin_decl_implicit_p (DECL_FUNCTION_CODE (op0), true);
7735 :
7736 : /* We use fb_either here because the C frontend sometimes takes
7737 : the address of a call that returns a struct; see
7738 : gcc.dg/c99-array-lval-1.c. The gimplifier will correctly make
7739 : the implied temporary explicit. */
7740 :
7741 : /* Make the operand addressable. */
7742 32689553 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
7743 : is_gimple_addressable, fb_either);
7744 32689553 : if (ret == GS_ERROR)
7745 : break;
7746 :
7747 : /* Then mark it. Beware that it may not be possible to do so directly
7748 : if a temporary has been created by the gimplification. */
7749 32689551 : prepare_gimple_addressable (&TREE_OPERAND (expr, 0), pre_p);
7750 :
7751 32689551 : op0 = TREE_OPERAND (expr, 0);
7752 :
7753 : /* For various reasons, the gimplification of the expression
7754 : may have made a new INDIRECT_REF. */
7755 32689551 : if (INDIRECT_REF_P (op0)
7756 32689551 : || (TREE_CODE (op0) == MEM_REF
7757 45755 : && integer_zerop (TREE_OPERAND (op0, 1))))
7758 17231 : goto do_indirect_ref;
7759 :
7760 32672320 : mark_addressable (TREE_OPERAND (expr, 0));
7761 :
7762 : /* The FEs may end up building ADDR_EXPRs early on a decl with
7763 : an incomplete type. Re-build ADDR_EXPRs in canonical form
7764 : here. */
7765 32672320 : if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
7766 146333 : *expr_p = build_fold_addr_expr (op0);
7767 :
7768 : /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */
7769 32672320 : if (TREE_CODE (*expr_p) == ADDR_EXPR)
7770 32672319 : recompute_tree_invariant_for_addr_expr (*expr_p);
7771 :
7772 : /* If we re-built the ADDR_EXPR add a conversion to the original type
7773 : if required. */
7774 32672320 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
7775 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
7776 :
7777 : break;
7778 : }
7779 :
7780 32770926 : return ret;
7781 : }
7782 :
7783 : /* Return the number of times character C occurs in string S. */
7784 :
7785 : static int
7786 92801 : num_occurrences (int c, const char *s)
7787 : {
7788 92801 : int n = 0;
7789 251913 : while (*s)
7790 159112 : n += (*s++ == c);
7791 92801 : return n;
7792 : }
7793 :
7794 : /* A subroutine of gimplify_asm_expr. Check that all operands have
7795 : the same number of alternatives. Return -1 if this is violated. Otherwise
7796 : return the number of alternatives. */
7797 :
7798 : static int
7799 195404 : num_alternatives (const_tree link)
7800 : {
7801 195404 : if (link == nullptr)
7802 : return 0;
7803 :
7804 47897 : const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7805 47897 : int num = num_occurrences (',', constraint);
7806 :
7807 47897 : if (num + 1 > MAX_RECOG_ALTERNATIVES)
7808 : return -1;
7809 :
7810 92801 : for (link = TREE_CHAIN (link); link; link = TREE_CHAIN (link))
7811 : {
7812 44904 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7813 89808 : if (num_occurrences (',', constraint) != num)
7814 : return -1;
7815 : }
7816 47897 : return num + 1;
7817 : }
7818 :
7819 : /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple
7820 : value; output operands should be a gimple lvalue. */
7821 :
7822 : static enum gimplify_status
7823 97702 : gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7824 : {
7825 97702 : tree expr;
7826 97702 : int noutputs;
7827 97702 : const char **oconstraints;
7828 97702 : int i;
7829 97702 : tree link;
7830 97702 : const char *constraint;
7831 97702 : bool allows_mem, allows_reg, is_inout;
7832 97702 : enum gimplify_status ret, tret;
7833 97702 : gasm *stmt;
7834 97702 : vec<tree, va_gc> *inputs;
7835 97702 : vec<tree, va_gc> *outputs;
7836 97702 : vec<tree, va_gc> *clobbers;
7837 97702 : vec<tree, va_gc> *labels;
7838 97702 : tree link_next;
7839 :
7840 97702 : expr = *expr_p;
7841 97702 : noutputs = list_length (ASM_OUTPUTS (expr));
7842 97702 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
7843 :
7844 97702 : inputs = NULL;
7845 97702 : outputs = NULL;
7846 97702 : clobbers = NULL;
7847 97702 : labels = NULL;
7848 :
7849 97702 : int num_alternatives_out = num_alternatives (ASM_OUTPUTS (expr));
7850 97702 : int num_alternatives_in = num_alternatives (ASM_INPUTS (expr));
7851 97702 : if (num_alternatives_out == -1 || num_alternatives_in == -1
7852 97702 : || (num_alternatives_out > 0 && num_alternatives_in > 0
7853 16887 : && num_alternatives_out != num_alternatives_in))
7854 : {
7855 0 : error ("operand constraints for %<asm%> differ "
7856 : "in number of alternatives");
7857 0 : return GS_ERROR;
7858 : }
7859 97702 : int num_alternatives = MAX (num_alternatives_out, num_alternatives_in);
7860 :
7861 97702 : gimplify_reg_info reg_info (num_alternatives, noutputs);
7862 :
7863 97702 : link_next = NULL_TREE;
7864 193165 : for (link = ASM_CLOBBERS (expr); link; link = link_next)
7865 : {
7866 : /* The clobber entry could also be an error marker. */
7867 95463 : if (TREE_CODE (TREE_VALUE (link)) == STRING_CST)
7868 : {
7869 95440 : const char *regname= TREE_STRING_POINTER (TREE_VALUE (link));
7870 95440 : int regno = decode_reg_name (regname);
7871 95440 : if (regno >= 0)
7872 41262 : reg_info.set_clobbered (regno);
7873 : }
7874 95463 : link_next = TREE_CHAIN (link);
7875 95463 : TREE_CHAIN (link) = NULL_TREE;
7876 95463 : vec_safe_push (clobbers, link);
7877 : }
7878 :
7879 97702 : ret = GS_ALL_DONE;
7880 97702 : link_next = NULL_TREE;
7881 157693 : for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
7882 : {
7883 60024 : bool ok;
7884 60024 : size_t constraint_len;
7885 :
7886 60024 : if (error_operand_p (TREE_VALUE (link)))
7887 : return GS_ERROR;
7888 60003 : link_next = TREE_CHAIN (link);
7889 :
7890 120006 : oconstraints[i]
7891 60003 : = constraint
7892 60003 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7893 60003 : constraint_len = strlen (constraint);
7894 60003 : if (constraint_len == 0)
7895 0 : continue;
7896 :
7897 60003 : reg_info.operand = TREE_VALUE (link);
7898 60003 : ok = parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
7899 : &allows_reg, &is_inout, ®_info);
7900 60003 : if (!ok)
7901 : {
7902 11 : ret = GS_ERROR;
7903 11 : is_inout = false;
7904 : }
7905 :
7906 : /* If we can't make copies, we can only accept memory.
7907 : Similarly for VLAs. */
7908 60003 : tree outtype = TREE_TYPE (TREE_VALUE (link));
7909 60003 : if (TREE_ADDRESSABLE (outtype)
7910 59988 : || !COMPLETE_TYPE_P (outtype)
7911 119966 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (outtype)))
7912 : {
7913 303 : if (allows_mem)
7914 291 : allows_reg = 0;
7915 : else
7916 : {
7917 12 : error ("impossible constraint in %<asm%>");
7918 12 : error ("non-memory output %d must stay in memory", i);
7919 12 : return GS_ERROR;
7920 : }
7921 : }
7922 :
7923 59991 : if (!allows_reg && allows_mem)
7924 1804 : mark_addressable (TREE_VALUE (link));
7925 :
7926 59991 : tree orig = TREE_VALUE (link);
7927 111317 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
7928 : is_inout ? is_gimple_min_lval : is_gimple_lvalue,
7929 : fb_lvalue | fb_mayfail);
7930 59991 : if (tret == GS_ERROR)
7931 : {
7932 0 : if (orig != error_mark_node)
7933 0 : error ("invalid lvalue in %<asm%> output %d", i);
7934 : ret = tret;
7935 : }
7936 :
7937 : /* If the gimplified operand is a register we do not allow memory. */
7938 59991 : if (allows_reg
7939 58184 : && allows_mem
7940 65917 : && (is_gimple_reg (TREE_VALUE (link))
7941 267 : || (handled_component_p (TREE_VALUE (link))
7942 36 : && is_gimple_reg (TREE_OPERAND (TREE_VALUE (link), 0)))))
7943 5660 : allows_mem = 0;
7944 :
7945 : /* If the constraint does not allow memory make sure we gimplify
7946 : it to a register if it is not already but its base is. This
7947 : happens for complex and vector components. */
7948 59991 : if (!allows_mem)
7949 : {
7950 57921 : tree op = TREE_VALUE (link);
7951 57921 : if (! is_gimple_val (op)
7952 21142 : && is_gimple_reg_type (TREE_TYPE (op))
7953 79062 : && is_gimple_reg (get_base_address (op)))
7954 : {
7955 19 : tree tem = create_tmp_reg (TREE_TYPE (op));
7956 19 : tree ass;
7957 19 : if (is_inout)
7958 : {
7959 7 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem),
7960 : tem, unshare_expr (op));
7961 7 : gimplify_and_add (ass, pre_p);
7962 : }
7963 19 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem), op, tem);
7964 19 : gimplify_and_add (ass, post_p);
7965 :
7966 19 : TREE_VALUE (link) = tem;
7967 19 : tret = GS_OK;
7968 : }
7969 : }
7970 :
7971 59991 : vec_safe_push (outputs, link);
7972 59991 : TREE_CHAIN (link) = NULL_TREE;
7973 :
7974 59991 : if (is_inout)
7975 : {
7976 : /* An input/output operand. To give the optimizers more
7977 : flexibility, split it into separate input and output
7978 : operands. */
7979 8665 : tree input;
7980 : /* Buffer big enough to format a 32-bit UINT_MAX into. */
7981 8665 : char buf[11];
7982 :
7983 : /* Turn the in/out constraint into an output constraint. */
7984 8665 : char *p = xstrdup (constraint);
7985 8665 : p[0] = '=';
7986 8665 : TREE_PURPOSE (link) = unshare_expr (TREE_PURPOSE (link));
7987 8665 : TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
7988 :
7989 : /* And add a matching input constraint. */
7990 8665 : if (allows_reg)
7991 : {
7992 8167 : sprintf (buf, "%u", i);
7993 :
7994 : /* If there are multiple alternatives in the constraint,
7995 : handle each of them individually. Those that allow register
7996 : will be replaced with operand number, the others will stay
7997 : unchanged. */
7998 8167 : if (strchr (p, ',') != NULL)
7999 : {
8000 100 : size_t len = 0, buflen = strlen (buf);
8001 100 : char *beg, *end, *str, *dst;
8002 :
8003 100 : for (beg = p + 1;;)
8004 : {
8005 200 : end = strchr (beg, ',');
8006 200 : if (end == NULL)
8007 100 : end = strchr (beg, '\0');
8008 200 : if ((size_t) (end - beg) < buflen)
8009 28 : len += buflen + 1;
8010 : else
8011 172 : len += end - beg + 1;
8012 200 : if (*end)
8013 100 : beg = end + 1;
8014 : else
8015 : break;
8016 : }
8017 :
8018 100 : str = (char *) alloca (len);
8019 100 : for (beg = p + 1, dst = str;;)
8020 : {
8021 200 : const char *tem;
8022 200 : bool mem_p, reg_p, inout_p;
8023 :
8024 200 : end = strchr (beg, ',');
8025 200 : if (end)
8026 100 : *end = '\0';
8027 200 : beg[-1] = '=';
8028 200 : tem = beg - 1;
8029 200 : parse_output_constraint (&tem, i, 0, 0, &mem_p, ®_p,
8030 : &inout_p, nullptr);
8031 200 : if (dst != str)
8032 100 : *dst++ = ',';
8033 200 : if (reg_p)
8034 : {
8035 115 : memcpy (dst, buf, buflen);
8036 115 : dst += buflen;
8037 : }
8038 : else
8039 : {
8040 85 : if (end)
8041 0 : len = end - beg;
8042 : else
8043 85 : len = strlen (beg);
8044 85 : memcpy (dst, beg, len);
8045 85 : dst += len;
8046 : }
8047 200 : if (end)
8048 100 : beg = end + 1;
8049 : else
8050 : break;
8051 100 : }
8052 100 : *dst = '\0';
8053 100 : input = build_string (dst - str, str);
8054 : }
8055 : else
8056 8067 : input = build_string (strlen (buf), buf);
8057 : }
8058 : else
8059 498 : input = build_string (constraint_len - 1, constraint + 1);
8060 :
8061 8665 : free (p);
8062 :
8063 8665 : input = build_tree_list (build_tree_list (NULL_TREE, input),
8064 8665 : unshare_expr (TREE_VALUE (link)));
8065 8665 : ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
8066 : }
8067 : }
8068 :
8069 : /* After all output operands have been gimplified, verify that each output
8070 : operand is used at most once in case of hard register constraints. Thus,
8071 : error out in cases like
8072 : asm ("" : "={0}" (x), "={1}" (x));
8073 : or even for
8074 : asm ("" : "=r" (x), "={1}" (x));
8075 :
8076 : FIXME: Ideally we would also error out for cases like
8077 : int x;
8078 : asm ("" : "=r" (x), "=r" (x));
8079 : However, since code like that was previously accepted, erroring out now might
8080 : break existing code. On the other hand, we already error out for register
8081 : asm like
8082 : register int x asm ("0");
8083 : asm ("" : "=r" (x), "=r" (x));
8084 : Thus, maybe it wouldn't be too bad to also error out in the former
8085 : non-register-asm case.
8086 : */
8087 157656 : for (unsigned i = 0; i < vec_safe_length (outputs); ++i)
8088 : {
8089 59989 : tree link = (*outputs)[i];
8090 59989 : tree op1 = TREE_VALUE (link);
8091 59989 : const char *constraint
8092 59989 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8093 59989 : if (strchr (constraint, '{') != nullptr)
8094 236 : for (unsigned j = 0; j < vec_safe_length (outputs); ++j)
8095 : {
8096 142 : if (i == j)
8097 95 : continue;
8098 47 : tree link2 = (*outputs)[j];
8099 47 : tree op2 = TREE_VALUE (link2);
8100 47 : if (op1 == op2)
8101 : {
8102 2 : error ("multiple outputs to lvalue %qE", op2);
8103 2 : return GS_ERROR;
8104 : }
8105 : }
8106 : }
8107 :
8108 97667 : link_next = NULL_TREE;
8109 97667 : int input_num = 0;
8110 139047 : for (link = ASM_INPUTS (expr); link; ++input_num, ++i, link = link_next)
8111 : {
8112 41438 : if (error_operand_p (TREE_VALUE (link)))
8113 : return GS_ERROR;
8114 41389 : link_next = TREE_CHAIN (link);
8115 41389 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8116 41389 : reg_info.operand = TREE_VALUE (link);
8117 41389 : bool ok = parse_input_constraint (&constraint, input_num, 0, noutputs, 0,
8118 : oconstraints, &allows_mem, &allows_reg,
8119 : ®_info);
8120 41389 : if (!ok)
8121 : {
8122 30 : ret = GS_ERROR;
8123 30 : is_inout = false;
8124 : }
8125 :
8126 : /* If we can't make copies, we can only accept memory. */
8127 41389 : tree intype = TREE_TYPE (TREE_VALUE (link));
8128 41389 : if (TREE_ADDRESSABLE (intype)
8129 41371 : || !COMPLETE_TYPE_P (intype)
8130 82721 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (intype)))
8131 : {
8132 312 : if (allows_mem)
8133 303 : allows_reg = 0;
8134 : else
8135 : {
8136 9 : error ("impossible constraint in %<asm%>");
8137 9 : error ("non-memory input %d must stay in memory", i);
8138 9 : return GS_ERROR;
8139 : }
8140 : }
8141 :
8142 : /* If the operand is a memory input, it should be an lvalue. */
8143 41380 : if (!allows_reg && allows_mem)
8144 : {
8145 2118 : tree inputv = TREE_VALUE (link);
8146 2118 : STRIP_NOPS (inputv);
8147 2118 : if (TREE_CODE (inputv) == PREDECREMENT_EXPR
8148 : || TREE_CODE (inputv) == PREINCREMENT_EXPR
8149 : || TREE_CODE (inputv) == POSTDECREMENT_EXPR
8150 2118 : || TREE_CODE (inputv) == POSTINCREMENT_EXPR
8151 2106 : || TREE_CODE (inputv) == MODIFY_EXPR
8152 4222 : || VOID_TYPE_P (TREE_TYPE (inputv)))
8153 38 : TREE_VALUE (link) = error_mark_node;
8154 2118 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8155 : is_gimple_lvalue, fb_lvalue | fb_mayfail);
8156 2118 : if (tret != GS_ERROR)
8157 : {
8158 : /* Unlike output operands, memory inputs are not guaranteed
8159 : to be lvalues by the FE, and while the expressions are
8160 : marked addressable there, if it is e.g. a statement
8161 : expression, temporaries in it might not end up being
8162 : addressable. They might be already used in the IL and thus
8163 : it is too late to make them addressable now though. */
8164 2072 : tree x = TREE_VALUE (link);
8165 2213 : while (handled_component_p (x))
8166 141 : x = TREE_OPERAND (x, 0);
8167 2072 : if (TREE_CODE (x) == MEM_REF
8168 2072 : && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
8169 0 : x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
8170 2072 : if ((VAR_P (x)
8171 : || TREE_CODE (x) == PARM_DECL
8172 : || TREE_CODE (x) == RESULT_DECL)
8173 1483 : && !TREE_ADDRESSABLE (x)
8174 23 : && is_gimple_reg (x))
8175 : {
8176 17 : warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link),
8177 17 : input_location), 0,
8178 : "memory input %d is not directly addressable",
8179 : i);
8180 17 : prepare_gimple_addressable (&TREE_VALUE (link), pre_p);
8181 : }
8182 : }
8183 2118 : mark_addressable (TREE_VALUE (link));
8184 2118 : if (tret == GS_ERROR)
8185 : {
8186 46 : if (inputv != error_mark_node)
8187 46 : error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
8188 : "memory input %d is not directly addressable", i);
8189 : ret = tret;
8190 : }
8191 : }
8192 : else
8193 : {
8194 39262 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8195 : is_gimple_asm_val, fb_rvalue);
8196 39262 : if (tret == GS_ERROR)
8197 46 : ret = tret;
8198 : }
8199 :
8200 41380 : TREE_CHAIN (link) = NULL_TREE;
8201 41380 : vec_safe_push (inputs, link);
8202 : }
8203 :
8204 97609 : link_next = NULL_TREE;
8205 98491 : for (link = ASM_LABELS (expr); link; link = link_next)
8206 : {
8207 882 : link_next = TREE_CHAIN (link);
8208 882 : TREE_CHAIN (link) = NULL_TREE;
8209 882 : vec_safe_push (labels, link);
8210 : }
8211 :
8212 : /* Do not add ASMs with errors to the gimple IL stream. */
8213 97609 : if (ret != GS_ERROR)
8214 : {
8215 97526 : stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
8216 : inputs, outputs, clobbers, labels);
8217 :
8218 : /* asm is volatile if it was marked by the user as volatile or
8219 : there are no outputs or this is an asm goto. */
8220 195052 : gimple_asm_set_volatile (stmt,
8221 97526 : ASM_VOLATILE_P (expr)
8222 7520 : || noutputs == 0
8223 105032 : || labels);
8224 97526 : gimple_asm_set_basic (stmt, ASM_BASIC_P (expr));
8225 97526 : gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
8226 :
8227 97526 : gimplify_seq_add_stmt (pre_p, stmt);
8228 : }
8229 :
8230 : return ret;
8231 97702 : }
8232 :
8233 : /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding
8234 : GIMPLE_WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
8235 : gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we
8236 : return to this function.
8237 :
8238 : FIXME should we complexify the prequeue handling instead? Or use flags
8239 : for all the cleanups and let the optimizer tighten them up? The current
8240 : code seems pretty fragile; it will break on a cleanup within any
8241 : non-conditional nesting. But any such nesting would be broken, anyway;
8242 : we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
8243 : and continues out of it. We can do that at the RTL level, though, so
8244 : having an optimizer to tighten up try/finally regions would be a Good
8245 : Thing. */
8246 :
8247 : static enum gimplify_status
8248 5167005 : gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
8249 : {
8250 5167005 : gimple_stmt_iterator iter;
8251 5167005 : gimple_seq body_sequence = NULL;
8252 :
8253 5167005 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
8254 :
8255 : /* We only care about the number of conditions between the innermost
8256 : CLEANUP_POINT_EXPR and the cleanup. So save and reset the count and
8257 : any cleanups collected outside the CLEANUP_POINT_EXPR. */
8258 5167005 : int old_conds = gimplify_ctxp->conditions;
8259 5167005 : gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
8260 5167005 : bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
8261 5167005 : gimplify_ctxp->conditions = 0;
8262 5167005 : gimplify_ctxp->conditional_cleanups = NULL;
8263 5167005 : gimplify_ctxp->in_cleanup_point_expr = true;
8264 :
8265 5167005 : gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
8266 :
8267 5167005 : gimplify_ctxp->conditions = old_conds;
8268 5167005 : gimplify_ctxp->conditional_cleanups = old_cleanups;
8269 5167005 : gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
8270 :
8271 26849990 : for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
8272 : {
8273 16555742 : gimple *wce = gsi_stmt (iter);
8274 :
8275 16555742 : if (gimple_code (wce) == GIMPLE_WITH_CLEANUP_EXPR)
8276 : {
8277 601095 : if (gsi_one_before_end_p (iter))
8278 : {
8279 : /* Note that gsi_insert_seq_before and gsi_remove do not
8280 : scan operands, unlike some other sequence mutators. */
8281 3024 : if (!gimple_wce_cleanup_eh_only (wce))
8282 3024 : gsi_insert_seq_before_without_update (&iter,
8283 : gimple_wce_cleanup (wce),
8284 : GSI_SAME_STMT);
8285 3024 : gsi_remove (&iter, true);
8286 3024 : break;
8287 : }
8288 : else
8289 : {
8290 598071 : gtry *gtry;
8291 598071 : gimple_seq seq;
8292 598071 : enum gimple_try_flags kind;
8293 :
8294 598071 : if (gimple_wce_cleanup_eh_only (wce))
8295 : kind = GIMPLE_TRY_CATCH;
8296 : else
8297 584281 : kind = GIMPLE_TRY_FINALLY;
8298 598071 : seq = gsi_split_seq_after (iter);
8299 :
8300 598071 : gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
8301 : /* Do not use gsi_replace here, as it may scan operands.
8302 : We want to do a simple structural modification only. */
8303 598071 : gsi_set_stmt (&iter, gtry);
8304 1196142 : iter = gsi_start (gtry->eval);
8305 : }
8306 : }
8307 : else
8308 15954647 : gsi_next (&iter);
8309 : }
8310 :
8311 5167005 : gimplify_seq_add_seq (pre_p, body_sequence);
8312 5167005 : if (temp)
8313 : {
8314 346094 : *expr_p = temp;
8315 346094 : return GS_OK;
8316 : }
8317 : else
8318 : {
8319 4820911 : *expr_p = NULL;
8320 4820911 : return GS_ALL_DONE;
8321 : }
8322 : }
8323 :
8324 : /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
8325 : is the cleanup action required. EH_ONLY is true if the cleanup should
8326 : only be executed if an exception is thrown, not on normal exit.
8327 : If FORCE_UNCOND is true perform the cleanup unconditionally; this is
8328 : only valid for clobbers. */
8329 :
8330 : static void
8331 605899 : gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
8332 : bool force_uncond = false)
8333 : {
8334 605899 : gimple *wce;
8335 605899 : gimple_seq cleanup_stmts = NULL;
8336 :
8337 : /* Errors can result in improperly nested cleanups. Which results in
8338 : confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
8339 605899 : if (seen_error ())
8340 4804 : return;
8341 :
8342 601095 : if (gimple_conditional_context ())
8343 : {
8344 : /* If we're in a conditional context, this is more complex. We only
8345 : want to run the cleanup if we actually ran the initialization that
8346 : necessitates it, but we want to run it after the end of the
8347 : conditional context. So we wrap the try/finally around the
8348 : condition and use a flag to determine whether or not to actually
8349 : run the destructor. Thus
8350 :
8351 : test ? f(A()) : 0
8352 :
8353 : becomes (approximately)
8354 :
8355 : flag = 0;
8356 : try {
8357 : if (test) { A::A(temp); flag = 1; val = f(temp); }
8358 : else { val = 0; }
8359 : } finally {
8360 : if (flag) A::~A(temp);
8361 : }
8362 : val
8363 : */
8364 14602 : if (force_uncond)
8365 : {
8366 13717 : gimplify_stmt (&cleanup, &cleanup_stmts);
8367 13717 : wce = gimple_build_wce (cleanup_stmts);
8368 13717 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8369 : }
8370 : else
8371 : {
8372 885 : tree flag = create_tmp_var (boolean_type_node, "cleanup");
8373 885 : gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
8374 885 : gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
8375 :
8376 885 : cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
8377 885 : gimplify_stmt (&cleanup, &cleanup_stmts);
8378 885 : wce = gimple_build_wce (cleanup_stmts);
8379 885 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8380 :
8381 885 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
8382 885 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8383 885 : gimplify_seq_add_stmt (pre_p, ftrue);
8384 :
8385 : /* Because of this manipulation, and the EH edges that jump
8386 : threading cannot redirect, the temporary (VAR) will appear
8387 : to be used uninitialized. Don't warn. */
8388 885 : suppress_warning (var, OPT_Wuninitialized);
8389 : }
8390 : }
8391 : else
8392 : {
8393 586493 : gimplify_stmt (&cleanup, &cleanup_stmts);
8394 586493 : wce = gimple_build_wce (cleanup_stmts);
8395 586493 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8396 586493 : gimplify_seq_add_stmt (pre_p, wce);
8397 : }
8398 : }
8399 :
8400 : /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
8401 :
8402 : static enum gimplify_status
8403 803585 : gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
8404 : {
8405 803585 : tree targ = *expr_p;
8406 803585 : tree temp = TARGET_EXPR_SLOT (targ);
8407 803585 : tree init = TARGET_EXPR_INITIAL (targ);
8408 803585 : enum gimplify_status ret;
8409 :
8410 803585 : bool unpoison_empty_seq = false;
8411 803585 : gimple_stmt_iterator unpoison_it;
8412 :
8413 803585 : if (init)
8414 : {
8415 766841 : gimple_seq init_pre_p = NULL;
8416 766841 : bool is_vla = false;
8417 :
8418 : /* TARGET_EXPR temps aren't part of the enclosing block, so add it
8419 : to the temps list. Handle also variable length TARGET_EXPRs. */
8420 766841 : if (!poly_int_tree_p (DECL_SIZE (temp)))
8421 : {
8422 44 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
8423 1 : gimplify_type_sizes (TREE_TYPE (temp), &init_pre_p);
8424 : /* FIXME: this is correct only when the size of the type does
8425 : not depend on expressions evaluated in init. */
8426 44 : gimplify_vla_decl (temp, &init_pre_p);
8427 44 : is_vla = true;
8428 : }
8429 : else
8430 : {
8431 : /* Save location where we need to place unpoisoning. It's possible
8432 : that a variable will be converted to needs_to_live_in_memory. */
8433 766797 : unpoison_it = gsi_last (*pre_p);
8434 766797 : unpoison_empty_seq = gsi_end_p (unpoison_it);
8435 :
8436 766797 : gimple_add_tmp_var (temp);
8437 : }
8438 :
8439 766841 : if (var_needs_auto_init_p (temp) && VOID_TYPE_P (TREE_TYPE (init)))
8440 : {
8441 47577 : gimple_add_init_for_auto_var (temp, flag_auto_var_init, &init_pre_p);
8442 47577 : if (flag_auto_var_init == AUTO_INIT_PATTERN
8443 0 : && !is_gimple_reg (temp)
8444 47577 : && clear_padding_type_may_have_padding_p (TREE_TYPE (temp)))
8445 0 : gimple_add_padding_init_for_auto_var (temp, is_vla, &init_pre_p);
8446 : }
8447 :
8448 : /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
8449 : expression is supposed to initialize the slot. */
8450 766841 : if (VOID_TYPE_P (TREE_TYPE (init)))
8451 276994 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8452 : fb_none);
8453 : else
8454 : {
8455 489847 : tree init_expr = build2 (INIT_EXPR, void_type_node, temp, init);
8456 489847 : init = init_expr;
8457 489847 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8458 : fb_none);
8459 489847 : init = NULL;
8460 489847 : ggc_free (init_expr);
8461 : }
8462 766841 : if (ret == GS_ERROR)
8463 : {
8464 : /* PR c++/28266 Make sure this is expanded only once. */
8465 10 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8466 10 : return GS_ERROR;
8467 : }
8468 :
8469 766831 : if (init)
8470 0 : gimplify_and_add (init, &init_pre_p);
8471 :
8472 : /* Add a clobber for the temporary going out of scope, like
8473 : gimplify_bind_expr. But only if we did not promote the
8474 : temporary to static storage. */
8475 766831 : if (gimplify_ctxp->in_cleanup_point_expr
8476 621595 : && !TREE_STATIC (temp)
8477 1387023 : && needs_to_live_in_memory (temp))
8478 : {
8479 460843 : if (flag_stack_reuse == SR_ALL)
8480 : {
8481 460357 : tree clobber = build_clobber (TREE_TYPE (temp),
8482 : CLOBBER_STORAGE_END);
8483 460357 : clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
8484 460357 : gimple_push_cleanup (temp, clobber, false, pre_p, true);
8485 : }
8486 460843 : if (asan_poisoned_variables
8487 486 : && DECL_ALIGN (temp) <= MAX_SUPPORTED_STACK_ALIGNMENT
8488 486 : && !TREE_STATIC (temp)
8489 486 : && dbg_cnt (asan_use_after_scope)
8490 461329 : && !gimplify_omp_ctxp)
8491 : {
8492 478 : tree asan_cleanup = build_asan_poison_call_expr (temp);
8493 478 : if (asan_cleanup)
8494 : {
8495 478 : if (unpoison_empty_seq)
8496 223 : unpoison_it = gsi_start (*pre_p);
8497 :
8498 478 : asan_poison_variable (temp, false, &unpoison_it,
8499 : unpoison_empty_seq);
8500 478 : gimple_push_cleanup (temp, asan_cleanup, false, pre_p);
8501 : }
8502 : }
8503 : }
8504 :
8505 766831 : gimple_seq_add_seq (pre_p, init_pre_p);
8506 :
8507 : /* If needed, push the cleanup for the temp. */
8508 766831 : if (TARGET_EXPR_CLEANUP (targ))
8509 145064 : gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
8510 145064 : CLEANUP_EH_ONLY (targ), pre_p);
8511 :
8512 : /* Only expand this once. */
8513 766831 : TREE_OPERAND (targ, 3) = init;
8514 766831 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8515 : }
8516 : else
8517 : /* We should have expanded this before. */
8518 36744 : gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
8519 :
8520 803575 : *expr_p = temp;
8521 803575 : return GS_OK;
8522 : }
8523 :
8524 : /* Gimplification of expression trees. */
8525 :
8526 : /* Gimplify an expression which appears at statement context. The
8527 : corresponding GIMPLE statements are added to *SEQ_P. If *SEQ_P is
8528 : NULL, a new sequence is allocated.
8529 :
8530 : Return true if we actually added a statement to the queue. */
8531 :
8532 : bool
8533 101748443 : gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
8534 : {
8535 101748443 : gimple_seq_node last;
8536 :
8537 101748443 : last = gimple_seq_last (*seq_p);
8538 101748443 : gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
8539 101748443 : return last != gimple_seq_last (*seq_p);
8540 : }
8541 :
8542 : /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
8543 : to CTX. If entries already exist, force them to be some flavor of private.
8544 : If there is no enclosing parallel, do nothing. */
8545 :
8546 : void
8547 123218 : omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
8548 : {
8549 123218 : splay_tree_node n;
8550 :
8551 123218 : if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE)
8552 : return;
8553 :
8554 36829 : do
8555 : {
8556 36829 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8557 36829 : if (n != NULL)
8558 : {
8559 4295 : if (n->value & GOVD_SHARED)
8560 183 : n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
8561 4112 : else if (n->value & GOVD_MAP)
8562 58 : n->value |= GOVD_MAP_TO_ONLY;
8563 : else
8564 : return;
8565 : }
8566 32534 : else if ((ctx->region_type & ORT_TARGET) != 0)
8567 : {
8568 6948 : if (ctx->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
8569 4189 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8570 : else
8571 2759 : omp_add_variable (ctx, decl, GOVD_MAP | GOVD_MAP_TO_ONLY);
8572 : }
8573 25586 : else if (ctx->region_type != ORT_WORKSHARE
8574 : && ctx->region_type != ORT_TASKGROUP
8575 23757 : && ctx->region_type != ORT_SIMD
8576 23133 : && ctx->region_type != ORT_ACC
8577 23016 : && !(ctx->region_type & ORT_TARGET_DATA))
8578 14435 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8579 :
8580 32775 : ctx = ctx->outer_context;
8581 : }
8582 32775 : while (ctx);
8583 : }
8584 :
8585 : /* Similarly for each of the type sizes of TYPE. */
8586 :
8587 : static void
8588 39870 : omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
8589 : {
8590 39870 : if (type == NULL || type == error_mark_node)
8591 : return;
8592 39866 : type = TYPE_MAIN_VARIANT (type);
8593 :
8594 39866 : if (ctx->privatized_types->add (type))
8595 : return;
8596 :
8597 30491 : switch (TREE_CODE (type))
8598 : {
8599 12978 : case INTEGER_TYPE:
8600 12978 : case ENUMERAL_TYPE:
8601 12978 : case BOOLEAN_TYPE:
8602 12978 : case REAL_TYPE:
8603 12978 : case FIXED_POINT_TYPE:
8604 12978 : omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
8605 12978 : omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
8606 12978 : break;
8607 :
8608 5365 : case ARRAY_TYPE:
8609 5365 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8610 5365 : omp_firstprivatize_type_sizes (ctx, TYPE_DOMAIN (type));
8611 5365 : break;
8612 :
8613 2502 : case RECORD_TYPE:
8614 2502 : case UNION_TYPE:
8615 2502 : case QUAL_UNION_TYPE:
8616 2502 : {
8617 2502 : tree field;
8618 26645 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
8619 24143 : if (TREE_CODE (field) == FIELD_DECL)
8620 : {
8621 8997 : omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
8622 8997 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (field));
8623 : }
8624 : }
8625 : break;
8626 :
8627 8997 : case POINTER_TYPE:
8628 8997 : case REFERENCE_TYPE:
8629 8997 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8630 8997 : break;
8631 :
8632 : default:
8633 : break;
8634 : }
8635 :
8636 30491 : omp_firstprivatize_variable (ctx, TYPE_SIZE (type));
8637 30491 : omp_firstprivatize_variable (ctx, TYPE_SIZE_UNIT (type));
8638 30491 : lang_hooks.types.omp_firstprivatize_type_sizes (ctx, type);
8639 : }
8640 :
8641 : /* Add an entry for DECL in the OMP context CTX with FLAGS. */
8642 :
8643 : static void
8644 713922 : omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
8645 : {
8646 713922 : splay_tree_node n;
8647 713922 : unsigned int nflags;
8648 713922 : tree t;
8649 :
8650 713922 : if (error_operand_p (decl) || ctx->region_type == ORT_NONE)
8651 : return;
8652 :
8653 : /* Never elide decls whose type has TREE_ADDRESSABLE set. This means
8654 : there are constructors involved somewhere. Exception is a shared clause,
8655 : there is nothing privatized in that case. */
8656 713777 : if ((flags & GOVD_SHARED) == 0
8657 713777 : && (TREE_ADDRESSABLE (TREE_TYPE (decl))
8658 653390 : || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
8659 7766 : flags |= GOVD_SEEN;
8660 :
8661 713777 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8662 713777 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
8663 : {
8664 : /* We shouldn't be re-adding the decl with the same data
8665 : sharing class. */
8666 824 : gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
8667 824 : nflags = n->value | flags;
8668 : /* The only combination of data sharing classes we should see is
8669 : FIRSTPRIVATE and LASTPRIVATE. However, OpenACC permits
8670 : reduction variables to be used in data sharing clauses. */
8671 824 : gcc_assert ((ctx->region_type & ORT_ACC) != 0
8672 : || ((nflags & GOVD_DATA_SHARE_CLASS)
8673 : == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE))
8674 : || (flags & GOVD_DATA_SHARE_CLASS) == 0);
8675 824 : n->value = nflags;
8676 824 : return;
8677 : }
8678 :
8679 : /* When adding a variable-sized variable, we have to handle all sorts
8680 : of additional bits of data: the pointer replacement variable, and
8681 : the parameters of the type. */
8682 712953 : if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl)))
8683 : {
8684 : /* Add the pointer replacement variable as PRIVATE if the variable
8685 : replacement is private, else FIRSTPRIVATE since we'll need the
8686 : address of the original variable either for SHARED, or for the
8687 : copy into or out of the context. */
8688 1329 : if (!(flags & GOVD_LOCAL) && ctx->region_type != ORT_TASKGROUP)
8689 : {
8690 1238 : if (flags & GOVD_MAP)
8691 : nflags = GOVD_MAP | GOVD_MAP_TO_ONLY | GOVD_EXPLICIT;
8692 531 : else if (flags & GOVD_PRIVATE)
8693 : nflags = GOVD_PRIVATE;
8694 441 : else if (((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
8695 50 : && (flags & GOVD_FIRSTPRIVATE))
8696 431 : || (ctx->region_type == ORT_TARGET_DATA
8697 6 : && (flags & GOVD_DATA_SHARE_CLASS) == 0))
8698 : nflags = GOVD_PRIVATE | GOVD_EXPLICIT;
8699 : else
8700 1238 : nflags = GOVD_FIRSTPRIVATE;
8701 1238 : nflags |= flags & GOVD_SEEN;
8702 1238 : t = DECL_VALUE_EXPR (decl);
8703 1238 : gcc_assert (INDIRECT_REF_P (t));
8704 1238 : t = TREE_OPERAND (t, 0);
8705 1238 : gcc_assert (DECL_P (t));
8706 1238 : omp_add_variable (ctx, t, nflags);
8707 : }
8708 :
8709 : /* Add all of the variable and type parameters (which should have
8710 : been gimplified to a formal temporary) as FIRSTPRIVATE. */
8711 1329 : omp_firstprivatize_variable (ctx, DECL_SIZE_UNIT (decl));
8712 1329 : omp_firstprivatize_variable (ctx, DECL_SIZE (decl));
8713 1329 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8714 :
8715 : /* The variable-sized variable itself is never SHARED, only some form
8716 : of PRIVATE. The sharing would take place via the pointer variable
8717 : which we remapped above. */
8718 1329 : if (flags & GOVD_SHARED)
8719 284 : flags = GOVD_SHARED | GOVD_DEBUG_PRIVATE
8720 284 : | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
8721 :
8722 : /* We're going to make use of the TYPE_SIZE_UNIT at least in the
8723 : alloca statement we generate for the variable, so make sure it
8724 : is available. This isn't automatically needed for the SHARED
8725 : case, since we won't be allocating local storage then.
8726 : For local variables TYPE_SIZE_UNIT might not be gimplified yet,
8727 : in this case omp_notice_variable will be called later
8728 : on when it is gimplified. */
8729 1045 : else if (! (flags & (GOVD_LOCAL | GOVD_MAP))
8730 1045 : && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
8731 275 : omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
8732 : }
8733 711624 : else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
8734 711624 : && omp_privatize_by_reference (decl))
8735 : {
8736 9817 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8737 :
8738 : /* Similar to the direct variable sized case above, we'll need the
8739 : size of references being privatized. */
8740 9817 : if ((flags & GOVD_SHARED) == 0)
8741 : {
8742 6132 : t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
8743 6132 : if (t && DECL_P (t))
8744 1373 : omp_notice_variable (ctx, t, true);
8745 : }
8746 : }
8747 :
8748 712953 : if (n != NULL)
8749 1868 : n->value |= flags;
8750 : else
8751 711085 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
8752 :
8753 : /* For reductions clauses in OpenACC loop directives, by default create a
8754 : copy clause on the enclosing parallel construct for carrying back the
8755 : results. */
8756 712953 : if (ctx->region_type == ORT_ACC && (flags & GOVD_REDUCTION))
8757 : {
8758 4716 : struct gimplify_omp_ctx *outer_ctx = ctx->outer_context;
8759 6454 : while (outer_ctx)
8760 : {
8761 5788 : n = splay_tree_lookup (outer_ctx->variables, (splay_tree_key)decl);
8762 5788 : if (n != NULL)
8763 : {
8764 : /* Ignore local variables and explicitly declared clauses. */
8765 3990 : if (n->value & (GOVD_LOCAL | GOVD_EXPLICIT))
8766 : break;
8767 443 : else if (outer_ctx->region_type == ORT_ACC_KERNELS)
8768 : {
8769 : /* According to the OpenACC spec, such a reduction variable
8770 : should already have a copy map on a kernels construct,
8771 : verify that here. */
8772 143 : gcc_assert (!(n->value & GOVD_FIRSTPRIVATE)
8773 : && (n->value & GOVD_MAP));
8774 : }
8775 300 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8776 : {
8777 : /* Remove firstprivate and make it a copy map. */
8778 150 : n->value &= ~GOVD_FIRSTPRIVATE;
8779 150 : n->value |= GOVD_MAP;
8780 : }
8781 : }
8782 1798 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8783 : {
8784 503 : splay_tree_insert (outer_ctx->variables, (splay_tree_key)decl,
8785 : GOVD_MAP | GOVD_SEEN);
8786 503 : break;
8787 : }
8788 1738 : outer_ctx = outer_ctx->outer_context;
8789 : }
8790 : }
8791 : }
8792 :
8793 : /* Notice a threadprivate variable DECL used in OMP context CTX.
8794 : This just prints out diagnostics about threadprivate variable uses
8795 : in untied tasks. If DECL2 is non-NULL, prevent this warning
8796 : on that variable. */
8797 :
8798 : static bool
8799 14183 : omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
8800 : tree decl2)
8801 : {
8802 14183 : splay_tree_node n;
8803 14183 : struct gimplify_omp_ctx *octx;
8804 :
8805 28798 : for (octx = ctx; octx; octx = octx->outer_context)
8806 14615 : if ((octx->region_type & ORT_TARGET) != 0
8807 14615 : || octx->order_concurrent)
8808 : {
8809 112 : n = splay_tree_lookup (octx->variables, (splay_tree_key)decl);
8810 112 : if (n == NULL)
8811 : {
8812 20 : if (octx->order_concurrent)
8813 : {
8814 20 : error ("threadprivate variable %qE used in a region with"
8815 20 : " %<order(concurrent)%> clause", DECL_NAME (decl));
8816 20 : inform (octx->location, "enclosing region");
8817 : }
8818 : else
8819 : {
8820 0 : error ("threadprivate variable %qE used in target region",
8821 0 : DECL_NAME (decl));
8822 0 : inform (octx->location, "enclosing target region");
8823 : }
8824 20 : splay_tree_insert (octx->variables, (splay_tree_key)decl, 0);
8825 : }
8826 112 : if (decl2)
8827 0 : splay_tree_insert (octx->variables, (splay_tree_key)decl2, 0);
8828 : }
8829 :
8830 14183 : if (ctx->region_type != ORT_UNTIED_TASK)
8831 : return false;
8832 37 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8833 37 : if (n == NULL)
8834 : {
8835 6 : error ("threadprivate variable %qE used in untied task",
8836 6 : DECL_NAME (decl));
8837 6 : inform (ctx->location, "enclosing task");
8838 6 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
8839 : }
8840 37 : if (decl2)
8841 4 : splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
8842 : return false;
8843 : }
8844 :
8845 : /* Return true if global var DECL is device resident. */
8846 :
8847 : static bool
8848 642 : device_resident_p (tree decl)
8849 : {
8850 642 : tree attr = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (decl));
8851 :
8852 642 : if (!attr)
8853 : return false;
8854 :
8855 0 : for (tree t = TREE_VALUE (attr); t; t = TREE_PURPOSE (t))
8856 : {
8857 0 : tree c = TREE_VALUE (t);
8858 0 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DEVICE_RESIDENT)
8859 : return true;
8860 : }
8861 :
8862 : return false;
8863 : }
8864 :
8865 : /* Return true if DECL has an ACC DECLARE attribute. */
8866 :
8867 : static bool
8868 9101 : is_oacc_declared (tree decl)
8869 : {
8870 9101 : tree t = TREE_CODE (decl) == MEM_REF ? TREE_OPERAND (decl, 0) : decl;
8871 9101 : tree declared = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (t));
8872 9101 : return declared != NULL_TREE;
8873 : }
8874 :
8875 : /* Determine outer default flags for DECL mentioned in an OMP region
8876 : but not declared in an enclosing clause.
8877 :
8878 : ??? Some compiler-generated variables (like SAVE_EXPRs) could be
8879 : remapped firstprivate instead of shared. To some extent this is
8880 : addressed in omp_firstprivatize_type_sizes, but not
8881 : effectively. */
8882 :
8883 : static unsigned
8884 47877 : omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
8885 : bool in_code, unsigned flags)
8886 : {
8887 47877 : enum omp_clause_default_kind default_kind = ctx->default_kind;
8888 47877 : enum omp_clause_default_kind kind;
8889 :
8890 47877 : kind = lang_hooks.decls.omp_predetermined_sharing (decl);
8891 47877 : if (ctx->region_type & ORT_TASK)
8892 : {
8893 3969 : tree detach_clause = omp_find_clause (ctx->clauses, OMP_CLAUSE_DETACH);
8894 :
8895 : /* The event-handle specified by a detach clause should always be firstprivate,
8896 : regardless of the current default. */
8897 4181 : if (detach_clause && OMP_CLAUSE_DECL (detach_clause) == decl)
8898 : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
8899 : }
8900 47877 : if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
8901 : default_kind = kind;
8902 45063 : else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
8903 : default_kind = OMP_CLAUSE_DEFAULT_SHARED;
8904 : /* For C/C++ default({,first}private), variables with static storage duration
8905 : declared in a namespace or global scope and referenced in construct
8906 : must be explicitly specified, i.e. acts as default(none). */
8907 45062 : else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
8908 45062 : || default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
8909 368 : && VAR_P (decl)
8910 321 : && is_global_var (decl)
8911 184 : && (DECL_FILE_SCOPE_P (decl)
8912 104 : || (DECL_CONTEXT (decl)
8913 104 : && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
8914 45190 : && !lang_GNU_Fortran ())
8915 : default_kind = OMP_CLAUSE_DEFAULT_NONE;
8916 :
8917 47748 : switch (default_kind)
8918 : {
8919 267 : case OMP_CLAUSE_DEFAULT_NONE:
8920 267 : {
8921 267 : const char *rtype;
8922 :
8923 267 : if (ctx->region_type & ORT_PARALLEL)
8924 : rtype = "parallel";
8925 108 : else if ((ctx->region_type & ORT_TASKLOOP) == ORT_TASKLOOP)
8926 : rtype = "taskloop";
8927 72 : else if (ctx->region_type & ORT_TASK)
8928 : rtype = "task";
8929 36 : else if (ctx->region_type & ORT_TEAMS)
8930 : rtype = "teams";
8931 : else
8932 0 : gcc_unreachable ();
8933 :
8934 267 : error ("%qE not specified in enclosing %qs",
8935 267 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)), rtype);
8936 267 : inform (ctx->location, "enclosing %qs", rtype);
8937 : }
8938 : /* FALLTHRU */
8939 44246 : case OMP_CLAUSE_DEFAULT_SHARED:
8940 44246 : flags |= GOVD_SHARED;
8941 44246 : break;
8942 155 : case OMP_CLAUSE_DEFAULT_PRIVATE:
8943 155 : flags |= GOVD_PRIVATE;
8944 155 : break;
8945 277 : case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
8946 277 : flags |= GOVD_FIRSTPRIVATE;
8947 277 : break;
8948 3199 : case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
8949 : /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */
8950 3199 : gcc_assert ((ctx->region_type & ORT_TASK) != 0);
8951 3199 : if (struct gimplify_omp_ctx *octx = ctx->outer_context)
8952 : {
8953 2162 : omp_notice_variable (octx, decl, in_code);
8954 2992 : for (; octx; octx = octx->outer_context)
8955 : {
8956 2936 : splay_tree_node n2;
8957 :
8958 2936 : n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
8959 2936 : if ((octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)) != 0
8960 5 : && (n2 == NULL || (n2->value & GOVD_DATA_SHARE_CLASS) == 0))
8961 5 : continue;
8962 2931 : if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
8963 : {
8964 897 : flags |= GOVD_FIRSTPRIVATE;
8965 897 : goto found_outer;
8966 : }
8967 2034 : if ((octx->region_type & (ORT_PARALLEL | ORT_TEAMS)) != 0)
8968 : {
8969 1209 : flags |= GOVD_SHARED;
8970 1209 : goto found_outer;
8971 : }
8972 : }
8973 : }
8974 :
8975 1093 : if (TREE_CODE (decl) == PARM_DECL
8976 1093 : || (!is_global_var (decl)
8977 288 : && DECL_CONTEXT (decl) == current_function_decl))
8978 713 : flags |= GOVD_FIRSTPRIVATE;
8979 : else
8980 380 : flags |= GOVD_SHARED;
8981 47877 : found_outer:
8982 : break;
8983 :
8984 0 : default:
8985 0 : gcc_unreachable ();
8986 : }
8987 :
8988 47877 : return flags;
8989 : }
8990 :
8991 : /* Return string name for types of OpenACC constructs from ORT_* values. */
8992 :
8993 : static const char *
8994 570 : oacc_region_type_name (enum omp_region_type region_type)
8995 : {
8996 570 : switch (region_type)
8997 : {
8998 : case ORT_ACC_DATA:
8999 : return "data";
9000 140 : case ORT_ACC_PARALLEL:
9001 140 : return "parallel";
9002 140 : case ORT_ACC_KERNELS:
9003 140 : return "kernels";
9004 140 : case ORT_ACC_SERIAL:
9005 140 : return "serial";
9006 0 : default:
9007 0 : gcc_unreachable ();
9008 : }
9009 : }
9010 :
9011 : /* Determine outer default flags for DECL mentioned in an OACC region
9012 : but not declared in an enclosing clause. */
9013 :
9014 : static unsigned
9015 8839 : oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
9016 : {
9017 8839 : struct gimplify_omp_ctx *ctx_default = ctx;
9018 : /* If no 'default' clause appears on this compute construct... */
9019 8839 : if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED)
9020 : {
9021 : /* ..., see if one appears on a lexically containing 'data'
9022 : construct. */
9023 9618 : while ((ctx_default = ctx_default->outer_context))
9024 : {
9025 1534 : if (ctx_default->region_type == ORT_ACC_DATA
9026 1534 : && ctx_default->default_kind != OMP_CLAUSE_DEFAULT_SHARED)
9027 : break;
9028 : }
9029 : /* If not, reset. */
9030 8260 : if (!ctx_default)
9031 8663 : ctx_default = ctx;
9032 : }
9033 :
9034 8839 : bool on_device = false;
9035 8839 : bool is_private = false;
9036 8839 : bool declared = is_oacc_declared (decl);
9037 8839 : tree type = TREE_TYPE (decl);
9038 :
9039 8839 : if (omp_privatize_by_reference (decl))
9040 338 : type = TREE_TYPE (type);
9041 :
9042 : /* For Fortran COMMON blocks, only used variables in those blocks are
9043 : transferred and remapped. The block itself will have a private clause to
9044 : avoid transfering the data twice.
9045 : The hook evaluates to false by default. For a variable in Fortran's COMMON
9046 : or EQUIVALENCE block, returns 'true' (as we have shared=false) - as only
9047 : the variables in such a COMMON/EQUIVALENCE block shall be privatized not
9048 : the whole block. For C++ and Fortran, it can also be true under certain
9049 : other conditions, if DECL_HAS_VALUE_EXPR. */
9050 8839 : if (RECORD_OR_UNION_TYPE_P (type))
9051 983 : is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false);
9052 :
9053 8839 : if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0
9054 8839 : && is_global_var (decl)
9055 642 : && device_resident_p (decl)
9056 8839 : && !is_private)
9057 : {
9058 0 : on_device = true;
9059 0 : flags |= GOVD_MAP_TO_ONLY;
9060 : }
9061 :
9062 8839 : switch (ctx->region_type)
9063 : {
9064 1460 : case ORT_ACC_KERNELS:
9065 1460 : if (is_private)
9066 0 : flags |= GOVD_FIRSTPRIVATE;
9067 1460 : else if (AGGREGATE_TYPE_P (type))
9068 : {
9069 : /* Aggregates default to 'present_or_copy', or 'present'. */
9070 415 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9071 397 : flags |= GOVD_MAP;
9072 : else
9073 18 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9074 : }
9075 : else
9076 : /* Scalars default to 'copy'. */
9077 1045 : flags |= GOVD_MAP | GOVD_MAP_FORCE;
9078 :
9079 : break;
9080 :
9081 7379 : case ORT_ACC_PARALLEL:
9082 7379 : case ORT_ACC_SERIAL:
9083 7379 : if (is_private)
9084 0 : flags |= GOVD_FIRSTPRIVATE;
9085 7379 : else if (on_device || declared)
9086 17 : flags |= GOVD_MAP;
9087 7362 : else if (AGGREGATE_TYPE_P (type))
9088 : {
9089 : /* Aggregates default to 'present_or_copy', or 'present'. */
9090 3697 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9091 3431 : flags |= GOVD_MAP;
9092 : else
9093 266 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9094 : }
9095 : else
9096 : /* Scalars default to 'firstprivate'. */
9097 3665 : flags |= GOVD_FIRSTPRIVATE;
9098 :
9099 : break;
9100 :
9101 0 : default:
9102 0 : gcc_unreachable ();
9103 : }
9104 :
9105 8839 : if (DECL_ARTIFICIAL (decl))
9106 : ; /* We can get compiler-generated decls, and should not complain
9107 : about them. */
9108 8528 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_NONE)
9109 : {
9110 420 : error ("%qE not specified in enclosing OpenACC %qs construct",
9111 210 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)),
9112 : oacc_region_type_name (ctx->region_type));
9113 210 : if (ctx_default != ctx)
9114 150 : inform (ctx->location, "enclosing OpenACC %qs construct and",
9115 : oacc_region_type_name (ctx->region_type));
9116 210 : inform (ctx_default->location,
9117 : "enclosing OpenACC %qs construct with %qs clause",
9118 : oacc_region_type_name (ctx_default->region_type),
9119 : "default(none)");
9120 : }
9121 8318 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_PRESENT)
9122 : ; /* Handled above. */
9123 : else
9124 7785 : gcc_checking_assert (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED);
9125 :
9126 8839 : return flags;
9127 : }
9128 :
9129 : /* Record the fact that DECL was used within the OMP context CTX.
9130 : IN_CODE is true when real code uses DECL, and false when we should
9131 : merely emit default(none) errors. Return true if DECL is going to
9132 : be remapped and thus DECL shouldn't be gimplified into its
9133 : DECL_VALUE_EXPR (if any). */
9134 :
9135 : static bool
9136 3900304 : omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
9137 : {
9138 3900304 : splay_tree_node n;
9139 3900304 : unsigned flags = in_code ? GOVD_SEEN : 0;
9140 3900304 : bool ret = false, shared;
9141 :
9142 3900304 : if (error_operand_p (decl))
9143 : return false;
9144 :
9145 3900304 : if (DECL_ARTIFICIAL (decl))
9146 : {
9147 2226827 : tree attr = lookup_attribute ("omp allocate var", DECL_ATTRIBUTES (decl));
9148 2226827 : if (attr)
9149 543 : decl = TREE_VALUE (TREE_VALUE (attr));
9150 : }
9151 :
9152 3900304 : if (ctx->region_type == ORT_NONE)
9153 248 : return lang_hooks.decls.omp_disregard_value_expr (decl, false);
9154 :
9155 3900056 : if (is_global_var (decl))
9156 : {
9157 : /* Threadprivate variables are predetermined. */
9158 501566 : if (DECL_THREAD_LOCAL_P (decl))
9159 13565 : return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
9160 :
9161 488001 : if (DECL_HAS_VALUE_EXPR_P (decl))
9162 : {
9163 4380 : if (ctx->region_type & ORT_ACC)
9164 : /* For OpenACC, defer expansion of value to avoid transfering
9165 : privatized common block data instead of im-/explicitly
9166 : transferred variables which are in common blocks. */
9167 : ;
9168 : else
9169 : {
9170 2104 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
9171 :
9172 2104 : if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
9173 618 : return omp_notice_threadprivate_variable (ctx, decl, value);
9174 : }
9175 : }
9176 :
9177 487383 : if (gimplify_omp_ctxp->outer_context == NULL
9178 113489 : && VAR_P (decl)
9179 600872 : && oacc_get_fn_attrib (current_function_decl))
9180 : {
9181 765 : location_t loc = DECL_SOURCE_LOCATION (decl);
9182 :
9183 765 : if (lookup_attribute ("omp declare target link",
9184 765 : DECL_ATTRIBUTES (decl)))
9185 : {
9186 48 : error_at (loc,
9187 : "%qE with %<link%> clause used in %<routine%> function",
9188 24 : DECL_NAME (decl));
9189 24 : return false;
9190 : }
9191 741 : else if (!lookup_attribute ("omp declare target",
9192 741 : DECL_ATTRIBUTES (decl)))
9193 : {
9194 132 : error_at (loc,
9195 : "%qE requires a %<declare%> directive for use "
9196 66 : "in a %<routine%> function", DECL_NAME (decl));
9197 66 : return false;
9198 : }
9199 : }
9200 : }
9201 :
9202 3885783 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9203 3885783 : if ((ctx->region_type & ORT_TARGET) != 0)
9204 : {
9205 844347 : if (n == NULL)
9206 : {
9207 44976 : unsigned nflags = flags;
9208 44976 : if ((ctx->region_type & ORT_ACC) == 0)
9209 : {
9210 34022 : bool is_declare_target = false;
9211 34022 : if (is_global_var (decl)
9212 34022 : && varpool_node::get_create (decl)->offloadable)
9213 : {
9214 7002 : struct gimplify_omp_ctx *octx;
9215 7002 : for (octx = ctx->outer_context;
9216 7010 : octx; octx = octx->outer_context)
9217 : {
9218 9 : n = splay_tree_lookup (octx->variables,
9219 : (splay_tree_key)decl);
9220 9 : if (n
9221 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED
9222 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
9223 : break;
9224 : }
9225 7002 : is_declare_target = octx == NULL;
9226 : }
9227 7002 : if (!is_declare_target)
9228 : {
9229 27021 : int gdmk;
9230 27021 : enum omp_clause_defaultmap_kind kind;
9231 27021 : if (lang_hooks.decls.omp_allocatable_p (decl))
9232 : gdmk = GDMK_ALLOCATABLE;
9233 26674 : else if (lang_hooks.decls.omp_scalar_target_p (decl))
9234 : gdmk = GDMK_SCALAR_TARGET;
9235 26599 : else if (lang_hooks.decls.omp_scalar_p (decl, false))
9236 : gdmk = GDMK_SCALAR;
9237 11152 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
9238 11152 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
9239 3102 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
9240 : == POINTER_TYPE)))
9241 : gdmk = GDMK_POINTER;
9242 : else
9243 : gdmk = GDMK_AGGREGATE;
9244 27021 : kind = lang_hooks.decls.omp_predetermined_mapping (decl);
9245 27021 : if (kind != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
9246 : {
9247 1096 : if (kind == OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE)
9248 101 : nflags |= GOVD_FIRSTPRIVATE;
9249 995 : else if (kind == OMP_CLAUSE_DEFAULTMAP_TO)
9250 995 : nflags |= GOVD_MAP | GOVD_MAP_TO_ONLY;
9251 : else
9252 0 : gcc_unreachable ();
9253 : }
9254 25925 : else if (ctx->defaultmap[gdmk] == 0)
9255 : {
9256 77 : tree d = lang_hooks.decls.omp_report_decl (decl);
9257 77 : error ("%qE not specified in enclosing %<target%>",
9258 77 : DECL_NAME (d));
9259 77 : inform (ctx->location, "enclosing %<target%>");
9260 : }
9261 25848 : else if (ctx->defaultmap[gdmk]
9262 25848 : & (GOVD_MAP_0LEN_ARRAY | GOVD_FIRSTPRIVATE))
9263 9058 : nflags |= ctx->defaultmap[gdmk];
9264 16790 : else if (ctx->defaultmap[gdmk] & GOVD_MAP_FORCE_PRESENT)
9265 : {
9266 42 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9267 42 : nflags |= ctx->defaultmap[gdmk] | GOVD_MAP_ALLOC_ONLY;
9268 : }
9269 : else
9270 : {
9271 16748 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9272 16748 : nflags |= ctx->defaultmap[gdmk] & ~GOVD_MAP;
9273 : }
9274 : }
9275 : }
9276 :
9277 44976 : struct gimplify_omp_ctx *octx = ctx->outer_context;
9278 44976 : if ((ctx->region_type & ORT_ACC) && octx)
9279 : {
9280 : /* Look in outer OpenACC contexts, to see if there's a
9281 : data attribute for this variable. */
9282 3535 : omp_notice_variable (octx, decl, in_code);
9283 :
9284 5307 : for (; octx; octx = octx->outer_context)
9285 : {
9286 3883 : if (!(octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)))
9287 : break;
9288 3883 : splay_tree_node n2
9289 3883 : = splay_tree_lookup (octx->variables,
9290 : (splay_tree_key) decl);
9291 3883 : if (n2)
9292 : {
9293 2111 : if (octx->region_type == ORT_ACC_HOST_DATA)
9294 4 : error ("variable %qE declared in enclosing "
9295 4 : "%<host_data%> region", DECL_NAME (decl));
9296 2111 : nflags |= GOVD_MAP;
9297 2111 : if (octx->region_type == ORT_ACC_DATA
9298 2107 : && (n2->value & GOVD_MAP_0LEN_ARRAY))
9299 288 : nflags |= GOVD_MAP_0LEN_ARRAY;
9300 2111 : goto found_outer;
9301 : }
9302 : }
9303 : }
9304 :
9305 42865 : if ((nflags & ~(GOVD_MAP_TO_ONLY | GOVD_MAP_FROM_ONLY
9306 : | GOVD_MAP_ALLOC_ONLY)) == flags)
9307 : {
9308 32669 : tree type = TREE_TYPE (decl);
9309 32669 : location_t loc = DECL_SOURCE_LOCATION (decl);
9310 :
9311 32669 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases
9312 32669 : && omp_privatize_by_reference (decl))
9313 28 : type = TREE_TYPE (type);
9314 :
9315 32669 : if (!verify_type_context (loc, TCTX_OMP_MAP_IMP_REF, type))
9316 : /* Check if TYPE can appear in a target region.
9317 : verify_type_context has already issued an error if it
9318 : can't. */
9319 0 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9320 32669 : else if (!omp_mappable_type (type))
9321 : {
9322 8 : error ("%qD referenced in target region does not have "
9323 : "a mappable type", decl);
9324 8 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9325 : }
9326 : else
9327 : {
9328 32661 : if ((ctx->region_type & ORT_ACC) != 0)
9329 8839 : nflags = oacc_default_clause (ctx, decl, flags);
9330 : else
9331 23822 : nflags |= GOVD_MAP;
9332 : }
9333 : }
9334 10196 : found_outer:
9335 44976 : omp_add_variable (ctx, decl, nflags);
9336 44976 : if (ctx->region_type & ORT_ACC)
9337 : /* For OpenACC, as remarked above, defer expansion. */
9338 : shared = false;
9339 : else
9340 34022 : shared = (nflags & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9341 44976 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9342 : }
9343 : else
9344 : {
9345 799371 : if (ctx->region_type & ORT_ACC)
9346 : /* For OpenACC, as remarked above, defer expansion. */
9347 : shared = false;
9348 : else
9349 502946 : shared = ((n->value | flags)
9350 502946 : & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9351 799371 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9352 : /* If nothing changed, there's nothing left to do. */
9353 799371 : if ((n->value & flags) == flags)
9354 : return ret;
9355 16409 : flags |= n->value;
9356 16409 : n->value = flags;
9357 : }
9358 61385 : goto do_outer;
9359 : }
9360 :
9361 3041436 : if (n == NULL)
9362 : {
9363 1181763 : if (ctx->region_type == ORT_WORKSHARE
9364 : || ctx->region_type == ORT_TASKGROUP
9365 560796 : || ctx->region_type == ORT_SIMD
9366 288753 : || ctx->region_type == ORT_ACC
9367 92500 : || (ctx->region_type & ORT_TARGET_DATA) != 0)
9368 1133886 : goto do_outer;
9369 :
9370 47877 : flags = omp_default_clause (ctx, decl, in_code, flags);
9371 :
9372 47877 : if ((flags & GOVD_PRIVATE)
9373 47877 : && lang_hooks.decls.omp_private_outer_ref (decl))
9374 6 : flags |= GOVD_PRIVATE_OUTER_REF;
9375 :
9376 47877 : omp_add_variable (ctx, decl, flags);
9377 :
9378 47877 : shared = (flags & GOVD_SHARED) != 0;
9379 47877 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9380 47877 : goto do_outer;
9381 : }
9382 :
9383 : /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd
9384 : lb, b or incr expressions, those shouldn't be turned into simd arrays. */
9385 1859673 : if (ctx->region_type == ORT_SIMD
9386 151155 : && ctx->in_for_exprs
9387 70 : && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT))
9388 : == GOVD_PRIVATE))
9389 1859673 : flags &= ~GOVD_SEEN;
9390 :
9391 1859673 : if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
9392 31804 : && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
9393 1891438 : && DECL_SIZE (decl))
9394 : {
9395 31764 : tree size;
9396 31764 : if (!poly_int_tree_p (DECL_SIZE (decl)))
9397 : {
9398 148 : splay_tree_node n2;
9399 148 : tree t = DECL_VALUE_EXPR (decl);
9400 148 : gcc_assert (INDIRECT_REF_P (t));
9401 148 : t = TREE_OPERAND (t, 0);
9402 148 : gcc_assert (DECL_P (t));
9403 148 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
9404 148 : n2->value |= GOVD_SEEN;
9405 : }
9406 31616 : else if (omp_privatize_by_reference (decl)
9407 4181 : && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
9408 35760 : && !poly_int_tree_p (size))
9409 : {
9410 1325 : splay_tree_node n2;
9411 1325 : gcc_assert (DECL_P (size));
9412 1325 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size);
9413 1325 : if (n2)
9414 617 : omp_notice_variable (ctx, size, true);
9415 : }
9416 : }
9417 :
9418 1859673 : if (ctx->region_type & ORT_ACC)
9419 : /* For OpenACC, as remarked above, defer expansion. */
9420 : shared = false;
9421 : else
9422 1677738 : shared = ((flags | n->value) & GOVD_SHARED) != 0;
9423 1859673 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9424 :
9425 : /* If nothing changed, there's nothing left to do. */
9426 1859673 : if ((n->value & flags) == flags)
9427 : return ret;
9428 31765 : flags |= n->value;
9429 31765 : n->value = flags;
9430 :
9431 1274913 : do_outer:
9432 : /* If the variable is private in the current context, then we don't
9433 : need to propagate anything to an outer context. */
9434 1274913 : if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF))
9435 : return ret;
9436 1264527 : if ((flags & (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9437 : == (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9438 : return ret;
9439 1264467 : if ((flags & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
9440 : | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9441 : == (GOVD_LASTPRIVATE | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9442 : return ret;
9443 1264467 : if (ctx->outer_context
9444 1264467 : && omp_notice_variable (ctx->outer_context, decl, in_code))
9445 : return true;
9446 : return ret;
9447 : }
9448 :
9449 : /* Verify that DECL is private within CTX. If there's specific information
9450 : to the contrary in the innermost scope, generate an error. */
9451 :
9452 : static bool
9453 50135 : omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd)
9454 : {
9455 95830 : splay_tree_node n;
9456 :
9457 95830 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9458 95830 : if (n != NULL)
9459 : {
9460 17960 : if (n->value & GOVD_SHARED)
9461 : {
9462 407 : if (ctx == gimplify_omp_ctxp)
9463 : {
9464 0 : if (simd)
9465 0 : error ("iteration variable %qE is predetermined linear",
9466 0 : DECL_NAME (decl));
9467 : else
9468 0 : error ("iteration variable %qE should be private",
9469 0 : DECL_NAME (decl));
9470 0 : n->value = GOVD_PRIVATE;
9471 0 : return true;
9472 : }
9473 : else
9474 : return false;
9475 : }
9476 17553 : else if ((n->value & GOVD_EXPLICIT) != 0
9477 9711 : && (ctx == gimplify_omp_ctxp
9478 340 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9479 220 : && gimplify_omp_ctxp->outer_context == ctx)))
9480 : {
9481 9591 : if ((n->value & GOVD_FIRSTPRIVATE) != 0)
9482 4 : error ("iteration variable %qE should not be firstprivate",
9483 4 : DECL_NAME (decl));
9484 9587 : else if ((n->value & GOVD_REDUCTION) != 0)
9485 8 : error ("iteration variable %qE should not be reduction",
9486 8 : DECL_NAME (decl));
9487 9579 : else if (simd != 1 && (n->value & GOVD_LINEAR) != 0)
9488 58 : error ("iteration variable %qE should not be linear",
9489 58 : DECL_NAME (decl));
9490 : }
9491 17553 : return (ctx == gimplify_omp_ctxp
9492 17553 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9493 19435 : && gimplify_omp_ctxp->outer_context == ctx));
9494 : }
9495 :
9496 77870 : if (ctx->region_type != ORT_WORKSHARE
9497 : && ctx->region_type != ORT_TASKGROUP
9498 49420 : && ctx->region_type != ORT_SIMD
9499 36155 : && ctx->region_type != ORT_ACC)
9500 : return false;
9501 53888 : else if (ctx->outer_context)
9502 : return omp_is_private (ctx->outer_context, decl, simd);
9503 : return false;
9504 : }
9505 :
9506 : /* Return true if DECL is private within a parallel region
9507 : that binds to the current construct's context or in parallel
9508 : region's REDUCTION clause. */
9509 :
9510 : static bool
9511 11547 : omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
9512 : {
9513 11619 : splay_tree_node n;
9514 :
9515 11619 : do
9516 : {
9517 11619 : ctx = ctx->outer_context;
9518 11619 : if (ctx == NULL)
9519 : {
9520 2764 : if (is_global_var (decl))
9521 : return false;
9522 :
9523 : /* References might be private, but might be shared too,
9524 : when checking for copyprivate, assume they might be
9525 : private, otherwise assume they might be shared. */
9526 1290 : if (copyprivate)
9527 : return true;
9528 :
9529 1244 : if (omp_privatize_by_reference (decl))
9530 : return false;
9531 :
9532 : /* Treat C++ privatized non-static data members outside
9533 : of the privatization the same. */
9534 1198 : if (omp_member_access_dummy_var (decl))
9535 : return false;
9536 :
9537 : return true;
9538 : }
9539 :
9540 8855 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
9541 :
9542 8855 : if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
9543 1291 : && (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0))
9544 : {
9545 242 : if ((ctx->region_type & ORT_TARGET_DATA) != 0
9546 238 : || n == NULL
9547 230 : || (n->value & GOVD_MAP) == 0)
9548 12 : continue;
9549 : return false;
9550 : }
9551 :
9552 7564 : if (n != NULL)
9553 : {
9554 5360 : if ((n->value & GOVD_LOCAL) != 0
9555 5360 : && omp_member_access_dummy_var (decl))
9556 : return false;
9557 5321 : return (n->value & GOVD_SHARED) == 0;
9558 : }
9559 :
9560 3253 : if (ctx->region_type == ORT_WORKSHARE
9561 : || ctx->region_type == ORT_TASKGROUP
9562 3197 : || ctx->region_type == ORT_SIMD
9563 3193 : || ctx->region_type == ORT_ACC)
9564 60 : continue;
9565 :
9566 : break;
9567 : }
9568 : while (1);
9569 : return false;
9570 : }
9571 :
9572 : /* Callback for walk_tree to find a DECL_EXPR for the given DECL. */
9573 :
9574 : static tree
9575 3148 : find_decl_expr (tree *tp, int *walk_subtrees, void *data)
9576 : {
9577 3148 : tree t = *tp;
9578 :
9579 : /* If this node has been visited, unmark it and keep looking. */
9580 3148 : if (TREE_CODE (t) == DECL_EXPR && DECL_EXPR_DECL (t) == (tree) data)
9581 : return t;
9582 :
9583 2724 : if (IS_TYPE_OR_DECL_P (t))
9584 452 : *walk_subtrees = 0;
9585 : return NULL_TREE;
9586 : }
9587 :
9588 :
9589 : /* Gimplify the affinity clause but effectively ignore it.
9590 : Generate:
9591 : var = begin;
9592 : if ((step > 1) ? var <= end : var > end)
9593 : locatator_var_expr; */
9594 :
9595 : static void
9596 374 : gimplify_omp_affinity (tree *list_p, gimple_seq *pre_p)
9597 : {
9598 374 : tree last_iter = NULL_TREE;
9599 374 : tree last_bind = NULL_TREE;
9600 374 : tree label = NULL_TREE;
9601 374 : tree *last_body = NULL;
9602 1011 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9603 637 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
9604 : {
9605 637 : tree t = OMP_CLAUSE_DECL (c);
9606 637 : if (OMP_ITERATOR_DECL_P (t))
9607 : {
9608 389 : if (TREE_VALUE (t) == null_pointer_node)
9609 201 : continue;
9610 188 : if (TREE_PURPOSE (t) != last_iter)
9611 : {
9612 127 : if (last_bind)
9613 : {
9614 9 : append_to_statement_list (label, last_body);
9615 9 : gimplify_and_add (last_bind, pre_p);
9616 9 : last_bind = NULL_TREE;
9617 : }
9618 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9619 : {
9620 147 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
9621 : is_gimple_val, fb_rvalue) == GS_ERROR
9622 147 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
9623 : is_gimple_val, fb_rvalue) == GS_ERROR
9624 147 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
9625 : is_gimple_val, fb_rvalue) == GS_ERROR
9626 294 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
9627 : is_gimple_val, fb_rvalue)
9628 : == GS_ERROR))
9629 0 : return;
9630 : }
9631 127 : last_iter = TREE_PURPOSE (t);
9632 127 : tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 5);
9633 127 : last_bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
9634 : NULL, block);
9635 127 : last_body = &BIND_EXPR_BODY (last_bind);
9636 127 : tree cond = NULL_TREE;
9637 127 : location_t loc = OMP_CLAUSE_LOCATION (c);
9638 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9639 : {
9640 147 : tree var = TREE_VEC_ELT (it, 0);
9641 147 : tree begin = TREE_VEC_ELT (it, 1);
9642 147 : tree end = TREE_VEC_ELT (it, 2);
9643 147 : tree step = TREE_VEC_ELT (it, 3);
9644 147 : loc = DECL_SOURCE_LOCATION (var);
9645 147 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
9646 : var, begin);
9647 147 : append_to_statement_list_force (tem, last_body);
9648 :
9649 147 : tree cond1 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9650 147 : step, build_zero_cst (TREE_TYPE (step)));
9651 147 : tree cond2 = fold_build2_loc (loc, LE_EXPR, boolean_type_node,
9652 : var, end);
9653 147 : tree cond3 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9654 : var, end);
9655 147 : cond1 = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
9656 : cond1, cond2, cond3);
9657 147 : if (cond)
9658 20 : cond = fold_build2_loc (loc, TRUTH_AND_EXPR,
9659 : boolean_type_node, cond, cond1);
9660 : else
9661 : cond = cond1;
9662 : }
9663 127 : tree cont_label = create_artificial_label (loc);
9664 127 : label = build1 (LABEL_EXPR, void_type_node, cont_label);
9665 127 : tree tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9666 : void_node,
9667 : build_and_jump (&cont_label));
9668 127 : append_to_statement_list_force (tem, last_body);
9669 : }
9670 188 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
9671 : {
9672 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t), 0),
9673 : last_body);
9674 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
9675 : }
9676 188 : if (error_operand_p (TREE_VALUE (t)))
9677 : return;
9678 188 : append_to_statement_list_force (TREE_VALUE (t), last_body);
9679 188 : TREE_VALUE (t) = null_pointer_node;
9680 : }
9681 : else
9682 : {
9683 248 : if (last_bind)
9684 : {
9685 9 : append_to_statement_list (label, last_body);
9686 9 : gimplify_and_add (last_bind, pre_p);
9687 9 : last_bind = NULL_TREE;
9688 : }
9689 248 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
9690 : {
9691 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
9692 : NULL, is_gimple_val, fb_rvalue);
9693 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
9694 : }
9695 248 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
9696 : return;
9697 248 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
9698 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
9699 : return;
9700 248 : gimplify_and_add (OMP_CLAUSE_DECL (c), pre_p);
9701 : }
9702 : }
9703 374 : if (last_bind)
9704 : {
9705 109 : append_to_statement_list (label, last_body);
9706 109 : gimplify_and_add (last_bind, pre_p);
9707 : }
9708 : return;
9709 : }
9710 :
9711 : /* Returns a tree expression containing the total iteration count of the
9712 : OpenMP iterator IT. */
9713 :
9714 : static tree
9715 328 : compute_omp_iterator_count (tree it, gimple_seq *pre_p)
9716 : {
9717 328 : tree tcnt = size_one_node;
9718 722 : for (; it; it = TREE_CHAIN (it))
9719 : {
9720 394 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
9721 : is_gimple_val, fb_rvalue) == GS_ERROR
9722 394 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
9723 : is_gimple_val, fb_rvalue) == GS_ERROR
9724 394 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
9725 : is_gimple_val, fb_rvalue) == GS_ERROR
9726 788 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
9727 : is_gimple_val, fb_rvalue) == GS_ERROR))
9728 0 : return NULL_TREE;
9729 394 : tree var = TREE_VEC_ELT (it, 0);
9730 394 : tree begin = TREE_VEC_ELT (it, 1);
9731 394 : tree end = TREE_VEC_ELT (it, 2);
9732 394 : tree step = TREE_VEC_ELT (it, 3);
9733 394 : tree orig_step = TREE_VEC_ELT (it, 4);
9734 394 : tree type = TREE_TYPE (var);
9735 394 : tree stype = TREE_TYPE (step);
9736 394 : location_t loc = DECL_SOURCE_LOCATION (var);
9737 394 : tree endmbegin;
9738 : /* Compute count for this iterator as
9739 : orig_step > 0
9740 : ? (begin < end ? (end - begin + (step - 1)) / step : 0)
9741 : : (begin > end ? (end - begin + (step + 1)) / step : 0)
9742 : and compute product of those for the entire clause. */
9743 394 : if (POINTER_TYPE_P (type))
9744 42 : endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR, stype, end, begin);
9745 : else
9746 352 : endmbegin = fold_build2_loc (loc, MINUS_EXPR, type, end, begin);
9747 394 : tree stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype, step,
9748 : build_int_cst (stype, 1));
9749 394 : tree stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
9750 : build_int_cst (stype, 1));
9751 394 : tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
9752 : unshare_expr (endmbegin), stepm1);
9753 394 : pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, pos, step);
9754 394 : tree neg = fold_build2_loc (loc, PLUS_EXPR, stype, endmbegin, stepp1);
9755 394 : if (TYPE_UNSIGNED (stype))
9756 : {
9757 31 : neg = fold_build1_loc (loc, NEGATE_EXPR, stype, neg);
9758 31 : step = fold_build1_loc (loc, NEGATE_EXPR, stype, step);
9759 : }
9760 394 : neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, neg, step);
9761 394 : step = NULL_TREE;
9762 394 : tree cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node, begin, end);
9763 394 : pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
9764 : build_int_cst (stype, 0));
9765 394 : cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node, end, begin);
9766 394 : neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
9767 : build_int_cst (stype, 0));
9768 394 : tree osteptype = TREE_TYPE (orig_step);
9769 394 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9770 : build_int_cst (osteptype, 0));
9771 394 : tree cnt = fold_build3_loc (loc, COND_EXPR, stype, cond, pos, neg);
9772 394 : cnt = fold_convert_loc (loc, sizetype, cnt);
9773 394 : if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
9774 : fb_rvalue) == GS_ERROR)
9775 : return NULL_TREE;
9776 394 : tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
9777 : }
9778 328 : if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
9779 : return NULL_TREE;
9780 :
9781 328 : return tcnt;
9782 : }
9783 :
9784 : /* Build loops iterating over the space defined by the OpenMP iterator IT.
9785 : Returns a pointer to the BIND_EXPR_BODY in the innermost loop body.
9786 : LAST_BIND is set to point to the BIND_EXPR containing the whole loop. */
9787 :
9788 : static tree *
9789 328 : build_omp_iterator_loop (tree it, gimple_seq *pre_p, tree *last_bind)
9790 : {
9791 328 : if (*last_bind)
9792 31 : gimplify_and_add (*last_bind, pre_p);
9793 328 : tree block = TREE_VEC_ELT (it, 5);
9794 328 : *last_bind = build3 (BIND_EXPR, void_type_node,
9795 328 : BLOCK_VARS (block), NULL, block);
9796 328 : TREE_SIDE_EFFECTS (*last_bind) = 1;
9797 328 : tree *p = &BIND_EXPR_BODY (*last_bind);
9798 722 : for (; it; it = TREE_CHAIN (it))
9799 : {
9800 394 : tree var = TREE_VEC_ELT (it, 0);
9801 394 : tree begin = TREE_VEC_ELT (it, 1);
9802 394 : tree end = TREE_VEC_ELT (it, 2);
9803 394 : tree step = TREE_VEC_ELT (it, 3);
9804 394 : tree orig_step = TREE_VEC_ELT (it, 4);
9805 394 : tree type = TREE_TYPE (var);
9806 394 : location_t loc = DECL_SOURCE_LOCATION (var);
9807 : /* Emit:
9808 : var = begin;
9809 : goto cond_label;
9810 : beg_label:
9811 : ...
9812 : var = var + step;
9813 : cond_label:
9814 : if (orig_step > 0) {
9815 : if (var < end) goto beg_label;
9816 : } else {
9817 : if (var > end) goto beg_label;
9818 : }
9819 : for each iterator, with inner iterators added to
9820 : the ... above. */
9821 394 : tree beg_label = create_artificial_label (loc);
9822 394 : tree cond_label = NULL_TREE;
9823 394 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, begin);
9824 394 : append_to_statement_list_force (tem, p);
9825 394 : tem = build_and_jump (&cond_label);
9826 394 : append_to_statement_list_force (tem, p);
9827 394 : tem = build1 (LABEL_EXPR, void_type_node, beg_label);
9828 394 : append_to_statement_list (tem, p);
9829 394 : tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
9830 : NULL_TREE, NULL_TREE);
9831 394 : TREE_SIDE_EFFECTS (bind) = 1;
9832 394 : SET_EXPR_LOCATION (bind, loc);
9833 394 : append_to_statement_list_force (bind, p);
9834 394 : if (POINTER_TYPE_P (type))
9835 42 : tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
9836 : var, fold_convert_loc (loc, sizetype, step));
9837 : else
9838 352 : tem = build2_loc (loc, PLUS_EXPR, type, var, step);
9839 394 : tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, tem);
9840 394 : append_to_statement_list_force (tem, p);
9841 394 : tem = build1 (LABEL_EXPR, void_type_node, cond_label);
9842 394 : append_to_statement_list (tem, p);
9843 394 : tree cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node, var, end);
9844 394 : tree pos = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9845 : build_and_jump (&beg_label), void_node);
9846 394 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, var, end);
9847 394 : tree neg = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9848 : build_and_jump (&beg_label), void_node);
9849 394 : tree osteptype = TREE_TYPE (orig_step);
9850 394 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9851 : build_int_cst (osteptype, 0));
9852 394 : tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, pos, neg);
9853 394 : append_to_statement_list_force (tem, p);
9854 394 : p = &BIND_EXPR_BODY (bind);
9855 : }
9856 :
9857 328 : return p;
9858 : }
9859 :
9860 :
9861 : /* Callback for walk_tree to find a VAR_DECL (stored in DATA) in the
9862 : tree TP. */
9863 :
9864 : static tree
9865 2354 : find_var_decl (tree *tp, int *, void *data)
9866 : {
9867 2354 : if (*tp == (tree) data)
9868 214 : return *tp;
9869 :
9870 : return NULL_TREE;
9871 : }
9872 :
9873 : /* Returns an element-by-element copy of OMP iterator tree IT. */
9874 :
9875 : static tree
9876 206 : copy_omp_iterator (tree it, int elem_count = -1)
9877 : {
9878 206 : if (elem_count < 0)
9879 60 : elem_count = TREE_VEC_LENGTH (it);
9880 206 : tree new_it = make_tree_vec (elem_count);
9881 1442 : for (int i = 0; i < TREE_VEC_LENGTH (it); i++)
9882 1236 : TREE_VEC_ELT (new_it, i) = TREE_VEC_ELT (it, i);
9883 :
9884 206 : return new_it;
9885 : }
9886 :
9887 : /* Helper function for walk_tree in remap_omp_iterator_var. */
9888 :
9889 : static tree
9890 871 : remap_omp_iterator_var_1 (tree *tp, int *, void *data)
9891 : {
9892 871 : tree old_var = ((tree *) data)[0];
9893 871 : tree new_var = ((tree *) data)[1];
9894 :
9895 871 : if (*tp == old_var)
9896 92 : *tp = new_var;
9897 871 : return NULL_TREE;
9898 : }
9899 :
9900 : /* Replace instances of OLD_VAR in TP with NEW_VAR. */
9901 :
9902 : static void
9903 184 : remap_omp_iterator_var (tree *tp, tree old_var, tree new_var)
9904 : {
9905 184 : tree vars[2] = { old_var, new_var };
9906 184 : walk_tree (tp, remap_omp_iterator_var_1, vars, NULL);
9907 184 : }
9908 :
9909 : /* Scan through all clauses using OpenMP iterators in LIST_P. If any
9910 : clauses have iterators with variables that are not used by the clause
9911 : decl or size, issue a warning and replace the iterator with a copy with
9912 : the unused variables removed. */
9913 :
9914 : static void
9915 27567 : remove_unused_omp_iterator_vars (tree *list_p)
9916 : {
9917 27567 : auto_vec< vec<tree> > iter_vars;
9918 27567 : auto_vec<tree> new_iterators;
9919 :
9920 80277 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9921 : {
9922 52710 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
9923 52654 : continue;
9924 154 : auto_vec<tree> vars;
9925 154 : bool need_new_iterators = false;
9926 432 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
9927 : {
9928 278 : tree var = TREE_VEC_ELT (it, 0);
9929 278 : tree t = walk_tree (&OMP_CLAUSE_DECL (c), find_var_decl, var, NULL);
9930 278 : if (t == NULL_TREE)
9931 130 : t = walk_tree (&OMP_CLAUSE_SIZE (c), find_var_decl, var, NULL);
9932 130 : if (t == NULL_TREE)
9933 : {
9934 64 : need_new_iterators = true;
9935 64 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
9936 44 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
9937 28 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM))
9938 44 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
9939 92 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
9940 40 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
9941 : "iterator variable %qE not used in clause "
9942 40 : "expression", DECL_NAME (var));
9943 : }
9944 : else
9945 214 : vars.safe_push (var);
9946 : }
9947 154 : if (!need_new_iterators)
9948 90 : continue;
9949 64 : if (need_new_iterators && vars.is_empty ())
9950 : {
9951 : /* No iteration variables are used in the clause - remove the
9952 : iterator from the clause. */
9953 8 : OMP_CLAUSE_ITERATORS (c) = NULL_TREE;
9954 8 : continue;
9955 : }
9956 :
9957 : /* If a new iterator has been created for the current set of used
9958 : iterator variables, then use that as the iterator. Otherwise,
9959 : create a new iterator for the current iterator variable set. */
9960 : unsigned i;
9961 92 : for (i = 0; i < iter_vars.length (); i++)
9962 : {
9963 112 : if (vars.length () != iter_vars[i].length ())
9964 0 : continue;
9965 : bool identical_p = true;
9966 136 : for (unsigned j = 0; j < vars.length () && identical_p; j++)
9967 80 : identical_p = vars[j] == iter_vars[i][j];
9968 :
9969 56 : if (identical_p)
9970 : break;
9971 : }
9972 56 : if (i < iter_vars.length ())
9973 20 : OMP_CLAUSE_ITERATORS (c) = new_iterators[i];
9974 : else
9975 : {
9976 36 : tree new_iters = NULL_TREE;
9977 36 : tree *new_iters_p = &new_iters;
9978 36 : tree new_vars = NULL_TREE;
9979 36 : tree *new_vars_p = &new_vars;
9980 36 : i = 0;
9981 112 : for (tree it = OMP_CLAUSE_ITERATORS (c); it && i < vars.length();
9982 76 : it = TREE_CHAIN (it))
9983 : {
9984 76 : tree var = TREE_VEC_ELT (it, 0);
9985 76 : if (var == vars[i])
9986 : {
9987 60 : *new_iters_p = copy_omp_iterator (it);
9988 60 : *new_vars_p = build_decl (OMP_CLAUSE_LOCATION (c), VAR_DECL,
9989 60 : DECL_NAME (var), TREE_TYPE (var));
9990 60 : DECL_ARTIFICIAL (*new_vars_p) = 1;
9991 60 : DECL_CONTEXT (*new_vars_p) = DECL_CONTEXT (var);
9992 60 : TREE_VEC_ELT (*new_iters_p, 0) = *new_vars_p;
9993 60 : new_iters_p = &TREE_CHAIN (*new_iters_p);
9994 60 : new_vars_p = &DECL_CHAIN (*new_vars_p);
9995 60 : i++;
9996 : }
9997 : }
9998 36 : tree new_block = make_node (BLOCK);
9999 36 : BLOCK_VARS (new_block) = new_vars;
10000 36 : TREE_VEC_ELT (new_iters, 5) = new_block;
10001 36 : new_iterators.safe_push (new_iters);
10002 36 : iter_vars.safe_push (vars.copy ());
10003 36 : OMP_CLAUSE_ITERATORS (c) = new_iters;
10004 : }
10005 :
10006 : /* Remap clause to use the new variables. */
10007 56 : i = 0;
10008 148 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
10009 : {
10010 92 : tree old_var = vars[i++];
10011 92 : tree new_var = TREE_VEC_ELT (it, 0);
10012 92 : remap_omp_iterator_var (&OMP_CLAUSE_DECL (c), old_var, new_var);
10013 92 : remap_omp_iterator_var (&OMP_CLAUSE_SIZE (c), old_var, new_var);
10014 : }
10015 154 : }
10016 :
10017 27603 : for (unsigned i = 0; i < iter_vars.length (); i++)
10018 36 : iter_vars[i].release ();
10019 27567 : }
10020 :
10021 148 : struct iterator_loop_info_t
10022 : {
10023 : tree bind;
10024 : tree count;
10025 : tree index;
10026 : tree body_label;
10027 : auto_vec<tree> clauses;
10028 : };
10029 :
10030 : typedef hash_map<tree, iterator_loop_info_t> iterator_loop_info_map_t;
10031 :
10032 : /* Builds a loop to expand any OpenMP iterators in the clauses in LIST_P,
10033 : reusing any previously built loops if they use the same set of iterators.
10034 : Generated Gimple statements are placed into LOOPS_SEQ_P. The clause
10035 : iterators are updated with information on how and where to insert code into
10036 : the loop body. */
10037 :
10038 : static void
10039 27567 : build_omp_iterators_loops (tree *list_p, gimple_seq *loops_seq_p)
10040 : {
10041 27567 : iterator_loop_info_map_t loops;
10042 :
10043 80277 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10044 : {
10045 52710 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10046 52564 : continue;
10047 :
10048 146 : bool built_p;
10049 146 : iterator_loop_info_t &loop
10050 146 : = loops.get_or_insert (OMP_CLAUSE_ITERATORS (c), &built_p);
10051 :
10052 146 : if (!built_p)
10053 : {
10054 74 : loop.count = compute_omp_iterator_count (OMP_CLAUSE_ITERATORS (c),
10055 : loops_seq_p);
10056 74 : if (!loop.count)
10057 0 : continue;
10058 74 : if (integer_zerop (loop.count))
10059 8 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
10060 : "iteration count is zero");
10061 :
10062 74 : loop.bind = NULL_TREE;
10063 74 : tree *body = build_omp_iterator_loop (OMP_CLAUSE_ITERATORS (c),
10064 : loops_seq_p, &loop.bind);
10065 :
10066 74 : loop.index = create_tmp_var (sizetype);
10067 74 : SET_EXPR_LOCATION (loop.bind, OMP_CLAUSE_LOCATION (c));
10068 :
10069 : /* BEFORE LOOP: */
10070 : /* idx = -1; */
10071 : /* This should be initialized to before the individual elements,
10072 : as idx is pre-incremented in the loop body. */
10073 74 : gimple *assign = gimple_build_assign (loop.index, size_int (-1));
10074 74 : gimple_seq_add_stmt (loops_seq_p, assign);
10075 :
10076 : /* IN LOOP BODY: */
10077 : /* Create a label so we can find this point later. */
10078 74 : loop.body_label = create_artificial_label (OMP_CLAUSE_LOCATION (c));
10079 74 : tree tem = build1 (LABEL_EXPR, void_type_node, loop.body_label);
10080 74 : append_to_statement_list_force (tem, body);
10081 :
10082 : /* idx += 2; */
10083 74 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10084 : void_type_node, loop.index,
10085 : size_binop (PLUS_EXPR, loop.index, size_int (2)));
10086 74 : append_to_statement_list_force (tem, body);
10087 : }
10088 :
10089 : /* Create array to hold expanded values. */
10090 146 : tree last_count_2 = size_binop (MULT_EXPR, loop.count, size_int (2));
10091 146 : tree arr_length = size_binop (PLUS_EXPR, last_count_2, size_int (1));
10092 146 : tree elems = NULL_TREE;
10093 146 : if (TREE_CONSTANT (arr_length))
10094 : {
10095 146 : tree type = build_array_type (ptr_type_node,
10096 : build_index_type (arr_length));
10097 146 : elems = create_tmp_var_raw (type, "omp_iter_data");
10098 146 : TREE_ADDRESSABLE (elems) = 1;
10099 146 : gimple_add_tmp_var (elems);
10100 : }
10101 : else
10102 : {
10103 : /* Handle dynamic sizes. */
10104 0 : sorry ("dynamic iterator sizes not implemented yet");
10105 : }
10106 :
10107 : /* BEFORE LOOP: */
10108 : /* elems[0] = count; */
10109 146 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, size_int (0),
10110 : NULL_TREE, NULL_TREE);
10111 146 : tree tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10112 : void_type_node, lhs, loop.count);
10113 146 : gimplify_and_add (tem, loops_seq_p);
10114 :
10115 : /* Make a copy of the iterator with extra info at the end. */
10116 146 : int elem_count = TREE_VEC_LENGTH (OMP_CLAUSE_ITERATORS (c));
10117 146 : tree new_iterator = copy_omp_iterator (OMP_CLAUSE_ITERATORS (c),
10118 : elem_count + 3);
10119 146 : TREE_VEC_ELT (new_iterator, elem_count) = loop.body_label;
10120 146 : TREE_VEC_ELT (new_iterator, elem_count + 1) = elems;
10121 146 : TREE_VEC_ELT (new_iterator, elem_count + 2) = loop.index;
10122 146 : TREE_CHAIN (new_iterator) = TREE_CHAIN (OMP_CLAUSE_ITERATORS (c));
10123 146 : OMP_CLAUSE_ITERATORS (c) = new_iterator;
10124 :
10125 146 : loop.clauses.safe_push (c);
10126 : }
10127 :
10128 : /* Now gimplify and add all the loops that were built. */
10129 27641 : for (hash_map<tree, iterator_loop_info_t>::iterator it = loops.begin ();
10130 55282 : it != loops.end (); ++it)
10131 74 : gimplify_and_add ((*it).second.bind, loops_seq_p);
10132 27567 : }
10133 :
10134 : /* Helper function for enter_omp_iterator_loop_context. */
10135 :
10136 : static gimple_seq *
10137 1651 : enter_omp_iterator_loop_context_1 (tree iterator, gimple_seq *loops_seq_p)
10138 : {
10139 : /* Drill into the nested bind expressions to get to the loop body. */
10140 1651 : for (gimple_stmt_iterator gsi = gsi_start (*loops_seq_p);
10141 10250 : !gsi_end_p (gsi); gsi_next (&gsi))
10142 : {
10143 9829 : gimple *stmt = gsi_stmt (gsi);
10144 :
10145 9829 : switch (gimple_code (stmt))
10146 : {
10147 1301 : case GIMPLE_BIND:
10148 1301 : {
10149 1301 : gbind *bind_stmt = as_a<gbind *> (stmt);
10150 1301 : gimple_push_bind_expr (bind_stmt);
10151 1301 : gimple_seq *bind_body_p = gimple_bind_body_ptr (bind_stmt);
10152 1301 : gimple_seq *seq =
10153 1301 : enter_omp_iterator_loop_context_1 (iterator, bind_body_p);
10154 1301 : if (seq)
10155 : return seq;
10156 421 : gimple_pop_bind_expr ();
10157 : }
10158 421 : break;
10159 0 : case GIMPLE_TRY:
10160 0 : {
10161 0 : gimple_seq *try_eval_p = gimple_try_eval_ptr (stmt);
10162 0 : gimple_seq *seq =
10163 0 : enter_omp_iterator_loop_context_1 (iterator, try_eval_p);
10164 0 : if (seq)
10165 : return seq;
10166 : }
10167 : break;
10168 1833 : case GIMPLE_LABEL:
10169 1833 : {
10170 1833 : glabel *label_stmt = as_a<glabel *> (stmt);
10171 1833 : tree label = gimple_label_label (label_stmt);
10172 1833 : if (label == TREE_VEC_ELT (iterator, 6))
10173 : return loops_seq_p;
10174 : }
10175 : break;
10176 : default:
10177 : break;
10178 : }
10179 : }
10180 :
10181 : return NULL;
10182 : }
10183 :
10184 : /* Enter the Gimplification context in LOOPS_SEQ_P for the iterator loop
10185 : associated with OpenMP clause C. Returns the gimple_seq for the loop body
10186 : if C has OpenMP iterators, or ALT_SEQ_P if not. */
10187 :
10188 : static gimple_seq *
10189 64556 : enter_omp_iterator_loop_context (tree c, gimple_seq *loops_seq_p,
10190 : gimple_seq *alt_seq_p)
10191 : {
10192 64556 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10193 : return alt_seq_p;
10194 :
10195 350 : push_gimplify_context ();
10196 :
10197 350 : gimple_seq *seq = enter_omp_iterator_loop_context_1 (OMP_CLAUSE_ITERATORS (c),
10198 : loops_seq_p);
10199 350 : gcc_assert (seq);
10200 : return seq;
10201 : }
10202 :
10203 : /* Enter the Gimplification context in STMT for the iterator loop associated
10204 : with OpenMP clause C. Returns the gimple_seq for the loop body if C has
10205 : OpenMP iterators, or ALT_SEQ_P if not. */
10206 :
10207 : gimple_seq *
10208 204 : enter_omp_iterator_loop_context (tree c, gomp_target *stmt,
10209 : gimple_seq *alt_seq_p)
10210 : {
10211 204 : gimple_seq *loops_seq_p = gimple_omp_target_iterator_loops_ptr (stmt);
10212 204 : return enter_omp_iterator_loop_context (c, loops_seq_p, alt_seq_p);
10213 : }
10214 :
10215 : /* Exit the Gimplification context for the OpenMP clause C. */
10216 :
10217 : void
10218 64646 : exit_omp_iterator_loop_context (tree c)
10219 : {
10220 64646 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10221 : return;
10222 1230 : while (!gimplify_ctxp->bind_expr_stack.is_empty ())
10223 880 : gimple_pop_bind_expr ();
10224 350 : pop_gimplify_context (NULL);
10225 : }
10226 :
10227 : /* If *LIST_P contains any OpenMP depend clauses with iterators,
10228 : lower all the depend clauses by populating corresponding depend
10229 : array. Returns 0 if there are no such depend clauses, or
10230 : 2 if all depend clauses should be removed, 1 otherwise. */
10231 :
10232 : static int
10233 1903 : gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
10234 : {
10235 1903 : tree c;
10236 1903 : gimple *g;
10237 1903 : size_t n[5] = { 0, 0, 0, 0, 0 };
10238 1903 : bool unused[5];
10239 1903 : tree counts[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
10240 1903 : tree last_iter = NULL_TREE, last_count = NULL_TREE;
10241 1903 : size_t i, j;
10242 1903 : location_t first_loc = UNKNOWN_LOCATION;
10243 :
10244 6246 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10245 4343 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10246 : {
10247 2205 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10248 : {
10249 : case OMP_CLAUSE_DEPEND_IN:
10250 : i = 2;
10251 : break;
10252 : case OMP_CLAUSE_DEPEND_OUT:
10253 : case OMP_CLAUSE_DEPEND_INOUT:
10254 : i = 0;
10255 : break;
10256 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10257 : i = 1;
10258 : break;
10259 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10260 : i = 3;
10261 : break;
10262 : case OMP_CLAUSE_DEPEND_INOUTSET:
10263 : i = 4;
10264 : break;
10265 0 : default:
10266 0 : gcc_unreachable ();
10267 : }
10268 2205 : tree t = OMP_CLAUSE_DECL (c);
10269 2205 : if (first_loc == UNKNOWN_LOCATION)
10270 1903 : first_loc = OMP_CLAUSE_LOCATION (c);
10271 2205 : if (OMP_ITERATOR_DECL_P (t))
10272 : {
10273 301 : if (TREE_PURPOSE (t) != last_iter)
10274 : {
10275 254 : tree tcnt = compute_omp_iterator_count (TREE_PURPOSE (t),
10276 : pre_p);
10277 254 : if (!tcnt)
10278 : return 2;
10279 254 : last_iter = TREE_PURPOSE (t);
10280 254 : last_count = tcnt;
10281 : }
10282 301 : if (counts[i] == NULL_TREE)
10283 247 : counts[i] = last_count;
10284 : else
10285 54 : counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
10286 : PLUS_EXPR, counts[i], last_count);
10287 : }
10288 : else
10289 1904 : n[i]++;
10290 : }
10291 10613 : for (i = 0; i < 5; i++)
10292 8919 : if (counts[i])
10293 : break;
10294 1903 : if (i == 5)
10295 : return 0;
10296 :
10297 209 : tree total = size_zero_node;
10298 1254 : for (i = 0; i < 5; i++)
10299 : {
10300 1045 : unused[i] = counts[i] == NULL_TREE && n[i] == 0;
10301 1045 : if (counts[i] == NULL_TREE)
10302 798 : counts[i] = size_zero_node;
10303 1045 : if (n[i])
10304 44 : counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
10305 1045 : if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
10306 : fb_rvalue) == GS_ERROR)
10307 : return 2;
10308 1045 : total = size_binop (PLUS_EXPR, total, counts[i]);
10309 : }
10310 :
10311 209 : if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
10312 : == GS_ERROR)
10313 : return 2;
10314 209 : bool is_old = unused[1] && unused[3] && unused[4];
10315 209 : tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
10316 : size_int (is_old ? 1 : 4));
10317 209 : if (!unused[4])
10318 3 : totalpx = size_binop (PLUS_EXPR, totalpx,
10319 : size_binop (MULT_EXPR, counts[4], size_int (2)));
10320 209 : tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
10321 209 : tree array = create_tmp_var_raw (type);
10322 209 : TREE_ADDRESSABLE (array) = 1;
10323 209 : if (!poly_int_tree_p (totalpx))
10324 : {
10325 82 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
10326 82 : gimplify_type_sizes (TREE_TYPE (array), pre_p);
10327 82 : if (gimplify_omp_ctxp)
10328 : {
10329 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
10330 : while (ctx
10331 21 : && (ctx->region_type == ORT_WORKSHARE
10332 : || ctx->region_type == ORT_TASKGROUP
10333 21 : || ctx->region_type == ORT_SIMD
10334 21 : || ctx->region_type == ORT_ACC))
10335 0 : ctx = ctx->outer_context;
10336 21 : if (ctx)
10337 21 : omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
10338 : }
10339 82 : gimplify_vla_decl (array, pre_p);
10340 : }
10341 : else
10342 127 : gimple_add_tmp_var (array);
10343 209 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
10344 : NULL_TREE);
10345 209 : tree tem;
10346 209 : if (!is_old)
10347 : {
10348 31 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10349 : build_int_cst (ptr_type_node, 0));
10350 31 : gimplify_and_add (tem, pre_p);
10351 31 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
10352 : NULL_TREE);
10353 : }
10354 209 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10355 : fold_convert (ptr_type_node, total));
10356 209 : gimplify_and_add (tem, pre_p);
10357 813 : for (i = 1; i < (is_old ? 2 : 4); i++)
10358 : {
10359 271 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
10360 : NULL_TREE, NULL_TREE);
10361 271 : tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
10362 271 : gimplify_and_add (tem, pre_p);
10363 : }
10364 :
10365 : tree cnts[6];
10366 735 : for (j = 5; j; j--)
10367 735 : if (!unused[j - 1])
10368 : break;
10369 1254 : for (i = 0; i < 5; i++)
10370 : {
10371 1045 : if (i && (i >= j || unused[i - 1]))
10372 : {
10373 786 : cnts[i] = cnts[i - 1];
10374 786 : continue;
10375 : }
10376 259 : cnts[i] = create_tmp_var (sizetype);
10377 259 : if (i == 0)
10378 240 : g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
10379 : else
10380 : {
10381 50 : tree t;
10382 50 : if (is_old)
10383 38 : t = size_binop (PLUS_EXPR, counts[0], size_int (2));
10384 : else
10385 12 : t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
10386 50 : if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
10387 : == GS_ERROR)
10388 0 : return 2;
10389 50 : g = gimple_build_assign (cnts[i], t);
10390 : }
10391 259 : gimple_seq_add_stmt (pre_p, g);
10392 : }
10393 209 : if (unused[4])
10394 206 : cnts[5] = NULL_TREE;
10395 : else
10396 : {
10397 3 : tree t = size_binop (PLUS_EXPR, total, size_int (5));
10398 3 : cnts[5] = create_tmp_var (sizetype);
10399 3 : g = gimple_build_assign (cnts[i], t);
10400 3 : gimple_seq_add_stmt (pre_p, g);
10401 : }
10402 :
10403 209 : last_iter = NULL_TREE;
10404 209 : tree last_bind = NULL_TREE;
10405 209 : tree *last_body = NULL;
10406 571 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10407 362 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10408 : {
10409 347 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10410 : {
10411 : case OMP_CLAUSE_DEPEND_IN:
10412 : i = 2;
10413 : break;
10414 : case OMP_CLAUSE_DEPEND_OUT:
10415 : case OMP_CLAUSE_DEPEND_INOUT:
10416 : i = 0;
10417 : break;
10418 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10419 : i = 1;
10420 : break;
10421 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10422 : i = 3;
10423 : break;
10424 : case OMP_CLAUSE_DEPEND_INOUTSET:
10425 : i = 4;
10426 : break;
10427 0 : default:
10428 0 : gcc_unreachable ();
10429 : }
10430 347 : tree t = OMP_CLAUSE_DECL (c);
10431 347 : if (OMP_ITERATOR_DECL_P (t))
10432 : {
10433 301 : if (TREE_PURPOSE (t) != last_iter)
10434 : {
10435 254 : last_body = build_omp_iterator_loop (TREE_PURPOSE (t), pre_p,
10436 : &last_bind);
10437 254 : SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
10438 : }
10439 301 : last_iter = TREE_PURPOSE (t);
10440 301 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
10441 : {
10442 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
10443 : 0), last_body);
10444 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
10445 : }
10446 301 : if (error_operand_p (TREE_VALUE (t)))
10447 : return 2;
10448 301 : if (TREE_VALUE (t) != null_pointer_node)
10449 295 : TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
10450 301 : if (i == 4)
10451 : {
10452 3 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10453 : NULL_TREE, NULL_TREE);
10454 3 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10455 : NULL_TREE, NULL_TREE);
10456 3 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10457 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10458 : void_type_node, r, r2);
10459 3 : append_to_statement_list_force (tem, last_body);
10460 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10461 : void_type_node, cnts[i],
10462 : size_binop (PLUS_EXPR, cnts[i],
10463 : size_int (1)));
10464 3 : append_to_statement_list_force (tem, last_body);
10465 3 : i = 5;
10466 : }
10467 301 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10468 : NULL_TREE, NULL_TREE);
10469 602 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10470 301 : void_type_node, r, TREE_VALUE (t));
10471 301 : append_to_statement_list_force (tem, last_body);
10472 301 : if (i == 5)
10473 : {
10474 3 : r = build4 (ARRAY_REF, ptr_type_node, array,
10475 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10476 : NULL_TREE, NULL_TREE);
10477 3 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10478 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10479 : void_type_node, r, tem);
10480 3 : append_to_statement_list_force (tem, last_body);
10481 : }
10482 301 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10483 : void_type_node, cnts[i],
10484 301 : size_binop (PLUS_EXPR, cnts[i],
10485 : size_int (1 + (i == 5))));
10486 301 : append_to_statement_list_force (tem, last_body);
10487 301 : TREE_VALUE (t) = null_pointer_node;
10488 : }
10489 : else
10490 : {
10491 46 : if (last_bind)
10492 : {
10493 18 : gimplify_and_add (last_bind, pre_p);
10494 18 : last_bind = NULL_TREE;
10495 : }
10496 46 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
10497 : {
10498 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
10499 : NULL, is_gimple_val, fb_rvalue);
10500 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
10501 : }
10502 46 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
10503 : return 2;
10504 46 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
10505 46 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
10506 46 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
10507 : is_gimple_val, fb_rvalue) == GS_ERROR)
10508 : return 2;
10509 46 : if (i == 4)
10510 : {
10511 0 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10512 : NULL_TREE, NULL_TREE);
10513 0 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10514 : NULL_TREE, NULL_TREE);
10515 0 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10516 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, r2);
10517 0 : gimplify_and_add (tem, pre_p);
10518 0 : g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR,
10519 : cnts[i],
10520 : size_int (1)));
10521 0 : gimple_seq_add_stmt (pre_p, g);
10522 0 : i = 5;
10523 : }
10524 46 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10525 : NULL_TREE, NULL_TREE);
10526 46 : tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
10527 46 : gimplify_and_add (tem, pre_p);
10528 46 : if (i == 5)
10529 : {
10530 0 : r = build4 (ARRAY_REF, ptr_type_node, array,
10531 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10532 : NULL_TREE, NULL_TREE);
10533 0 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10534 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, tem);
10535 0 : append_to_statement_list_force (tem, last_body);
10536 0 : gimplify_and_add (tem, pre_p);
10537 : }
10538 46 : g = gimple_build_assign (cnts[i],
10539 46 : size_binop (PLUS_EXPR, cnts[i],
10540 : size_int (1 + (i == 5))));
10541 46 : gimple_seq_add_stmt (pre_p, g);
10542 : }
10543 : }
10544 209 : if (last_bind)
10545 205 : gimplify_and_add (last_bind, pre_p);
10546 209 : tree cond = boolean_false_node;
10547 209 : if (is_old)
10548 : {
10549 178 : if (!unused[0])
10550 91 : cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
10551 : size_binop_loc (first_loc, PLUS_EXPR, counts[0],
10552 : size_int (2)));
10553 178 : if (!unused[2])
10554 125 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10555 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10556 : cnts[2],
10557 : size_binop_loc (first_loc, PLUS_EXPR,
10558 : totalpx,
10559 : size_int (1))));
10560 : }
10561 : else
10562 : {
10563 31 : tree prev = size_int (5);
10564 186 : for (i = 0; i < 5; i++)
10565 : {
10566 155 : if (unused[i])
10567 112 : continue;
10568 43 : prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
10569 43 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10570 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10571 : cnts[i], unshare_expr (prev)));
10572 : }
10573 : }
10574 209 : tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
10575 : build_call_expr_loc (first_loc,
10576 : builtin_decl_explicit (BUILT_IN_TRAP),
10577 : 0), void_node);
10578 209 : gimplify_and_add (tem, pre_p);
10579 209 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10580 209 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
10581 209 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10582 209 : OMP_CLAUSE_CHAIN (c) = *list_p;
10583 209 : *list_p = c;
10584 209 : return 1;
10585 : }
10586 :
10587 : /* True if mapping node C maps, or unmaps, a (Fortran) array descriptor. */
10588 :
10589 : static bool
10590 125198 : omp_map_clause_descriptor_p (tree c)
10591 : {
10592 125198 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
10593 : return false;
10594 :
10595 125194 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)
10596 : return true;
10597 :
10598 82318 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
10599 74280 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE)
10600 82800 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (c))
10601 6135 : return true;
10602 :
10603 : return false;
10604 : }
10605 :
10606 : /* For a set of mappings describing an array section pointed to by a struct
10607 : (or derived type, etc.) component, create an "alloc" or "release" node to
10608 : insert into a list following a GOMP_MAP_STRUCT node. For some types of
10609 : mapping (e.g. Fortran arrays with descriptors), an additional mapping may
10610 : be created that is inserted into the list of mapping nodes attached to the
10611 : directive being processed -- not part of the sorted list of nodes after
10612 : GOMP_MAP_STRUCT.
10613 :
10614 : CODE is the code of the directive being processed. GRP_START and GRP_END
10615 : are the first and last of two or three nodes representing this array section
10616 : mapping (e.g. a data movement node like GOMP_MAP_{TO,FROM}, optionally a
10617 : GOMP_MAP_TO_PSET, and finally a GOMP_MAP_ALWAYS_POINTER). EXTRA_NODE is
10618 : filled with the additional node described above, if needed.
10619 :
10620 : This function does not add the new nodes to any lists itself. It is the
10621 : responsibility of the caller to do that. */
10622 :
10623 : static tree
10624 1729 : build_omp_struct_comp_nodes (enum tree_code code, tree grp_start, tree grp_end,
10625 : tree *extra_node)
10626 : {
10627 1524 : enum gomp_map_kind mkind
10628 1729 : = (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
10629 1729 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
10630 :
10631 1729 : gcc_assert (grp_start != grp_end);
10632 :
10633 1729 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10634 1729 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
10635 1729 : OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (grp_end));
10636 1729 : OMP_CLAUSE_CHAIN (c2) = NULL_TREE;
10637 1729 : tree grp_mid = NULL_TREE;
10638 1729 : if (OMP_CLAUSE_CHAIN (grp_start) != grp_end)
10639 197 : grp_mid = OMP_CLAUSE_CHAIN (grp_start);
10640 :
10641 197 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
10642 0 : OMP_CLAUSE_SIZE (c2) = OMP_CLAUSE_SIZE (grp_mid);
10643 : else
10644 1729 : OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node);
10645 :
10646 1729 : if (grp_mid
10647 197 : && OMP_CLAUSE_CODE (grp_mid) == OMP_CLAUSE_MAP
10648 1926 : && OMP_CLAUSE_MAP_KIND (grp_mid) == GOMP_MAP_ALWAYS_POINTER)
10649 : {
10650 0 : tree c3
10651 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10652 0 : OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
10653 0 : OMP_CLAUSE_DECL (c3) = unshare_expr (OMP_CLAUSE_DECL (grp_mid));
10654 0 : OMP_CLAUSE_SIZE (c3) = TYPE_SIZE_UNIT (ptr_type_node);
10655 0 : OMP_CLAUSE_CHAIN (c3) = NULL_TREE;
10656 :
10657 0 : *extra_node = c3;
10658 : }
10659 : else
10660 1729 : *extra_node = NULL_TREE;
10661 :
10662 1729 : return c2;
10663 : }
10664 :
10665 : /* Strip ARRAY_REFS or an indirect ref off BASE, find the containing object,
10666 : and set *BITPOSP and *POFFSETP to the bit offset of the access.
10667 : If BASE_REF is non-NULL and the containing object is a reference, set
10668 : *BASE_REF to that reference before dereferencing the object.
10669 : If BASE_REF is NULL, check that the containing object is a COMPONENT_REF or
10670 : has array type, else return NULL. */
10671 :
10672 : static tree
10673 7705 : extract_base_bit_offset (tree base, poly_int64 *bitposp,
10674 : poly_offset_int *poffsetp,
10675 : bool *variable_offset)
10676 : {
10677 7705 : tree offset;
10678 7705 : poly_int64 bitsize, bitpos;
10679 7705 : machine_mode mode;
10680 7705 : int unsignedp, reversep, volatilep = 0;
10681 7705 : poly_offset_int poffset;
10682 :
10683 7705 : STRIP_NOPS (base);
10684 :
10685 7705 : base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
10686 : &unsignedp, &reversep, &volatilep);
10687 :
10688 7705 : STRIP_NOPS (base);
10689 :
10690 7705 : if (offset && poly_int_tree_p (offset))
10691 : {
10692 0 : poffset = wi::to_poly_offset (offset);
10693 0 : *variable_offset = false;
10694 : }
10695 : else
10696 : {
10697 7705 : poffset = 0;
10698 7705 : *variable_offset = (offset != NULL_TREE);
10699 : }
10700 :
10701 7705 : if (maybe_ne (bitpos, 0))
10702 5627 : poffset += bits_to_bytes_round_down (bitpos);
10703 :
10704 7705 : *bitposp = bitpos;
10705 7705 : *poffsetp = poffset;
10706 :
10707 7705 : return base;
10708 : }
10709 :
10710 : /* Used for topological sorting of mapping groups. UNVISITED means we haven't
10711 : started processing the group yet. The TEMPORARY mark is used when we first
10712 : encounter a group on a depth-first traversal, and the PERMANENT mark is used
10713 : when we have processed all the group's children (i.e. all the base pointers
10714 : referred to by the group's mapping nodes, recursively). */
10715 :
10716 : enum omp_tsort_mark {
10717 : UNVISITED,
10718 : TEMPORARY,
10719 : PERMANENT
10720 : };
10721 :
10722 : /* Hash for trees based on operand_equal_p. Like tree_operand_hash
10723 : but ignores side effects in the equality comparisons. */
10724 :
10725 : struct tree_operand_hash_no_se : tree_operand_hash
10726 : {
10727 : static inline bool equal (const value_type &,
10728 : const compare_type &);
10729 : };
10730 :
10731 : inline bool
10732 402156 : tree_operand_hash_no_se::equal (const value_type &t1,
10733 : const compare_type &t2)
10734 : {
10735 402156 : return operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS);
10736 : }
10737 :
10738 : /* A group of OMP_CLAUSE_MAP nodes that correspond to a single "map"
10739 : clause. */
10740 :
10741 : struct omp_mapping_group {
10742 : tree *grp_start;
10743 : tree grp_end;
10744 : omp_tsort_mark mark;
10745 : /* If we've removed the group but need to reindex, mark the group as
10746 : deleted. */
10747 : bool deleted;
10748 : /* The group points to an already-created "GOMP_MAP_STRUCT
10749 : GOMP_MAP_ATTACH_DETACH" pair. */
10750 : bool reprocess_struct;
10751 : /* The group should use "zero-length" allocations for pointers that are not
10752 : mapped "to" on the same directive. */
10753 : bool fragile;
10754 : struct omp_mapping_group *sibling;
10755 : struct omp_mapping_group *next;
10756 : };
10757 :
10758 : DEBUG_FUNCTION void
10759 0 : debug_mapping_group (omp_mapping_group *grp)
10760 : {
10761 0 : tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end);
10762 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = NULL;
10763 0 : debug_generic_expr (*grp->grp_start);
10764 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = tmp;
10765 0 : }
10766 :
10767 : /* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there
10768 : isn't one. */
10769 :
10770 : static tree
10771 36092 : omp_get_base_pointer (tree expr)
10772 : {
10773 36092 : while (TREE_CODE (expr) == ARRAY_REF
10774 43227 : || TREE_CODE (expr) == COMPONENT_REF)
10775 7135 : expr = TREE_OPERAND (expr, 0);
10776 :
10777 36092 : if (INDIRECT_REF_P (expr)
10778 36092 : || (TREE_CODE (expr) == MEM_REF
10779 0 : && integer_zerop (TREE_OPERAND (expr, 1))))
10780 : {
10781 10546 : expr = TREE_OPERAND (expr, 0);
10782 10583 : while (TREE_CODE (expr) == COMPOUND_EXPR)
10783 37 : expr = TREE_OPERAND (expr, 1);
10784 10546 : if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
10785 841 : expr = TREE_OPERAND (expr, 0);
10786 10546 : if (TREE_CODE (expr) == SAVE_EXPR)
10787 31 : expr = TREE_OPERAND (expr, 0);
10788 10546 : STRIP_NOPS (expr);
10789 10546 : return expr;
10790 : }
10791 :
10792 : return NULL_TREE;
10793 : }
10794 :
10795 : /* An attach or detach operation depends directly on the address being
10796 : attached/detached. Return that address, or none if there are no
10797 : attachments/detachments. */
10798 :
10799 : static tree
10800 16680 : omp_get_attachment (omp_mapping_group *grp)
10801 : {
10802 16680 : tree node = *grp->grp_start;
10803 :
10804 16680 : switch (OMP_CLAUSE_MAP_KIND (node))
10805 : {
10806 13760 : case GOMP_MAP_TO:
10807 13760 : case GOMP_MAP_FROM:
10808 13760 : case GOMP_MAP_TOFROM:
10809 13760 : case GOMP_MAP_ALWAYS_FROM:
10810 13760 : case GOMP_MAP_ALWAYS_TO:
10811 13760 : case GOMP_MAP_ALWAYS_TOFROM:
10812 13760 : case GOMP_MAP_FORCE_FROM:
10813 13760 : case GOMP_MAP_FORCE_TO:
10814 13760 : case GOMP_MAP_FORCE_TOFROM:
10815 13760 : case GOMP_MAP_FORCE_PRESENT:
10816 13760 : case GOMP_MAP_PRESENT_ALLOC:
10817 13760 : case GOMP_MAP_PRESENT_FROM:
10818 13760 : case GOMP_MAP_PRESENT_TO:
10819 13760 : case GOMP_MAP_PRESENT_TOFROM:
10820 13760 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
10821 13760 : case GOMP_MAP_ALWAYS_PRESENT_TO:
10822 13760 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
10823 13760 : case GOMP_MAP_ALLOC:
10824 13760 : case GOMP_MAP_RELEASE:
10825 13760 : case GOMP_MAP_DELETE:
10826 13760 : case GOMP_MAP_FORCE_ALLOC:
10827 13760 : if (node == grp->grp_end)
10828 : return NULL_TREE;
10829 :
10830 6575 : node = OMP_CLAUSE_CHAIN (node);
10831 6575 : if (node && omp_map_clause_descriptor_p (node))
10832 : {
10833 1037 : gcc_assert (node != grp->grp_end);
10834 1037 : node = OMP_CLAUSE_CHAIN (node);
10835 : }
10836 6575 : if (node)
10837 6575 : switch (OMP_CLAUSE_MAP_KIND (node))
10838 : {
10839 : case GOMP_MAP_POINTER:
10840 : case GOMP_MAP_ALWAYS_POINTER:
10841 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
10842 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
10843 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
10844 : return NULL_TREE;
10845 :
10846 2521 : case GOMP_MAP_ATTACH_DETACH:
10847 2521 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10848 2521 : case GOMP_MAP_DETACH:
10849 2521 : return OMP_CLAUSE_DECL (node);
10850 :
10851 0 : default:
10852 0 : internal_error ("unexpected mapping node");
10853 : }
10854 0 : return error_mark_node;
10855 :
10856 0 : case GOMP_MAP_TO_PSET:
10857 0 : gcc_assert (node != grp->grp_end);
10858 0 : node = OMP_CLAUSE_CHAIN (node);
10859 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
10860 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
10861 0 : return OMP_CLAUSE_DECL (node);
10862 : else
10863 0 : internal_error ("unexpected mapping node");
10864 : return error_mark_node;
10865 :
10866 537 : case GOMP_MAP_ATTACH:
10867 537 : case GOMP_MAP_DETACH:
10868 537 : node = OMP_CLAUSE_CHAIN (node);
10869 537 : if (!node || *grp->grp_start == grp->grp_end)
10870 537 : return OMP_CLAUSE_DECL (*grp->grp_start);
10871 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
10872 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
10873 0 : return OMP_CLAUSE_DECL (*grp->grp_start);
10874 : else
10875 0 : internal_error ("unexpected mapping node");
10876 : return error_mark_node;
10877 :
10878 : case GOMP_MAP_STRUCT:
10879 : case GOMP_MAP_STRUCT_UNORD:
10880 : case GOMP_MAP_FORCE_DEVICEPTR:
10881 : case GOMP_MAP_DEVICE_RESIDENT:
10882 : case GOMP_MAP_LINK:
10883 : case GOMP_MAP_IF_PRESENT:
10884 : case GOMP_MAP_FIRSTPRIVATE:
10885 : case GOMP_MAP_FIRSTPRIVATE_INT:
10886 : case GOMP_MAP_USE_DEVICE_PTR:
10887 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10888 : return NULL_TREE;
10889 :
10890 0 : default:
10891 0 : internal_error ("unexpected mapping node");
10892 : }
10893 :
10894 : return error_mark_node;
10895 : }
10896 :
10897 : /* Given a pointer START_P to the start of a group of related (e.g. pointer)
10898 : mappings, return the chain pointer to the end of that group in the list. */
10899 :
10900 : static tree *
10901 110706 : omp_group_last (tree *start_p)
10902 : {
10903 110706 : tree c = *start_p, nc, *grp_last_p = start_p;
10904 :
10905 110706 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
10906 :
10907 110706 : nc = OMP_CLAUSE_CHAIN (c);
10908 :
10909 193326 : if (!nc || OMP_CLAUSE_CODE (nc) != OMP_CLAUSE_MAP)
10910 : return grp_last_p;
10911 :
10912 70411 : switch (OMP_CLAUSE_MAP_KIND (c))
10913 : {
10914 : default:
10915 : while (nc
10916 113211 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
10917 237763 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
10918 106033 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
10919 95460 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH
10920 82778 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
10921 56702 : || (OMP_CLAUSE_MAP_KIND (nc)
10922 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
10923 56686 : || (OMP_CLAUSE_MAP_KIND (nc)
10924 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)
10925 56319 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH
10926 56264 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER
10927 54352 : || omp_map_clause_descriptor_p (nc)))
10928 : {
10929 66712 : tree nc2 = OMP_CLAUSE_CHAIN (nc);
10930 66712 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH)
10931 : {
10932 : /* In the specific case we're doing "exit data" on an array
10933 : slice of a reference-to-pointer struct component, we will see
10934 : DETACH followed by ATTACH_DETACH here. We want to treat that
10935 : as a single group. In other cases DETACH might represent a
10936 : stand-alone "detach" clause, so we don't want to consider
10937 : that part of the group. */
10938 55 : if (nc2
10939 16 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
10940 71 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH)
10941 0 : goto consume_two_nodes;
10942 : else
10943 : break;
10944 : }
10945 66657 : if (nc2
10946 48807 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
10947 42294 : && (OMP_CLAUSE_MAP_KIND (nc)
10948 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
10949 66673 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH)
10950 : {
10951 16 : consume_two_nodes:
10952 16 : grp_last_p = &OMP_CLAUSE_CHAIN (nc);
10953 16 : c = nc2;
10954 16 : nc = OMP_CLAUSE_CHAIN (nc2);
10955 : }
10956 : else
10957 : {
10958 66641 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
10959 66641 : c = nc;
10960 66641 : nc = nc2;
10961 : }
10962 : }
10963 : break;
10964 :
10965 302 : case GOMP_MAP_ATTACH:
10966 302 : case GOMP_MAP_DETACH:
10967 : /* This is a weird artifact of how directives are parsed: bare attach or
10968 : detach clauses get a subsequent (meaningless) FIRSTPRIVATE_POINTER or
10969 : FIRSTPRIVATE_REFERENCE node. FIXME. */
10970 302 : if (nc
10971 302 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
10972 302 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
10973 302 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER))
10974 0 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
10975 : break;
10976 :
10977 39 : case GOMP_MAP_TO_PSET:
10978 39 : if (OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
10979 39 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH
10980 12 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH))
10981 39 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
10982 : break;
10983 :
10984 5662 : case GOMP_MAP_STRUCT:
10985 5662 : case GOMP_MAP_STRUCT_UNORD:
10986 5662 : {
10987 5662 : unsigned HOST_WIDE_INT num_mappings
10988 5662 : = tree_to_uhwi (OMP_CLAUSE_SIZE (c));
10989 5662 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
10990 5324 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
10991 10504 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH)
10992 1134 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
10993 14267 : for (unsigned i = 0; i < num_mappings; i++)
10994 8605 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
10995 : }
10996 : break;
10997 : }
10998 :
10999 : return grp_last_p;
11000 : }
11001 :
11002 : /* Walk through LIST_P, and return a list of groups of mappings found (e.g.
11003 : OMP_CLAUSE_MAP with GOMP_MAP_{TO/FROM/TOFROM} followed by one or two
11004 : associated GOMP_MAP_POINTER mappings). Return a vector of omp_mapping_group
11005 : if we have more than one such group, else return NULL. */
11006 :
11007 : static void
11008 89401 : omp_gather_mapping_groups_1 (tree *list_p, vec<omp_mapping_group> *groups,
11009 : tree gather_sentinel)
11010 : {
11011 89401 : for (tree *cp = list_p;
11012 266823 : *cp && *cp != gather_sentinel;
11013 177422 : cp = &OMP_CLAUSE_CHAIN (*cp))
11014 : {
11015 177422 : if (OMP_CLAUSE_CODE (*cp) != OMP_CLAUSE_MAP)
11016 98301 : continue;
11017 :
11018 79121 : tree *grp_last_p = omp_group_last (cp);
11019 79121 : omp_mapping_group grp;
11020 :
11021 79121 : grp.grp_start = cp;
11022 79121 : grp.grp_end = *grp_last_p;
11023 79121 : grp.mark = UNVISITED;
11024 79121 : grp.sibling = NULL;
11025 79121 : grp.deleted = false;
11026 79121 : grp.reprocess_struct = false;
11027 79121 : grp.fragile = false;
11028 79121 : grp.next = NULL;
11029 79121 : groups->safe_push (grp);
11030 :
11031 79121 : cp = grp_last_p;
11032 : }
11033 89401 : }
11034 :
11035 : static vec<omp_mapping_group> *
11036 89083 : omp_gather_mapping_groups (tree *list_p)
11037 : {
11038 89083 : vec<omp_mapping_group> *groups = new vec<omp_mapping_group> ();
11039 :
11040 89083 : omp_gather_mapping_groups_1 (list_p, groups, NULL_TREE);
11041 :
11042 89083 : if (groups->length () > 0)
11043 : return groups;
11044 : else
11045 : {
11046 44626 : delete groups;
11047 44626 : return NULL;
11048 : }
11049 : }
11050 :
11051 : /* A pointer mapping group GRP may define a block of memory starting at some
11052 : base address, and maybe also define a firstprivate pointer or firstprivate
11053 : reference that points to that block. The return value is a node containing
11054 : the former, and the *FIRSTPRIVATE pointer is set if we have the latter.
11055 : If we define several base pointers, i.e. for a GOMP_MAP_STRUCT mapping,
11056 : return the number of consecutive chained nodes in CHAINED. */
11057 :
11058 : static tree
11059 79515 : omp_group_base (omp_mapping_group *grp, unsigned int *chained,
11060 : tree *firstprivate)
11061 : {
11062 79515 : tree node = *grp->grp_start;
11063 :
11064 79515 : *firstprivate = NULL_TREE;
11065 79515 : *chained = 1;
11066 :
11067 79515 : switch (OMP_CLAUSE_MAP_KIND (node))
11068 : {
11069 75365 : case GOMP_MAP_TO:
11070 75365 : case GOMP_MAP_FROM:
11071 75365 : case GOMP_MAP_TOFROM:
11072 75365 : case GOMP_MAP_ALWAYS_FROM:
11073 75365 : case GOMP_MAP_ALWAYS_TO:
11074 75365 : case GOMP_MAP_ALWAYS_TOFROM:
11075 75365 : case GOMP_MAP_FORCE_FROM:
11076 75365 : case GOMP_MAP_FORCE_TO:
11077 75365 : case GOMP_MAP_FORCE_TOFROM:
11078 75365 : case GOMP_MAP_FORCE_PRESENT:
11079 75365 : case GOMP_MAP_PRESENT_ALLOC:
11080 75365 : case GOMP_MAP_PRESENT_FROM:
11081 75365 : case GOMP_MAP_PRESENT_TO:
11082 75365 : case GOMP_MAP_PRESENT_TOFROM:
11083 75365 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
11084 75365 : case GOMP_MAP_ALWAYS_PRESENT_TO:
11085 75365 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
11086 75365 : case GOMP_MAP_ALLOC:
11087 75365 : case GOMP_MAP_RELEASE:
11088 75365 : case GOMP_MAP_DELETE:
11089 75365 : case GOMP_MAP_FORCE_ALLOC:
11090 75365 : case GOMP_MAP_IF_PRESENT:
11091 75365 : if (node == grp->grp_end)
11092 : return node;
11093 :
11094 34642 : node = OMP_CLAUSE_CHAIN (node);
11095 34642 : if (!node)
11096 0 : internal_error ("unexpected mapping node");
11097 34642 : if (omp_map_clause_descriptor_p (node))
11098 : {
11099 10685 : if (node == grp->grp_end)
11100 0 : return *grp->grp_start;
11101 10685 : node = OMP_CLAUSE_CHAIN (node);
11102 : }
11103 34642 : switch (OMP_CLAUSE_MAP_KIND (node))
11104 : {
11105 23443 : case GOMP_MAP_POINTER:
11106 23443 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11107 23443 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11108 23443 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11109 23443 : *firstprivate = OMP_CLAUSE_DECL (node);
11110 23443 : return *grp->grp_start;
11111 :
11112 11199 : case GOMP_MAP_ALWAYS_POINTER:
11113 11199 : case GOMP_MAP_ATTACH_DETACH:
11114 11199 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11115 11199 : case GOMP_MAP_DETACH:
11116 11199 : return *grp->grp_start;
11117 :
11118 0 : default:
11119 0 : internal_error ("unexpected mapping node");
11120 : }
11121 : return error_mark_node;
11122 :
11123 26 : case GOMP_MAP_TO_PSET:
11124 26 : gcc_assert (node != grp->grp_end);
11125 26 : node = OMP_CLAUSE_CHAIN (node);
11126 26 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
11127 26 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
11128 : return NULL_TREE;
11129 : else
11130 0 : internal_error ("unexpected mapping node");
11131 : return error_mark_node;
11132 :
11133 1097 : case GOMP_MAP_ATTACH:
11134 1097 : case GOMP_MAP_DETACH:
11135 1097 : node = OMP_CLAUSE_CHAIN (node);
11136 1097 : if (!node || *grp->grp_start == grp->grp_end)
11137 : return NULL_TREE;
11138 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11139 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11140 : {
11141 : /* We're mapping the base pointer itself in a bare attach or detach
11142 : node. This is a side effect of how parsing works, and the mapping
11143 : will be removed anyway (at least for enter/exit data directives).
11144 : We should ignore the mapping here. FIXME. */
11145 : return NULL_TREE;
11146 : }
11147 : else
11148 0 : internal_error ("unexpected mapping node");
11149 : return error_mark_node;
11150 :
11151 2743 : case GOMP_MAP_STRUCT:
11152 2743 : case GOMP_MAP_STRUCT_UNORD:
11153 2743 : {
11154 2743 : unsigned HOST_WIDE_INT num_mappings
11155 2743 : = tree_to_uhwi (OMP_CLAUSE_SIZE (node));
11156 2743 : node = OMP_CLAUSE_CHAIN (node);
11157 2743 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11158 2743 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11159 : {
11160 393 : *firstprivate = OMP_CLAUSE_DECL (node);
11161 393 : node = OMP_CLAUSE_CHAIN (node);
11162 : }
11163 2350 : else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH_DETACH)
11164 314 : node = OMP_CLAUSE_CHAIN (node);
11165 2743 : *chained = num_mappings;
11166 2743 : return node;
11167 : }
11168 :
11169 : case GOMP_MAP_FORCE_DEVICEPTR:
11170 : case GOMP_MAP_DEVICE_RESIDENT:
11171 : case GOMP_MAP_LINK:
11172 : case GOMP_MAP_FIRSTPRIVATE:
11173 : case GOMP_MAP_FIRSTPRIVATE_INT:
11174 : case GOMP_MAP_USE_DEVICE_PTR:
11175 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11176 : return NULL_TREE;
11177 :
11178 0 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11179 0 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11180 0 : case GOMP_MAP_POINTER:
11181 0 : case GOMP_MAP_ALWAYS_POINTER:
11182 0 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11183 : /* These shouldn't appear by themselves. */
11184 0 : if (!seen_error ())
11185 0 : internal_error ("unexpected pointer mapping node");
11186 0 : return error_mark_node;
11187 :
11188 0 : default:
11189 0 : gcc_unreachable ();
11190 : }
11191 :
11192 : return error_mark_node;
11193 : }
11194 :
11195 : /* Given a vector of omp_mapping_groups, build a hash table so we can look up
11196 : nodes by tree_operand_hash_no_se. */
11197 :
11198 : static void
11199 44941 : omp_index_mapping_groups_1 (hash_map<tree_operand_hash_no_se,
11200 : omp_mapping_group *> *grpmap,
11201 : vec<omp_mapping_group> *groups,
11202 : tree reindex_sentinel)
11203 : {
11204 44941 : omp_mapping_group *grp;
11205 44941 : unsigned int i;
11206 44941 : bool reindexing = reindex_sentinel != NULL_TREE, above_hwm = false;
11207 :
11208 124910 : FOR_EACH_VEC_ELT (*groups, i, grp)
11209 : {
11210 79969 : if (reindexing && *grp->grp_start == reindex_sentinel)
11211 79969 : above_hwm = true;
11212 :
11213 79969 : if (reindexing && !above_hwm)
11214 56133 : continue;
11215 :
11216 79669 : if (grp->reprocess_struct)
11217 154 : continue;
11218 :
11219 79515 : tree fpp;
11220 79515 : unsigned int chained;
11221 79515 : tree node = omp_group_base (grp, &chained, &fpp);
11222 :
11223 79515 : if (node == error_mark_node || (!node && !fpp))
11224 1407 : continue;
11225 :
11226 : for (unsigned j = 0;
11227 157660 : node && j < chained;
11228 79552 : node = OMP_CLAUSE_CHAIN (node), j++)
11229 : {
11230 79552 : tree decl = OMP_CLAUSE_DECL (node);
11231 : /* Sometimes we see zero-offset MEM_REF instead of INDIRECT_REF,
11232 : meaning node-hash lookups don't work. This is a workaround for
11233 : that, but ideally we should just create the INDIRECT_REF at
11234 : source instead. FIXME. */
11235 79552 : if (TREE_CODE (decl) == MEM_REF
11236 79552 : && integer_zerop (TREE_OPERAND (decl, 1)))
11237 0 : decl = build_fold_indirect_ref (TREE_OPERAND (decl, 0));
11238 :
11239 79552 : omp_mapping_group **prev = grpmap->get (decl);
11240 :
11241 79552 : if (prev && *prev == grp)
11242 : /* Empty. */;
11243 79552 : else if (prev)
11244 : {
11245 : /* Mapping the same thing twice is normally diagnosed as an error,
11246 : but can happen under some circumstances, e.g. in pr99928-16.c,
11247 : the directive:
11248 :
11249 : #pragma omp target simd reduction(+:a[:3]) \
11250 : map(always, tofrom: a[:6])
11251 : ...
11252 :
11253 : will result in two "a[0]" mappings (of different sizes). */
11254 :
11255 326 : grp->sibling = (*prev)->sibling;
11256 326 : (*prev)->sibling = grp;
11257 : }
11258 : else
11259 79226 : grpmap->put (decl, grp);
11260 : }
11261 :
11262 78108 : if (!fpp)
11263 54272 : continue;
11264 :
11265 23836 : omp_mapping_group **prev = grpmap->get (fpp);
11266 23836 : if (prev && *prev != grp)
11267 : {
11268 12 : grp->sibling = (*prev)->sibling;
11269 12 : (*prev)->sibling = grp;
11270 : }
11271 : else
11272 23824 : grpmap->put (fpp, grp);
11273 : }
11274 44941 : }
11275 :
11276 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11277 44457 : omp_index_mapping_groups (vec<omp_mapping_group> *groups)
11278 : {
11279 44457 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11280 44457 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11281 :
11282 44457 : omp_index_mapping_groups_1 (grpmap, groups, NULL_TREE);
11283 :
11284 44457 : return grpmap;
11285 : }
11286 :
11287 : /* Rebuild group map from partially-processed clause list (during
11288 : omp_build_struct_sibling_lists). We have already processed nodes up until
11289 : a high-water mark (HWM). This is a bit tricky because the list is being
11290 : reordered as it is scanned, but we know:
11291 :
11292 : 1. The list after HWM has not been touched yet, so we can reindex it safely.
11293 :
11294 : 2. The list before and including HWM has been altered, but remains
11295 : well-formed throughout the sibling-list building operation.
11296 :
11297 : so, we can do the reindex operation in two parts, on the processed and
11298 : then the unprocessed halves of the list. */
11299 :
11300 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11301 318 : omp_reindex_mapping_groups (tree *list_p,
11302 : vec<omp_mapping_group> *groups,
11303 : vec<omp_mapping_group> *processed_groups,
11304 : tree sentinel)
11305 : {
11306 318 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11307 318 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11308 :
11309 318 : processed_groups->truncate (0);
11310 :
11311 318 : omp_gather_mapping_groups_1 (list_p, processed_groups, sentinel);
11312 318 : omp_index_mapping_groups_1 (grpmap, processed_groups, NULL_TREE);
11313 318 : if (sentinel)
11314 166 : omp_index_mapping_groups_1 (grpmap, groups, sentinel);
11315 :
11316 318 : return grpmap;
11317 : }
11318 :
11319 : /* Find the immediately-containing struct for a component ref (etc.)
11320 : expression EXPR. */
11321 :
11322 : static tree
11323 47389 : omp_containing_struct (tree expr)
11324 : {
11325 47389 : tree expr0 = expr;
11326 :
11327 47389 : STRIP_NOPS (expr);
11328 :
11329 : /* Note: don't strip NOPs unless we're also stripping off array refs or a
11330 : component ref. */
11331 47389 : if (TREE_CODE (expr) != ARRAY_REF && TREE_CODE (expr) != COMPONENT_REF)
11332 : return expr0;
11333 :
11334 26695 : while (TREE_CODE (expr) == ARRAY_REF)
11335 3544 : expr = TREE_OPERAND (expr, 0);
11336 :
11337 23151 : if (TREE_CODE (expr) == COMPONENT_REF)
11338 20828 : expr = TREE_OPERAND (expr, 0);
11339 :
11340 : return expr;
11341 : }
11342 :
11343 : /* Return TRUE if DECL describes a component that is part of a whole structure
11344 : that is mapped elsewhere in GRPMAP. *MAPPED_BY_GROUP is set to the group
11345 : that maps that structure, if present. */
11346 :
11347 : static bool
11348 25477 : omp_mapped_by_containing_struct (hash_map<tree_operand_hash_no_se,
11349 : omp_mapping_group *> *grpmap,
11350 : tree decl,
11351 : omp_mapping_group **mapped_by_group)
11352 : {
11353 25477 : tree wsdecl = NULL_TREE;
11354 :
11355 25477 : *mapped_by_group = NULL;
11356 :
11357 47389 : while (true)
11358 : {
11359 47389 : wsdecl = omp_containing_struct (decl);
11360 47389 : if (wsdecl == decl)
11361 : break;
11362 23151 : omp_mapping_group **wholestruct = grpmap->get (wsdecl);
11363 23151 : if (!wholestruct
11364 20582 : && TREE_CODE (wsdecl) == MEM_REF
11365 23151 : && integer_zerop (TREE_OPERAND (wsdecl, 1)))
11366 : {
11367 0 : tree deref = TREE_OPERAND (wsdecl, 0);
11368 0 : deref = build_fold_indirect_ref (deref);
11369 0 : wholestruct = grpmap->get (deref);
11370 : }
11371 23151 : if (wholestruct)
11372 : {
11373 : /* An intermediate descriptor should not match here because the
11374 : pointee is actually not mapped by this group -- it is just a
11375 : zero-length alloc. */
11376 2569 : tree desc = OMP_CLAUSE_CHAIN (*(*wholestruct)->grp_start);
11377 2569 : if (desc != NULL_TREE && omp_map_clause_descriptor_p (desc))
11378 1330 : goto next;
11379 1239 : *mapped_by_group = *wholestruct;
11380 1239 : return true;
11381 : }
11382 20582 : next:
11383 : decl = wsdecl;
11384 : }
11385 :
11386 : return false;
11387 : }
11388 :
11389 : /* Helper function for omp_tsort_mapping_groups. Returns TRUE on success, or
11390 : FALSE on error. */
11391 :
11392 : static bool
11393 20016 : omp_tsort_mapping_groups_1 (omp_mapping_group ***outlist,
11394 : vec<omp_mapping_group> *groups,
11395 : hash_map<tree_operand_hash_no_se,
11396 : omp_mapping_group *> *grpmap,
11397 : omp_mapping_group *grp)
11398 : {
11399 20016 : if (grp->mark == PERMANENT)
11400 : return true;
11401 16680 : if (grp->mark == TEMPORARY)
11402 : {
11403 0 : fprintf (stderr, "when processing group:\n");
11404 0 : debug_mapping_group (grp);
11405 0 : internal_error ("base pointer cycle detected");
11406 : return false;
11407 : }
11408 16680 : grp->mark = TEMPORARY;
11409 :
11410 16680 : tree attaches_to = omp_get_attachment (grp);
11411 :
11412 16680 : if (attaches_to)
11413 : {
11414 3058 : omp_mapping_group **basep = grpmap->get (attaches_to);
11415 :
11416 3058 : if (basep && *basep != grp)
11417 : {
11418 2920 : for (omp_mapping_group *w = *basep; w; w = w->sibling)
11419 1460 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11420 : return false;
11421 : }
11422 : }
11423 :
11424 16680 : tree decl = OMP_CLAUSE_DECL (*grp->grp_start);
11425 :
11426 22858 : while (decl)
11427 : {
11428 22858 : tree base = omp_get_base_pointer (decl);
11429 :
11430 22858 : if (!base)
11431 : break;
11432 :
11433 8938 : omp_mapping_group **innerp = grpmap->get (base);
11434 8938 : omp_mapping_group *wholestruct;
11435 :
11436 : /* We should treat whole-structure mappings as if all (pointer, in this
11437 : case) members are mapped as individual list items. Check if we have
11438 : such a whole-structure mapping, if we don't have an explicit reference
11439 : to the pointer member itself. */
11440 8938 : if (!innerp
11441 4129 : && TREE_CODE (base) == COMPONENT_REF
11442 11136 : && omp_mapped_by_containing_struct (grpmap, base, &wholestruct))
11443 : innerp = &wholestruct;
11444 :
11445 8938 : if (innerp && *innerp != grp)
11446 : {
11447 5532 : for (omp_mapping_group *w = *innerp; w; w = w->sibling)
11448 2772 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11449 0 : return false;
11450 : break;
11451 : }
11452 :
11453 6178 : decl = base;
11454 : }
11455 :
11456 16680 : grp->mark = PERMANENT;
11457 :
11458 : /* Emit grp to output list. */
11459 :
11460 16680 : **outlist = grp;
11461 16680 : *outlist = &grp->next;
11462 :
11463 16680 : return true;
11464 : }
11465 :
11466 : /* Topologically sort GROUPS, so that OMP 5.0-defined base pointers come
11467 : before mappings that use those pointers. This is an implementation of the
11468 : depth-first search algorithm, described e.g. at:
11469 :
11470 : https://en.wikipedia.org/wiki/Topological_sorting
11471 : */
11472 :
11473 : static omp_mapping_group *
11474 8444 : omp_tsort_mapping_groups (vec<omp_mapping_group> *groups,
11475 : hash_map<tree_operand_hash_no_se, omp_mapping_group *>
11476 : *grpmap,
11477 : bool enter_exit_data)
11478 : {
11479 8444 : omp_mapping_group *grp, *outlist = NULL, **cursor;
11480 8444 : unsigned int i;
11481 8444 : bool saw_runtime_implicit = false;
11482 :
11483 8444 : cursor = &outlist;
11484 :
11485 25124 : FOR_EACH_VEC_ELT (*groups, i, grp)
11486 : {
11487 16680 : if (grp->mark != PERMANENT)
11488 : {
11489 15808 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11490 : {
11491 683 : saw_runtime_implicit = true;
11492 683 : continue;
11493 : }
11494 15125 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11495 : return NULL;
11496 : }
11497 : }
11498 :
11499 8444 : if (!saw_runtime_implicit)
11500 8162 : return outlist;
11501 :
11502 1634 : FOR_EACH_VEC_ELT (*groups, i, grp)
11503 : {
11504 1352 : if (grp->mark != PERMANENT
11505 1352 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11506 : {
11507 : /* Clear the flag for enter/exit data because it is currently
11508 : meaningless for those operations in libgomp. */
11509 659 : if (enter_exit_data)
11510 446 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start) = 0;
11511 :
11512 659 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11513 : return NULL;
11514 : }
11515 : }
11516 :
11517 282 : return outlist;
11518 : }
11519 :
11520 : /* Split INLIST into three parts:
11521 :
11522 : - "present" alloc/to/from groups
11523 : - other to/from groups
11524 : - other alloc/release/delete groups
11525 :
11526 : These sub-lists are then concatenated together to form the final list.
11527 : Each sub-list retains the order of the original list.
11528 : Note that ATTACH nodes are later moved to the end of the list in
11529 : gimplify_adjust_omp_clauses, for target regions. */
11530 :
11531 : static omp_mapping_group *
11532 8444 : omp_segregate_mapping_groups (omp_mapping_group *inlist)
11533 : {
11534 8444 : omp_mapping_group *ard_groups = NULL, *tf_groups = NULL;
11535 8444 : omp_mapping_group *p_groups = NULL;
11536 8444 : omp_mapping_group **ard_tail = &ard_groups, **tf_tail = &tf_groups;
11537 8444 : omp_mapping_group **p_tail = &p_groups;
11538 :
11539 25124 : for (omp_mapping_group *w = inlist; w;)
11540 : {
11541 16680 : tree c = *w->grp_start;
11542 16680 : omp_mapping_group *next = w->next;
11543 :
11544 16680 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
11545 :
11546 16680 : switch (OMP_CLAUSE_MAP_KIND (c))
11547 : {
11548 1938 : case GOMP_MAP_ALLOC:
11549 1938 : case GOMP_MAP_RELEASE:
11550 1938 : case GOMP_MAP_DELETE:
11551 1938 : *ard_tail = w;
11552 1938 : w->next = NULL;
11553 1938 : ard_tail = &w->next;
11554 1938 : break;
11555 :
11556 : /* These map types are all semantically identical, so are moved into a
11557 : single group. They will each be changed into GOMP_MAP_FORCE_PRESENT
11558 : in gimplify_adjust_omp_clauses. */
11559 149 : case GOMP_MAP_PRESENT_ALLOC:
11560 149 : case GOMP_MAP_PRESENT_FROM:
11561 149 : case GOMP_MAP_PRESENT_TO:
11562 149 : case GOMP_MAP_PRESENT_TOFROM:
11563 149 : *p_tail = w;
11564 149 : w->next = NULL;
11565 149 : p_tail = &w->next;
11566 149 : break;
11567 :
11568 14593 : default:
11569 14593 : *tf_tail = w;
11570 14593 : w->next = NULL;
11571 14593 : tf_tail = &w->next;
11572 : }
11573 :
11574 : w = next;
11575 : }
11576 :
11577 : /* Now splice the lists together... */
11578 8444 : *tf_tail = ard_groups;
11579 8444 : *p_tail = tf_groups;
11580 :
11581 8444 : return p_groups;
11582 : }
11583 :
11584 : /* Given a list LIST_P containing groups of mappings given by GROUPS, reorder
11585 : those groups based on the output list of omp_tsort_mapping_groups --
11586 : singly-linked, threaded through each element's NEXT pointer starting at
11587 : HEAD. Each list element appears exactly once in that linked list.
11588 :
11589 : Each element of GROUPS may correspond to one or several mapping nodes.
11590 : Node groups are kept together, and in the reordered list, the positions of
11591 : the original groups are reused for the positions of the reordered list.
11592 : Hence if we have e.g.
11593 :
11594 : {to ptr ptr} firstprivate {tofrom ptr} ...
11595 : ^ ^ ^
11596 : first group non-"map" second group
11597 :
11598 : and say the second group contains a base pointer for the first so must be
11599 : moved before it, the resulting list will contain:
11600 :
11601 : {tofrom ptr} firstprivate {to ptr ptr} ...
11602 : ^ prev. second group ^ prev. first group
11603 : */
11604 :
11605 : static tree *
11606 8444 : omp_reorder_mapping_groups (vec<omp_mapping_group> *groups,
11607 : omp_mapping_group *head,
11608 : tree *list_p)
11609 : {
11610 8444 : omp_mapping_group *grp;
11611 8444 : unsigned int i;
11612 8444 : unsigned numgroups = groups->length ();
11613 8444 : auto_vec<tree> old_heads (numgroups);
11614 8444 : auto_vec<tree *> old_headps (numgroups);
11615 8444 : auto_vec<tree> new_heads (numgroups);
11616 8444 : auto_vec<tree> old_succs (numgroups);
11617 8444 : bool map_at_start = (list_p == (*groups)[0].grp_start);
11618 :
11619 8444 : tree *new_grp_tail = NULL;
11620 :
11621 : /* Stash the start & end nodes of each mapping group before we start
11622 : modifying the list. */
11623 25124 : FOR_EACH_VEC_ELT (*groups, i, grp)
11624 : {
11625 16680 : old_headps.quick_push (grp->grp_start);
11626 16680 : old_heads.quick_push (*grp->grp_start);
11627 16680 : old_succs.quick_push (OMP_CLAUSE_CHAIN (grp->grp_end));
11628 : }
11629 :
11630 : /* And similarly, the heads of the groups in the order we want to rearrange
11631 : the list to. */
11632 25124 : for (omp_mapping_group *w = head; w; w = w->next)
11633 16680 : new_heads.quick_push (*w->grp_start);
11634 :
11635 25124 : FOR_EACH_VEC_ELT (*groups, i, grp)
11636 : {
11637 16680 : gcc_assert (head);
11638 :
11639 16680 : if (new_grp_tail && old_succs[i - 1] == old_heads[i])
11640 : {
11641 : /* a {b c d} {e f g} h i j (original)
11642 : -->
11643 : a {k l m} {e f g} h i j (inserted new group on last iter)
11644 : -->
11645 : a {k l m} {n o p} h i j (this time, chain last group to new one)
11646 : ^new_grp_tail
11647 : */
11648 7614 : *new_grp_tail = new_heads[i];
11649 : }
11650 9066 : else if (new_grp_tail)
11651 : {
11652 : /* a {b c d} e {f g h} i j k (original)
11653 : -->
11654 : a {l m n} e {f g h} i j k (gap after last iter's group)
11655 : -->
11656 : a {l m n} e {o p q} h i j (chain last group to old successor)
11657 : ^new_grp_tail
11658 : */
11659 622 : *new_grp_tail = old_succs[i - 1];
11660 622 : *old_headps[i] = new_heads[i];
11661 : }
11662 : else
11663 : {
11664 : /* The first inserted group -- point to new group, and leave end
11665 : open.
11666 : a {b c d} e f
11667 : -->
11668 : a {g h i...
11669 : */
11670 8444 : *grp->grp_start = new_heads[i];
11671 : }
11672 :
11673 16680 : new_grp_tail = &OMP_CLAUSE_CHAIN (head->grp_end);
11674 :
11675 16680 : head = head->next;
11676 : }
11677 :
11678 8444 : if (new_grp_tail)
11679 8444 : *new_grp_tail = old_succs[numgroups - 1];
11680 :
11681 8444 : gcc_assert (!head);
11682 :
11683 11821 : return map_at_start ? (*groups)[0].grp_start : list_p;
11684 8444 : }
11685 :
11686 : /* DECL is supposed to have lastprivate semantics in the outer contexts
11687 : of combined/composite constructs, starting with OCTX.
11688 : Add needed lastprivate, shared or map clause if no data sharing or
11689 : mapping clause are present. IMPLICIT_P is true if it is an implicit
11690 : clause (IV on simd), in which case the lastprivate will not be
11691 : copied to some constructs. */
11692 :
11693 : static void
11694 14652 : omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx,
11695 : tree decl, bool implicit_p)
11696 : {
11697 14652 : struct gimplify_omp_ctx *orig_octx = octx;
11698 26973 : for (; octx; octx = octx->outer_context)
11699 : {
11700 25900 : if ((octx->region_type == ORT_COMBINED_PARALLEL
11701 20864 : || (octx->region_type & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS)
11702 25331 : && splay_tree_lookup (octx->variables,
11703 : (splay_tree_key) decl) == NULL)
11704 : {
11705 3887 : omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN);
11706 3887 : continue;
11707 : }
11708 18374 : if ((octx->region_type & ORT_TASK) != 0
11709 575 : && octx->combined_loop
11710 18655 : && splay_tree_lookup (octx->variables,
11711 : (splay_tree_key) decl) == NULL)
11712 : {
11713 248 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11714 248 : continue;
11715 : }
11716 22710 : if (implicit_p
11717 13619 : && octx->region_type == ORT_WORKSHARE
11718 10405 : && octx->combined_loop
11719 10300 : && splay_tree_lookup (octx->variables,
11720 : (splay_tree_key) decl) == NULL
11721 10300 : && octx->outer_context
11722 8907 : && octx->outer_context->region_type == ORT_COMBINED_PARALLEL
11723 22717 : && splay_tree_lookup (octx->outer_context->variables,
11724 : (splay_tree_key) decl) == NULL)
11725 : {
11726 4832 : octx = octx->outer_context;
11727 4832 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11728 4832 : continue;
11729 : }
11730 5564 : if ((octx->region_type == ORT_WORKSHARE || octx->region_type == ORT_ACC)
11731 7482 : && octx->combined_loop
11732 7295 : && splay_tree_lookup (octx->variables,
11733 : (splay_tree_key) decl) == NULL
11734 19071 : && !omp_check_private (octx, decl, false))
11735 : {
11736 3354 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11737 3354 : continue;
11738 : }
11739 9692 : if (octx->region_type == ORT_COMBINED_TARGET)
11740 : {
11741 2008 : splay_tree_node n = splay_tree_lookup (octx->variables,
11742 : (splay_tree_key) decl);
11743 2008 : if (n == NULL)
11744 : {
11745 1986 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11746 1986 : octx = octx->outer_context;
11747 : }
11748 22 : else if (!implicit_p
11749 22 : && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT))
11750 : {
11751 12 : n->value &= ~(GOVD_FIRSTPRIVATE
11752 : | GOVD_FIRSTPRIVATE_IMPLICIT
11753 : | GOVD_EXPLICIT);
11754 12 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11755 12 : octx = octx->outer_context;
11756 : }
11757 : }
11758 : break;
11759 : }
11760 14652 : if (octx && (implicit_p || octx != orig_octx))
11761 4046 : omp_notice_variable (octx, decl, true);
11762 14652 : }
11763 :
11764 : /* We might have indexed several groups for DECL, e.g. a "TO" mapping and also
11765 : a "FIRSTPRIVATE" mapping. Return the one that isn't firstprivate, etc. */
11766 :
11767 : static omp_mapping_group *
11768 5940 : omp_get_nonfirstprivate_group (hash_map<tree_operand_hash_no_se,
11769 : omp_mapping_group *> *grpmap,
11770 : tree decl, bool allow_deleted = false)
11771 : {
11772 5940 : omp_mapping_group **to_group_p = grpmap->get (decl);
11773 :
11774 5940 : if (!to_group_p)
11775 : return NULL;
11776 :
11777 2445 : omp_mapping_group *to_group = *to_group_p;
11778 :
11779 3768 : for (; to_group; to_group = to_group->sibling)
11780 : {
11781 2482 : tree grp_end = to_group->grp_end;
11782 2482 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
11783 : {
11784 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11785 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11786 : break;
11787 :
11788 1161 : default:
11789 1161 : if (allow_deleted || !to_group->deleted)
11790 : return to_group;
11791 : }
11792 : }
11793 :
11794 : return NULL;
11795 : }
11796 :
11797 : /* Return TRUE if the directive (whose clauses are described by the hash table
11798 : of mapping groups, GRPMAP) maps DECL explicitly. If TO_SPECIFICALLY is
11799 : true, only count TO mappings. If ALLOW_DELETED is true, ignore the
11800 : "deleted" flag for groups. If CONTAINED_IN_STRUCT is true, also return
11801 : TRUE if DECL is mapped as a member of a whole-struct mapping. */
11802 :
11803 : static bool
11804 4412 : omp_directive_maps_explicitly (hash_map<tree_operand_hash_no_se,
11805 : omp_mapping_group *> *grpmap,
11806 : tree decl, omp_mapping_group **base_group,
11807 : bool to_specifically, bool allow_deleted,
11808 : bool contained_in_struct)
11809 : {
11810 4412 : omp_mapping_group *decl_group
11811 4412 : = omp_get_nonfirstprivate_group (grpmap, decl, allow_deleted);
11812 :
11813 4412 : *base_group = NULL;
11814 :
11815 4412 : if (decl_group)
11816 : {
11817 1042 : tree grp_first = *decl_group->grp_start;
11818 : /* We might be called during omp_build_struct_sibling_lists, when
11819 : GOMP_MAP_STRUCT might have been inserted at the start of the group.
11820 : Skip over that, and also possibly the node after it. */
11821 1042 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT
11822 1042 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT_UNORD)
11823 : {
11824 6 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11825 6 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_FIRSTPRIVATE_POINTER
11826 6 : || (OMP_CLAUSE_MAP_KIND (grp_first)
11827 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11828 12 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_ATTACH_DETACH)
11829 0 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11830 : }
11831 1042 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
11832 1042 : if (!to_specifically
11833 592 : || GOMP_MAP_COPY_TO_P (first_kind)
11834 382 : || first_kind == GOMP_MAP_ALLOC)
11835 : {
11836 960 : *base_group = decl_group;
11837 960 : return true;
11838 : }
11839 : }
11840 :
11841 3452 : if (contained_in_struct
11842 3452 : && omp_mapped_by_containing_struct (grpmap, decl, base_group))
11843 : return true;
11844 :
11845 : return false;
11846 : }
11847 :
11848 : /* If we have mappings INNER and OUTER, where INNER is a component access and
11849 : OUTER is a mapping of the whole containing struct, check that the mappings
11850 : are compatible. We'll be deleting the inner mapping, so we need to make
11851 : sure the outer mapping does (at least) the same transfers to/from the device
11852 : as the inner mapping. */
11853 :
11854 : bool
11855 172 : omp_check_mapping_compatibility (location_t loc,
11856 : omp_mapping_group *outer,
11857 : omp_mapping_group *inner)
11858 : {
11859 172 : tree first_outer = *outer->grp_start, first_inner = *inner->grp_start;
11860 :
11861 172 : gcc_assert (OMP_CLAUSE_CODE (first_outer) == OMP_CLAUSE_MAP);
11862 172 : gcc_assert (OMP_CLAUSE_CODE (first_inner) == OMP_CLAUSE_MAP);
11863 :
11864 172 : enum gomp_map_kind outer_kind = OMP_CLAUSE_MAP_KIND (first_outer);
11865 172 : enum gomp_map_kind inner_kind = OMP_CLAUSE_MAP_KIND (first_inner);
11866 :
11867 172 : if (outer_kind == inner_kind)
11868 : return true;
11869 :
11870 70 : switch (outer_kind)
11871 : {
11872 0 : case GOMP_MAP_ALWAYS_TO:
11873 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11874 0 : || inner_kind == GOMP_MAP_ALLOC
11875 0 : || inner_kind == GOMP_MAP_TO)
11876 : return true;
11877 : break;
11878 :
11879 0 : case GOMP_MAP_ALWAYS_FROM:
11880 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11881 0 : || inner_kind == GOMP_MAP_RELEASE
11882 : || inner_kind == GOMP_MAP_FROM)
11883 : return true;
11884 : break;
11885 :
11886 10 : case GOMP_MAP_TO:
11887 10 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11888 10 : || inner_kind == GOMP_MAP_ALLOC)
11889 : return true;
11890 : break;
11891 :
11892 8 : case GOMP_MAP_FROM:
11893 8 : if (inner_kind == GOMP_MAP_RELEASE
11894 8 : || inner_kind == GOMP_MAP_FORCE_PRESENT)
11895 : return true;
11896 : break;
11897 :
11898 32 : case GOMP_MAP_ALWAYS_TOFROM:
11899 32 : case GOMP_MAP_TOFROM:
11900 32 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11901 32 : || inner_kind == GOMP_MAP_ALLOC
11902 : || inner_kind == GOMP_MAP_TO
11903 24 : || inner_kind == GOMP_MAP_FROM
11904 12 : || inner_kind == GOMP_MAP_TOFROM)
11905 : return true;
11906 : break;
11907 :
11908 28 : default:
11909 28 : ;
11910 : }
11911 :
11912 84 : error_at (loc, "data movement for component %qE is not compatible with "
11913 28 : "movement for struct %qE", OMP_CLAUSE_DECL (first_inner),
11914 28 : OMP_CLAUSE_DECL (first_outer));
11915 :
11916 28 : return false;
11917 : }
11918 :
11919 : /* This function handles several cases where clauses on a mapping directive
11920 : can interact with each other.
11921 :
11922 : If we have a FIRSTPRIVATE_POINTER node and we're also mapping the pointer
11923 : on the same directive, change the mapping of the first node to
11924 : ATTACH_DETACH. We should have detected that this will happen already in
11925 : c-omp.cc:c_omp_adjust_map_clauses and marked the appropriate decl
11926 : as addressable. (If we didn't, bail out.)
11927 :
11928 : If we have a FIRSTPRIVATE_REFERENCE (for a reference to pointer) and we're
11929 : mapping the base pointer also, we may need to change the mapping type to
11930 : ATTACH_DETACH and synthesize an alloc node for the reference itself.
11931 :
11932 : If we have an ATTACH_DETACH node, this is an array section with a pointer
11933 : base. If we're mapping the base on the same directive too, we can drop its
11934 : mapping. However, if we have a reference to pointer, make other appropriate
11935 : adjustments to the mapping nodes instead.
11936 :
11937 : If we have an ATTACH_DETACH node with a Fortran pointer-set (array
11938 : descriptor) mapping for a derived-type component, and we're also mapping the
11939 : whole of the derived-type variable on another clause, the pointer-set
11940 : mapping is removed.
11941 :
11942 : If we have a component access but we're also mapping the whole of the
11943 : containing struct, drop the former access.
11944 :
11945 : If the expression is a component access, and we're also mapping a base
11946 : pointer used in that component access in the same expression, change the
11947 : mapping type of the latter to ALLOC (ready for processing by
11948 : omp_build_struct_sibling_lists). */
11949 :
11950 : void
11951 8444 : omp_resolve_clause_dependencies (enum tree_code code,
11952 : vec<omp_mapping_group> *groups,
11953 : hash_map<tree_operand_hash_no_se,
11954 : omp_mapping_group *> *grpmap)
11955 : {
11956 8444 : int i;
11957 8444 : omp_mapping_group *grp;
11958 8444 : bool repair_chain = false;
11959 :
11960 24093 : FOR_EACH_VEC_ELT (*groups, i, grp)
11961 : {
11962 15649 : tree grp_end = grp->grp_end;
11963 15649 : tree decl = OMP_CLAUSE_DECL (grp_end);
11964 :
11965 15649 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
11966 :
11967 15649 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
11968 : {
11969 1212 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11970 1212 : {
11971 1212 : omp_mapping_group *to_group
11972 1212 : = omp_get_nonfirstprivate_group (grpmap, decl);
11973 :
11974 1212 : if (!to_group || to_group == grp)
11975 1187 : continue;
11976 :
11977 25 : tree grp_first = *to_group->grp_start;
11978 25 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
11979 :
11980 25 : if ((GOMP_MAP_COPY_TO_P (first_kind)
11981 7 : || first_kind == GOMP_MAP_ALLOC)
11982 50 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
11983 : != GOMP_MAP_FIRSTPRIVATE_POINTER))
11984 : {
11985 25 : gcc_assert (TREE_ADDRESSABLE (OMP_CLAUSE_DECL (grp_end)));
11986 25 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
11987 : }
11988 : }
11989 : break;
11990 :
11991 160 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11992 160 : {
11993 160 : tree ptr = build_fold_indirect_ref (decl);
11994 :
11995 160 : omp_mapping_group *to_group
11996 160 : = omp_get_nonfirstprivate_group (grpmap, ptr);
11997 :
11998 160 : if (!to_group || to_group == grp)
11999 156 : continue;
12000 :
12001 4 : tree grp_first = *to_group->grp_start;
12002 4 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12003 :
12004 4 : if (GOMP_MAP_COPY_TO_P (first_kind)
12005 4 : || first_kind == GOMP_MAP_ALLOC)
12006 : {
12007 4 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12008 4 : OMP_CLAUSE_DECL (grp_end) = ptr;
12009 4 : if ((OMP_CLAUSE_CHAIN (*to_group->grp_start)
12010 4 : == to_group->grp_end)
12011 4 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12012 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
12013 : {
12014 0 : gcc_assert (TREE_ADDRESSABLE
12015 : (OMP_CLAUSE_DECL (to_group->grp_end)));
12016 0 : OMP_CLAUSE_SET_MAP_KIND (to_group->grp_end,
12017 : GOMP_MAP_ATTACH_DETACH);
12018 :
12019 0 : location_t loc = OMP_CLAUSE_LOCATION (to_group->grp_end);
12020 0 : tree alloc
12021 0 : = build_omp_clause (loc, OMP_CLAUSE_MAP);
12022 0 : OMP_CLAUSE_SET_MAP_KIND (alloc, GOMP_MAP_ALLOC);
12023 0 : tree tmp = build_fold_addr_expr (OMP_CLAUSE_DECL
12024 : (to_group->grp_end));
12025 0 : tree char_ptr_type = build_pointer_type (char_type_node);
12026 0 : OMP_CLAUSE_DECL (alloc)
12027 0 : = build2 (MEM_REF, char_type_node,
12028 : tmp,
12029 : build_int_cst (char_ptr_type, 0));
12030 0 : OMP_CLAUSE_SIZE (alloc) = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
12031 :
12032 0 : OMP_CLAUSE_CHAIN (alloc)
12033 0 : = OMP_CLAUSE_CHAIN (*to_group->grp_start);
12034 0 : OMP_CLAUSE_CHAIN (*to_group->grp_start) = alloc;
12035 : }
12036 : }
12037 : }
12038 : break;
12039 :
12040 : case GOMP_MAP_ATTACH_DETACH:
12041 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
12042 : {
12043 2588 : tree base_ptr, referenced_ptr_node = NULL_TREE;
12044 :
12045 2588 : while (TREE_CODE (decl) == ARRAY_REF)
12046 0 : decl = TREE_OPERAND (decl, 0);
12047 :
12048 2588 : if (TREE_CODE (decl) == INDIRECT_REF)
12049 13 : decl = TREE_OPERAND (decl, 0);
12050 :
12051 : /* Only component accesses. */
12052 2588 : if (DECL_P (decl))
12053 226 : continue;
12054 :
12055 : /* We want the pointer itself when checking if the base pointer is
12056 : mapped elsewhere in the same directive -- if we have a
12057 : reference to the pointer, don't use that. */
12058 :
12059 2362 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12060 2362 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12061 : {
12062 394 : referenced_ptr_node = OMP_CLAUSE_CHAIN (*grp->grp_start);
12063 394 : base_ptr = OMP_CLAUSE_DECL (referenced_ptr_node);
12064 : }
12065 : else
12066 : base_ptr = decl;
12067 :
12068 1944 : gomp_map_kind zlas_kind
12069 2362 : = (code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
12070 2362 : ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION;
12071 :
12072 2362 : if (TREE_CODE (TREE_TYPE (base_ptr)) == POINTER_TYPE)
12073 : {
12074 : /* If we map the base TO, and we're doing an attachment, we can
12075 : skip the TO mapping altogether and create an ALLOC mapping
12076 : instead, since the attachment will overwrite the device
12077 : pointer in that location immediately anyway. Otherwise,
12078 : change our mapping to
12079 : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION in case the
12080 : attachment target has not been copied to the device already
12081 : by some earlier directive. */
12082 :
12083 1938 : bool base_mapped_to = false;
12084 :
12085 1938 : omp_mapping_group *base_group;
12086 :
12087 1938 : if (omp_directive_maps_explicitly (grpmap, base_ptr,
12088 : &base_group, false, true,
12089 : false))
12090 : {
12091 450 : if (referenced_ptr_node)
12092 : {
12093 129 : base_mapped_to = true;
12094 129 : if ((OMP_CLAUSE_MAP_KIND (base_group->grp_end)
12095 : == GOMP_MAP_ATTACH_DETACH)
12096 129 : && (OMP_CLAUSE_CHAIN (*base_group->grp_start)
12097 : == base_group->grp_end))
12098 : {
12099 258 : OMP_CLAUSE_CHAIN (*base_group->grp_start)
12100 129 : = OMP_CLAUSE_CHAIN (base_group->grp_end);
12101 129 : base_group->grp_end = *base_group->grp_start;
12102 129 : repair_chain = true;
12103 : }
12104 : }
12105 : else
12106 : {
12107 321 : base_group->deleted = true;
12108 321 : OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end) = 1;
12109 : }
12110 : }
12111 :
12112 : /* We're dealing with a reference to a pointer, and we are
12113 : attaching both the reference and the pointer. We know the
12114 : reference itself is on the target, because we are going to
12115 : create an ALLOC node for it in accumulate_sibling_list. The
12116 : pointer might be on the target already or it might not, but
12117 : if it isn't then it's not an error, so use
12118 : GOMP_MAP_ATTACH_ZLAS for it. */
12119 1938 : if (!base_mapped_to && referenced_ptr_node)
12120 56 : OMP_CLAUSE_SET_MAP_KIND (referenced_ptr_node, zlas_kind);
12121 :
12122 1938 : omp_mapping_group *struct_group;
12123 1938 : tree desc;
12124 1938 : if ((desc = OMP_CLAUSE_CHAIN (*grp->grp_start))
12125 1938 : && omp_map_clause_descriptor_p (desc)
12126 2983 : && omp_mapped_by_containing_struct (grpmap, decl,
12127 : &struct_group))
12128 : /* If we have a pointer set but we're mapping (or unmapping)
12129 : the whole of the containing struct, we can remove the
12130 : pointer set mapping. */
12131 15 : OMP_CLAUSE_CHAIN (*grp->grp_start) = OMP_CLAUSE_CHAIN (desc);
12132 : }
12133 424 : else if (TREE_CODE (TREE_TYPE (base_ptr)) == REFERENCE_TYPE
12134 424 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (base_ptr)))
12135 : == ARRAY_TYPE)
12136 562 : && OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION
12137 : (*grp->grp_start))
12138 92 : OMP_CLAUSE_SET_MAP_KIND (grp->grp_end, zlas_kind);
12139 : }
12140 : break;
12141 :
12142 : case GOMP_MAP_ATTACH:
12143 : /* Ignore standalone attach here. */
12144 : break;
12145 :
12146 11626 : default:
12147 11626 : {
12148 11626 : omp_mapping_group *struct_group;
12149 11626 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12150 11626 : && *grp->grp_start == grp_end)
12151 : {
12152 94 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12153 : struct_group, grp);
12154 : /* Remove the whole of this mapping -- redundant. */
12155 94 : grp->deleted = true;
12156 : }
12157 :
12158 : tree base = decl;
12159 13234 : while ((base = omp_get_base_pointer (base)))
12160 : {
12161 1608 : omp_mapping_group *base_group;
12162 :
12163 1608 : if (omp_directive_maps_explicitly (grpmap, base, &base_group,
12164 : true, true, false))
12165 : {
12166 343 : tree grp_first = *base_group->grp_start;
12167 343 : OMP_CLAUSE_SET_MAP_KIND (grp_first, GOMP_MAP_ALLOC);
12168 : }
12169 : }
12170 : }
12171 : }
12172 : }
12173 :
12174 8444 : if (repair_chain)
12175 : {
12176 : /* Group start pointers may have become detached from the
12177 : OMP_CLAUSE_CHAIN of previous groups if elements were removed from the
12178 : end of those groups. Fix that now. */
12179 : tree *new_next = NULL;
12180 716 : FOR_EACH_VEC_ELT (*groups, i, grp)
12181 : {
12182 587 : if (new_next)
12183 458 : grp->grp_start = new_next;
12184 :
12185 587 : new_next = &OMP_CLAUSE_CHAIN (grp->grp_end);
12186 : }
12187 : }
12188 8444 : }
12189 :
12190 : /* Similar to omp_resolve_clause_dependencies, but for OpenACC. The only
12191 : clause dependencies we handle for now are struct element mappings and
12192 : whole-struct mappings on the same directive, and duplicate clause
12193 : detection. */
12194 :
12195 : void
12196 9462 : oacc_resolve_clause_dependencies (vec<omp_mapping_group> *groups,
12197 : hash_map<tree_operand_hash_no_se,
12198 : omp_mapping_group *> *grpmap)
12199 : {
12200 9462 : int i;
12201 9462 : omp_mapping_group *grp;
12202 9462 : hash_set<tree_operand_hash> *seen_components = NULL;
12203 9462 : hash_set<tree_operand_hash> *shown_error = NULL;
12204 :
12205 24643 : FOR_EACH_VEC_ELT (*groups, i, grp)
12206 : {
12207 15181 : tree grp_end = grp->grp_end;
12208 15181 : tree decl = OMP_CLAUSE_DECL (grp_end);
12209 :
12210 15181 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12211 :
12212 15181 : if (DECL_P (grp_end))
12213 14664 : continue;
12214 :
12215 15181 : tree c = OMP_CLAUSE_DECL (*grp->grp_start);
12216 16806 : while (TREE_CODE (c) == ARRAY_REF)
12217 1625 : c = TREE_OPERAND (c, 0);
12218 15181 : if (TREE_CODE (c) != COMPONENT_REF)
12219 14664 : continue;
12220 517 : if (!seen_components)
12221 474 : seen_components = new hash_set<tree_operand_hash> ();
12222 517 : if (!shown_error)
12223 474 : shown_error = new hash_set<tree_operand_hash> ();
12224 517 : if (seen_components->contains (c)
12225 517 : && !shown_error->contains (c))
12226 : {
12227 10 : error_at (OMP_CLAUSE_LOCATION (grp_end),
12228 : "%qE appears more than once in map clauses",
12229 5 : OMP_CLAUSE_DECL (grp_end));
12230 5 : shown_error->add (c);
12231 : }
12232 : else
12233 512 : seen_components->add (c);
12234 :
12235 517 : omp_mapping_group *struct_group;
12236 517 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12237 517 : && *grp->grp_start == grp_end)
12238 : {
12239 78 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12240 : struct_group, grp);
12241 : /* Remove the whole of this mapping -- redundant. */
12242 78 : grp->deleted = true;
12243 : }
12244 : }
12245 :
12246 9462 : if (seen_components)
12247 474 : delete seen_components;
12248 9462 : if (shown_error)
12249 474 : delete shown_error;
12250 9462 : }
12251 :
12252 : /* Link node NEWNODE so it is pointed to by chain INSERT_AT. NEWNODE's chain
12253 : is linked to the previous node pointed to by INSERT_AT. */
12254 :
12255 : static tree *
12256 1132 : omp_siblist_insert_node_after (tree newnode, tree *insert_at)
12257 : {
12258 1132 : OMP_CLAUSE_CHAIN (newnode) = *insert_at;
12259 1132 : *insert_at = newnode;
12260 1132 : return &OMP_CLAUSE_CHAIN (newnode);
12261 : }
12262 :
12263 : /* Move NODE (which is currently pointed to by the chain OLD_POS) so it is
12264 : pointed to by chain MOVE_AFTER instead. */
12265 :
12266 : static void
12267 1320 : omp_siblist_move_node_after (tree node, tree *old_pos, tree *move_after)
12268 : {
12269 1320 : gcc_assert (node == *old_pos);
12270 1320 : *old_pos = OMP_CLAUSE_CHAIN (node);
12271 1320 : OMP_CLAUSE_CHAIN (node) = *move_after;
12272 1320 : *move_after = node;
12273 1320 : }
12274 :
12275 : /* Move nodes from FIRST_PTR (pointed to by previous node's chain) to
12276 : LAST_NODE to after MOVE_AFTER chain. Similar to below function, but no
12277 : new nodes are prepended to the list before splicing into the new position.
12278 : Return the position we should continue scanning the list at, or NULL to
12279 : stay where we were. */
12280 :
12281 : static tree *
12282 254 : omp_siblist_move_nodes_after (tree *first_ptr, tree last_node,
12283 : tree *move_after)
12284 : {
12285 254 : if (first_ptr == move_after)
12286 : return NULL;
12287 :
12288 243 : tree tmp = *first_ptr;
12289 243 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12290 243 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12291 243 : *move_after = tmp;
12292 :
12293 243 : return first_ptr;
12294 : }
12295 :
12296 : /* Concatenate two lists described by [FIRST_NEW, LAST_NEW_TAIL] and
12297 : [FIRST_PTR, LAST_NODE], and insert them in the OMP clause list after chain
12298 : pointer MOVE_AFTER.
12299 :
12300 : The latter list was previously part of the OMP clause list, and the former
12301 : (prepended) part is comprised of new nodes.
12302 :
12303 : We start with a list of nodes starting with a struct mapping node. We
12304 : rearrange the list so that new nodes starting from FIRST_NEW and whose last
12305 : node's chain is LAST_NEW_TAIL comes directly after MOVE_AFTER, followed by
12306 : the group of mapping nodes we are currently processing (from the chain
12307 : FIRST_PTR to LAST_NODE). The return value is the pointer to the next chain
12308 : we should continue processing from, or NULL to stay where we were.
12309 :
12310 : The transformation (in the case where MOVE_AFTER and FIRST_PTR are
12311 : different) is worked through below. Here we are processing LAST_NODE, and
12312 : FIRST_PTR points at the preceding mapping clause:
12313 :
12314 : #. mapping node chain
12315 : ---------------------------------------------------
12316 : A. struct_node [->B]
12317 : B. comp_1 [->C]
12318 : C. comp_2 [->D (move_after)]
12319 : D. map_to_3 [->E]
12320 : E. attach_3 [->F (first_ptr)]
12321 : F. map_to_4 [->G (continue_at)]
12322 : G. attach_4 (last_node) [->H]
12323 : H. ...
12324 :
12325 : *last_new_tail = *first_ptr;
12326 :
12327 : I. new_node (first_new) [->F (last_new_tail)]
12328 :
12329 : *first_ptr = OMP_CLAUSE_CHAIN (last_node)
12330 :
12331 : #. mapping node chain
12332 : ----------------------------------------------------
12333 : A. struct_node [->B]
12334 : B. comp_1 [->C]
12335 : C. comp_2 [->D (move_after)]
12336 : D. map_to_3 [->E]
12337 : E. attach_3 [->H (first_ptr)]
12338 : F. map_to_4 [->G (continue_at)]
12339 : G. attach_4 (last_node) [->H]
12340 : H. ...
12341 :
12342 : I. new_node (first_new) [->F (last_new_tail)]
12343 :
12344 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12345 :
12346 : #. mapping node chain
12347 : ---------------------------------------------------
12348 : A. struct_node [->B]
12349 : B. comp_1 [->C]
12350 : C. comp_2 [->D (move_after)]
12351 : D. map_to_3 [->E]
12352 : E. attach_3 [->H (continue_at)]
12353 : F. map_to_4 [->G]
12354 : G. attach_4 (last_node) [->D]
12355 : H. ...
12356 :
12357 : I. new_node (first_new) [->F (last_new_tail)]
12358 :
12359 : *move_after = first_new;
12360 :
12361 : #. mapping node chain
12362 : ---------------------------------------------------
12363 : A. struct_node [->B]
12364 : B. comp_1 [->C]
12365 : C. comp_2 [->I (move_after)]
12366 : D. map_to_3 [->E]
12367 : E. attach_3 [->H (continue_at)]
12368 : F. map_to_4 [->G]
12369 : G. attach_4 (last_node) [->D]
12370 : H. ...
12371 : I. new_node (first_new) [->F (last_new_tail)]
12372 :
12373 : or, in order:
12374 :
12375 : #. mapping node chain
12376 : ---------------------------------------------------
12377 : A. struct_node [->B]
12378 : B. comp_1 [->C]
12379 : C. comp_2 [->I (move_after)]
12380 : I. new_node (first_new) [->F (last_new_tail)]
12381 : F. map_to_4 [->G]
12382 : G. attach_4 (last_node) [->D]
12383 : D. map_to_3 [->E]
12384 : E. attach_3 [->H (continue_at)]
12385 : H. ...
12386 : */
12387 :
12388 : static tree *
12389 71 : omp_siblist_move_concat_nodes_after (tree first_new, tree *last_new_tail,
12390 : tree *first_ptr, tree last_node,
12391 : tree *move_after)
12392 : {
12393 71 : tree *continue_at = NULL;
12394 71 : *last_new_tail = *first_ptr;
12395 71 : if (first_ptr == move_after)
12396 12 : *move_after = first_new;
12397 : else
12398 : {
12399 59 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12400 59 : continue_at = first_ptr;
12401 59 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12402 59 : *move_after = first_new;
12403 : }
12404 71 : return continue_at;
12405 : }
12406 :
12407 : static omp_addr_token *
12408 11472 : omp_first_chained_access_token (vec<omp_addr_token *> &addr_tokens)
12409 : {
12410 11472 : using namespace omp_addr_tokenizer;
12411 11472 : int idx = addr_tokens.length () - 1;
12412 11472 : gcc_assert (idx >= 0);
12413 11472 : if (addr_tokens[idx]->type != ACCESS_METHOD)
12414 : return addr_tokens[idx];
12415 11499 : while (idx > 0 && addr_tokens[idx - 1]->type == ACCESS_METHOD)
12416 : idx--;
12417 11472 : return addr_tokens[idx];
12418 : }
12419 :
12420 : /* Mapping struct members causes an additional set of nodes to be created,
12421 : starting with GOMP_MAP_STRUCT followed by a number of mappings equal to the
12422 : number of members being mapped, in order of ascending position (address or
12423 : bitwise).
12424 :
12425 : We scan through the list of mapping clauses, calling this function for each
12426 : struct member mapping we find, and build up the list of mappings after the
12427 : initial GOMP_MAP_STRUCT node. For pointer members, these will be
12428 : newly-created ALLOC nodes. For non-pointer members, the existing mapping is
12429 : moved into place in the sorted list.
12430 :
12431 : struct {
12432 : int *a;
12433 : int *b;
12434 : int c;
12435 : int *d;
12436 : };
12437 :
12438 : #pragma (acc|omp directive) copy(struct.a[0:n], struct.b[0:n], struct.c,
12439 : struct.d[0:n])
12440 :
12441 : GOMP_MAP_STRUCT (4)
12442 : [GOMP_MAP_FIRSTPRIVATE_REFERENCE -- for refs to structs]
12443 : GOMP_MAP_ALLOC (struct.a)
12444 : GOMP_MAP_ALLOC (struct.b)
12445 : GOMP_MAP_TO (struct.c)
12446 : GOMP_MAP_ALLOC (struct.d)
12447 : ...
12448 :
12449 : In the case where we are mapping references to pointers, or in Fortran if
12450 : we are mapping an array with a descriptor, additional nodes may be created
12451 : after the struct node list also.
12452 :
12453 : The return code is either a pointer to the next node to process (if the
12454 : list has been rearranged), else NULL to continue with the next node in the
12455 : original list. */
12456 :
12457 : static tree *
12458 4731 : omp_accumulate_sibling_list (enum omp_region_type region_type,
12459 : enum tree_code code,
12460 : hash_map<tree_operand_hash, tree>
12461 : *&struct_map_to_clause,
12462 : hash_map<tree_operand_hash_no_se,
12463 : omp_mapping_group *> *group_map,
12464 : tree *grp_start_p, tree grp_end,
12465 : vec<omp_addr_token *> &addr_tokens, tree **inner,
12466 : bool *fragile_p, bool reprocessing_struct,
12467 : tree **added_tail)
12468 : {
12469 4731 : using namespace omp_addr_tokenizer;
12470 4731 : poly_offset_int coffset;
12471 4731 : poly_int64 cbitpos;
12472 4731 : tree ocd = OMP_CLAUSE_DECL (grp_end);
12473 4731 : bool openmp = !(region_type & ORT_ACC);
12474 4731 : bool target = (region_type & ORT_TARGET) != 0;
12475 4731 : tree *continue_at = NULL;
12476 :
12477 5044 : while (TREE_CODE (ocd) == ARRAY_REF)
12478 313 : ocd = TREE_OPERAND (ocd, 0);
12479 :
12480 4731 : if (*fragile_p)
12481 : {
12482 156 : omp_mapping_group *to_group
12483 156 : = omp_get_nonfirstprivate_group (group_map, ocd, true);
12484 :
12485 156 : if (to_group)
12486 : return NULL;
12487 : }
12488 :
12489 4643 : omp_addr_token *last_token = omp_first_chained_access_token (addr_tokens);
12490 4643 : if (last_token->type == ACCESS_METHOD)
12491 : {
12492 4643 : switch (last_token->u.access_kind)
12493 : {
12494 735 : case ACCESS_REF:
12495 735 : case ACCESS_REF_TO_POINTER:
12496 735 : case ACCESS_REF_TO_POINTER_OFFSET:
12497 735 : case ACCESS_INDEXED_REF_TO_ARRAY:
12498 : /* We may see either a bare reference or a dereferenced
12499 : "convert_from_reference"-like one here. Handle either way. */
12500 735 : if (TREE_CODE (ocd) == INDIRECT_REF)
12501 64 : ocd = TREE_OPERAND (ocd, 0);
12502 735 : gcc_assert (TREE_CODE (TREE_TYPE (ocd)) == REFERENCE_TYPE);
12503 : break;
12504 :
12505 : default:
12506 : ;
12507 : }
12508 : }
12509 :
12510 4643 : bool variable_offset;
12511 4643 : tree base
12512 4643 : = extract_base_bit_offset (ocd, &cbitpos, &coffset, &variable_offset);
12513 :
12514 4643 : int base_token;
12515 23726 : for (base_token = addr_tokens.length () - 1; base_token >= 0; base_token--)
12516 : {
12517 19083 : if (addr_tokens[base_token]->type == ARRAY_BASE
12518 19083 : || addr_tokens[base_token]->type == STRUCTURE_BASE)
12519 : break;
12520 : }
12521 :
12522 : /* The two expressions in the assertion below aren't quite the same: if we
12523 : have 'struct_base_decl access_indexed_array' for something like
12524 : "myvar[2].x" then base will be "myvar" and addr_tokens[base_token]->expr
12525 : will be "myvar[2]" -- the actual base of the structure.
12526 : The former interpretation leads to a strange situation where we get
12527 : struct(myvar) alloc(myvar[2].ptr1)
12528 : That is, the array of structures is kind of treated as one big structure
12529 : for the purposes of gathering sibling lists, etc. */
12530 : /* gcc_assert (base == addr_tokens[base_token]->expr); */
12531 :
12532 4643 : bool attach_detach = ((OMP_CLAUSE_MAP_KIND (grp_end)
12533 : == GOMP_MAP_ATTACH_DETACH)
12534 4643 : || (OMP_CLAUSE_MAP_KIND (grp_end)
12535 4643 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
12536 4643 : bool has_descriptor = false;
12537 4643 : if (OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
12538 : {
12539 3103 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
12540 3103 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
12541 : has_descriptor = true;
12542 : }
12543 :
12544 4643 : if (!struct_map_to_clause || struct_map_to_clause->get (base) == NULL)
12545 : {
12546 3024 : enum gomp_map_kind str_kind = GOMP_MAP_STRUCT;
12547 :
12548 3024 : if (struct_map_to_clause == NULL)
12549 2468 : struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
12550 :
12551 3024 : if (variable_offset)
12552 274 : str_kind = GOMP_MAP_STRUCT_UNORD;
12553 :
12554 3024 : tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
12555 :
12556 3024 : OMP_CLAUSE_SET_MAP_KIND (l, str_kind);
12557 3024 : OMP_CLAUSE_DECL (l) = unshare_expr (base);
12558 3024 : OMP_CLAUSE_SIZE (l) = size_int (1);
12559 :
12560 3024 : struct_map_to_clause->put (base, l);
12561 :
12562 : /* On first iterating through the clause list, we insert the struct node
12563 : just before the component access node that triggers the initial
12564 : omp_accumulate_sibling_list call for a particular sibling list (and
12565 : it then forms the first entry in that list). When reprocessing
12566 : struct bases that are themselves component accesses, we insert the
12567 : struct node on an off-side list to avoid inserting the new
12568 : GOMP_MAP_STRUCT into the middle of the old one. */
12569 3024 : tree *insert_node_pos = reprocessing_struct ? *added_tail : grp_start_p;
12570 :
12571 3024 : if (has_descriptor)
12572 : {
12573 726 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
12574 726 : if (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
12575 187 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
12576 726 : tree sc = *insert_node_pos;
12577 726 : OMP_CLAUSE_CHAIN (l) = desc;
12578 726 : OMP_CLAUSE_CHAIN (*grp_start_p) = OMP_CLAUSE_CHAIN (desc);
12579 726 : OMP_CLAUSE_CHAIN (desc) = sc;
12580 726 : *insert_node_pos = l;
12581 : }
12582 2298 : else if (attach_detach)
12583 : {
12584 1396 : tree extra_node;
12585 1396 : tree alloc_node
12586 1396 : = build_omp_struct_comp_nodes (code, *grp_start_p, grp_end,
12587 : &extra_node);
12588 1396 : tree *tail;
12589 1396 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12590 :
12591 1396 : if (extra_node)
12592 : {
12593 0 : OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos;
12594 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
12595 0 : tail = &OMP_CLAUSE_CHAIN (extra_node);
12596 : }
12597 : else
12598 : {
12599 1396 : OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
12600 1396 : tail = &OMP_CLAUSE_CHAIN (alloc_node);
12601 : }
12602 :
12603 : /* For OpenMP semantics, we don't want to implicitly allocate
12604 : space for the pointer here for non-compute regions (e.g. "enter
12605 : data"). A FRAGILE_P node is only being created so that
12606 : omp-low.cc is able to rewrite the struct properly.
12607 : For references (to pointers), we want to actually allocate the
12608 : space for the reference itself in the sorted list following the
12609 : struct node.
12610 : For pointers, we want to allocate space if we had an explicit
12611 : mapping of the attachment point, but not otherwise. */
12612 1396 : if (*fragile_p
12613 1396 : || (openmp
12614 : && !target
12615 : && attach_detach
12616 234 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
12617 88 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
12618 : {
12619 133 : if (!lang_GNU_Fortran ())
12620 : /* In Fortran, pointers are dereferenced automatically, but may
12621 : be unassociated. So we still want to allocate space for the
12622 : pointer (as the base for an attach operation that should be
12623 : present in the same directive's clause list also). */
12624 103 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
12625 133 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
12626 : }
12627 :
12628 1396 : *insert_node_pos = l;
12629 :
12630 1396 : if (reprocessing_struct)
12631 : {
12632 : /* When reprocessing a struct node group used as the base of a
12633 : subcomponent access, if we have a reference-to-pointer base,
12634 : we will see:
12635 : struct(**ptr) attach(*ptr)
12636 : whereas for a non-reprocess-struct group, we see, e.g.:
12637 : tofrom(**ptr) attach(*ptr) attach(ptr)
12638 : and we create the "alloc" for the second "attach", i.e.
12639 : for the reference itself. When reprocessing a struct group we
12640 : thus change the pointer attachment into a reference attachment
12641 : by stripping the indirection. (The attachment of the
12642 : referenced pointer must happen elsewhere, either on the same
12643 : directive, or otherwise.) */
12644 180 : tree adecl = OMP_CLAUSE_DECL (alloc_node);
12645 :
12646 180 : if ((TREE_CODE (adecl) == INDIRECT_REF
12647 148 : || (TREE_CODE (adecl) == MEM_REF
12648 0 : && integer_zerop (TREE_OPERAND (adecl, 1))))
12649 32 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (adecl, 0)))
12650 : == REFERENCE_TYPE)
12651 212 : && (TREE_CODE (TREE_TYPE (TREE_TYPE
12652 : (TREE_OPERAND (adecl, 0)))) == POINTER_TYPE))
12653 32 : OMP_CLAUSE_DECL (alloc_node) = TREE_OPERAND (adecl, 0);
12654 :
12655 180 : *added_tail = tail;
12656 : }
12657 : }
12658 : else
12659 : {
12660 902 : gcc_assert (*grp_start_p == grp_end);
12661 902 : if (reprocessing_struct)
12662 : {
12663 : /* If we don't have an attach/detach node, this is a
12664 : "target data" directive or similar, not an offload region.
12665 : Synthesize an "alloc" node using just the initiating
12666 : GOMP_MAP_STRUCT decl. */
12667 16 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
12668 32 : || code == OACC_EXIT_DATA)
12669 32 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
12670 32 : tree alloc_node
12671 32 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12672 : OMP_CLAUSE_MAP);
12673 32 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
12674 32 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
12675 64 : OMP_CLAUSE_SIZE (alloc_node)
12676 32 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
12677 :
12678 32 : OMP_CLAUSE_CHAIN (alloc_node) = OMP_CLAUSE_CHAIN (l);
12679 32 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12680 32 : *insert_node_pos = l;
12681 32 : *added_tail = &OMP_CLAUSE_CHAIN (alloc_node);
12682 : }
12683 : else
12684 870 : grp_start_p = omp_siblist_insert_node_after (l, insert_node_pos);
12685 : }
12686 :
12687 3024 : unsigned last_access = base_token + 1;
12688 :
12689 3024 : while (last_access + 1 < addr_tokens.length ()
12690 3358 : && addr_tokens[last_access + 1]->type == ACCESS_METHOD)
12691 : last_access++;
12692 :
12693 3024 : if ((region_type & ORT_TARGET)
12694 3024 : && addr_tokens[base_token + 1]->type == ACCESS_METHOD)
12695 : {
12696 1682 : bool base_ref = false;
12697 1682 : access_method_kinds access_kind
12698 1682 : = addr_tokens[last_access]->u.access_kind;
12699 :
12700 1682 : switch (access_kind)
12701 : {
12702 : case ACCESS_DIRECT:
12703 : case ACCESS_INDEXED_ARRAY:
12704 1034 : return NULL;
12705 :
12706 403 : case ACCESS_REF:
12707 403 : case ACCESS_REF_TO_POINTER:
12708 403 : case ACCESS_REF_TO_POINTER_OFFSET:
12709 403 : case ACCESS_INDEXED_REF_TO_ARRAY:
12710 403 : base_ref = true;
12711 403 : break;
12712 :
12713 866 : default:
12714 866 : ;
12715 : }
12716 866 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12717 : OMP_CLAUSE_MAP);
12718 866 : enum gomp_map_kind mkind;
12719 866 : omp_mapping_group *decl_group;
12720 866 : tree use_base;
12721 866 : switch (access_kind)
12722 : {
12723 463 : case ACCESS_POINTER:
12724 463 : case ACCESS_POINTER_OFFSET:
12725 463 : use_base = addr_tokens[last_access]->expr;
12726 463 : break;
12727 198 : case ACCESS_REF_TO_POINTER:
12728 198 : case ACCESS_REF_TO_POINTER_OFFSET:
12729 198 : use_base
12730 198 : = build_fold_indirect_ref (addr_tokens[last_access]->expr);
12731 198 : break;
12732 205 : default:
12733 205 : use_base = addr_tokens[base_token]->expr;
12734 : }
12735 866 : bool mapped_to_p
12736 866 : = omp_directive_maps_explicitly (group_map, use_base, &decl_group,
12737 : true, false, true);
12738 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12739 866 : && DECL_P (addr_tokens[last_access]->expr)
12740 1372 : && !mapped_to_p)
12741 444 : mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
12742 : : GOMP_MAP_FIRSTPRIVATE_POINTER;
12743 : else
12744 : mkind = GOMP_MAP_ATTACH_DETACH;
12745 :
12746 866 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
12747 : /* If we have a reference to pointer base, we want to attach the
12748 : pointer here, not the reference. The reference attachment happens
12749 : elsewhere. */
12750 866 : bool ref_to_ptr
12751 866 : = (access_kind == ACCESS_REF_TO_POINTER
12752 866 : || access_kind == ACCESS_REF_TO_POINTER_OFFSET);
12753 866 : tree sdecl = addr_tokens[last_access]->expr;
12754 866 : tree sdecl_ptr = ref_to_ptr ? build_fold_indirect_ref (sdecl)
12755 : : sdecl;
12756 : /* For the FIRSTPRIVATE_REFERENCE after the struct node, we
12757 : want to use the reference itself for the decl, but we
12758 : still want to use the pointer to calculate the bias. */
12759 866 : OMP_CLAUSE_DECL (c2) = (mkind == GOMP_MAP_ATTACH_DETACH)
12760 866 : ? sdecl_ptr : sdecl;
12761 866 : sdecl = sdecl_ptr;
12762 866 : tree baddr = build_fold_addr_expr (base);
12763 866 : baddr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12764 : ptrdiff_type_node, baddr);
12765 866 : tree decladdr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12766 : ptrdiff_type_node, sdecl);
12767 866 : OMP_CLAUSE_SIZE (c2)
12768 866 : = fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR,
12769 : ptrdiff_type_node, baddr, decladdr);
12770 : /* Insert after struct node. */
12771 866 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
12772 866 : OMP_CLAUSE_CHAIN (l) = c2;
12773 :
12774 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12775 866 : && (addr_tokens[base_token]->u.structure_base_kind
12776 : == BASE_COMPONENT_EXPR)
12777 286 : && mkind == GOMP_MAP_ATTACH_DETACH
12778 1152 : && addr_tokens[last_access]->u.access_kind != ACCESS_REF)
12779 : {
12780 218 : *inner = insert_node_pos;
12781 218 : if (openmp)
12782 166 : *fragile_p = true;
12783 218 : return NULL;
12784 : }
12785 : }
12786 :
12787 1990 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12788 1990 : && (addr_tokens[base_token]->u.structure_base_kind
12789 : == BASE_COMPONENT_EXPR)
12790 2457 : && addr_tokens[last_access]->u.access_kind == ACCESS_REF)
12791 100 : *inner = insert_node_pos;
12792 :
12793 1990 : return NULL;
12794 : }
12795 1619 : else if (struct_map_to_clause)
12796 : {
12797 1619 : tree *osc = struct_map_to_clause->get (base);
12798 1619 : tree *sc = NULL, *scp = NULL;
12799 :
12800 1619 : unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
12801 1619 : sc = &OMP_CLAUSE_CHAIN (*osc);
12802 : /* The struct mapping might be immediately followed by a
12803 : FIRSTPRIVATE_POINTER, FIRSTPRIVATE_REFERENCE or an ATTACH_DETACH --
12804 : if it's an indirect access or a reference, or if the structure base
12805 : is not a decl. The FIRSTPRIVATE_* nodes are removed in omp-low.cc
12806 : after they have been processed there, and ATTACH_DETACH nodes are
12807 : recomputed and moved out of the GOMP_MAP_STRUCT construct once
12808 : sibling list building is complete. */
12809 1619 : if (OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_POINTER
12810 1574 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
12811 3148 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_ATTACH_DETACH)
12812 201 : sc = &OMP_CLAUSE_CHAIN (*sc);
12813 4108 : for (i = 0; i < elems; i++, sc = &OMP_CLAUSE_CHAIN (*sc))
12814 3062 : if (attach_detach && sc == grp_start_p)
12815 : break;
12816 3062 : else if (TREE_CODE (OMP_CLAUSE_DECL (*sc)) != COMPONENT_REF
12817 182 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != INDIRECT_REF
12818 3244 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != ARRAY_REF)
12819 : break;
12820 : else
12821 : {
12822 3062 : tree sc_decl = OMP_CLAUSE_DECL (*sc);
12823 3062 : poly_offset_int offset;
12824 3062 : poly_int64 bitpos;
12825 :
12826 3062 : if (TREE_CODE (sc_decl) == ARRAY_REF)
12827 : {
12828 366 : while (TREE_CODE (sc_decl) == ARRAY_REF)
12829 184 : sc_decl = TREE_OPERAND (sc_decl, 0);
12830 182 : if (TREE_CODE (sc_decl) != COMPONENT_REF
12831 182 : || TREE_CODE (TREE_TYPE (sc_decl)) != ARRAY_TYPE)
12832 : break;
12833 : }
12834 2880 : else if (INDIRECT_REF_P (sc_decl)
12835 0 : && TREE_CODE (TREE_OPERAND (sc_decl, 0)) == COMPONENT_REF
12836 2880 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (sc_decl, 0)))
12837 : == REFERENCE_TYPE))
12838 0 : sc_decl = TREE_OPERAND (sc_decl, 0);
12839 :
12840 3062 : bool variable_offset2;
12841 3062 : tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset,
12842 : &variable_offset2);
12843 3062 : if (!base2 || !operand_equal_p (base2, base, 0))
12844 : break;
12845 3062 : if (scp)
12846 469 : continue;
12847 2842 : if (variable_offset2)
12848 : {
12849 341 : OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
12850 :
12851 341 : if (has_descriptor)
12852 : {
12853 : /* Sort mapped components by offset. This is needed for
12854 : libgomp to handle Fortran derived-type allocatable
12855 : components transparently. */
12856 :
12857 323 : poly_int64 bitsize;
12858 323 : tree offset, coffset;
12859 323 : machine_mode mode;
12860 323 : int unsignedp, reversep, volatilep;
12861 323 : tree inner_ref1
12862 323 : = get_inner_reference (sc_decl, &bitsize, &bitpos,
12863 : &offset, &mode, &unsignedp,
12864 : &reversep, &volatilep);
12865 323 : tree osc_decl = ocd;
12866 323 : STRIP_NOPS (osc_decl);
12867 323 : tree inner_ref2
12868 323 : = get_inner_reference (osc_decl, &bitsize, &bitpos,
12869 : &coffset, &mode, &unsignedp,
12870 : &reversep, &volatilep);
12871 323 : gcc_assert (operand_equal_p (inner_ref1, inner_ref2, 0));
12872 323 : tree offset_diff
12873 323 : = fold_binary_to_constant (MINUS_EXPR, size_type_node,
12874 : coffset, offset);
12875 572 : if (offset_diff == NULL_TREE
12876 323 : || TREE_INT_CST_ELT (offset_diff, 0) > 0)
12877 249 : continue;
12878 : else
12879 : break;
12880 : }
12881 : }
12882 2501 : else if ((region_type & ORT_ACC) != 0)
12883 : {
12884 : /* For OpenACC, allow (ignore) duplicate struct accesses in
12885 : the middle of a mapping clause, e.g. "mystruct->foo" in:
12886 : copy(mystruct->foo->bar) copy(mystruct->foo->qux). */
12887 223 : if (reprocessing_struct
12888 8 : && known_eq (coffset, offset)
12889 223 : && known_eq (cbitpos, bitpos))
12890 16 : return NULL;
12891 : }
12892 2278 : else if (known_eq (coffset, offset)
12893 2278 : && known_eq (cbitpos, bitpos))
12894 : {
12895 : /* Having two struct members at the same offset doesn't work,
12896 : so make sure we don't. (We're allowed to ignore this.
12897 : Should we report the error?) */
12898 : /*error_at (OMP_CLAUSE_LOCATION (grp_end),
12899 : "duplicate struct member %qE in map clauses",
12900 : OMP_CLAUSE_DECL (grp_end));*/
12901 : return NULL;
12902 : }
12903 2503 : if (maybe_lt (coffset, offset)
12904 4231 : || (known_eq (coffset, offset)
12905 20 : && maybe_lt (cbitpos, bitpos)))
12906 : {
12907 775 : if (attach_detach)
12908 : scp = sc;
12909 : else
12910 : break;
12911 : }
12912 : }
12913 :
12914 1603 : OMP_CLAUSE_SIZE (*osc)
12915 1603 : = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
12916 :
12917 1603 : if (reprocessing_struct)
12918 : {
12919 : /* If we're reprocessing a struct node, we don't want to do most of
12920 : the list manipulation below. We only need to handle the (pointer
12921 : or reference) attach/detach case. */
12922 8 : tree extra_node, alloc_node;
12923 8 : if (has_descriptor)
12924 0 : gcc_unreachable ();
12925 8 : else if (attach_detach)
12926 8 : alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
12927 : grp_end, &extra_node);
12928 : else
12929 : {
12930 : /* If we don't have an attach/detach node, this is a
12931 : "target data" directive or similar, not an offload region.
12932 : Synthesize an "alloc" node using just the initiating
12933 : GOMP_MAP_STRUCT decl. */
12934 0 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
12935 0 : || code == OACC_EXIT_DATA)
12936 0 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
12937 0 : alloc_node
12938 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12939 : OMP_CLAUSE_MAP);
12940 0 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
12941 0 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
12942 0 : OMP_CLAUSE_SIZE (alloc_node)
12943 0 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
12944 : }
12945 :
12946 8 : if (scp)
12947 0 : omp_siblist_insert_node_after (alloc_node, scp);
12948 : else
12949 : {
12950 8 : tree *new_end = omp_siblist_insert_node_after (alloc_node, sc);
12951 8 : if (sc == *added_tail)
12952 8 : *added_tail = new_end;
12953 : }
12954 :
12955 8 : return NULL;
12956 : }
12957 :
12958 1595 : if (has_descriptor)
12959 : {
12960 538 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
12961 538 : if (code == OMP_TARGET_EXIT_DATA
12962 538 : || code == OACC_EXIT_DATA)
12963 105 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
12964 1076 : omp_siblist_move_node_after (desc,
12965 538 : &OMP_CLAUSE_CHAIN (*grp_start_p),
12966 : scp ? scp : sc);
12967 : }
12968 1057 : else if (attach_detach)
12969 : {
12970 325 : tree cl = NULL_TREE, extra_node;
12971 325 : tree alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
12972 : grp_end, &extra_node);
12973 325 : tree *tail_chain = NULL;
12974 :
12975 325 : if (*fragile_p
12976 325 : || (openmp
12977 : && !target
12978 : && attach_detach
12979 62 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
12980 23 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
12981 : {
12982 6 : if (!lang_GNU_Fortran ())
12983 6 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
12984 6 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
12985 : }
12986 :
12987 : /* Here, we have:
12988 :
12989 : grp_end : the last (or only) node in this group.
12990 : grp_start_p : pointer to the first node in a pointer mapping group
12991 : up to and including GRP_END.
12992 : sc : pointer to the chain for the end of the struct component
12993 : list.
12994 : scp : pointer to the chain for the sorted position at which we
12995 : should insert in the middle of the struct component list
12996 : (else NULL to insert at end).
12997 : alloc_node : the "alloc" node for the structure (pointer-type)
12998 : component. We insert at SCP (if present), else SC
12999 : (the end of the struct component list).
13000 : extra_node : a newly-synthesized node for an additional indirect
13001 : pointer mapping or a Fortran pointer set, if needed.
13002 : cl : first node to prepend before grp_start_p.
13003 : tail_chain : pointer to chain of last prepended node.
13004 :
13005 : The general idea is we move the nodes for this struct mapping
13006 : together: the alloc node goes into the sorted list directly after
13007 : the struct mapping, and any extra nodes (together with the nodes
13008 : mapping arrays pointed to by struct components) get moved after
13009 : that list. When SCP is NULL, we insert the nodes at SC, i.e. at
13010 : the end of the struct component mapping list. It's important that
13011 : the alloc_node comes first in that case because it's part of the
13012 : sorted component mapping list (but subsequent nodes are not!). */
13013 :
13014 325 : if (scp)
13015 254 : omp_siblist_insert_node_after (alloc_node, scp);
13016 :
13017 : /* Make [cl,tail_chain] a list of the alloc node (if we haven't
13018 : already inserted it) and the extra_node (if it is present). The
13019 : list can be empty if we added alloc_node above and there is no
13020 : extra node. */
13021 254 : if (scp && extra_node)
13022 : {
13023 0 : cl = extra_node;
13024 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13025 : }
13026 325 : else if (extra_node)
13027 : {
13028 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
13029 0 : cl = alloc_node;
13030 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13031 : }
13032 325 : else if (!scp)
13033 : {
13034 71 : cl = alloc_node;
13035 71 : tail_chain = &OMP_CLAUSE_CHAIN (alloc_node);
13036 : }
13037 :
13038 325 : continue_at
13039 71 : = cl ? omp_siblist_move_concat_nodes_after (cl, tail_chain,
13040 : grp_start_p, grp_end,
13041 : sc)
13042 254 : : omp_siblist_move_nodes_after (grp_start_p, grp_end, sc);
13043 : }
13044 732 : else if (*sc != grp_end)
13045 : {
13046 692 : gcc_assert (*grp_start_p == grp_end);
13047 :
13048 : /* We are moving the current node back to a previous struct node:
13049 : the node that used to point to the current node will now point to
13050 : the next node. */
13051 692 : continue_at = grp_start_p;
13052 : /* In the non-pointer case, the mapping clause itself is moved into
13053 : the correct position in the struct component list, which in this
13054 : case is just SC. */
13055 692 : omp_siblist_move_node_after (*grp_start_p, grp_start_p, sc);
13056 : }
13057 : }
13058 : return continue_at;
13059 : }
13060 :
13061 : /* Scan through GROUPS, and create sorted structure sibling lists without
13062 : gimplifying. */
13063 :
13064 : static bool
13065 17906 : omp_build_struct_sibling_lists (enum tree_code code,
13066 : enum omp_region_type region_type,
13067 : vec<omp_mapping_group> *groups,
13068 : hash_map<tree_operand_hash_no_se,
13069 : omp_mapping_group *> **grpmap,
13070 : tree *list_p)
13071 : {
13072 17906 : using namespace omp_addr_tokenizer;
13073 17906 : unsigned i;
13074 17906 : omp_mapping_group *grp;
13075 17906 : hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
13076 17906 : bool success = true;
13077 17906 : tree *new_next = NULL;
13078 35812 : tree *tail = &OMP_CLAUSE_CHAIN ((*groups)[groups->length () - 1].grp_end);
13079 17906 : tree added_nodes = NULL_TREE;
13080 17906 : tree *added_tail = &added_nodes;
13081 17906 : auto_vec<omp_mapping_group> pre_hwm_groups;
13082 :
13083 66960 : FOR_EACH_VEC_ELT (*groups, i, grp)
13084 : {
13085 31148 : tree c = grp->grp_end;
13086 31148 : tree decl = OMP_CLAUSE_DECL (c);
13087 31148 : tree grp_end = grp->grp_end;
13088 31148 : auto_vec<omp_addr_token *> addr_tokens;
13089 31148 : tree sentinel = OMP_CLAUSE_CHAIN (grp_end);
13090 :
13091 31148 : if (new_next && !grp->reprocess_struct)
13092 622 : grp->grp_start = new_next;
13093 :
13094 31148 : new_next = NULL;
13095 :
13096 31148 : tree *grp_start_p = grp->grp_start;
13097 :
13098 31148 : if (DECL_P (decl))
13099 21050 : continue;
13100 :
13101 : /* Skip groups we marked for deletion in
13102 : {omp,oacc}_resolve_clause_dependencies. */
13103 10098 : if (grp->deleted)
13104 462 : continue;
13105 :
13106 9636 : if (OMP_CLAUSE_CHAIN (*grp_start_p)
13107 9636 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
13108 : {
13109 : /* Don't process an array descriptor that isn't inside a derived type
13110 : as a struct (the GOMP_MAP_POINTER following will have the form
13111 : "var.data", but such mappings are handled specially). */
13112 6078 : tree grpmid = OMP_CLAUSE_CHAIN (*grp_start_p);
13113 6078 : if (omp_map_clause_descriptor_p (grpmid)
13114 10196 : && DECL_P (OMP_CLAUSE_DECL (grpmid)))
13115 2807 : continue;
13116 : }
13117 :
13118 : tree expr = decl;
13119 :
13120 7842 : while (TREE_CODE (expr) == ARRAY_REF)
13121 1013 : expr = TREE_OPERAND (expr, 0);
13122 :
13123 6829 : if (!omp_parse_expr (addr_tokens, expr))
13124 0 : continue;
13125 :
13126 6829 : omp_addr_token *last_token
13127 6829 : = omp_first_chained_access_token (addr_tokens);
13128 :
13129 : /* A mapping of a reference to a pointer member that doesn't specify an
13130 : array section, etc., like this:
13131 : *mystruct.ref_to_ptr
13132 : should not be processed by the struct sibling-list handling code --
13133 : it just transfers the referenced pointer.
13134 :
13135 : In contrast, the quite similar-looking construct:
13136 : *mystruct.ptr
13137 : which is equivalent to e.g.
13138 : mystruct.ptr[0]
13139 : *does* trigger sibling-list processing.
13140 :
13141 : An exception for the former case is for "fragile" groups where the
13142 : reference itself is not handled otherwise; this is subject to special
13143 : handling in omp_accumulate_sibling_list also. */
13144 :
13145 6829 : if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
13146 3364 : && last_token->type == ACCESS_METHOD
13147 3364 : && last_token->u.access_kind == ACCESS_REF
13148 7111 : && !grp->fragile)
13149 217 : continue;
13150 :
13151 6612 : tree d = decl;
13152 6612 : if (TREE_CODE (d) == ARRAY_REF)
13153 : {
13154 1974 : while (TREE_CODE (d) == ARRAY_REF)
13155 998 : d = TREE_OPERAND (d, 0);
13156 976 : if (TREE_CODE (d) == COMPONENT_REF
13157 976 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
13158 : decl = d;
13159 : }
13160 6612 : if (d == decl
13161 5947 : && INDIRECT_REF_P (decl)
13162 734 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
13163 105 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
13164 : == REFERENCE_TYPE)
13165 6709 : && (OMP_CLAUSE_MAP_KIND (c)
13166 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
13167 97 : decl = TREE_OPERAND (decl, 0);
13168 :
13169 6612 : STRIP_NOPS (decl);
13170 :
13171 6612 : if (TREE_CODE (decl) != COMPONENT_REF)
13172 1343 : continue;
13173 :
13174 : /* If we're mapping the whole struct in another node, skip adding this
13175 : node to a sibling list. */
13176 5269 : omp_mapping_group *wholestruct;
13177 5269 : if (omp_mapped_by_containing_struct (*grpmap, OMP_CLAUSE_DECL (c),
13178 : &wholestruct))
13179 : {
13180 177 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
13181 160 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
13182 177 : continue;
13183 : }
13184 :
13185 5092 : if (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
13186 5092 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
13187 4989 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
13188 : && code != OACC_UPDATE
13189 10014 : && code != OMP_TARGET_UPDATE)
13190 : {
13191 4731 : if (error_operand_p (decl))
13192 : {
13193 0 : success = false;
13194 0 : goto error_out;
13195 : }
13196 :
13197 4731 : tree stype = TREE_TYPE (decl);
13198 4731 : if (TREE_CODE (stype) == REFERENCE_TYPE)
13199 768 : stype = TREE_TYPE (stype);
13200 4731 : if (TYPE_SIZE_UNIT (stype) == NULL
13201 4731 : || TREE_CODE (TYPE_SIZE_UNIT (stype)) != INTEGER_CST)
13202 : {
13203 0 : error_at (OMP_CLAUSE_LOCATION (c),
13204 : "mapping field %qE of variable length "
13205 0 : "structure", OMP_CLAUSE_DECL (c));
13206 0 : success = false;
13207 0 : goto error_out;
13208 : }
13209 :
13210 4731 : tree *inner = NULL;
13211 4731 : bool fragile_p = grp->fragile;
13212 :
13213 4731 : new_next
13214 9462 : = omp_accumulate_sibling_list (region_type, code,
13215 : struct_map_to_clause, *grpmap,
13216 : grp_start_p, grp_end, addr_tokens,
13217 : &inner, &fragile_p,
13218 4731 : grp->reprocess_struct, &added_tail);
13219 :
13220 4731 : if (inner)
13221 : {
13222 318 : omp_mapping_group newgrp;
13223 318 : newgrp.grp_start = inner;
13224 318 : if (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (*inner))
13225 : == GOMP_MAP_ATTACH_DETACH)
13226 286 : newgrp.grp_end = OMP_CLAUSE_CHAIN (*inner);
13227 : else
13228 32 : newgrp.grp_end = *inner;
13229 318 : newgrp.mark = UNVISITED;
13230 318 : newgrp.sibling = NULL;
13231 318 : newgrp.deleted = false;
13232 318 : newgrp.reprocess_struct = true;
13233 318 : newgrp.fragile = fragile_p;
13234 318 : newgrp.next = NULL;
13235 318 : groups->safe_push (newgrp);
13236 :
13237 : /* !!! Growing GROUPS might invalidate the pointers in the group
13238 : map. Rebuild it here. This is a bit inefficient, but
13239 : shouldn't happen very often. */
13240 636 : delete (*grpmap);
13241 318 : *grpmap
13242 318 : = omp_reindex_mapping_groups (list_p, groups, &pre_hwm_groups,
13243 : sentinel);
13244 : }
13245 : }
13246 31148 : }
13247 :
13248 : /* Delete groups marked for deletion above. At this point the order of the
13249 : groups may no longer correspond to the order of the underlying list,
13250 : which complicates this a little. First clear out OMP_CLAUSE_DECL for
13251 : deleted nodes... */
13252 :
13253 49054 : FOR_EACH_VEC_ELT (*groups, i, grp)
13254 31148 : if (grp->deleted)
13255 462 : for (tree d = *grp->grp_start;
13256 924 : d != OMP_CLAUSE_CHAIN (grp->grp_end);
13257 462 : d = OMP_CLAUSE_CHAIN (d))
13258 462 : OMP_CLAUSE_DECL (d) = NULL_TREE;
13259 :
13260 : /* ...then sweep through the list removing the now-empty nodes. */
13261 :
13262 : tail = list_p;
13263 95499 : while (*tail)
13264 : {
13265 77593 : if (OMP_CLAUSE_CODE (*tail) == OMP_CLAUSE_MAP
13266 77593 : && OMP_CLAUSE_DECL (*tail) == NULL_TREE)
13267 462 : *tail = OMP_CLAUSE_CHAIN (*tail);
13268 : else
13269 77131 : tail = &OMP_CLAUSE_CHAIN (*tail);
13270 : }
13271 :
13272 : /* Tack on the struct nodes added during nested struct reprocessing. */
13273 17906 : if (added_nodes)
13274 : {
13275 192 : *tail = added_nodes;
13276 192 : tail = added_tail;
13277 : }
13278 :
13279 : /* Find each attach node whose bias needs to be adjusted and move it to the
13280 : group containing its pointee, right after the struct node, so that it can
13281 : be picked up by the adjustment code further down in this function. */
13282 17906 : bool attach_bias_needs_adjustment;
13283 17906 : attach_bias_needs_adjustment = false;
13284 66960 : FOR_EACH_VEC_ELT_REVERSE (*groups, i, grp)
13285 : {
13286 31148 : tree c = *grp->grp_start;
13287 30209 : if (c != NULL && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13288 30194 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
13289 27157 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
13290 3317 : && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) == GOMP_MAP_TO_PSET
13291 527 : && OMP_CLAUSE_MAP_KIND (grp->grp_end) == GOMP_MAP_ATTACH_DETACH
13292 31675 : && OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end))
13293 : {
13294 90 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end) = 0;
13295 90 : attach_bias_needs_adjustment = true;
13296 90 : tree *cp;
13297 90 : for (cp = &OMP_CLAUSE_CHAIN (c); cp != NULL;
13298 206 : cp = &OMP_CLAUSE_CHAIN (*cp))
13299 296 : if (*cp == grp->grp_end)
13300 : {
13301 : c = *cp;
13302 : break;
13303 : }
13304 :
13305 90 : tree base = OMP_CLAUSE_DECL (c);
13306 90 : gcc_assert (TREE_CODE (base) == NOP_EXPR);
13307 90 : base = build_fold_indirect_ref (base);
13308 90 : tree *struct_node = struct_map_to_clause->get (base);
13309 90 : omp_siblist_move_node_after (c, cp, &OMP_CLAUSE_CHAIN (*struct_node));
13310 : }
13311 : }
13312 :
13313 : /* Now we have finished building the struct sibling lists, reprocess
13314 : newly-added "attach" nodes: we need the address of the first
13315 : mapped element of each struct sibling list for the bias of the attach
13316 : operation -- not necessarily the base address of the whole struct. */
13317 17906 : if (struct_map_to_clause)
13318 5492 : for (hash_map<tree_operand_hash, tree>::iterator iter
13319 2468 : = struct_map_to_clause->begin ();
13320 7960 : iter != struct_map_to_clause->end ();
13321 3024 : ++iter)
13322 : {
13323 3024 : tree struct_node = (*iter).second;
13324 3024 : gcc_assert (OMP_CLAUSE_CODE (struct_node) == OMP_CLAUSE_MAP);
13325 3024 : tree attach = OMP_CLAUSE_CHAIN (struct_node);
13326 :
13327 3024 : if (OMP_CLAUSE_CODE (attach) != OMP_CLAUSE_MAP
13328 3024 : || OMP_CLAUSE_MAP_KIND (attach) != GOMP_MAP_ATTACH_DETACH)
13329 2512 : continue;
13330 :
13331 512 : OMP_CLAUSE_SET_MAP_KIND (attach, GOMP_MAP_ATTACH);
13332 :
13333 : /* Sanity check: the standalone attach node will not work if we have
13334 : an "enter data" operation (because for those, variables need to be
13335 : mapped separately and attach nodes must be grouped together with the
13336 : base they attach to). We should only have created the
13337 : ATTACH_DETACH node either after GOMP_MAP_STRUCT for a target region
13338 : or for an intermediate descriptor that needs adjustment -- so this
13339 : should never be true. */
13340 512 : gcc_assert ((region_type & ORT_TARGET) != 0
13341 : || attach_bias_needs_adjustment);
13342 :
13343 : /* This is the first sorted node in the struct sibling list. Use it
13344 : to recalculate the correct bias to use.
13345 : (&first_node - attach_decl).
13346 : For GOMP_MAP_STRUCT_UNORD, we need e.g. the
13347 : min(min(min(first,second),third),fourth) element, because the
13348 : elements aren't in any particular order. */
13349 512 : tree lowest_addr;
13350 512 : if (OMP_CLAUSE_MAP_KIND (struct_node) == GOMP_MAP_STRUCT_UNORD)
13351 : {
13352 94 : tree first_node = OMP_CLAUSE_CHAIN (attach);
13353 94 : unsigned HOST_WIDE_INT num_mappings
13354 94 : = tree_to_uhwi (OMP_CLAUSE_SIZE (struct_node));
13355 94 : lowest_addr = OMP_CLAUSE_DECL (first_node);
13356 94 : lowest_addr = build_fold_addr_expr (lowest_addr);
13357 94 : lowest_addr = fold_convert (pointer_sized_int_node, lowest_addr);
13358 94 : tree next_node = OMP_CLAUSE_CHAIN (first_node);
13359 185 : while (num_mappings > 1)
13360 : {
13361 91 : tree tmp = OMP_CLAUSE_DECL (next_node);
13362 91 : tmp = build_fold_addr_expr (tmp);
13363 91 : tmp = fold_convert (pointer_sized_int_node, tmp);
13364 91 : lowest_addr = fold_build2 (MIN_EXPR, pointer_sized_int_node,
13365 : lowest_addr, tmp);
13366 91 : next_node = OMP_CLAUSE_CHAIN (next_node);
13367 91 : num_mappings--;
13368 : }
13369 94 : lowest_addr = fold_convert (ptrdiff_type_node, lowest_addr);
13370 : }
13371 : else
13372 : {
13373 418 : tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
13374 418 : first_node = build_fold_addr_expr (first_node);
13375 418 : lowest_addr = fold_convert (ptrdiff_type_node, first_node);
13376 : }
13377 512 : tree attach_decl = OMP_CLAUSE_DECL (attach);
13378 512 : attach_decl = fold_convert (ptrdiff_type_node, attach_decl);
13379 512 : OMP_CLAUSE_SIZE (attach)
13380 512 : = fold_build2 (MINUS_EXPR, ptrdiff_type_node, lowest_addr,
13381 : attach_decl);
13382 :
13383 : /* Remove GOMP_MAP_ATTACH node from after struct node. */
13384 512 : OMP_CLAUSE_CHAIN (struct_node) = OMP_CLAUSE_CHAIN (attach);
13385 : /* ...and re-insert it at the end of our clause list. */
13386 512 : *tail = attach;
13387 512 : OMP_CLAUSE_CHAIN (attach) = NULL_TREE;
13388 512 : tail = &OMP_CLAUSE_CHAIN (attach);
13389 : }
13390 :
13391 15438 : error_out:
13392 17906 : if (struct_map_to_clause)
13393 2468 : delete struct_map_to_clause;
13394 :
13395 17906 : return success;
13396 17906 : }
13397 :
13398 : struct instantiate_mapper_info
13399 : {
13400 : tree *mapper_clauses_p;
13401 : struct gimplify_omp_ctx *omp_ctx;
13402 : gimple_seq *pre_p;
13403 : };
13404 :
13405 : /* Helper function for omp_instantiate_mapper. */
13406 :
13407 : static tree
13408 1592 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
13409 : {
13410 1592 : copy_body_data *id = (copy_body_data *) data;
13411 :
13412 1592 : if (DECL_P (*tp))
13413 : {
13414 724 : tree replacement = remap_decl (*tp, id);
13415 724 : if (*tp != replacement)
13416 : {
13417 369 : *tp = unshare_expr (replacement);
13418 369 : *walk_subtrees = 0;
13419 : }
13420 : }
13421 :
13422 1592 : return NULL_TREE;
13423 : }
13424 :
13425 : /* A copy_decl implementation (for use with tree-inline.cc functions) that
13426 : only transform decls or SSA names that are part of a map we already
13427 : prepared. */
13428 :
13429 : static tree
13430 126 : omp_mapper_copy_decl (tree var, copy_body_data *cb)
13431 : {
13432 126 : tree *repl = cb->decl_map->get (var);
13433 :
13434 126 : if (repl)
13435 0 : return *repl;
13436 :
13437 126 : return var;
13438 : }
13439 :
13440 : static tree *
13441 90 : omp_instantiate_mapper (gimple_seq *pre_p,
13442 : hash_map<omp_name_type<tree>, tree> *implicit_mappers,
13443 : tree mapperfn, tree expr, enum gomp_map_kind outer_kind,
13444 : tree *mapper_clauses_p)
13445 : {
13446 90 : tree mapper_name = NULL_TREE;
13447 90 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapperfn);
13448 90 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
13449 :
13450 90 : tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
13451 90 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
13452 :
13453 : /* The "extraction map" is used to map the mapper variable in the "declare
13454 : mapper" directive, and also any temporary variables that have been created
13455 : as part of expanding the mapper function's body (which are expanded as a
13456 : "bind" expression in the pre_p sequence). */
13457 90 : hash_map<tree, tree> extraction_map;
13458 :
13459 90 : extraction_map.put (dummy_var, expr);
13460 90 : extraction_map.put (expr, expr);
13461 :
13462 : /* This copy_body_data is only used to remap the decls in the
13463 : OMP_DECLARE_MAPPER tree node expansion itself. All relevant decls should
13464 : already be in the current function. */
13465 90 : copy_body_data id;
13466 90 : memset (&id, 0, sizeof (id));
13467 90 : id.src_fn = current_function_decl;
13468 90 : id.dst_fn = current_function_decl;
13469 90 : id.src_cfun = cfun;
13470 90 : id.decl_map = &extraction_map;
13471 90 : id.copy_decl = omp_mapper_copy_decl;
13472 90 : id.transform_call_graph_edges = CB_CGE_DUPLICATE; // ???
13473 90 : id.transform_new_cfg = true; // ???
13474 :
13475 282 : for (; clause; clause = OMP_CLAUSE_CHAIN (clause))
13476 : {
13477 192 : enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (clause);
13478 192 : tree *nested_mapper_p = NULL;
13479 :
13480 192 : if (map_kind == GOMP_MAP_PUSH_MAPPER_NAME)
13481 : {
13482 0 : mapper_name = OMP_CLAUSE_DECL (clause);
13483 25 : continue;
13484 : }
13485 192 : else if (map_kind == GOMP_MAP_POP_MAPPER_NAME)
13486 : {
13487 0 : mapper_name = NULL_TREE;
13488 0 : continue;
13489 : }
13490 :
13491 192 : if (OMP_CLAUSE_HAS_ITERATORS (clause))
13492 : {
13493 2 : sorry_at (OMP_CLAUSE_LOCATION (clause),
13494 : "user-defined mapper that uses a %<map%> clause "
13495 : "with %<iterator%>");
13496 2 : continue;
13497 : }
13498 :
13499 190 : tree decl = OMP_CLAUSE_DECL (clause);
13500 190 : tree unshared, type;
13501 190 : bool nonunit_array_with_mapper = false;
13502 :
13503 190 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
13504 : {
13505 62 : location_t loc = OMP_CLAUSE_LOCATION (clause);
13506 62 : tree tmp = lang_hooks.decls.omp_map_array_section (loc, decl);
13507 62 : if (tmp == decl)
13508 : {
13509 48 : unshared = unshare_expr (clause);
13510 48 : nonunit_array_with_mapper = true;
13511 48 : type = TREE_TYPE (TREE_TYPE (decl));
13512 : }
13513 : else
13514 : {
13515 14 : unshared = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
13516 14 : OMP_CLAUSE_CODE (clause));
13517 14 : OMP_CLAUSE_DECL (unshared) = tmp;
13518 14 : OMP_CLAUSE_SIZE (unshared)
13519 28 : = DECL_P (tmp) ? DECL_SIZE_UNIT (tmp)
13520 14 : : TYPE_SIZE_UNIT (TREE_TYPE (tmp));
13521 14 : type = TREE_TYPE (tmp);
13522 : }
13523 : }
13524 : else
13525 : {
13526 128 : unshared = unshare_expr (clause);
13527 128 : type = TREE_TYPE (decl);
13528 : }
13529 :
13530 190 : walk_tree (&unshared, remap_mapper_decl_1, &id, NULL);
13531 :
13532 190 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
13533 28 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
13534 :
13535 190 : decl = OMP_CLAUSE_DECL (unshared);
13536 190 : type = TYPE_MAIN_VARIANT (type);
13537 :
13538 190 : nested_mapper_p = implicit_mappers->get ({ mapper_name, type });
13539 :
13540 190 : if (nested_mapper_p && *nested_mapper_p != mapperfn)
13541 : {
13542 23 : if (nonunit_array_with_mapper)
13543 : {
13544 8 : sorry ("user-defined mapper with non-unit length array section");
13545 8 : continue;
13546 : }
13547 :
13548 15 : if (map_kind == GOMP_MAP_UNSET)
13549 0 : map_kind = outer_kind;
13550 :
13551 15 : mapper_clauses_p
13552 15 : = omp_instantiate_mapper (pre_p, implicit_mappers,
13553 : *nested_mapper_p, decl, map_kind,
13554 : mapper_clauses_p);
13555 15 : continue;
13556 : }
13557 :
13558 167 : *mapper_clauses_p = unshared;
13559 167 : mapper_clauses_p = &OMP_CLAUSE_CHAIN (unshared);
13560 : }
13561 :
13562 90 : return mapper_clauses_p;
13563 90 : }
13564 :
13565 : static int
13566 136752 : omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
13567 : {
13568 136752 : tree decl = (tree) n->key;
13569 136752 : instantiate_mapper_info *im_info = (instantiate_mapper_info *) data;
13570 136752 : gimplify_omp_ctx *ctx = im_info->omp_ctx;
13571 136752 : tree *mapper_p = NULL;
13572 136752 : tree type = TREE_TYPE (decl);
13573 136752 : bool ref_p = false;
13574 136752 : unsigned flags = n->value;
13575 :
13576 136752 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
13577 : return 0;
13578 23475 : if ((flags & GOVD_SEEN) == 0)
13579 : return 0;
13580 : /* If we already have clauses pertaining to a struct variable, then we don't
13581 : want to implicitly invoke a user-defined mapper. */
13582 19981 : if ((flags & GOVD_EXPLICIT) != 0 && AGGREGATE_TYPE_P (TREE_TYPE (decl)))
13583 : return 0;
13584 :
13585 19981 : if (TREE_CODE (type) == REFERENCE_TYPE)
13586 : {
13587 899 : ref_p = true;
13588 899 : type = TREE_TYPE (type);
13589 : }
13590 :
13591 19981 : type = TYPE_MAIN_VARIANT (type);
13592 :
13593 19981 : if (DECL_P (decl) && type && AGGREGATE_TYPE_P (type))
13594 : {
13595 5286 : gcc_assert (ctx);
13596 5286 : mapper_p = ctx->implicit_mappers->get ({ NULL_TREE, type });
13597 : }
13598 :
13599 5286 : if (mapper_p)
13600 : {
13601 : /* If we have a reference, map the pointed-to object rather than the
13602 : reference itself. */
13603 75 : if (ref_p)
13604 2 : decl = build_fold_indirect_ref (decl);
13605 :
13606 75 : im_info->mapper_clauses_p
13607 75 : = omp_instantiate_mapper (im_info->pre_p, ctx->implicit_mappers,
13608 : *mapper_p, decl, GOMP_MAP_TOFROM,
13609 : im_info->mapper_clauses_p);
13610 : /* Make sure we don't map the same variable implicitly in
13611 : gimplify_adjust_omp_clauses_1 also. */
13612 75 : n->value |= GOVD_EXPLICIT;
13613 : }
13614 :
13615 : return 0;
13616 : }
13617 :
13618 : /* Scan the OMP clauses in *LIST_P, installing mappings into a new
13619 : and previous omp contexts. */
13620 :
13621 : static void
13622 130446 : gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
13623 : enum omp_region_type region_type,
13624 : enum tree_code code,
13625 : gimple_seq *loops_seq_p = NULL)
13626 : {
13627 130446 : using namespace omp_addr_tokenizer;
13628 130446 : struct gimplify_omp_ctx *ctx, *outer_ctx;
13629 130446 : tree c;
13630 130446 : tree *orig_list_p = list_p;
13631 130446 : int handled_depend_iterators = -1;
13632 130446 : int nowait = -1;
13633 :
13634 130446 : ctx = new_omp_context (region_type);
13635 130446 : ctx->code = code;
13636 130446 : outer_ctx = ctx->outer_context;
13637 130446 : if (code == OMP_TARGET)
13638 : {
13639 13426 : if (!lang_GNU_Fortran ())
13640 11130 : ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
13641 13426 : ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE;
13642 26852 : ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran ()
13643 13426 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
13644 : }
13645 130446 : if (!lang_GNU_Fortran ())
13646 99322 : switch (code)
13647 : {
13648 18574 : case OMP_TARGET:
13649 18574 : case OMP_TARGET_DATA:
13650 18574 : case OMP_TARGET_ENTER_DATA:
13651 18574 : case OMP_TARGET_EXIT_DATA:
13652 18574 : case OACC_DECLARE:
13653 18574 : case OACC_HOST_DATA:
13654 18574 : case OACC_PARALLEL:
13655 18574 : case OACC_KERNELS:
13656 18574 : ctx->target_firstprivatize_array_bases = true;
13657 : default:
13658 : break;
13659 : }
13660 :
13661 130446 : vec<omp_mapping_group> *groups = NULL;
13662 130446 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
13663 130446 : unsigned grpnum = 0;
13664 130446 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
13665 :
13666 130446 : if (code == OMP_TARGET
13667 130446 : || code == OMP_TARGET_DATA
13668 130446 : || code == OMP_TARGET_ENTER_DATA
13669 : || code == OMP_TARGET_EXIT_DATA
13670 : || code == OACC_DATA
13671 : || code == OACC_KERNELS
13672 : || code == OACC_PARALLEL
13673 : || code == OACC_SERIAL
13674 : || code == OACC_ENTER_DATA
13675 : || code == OACC_EXIT_DATA
13676 : || code == OACC_UPDATE
13677 : || code == OACC_DECLARE)
13678 : {
13679 33779 : if (!(region_type & ORT_ACC))
13680 17267 : *list_p = omp_remove_duplicate_maps (*list_p, false);
13681 33779 : groups = omp_gather_mapping_groups (list_p);
13682 :
13683 33779 : if (groups)
13684 18107 : grpmap = omp_index_mapping_groups (groups);
13685 : }
13686 :
13687 335599 : while ((c = *list_p) != NULL)
13688 : {
13689 205153 : bool remove = false;
13690 205153 : bool notice_outer = true;
13691 205153 : bool map_descriptor;
13692 205153 : const char *check_non_private = NULL;
13693 205153 : unsigned int flags;
13694 205153 : tree decl;
13695 205153 : auto_vec<omp_addr_token *, 10> addr_tokens;
13696 205153 : tree op = NULL_TREE;
13697 205153 : location_t loc = OMP_CLAUSE_LOCATION (c);
13698 :
13699 242542 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
13700 : {
13701 : grp_start_p = NULL;
13702 : grp_end = NULL_TREE;
13703 : }
13704 :
13705 205153 : if (code == OMP_TARGET
13706 : || code == OMP_TARGET_DATA
13707 : || code == OMP_TARGET_ENTER_DATA
13708 172766 : || code == OMP_TARGET_EXIT_DATA)
13709 : /* Do some target-specific type checks for map operands. */
13710 34810 : switch (OMP_CLAUSE_CODE (c))
13711 : {
13712 25441 : case OMP_CLAUSE_MAP:
13713 25441 : op = OMP_CLAUSE_OPERAND (c, 0);
13714 25441 : verify_type_context (loc, TCTX_OMP_MAP, TREE_TYPE (op));
13715 25441 : break;
13716 180 : case OMP_CLAUSE_PRIVATE:
13717 180 : op = OMP_CLAUSE_OPERAND (c, 0);
13718 180 : verify_type_context (loc, TCTX_OMP_PRIVATE, TREE_TYPE (op));
13719 180 : break;
13720 1332 : case OMP_CLAUSE_FIRSTPRIVATE:
13721 1332 : op = OMP_CLAUSE_OPERAND (c, 0);
13722 1332 : verify_type_context (loc, TCTX_OMP_FIRSTPRIVATE, TREE_TYPE (op));
13723 1332 : break;
13724 2922 : case OMP_CLAUSE_IS_DEVICE_PTR:
13725 2922 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13726 2922 : case OMP_CLAUSE_USE_DEVICE_PTR:
13727 2922 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13728 2922 : op = OMP_CLAUSE_OPERAND (c, 0);
13729 2922 : verify_type_context (loc, TCTX_OMP_DEVICE_ADDR, TREE_TYPE (op));
13730 2922 : break;
13731 : default:
13732 : break;
13733 : }
13734 :
13735 205153 : switch (OMP_CLAUSE_CODE (c))
13736 : {
13737 12231 : case OMP_CLAUSE_PRIVATE:
13738 12231 : flags = GOVD_PRIVATE | GOVD_EXPLICIT;
13739 12231 : if (lang_hooks.decls.omp_private_outer_ref (OMP_CLAUSE_DECL (c)))
13740 : {
13741 167 : flags |= GOVD_PRIVATE_OUTER_REF;
13742 167 : OMP_CLAUSE_PRIVATE_OUTER_REF (c) = 1;
13743 : }
13744 : else
13745 : notice_outer = false;
13746 12231 : goto do_add;
13747 5536 : case OMP_CLAUSE_SHARED:
13748 5536 : flags = GOVD_SHARED | GOVD_EXPLICIT;
13749 5536 : goto do_add;
13750 7963 : case OMP_CLAUSE_FIRSTPRIVATE:
13751 7963 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
13752 7963 : check_non_private = "firstprivate";
13753 7963 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13754 : {
13755 380 : gcc_assert (code == OMP_TARGET);
13756 : flags |= GOVD_FIRSTPRIVATE_IMPLICIT;
13757 : }
13758 7963 : goto do_add;
13759 7332 : case OMP_CLAUSE_LASTPRIVATE:
13760 7332 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13761 496 : switch (code)
13762 : {
13763 25 : case OMP_DISTRIBUTE:
13764 25 : error_at (OMP_CLAUSE_LOCATION (c),
13765 : "conditional %<lastprivate%> clause on "
13766 : "%qs construct", "distribute");
13767 25 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13768 25 : break;
13769 13 : case OMP_TASKLOOP:
13770 13 : error_at (OMP_CLAUSE_LOCATION (c),
13771 : "conditional %<lastprivate%> clause on "
13772 : "%qs construct", "taskloop");
13773 13 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13774 13 : break;
13775 : default:
13776 : break;
13777 : }
13778 7332 : flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
13779 7332 : if (code != OMP_LOOP)
13780 6981 : check_non_private = "lastprivate";
13781 7332 : decl = OMP_CLAUSE_DECL (c);
13782 7332 : if (error_operand_p (decl))
13783 0 : goto do_add;
13784 7332 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
13785 7332 : && !lang_hooks.decls.omp_scalar_p (decl, true))
13786 : {
13787 5 : error_at (OMP_CLAUSE_LOCATION (c),
13788 : "non-scalar variable %qD in conditional "
13789 : "%<lastprivate%> clause", decl);
13790 5 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13791 : }
13792 7332 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13793 453 : flags |= GOVD_LASTPRIVATE_CONDITIONAL;
13794 7332 : omp_lastprivate_for_combined_outer_constructs (outer_ctx, decl,
13795 : false);
13796 7332 : goto do_add;
13797 15218 : case OMP_CLAUSE_REDUCTION:
13798 15218 : if (OMP_CLAUSE_REDUCTION_TASK (c))
13799 : {
13800 595 : if (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
13801 : {
13802 408 : if (nowait == -1)
13803 293 : nowait = omp_find_clause (*list_p,
13804 293 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
13805 408 : if (nowait
13806 15 : && (outer_ctx == NULL
13807 0 : || outer_ctx->region_type != ORT_COMBINED_PARALLEL))
13808 : {
13809 15 : error_at (OMP_CLAUSE_LOCATION (c),
13810 : "%<task%> reduction modifier on a construct "
13811 : "with a %<nowait%> clause");
13812 15 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13813 : }
13814 : }
13815 187 : else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL)
13816 : {
13817 40 : error_at (OMP_CLAUSE_LOCATION (c),
13818 : "invalid %<task%> reduction modifier on construct "
13819 : "other than %<parallel%>, %qs, %<sections%> or "
13820 20 : "%<scope%>", lang_GNU_Fortran () ? "do" : "for");
13821 20 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13822 : }
13823 : }
13824 15218 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
13825 831 : switch (code)
13826 : {
13827 4 : case OMP_SECTIONS:
13828 4 : error_at (OMP_CLAUSE_LOCATION (c),
13829 : "%<inscan%> %<reduction%> clause on "
13830 : "%qs construct", "sections");
13831 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13832 4 : break;
13833 4 : case OMP_PARALLEL:
13834 4 : error_at (OMP_CLAUSE_LOCATION (c),
13835 : "%<inscan%> %<reduction%> clause on "
13836 : "%qs construct", "parallel");
13837 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13838 4 : break;
13839 4 : case OMP_TEAMS:
13840 4 : error_at (OMP_CLAUSE_LOCATION (c),
13841 : "%<inscan%> %<reduction%> clause on "
13842 : "%qs construct", "teams");
13843 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13844 4 : break;
13845 4 : case OMP_TASKLOOP:
13846 4 : error_at (OMP_CLAUSE_LOCATION (c),
13847 : "%<inscan%> %<reduction%> clause on "
13848 : "%qs construct", "taskloop");
13849 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13850 4 : break;
13851 4 : case OMP_SCOPE:
13852 4 : error_at (OMP_CLAUSE_LOCATION (c),
13853 : "%<inscan%> %<reduction%> clause on "
13854 : "%qs construct", "scope");
13855 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13856 4 : break;
13857 : default:
13858 : break;
13859 : }
13860 : /* FALLTHRU */
13861 17822 : case OMP_CLAUSE_IN_REDUCTION:
13862 17822 : case OMP_CLAUSE_TASK_REDUCTION:
13863 17822 : flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
13864 : /* OpenACC permits reductions on private variables. */
13865 17822 : if (!(region_type & ORT_ACC)
13866 : /* taskgroup is actually not a worksharing region. */
13867 12303 : && code != OMP_TASKGROUP)
13868 11773 : check_non_private = omp_clause_code_name[OMP_CLAUSE_CODE (c)];
13869 17822 : decl = OMP_CLAUSE_DECL (c);
13870 17822 : if (TREE_CODE (decl) == MEM_REF)
13871 : {
13872 2539 : tree type = TREE_TYPE (decl);
13873 2539 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
13874 2539 : gimplify_ctxp->into_ssa = false;
13875 2539 : if (gimplify_expr (&TYPE_MAX_VALUE (TYPE_DOMAIN (type)), pre_p,
13876 : NULL, is_gimple_val, fb_rvalue, false)
13877 : == GS_ERROR)
13878 : {
13879 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13880 0 : remove = true;
13881 0 : break;
13882 : }
13883 2539 : gimplify_ctxp->into_ssa = saved_into_ssa;
13884 2539 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
13885 2539 : if (DECL_P (v))
13886 : {
13887 571 : omp_firstprivatize_variable (ctx, v);
13888 571 : omp_notice_variable (ctx, v, true);
13889 : }
13890 2539 : decl = TREE_OPERAND (decl, 0);
13891 2539 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
13892 : {
13893 477 : gimplify_ctxp->into_ssa = false;
13894 477 : if (gimplify_expr (&TREE_OPERAND (decl, 1), pre_p,
13895 : NULL, is_gimple_val, fb_rvalue, false)
13896 : == GS_ERROR)
13897 : {
13898 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13899 0 : remove = true;
13900 0 : break;
13901 : }
13902 477 : gimplify_ctxp->into_ssa = saved_into_ssa;
13903 477 : v = TREE_OPERAND (decl, 1);
13904 477 : if (DECL_P (v))
13905 : {
13906 477 : omp_firstprivatize_variable (ctx, v);
13907 477 : omp_notice_variable (ctx, v, true);
13908 : }
13909 477 : decl = TREE_OPERAND (decl, 0);
13910 : }
13911 2539 : if (TREE_CODE (decl) == ADDR_EXPR
13912 1163 : || TREE_CODE (decl) == INDIRECT_REF)
13913 1474 : decl = TREE_OPERAND (decl, 0);
13914 : }
13915 17822 : goto do_add_decl;
13916 2668 : case OMP_CLAUSE_LINEAR:
13917 2668 : if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
13918 : is_gimple_val, fb_rvalue) == GS_ERROR)
13919 : {
13920 : remove = true;
13921 : break;
13922 : }
13923 : else
13924 : {
13925 2668 : if (code == OMP_SIMD
13926 2668 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
13927 : {
13928 1154 : struct gimplify_omp_ctx *octx = outer_ctx;
13929 1154 : if (octx
13930 741 : && octx->region_type == ORT_WORKSHARE
13931 500 : && octx->combined_loop
13932 500 : && !octx->distribute)
13933 : {
13934 492 : if (octx->outer_context
13935 430 : && (octx->outer_context->region_type
13936 : == ORT_COMBINED_PARALLEL))
13937 393 : octx = octx->outer_context->outer_context;
13938 : else
13939 : octx = octx->outer_context;
13940 : }
13941 905 : if (octx
13942 316 : && octx->region_type == ORT_WORKSHARE
13943 16 : && octx->combined_loop
13944 16 : && octx->distribute)
13945 : {
13946 16 : error_at (OMP_CLAUSE_LOCATION (c),
13947 : "%<linear%> clause for variable other than "
13948 : "loop iterator specified on construct "
13949 : "combined with %<distribute%>");
13950 16 : remove = true;
13951 16 : break;
13952 : }
13953 : }
13954 : /* For combined #pragma omp parallel for simd, need to put
13955 : lastprivate and perhaps firstprivate too on the
13956 : parallel. Similarly for #pragma omp for simd. */
13957 : struct gimplify_omp_ctx *octx = outer_ctx;
13958 : bool taskloop_seen = false;
13959 : decl = NULL_TREE;
13960 3443 : do
13961 : {
13962 3443 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
13963 3443 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
13964 : break;
13965 3383 : decl = OMP_CLAUSE_DECL (c);
13966 3383 : if (error_operand_p (decl))
13967 : {
13968 : decl = NULL_TREE;
13969 : break;
13970 : }
13971 3383 : flags = GOVD_SEEN;
13972 3383 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
13973 1672 : flags |= GOVD_FIRSTPRIVATE;
13974 3383 : if (!OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
13975 3383 : flags |= GOVD_LASTPRIVATE;
13976 3383 : if (octx
13977 2506 : && octx->region_type == ORT_WORKSHARE
13978 1213 : && octx->combined_loop)
13979 : {
13980 1207 : if (octx->outer_context
13981 1037 : && (octx->outer_context->region_type
13982 : == ORT_COMBINED_PARALLEL))
13983 : octx = octx->outer_context;
13984 476 : else if (omp_check_private (octx, decl, false))
13985 : break;
13986 : }
13987 : else if (octx
13988 1299 : && (octx->region_type & ORT_TASK) != 0
13989 307 : && octx->combined_loop)
13990 : taskloop_seen = true;
13991 : else if (octx
13992 996 : && octx->region_type == ORT_COMBINED_PARALLEL
13993 301 : && ((ctx->region_type == ORT_WORKSHARE
13994 201 : && octx == outer_ctx)
13995 100 : || taskloop_seen))
13996 : flags = GOVD_SEEN | GOVD_SHARED;
13997 : else if (octx
13998 695 : && ((octx->region_type & ORT_COMBINED_TEAMS)
13999 : == ORT_COMBINED_TEAMS))
14000 : flags = GOVD_SEEN | GOVD_SHARED;
14001 540 : else if (octx
14002 540 : && octx->region_type == ORT_COMBINED_TARGET)
14003 : {
14004 195 : if (flags & GOVD_LASTPRIVATE)
14005 195 : flags = GOVD_SEEN | GOVD_MAP;
14006 : }
14007 : else
14008 : break;
14009 2071 : splay_tree_node on
14010 2071 : = splay_tree_lookup (octx->variables,
14011 : (splay_tree_key) decl);
14012 2071 : if (on && (on->value & GOVD_DATA_SHARE_CLASS) != 0)
14013 : {
14014 : octx = NULL;
14015 : break;
14016 : }
14017 2067 : omp_add_variable (octx, decl, flags);
14018 2067 : if (octx->outer_context == NULL)
14019 : break;
14020 : octx = octx->outer_context;
14021 : }
14022 : while (1);
14023 2652 : if (octx
14024 2652 : && decl
14025 2652 : && (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14026 728 : || !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
14027 1711 : omp_notice_variable (octx, decl, true);
14028 : }
14029 2652 : flags = GOVD_LINEAR | GOVD_EXPLICIT;
14030 2652 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14031 2652 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14032 : {
14033 : notice_outer = false;
14034 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
14035 : }
14036 2652 : goto do_add;
14037 :
14038 51026 : case OMP_CLAUSE_MAP:
14039 51026 : if (!grp_start_p)
14040 : {
14041 30925 : grp_start_p = list_p;
14042 30925 : grp_end = (*groups)[grpnum].grp_end;
14043 30925 : grpnum++;
14044 : }
14045 51026 : decl = OMP_CLAUSE_DECL (c);
14046 :
14047 51026 : if (error_operand_p (decl))
14048 : {
14049 : remove = true;
14050 : break;
14051 : }
14052 :
14053 51026 : if (!omp_parse_expr (addr_tokens, decl))
14054 : {
14055 : remove = true;
14056 : break;
14057 : }
14058 :
14059 51026 : if (remove)
14060 : break;
14061 51026 : if (DECL_P (decl) && outer_ctx && (region_type & ORT_ACC))
14062 : {
14063 : struct gimplify_omp_ctx *octx;
14064 1167 : for (octx = outer_ctx; octx; octx = octx->outer_context)
14065 : {
14066 1167 : if (octx->region_type != ORT_ACC_HOST_DATA)
14067 : break;
14068 12 : splay_tree_node n2
14069 12 : = splay_tree_lookup (octx->variables,
14070 : (splay_tree_key) decl);
14071 12 : if (n2)
14072 4 : error_at (OMP_CLAUSE_LOCATION (c), "variable %qE "
14073 : "declared in enclosing %<host_data%> region",
14074 4 : DECL_NAME (decl));
14075 : }
14076 : }
14077 :
14078 51026 : map_descriptor = false;
14079 :
14080 : /* This condition checks if we're mapping an array descriptor that
14081 : isn't inside a derived type -- these have special handling, and
14082 : are not handled as structs in omp_build_struct_sibling_lists.
14083 : See that function for further details. */
14084 51026 : if (*grp_start_p != grp_end
14085 34059 : && OMP_CLAUSE_CHAIN (*grp_start_p)
14086 85085 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
14087 : {
14088 16993 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
14089 16993 : if (omp_map_clause_descriptor_p (grp_mid)
14090 32159 : && DECL_P (OMP_CLAUSE_DECL (grp_mid)))
14091 : map_descriptor = true;
14092 : }
14093 34033 : else if (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP
14094 34033 : && (OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_RELEASE
14095 33290 : || OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_DELETE)
14096 34954 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (grp_end))
14097 : map_descriptor = true;
14098 :
14099 : /* Adding the decl for a struct access: we haven't created
14100 : GOMP_MAP_STRUCT nodes yet, so this statement needs to predict
14101 : whether they will be created in gimplify_adjust_omp_clauses.
14102 : NOTE: Technically we should probably look through DECL_VALUE_EXPR
14103 : here because something that looks like a DECL_P may actually be a
14104 : struct access, e.g. variables in a lambda closure
14105 : (__closure->__foo) or class members (this->foo). Currently in both
14106 : those cases we map the whole of the containing object (directly in
14107 : the C++ FE) though, so struct nodes are not created. */
14108 51026 : if (c == grp_end
14109 30925 : && addr_tokens[0]->type == STRUCTURE_BASE
14110 8362 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14111 59388 : && !map_descriptor)
14112 : {
14113 5558 : gcc_assert (addr_tokens[1]->type == ACCESS_METHOD);
14114 : /* If we got to this struct via a chain of pointers, maybe we
14115 : want to map it implicitly instead. */
14116 5558 : if (omp_access_chain_p (addr_tokens, 1))
14117 : break;
14118 5398 : omp_mapping_group *wholestruct;
14119 5398 : if (!(region_type & ORT_ACC)
14120 9521 : && omp_mapped_by_containing_struct (grpmap,
14121 4123 : OMP_CLAUSE_DECL (c),
14122 : &wholestruct))
14123 : break;
14124 5162 : decl = addr_tokens[1]->expr;
14125 5162 : if (splay_tree_lookup (ctx->variables, (splay_tree_key) decl))
14126 : break;
14127 : /* Standalone attach or detach clauses for a struct element
14128 : should not inhibit implicit mapping of the whole struct. */
14129 2950 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
14130 2950 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
14131 : break;
14132 2800 : flags = GOVD_MAP | GOVD_EXPLICIT;
14133 :
14134 2800 : gcc_assert (addr_tokens[1]->u.access_kind != ACCESS_DIRECT
14135 : || TREE_ADDRESSABLE (decl));
14136 2800 : goto do_add_decl;
14137 : }
14138 :
14139 45468 : if (!DECL_P (decl))
14140 : {
14141 21007 : tree d = decl, *pd;
14142 21007 : if (TREE_CODE (d) == ARRAY_REF)
14143 : {
14144 5014 : while (TREE_CODE (d) == ARRAY_REF)
14145 2564 : d = TREE_OPERAND (d, 0);
14146 2450 : if (TREE_CODE (d) == COMPONENT_REF
14147 2450 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
14148 : decl = d;
14149 : }
14150 21007 : pd = &OMP_CLAUSE_DECL (c);
14151 21007 : if (d == decl
14152 18603 : && TREE_CODE (decl) == INDIRECT_REF
14153 13901 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
14154 1069 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
14155 : == REFERENCE_TYPE)
14156 21658 : && (OMP_CLAUSE_MAP_KIND (c)
14157 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
14158 : {
14159 647 : pd = &TREE_OPERAND (decl, 0);
14160 647 : decl = TREE_OPERAND (decl, 0);
14161 : }
14162 :
14163 21007 : if (addr_tokens[0]->type == STRUCTURE_BASE
14164 11371 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14165 11371 : && addr_tokens[1]->type == ACCESS_METHOD
14166 11371 : && (addr_tokens[1]->u.access_kind == ACCESS_POINTER
14167 10874 : || (addr_tokens[1]->u.access_kind
14168 : == ACCESS_POINTER_OFFSET))
14169 21586 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)))
14170 : {
14171 0 : tree base = addr_tokens[1]->expr;
14172 0 : splay_tree_node n
14173 0 : = splay_tree_lookup (ctx->variables,
14174 : (splay_tree_key) base);
14175 0 : n->value |= GOVD_SEEN;
14176 : }
14177 :
14178 21007 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
14179 : {
14180 : /* Don't gimplify *pd fully at this point, as the base
14181 : will need to be adjusted during omp lowering. */
14182 88 : auto_vec<tree, 10> expr_stack;
14183 88 : tree *p = pd;
14184 88 : while (handled_component_p (*p)
14185 : || TREE_CODE (*p) == INDIRECT_REF
14186 : || TREE_CODE (*p) == ADDR_EXPR
14187 : || TREE_CODE (*p) == MEM_REF
14188 224 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
14189 : {
14190 136 : expr_stack.safe_push (*p);
14191 136 : p = &TREE_OPERAND (*p, 0);
14192 : }
14193 312 : for (int i = expr_stack.length () - 1; i >= 0; i--)
14194 : {
14195 136 : tree t = expr_stack[i];
14196 136 : if (TREE_CODE (t) == ARRAY_REF
14197 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14198 : {
14199 56 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14200 : {
14201 56 : tree low = unshare_expr (array_ref_low_bound (t));
14202 56 : if (!is_gimple_min_invariant (low))
14203 : {
14204 0 : TREE_OPERAND (t, 2) = low;
14205 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14206 : pre_p, NULL,
14207 : is_gimple_reg,
14208 : fb_rvalue) == GS_ERROR)
14209 0 : remove = true;
14210 : }
14211 : }
14212 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14213 : NULL, is_gimple_reg,
14214 : fb_rvalue) == GS_ERROR)
14215 0 : remove = true;
14216 56 : if (TREE_OPERAND (t, 3) == NULL_TREE)
14217 : {
14218 56 : tree elmt_size = array_ref_element_size (t);
14219 56 : if (!is_gimple_min_invariant (elmt_size))
14220 : {
14221 0 : elmt_size = unshare_expr (elmt_size);
14222 0 : tree elmt_type
14223 0 : = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t,
14224 : 0)));
14225 0 : tree factor
14226 0 : = size_int (TYPE_ALIGN_UNIT (elmt_type));
14227 0 : elmt_size
14228 0 : = size_binop (EXACT_DIV_EXPR, elmt_size,
14229 : factor);
14230 0 : TREE_OPERAND (t, 3) = elmt_size;
14231 0 : if (gimplify_expr (&TREE_OPERAND (t, 3),
14232 : pre_p, NULL,
14233 : is_gimple_reg,
14234 : fb_rvalue) == GS_ERROR)
14235 0 : remove = true;
14236 : }
14237 : }
14238 0 : else if (gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
14239 : NULL, is_gimple_reg,
14240 : fb_rvalue) == GS_ERROR)
14241 0 : remove = true;
14242 : }
14243 80 : else if (TREE_CODE (t) == COMPONENT_REF)
14244 : {
14245 0 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14246 : {
14247 0 : tree offset = component_ref_field_offset (t);
14248 0 : if (!is_gimple_min_invariant (offset))
14249 : {
14250 0 : offset = unshare_expr (offset);
14251 0 : tree field = TREE_OPERAND (t, 1);
14252 0 : tree factor
14253 0 : = size_int (DECL_OFFSET_ALIGN (field)
14254 : / BITS_PER_UNIT);
14255 0 : offset = size_binop (EXACT_DIV_EXPR, offset,
14256 : factor);
14257 0 : TREE_OPERAND (t, 2) = offset;
14258 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14259 : pre_p, NULL,
14260 : is_gimple_reg,
14261 : fb_rvalue) == GS_ERROR)
14262 0 : remove = true;
14263 : }
14264 : }
14265 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14266 : NULL, is_gimple_reg,
14267 : fb_rvalue) == GS_ERROR)
14268 0 : remove = true;
14269 : }
14270 : }
14271 224 : for (; expr_stack.length () > 0; )
14272 : {
14273 136 : tree t = expr_stack.pop ();
14274 :
14275 136 : if (TREE_CODE (t) == ARRAY_REF
14276 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14277 : {
14278 56 : if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))
14279 56 : && gimplify_expr (&TREE_OPERAND (t, 1), pre_p,
14280 : NULL, is_gimple_val,
14281 : fb_rvalue) == GS_ERROR)
14282 144 : remove = true;
14283 : }
14284 : }
14285 88 : }
14286 : break;
14287 : }
14288 :
14289 24461 : if ((code == OMP_TARGET
14290 : || code == OMP_TARGET_DATA
14291 : || code == OMP_TARGET_ENTER_DATA
14292 14223 : || code == OMP_TARGET_EXIT_DATA)
14293 25097 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14294 : {
14295 : /* If we have attach/detach but the decl we have is a pointer to
14296 : pointer, we're probably mapping the "base level" array
14297 : implicitly. Make sure we don't add the decl as if we mapped
14298 : it explicitly. That is,
14299 :
14300 : int **arr;
14301 : [...]
14302 : #pragma omp target map(arr[a][b:c])
14303 :
14304 : should *not* map "arr" explicitly. That way we get a
14305 : zero-length "alloc" mapping for it, and assuming it's been
14306 : mapped by some previous directive, etc., things work as they
14307 : should. */
14308 :
14309 213 : tree basetype = TREE_TYPE (addr_tokens[0]->expr);
14310 :
14311 213 : if (TREE_CODE (basetype) == REFERENCE_TYPE)
14312 34 : basetype = TREE_TYPE (basetype);
14313 :
14314 213 : if (code == OMP_TARGET
14315 54 : && addr_tokens[0]->type == ARRAY_BASE
14316 54 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14317 54 : && TREE_CODE (basetype) == POINTER_TYPE
14318 267 : && TREE_CODE (TREE_TYPE (basetype)) == POINTER_TYPE)
14319 : break;
14320 : }
14321 :
14322 24439 : flags = GOVD_MAP | GOVD_EXPLICIT;
14323 24439 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
14324 24304 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM
14325 23800 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TO
14326 48209 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TOFROM)
14327 : flags |= GOVD_MAP_ALWAYS_TO;
14328 :
14329 24439 : goto do_add;
14330 :
14331 374 : case OMP_CLAUSE_AFFINITY:
14332 374 : gimplify_omp_affinity (list_p, pre_p);
14333 374 : remove = true;
14334 374 : break;
14335 8 : case OMP_CLAUSE_DOACROSS:
14336 8 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
14337 : {
14338 4 : tree deps = OMP_CLAUSE_DECL (c);
14339 8 : while (deps && TREE_CODE (deps) == TREE_LIST)
14340 : {
14341 4 : if (TREE_CODE (TREE_PURPOSE (deps)) == TRUNC_DIV_EXPR
14342 4 : && DECL_P (TREE_OPERAND (TREE_PURPOSE (deps), 1)))
14343 0 : gimplify_expr (&TREE_OPERAND (TREE_PURPOSE (deps), 1),
14344 : pre_p, NULL, is_gimple_val, fb_rvalue);
14345 4 : deps = TREE_CHAIN (deps);
14346 : }
14347 : }
14348 : else
14349 4 : gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
14350 : == OMP_CLAUSE_DOACROSS_SOURCE);
14351 : break;
14352 2205 : case OMP_CLAUSE_DEPEND:
14353 2205 : if (handled_depend_iterators == -1)
14354 1903 : handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
14355 2205 : if (handled_depend_iterators)
14356 : {
14357 347 : if (handled_depend_iterators == 2)
14358 0 : remove = true;
14359 : break;
14360 : }
14361 1858 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
14362 : {
14363 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
14364 : NULL, is_gimple_val, fb_rvalue);
14365 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
14366 : }
14367 1858 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
14368 : {
14369 : remove = true;
14370 : break;
14371 : }
14372 1858 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
14373 : {
14374 1827 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
14375 1827 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
14376 : is_gimple_val, fb_rvalue) == GS_ERROR)
14377 : {
14378 : remove = true;
14379 : break;
14380 : }
14381 : }
14382 1858 : if (code == OMP_TASK)
14383 1400 : ctx->has_depend = true;
14384 : break;
14385 :
14386 8319 : case OMP_CLAUSE_TO:
14387 8319 : case OMP_CLAUSE_FROM:
14388 8319 : case OMP_CLAUSE__CACHE_:
14389 8319 : decl = OMP_CLAUSE_DECL (c);
14390 8319 : if (error_operand_p (decl))
14391 : {
14392 : remove = true;
14393 : break;
14394 : }
14395 8319 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14396 7659 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
14397 796 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
14398 8319 : gimple_seq *seq_p;
14399 8319 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
14400 8319 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
14401 : is_gimple_val, fb_rvalue) == GS_ERROR)
14402 : {
14403 0 : remove = true;
14404 0 : exit_omp_iterator_loop_context (c);
14405 0 : break;
14406 : }
14407 8319 : if (!DECL_P (decl))
14408 : {
14409 2131 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
14410 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
14411 0 : remove = true;
14412 2131 : exit_omp_iterator_loop_context (c);
14413 2131 : break;
14414 : }
14415 6188 : exit_omp_iterator_loop_context (c);
14416 6188 : goto do_notice;
14417 :
14418 135 : case OMP_CLAUSE__MAPPER_BINDING_:
14419 135 : {
14420 135 : tree name = OMP_CLAUSE__MAPPER_BINDING__ID (c);
14421 135 : tree var = OMP_CLAUSE__MAPPER_BINDING__DECL (c);
14422 135 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (var));
14423 135 : tree fndecl = OMP_CLAUSE__MAPPER_BINDING__MAPPER (c);
14424 135 : ctx->implicit_mappers->put ({ name, type }, fndecl);
14425 135 : remove = true;
14426 135 : break;
14427 : }
14428 :
14429 2118 : case OMP_CLAUSE_USE_DEVICE_PTR:
14430 2118 : case OMP_CLAUSE_USE_DEVICE_ADDR:
14431 2118 : flags = GOVD_EXPLICIT;
14432 2118 : goto do_add;
14433 :
14434 557 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14435 557 : decl = OMP_CLAUSE_DECL (c);
14436 557 : while (TREE_CODE (decl) == INDIRECT_REF
14437 606 : || TREE_CODE (decl) == ARRAY_REF)
14438 49 : decl = TREE_OPERAND (decl, 0);
14439 557 : flags = GOVD_EXPLICIT;
14440 557 : goto do_add_decl;
14441 :
14442 500 : case OMP_CLAUSE_IS_DEVICE_PTR:
14443 500 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
14444 500 : goto do_add;
14445 :
14446 62961 : do_add:
14447 62961 : decl = OMP_CLAUSE_DECL (c);
14448 84140 : do_add_decl:
14449 84140 : if (error_operand_p (decl))
14450 : {
14451 : remove = true;
14452 : break;
14453 : }
14454 84132 : if (DECL_NAME (decl) == NULL_TREE && (flags & GOVD_SHARED) == 0)
14455 : {
14456 1755 : tree t = omp_member_access_dummy_var (decl);
14457 1755 : if (t)
14458 : {
14459 668 : tree v = DECL_VALUE_EXPR (decl);
14460 668 : DECL_NAME (decl) = DECL_NAME (TREE_OPERAND (v, 1));
14461 668 : if (outer_ctx)
14462 140 : omp_notice_variable (outer_ctx, t, true);
14463 : }
14464 : }
14465 84132 : if (code == OACC_DATA
14466 2402 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14467 86534 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14468 307 : flags |= GOVD_MAP_0LEN_ARRAY;
14469 84132 : omp_add_variable (ctx, decl, flags);
14470 84132 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14471 68914 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
14472 66840 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
14473 86736 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
14474 : {
14475 2091 : struct gimplify_omp_ctx *pctx
14476 2151 : = code == OMP_TARGET ? outer_ctx : ctx;
14477 2151 : if (pctx)
14478 2121 : omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
14479 : GOVD_LOCAL | GOVD_SEEN);
14480 2121 : if (pctx
14481 2121 : && OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
14482 632 : && walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
14483 : find_decl_expr,
14484 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14485 : NULL) == NULL_TREE)
14486 208 : omp_add_variable (pctx,
14487 208 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14488 : GOVD_LOCAL | GOVD_SEEN);
14489 2151 : gimplify_omp_ctxp = pctx;
14490 2151 : push_gimplify_context ();
14491 :
14492 2151 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
14493 2151 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
14494 :
14495 2151 : gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
14496 2151 : &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
14497 2151 : pop_gimplify_context
14498 2151 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)));
14499 2151 : push_gimplify_context ();
14500 4302 : gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
14501 2151 : &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
14502 2151 : pop_gimplify_context
14503 2151 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
14504 2151 : OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
14505 2151 : OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
14506 :
14507 2151 : gimplify_omp_ctxp = outer_ctx;
14508 : }
14509 81981 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
14510 81981 : && OMP_CLAUSE_LASTPRIVATE_STMT (c))
14511 : {
14512 303 : gimplify_omp_ctxp = ctx;
14513 303 : push_gimplify_context ();
14514 303 : if (TREE_CODE (OMP_CLAUSE_LASTPRIVATE_STMT (c)) != BIND_EXPR)
14515 : {
14516 303 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14517 : NULL, NULL);
14518 303 : TREE_SIDE_EFFECTS (bind) = 1;
14519 303 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LASTPRIVATE_STMT (c);
14520 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = bind;
14521 : }
14522 606 : gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c),
14523 303 : &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
14524 303 : pop_gimplify_context
14525 303 : (gimple_seq_first_stmt (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)));
14526 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL_TREE;
14527 :
14528 303 : gimplify_omp_ctxp = outer_ctx;
14529 : }
14530 81678 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14531 81678 : && OMP_CLAUSE_LINEAR_STMT (c))
14532 : {
14533 60 : gimplify_omp_ctxp = ctx;
14534 60 : push_gimplify_context ();
14535 60 : if (TREE_CODE (OMP_CLAUSE_LINEAR_STMT (c)) != BIND_EXPR)
14536 : {
14537 60 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14538 : NULL, NULL);
14539 60 : TREE_SIDE_EFFECTS (bind) = 1;
14540 60 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LINEAR_STMT (c);
14541 60 : OMP_CLAUSE_LINEAR_STMT (c) = bind;
14542 : }
14543 120 : gimplify_and_add (OMP_CLAUSE_LINEAR_STMT (c),
14544 60 : &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
14545 60 : pop_gimplify_context
14546 60 : (gimple_seq_first_stmt (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)));
14547 60 : OMP_CLAUSE_LINEAR_STMT (c) = NULL_TREE;
14548 :
14549 60 : gimplify_omp_ctxp = outer_ctx;
14550 : }
14551 84132 : if (notice_outer)
14552 72008 : goto do_notice;
14553 : break;
14554 :
14555 906 : case OMP_CLAUSE_COPYIN:
14556 906 : case OMP_CLAUSE_COPYPRIVATE:
14557 906 : decl = OMP_CLAUSE_DECL (c);
14558 906 : if (error_operand_p (decl))
14559 : {
14560 : remove = true;
14561 : break;
14562 : }
14563 906 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
14564 : && !remove
14565 906 : && !omp_check_private (ctx, decl, true))
14566 : {
14567 35 : remove = true;
14568 35 : if (is_global_var (decl))
14569 : {
14570 30 : if (DECL_THREAD_LOCAL_P (decl))
14571 : remove = false;
14572 10 : else if (DECL_HAS_VALUE_EXPR_P (decl))
14573 : {
14574 2 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
14575 :
14576 2 : if (value
14577 2 : && DECL_P (value)
14578 4 : && DECL_THREAD_LOCAL_P (value))
14579 : remove = false;
14580 : }
14581 : }
14582 : if (remove)
14583 13 : error_at (OMP_CLAUSE_LOCATION (c),
14584 : "copyprivate variable %qE is not threadprivate"
14585 13 : " or private in outer context", DECL_NAME (decl));
14586 : }
14587 79102 : do_notice:
14588 79102 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14589 63884 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
14590 55921 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
14591 30513 : && outer_ctx
14592 17547 : && ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
14593 16208 : || (region_type == ORT_WORKSHARE
14594 3884 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14595 1087 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
14596 912 : || code == OMP_LOOP)))
14597 81047 : && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
14598 857 : || (code == OMP_LOOP
14599 138 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14600 138 : && ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
14601 : == ORT_COMBINED_TEAMS))))
14602 : {
14603 1209 : splay_tree_node on
14604 1209 : = splay_tree_lookup (outer_ctx->variables,
14605 : (splay_tree_key)decl);
14606 1209 : if (on == NULL || (on->value & GOVD_DATA_SHARE_CLASS) == 0)
14607 : {
14608 891 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14609 705 : && TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14610 1003 : && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
14611 56 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
14612 0 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
14613 : == POINTER_TYPE))))
14614 56 : omp_firstprivatize_variable (outer_ctx, decl);
14615 : else
14616 : {
14617 835 : omp_add_variable (outer_ctx, decl,
14618 : GOVD_SEEN | GOVD_SHARED);
14619 835 : if (outer_ctx->outer_context)
14620 235 : omp_notice_variable (outer_ctx->outer_context, decl,
14621 : true);
14622 : }
14623 : }
14624 : }
14625 78502 : if (outer_ctx)
14626 29585 : omp_notice_variable (outer_ctx, decl, true);
14627 79102 : if (check_non_private
14628 26717 : && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
14629 4747 : && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
14630 1641 : || decl == OMP_CLAUSE_DECL (c)
14631 224 : || (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14632 224 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14633 : == ADDR_EXPR
14634 103 : || (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14635 : == POINTER_PLUS_EXPR
14636 22 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND
14637 : (OMP_CLAUSE_DECL (c), 0), 0))
14638 : == ADDR_EXPR)))))
14639 83761 : && omp_check_private (ctx, decl, false))
14640 : {
14641 58 : error ("%s variable %qE is private in outer context",
14642 29 : check_non_private, DECL_NAME (decl));
14643 29 : remove = true;
14644 : }
14645 : break;
14646 :
14647 190 : case OMP_CLAUSE_DETACH:
14648 190 : flags = GOVD_FIRSTPRIVATE | GOVD_SEEN;
14649 190 : goto do_add;
14650 :
14651 4102 : case OMP_CLAUSE_IF:
14652 4102 : if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK
14653 4102 : && OMP_CLAUSE_IF_MODIFIER (c) != code)
14654 : {
14655 : const char *p[2];
14656 168 : for (int i = 0; i < 2; i++)
14657 112 : switch (i ? OMP_CLAUSE_IF_MODIFIER (c) : code)
14658 : {
14659 8 : case VOID_CST: p[i] = "cancel"; break;
14660 24 : case OMP_PARALLEL: p[i] = "parallel"; break;
14661 4 : case OMP_SIMD: p[i] = "simd"; break;
14662 12 : case OMP_TASK: p[i] = "task"; break;
14663 12 : case OMP_TASKLOOP: p[i] = "taskloop"; break;
14664 8 : case OMP_TARGET_DATA: p[i] = "target data"; break;
14665 12 : case OMP_TARGET: p[i] = "target"; break;
14666 12 : case OMP_TARGET_UPDATE: p[i] = "target update"; break;
14667 8 : case OMP_TARGET_ENTER_DATA:
14668 8 : p[i] = "target enter data"; break;
14669 12 : case OMP_TARGET_EXIT_DATA: p[i] = "target exit data"; break;
14670 0 : default: gcc_unreachable ();
14671 : }
14672 56 : error_at (OMP_CLAUSE_LOCATION (c),
14673 : "expected %qs %<if%> clause modifier rather than %qs",
14674 : p[0], p[1]);
14675 56 : remove = true;
14676 : }
14677 : /* Fall through. */
14678 :
14679 4812 : case OMP_CLAUSE_SELF:
14680 4812 : case OMP_CLAUSE_FINAL:
14681 4812 : OMP_CLAUSE_OPERAND (c, 0)
14682 9624 : = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
14683 : /* Fall through. */
14684 :
14685 5715 : case OMP_CLAUSE_NUM_TEAMS:
14686 5715 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
14687 903 : && OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14688 5960 : && !is_gimple_min_invariant (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14689 : {
14690 208 : if (error_operand_p (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14691 : {
14692 : remove = true;
14693 : break;
14694 : }
14695 208 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14696 416 : = get_initialized_tmp_var (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c),
14697 : pre_p, NULL, true);
14698 : }
14699 : /* Fall through. */
14700 :
14701 21796 : case OMP_CLAUSE_SCHEDULE:
14702 21796 : case OMP_CLAUSE_NUM_THREADS:
14703 21796 : case OMP_CLAUSE_THREAD_LIMIT:
14704 21796 : case OMP_CLAUSE_DIST_SCHEDULE:
14705 21796 : case OMP_CLAUSE_DEVICE:
14706 21796 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14707 21796 : && OMP_CLAUSE_DEVICE_ANCESTOR (c))
14708 : {
14709 125 : if (code != OMP_TARGET)
14710 : {
14711 20 : error_at (OMP_CLAUSE_LOCATION (c),
14712 : "%<device%> clause with %<ancestor%> is only "
14713 : "allowed on %<target%> construct");
14714 20 : remove = true;
14715 20 : break;
14716 : }
14717 :
14718 105 : tree clauses = *orig_list_p;
14719 330 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
14720 236 : if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE
14721 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE
14722 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE
14723 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP
14724 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP
14725 : )
14726 : {
14727 11 : error_at (OMP_CLAUSE_LOCATION (c),
14728 : "with %<ancestor%>, only the %<device%>, "
14729 : "%<firstprivate%>, %<private%>, %<defaultmap%>, "
14730 : "and %<map%> clauses may appear on the "
14731 : "construct");
14732 11 : remove = true;
14733 11 : break;
14734 : }
14735 : }
14736 21671 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14737 21671 : && code == OMP_DISPATCH)
14738 : {
14739 272 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
14740 272 : gimplify_ctxp->into_ssa = false;
14741 272 : if (gimplify_expr (&OMP_CLAUSE_DEVICE_ID (c), pre_p, NULL,
14742 : is_gimple_val, fb_rvalue)
14743 : == GS_ERROR)
14744 : remove = true;
14745 272 : else if (DECL_P (OMP_CLAUSE_DEVICE_ID (c)))
14746 55 : omp_add_variable (ctx, OMP_CLAUSE_DEVICE_ID (c),
14747 : GOVD_SHARED | GOVD_SEEN);
14748 272 : gimplify_ctxp->into_ssa = saved_into_ssa;
14749 272 : break;
14750 : }
14751 : /* Fall through. */
14752 :
14753 31245 : case OMP_CLAUSE_PRIORITY:
14754 31245 : case OMP_CLAUSE_GRAINSIZE:
14755 31245 : case OMP_CLAUSE_NUM_TASKS:
14756 31245 : case OMP_CLAUSE_FILTER:
14757 31245 : case OMP_CLAUSE_HINT:
14758 31245 : case OMP_CLAUSE_ASYNC:
14759 31245 : case OMP_CLAUSE_WAIT:
14760 31245 : case OMP_CLAUSE_NUM_GANGS:
14761 31245 : case OMP_CLAUSE_NUM_WORKERS:
14762 31245 : case OMP_CLAUSE_VECTOR_LENGTH:
14763 31245 : case OMP_CLAUSE_WORKER:
14764 31245 : case OMP_CLAUSE_VECTOR:
14765 31245 : if (OMP_CLAUSE_OPERAND (c, 0)
14766 31245 : && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0)))
14767 : {
14768 7774 : if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0)))
14769 : {
14770 : remove = true;
14771 : break;
14772 : }
14773 : /* All these clauses care about value, not a particular decl,
14774 : so try to force it into a SSA_NAME or fresh temporary. */
14775 7767 : OMP_CLAUSE_OPERAND (c, 0)
14776 15534 : = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0),
14777 : pre_p, NULL, true);
14778 : }
14779 : break;
14780 :
14781 2332 : case OMP_CLAUSE_GANG:
14782 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
14783 : is_gimple_val, fb_rvalue) == GS_ERROR)
14784 0 : remove = true;
14785 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL,
14786 : is_gimple_val, fb_rvalue) == GS_ERROR)
14787 0 : remove = true;
14788 : break;
14789 :
14790 13093 : case OMP_CLAUSE_NOWAIT:
14791 13093 : nowait = 1;
14792 13093 : break;
14793 :
14794 72 : case OMP_CLAUSE_USES_ALLOCATORS:
14795 72 : sorry_at (OMP_CLAUSE_LOCATION (c), "%<uses_allocators%> clause");
14796 72 : remove = 1;
14797 72 : break;
14798 :
14799 : case OMP_CLAUSE_ORDERED:
14800 : case OMP_CLAUSE_UNTIED:
14801 : case OMP_CLAUSE_COLLAPSE:
14802 : case OMP_CLAUSE_TILE:
14803 : case OMP_CLAUSE_AUTO:
14804 : case OMP_CLAUSE_SEQ:
14805 : case OMP_CLAUSE_INDEPENDENT:
14806 : case OMP_CLAUSE_MERGEABLE:
14807 : case OMP_CLAUSE_PROC_BIND:
14808 : case OMP_CLAUSE_SAFELEN:
14809 : case OMP_CLAUSE_SIMDLEN:
14810 : case OMP_CLAUSE_NOGROUP:
14811 : case OMP_CLAUSE_THREADS:
14812 : case OMP_CLAUSE_SIMD:
14813 : case OMP_CLAUSE_BIND:
14814 : case OMP_CLAUSE_IF_PRESENT:
14815 : case OMP_CLAUSE_FINALIZE:
14816 : case OMP_CLAUSE_INTEROP:
14817 : case OMP_CLAUSE_INIT:
14818 : case OMP_CLAUSE_USE:
14819 : case OMP_CLAUSE_DESTROY:
14820 : case OMP_CLAUSE_DEVICE_TYPE:
14821 : break;
14822 :
14823 52 : case OMP_CLAUSE_DYN_GROUPPRIVATE:
14824 52 : remove = true;
14825 52 : sorry_at (OMP_CLAUSE_LOCATION (c),"%<dyn_groupprivate%> clause");
14826 52 : break;
14827 :
14828 3976 : case OMP_CLAUSE_ORDER:
14829 3976 : ctx->order_concurrent = true;
14830 3976 : break;
14831 :
14832 1010 : case OMP_CLAUSE_DEFAULTMAP:
14833 1010 : enum gimplify_defaultmap_kind gdmkmin, gdmkmax;
14834 1010 : switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c))
14835 : {
14836 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
14837 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
14838 : gdmkmin = GDMK_SCALAR;
14839 : gdmkmax = GDMK_POINTER;
14840 : break;
14841 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
14842 : gdmkmin = GDMK_SCALAR;
14843 : gdmkmax = GDMK_SCALAR_TARGET;
14844 : break;
14845 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
14846 : gdmkmin = gdmkmax = GDMK_AGGREGATE;
14847 : break;
14848 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE:
14849 : gdmkmin = gdmkmax = GDMK_ALLOCATABLE;
14850 : break;
14851 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
14852 : gdmkmin = gdmkmax = GDMK_POINTER;
14853 : break;
14854 0 : default:
14855 0 : gcc_unreachable ();
14856 : }
14857 4471 : for (int gdmk = gdmkmin; gdmk <= gdmkmax; gdmk++)
14858 3461 : switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (c))
14859 : {
14860 91 : case OMP_CLAUSE_DEFAULTMAP_ALLOC:
14861 91 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_ALLOC_ONLY;
14862 91 : break;
14863 96 : case OMP_CLAUSE_DEFAULTMAP_TO:
14864 96 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_TO_ONLY;
14865 96 : break;
14866 28 : case OMP_CLAUSE_DEFAULTMAP_FROM:
14867 28 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FROM_ONLY;
14868 28 : break;
14869 671 : case OMP_CLAUSE_DEFAULTMAP_TOFROM:
14870 671 : ctx->defaultmap[gdmk] = GOVD_MAP;
14871 671 : break;
14872 380 : case OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE:
14873 380 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14874 380 : break;
14875 2094 : case OMP_CLAUSE_DEFAULTMAP_NONE:
14876 2094 : ctx->defaultmap[gdmk] = 0;
14877 2094 : break;
14878 45 : case OMP_CLAUSE_DEFAULTMAP_PRESENT:
14879 45 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
14880 45 : break;
14881 56 : case OMP_CLAUSE_DEFAULTMAP_DEFAULT:
14882 56 : switch (gdmk)
14883 : {
14884 11 : case GDMK_SCALAR:
14885 11 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14886 11 : break;
14887 11 : case GDMK_SCALAR_TARGET:
14888 11 : ctx->defaultmap[gdmk] = (lang_GNU_Fortran ()
14889 11 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
14890 11 : break;
14891 14 : case GDMK_AGGREGATE:
14892 14 : case GDMK_ALLOCATABLE:
14893 14 : ctx->defaultmap[gdmk] = GOVD_MAP;
14894 14 : break;
14895 20 : case GDMK_POINTER:
14896 20 : ctx->defaultmap[gdmk] = GOVD_MAP;
14897 20 : if (!lang_GNU_Fortran ())
14898 12 : ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY;
14899 : break;
14900 : default:
14901 : gcc_unreachable ();
14902 : }
14903 : break;
14904 0 : default:
14905 0 : gcc_unreachable ();
14906 : }
14907 : break;
14908 :
14909 824 : case OMP_CLAUSE_ALIGNED:
14910 824 : decl = OMP_CLAUSE_DECL (c);
14911 824 : if (error_operand_p (decl))
14912 : {
14913 : remove = true;
14914 : break;
14915 : }
14916 824 : if (gimplify_expr (&OMP_CLAUSE_ALIGNED_ALIGNMENT (c), pre_p, NULL,
14917 : is_gimple_val, fb_rvalue) == GS_ERROR)
14918 : {
14919 : remove = true;
14920 : break;
14921 : }
14922 824 : if (!is_global_var (decl)
14923 824 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
14924 592 : omp_add_variable (ctx, decl, GOVD_ALIGNED);
14925 : break;
14926 :
14927 489 : case OMP_CLAUSE_NONTEMPORAL:
14928 489 : decl = OMP_CLAUSE_DECL (c);
14929 489 : if (error_operand_p (decl))
14930 : {
14931 : remove = true;
14932 : break;
14933 : }
14934 489 : omp_add_variable (ctx, decl, GOVD_NONTEMPORAL);
14935 489 : break;
14936 :
14937 3541 : case OMP_CLAUSE_ALLOCATE:
14938 3541 : decl = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
14939 3541 : if (decl
14940 1700 : && TREE_CODE (decl) == INTEGER_CST
14941 3570 : && wi::eq_p (wi::to_widest (decl), GOMP_OMP_PREDEF_ALLOC_THREAD)
14942 3570 : && (code == OMP_TARGET || code == OMP_TASK || code == OMP_TASKLOOP))
14943 35 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
14944 : "allocator with access trait set to %<thread%> "
14945 : "results in undefined behavior for %qs directive",
14946 : code == OMP_TARGET ? "target"
14947 : : (code == OMP_TASK
14948 15 : ? "task" : "taskloop"));
14949 3541 : decl = OMP_CLAUSE_DECL (c);
14950 3541 : if (error_operand_p (decl))
14951 : {
14952 : remove = true;
14953 : break;
14954 : }
14955 3541 : if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL,
14956 : is_gimple_val, fb_rvalue) == GS_ERROR)
14957 : {
14958 : remove = true;
14959 : break;
14960 : }
14961 3541 : else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
14962 3541 : || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
14963 : == INTEGER_CST))
14964 : ;
14965 503 : else if (code == OMP_TASKLOOP
14966 503 : || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
14967 66 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
14968 132 : = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
14969 : pre_p, NULL, false);
14970 : break;
14971 :
14972 4365 : case OMP_CLAUSE_DEFAULT:
14973 4365 : ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
14974 4365 : break;
14975 :
14976 640 : case OMP_CLAUSE_INCLUSIVE:
14977 640 : case OMP_CLAUSE_EXCLUSIVE:
14978 640 : decl = OMP_CLAUSE_DECL (c);
14979 640 : {
14980 640 : splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
14981 : (splay_tree_key) decl);
14982 640 : if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
14983 : {
14984 5 : error_at (OMP_CLAUSE_LOCATION (c),
14985 : "%qD specified in %qs clause but not in %<inscan%> "
14986 : "%<reduction%> clause on the containing construct",
14987 5 : decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
14988 5 : remove = true;
14989 : }
14990 : else
14991 : {
14992 635 : n->value |= GOVD_REDUCTION_INSCAN;
14993 635 : if (outer_ctx->region_type == ORT_SIMD
14994 520 : && outer_ctx->outer_context
14995 107 : && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
14996 : {
14997 107 : n = splay_tree_lookup (outer_ctx->outer_context->variables,
14998 : (splay_tree_key) decl);
14999 107 : if (n && (n->value & GOVD_REDUCTION) != 0)
15000 107 : n->value |= GOVD_REDUCTION_INSCAN;
15001 : }
15002 : }
15003 : }
15004 : break;
15005 :
15006 103 : case OMP_CLAUSE_NOVARIANTS:
15007 103 : OMP_CLAUSE_NOVARIANTS_EXPR (c)
15008 103 : = gimple_boolify (OMP_CLAUSE_NOVARIANTS_EXPR (c));
15009 103 : break;
15010 115 : case OMP_CLAUSE_NOCONTEXT:
15011 115 : OMP_CLAUSE_NOCONTEXT_EXPR (c)
15012 115 : = gimple_boolify (OMP_CLAUSE_NOCONTEXT_EXPR (c));
15013 115 : break;
15014 0 : case OMP_CLAUSE_NOHOST:
15015 0 : default:
15016 0 : gcc_unreachable ();
15017 : }
15018 :
15019 1400 : if (code == OACC_DATA
15020 5123 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15021 208564 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15022 4504 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15023 : remove = true;
15024 204846 : if (remove)
15025 1105 : *list_p = OMP_CLAUSE_CHAIN (c);
15026 : else
15027 204048 : list_p = &OMP_CLAUSE_CHAIN (c);
15028 205153 : }
15029 :
15030 130446 : if (groups)
15031 : {
15032 36214 : delete grpmap;
15033 18107 : delete groups;
15034 : }
15035 :
15036 130446 : ctx->clauses = *orig_list_p;
15037 130446 : gimplify_omp_ctxp = ctx;
15038 130446 : }
15039 :
15040 : /* Return true if DECL is a candidate for shared to firstprivate
15041 : optimization. We only consider non-addressable scalars, not
15042 : too big, and not references. */
15043 :
15044 : static bool
15045 404133 : omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
15046 : {
15047 404133 : if (TREE_ADDRESSABLE (decl))
15048 : return false;
15049 355018 : tree type = TREE_TYPE (decl);
15050 355018 : if (!is_gimple_reg_type (type)
15051 330270 : || TREE_CODE (type) == REFERENCE_TYPE
15052 681023 : || TREE_ADDRESSABLE (type))
15053 : return false;
15054 : /* Don't optimize too large decls, as each thread/task will have
15055 : its own. */
15056 326005 : HOST_WIDE_INT len = int_size_in_bytes (type);
15057 326005 : if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
15058 : return false;
15059 325988 : if (omp_privatize_by_reference (decl))
15060 : return false;
15061 : return true;
15062 : }
15063 :
15064 : /* Helper function of omp_find_stores_op and gimplify_adjust_omp_clauses*.
15065 : For omp_shared_to_firstprivate_optimizable_decl_p decl mark it as
15066 : GOVD_WRITTEN in outer contexts. */
15067 :
15068 : static void
15069 303094 : omp_mark_stores (struct gimplify_omp_ctx *ctx, tree decl)
15070 : {
15071 464923 : for (; ctx; ctx = ctx->outer_context)
15072 : {
15073 447917 : splay_tree_node n = splay_tree_lookup (ctx->variables,
15074 : (splay_tree_key) decl);
15075 447917 : if (n == NULL)
15076 158250 : continue;
15077 289667 : else if (n->value & GOVD_SHARED)
15078 : {
15079 9121 : n->value |= GOVD_WRITTEN;
15080 9121 : return;
15081 : }
15082 280546 : else if (n->value & GOVD_DATA_SHARE_CLASS)
15083 : return;
15084 : }
15085 : }
15086 :
15087 : /* Helper callback for walk_gimple_seq to discover possible stores
15088 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15089 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15090 : for those. */
15091 :
15092 : static tree
15093 1123922 : omp_find_stores_op (tree *tp, int *walk_subtrees, void *data)
15094 : {
15095 1123922 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15096 :
15097 1123922 : *walk_subtrees = 0;
15098 1123922 : if (!wi->is_lhs)
15099 : return NULL_TREE;
15100 :
15101 320850 : tree op = *tp;
15102 399603 : do
15103 : {
15104 399603 : if (handled_component_p (op))
15105 78753 : op = TREE_OPERAND (op, 0);
15106 320850 : else if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
15107 320850 : && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
15108 0 : op = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
15109 : else
15110 : break;
15111 : }
15112 : while (1);
15113 320850 : if (!DECL_P (op) || !omp_shared_to_firstprivate_optimizable_decl_p (op))
15114 58065 : return NULL_TREE;
15115 :
15116 262785 : omp_mark_stores (gimplify_omp_ctxp, op);
15117 262785 : return NULL_TREE;
15118 : }
15119 :
15120 : /* Helper callback for walk_gimple_seq to discover possible stores
15121 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15122 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15123 : for those. */
15124 :
15125 : static tree
15126 624954 : omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
15127 : bool *handled_ops_p,
15128 : struct walk_stmt_info *wi)
15129 : {
15130 624954 : gimple *stmt = gsi_stmt (*gsi_p);
15131 624954 : switch (gimple_code (stmt))
15132 : {
15133 : /* Don't recurse on OpenMP constructs for which
15134 : gimplify_adjust_omp_clauses already handled the bodies,
15135 : except handle gimple_omp_for_pre_body. */
15136 26689 : case GIMPLE_OMP_FOR:
15137 26689 : *handled_ops_p = true;
15138 26689 : if (gimple_omp_for_pre_body (stmt))
15139 1780 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15140 : omp_find_stores_stmt, omp_find_stores_op, wi);
15141 : break;
15142 8561 : case GIMPLE_OMP_PARALLEL:
15143 8561 : case GIMPLE_OMP_TASK:
15144 8561 : case GIMPLE_OMP_SECTIONS:
15145 8561 : case GIMPLE_OMP_SINGLE:
15146 8561 : case GIMPLE_OMP_SCOPE:
15147 8561 : case GIMPLE_OMP_TARGET:
15148 8561 : case GIMPLE_OMP_TEAMS:
15149 8561 : case GIMPLE_OMP_CRITICAL:
15150 8561 : *handled_ops_p = true;
15151 8561 : break;
15152 : default:
15153 : break;
15154 : }
15155 624954 : return NULL_TREE;
15156 : }
15157 :
15158 : struct gimplify_adjust_omp_clauses_data
15159 : {
15160 : tree *list_p;
15161 : gimple_seq *pre_p;
15162 : };
15163 :
15164 : /* For all variables that were not actually used within the context,
15165 : remove PRIVATE, SHARED, and FIRSTPRIVATE clauses. */
15166 :
15167 : static int
15168 674888 : gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
15169 : {
15170 674888 : tree *list_p = ((struct gimplify_adjust_omp_clauses_data *) data)->list_p;
15171 674888 : gimple_seq *pre_p
15172 : = ((struct gimplify_adjust_omp_clauses_data *) data)->pre_p;
15173 674888 : tree decl = (tree) n->key;
15174 674888 : unsigned flags = n->value;
15175 674888 : enum omp_clause_code code;
15176 674888 : tree clause;
15177 674888 : bool private_debug;
15178 :
15179 674888 : if (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
15180 132785 : && (flags & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
15181 : flags = GOVD_SHARED | GOVD_SEEN | GOVD_WRITTEN;
15182 674763 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
15183 : return 0;
15184 178454 : if ((flags & GOVD_SEEN) == 0)
15185 : return 0;
15186 157435 : if (flags & GOVD_DEBUG_PRIVATE)
15187 : {
15188 260 : gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_SHARED);
15189 : private_debug = true;
15190 : }
15191 157175 : else if (flags & GOVD_MAP)
15192 : private_debug = false;
15193 : else
15194 139005 : private_debug
15195 139005 : = lang_hooks.decls.omp_private_debug_clause (decl,
15196 139005 : !!(flags & GOVD_SHARED));
15197 139005 : if (private_debug)
15198 : code = OMP_CLAUSE_PRIVATE;
15199 157053 : else if (flags & GOVD_MAP)
15200 : {
15201 18170 : code = OMP_CLAUSE_MAP;
15202 18170 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15203 18170 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15204 : {
15205 2 : error ("%<_Atomic%> %qD in implicit %<map%> clause", decl);
15206 2 : return 0;
15207 : }
15208 18168 : if (VAR_P (decl)
15209 16230 : && DECL_IN_CONSTANT_POOL (decl)
15210 18169 : && !lookup_attribute ("omp declare target",
15211 1 : DECL_ATTRIBUTES (decl)))
15212 : {
15213 1 : tree id = get_identifier ("omp declare target");
15214 1 : DECL_ATTRIBUTES (decl)
15215 1 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
15216 1 : varpool_node *node = varpool_node::get (decl);
15217 1 : if (node)
15218 : {
15219 1 : node->offloadable = 1;
15220 1 : if (ENABLE_OFFLOADING)
15221 : g->have_offload = true;
15222 : }
15223 : }
15224 : }
15225 138883 : else if (flags & GOVD_SHARED)
15226 : {
15227 49055 : if (is_global_var (decl))
15228 : {
15229 16138 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15230 25325 : while (ctx != NULL)
15231 : {
15232 17604 : splay_tree_node on
15233 17604 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15234 17604 : if (on && (on->value & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
15235 : | GOVD_PRIVATE | GOVD_REDUCTION
15236 : | GOVD_LINEAR | GOVD_MAP)) != 0)
15237 : break;
15238 9187 : ctx = ctx->outer_context;
15239 : }
15240 16138 : if (ctx == NULL)
15241 : return 0;
15242 : }
15243 41334 : code = OMP_CLAUSE_SHARED;
15244 : /* Don't optimize shared into firstprivate for read-only vars
15245 : on tasks with depend clause, we shouldn't try to copy them
15246 : until the dependencies are satisfied. */
15247 41334 : if (gimplify_omp_ctxp->has_depend)
15248 350 : flags |= GOVD_WRITTEN;
15249 : }
15250 89828 : else if (flags & GOVD_PRIVATE)
15251 : code = OMP_CLAUSE_PRIVATE;
15252 31359 : else if (flags & GOVD_FIRSTPRIVATE)
15253 : {
15254 21958 : code = OMP_CLAUSE_FIRSTPRIVATE;
15255 21958 : if ((gimplify_omp_ctxp->region_type & ORT_TARGET)
15256 13924 : && (gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15257 32201 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15258 : {
15259 1 : error ("%<_Atomic%> %qD in implicit %<firstprivate%> clause on "
15260 : "%<target%> construct", decl);
15261 1 : return 0;
15262 : }
15263 : }
15264 9401 : else if (flags & GOVD_LASTPRIVATE)
15265 : code = OMP_CLAUSE_LASTPRIVATE;
15266 241 : else if (flags & (GOVD_ALIGNED | GOVD_NONTEMPORAL))
15267 : return 0;
15268 118 : else if (flags & GOVD_CONDTEMP)
15269 : {
15270 118 : code = OMP_CLAUSE__CONDTEMP_;
15271 118 : gimple_add_tmp_var (decl);
15272 : }
15273 : else
15274 0 : gcc_unreachable ();
15275 :
15276 140428 : if (((flags & GOVD_LASTPRIVATE)
15277 139738 : || (code == OMP_CLAUSE_SHARED && (flags & GOVD_WRITTEN)))
15278 155647 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15279 15205 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15280 :
15281 149588 : tree chain = *list_p;
15282 149588 : clause = build_omp_clause (input_location, code);
15283 149588 : OMP_CLAUSE_DECL (clause) = decl;
15284 149588 : OMP_CLAUSE_CHAIN (clause) = chain;
15285 149588 : if (private_debug)
15286 382 : OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
15287 149206 : else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
15288 6 : OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
15289 149200 : else if (code == OMP_CLAUSE_SHARED
15290 41334 : && (flags & GOVD_WRITTEN) == 0
15291 184475 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15292 21044 : OMP_CLAUSE_SHARED_READONLY (clause) = 1;
15293 128156 : else if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_EXPLICIT) == 0)
15294 21957 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clause) = 1;
15295 106199 : else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
15296 : {
15297 626 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
15298 626 : OMP_CLAUSE_DECL (nc) = decl;
15299 626 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
15300 626 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
15301 15 : OMP_CLAUSE_DECL (clause)
15302 30 : = build_fold_indirect_ref_loc (input_location, decl);
15303 626 : OMP_CLAUSE_DECL (clause)
15304 626 : = build2 (MEM_REF, char_type_node, OMP_CLAUSE_DECL (clause),
15305 : build_int_cst (build_pointer_type (char_type_node), 0));
15306 626 : OMP_CLAUSE_SIZE (clause) = size_zero_node;
15307 626 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15308 626 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
15309 626 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
15310 626 : tree dtype = TREE_TYPE (decl);
15311 626 : if (TREE_CODE (dtype) == REFERENCE_TYPE)
15312 15 : dtype = TREE_TYPE (dtype);
15313 : /* FIRSTPRIVATE_POINTER doesn't work well if we have a
15314 : multiply-indirected pointer. If we have a reference to a pointer to
15315 : a pointer, it's possible that this should really be
15316 : GOMP_MAP_FIRSTPRIVATE_REFERENCE -- but that also doesn't work at the
15317 : moment, so stick with this. (See PR113279 and testcases
15318 : baseptrs-{4,6}.C:ref2ptrptr_offset_decl_member_slice). */
15319 626 : if (TREE_CODE (dtype) == POINTER_TYPE
15320 626 : && TREE_CODE (TREE_TYPE (dtype)) == POINTER_TYPE)
15321 19 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15322 : else
15323 607 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15324 626 : OMP_CLAUSE_CHAIN (nc) = chain;
15325 626 : OMP_CLAUSE_CHAIN (clause) = nc;
15326 626 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15327 626 : gimplify_omp_ctxp = ctx->outer_context;
15328 626 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0),
15329 : pre_p, NULL, is_gimple_val, fb_rvalue);
15330 626 : gimplify_omp_ctxp = ctx;
15331 626 : }
15332 17542 : else if (code == OMP_CLAUSE_MAP)
15333 : {
15334 17542 : int kind;
15335 : /* Not all combinations of these GOVD_MAP flags are actually valid. */
15336 17542 : switch (flags & (GOVD_MAP_TO_ONLY
15337 : | GOVD_MAP_FORCE
15338 : | GOVD_MAP_FORCE_PRESENT
15339 : | GOVD_MAP_ALLOC_ONLY
15340 : | GOVD_MAP_FROM_ONLY))
15341 : {
15342 : case 0:
15343 : kind = GOMP_MAP_TOFROM;
15344 : break;
15345 1042 : case GOVD_MAP_FORCE:
15346 1042 : kind = GOMP_MAP_TOFROM | GOMP_MAP_FLAG_FORCE;
15347 1042 : break;
15348 1015 : case GOVD_MAP_TO_ONLY:
15349 1015 : kind = GOMP_MAP_TO;
15350 1015 : break;
15351 16 : case GOVD_MAP_FROM_ONLY:
15352 16 : kind = GOMP_MAP_FROM;
15353 16 : break;
15354 37 : case GOVD_MAP_ALLOC_ONLY:
15355 37 : kind = GOMP_MAP_ALLOC;
15356 37 : break;
15357 3 : case GOVD_MAP_TO_ONLY | GOVD_MAP_FORCE:
15358 3 : kind = GOMP_MAP_TO | GOMP_MAP_FLAG_FORCE;
15359 3 : break;
15360 : case GOVD_MAP_FORCE_PRESENT:
15361 326 : kind = GOMP_MAP_FORCE_PRESENT;
15362 : break;
15363 : case GOVD_MAP_FORCE_PRESENT | GOVD_MAP_ALLOC_ONLY:
15364 326 : kind = GOMP_MAP_FORCE_PRESENT;
15365 : break;
15366 0 : default:
15367 0 : gcc_unreachable ();
15368 : }
15369 17542 : OMP_CLAUSE_SET_MAP_KIND (clause, kind);
15370 : /* Setting of the implicit flag for the runtime is currently disabled for
15371 : OpenACC. */
15372 17542 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
15373 10008 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1;
15374 17542 : if (DECL_SIZE (decl)
15375 17542 : && !poly_int_tree_p (DECL_SIZE (decl)))
15376 : {
15377 535 : tree decl2 = DECL_VALUE_EXPR (decl);
15378 535 : gcc_assert (INDIRECT_REF_P (decl2));
15379 535 : decl2 = TREE_OPERAND (decl2, 0);
15380 535 : gcc_assert (DECL_P (decl2));
15381 535 : tree mem = build_simple_mem_ref (decl2);
15382 535 : OMP_CLAUSE_DECL (clause) = mem;
15383 535 : OMP_CLAUSE_SIZE (clause) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
15384 535 : if (gimplify_omp_ctxp->outer_context)
15385 : {
15386 446 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15387 446 : omp_notice_variable (ctx, decl2, true);
15388 446 : omp_notice_variable (ctx, OMP_CLAUSE_SIZE (clause), true);
15389 : }
15390 535 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15391 : OMP_CLAUSE_MAP);
15392 535 : OMP_CLAUSE_DECL (nc) = decl;
15393 535 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15394 535 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases)
15395 535 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15396 : else
15397 0 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15398 535 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15399 535 : OMP_CLAUSE_CHAIN (clause) = nc;
15400 : }
15401 17007 : else if (gimplify_omp_ctxp->target_firstprivatize_array_bases
15402 17007 : && omp_privatize_by_reference (decl))
15403 : {
15404 28 : OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl);
15405 28 : OMP_CLAUSE_SIZE (clause)
15406 28 : = unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))));
15407 28 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15408 28 : gimplify_omp_ctxp = ctx->outer_context;
15409 28 : gimplify_expr (&OMP_CLAUSE_SIZE (clause),
15410 : pre_p, NULL, is_gimple_val, fb_rvalue);
15411 28 : gimplify_omp_ctxp = ctx;
15412 28 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15413 : OMP_CLAUSE_MAP);
15414 28 : OMP_CLAUSE_DECL (nc) = decl;
15415 28 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15416 28 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
15417 28 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15418 28 : OMP_CLAUSE_CHAIN (clause) = nc;
15419 : }
15420 : else
15421 16979 : OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
15422 : }
15423 149588 : if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
15424 : {
15425 690 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
15426 690 : OMP_CLAUSE_DECL (nc) = decl;
15427 690 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
15428 690 : OMP_CLAUSE_CHAIN (nc) = chain;
15429 690 : OMP_CLAUSE_CHAIN (clause) = nc;
15430 690 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15431 690 : gimplify_omp_ctxp = ctx->outer_context;
15432 690 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
15433 690 : (ctx->region_type & ORT_ACC) != 0);
15434 690 : gimplify_omp_ctxp = ctx;
15435 : }
15436 149588 : *list_p = clause;
15437 149588 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15438 149588 : gimplify_omp_ctxp = ctx->outer_context;
15439 : /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
15440 : in simd. Those are only added for the local vars inside of simd body
15441 : and they don't need to be e.g. default constructible. */
15442 149588 : if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
15443 141538 : lang_hooks.decls.omp_finish_clause (clause, pre_p,
15444 141538 : (ctx->region_type & ORT_ACC) != 0);
15445 149588 : if (gimplify_omp_ctxp)
15446 184137 : for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
15447 93481 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
15448 93481 : && DECL_P (OMP_CLAUSE_SIZE (clause)))
15449 1241 : omp_notice_variable (gimplify_omp_ctxp, OMP_CLAUSE_SIZE (clause),
15450 : true);
15451 149588 : gimplify_omp_ctxp = ctx;
15452 149588 : return 0;
15453 : }
15454 :
15455 : static void
15456 128982 : gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
15457 : enum tree_code code,
15458 : gimple_seq *loops_seq_p = NULL)
15459 : {
15460 128982 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15461 128982 : tree *orig_list_p = list_p;
15462 128982 : tree c, decl;
15463 128982 : bool has_inscan_reductions = false;
15464 :
15465 128982 : if (body)
15466 : {
15467 : struct gimplify_omp_ctx *octx;
15468 224792 : for (octx = ctx; octx; octx = octx->outer_context)
15469 173546 : if ((octx->region_type & (ORT_PARALLEL | ORT_TASK | ORT_TEAMS)) != 0)
15470 : break;
15471 111432 : if (octx)
15472 : {
15473 60186 : struct walk_stmt_info wi;
15474 60186 : memset (&wi, 0, sizeof (wi));
15475 60186 : walk_gimple_seq (body, omp_find_stores_stmt,
15476 : omp_find_stores_op, &wi);
15477 : }
15478 : }
15479 :
15480 128982 : if (ctx->add_safelen1)
15481 : {
15482 : /* If there are VLAs in the body of simd loop, prevent
15483 : vectorization. */
15484 2 : gcc_assert (ctx->region_type == ORT_SIMD);
15485 2 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
15486 2 : OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node;
15487 2 : OMP_CLAUSE_CHAIN (c) = *list_p;
15488 2 : *list_p = c;
15489 2 : list_p = &OMP_CLAUSE_CHAIN (c);
15490 : }
15491 :
15492 128982 : if (ctx->region_type == ORT_WORKSHARE
15493 39650 : && ctx->outer_context
15494 27883 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
15495 : {
15496 24917 : for (c = ctx->outer_context->clauses; c; c = OMP_CLAUSE_CHAIN (c))
15497 12568 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15498 12568 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
15499 : {
15500 125 : decl = OMP_CLAUSE_DECL (c);
15501 125 : splay_tree_node n
15502 125 : = splay_tree_lookup (ctx->outer_context->variables,
15503 : (splay_tree_key) decl);
15504 125 : gcc_checking_assert (!splay_tree_lookup (ctx->variables,
15505 : (splay_tree_key) decl));
15506 125 : omp_add_variable (ctx, decl, n->value);
15507 125 : tree c2 = copy_node (c);
15508 125 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15509 125 : *list_p = c2;
15510 125 : if ((n->value & GOVD_FIRSTPRIVATE) == 0)
15511 103 : continue;
15512 22 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
15513 : OMP_CLAUSE_FIRSTPRIVATE);
15514 22 : OMP_CLAUSE_DECL (c2) = decl;
15515 22 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15516 22 : *list_p = c2;
15517 : }
15518 : }
15519 :
15520 128982 : if (code == OMP_TARGET
15521 128982 : || code == OMP_TARGET_DATA
15522 128982 : || code == OMP_TARGET_ENTER_DATA
15523 112754 : || code == OMP_TARGET_EXIT_DATA)
15524 : {
15525 17013 : tree mapper_clauses = NULL_TREE;
15526 17013 : instantiate_mapper_info im_info;
15527 :
15528 17013 : im_info.mapper_clauses_p = &mapper_clauses;
15529 17013 : im_info.omp_ctx = ctx;
15530 17013 : im_info.pre_p = pre_p;
15531 :
15532 17013 : splay_tree_foreach (ctx->variables,
15533 : omp_instantiate_implicit_mappers,
15534 : (void *) &im_info);
15535 :
15536 17013 : if (mapper_clauses)
15537 : {
15538 53 : mapper_clauses
15539 53 : = lang_hooks.decls.omp_finish_mapper_clauses (mapper_clauses);
15540 :
15541 : /* Stick the implicitly-expanded mapper clauses at the end of the
15542 : clause list. */
15543 53 : tree *tail = list_p;
15544 163 : while (*tail)
15545 110 : tail = &OMP_CLAUSE_CHAIN (*tail);
15546 53 : *tail = mapper_clauses;
15547 : }
15548 :
15549 17013 : vec<omp_mapping_group> *groups;
15550 17013 : groups = omp_gather_mapping_groups (list_p);
15551 17013 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
15552 :
15553 17013 : if (groups)
15554 : {
15555 8444 : grpmap = omp_index_mapping_groups (groups);
15556 :
15557 8444 : omp_resolve_clause_dependencies (code, groups, grpmap);
15558 8444 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15559 : &grpmap, list_p);
15560 :
15561 8444 : omp_mapping_group *outlist = NULL;
15562 :
15563 16888 : delete grpmap;
15564 8444 : delete groups;
15565 :
15566 : /* Rebuild now we have struct sibling lists. */
15567 8444 : groups = omp_gather_mapping_groups (list_p);
15568 8444 : grpmap = omp_index_mapping_groups (groups);
15569 :
15570 8444 : bool enter_exit = (code == OMP_TARGET_ENTER_DATA
15571 8444 : || code == OMP_TARGET_EXIT_DATA);
15572 :
15573 8444 : outlist = omp_tsort_mapping_groups (groups, grpmap, enter_exit);
15574 8444 : outlist = omp_segregate_mapping_groups (outlist);
15575 8444 : list_p = omp_reorder_mapping_groups (groups, outlist, list_p);
15576 :
15577 8444 : delete grpmap;
15578 8444 : delete groups;
15579 : }
15580 17013 : }
15581 111969 : else if (ctx->region_type & ORT_ACC)
15582 : {
15583 29847 : vec<omp_mapping_group> *groups;
15584 29847 : groups = omp_gather_mapping_groups (list_p);
15585 29847 : if (groups)
15586 : {
15587 9462 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap;
15588 9462 : grpmap = omp_index_mapping_groups (groups);
15589 :
15590 9462 : oacc_resolve_clause_dependencies (groups, grpmap);
15591 9462 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15592 : &grpmap, list_p);
15593 :
15594 9462 : delete groups;
15595 18924 : delete grpmap;
15596 : }
15597 : }
15598 :
15599 128982 : tree attach_list = NULL_TREE;
15600 128982 : tree *attach_tail = &attach_list;
15601 :
15602 128982 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
15603 :
15604 377400 : while ((c = *list_p) != NULL)
15605 : {
15606 248418 : splay_tree_node n;
15607 248418 : bool remove = false;
15608 248418 : bool move_attach = false;
15609 :
15610 290871 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
15611 : grp_end = NULL_TREE;
15612 :
15613 248418 : switch (OMP_CLAUSE_CODE (c))
15614 : {
15615 7979 : case OMP_CLAUSE_FIRSTPRIVATE:
15616 7979 : if ((ctx->region_type & ORT_TARGET)
15617 1938 : && (ctx->region_type & ORT_ACC) == 0
15618 9311 : && TYPE_ATOMIC (strip_array_types
15619 : (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
15620 : {
15621 4 : error_at (OMP_CLAUSE_LOCATION (c),
15622 : "%<_Atomic%> %qD in %<firstprivate%> clause on "
15623 2 : "%<target%> construct", OMP_CLAUSE_DECL (c));
15624 2 : remove = true;
15625 2 : break;
15626 : }
15627 7977 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
15628 : {
15629 380 : decl = OMP_CLAUSE_DECL (c);
15630 380 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15631 380 : if ((n->value & GOVD_MAP) != 0)
15632 : {
15633 : remove = true;
15634 : break;
15635 : }
15636 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0;
15637 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0;
15638 : }
15639 : /* FALLTHRU */
15640 36779 : case OMP_CLAUSE_PRIVATE:
15641 36779 : case OMP_CLAUSE_SHARED:
15642 36779 : case OMP_CLAUSE_LINEAR:
15643 36779 : decl = OMP_CLAUSE_DECL (c);
15644 36779 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15645 36779 : remove = !(n->value & GOVD_SEEN);
15646 36779 : if ((n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0
15647 48 : && code == OMP_PARALLEL
15648 36801 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15649 : remove = true;
15650 36757 : if (! remove)
15651 : {
15652 32155 : bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
15653 32155 : if ((n->value & GOVD_DEBUG_PRIVATE)
15654 32155 : || lang_hooks.decls.omp_private_debug_clause (decl, shared))
15655 : {
15656 87 : gcc_assert ((n->value & GOVD_DEBUG_PRIVATE) == 0
15657 : || ((n->value & GOVD_DATA_SHARE_CLASS)
15658 : == GOVD_SHARED));
15659 87 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
15660 87 : OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
15661 : }
15662 32155 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15663 4159 : && ctx->has_depend
15664 32713 : && DECL_P (decl))
15665 558 : n->value |= GOVD_WRITTEN;
15666 32155 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15667 4159 : && (n->value & GOVD_WRITTEN) == 0
15668 3042 : && DECL_P (decl)
15669 35197 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15670 526 : OMP_CLAUSE_SHARED_READONLY (c) = 1;
15671 31629 : else if (DECL_P (decl)
15672 31629 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15673 3633 : && (n->value & GOVD_WRITTEN) != 0)
15674 30512 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15675 9032 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
15676 38667 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15677 5734 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15678 : }
15679 : else
15680 4624 : n->value &= ~GOVD_EXPLICIT;
15681 : break;
15682 :
15683 13004 : case OMP_CLAUSE_LASTPRIVATE:
15684 : /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
15685 : accurately reflect the presence of a FIRSTPRIVATE clause. */
15686 13004 : decl = OMP_CLAUSE_DECL (c);
15687 13004 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15688 13004 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
15689 13004 : = (n->value & GOVD_FIRSTPRIVATE) != 0;
15690 13004 : if (code == OMP_DISTRIBUTE
15691 13004 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
15692 : {
15693 4 : remove = true;
15694 4 : error_at (OMP_CLAUSE_LOCATION (c),
15695 : "same variable used in %<firstprivate%> and "
15696 : "%<lastprivate%> clauses on %<distribute%> "
15697 : "construct");
15698 : }
15699 13004 : if (!remove
15700 13000 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15701 13000 : && DECL_P (decl)
15702 13000 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15703 11407 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15704 13004 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && code == OMP_PARALLEL)
15705 : remove = true;
15706 : break;
15707 :
15708 824 : case OMP_CLAUSE_ALIGNED:
15709 824 : decl = OMP_CLAUSE_DECL (c);
15710 824 : if (!is_global_var (decl))
15711 : {
15712 738 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15713 738 : remove = n == NULL || !(n->value & GOVD_SEEN);
15714 88 : if (!remove && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
15715 : {
15716 88 : struct gimplify_omp_ctx *octx;
15717 88 : if (n != NULL
15718 88 : && (n->value & (GOVD_DATA_SHARE_CLASS
15719 : & ~GOVD_FIRSTPRIVATE)))
15720 : remove = true;
15721 : else
15722 100 : for (octx = ctx->outer_context; octx;
15723 12 : octx = octx->outer_context)
15724 : {
15725 24 : n = splay_tree_lookup (octx->variables,
15726 : (splay_tree_key) decl);
15727 24 : if (n == NULL)
15728 12 : continue;
15729 12 : if (n->value & GOVD_LOCAL)
15730 : break;
15731 : /* We have to avoid assigning a shared variable
15732 : to itself when trying to add
15733 : __builtin_assume_aligned. */
15734 12 : if (n->value & GOVD_SHARED)
15735 : {
15736 : remove = true;
15737 : break;
15738 : }
15739 : }
15740 : }
15741 : }
15742 86 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
15743 : {
15744 86 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15745 86 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
15746 : remove = true;
15747 : }
15748 : break;
15749 :
15750 552 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
15751 552 : decl = OMP_CLAUSE_DECL (c);
15752 552 : while (INDIRECT_REF_P (decl)
15753 601 : || TREE_CODE (decl) == ARRAY_REF)
15754 49 : decl = TREE_OPERAND (decl, 0);
15755 552 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15756 552 : remove = n == NULL || !(n->value & GOVD_SEEN);
15757 : break;
15758 :
15759 900 : case OMP_CLAUSE_IS_DEVICE_PTR:
15760 900 : case OMP_CLAUSE_NONTEMPORAL:
15761 900 : decl = OMP_CLAUSE_DECL (c);
15762 900 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15763 900 : remove = n == NULL || !(n->value & GOVD_SEEN);
15764 : break;
15765 :
15766 56458 : case OMP_CLAUSE_MAP:
15767 56458 : if (OMP_CLAUSE_MAP_GIMPLE_ONLY (c))
15768 : {
15769 90 : remove = true;
15770 90 : goto end_adjust_omp_map_clause;
15771 : }
15772 56368 : decl = OMP_CLAUSE_DECL (c);
15773 56368 : if (!grp_end)
15774 : {
15775 31585 : grp_start_p = list_p;
15776 31585 : grp_end = *omp_group_last (grp_start_p);
15777 : }
15778 56368 : switch (OMP_CLAUSE_MAP_KIND (c))
15779 : {
15780 181 : case GOMP_MAP_PRESENT_ALLOC:
15781 181 : case GOMP_MAP_PRESENT_TO:
15782 181 : case GOMP_MAP_PRESENT_FROM:
15783 181 : case GOMP_MAP_PRESENT_TOFROM:
15784 181 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_PRESENT);
15785 181 : break;
15786 : default:
15787 : break;
15788 : }
15789 56368 : switch (code)
15790 : {
15791 4563 : case OACC_DATA:
15792 4563 : if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
15793 : break;
15794 : /* Fallthrough. */
15795 19180 : case OACC_HOST_DATA:
15796 19180 : case OACC_ENTER_DATA:
15797 19180 : case OACC_EXIT_DATA:
15798 19180 : case OMP_TARGET_DATA:
15799 19180 : case OMP_TARGET_ENTER_DATA:
15800 19180 : case OMP_TARGET_EXIT_DATA:
15801 19180 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15802 19180 : || (OMP_CLAUSE_MAP_KIND (c)
15803 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15804 : /* For target {,enter ,exit }data only the array slice is
15805 : mapped, but not the pointer to it. */
15806 : remove = true;
15807 19180 : if (code == OMP_TARGET_EXIT_DATA
15808 19180 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
15809 2793 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER))
15810 : remove = true;
15811 : break;
15812 : case OMP_TARGET:
15813 : break;
15814 : default:
15815 : break;
15816 : }
15817 19178 : if (remove)
15818 : break;
15819 56033 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
15820 : {
15821 : /* Sanity check: attach/detach map kinds use the size as a bias,
15822 : and it's never right to use the decl size for such
15823 : mappings. */
15824 17647 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
15825 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
15826 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DETACH
15827 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
15828 : && (OMP_CLAUSE_MAP_KIND (c)
15829 : != GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
15830 21703 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
15831 4056 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
15832 : }
15833 56033 : gimplify_omp_ctxp = ctx->outer_context;
15834 56033 : gimple_seq *seq_p;
15835 56033 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
15836 56033 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
15837 : is_gimple_val, fb_rvalue) == GS_ERROR)
15838 : {
15839 0 : gimplify_omp_ctxp = ctx;
15840 0 : remove = true;
15841 0 : goto end_adjust_omp_map_clause;
15842 : }
15843 56033 : else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15844 53142 : || (OMP_CLAUSE_MAP_KIND (c)
15845 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15846 52729 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15847 62608 : && TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
15848 : {
15849 912 : OMP_CLAUSE_SIZE (c)
15850 912 : = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), seq_p, NULL,
15851 : false);
15852 912 : if ((ctx->region_type & ORT_TARGET) != 0)
15853 703 : omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
15854 : GOVD_FIRSTPRIVATE | GOVD_SEEN);
15855 : }
15856 56033 : gimplify_omp_ctxp = ctx;
15857 : /* Data clauses associated with reductions must be
15858 : compatible with present_or_copy. Warn and adjust the clause
15859 : if that is not the case. */
15860 56033 : if (ctx->region_type == ORT_ACC_PARALLEL
15861 47054 : || ctx->region_type == ORT_ACC_SERIAL)
15862 : {
15863 9535 : tree t = DECL_P (decl) ? decl : TREE_OPERAND (decl, 0);
15864 9535 : n = NULL;
15865 :
15866 9535 : if (DECL_P (t))
15867 7770 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
15868 :
15869 7770 : if (n && (n->value & GOVD_REDUCTION))
15870 : {
15871 809 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
15872 :
15873 809 : OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1;
15874 809 : if ((kind & GOMP_MAP_TOFROM) != GOMP_MAP_TOFROM
15875 159 : && kind != GOMP_MAP_FORCE_PRESENT
15876 159 : && kind != GOMP_MAP_POINTER)
15877 : {
15878 120 : warning_at (OMP_CLAUSE_LOCATION (c), 0,
15879 : "incompatible data clause with reduction "
15880 : "on %qE; promoting to %<present_or_copy%>",
15881 120 : DECL_NAME (t));
15882 120 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
15883 : }
15884 : }
15885 : }
15886 56033 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
15887 53283 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
15888 56307 : && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
15889 : {
15890 534 : remove = true;
15891 534 : goto end_adjust_omp_map_clause;
15892 : }
15893 : /* If we have a DECL_VALUE_EXPR (e.g. this is a class member and/or
15894 : a variable captured in a lambda closure), look through that now
15895 : before the DECL_P check below. (A code other than COMPONENT_REF,
15896 : i.e. INDIRECT_REF, will be a VLA/variable-length array
15897 : section. A global var may be a variable in a common block. We
15898 : don't want to do this here for either of those.) */
15899 55499 : if ((ctx->region_type & ORT_ACC) == 0
15900 29292 : && DECL_P (decl)
15901 12511 : && !is_global_var (decl)
15902 11120 : && DECL_HAS_VALUE_EXPR_P (decl)
15903 55689 : && TREE_CODE (DECL_VALUE_EXPR (decl)) == COMPONENT_REF)
15904 0 : decl = OMP_CLAUSE_DECL (c) = DECL_VALUE_EXPR (decl);
15905 55499 : if (TREE_CODE (decl) == TARGET_EXPR)
15906 : {
15907 0 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
15908 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
15909 26070 : remove = true;
15910 : }
15911 55499 : else if (!DECL_P (decl))
15912 : {
15913 29429 : if ((ctx->region_type & ORT_TARGET) != 0
15914 29429 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15915 : {
15916 24 : if (INDIRECT_REF_P (decl)
15917 0 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
15918 24 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
15919 : == REFERENCE_TYPE))
15920 0 : decl = TREE_OPERAND (decl, 0);
15921 24 : if (TREE_CODE (decl) == COMPONENT_REF)
15922 : {
15923 0 : while (TREE_CODE (decl) == COMPONENT_REF)
15924 0 : decl = TREE_OPERAND (decl, 0);
15925 0 : if (DECL_P (decl))
15926 : {
15927 0 : n = splay_tree_lookup (ctx->variables,
15928 : (splay_tree_key) decl);
15929 0 : if (!(n->value & GOVD_SEEN))
15930 29429 : remove = true;
15931 : }
15932 : }
15933 : }
15934 :
15935 29429 : tree d = decl, *pd;
15936 29429 : if (TREE_CODE (d) == ARRAY_REF)
15937 : {
15938 5718 : while (TREE_CODE (d) == ARRAY_REF)
15939 2919 : d = TREE_OPERAND (d, 0);
15940 2799 : if (TREE_CODE (d) == COMPONENT_REF
15941 2799 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
15942 : decl = d;
15943 : }
15944 29429 : pd = &OMP_CLAUSE_DECL (c);
15945 29429 : if (d == decl
15946 26987 : && TREE_CODE (decl) == INDIRECT_REF
15947 15414 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
15948 1470 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
15949 : == REFERENCE_TYPE)
15950 30229 : && (OMP_CLAUSE_MAP_KIND (c)
15951 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
15952 : {
15953 796 : pd = &TREE_OPERAND (decl, 0);
15954 796 : decl = TREE_OPERAND (decl, 0);
15955 : }
15956 :
15957 29429 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15958 3033 : switch (code)
15959 : {
15960 427 : case OACC_ENTER_DATA:
15961 427 : case OACC_EXIT_DATA:
15962 427 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
15963 : == ARRAY_TYPE)
15964 : remove = true;
15965 417 : else if (code == OACC_ENTER_DATA)
15966 263 : goto change_to_attach;
15967 : /* Fallthrough. */
15968 605 : case OMP_TARGET_EXIT_DATA:
15969 605 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DETACH);
15970 605 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
15971 605 : break;
15972 71 : case OACC_UPDATE:
15973 : /* An "attach/detach" operation on an update directive
15974 : should behave as a GOMP_MAP_ALWAYS_POINTER. Note that
15975 : both GOMP_MAP_ATTACH_DETACH and GOMP_MAP_ALWAYS_POINTER
15976 : kinds depend on the previous mapping (for non-TARGET
15977 : regions). */
15978 71 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
15979 71 : break;
15980 2357 : default:
15981 2357 : change_to_attach:
15982 2357 : gcc_assert (!OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c));
15983 2357 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH);
15984 2357 : if ((ctx->region_type & ORT_TARGET) != 0)
15985 1777 : move_attach = true;
15986 : }
15987 26396 : else if ((ctx->region_type & ORT_TARGET) != 0
15988 26396 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
15989 11741 : || (OMP_CLAUSE_MAP_KIND (c)
15990 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
15991 : move_attach = true;
15992 :
15993 : /* If we have e.g. map(struct: *var), don't gimplify the
15994 : argument since omp-low.cc wants to see the decl itself. */
15995 29429 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
15996 1135 : goto end_adjust_omp_map_clause;
15997 :
15998 : /* We've already partly gimplified this in
15999 : gimplify_scan_omp_clauses. Don't do any more. */
16000 28294 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
16001 88 : goto end_adjust_omp_map_clause;
16002 :
16003 28206 : gimplify_omp_ctxp = ctx->outer_context;
16004 28206 : if (gimplify_expr (pd, seq_p, NULL, is_gimple_lvalue,
16005 : fb_lvalue) == GS_ERROR)
16006 0 : remove = true;
16007 28206 : gimplify_omp_ctxp = ctx;
16008 28206 : goto end_adjust_omp_map_clause;
16009 : }
16010 :
16011 26070 : if ((code == OMP_TARGET
16012 : || code == OMP_TARGET_DATA
16013 : || code == OMP_TARGET_ENTER_DATA
16014 14447 : || code == OMP_TARGET_EXIT_DATA)
16015 26696 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16016 : {
16017 238 : bool firstprivatize = false;
16018 :
16019 243 : for (struct gimplify_omp_ctx *octx = ctx->outer_context; octx;
16020 5 : octx = octx->outer_context)
16021 : {
16022 6 : splay_tree_node n
16023 12 : = splay_tree_lookup (octx->variables,
16024 6 : (splay_tree_key) OMP_CLAUSE_DECL (c));
16025 : /* If this is contained in an outer OpenMP region as a
16026 : firstprivate value, remove the attach/detach. */
16027 6 : if (n && (n->value & GOVD_FIRSTPRIVATE))
16028 : {
16029 : firstprivatize = true;
16030 : break;
16031 : }
16032 : }
16033 :
16034 238 : enum gomp_map_kind map_kind;
16035 238 : if (firstprivatize)
16036 : map_kind = GOMP_MAP_FIRSTPRIVATE_POINTER;
16037 237 : else if (code == OMP_TARGET_EXIT_DATA)
16038 : map_kind = GOMP_MAP_DETACH;
16039 : else
16040 186 : map_kind = GOMP_MAP_ATTACH;
16041 238 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16042 : }
16043 25832 : else if ((ctx->region_type & ORT_ACC) != 0
16044 25832 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16045 : {
16046 0 : enum gomp_map_kind map_kind = (code == OACC_EXIT_DATA
16047 0 : ? GOMP_MAP_DETACH
16048 : : GOMP_MAP_ATTACH);
16049 0 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16050 : }
16051 :
16052 26070 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16053 26070 : if ((ctx->region_type & ORT_TARGET) != 0
16054 16173 : && !(n->value & GOVD_SEEN)
16055 1480 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) == 0
16056 27303 : && (!is_global_var (decl)
16057 75 : || !lookup_attribute ("omp declare target link",
16058 75 : DECL_ATTRIBUTES (decl))))
16059 : {
16060 1221 : remove = true;
16061 : /* For struct element mapping, if struct is never referenced
16062 : in target block and none of the mapping has always modifier,
16063 : remove all the struct element mappings, which immediately
16064 : follow the GOMP_MAP_STRUCT map clause. */
16065 1221 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
16066 1221 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
16067 : {
16068 28 : HOST_WIDE_INT cnt = tree_to_shwi (OMP_CLAUSE_SIZE (c));
16069 76 : while (cnt--)
16070 48 : OMP_CLAUSE_CHAIN (c)
16071 48 : = OMP_CLAUSE_CHAIN (OMP_CLAUSE_CHAIN (c));
16072 : }
16073 : }
16074 24849 : else if (DECL_SIZE (decl)
16075 24825 : && !poly_int_tree_p (DECL_SIZE (decl))
16076 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER
16077 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
16078 24900 : && (OMP_CLAUSE_MAP_KIND (c)
16079 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
16080 : {
16081 : /* For GOMP_MAP_FORCE_DEVICEPTR, we'll never enter here, because
16082 : for these, TREE_CODE (DECL_SIZE (decl)) will always be
16083 : INTEGER_CST. */
16084 51 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
16085 :
16086 51 : tree decl2 = DECL_VALUE_EXPR (decl);
16087 51 : gcc_assert (INDIRECT_REF_P (decl2));
16088 51 : decl2 = TREE_OPERAND (decl2, 0);
16089 51 : gcc_assert (DECL_P (decl2));
16090 51 : tree mem = build_simple_mem_ref (decl2);
16091 51 : OMP_CLAUSE_DECL (c) = mem;
16092 51 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16093 51 : if (ctx->outer_context)
16094 : {
16095 15 : omp_notice_variable (ctx->outer_context, decl2, true);
16096 30 : omp_notice_variable (ctx->outer_context,
16097 15 : OMP_CLAUSE_SIZE (c), true);
16098 : }
16099 51 : if (((ctx->region_type & ORT_TARGET) != 0
16100 24 : || !ctx->target_firstprivatize_array_bases)
16101 34 : && ((n->value & GOVD_SEEN) == 0
16102 30 : || (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0))
16103 : {
16104 34 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16105 : OMP_CLAUSE_MAP);
16106 34 : OMP_CLAUSE_DECL (nc) = decl;
16107 34 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
16108 34 : if (ctx->target_firstprivatize_array_bases)
16109 27 : OMP_CLAUSE_SET_MAP_KIND (nc,
16110 : GOMP_MAP_FIRSTPRIVATE_POINTER);
16111 : else
16112 7 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
16113 34 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
16114 34 : OMP_CLAUSE_CHAIN (c) = nc;
16115 34 : c = nc;
16116 : }
16117 : }
16118 : else
16119 : {
16120 24798 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16121 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16122 24798 : gcc_assert ((n->value & GOVD_SEEN) == 0
16123 : || ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16124 : == 0));
16125 : }
16126 :
16127 : /* If we have a target region, we can push all the attaches to the
16128 : end of the list (we may have standalone "attach" operations
16129 : synthesized for GOMP_MAP_STRUCT nodes that must be processed after
16130 : the attachment point AND the pointed-to block have been mapped).
16131 : If we have something else, e.g. "enter data", we need to keep
16132 : "attach" nodes together with the previous node they attach to so
16133 : that separate "exit data" operations work properly (see
16134 : libgomp/target.c). */
16135 26070 : if ((ctx->region_type & ORT_TARGET) != 0
16136 26070 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16137 16057 : || (OMP_CLAUSE_MAP_KIND (c)
16138 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16139 : move_attach = true;
16140 :
16141 56123 : end_adjust_omp_map_clause:
16142 56123 : exit_omp_iterator_loop_context (c);
16143 56123 : break;
16144 :
16145 8319 : case OMP_CLAUSE_TO:
16146 8319 : case OMP_CLAUSE_FROM:
16147 8319 : case OMP_CLAUSE__CACHE_:
16148 8319 : decl = OMP_CLAUSE_DECL (c);
16149 8319 : if (!DECL_P (decl))
16150 : break;
16151 6188 : if (DECL_SIZE (decl)
16152 6188 : && !poly_int_tree_p (DECL_SIZE (decl)))
16153 : {
16154 4 : tree decl2 = DECL_VALUE_EXPR (decl);
16155 4 : gcc_assert (INDIRECT_REF_P (decl2));
16156 4 : decl2 = TREE_OPERAND (decl2, 0);
16157 4 : gcc_assert (DECL_P (decl2));
16158 4 : tree mem = build_simple_mem_ref (decl2);
16159 4 : OMP_CLAUSE_DECL (c) = mem;
16160 4 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16161 4 : if (ctx->outer_context)
16162 : {
16163 4 : omp_notice_variable (ctx->outer_context, decl2, true);
16164 4 : omp_notice_variable (ctx->outer_context,
16165 4 : OMP_CLAUSE_SIZE (c), true);
16166 : }
16167 : }
16168 6184 : else if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16169 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16170 : break;
16171 :
16172 15213 : case OMP_CLAUSE_REDUCTION:
16173 15213 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
16174 : {
16175 811 : decl = OMP_CLAUSE_DECL (c);
16176 811 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16177 811 : if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
16178 : {
16179 69 : remove = true;
16180 69 : error_at (OMP_CLAUSE_LOCATION (c),
16181 : "%qD specified in %<inscan%> %<reduction%> clause "
16182 : "but not in %<scan%> directive clause", decl);
16183 69 : break;
16184 : }
16185 : has_inscan_reductions = true;
16186 : }
16187 : /* FALLTHRU */
16188 17748 : case OMP_CLAUSE_IN_REDUCTION:
16189 17748 : case OMP_CLAUSE_TASK_REDUCTION:
16190 17748 : decl = OMP_CLAUSE_DECL (c);
16191 : /* OpenACC reductions need a present_or_copy data clause.
16192 : Add one if necessary. Emit error when the reduction is private. */
16193 17748 : if (ctx->region_type == ORT_ACC_PARALLEL
16194 17216 : || ctx->region_type == ORT_ACC_SERIAL)
16195 : {
16196 803 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16197 803 : if (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16198 : {
16199 13 : remove = true;
16200 13 : error_at (OMP_CLAUSE_LOCATION (c), "invalid private "
16201 13 : "reduction on %qE", DECL_NAME (decl));
16202 : }
16203 790 : else if ((n->value & GOVD_MAP) == 0)
16204 : {
16205 524 : tree next = OMP_CLAUSE_CHAIN (c);
16206 524 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP);
16207 524 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM);
16208 524 : OMP_CLAUSE_DECL (nc) = decl;
16209 524 : OMP_CLAUSE_CHAIN (c) = nc;
16210 524 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
16211 524 : (ctx->region_type
16212 : & ORT_ACC) != 0);
16213 550 : while (1)
16214 : {
16215 537 : OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1;
16216 537 : if (OMP_CLAUSE_CHAIN (nc) == NULL)
16217 : break;
16218 13 : nc = OMP_CLAUSE_CHAIN (nc);
16219 : }
16220 524 : OMP_CLAUSE_CHAIN (nc) = next;
16221 524 : n->value |= GOVD_MAP;
16222 : }
16223 : }
16224 17748 : if (DECL_P (decl)
16225 17748 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
16226 7963 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
16227 : break;
16228 :
16229 3541 : case OMP_CLAUSE_ALLOCATE:
16230 3541 : decl = OMP_CLAUSE_DECL (c);
16231 3541 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16232 3541 : if (n != NULL && !(n->value & GOVD_SEEN))
16233 : {
16234 1176 : if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
16235 : != 0
16236 1176 : && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
16237 : remove = true;
16238 : }
16239 : if (!remove
16240 2365 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
16241 1273 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
16242 483 : && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
16243 347 : || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
16244 287 : || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
16245 : {
16246 214 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
16247 214 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
16248 214 : if (n == NULL)
16249 : {
16250 92 : enum omp_clause_default_kind default_kind
16251 : = ctx->default_kind;
16252 92 : ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
16253 92 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16254 : true);
16255 92 : ctx->default_kind = default_kind;
16256 : }
16257 : else
16258 122 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16259 : true);
16260 : }
16261 : break;
16262 :
16263 : case OMP_CLAUSE_COPYIN:
16264 : case OMP_CLAUSE_COPYPRIVATE:
16265 : case OMP_CLAUSE_IF:
16266 : case OMP_CLAUSE_SELF:
16267 : case OMP_CLAUSE_NUM_THREADS:
16268 : case OMP_CLAUSE_NUM_TEAMS:
16269 : case OMP_CLAUSE_THREAD_LIMIT:
16270 : case OMP_CLAUSE_DIST_SCHEDULE:
16271 : case OMP_CLAUSE_DEVICE:
16272 : case OMP_CLAUSE_SCHEDULE:
16273 : case OMP_CLAUSE_NOWAIT:
16274 : case OMP_CLAUSE_ORDERED:
16275 : case OMP_CLAUSE_DEFAULT:
16276 : case OMP_CLAUSE_UNTIED:
16277 : case OMP_CLAUSE_COLLAPSE:
16278 : case OMP_CLAUSE_FINAL:
16279 : case OMP_CLAUSE_MERGEABLE:
16280 : case OMP_CLAUSE_PROC_BIND:
16281 : case OMP_CLAUSE_SAFELEN:
16282 : case OMP_CLAUSE_SIMDLEN:
16283 : case OMP_CLAUSE_DEPEND:
16284 : case OMP_CLAUSE_DOACROSS:
16285 : case OMP_CLAUSE_PRIORITY:
16286 : case OMP_CLAUSE_GRAINSIZE:
16287 : case OMP_CLAUSE_NUM_TASKS:
16288 : case OMP_CLAUSE_NOGROUP:
16289 : case OMP_CLAUSE_THREADS:
16290 : case OMP_CLAUSE_SIMD:
16291 : case OMP_CLAUSE_FILTER:
16292 : case OMP_CLAUSE_HINT:
16293 : case OMP_CLAUSE_DEFAULTMAP:
16294 : case OMP_CLAUSE_ORDER:
16295 : case OMP_CLAUSE_BIND:
16296 : case OMP_CLAUSE_DETACH:
16297 : case OMP_CLAUSE_USE_DEVICE_PTR:
16298 : case OMP_CLAUSE_USE_DEVICE_ADDR:
16299 : case OMP_CLAUSE_ASYNC:
16300 : case OMP_CLAUSE_WAIT:
16301 : case OMP_CLAUSE_INDEPENDENT:
16302 : case OMP_CLAUSE_NUM_GANGS:
16303 : case OMP_CLAUSE_NUM_WORKERS:
16304 : case OMP_CLAUSE_VECTOR_LENGTH:
16305 : case OMP_CLAUSE_GANG:
16306 : case OMP_CLAUSE_WORKER:
16307 : case OMP_CLAUSE_VECTOR:
16308 : case OMP_CLAUSE_AUTO:
16309 : case OMP_CLAUSE_SEQ:
16310 : case OMP_CLAUSE_TILE:
16311 : case OMP_CLAUSE_IF_PRESENT:
16312 : case OMP_CLAUSE_FINALIZE:
16313 : case OMP_CLAUSE_INCLUSIVE:
16314 : case OMP_CLAUSE_EXCLUSIVE:
16315 : case OMP_CLAUSE_USES_ALLOCATORS:
16316 : case OMP_CLAUSE_DEVICE_TYPE:
16317 : break;
16318 :
16319 0 : case OMP_CLAUSE_NOHOST:
16320 0 : default:
16321 0 : gcc_unreachable ();
16322 : }
16323 :
16324 129335 : if (remove)
16325 9904 : *list_p = OMP_CLAUSE_CHAIN (c);
16326 238514 : else if (move_attach)
16327 : {
16328 : /* Remove attach node from here, separate out into its own list. */
16329 2334 : *attach_tail = c;
16330 2334 : *list_p = OMP_CLAUSE_CHAIN (c);
16331 2334 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
16332 2334 : attach_tail = &OMP_CLAUSE_CHAIN (c);
16333 : }
16334 : else
16335 236180 : list_p = &OMP_CLAUSE_CHAIN (c);
16336 : }
16337 :
16338 : /* Splice attach nodes at the end of the list. */
16339 128982 : if (attach_list)
16340 : {
16341 1108 : *list_p = attach_list;
16342 1108 : list_p = attach_tail;
16343 : }
16344 :
16345 : /* Add in any implicit data sharing. */
16346 128982 : struct gimplify_adjust_omp_clauses_data data;
16347 128982 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
16348 : {
16349 : /* OpenMP. Implicit clauses are added at the start of the clause list,
16350 : but after any non-map clauses. */
16351 : tree *implicit_add_list_p = orig_list_p;
16352 252150 : while (*implicit_add_list_p
16353 252150 : && OMP_CLAUSE_CODE (*implicit_add_list_p) != OMP_CLAUSE_MAP)
16354 153015 : implicit_add_list_p = &OMP_CLAUSE_CHAIN (*implicit_add_list_p);
16355 99135 : data.list_p = implicit_add_list_p;
16356 : }
16357 : else
16358 : /* OpenACC. */
16359 29847 : data.list_p = list_p;
16360 128982 : data.pre_p = pre_p;
16361 128982 : splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
16362 :
16363 128982 : if (has_inscan_reductions)
16364 2431 : for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
16365 1822 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
16366 1822 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
16367 : {
16368 5 : error_at (OMP_CLAUSE_LOCATION (c),
16369 : "%<inscan%> %<reduction%> clause used together with "
16370 : "%<linear%> clause for a variable other than loop "
16371 : "iterator");
16372 5 : break;
16373 : }
16374 :
16375 128982 : gimplify_omp_ctxp = ctx->outer_context;
16376 128982 : delete_omp_context (ctx);
16377 128982 : }
16378 :
16379 : /* Try to evaluate a novariants clause. Return 1 if true, 0 if false or absent,
16380 : * -1 if run-time evaluation is needed. */
16381 :
16382 : int
16383 249998 : omp_has_novariants (void)
16384 : {
16385 249998 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16386 249998 : if (ctx != NULL && ctx->code == OMP_DISPATCH && !ctx->in_call_args)
16387 : {
16388 3290 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOVARIANTS);
16389 3290 : if (c != NULL_TREE)
16390 : {
16391 299 : if (integer_nonzerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16392 : return 1;
16393 171 : else if (integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16394 : return 0;
16395 : else
16396 : return -1;
16397 : }
16398 : return 0;
16399 : }
16400 : return 0;
16401 : }
16402 :
16403 : /* Try to evaluate a nocontext clause. Return 1 if true, 0 if false or absent,
16404 : * -1 if run-time evaluation is needed. */
16405 :
16406 : static int
16407 1903 : omp_has_nocontext (void)
16408 : {
16409 1903 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16410 1903 : if (ctx != NULL && ctx->code == OMP_DISPATCH)
16411 : {
16412 1903 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOCONTEXT);
16413 1903 : if (c != NULL_TREE)
16414 : {
16415 256 : if (integer_nonzerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16416 : return 1;
16417 94 : else if (integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16418 : return 0;
16419 : else
16420 : return -1;
16421 : }
16422 : return 0;
16423 : }
16424 : return 0;
16425 : }
16426 :
16427 : /* Collect a list of traits for enclosing constructs in the current
16428 : OpenMP context. The list is in the same format as the trait selector
16429 : list of construct trait sets built by the front ends.
16430 :
16431 : Per the OpenMP specification, the construct trait set includes constructs
16432 : up to an enclosing "target" construct. If there is no "target" construct,
16433 : then additional things may be added to the construct trait set (simd for
16434 : simd clones, additional constructs associated with "declare variant",
16435 : the target trait for "declare target"); those are not handled here.
16436 : In particular simd clones are not known during gimplification so
16437 : matching/scoring of context selectors that might involve them needs
16438 : to be deferred to the omp_device_lower pass. */
16439 :
16440 : tree
16441 2213 : omp_get_construct_context (void)
16442 : {
16443 2213 : tree result = NULL_TREE;
16444 4184 : for (struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; ctx;)
16445 : {
16446 2092 : if (((ctx->region_type & (ORT_TARGET | ORT_IMPLICIT_TARGET | ORT_ACC))
16447 : == ORT_TARGET)
16448 121 : && ctx->code == OMP_TARGET)
16449 : {
16450 121 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TARGET,
16451 : NULL_TREE, NULL_TREE, result);
16452 : /* We're not interested in any outer constructs. */
16453 121 : break;
16454 : }
16455 1971 : else if ((ctx->region_type & ORT_PARALLEL) && ctx->code == OMP_PARALLEL)
16456 214 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_PARALLEL,
16457 : NULL_TREE, NULL_TREE, result);
16458 1757 : else if ((ctx->region_type & ORT_TEAMS) && ctx->code == OMP_TEAMS)
16459 75 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TEAMS,
16460 : NULL_TREE, NULL_TREE, result);
16461 1682 : else if (ctx->region_type == ORT_WORKSHARE && ctx->code == OMP_FOR)
16462 164 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_FOR,
16463 : NULL_TREE, NULL_TREE, result);
16464 1518 : else if (ctx->code == OMP_DISPATCH && omp_has_nocontext () != 1)
16465 1279 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_DISPATCH,
16466 : NULL_TREE, NULL_TREE, result);
16467 239 : else if (ctx->region_type == ORT_SIMD
16468 32 : && ctx->code == OMP_SIMD
16469 271 : && !omp_find_clause (ctx->clauses, OMP_CLAUSE_BIND))
16470 : {
16471 32 : tree props = NULL_TREE;
16472 32 : tree *last = &props;
16473 72 : for (tree c = ctx->clauses; c; c = OMP_CLAUSE_CHAIN (c))
16474 40 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMDLEN
16475 32 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INBRANCH
16476 72 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOTINBRANCH)
16477 : {
16478 8 : *last = unshare_expr (c);
16479 8 : last = &(OMP_CLAUSE_CHAIN (c));
16480 : }
16481 32 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_SIMD,
16482 : NULL_TREE, props, result);
16483 : }
16484 207 : else if (ctx->region_type == ORT_WORKSHARE
16485 5 : && ctx->code == OMP_LOOP
16486 0 : && ctx->outer_context
16487 0 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL
16488 0 : && ctx->outer_context->outer_context
16489 0 : && ctx->outer_context->outer_context->code == OMP_LOOP
16490 0 : && ctx->outer_context->outer_context->distribute)
16491 1971 : ctx = ctx->outer_context->outer_context;
16492 1971 : ctx = ctx->outer_context;
16493 : }
16494 :
16495 2213 : return result;
16496 : }
16497 :
16498 : /* Gimplify OACC_CACHE. */
16499 :
16500 : static void
16501 665 : gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
16502 : {
16503 665 : tree expr = *expr_p;
16504 :
16505 665 : gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_ACC,
16506 : OACC_CACHE);
16507 665 : gimplify_adjust_omp_clauses (pre_p, NULL, &OACC_CACHE_CLAUSES (expr),
16508 : OACC_CACHE);
16509 :
16510 : /* TODO: Do something sensible with this information. */
16511 :
16512 665 : *expr_p = NULL_TREE;
16513 665 : }
16514 :
16515 : /* Helper function of gimplify_oacc_declare. The helper's purpose is to,
16516 : if required, translate 'kind' in CLAUSE into an 'entry' kind and 'exit'
16517 : kind. The entry kind will replace the one in CLAUSE, while the exit
16518 : kind will be used in a new omp_clause and returned to the caller. */
16519 :
16520 : static tree
16521 190 : gimplify_oacc_declare_1 (tree clause)
16522 : {
16523 190 : HOST_WIDE_INT kind, new_op;
16524 190 : bool ret = false;
16525 190 : tree c = NULL;
16526 :
16527 190 : kind = OMP_CLAUSE_MAP_KIND (clause);
16528 :
16529 190 : switch (kind)
16530 : {
16531 : case GOMP_MAP_ALLOC:
16532 : new_op = GOMP_MAP_RELEASE;
16533 : ret = true;
16534 : break;
16535 :
16536 29 : case GOMP_MAP_FROM:
16537 29 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_ALLOC);
16538 29 : new_op = GOMP_MAP_FROM;
16539 29 : ret = true;
16540 29 : break;
16541 :
16542 40 : case GOMP_MAP_TOFROM:
16543 40 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_TO);
16544 40 : new_op = GOMP_MAP_FROM;
16545 40 : ret = true;
16546 40 : break;
16547 :
16548 : case GOMP_MAP_DEVICE_RESIDENT:
16549 : case GOMP_MAP_FORCE_DEVICEPTR:
16550 : case GOMP_MAP_FORCE_PRESENT:
16551 : case GOMP_MAP_LINK:
16552 : case GOMP_MAP_POINTER:
16553 : case GOMP_MAP_TO:
16554 : break;
16555 :
16556 0 : default:
16557 0 : gcc_unreachable ();
16558 69 : break;
16559 : }
16560 :
16561 69 : if (ret)
16562 : {
16563 116 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clause), OMP_CLAUSE_MAP);
16564 116 : OMP_CLAUSE_SET_MAP_KIND (c, new_op);
16565 116 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clause);
16566 : }
16567 :
16568 190 : return c;
16569 : }
16570 :
16571 : /* Gimplify OACC_DECLARE. */
16572 :
16573 : static void
16574 254 : gimplify_oacc_declare (tree *expr_p, gimple_seq *pre_p)
16575 : {
16576 254 : tree expr = *expr_p;
16577 254 : gomp_target *stmt;
16578 254 : tree clauses, t, decl;
16579 :
16580 254 : clauses = OACC_DECLARE_CLAUSES (expr);
16581 :
16582 254 : gimplify_scan_omp_clauses (&clauses, pre_p, ORT_TARGET_DATA, OACC_DECLARE);
16583 254 : gimplify_adjust_omp_clauses (pre_p, NULL, &clauses, OACC_DECLARE);
16584 :
16585 516 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16586 : {
16587 262 : decl = OMP_CLAUSE_DECL (t);
16588 :
16589 262 : if (TREE_CODE (decl) == MEM_REF)
16590 8 : decl = TREE_OPERAND (decl, 0);
16591 :
16592 262 : if (VAR_P (decl) && !is_oacc_declared (decl))
16593 : {
16594 262 : tree attr = get_identifier ("oacc declare target");
16595 262 : DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE,
16596 262 : DECL_ATTRIBUTES (decl));
16597 : }
16598 :
16599 262 : if (VAR_P (decl)
16600 262 : && !is_global_var (decl)
16601 452 : && DECL_CONTEXT (decl) == current_function_decl)
16602 : {
16603 190 : tree c = gimplify_oacc_declare_1 (t);
16604 190 : if (c)
16605 : {
16606 116 : if (oacc_declare_returns == NULL)
16607 40 : oacc_declare_returns = new hash_map<tree, tree>;
16608 :
16609 116 : oacc_declare_returns->put (decl, c);
16610 : }
16611 : }
16612 :
16613 262 : if (gimplify_omp_ctxp)
16614 72 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_SEEN);
16615 : }
16616 :
16617 254 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
16618 : clauses);
16619 :
16620 254 : gimplify_seq_add_stmt (pre_p, stmt);
16621 :
16622 254 : *expr_p = NULL_TREE;
16623 254 : }
16624 :
16625 : /* Gimplify the contents of an OMP_PARALLEL statement. This involves
16626 : gimplification of the body, as well as scanning the body for used
16627 : variables. We need to do this scan now, because variable-sized
16628 : decls will be decomposed during gimplification. */
16629 :
16630 : static void
16631 18229 : gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
16632 : {
16633 18229 : tree expr = *expr_p;
16634 18229 : gimple *g;
16635 18229 : gimple_seq body = NULL;
16636 :
16637 36458 : gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
16638 18229 : OMP_PARALLEL_COMBINED (expr)
16639 : ? ORT_COMBINED_PARALLEL
16640 : : ORT_PARALLEL, OMP_PARALLEL);
16641 :
16642 18229 : push_gimplify_context ();
16643 :
16644 18229 : g = gimplify_and_return_first (OMP_PARALLEL_BODY (expr), &body);
16645 18229 : if (gimple_code (g) == GIMPLE_BIND)
16646 18229 : pop_gimplify_context (g);
16647 : else
16648 0 : pop_gimplify_context (NULL);
16649 :
16650 18229 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_PARALLEL_CLAUSES (expr),
16651 : OMP_PARALLEL);
16652 :
16653 36458 : g = gimple_build_omp_parallel (body,
16654 18229 : OMP_PARALLEL_CLAUSES (expr),
16655 : NULL_TREE, NULL_TREE);
16656 18229 : if (OMP_PARALLEL_COMBINED (expr))
16657 12536 : gimple_omp_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
16658 18229 : gimplify_seq_add_stmt (pre_p, g);
16659 18229 : *expr_p = NULL_TREE;
16660 18229 : }
16661 :
16662 : /* Gimplify the contents of an OMP_TASK statement. This involves
16663 : gimplification of the body, as well as scanning the body for used
16664 : variables. We need to do this scan now, because variable-sized
16665 : decls will be decomposed during gimplification. */
16666 :
16667 : static void
16668 3853 : gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
16669 : {
16670 3853 : tree expr = *expr_p;
16671 3853 : gimple *g;
16672 3853 : gimple_seq body = NULL;
16673 3853 : bool nowait = false;
16674 3853 : bool has_depend = false;
16675 :
16676 3853 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16677 : {
16678 240 : for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
16679 152 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
16680 : {
16681 110 : has_depend = true;
16682 110 : if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
16683 : {
16684 9 : error_at (OMP_CLAUSE_LOCATION (c),
16685 : "%<mutexinoutset%> kind in %<depend%> clause on a "
16686 : "%<taskwait%> construct");
16687 9 : break;
16688 : }
16689 : }
16690 42 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT)
16691 42 : nowait = true;
16692 97 : if (nowait && !has_depend)
16693 : {
16694 5 : error_at (EXPR_LOCATION (expr),
16695 : "%<taskwait%> construct with %<nowait%> clause but no "
16696 : "%<depend%> clauses");
16697 5 : *expr_p = NULL_TREE;
16698 5 : return;
16699 : }
16700 : }
16701 :
16702 11544 : gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
16703 3848 : omp_find_clause (OMP_TASK_CLAUSES (expr),
16704 : OMP_CLAUSE_UNTIED)
16705 : ? ORT_UNTIED_TASK : ORT_TASK, OMP_TASK);
16706 :
16707 3848 : if (OMP_TASK_BODY (expr))
16708 : {
16709 3756 : push_gimplify_context ();
16710 :
16711 3756 : g = gimplify_and_return_first (OMP_TASK_BODY (expr), &body);
16712 3756 : if (gimple_code (g) == GIMPLE_BIND)
16713 3756 : pop_gimplify_context (g);
16714 : else
16715 0 : pop_gimplify_context (NULL);
16716 : }
16717 :
16718 3848 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_TASK_CLAUSES (expr),
16719 : OMP_TASK);
16720 :
16721 7696 : g = gimple_build_omp_task (body,
16722 3848 : OMP_TASK_CLAUSES (expr),
16723 : NULL_TREE, NULL_TREE,
16724 : NULL_TREE, NULL_TREE, NULL_TREE);
16725 3848 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16726 92 : gimple_omp_task_set_taskwait_p (g, true);
16727 3848 : gimplify_seq_add_stmt (pre_p, g);
16728 3848 : *expr_p = NULL_TREE;
16729 : }
16730 :
16731 : /* Helper function for gimplify_omp_for. If *TP is not a gimple constant,
16732 : force it into a temporary initialized in PRE_P and add firstprivate clause
16733 : to ORIG_FOR_STMT. */
16734 :
16735 : static void
16736 4399 : gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p,
16737 : tree orig_for_stmt)
16738 : {
16739 4399 : if (*tp == NULL || is_gimple_constant (*tp))
16740 : return;
16741 :
16742 779 : if (TREE_CODE (*tp) == SAVE_EXPR)
16743 135 : gimplify_save_expr (tp, pre_p, NULL);
16744 : else
16745 644 : *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false);
16746 : /* Reference to pointer conversion is considered useless,
16747 : but is significant for firstprivate clause. Force it
16748 : here. */
16749 779 : if (type
16750 687 : && TREE_CODE (type) == POINTER_TYPE
16751 869 : && TREE_CODE (TREE_TYPE (*tp)) == REFERENCE_TYPE)
16752 : {
16753 2 : tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
16754 2 : tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, *tp);
16755 2 : gimplify_and_add (m, pre_p);
16756 2 : *tp = v;
16757 : }
16758 :
16759 779 : tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
16760 779 : OMP_CLAUSE_DECL (c) = *tp;
16761 779 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (orig_for_stmt);
16762 779 : OMP_FOR_CLAUSES (orig_for_stmt) = c;
16763 : }
16764 :
16765 : /* Helper function of gimplify_omp_for, find OMP_ORDERED with
16766 : null OMP_ORDERED_BODY inside of OMP_FOR's body. */
16767 :
16768 : static tree
16769 16496 : find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
16770 : {
16771 16496 : switch (TREE_CODE (*tp))
16772 : {
16773 901 : case OMP_ORDERED:
16774 901 : if (OMP_ORDERED_BODY (*tp) == NULL_TREE)
16775 : return *tp;
16776 : break;
16777 23 : case OMP_SIMD:
16778 23 : case OMP_PARALLEL:
16779 23 : case OMP_TARGET:
16780 23 : *walk_subtrees = 0;
16781 23 : break;
16782 : default:
16783 : break;
16784 : }
16785 : return NULL_TREE;
16786 : }
16787 :
16788 : /* Gimplify standalone loop transforming directive which has the
16789 : transformations applied already. So, all that is needed is gimplify
16790 : the remaining loops as normal loops. */
16791 :
16792 : static enum gimplify_status
16793 2264 : gimplify_omp_loop_xform (tree *expr_p, gimple_seq *pre_p)
16794 : {
16795 2264 : tree for_stmt = *expr_p;
16796 :
16797 2264 : if (OMP_FOR_PRE_BODY (for_stmt))
16798 759 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), pre_p);
16799 :
16800 2264 : gimple_seq pre_body = NULL, post_body = NULL;
16801 5203 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16802 : {
16803 2939 : if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE)
16804 1707 : continue;
16805 1283 : tree iters = NULL_TREE;
16806 1283 : if (i == 0
16807 826 : && TREE_CODE (for_stmt) == OMP_UNROLL
16808 1771 : && !omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_PARTIAL))
16809 : {
16810 311 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL))
16811 269 : iters = omp_loop_number_of_iterations (for_stmt, 0, NULL);
16812 : else
16813 42 : iters = build_int_cst (integer_type_node, 8);
16814 : }
16815 1283 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
16816 1283 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
16817 1283 : tree decl = TREE_OPERAND (t, 0);
16818 1283 : gcc_assert (DECL_P (decl));
16819 1283 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
16820 : || POINTER_TYPE_P (TREE_TYPE (decl)));
16821 1283 : if (DECL_ARTIFICIAL (decl)
16822 876 : && TREE_PRIVATE (t)
16823 867 : && gimplify_omp_ctxp
16824 1613 : && gimplify_omp_ctxp->region_type != ORT_NONE)
16825 : {
16826 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16827 504 : do
16828 : {
16829 504 : splay_tree_node n
16830 504 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16831 504 : if (n != NULL)
16832 : break;
16833 346 : else if (ctx->region_type != ORT_WORKSHARE
16834 : && ctx->region_type != ORT_TASKGROUP
16835 62 : && ctx->region_type != ORT_SIMD
16836 38 : && ctx->region_type != ORT_ACC
16837 38 : && !(ctx->region_type & ORT_TARGET_DATA))
16838 : {
16839 38 : omp_add_variable (ctx, decl, GOVD_PRIVATE);
16840 38 : break;
16841 : }
16842 308 : ctx = ctx->outer_context;
16843 : }
16844 308 : while (ctx);
16845 : }
16846 1283 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16847 : {
16848 23 : gcc_assert (seen_error ());
16849 23 : continue;
16850 : }
16851 1260 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16852 : fb_rvalue);
16853 1260 : gimplify_and_add (t, &pre_body);
16854 1260 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16855 1260 : gcc_assert (TREE_OPERAND (t, 0) == decl);
16856 1260 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16857 : {
16858 28 : gcc_assert (seen_error ());
16859 28 : continue;
16860 : }
16861 1232 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16862 : fb_rvalue);
16863 1232 : tree l1 = create_artificial_label (UNKNOWN_LOCATION);
16864 1232 : tree l2 = create_artificial_label (UNKNOWN_LOCATION);
16865 1232 : tree l3 = create_artificial_label (UNKNOWN_LOCATION);
16866 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_goto (l2));
16867 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_label (l1));
16868 1232 : gimple_seq this_post_body = NULL;
16869 1232 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
16870 1232 : if (TREE_CODE (t) == MODIFY_EXPR)
16871 : {
16872 975 : t = TREE_OPERAND (t, 1);
16873 975 : if (TREE_CODE (t) == PLUS_EXPR
16874 975 : && TREE_OPERAND (t, 1) == decl)
16875 : {
16876 0 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
16877 0 : TREE_OPERAND (t, 0) = decl;
16878 : }
16879 975 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16880 : fb_rvalue);
16881 : }
16882 1232 : gimplify_and_add (TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i),
16883 : &this_post_body);
16884 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l2));
16885 1232 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16886 1232 : gcond *cond = NULL;
16887 1232 : tree d = decl;
16888 1232 : gimplify_expr (&d, &this_post_body, NULL, is_gimple_val, fb_rvalue);
16889 1232 : if (iters && tree_fits_uhwi_p (iters))
16890 : {
16891 299 : unsigned HOST_WIDE_INT niters = tree_to_uhwi (iters);
16892 299 : if ((unsigned HOST_WIDE_INT) (int) niters == niters
16893 299 : && (int) niters > 0)
16894 : {
16895 299 : t = build2 (TREE_CODE (t), boolean_type_node, d,
16896 299 : TREE_OPERAND (t, 1));
16897 299 : t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t,
16898 : build_int_cst (integer_type_node,
16899 : annot_expr_unroll_kind),
16900 299 : build_int_cst (integer_type_node, niters));
16901 299 : gimplify_expr (&t, &this_post_body, NULL, is_gimple_val,
16902 : fb_rvalue);
16903 299 : cond = gimple_build_cond (NE_EXPR, t, boolean_false_node,
16904 : l1, l3);
16905 : }
16906 : }
16907 299 : if (cond == NULL)
16908 933 : cond = gimple_build_cond (TREE_CODE (t), d, TREE_OPERAND (t, 1),
16909 : l1, l3);
16910 1232 : gimplify_seq_add_stmt (&this_post_body, cond);
16911 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l3));
16912 1232 : gimplify_seq_add_seq (&this_post_body, post_body);
16913 1232 : post_body = this_post_body;
16914 : }
16915 2264 : gimplify_seq_add_seq (pre_p, pre_body);
16916 2264 : gimplify_and_add (OMP_FOR_BODY (for_stmt), pre_p);
16917 2264 : gimplify_seq_add_seq (pre_p, post_body);
16918 :
16919 2264 : *expr_p = NULL_TREE;
16920 2264 : return GS_ALL_DONE;
16921 : }
16922 :
16923 : /* Gimplify the gross structure of an OMP_FOR statement. */
16924 :
16925 : static enum gimplify_status
16926 58084 : gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
16927 : {
16928 58084 : tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t;
16929 58084 : enum gimplify_status ret = GS_ALL_DONE;
16930 58084 : enum gimplify_status tret;
16931 58084 : gomp_for *gfor;
16932 58084 : gimple_seq for_body, for_pre_body;
16933 58084 : int i;
16934 58084 : bitmap has_decl_expr = NULL;
16935 58084 : enum omp_region_type ort = ORT_WORKSHARE;
16936 58084 : bool openacc = TREE_CODE (*expr_p) == OACC_LOOP;
16937 :
16938 58084 : orig_for_stmt = for_stmt = *expr_p;
16939 :
16940 58084 : bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND)
16941 58084 : != NULL_TREE);
16942 58155 : while (OMP_FOR_INIT (for_stmt) == NULL_TREE)
16943 : {
16944 17738 : tree *data[4] = { NULL, NULL, NULL, NULL };
16945 17738 : gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
16946 17738 : inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt),
16947 : find_combined_omp_for, data, NULL);
16948 17738 : if (inner_for_stmt == NULL_TREE)
16949 : {
16950 36 : gcc_assert (seen_error ());
16951 36 : *expr_p = NULL_TREE;
16952 3741 : return GS_ERROR;
16953 : }
16954 17702 : gcc_assert (inner_for_stmt == *data[3]);
16955 17702 : omp_maybe_apply_loop_xforms (data[3],
16956 17702 : data[2]
16957 4279 : ? OMP_FOR_CLAUSES (*data[2])
16958 13423 : : TREE_CODE (for_stmt) == OMP_FOR
16959 13423 : ? OMP_FOR_CLAUSES (for_stmt)
16960 : : NULL_TREE);
16961 17702 : if (inner_for_stmt != *data[3])
16962 71 : continue;
16963 17631 : if (data[2] && OMP_FOR_PRE_BODY (*data[2]))
16964 : {
16965 2 : append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]),
16966 : &OMP_FOR_PRE_BODY (for_stmt));
16967 2 : OMP_FOR_PRE_BODY (*data[2]) = NULL_TREE;
16968 : }
16969 17631 : if (OMP_FOR_PRE_BODY (inner_for_stmt))
16970 : {
16971 7193 : append_to_statement_list_force (OMP_FOR_PRE_BODY (inner_for_stmt),
16972 : &OMP_FOR_PRE_BODY (for_stmt));
16973 7193 : OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
16974 : }
16975 :
16976 17631 : if (data[0])
16977 : {
16978 : /* We have some statements or variable declarations in between
16979 : the composite construct directives. Move them around the
16980 : inner_for_stmt. */
16981 3705 : data[0] = expr_p;
16982 14820 : for (i = 0; i < 3; i++)
16983 11115 : if (data[i])
16984 : {
16985 7028 : tree t = *data[i];
16986 7028 : if (i < 2 && data[i + 1] == &OMP_BODY (t))
16987 1005 : data[i + 1] = data[i];
16988 7028 : *data[i] = OMP_BODY (t);
16989 7028 : tree body = build3 (BIND_EXPR, void_type_node, NULL_TREE,
16990 : NULL_TREE, make_node (BLOCK));
16991 7028 : OMP_BODY (t) = body;
16992 7028 : append_to_statement_list_force (inner_for_stmt,
16993 : &BIND_EXPR_BODY (body));
16994 7028 : *data[3] = t;
16995 7028 : data[3] = tsi_stmt_ptr (tsi_start (BIND_EXPR_BODY (body)));
16996 7028 : gcc_assert (*data[3] == inner_for_stmt);
16997 : }
16998 : return GS_OK;
16999 : }
17000 :
17001 36734 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17002 22808 : if (!loop_p
17003 21927 : && OMP_FOR_ORIG_DECLS (inner_for_stmt)
17004 11098 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17005 : i)) == TREE_LIST
17006 22876 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17007 : i)))
17008 : {
17009 40 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17010 : /* Class iterators aren't allowed on OMP_SIMD, so the only
17011 : case we need to solve is distribute parallel for. They are
17012 : allowed on the loop construct, but that is already handled
17013 : in gimplify_omp_loop. */
17014 40 : gcc_assert (TREE_CODE (inner_for_stmt) == OMP_FOR
17015 : && TREE_CODE (for_stmt) == OMP_DISTRIBUTE
17016 : && data[1]);
17017 40 : tree orig_decl = TREE_PURPOSE (orig);
17018 40 : tree last = TREE_VALUE (orig);
17019 40 : tree *pc;
17020 40 : for (pc = &OMP_FOR_CLAUSES (inner_for_stmt);
17021 74 : *pc; pc = &OMP_CLAUSE_CHAIN (*pc))
17022 42 : if ((OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE
17023 35 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE)
17024 43 : && OMP_CLAUSE_DECL (*pc) == orig_decl)
17025 : break;
17026 40 : if (*pc == NULL_TREE)
17027 : {
17028 32 : tree *spc;
17029 32 : for (spc = &OMP_PARALLEL_CLAUSES (*data[1]);
17030 98 : *spc; spc = &OMP_CLAUSE_CHAIN (*spc))
17031 67 : if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE
17032 67 : && OMP_CLAUSE_DECL (*spc) == orig_decl)
17033 : break;
17034 32 : if (*spc)
17035 : {
17036 1 : tree c = *spc;
17037 1 : *spc = OMP_CLAUSE_CHAIN (c);
17038 1 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
17039 1 : *pc = c;
17040 : }
17041 : }
17042 40 : if (*pc == NULL_TREE)
17043 : ;
17044 9 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE)
17045 : {
17046 : /* private clause will appear only on inner_for_stmt.
17047 : Change it into firstprivate, and add private clause
17048 : on for_stmt. */
17049 8 : tree c = copy_node (*pc);
17050 8 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17051 8 : OMP_FOR_CLAUSES (for_stmt) = c;
17052 8 : OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE;
17053 8 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17054 : }
17055 : else
17056 : {
17057 : /* lastprivate clause will appear on both inner_for_stmt
17058 : and for_stmt. Add firstprivate clause to
17059 : inner_for_stmt. */
17060 1 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (*pc),
17061 : OMP_CLAUSE_FIRSTPRIVATE);
17062 1 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc);
17063 1 : OMP_CLAUSE_CHAIN (c) = *pc;
17064 1 : *pc = c;
17065 1 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17066 : }
17067 40 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17068 : OMP_CLAUSE_FIRSTPRIVATE);
17069 40 : OMP_CLAUSE_DECL (c) = last;
17070 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17071 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17072 40 : c = build_omp_clause (UNKNOWN_LOCATION,
17073 40 : *pc ? OMP_CLAUSE_SHARED
17074 : : OMP_CLAUSE_FIRSTPRIVATE);
17075 40 : OMP_CLAUSE_DECL (c) = orig_decl;
17076 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17077 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17078 : }
17079 : /* Similarly, take care of C++ range for temporaries, those should
17080 : be firstprivate on OMP_PARALLEL if any. */
17081 13926 : if (data[1])
17082 17503 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17083 11108 : if (OMP_FOR_ORIG_DECLS (inner_for_stmt)
17084 5733 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17085 : i)) == TREE_LIST
17086 11184 : && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17087 : i)))
17088 : {
17089 49 : tree orig
17090 49 : = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17091 49 : tree v = TREE_CHAIN (orig);
17092 49 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17093 : OMP_CLAUSE_FIRSTPRIVATE);
17094 : /* First add firstprivate clause for the __for_end artificial
17095 : decl. */
17096 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 1);
17097 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17098 : == REFERENCE_TYPE)
17099 0 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17100 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17101 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17102 49 : if (TREE_VEC_ELT (v, 0))
17103 : {
17104 : /* And now the same for __for_range artificial decl if it
17105 : exists. */
17106 49 : c = build_omp_clause (UNKNOWN_LOCATION,
17107 : OMP_CLAUSE_FIRSTPRIVATE);
17108 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 0);
17109 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17110 : == REFERENCE_TYPE)
17111 49 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17112 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17113 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17114 : }
17115 : }
17116 13926 : break;
17117 : }
17118 54343 : if (OMP_FOR_INIT (for_stmt) != NULL_TREE)
17119 : {
17120 40417 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
17121 40417 : if (*expr_p != for_stmt)
17122 : return GS_OK;
17123 : }
17124 :
17125 53461 : switch (TREE_CODE (for_stmt))
17126 : {
17127 18187 : case OMP_FOR:
17128 30405 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17129 : {
17130 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17131 : OMP_CLAUSE_SCHEDULE))
17132 47 : error_at (EXPR_LOCATION (for_stmt),
17133 : "%qs clause may not appear on non-rectangular %qs",
17134 27 : "schedule", lang_GNU_Fortran () ? "do" : "for");
17135 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED))
17136 34 : error_at (EXPR_LOCATION (for_stmt),
17137 : "%qs clause may not appear on non-rectangular %qs",
17138 18 : "ordered", lang_GNU_Fortran () ? "do" : "for");
17139 : }
17140 : break;
17141 8219 : case OMP_DISTRIBUTE:
17142 9130 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)
17143 8219 : && omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17144 : OMP_CLAUSE_DIST_SCHEDULE))
17145 29 : error_at (EXPR_LOCATION (for_stmt),
17146 : "%qs clause may not appear on non-rectangular %qs",
17147 : "dist_schedule", "distribute");
17148 : break;
17149 : case OACC_LOOP:
17150 : ort = ORT_ACC;
17151 : break;
17152 1586 : case OMP_TASKLOOP:
17153 2523 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17154 : {
17155 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17156 : OMP_CLAUSE_GRAINSIZE))
17157 11 : error_at (EXPR_LOCATION (for_stmt),
17158 : "%qs clause may not appear on non-rectangular %qs",
17159 : "grainsize", "taskloop");
17160 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17161 : OMP_CLAUSE_NUM_TASKS))
17162 6 : error_at (EXPR_LOCATION (for_stmt),
17163 : "%qs clause may not appear on non-rectangular %qs",
17164 : "num_tasks", "taskloop");
17165 : }
17166 1586 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED))
17167 : ort = ORT_UNTIED_TASKLOOP;
17168 : else
17169 : ort = ORT_TASKLOOP;
17170 : break;
17171 10653 : case OMP_SIMD:
17172 10653 : ort = ORT_SIMD;
17173 10653 : break;
17174 2264 : case OMP_TILE:
17175 2264 : case OMP_UNROLL:
17176 2264 : gcc_assert (inner_for_stmt == NULL_TREE);
17177 2264 : return gimplify_omp_loop_xform (expr_p, pre_p);
17178 0 : default:
17179 0 : gcc_unreachable ();
17180 : }
17181 :
17182 : /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear
17183 : clause for the IV. */
17184 10700 : if (ort == ORT_SIMD && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17185 : {
17186 7825 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0);
17187 7825 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17188 7825 : decl = TREE_OPERAND (t, 0);
17189 18635 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
17190 11924 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17191 11924 : && OMP_CLAUSE_DECL (c) == decl)
17192 : {
17193 1114 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17194 1114 : break;
17195 : }
17196 : }
17197 :
17198 51197 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP)
17199 51521 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort,
17200 1910 : loop_p && TREE_CODE (for_stmt) != OMP_SIMD
17201 : ? OMP_LOOP : TREE_CODE (for_stmt));
17202 :
17203 51197 : if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE)
17204 8219 : gimplify_omp_ctxp->distribute = true;
17205 :
17206 : /* Handle OMP_FOR_INIT. */
17207 51197 : for_pre_body = NULL;
17208 51197 : if ((ort == ORT_SIMD
17209 40544 : || (inner_for_stmt && TREE_CODE (inner_for_stmt) == OMP_SIMD))
17210 61937 : && OMP_FOR_PRE_BODY (for_stmt))
17211 : {
17212 6784 : has_decl_expr = BITMAP_ALLOC (NULL);
17213 6784 : if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR
17214 6784 : && VAR_P (DECL_EXPR_DECL (OMP_FOR_PRE_BODY (for_stmt))))
17215 : {
17216 18 : t = OMP_FOR_PRE_BODY (for_stmt);
17217 18 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17218 : }
17219 6766 : else if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == STATEMENT_LIST)
17220 : {
17221 6764 : tree_stmt_iterator si;
17222 11234 : for (si = tsi_start (OMP_FOR_PRE_BODY (for_stmt)); !tsi_end_p (si);
17223 4470 : tsi_next (&si))
17224 : {
17225 4470 : t = tsi_stmt (si);
17226 4470 : if (TREE_CODE (t) == DECL_EXPR
17227 4470 : && VAR_P (DECL_EXPR_DECL (t)))
17228 4397 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17229 : }
17230 : }
17231 : }
17232 51197 : if (OMP_FOR_PRE_BODY (for_stmt))
17233 : {
17234 20979 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp)
17235 20254 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17236 : else
17237 : {
17238 725 : struct gimplify_omp_ctx ctx;
17239 725 : memset (&ctx, 0, sizeof (ctx));
17240 725 : ctx.region_type = ORT_NONE;
17241 725 : gimplify_omp_ctxp = &ctx;
17242 725 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17243 725 : gimplify_omp_ctxp = NULL;
17244 : }
17245 : }
17246 51197 : OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
17247 :
17248 51197 : if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
17249 13926 : for_stmt = inner_for_stmt;
17250 :
17251 : /* For taskloop, need to gimplify the start, end and step before the
17252 : taskloop, outside of the taskloop omp context. */
17253 51197 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17254 : {
17255 3458 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17256 : {
17257 1872 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17258 1872 : gimple_seq *for_pre_p = (gimple_seq_empty_p (for_pre_body)
17259 1872 : ? pre_p : &for_pre_body);
17260 1872 : tree type = TREE_TYPE (TREE_OPERAND (t, 0));
17261 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17262 : {
17263 34 : tree v = TREE_OPERAND (t, 1);
17264 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17265 : for_pre_p, orig_for_stmt);
17266 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17267 : for_pre_p, orig_for_stmt);
17268 : }
17269 : else
17270 1838 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17271 : orig_for_stmt);
17272 :
17273 : /* Handle OMP_FOR_COND. */
17274 1872 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17275 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17276 : {
17277 31 : tree v = TREE_OPERAND (t, 1);
17278 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17279 : for_pre_p, orig_for_stmt);
17280 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17281 : for_pre_p, orig_for_stmt);
17282 : }
17283 : else
17284 1841 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17285 : orig_for_stmt);
17286 :
17287 : /* Handle OMP_FOR_INCR. */
17288 1872 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17289 1872 : if (TREE_CODE (t) == MODIFY_EXPR)
17290 : {
17291 590 : decl = TREE_OPERAND (t, 0);
17292 590 : t = TREE_OPERAND (t, 1);
17293 590 : tree *tp = &TREE_OPERAND (t, 1);
17294 590 : if (TREE_CODE (t) == PLUS_EXPR && *tp == decl)
17295 22 : tp = &TREE_OPERAND (t, 0);
17296 :
17297 590 : gimplify_omp_taskloop_expr (NULL_TREE, tp, for_pre_p,
17298 : orig_for_stmt);
17299 : }
17300 : }
17301 :
17302 1586 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort,
17303 : OMP_TASKLOOP);
17304 : }
17305 :
17306 51197 : if (orig_for_stmt != for_stmt)
17307 13926 : gimplify_omp_ctxp->combined_loop = true;
17308 :
17309 51197 : for_body = NULL;
17310 51197 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17311 : == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
17312 51197 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17313 : == TREE_VEC_LENGTH (OMP_FOR_INCR (for_stmt)));
17314 :
17315 51197 : tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
17316 51197 : bool is_doacross = false;
17317 51197 : if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
17318 : find_standalone_omp_ordered, NULL))
17319 : {
17320 531 : OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
17321 531 : is_doacross = true;
17322 531 : int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
17323 531 : gimplify_omp_ctxp->loop_iter_var.create (len * 2);
17324 2200 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
17325 1669 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
17326 : {
17327 10 : error_at (OMP_CLAUSE_LOCATION (*pc),
17328 : "%<linear%> clause may not be specified together "
17329 : "with %<ordered%> clause if stand-alone %<ordered%> "
17330 : "construct is nested in it");
17331 10 : *pc = OMP_CLAUSE_CHAIN (*pc);
17332 : }
17333 : else
17334 1659 : pc = &OMP_CLAUSE_CHAIN (*pc);
17335 : }
17336 51197 : int collapse = 1, tile = 0;
17337 51197 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
17338 51197 : if (c)
17339 13727 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
17340 51197 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
17341 51197 : if (c)
17342 384 : tile = list_length (OMP_CLAUSE_TILE_LIST (c));
17343 51197 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
17344 51197 : hash_set<tree> *allocate_uids = NULL;
17345 51197 : if (c)
17346 : {
17347 275 : allocate_uids = new hash_set<tree>;
17348 1682 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17349 1132 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
17350 478 : allocate_uids->add (OMP_CLAUSE_DECL (c));
17351 : }
17352 124140 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17353 : {
17354 72943 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17355 72943 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17356 72943 : decl = TREE_OPERAND (t, 0);
17357 72943 : gcc_assert (DECL_P (decl));
17358 72943 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
17359 : || POINTER_TYPE_P (TREE_TYPE (decl)));
17360 72943 : if (is_doacross)
17361 : {
17362 1654 : if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt))
17363 : {
17364 960 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17365 960 : if (TREE_CODE (orig_decl) == TREE_LIST)
17366 : {
17367 15 : orig_decl = TREE_PURPOSE (orig_decl);
17368 15 : if (!orig_decl)
17369 0 : orig_decl = decl;
17370 : }
17371 960 : gimplify_omp_ctxp->loop_iter_var.quick_push (orig_decl);
17372 : }
17373 : else
17374 694 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17375 1654 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17376 : }
17377 :
17378 72943 : if (for_stmt == orig_for_stmt)
17379 : {
17380 50135 : tree orig_decl = decl;
17381 50135 : if (OMP_FOR_ORIG_DECLS (for_stmt))
17382 : {
17383 23916 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17384 23916 : if (TREE_CODE (orig_decl) == TREE_LIST)
17385 : {
17386 : orig_decl = TREE_PURPOSE (orig_decl);
17387 : if (!orig_decl)
17388 : orig_decl = decl;
17389 : }
17390 : }
17391 50135 : if (is_global_var (orig_decl) && DECL_THREAD_LOCAL_P (orig_decl))
17392 36 : error_at (EXPR_LOCATION (for_stmt),
17393 : "threadprivate iteration variable %qD", orig_decl);
17394 : }
17395 :
17396 : /* Make sure the iteration variable is private. */
17397 72943 : tree c = NULL_TREE;
17398 72943 : tree c2 = NULL_TREE;
17399 72943 : if (orig_for_stmt != for_stmt)
17400 : {
17401 : /* Preserve this information until we gimplify the inner simd. */
17402 22808 : if (has_decl_expr
17403 22808 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17404 3413 : TREE_PRIVATE (t) = 1;
17405 : }
17406 50135 : else if (ort == ORT_SIMD)
17407 : {
17408 15726 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17409 : (splay_tree_key) decl);
17410 15726 : omp_is_private (gimplify_omp_ctxp, decl,
17411 15726 : 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17412 : != 1));
17413 15726 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
17414 : {
17415 2518 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17416 2518 : if (n->value & GOVD_LASTPRIVATE_CONDITIONAL)
17417 0 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17418 : OMP_CLAUSE_LASTPRIVATE);
17419 0 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17420 : OMP_CLAUSE_LASTPRIVATE))
17421 0 : if (OMP_CLAUSE_DECL (c3) == decl)
17422 : {
17423 0 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17424 : "conditional %<lastprivate%> on loop "
17425 : "iterator %qD ignored", decl);
17426 0 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17427 0 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17428 : }
17429 : }
17430 13208 : else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1 && !loop_p)
17431 : {
17432 5637 : c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17433 5637 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17434 5637 : unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN;
17435 5637 : if ((has_decl_expr
17436 1309 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17437 6321 : || TREE_PRIVATE (t))
17438 : {
17439 2281 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17440 2281 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17441 : }
17442 5637 : struct gimplify_omp_ctx *outer
17443 5637 : = gimplify_omp_ctxp->outer_context;
17444 5637 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17445 : {
17446 2433 : if (outer->region_type == ORT_WORKSHARE
17447 2193 : && outer->combined_loop)
17448 : {
17449 2142 : n = splay_tree_lookup (outer->variables,
17450 : (splay_tree_key)decl);
17451 2142 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17452 : {
17453 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17454 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17455 : }
17456 : else
17457 : {
17458 2142 : struct gimplify_omp_ctx *octx = outer->outer_context;
17459 2142 : if (octx
17460 1714 : && octx->region_type == ORT_COMBINED_PARALLEL
17461 1476 : && octx->outer_context
17462 1209 : && (octx->outer_context->region_type
17463 : == ORT_WORKSHARE)
17464 1079 : && octx->outer_context->combined_loop)
17465 : {
17466 1079 : octx = octx->outer_context;
17467 1079 : n = splay_tree_lookup (octx->variables,
17468 : (splay_tree_key)decl);
17469 1079 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17470 : {
17471 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17472 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17473 : }
17474 : }
17475 : }
17476 : }
17477 : }
17478 :
17479 5637 : OMP_CLAUSE_DECL (c) = decl;
17480 5637 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17481 5637 : OMP_FOR_CLAUSES (for_stmt) = c;
17482 5637 : omp_add_variable (gimplify_omp_ctxp, decl, flags);
17483 5637 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17484 2433 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17485 : true);
17486 : }
17487 : else
17488 : {
17489 7571 : bool lastprivate
17490 : = (!has_decl_expr
17491 7571 : || !bitmap_bit_p (has_decl_expr, DECL_UID (decl)));
17492 7571 : if (TREE_PRIVATE (t))
17493 1787 : lastprivate = false;
17494 7571 : if (loop_p && OMP_FOR_ORIG_DECLS (for_stmt))
17495 : {
17496 509 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17497 509 : if (TREE_CODE (elt) == TREE_LIST && TREE_PURPOSE (elt))
17498 : lastprivate = false;
17499 : }
17500 :
17501 7571 : struct gimplify_omp_ctx *outer
17502 7571 : = gimplify_omp_ctxp->outer_context;
17503 7571 : if (outer && lastprivate)
17504 4887 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17505 : true);
17506 :
17507 9577 : c = build_omp_clause (input_location,
17508 : lastprivate ? OMP_CLAUSE_LASTPRIVATE
17509 : : OMP_CLAUSE_PRIVATE);
17510 7571 : OMP_CLAUSE_DECL (c) = decl;
17511 7571 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17512 7571 : OMP_FOR_CLAUSES (for_stmt) = c;
17513 7571 : omp_add_variable (gimplify_omp_ctxp, decl,
17514 : (lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE)
17515 : | GOVD_EXPLICIT | GOVD_SEEN);
17516 7571 : c = NULL_TREE;
17517 : }
17518 : }
17519 34409 : else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
17520 : {
17521 8735 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17522 8735 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17523 : (splay_tree_key) decl);
17524 8735 : if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL))
17525 80 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17526 : OMP_CLAUSE_LASTPRIVATE);
17527 80 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17528 : OMP_CLAUSE_LASTPRIVATE))
17529 40 : if (OMP_CLAUSE_DECL (c3) == decl)
17530 : {
17531 40 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17532 : "conditional %<lastprivate%> on loop "
17533 : "iterator %qD ignored", decl);
17534 40 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17535 40 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17536 : }
17537 : }
17538 : else
17539 25674 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
17540 :
17541 : /* If DECL is not a gimple register, create a temporary variable to act
17542 : as an iteration counter. This is valid, since DECL cannot be
17543 : modified in the body of the loop. Similarly for any iteration vars
17544 : in simd with collapse > 1 where the iterator vars must be
17545 : lastprivate. And similarly for vars mentioned in allocate clauses. */
17546 72943 : if (orig_for_stmt != for_stmt)
17547 22808 : var = decl;
17548 50135 : else if (!is_gimple_reg (decl)
17549 46868 : || (ort == ORT_SIMD
17550 14125 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
17551 89933 : || (allocate_uids && allocate_uids->contains (decl)))
17552 : {
17553 10369 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17554 : /* Make sure omp_add_variable is not called on it prematurely.
17555 : We call it ourselves a few lines later. */
17556 10369 : gimplify_omp_ctxp = NULL;
17557 10369 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17558 10369 : gimplify_omp_ctxp = ctx;
17559 10369 : TREE_OPERAND (t, 0) = var;
17560 :
17561 10369 : gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
17562 :
17563 10369 : if (ort == ORT_SIMD
17564 10369 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17565 : {
17566 770 : c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17567 770 : OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1;
17568 770 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1;
17569 770 : OMP_CLAUSE_DECL (c2) = var;
17570 770 : OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt);
17571 770 : OMP_FOR_CLAUSES (for_stmt) = c2;
17572 770 : omp_add_variable (gimplify_omp_ctxp, var,
17573 : GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
17574 770 : if (c == NULL_TREE)
17575 : {
17576 518 : c = c2;
17577 518 : c2 = NULL_TREE;
17578 : }
17579 : }
17580 : else
17581 9599 : omp_add_variable (gimplify_omp_ctxp, var,
17582 : GOVD_PRIVATE | GOVD_SEEN);
17583 : }
17584 : else
17585 : var = decl;
17586 :
17587 72943 : gimplify_omp_ctxp->in_for_exprs = true;
17588 72943 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17589 : {
17590 719 : tree lb = TREE_OPERAND (t, 1);
17591 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL,
17592 : is_gimple_val, fb_rvalue, false);
17593 719 : ret = MIN (ret, tret);
17594 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL,
17595 : is_gimple_val, fb_rvalue, false);
17596 : }
17597 : else
17598 72224 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17599 : is_gimple_val, fb_rvalue, false);
17600 72943 : gimplify_omp_ctxp->in_for_exprs = false;
17601 72943 : ret = MIN (ret, tret);
17602 72943 : if (ret == GS_ERROR)
17603 : return ret;
17604 :
17605 : /* Handle OMP_FOR_COND. */
17606 72943 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17607 72943 : gcc_assert (COMPARISON_CLASS_P (t));
17608 72943 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17609 :
17610 72943 : gimplify_omp_ctxp->in_for_exprs = true;
17611 72943 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17612 : {
17613 599 : tree ub = TREE_OPERAND (t, 1);
17614 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL,
17615 : is_gimple_val, fb_rvalue, false);
17616 599 : ret = MIN (ret, tret);
17617 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL,
17618 : is_gimple_val, fb_rvalue, false);
17619 : }
17620 : else
17621 72344 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17622 : is_gimple_val, fb_rvalue, false);
17623 72943 : gimplify_omp_ctxp->in_for_exprs = false;
17624 72943 : ret = MIN (ret, tret);
17625 :
17626 : /* Handle OMP_FOR_INCR. */
17627 72943 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17628 72943 : switch (TREE_CODE (t))
17629 : {
17630 35676 : case PREINCREMENT_EXPR:
17631 35676 : case POSTINCREMENT_EXPR:
17632 35676 : {
17633 35676 : tree decl = TREE_OPERAND (t, 0);
17634 : /* c_omp_for_incr_canonicalize_ptr() should have been
17635 : called to massage things appropriately. */
17636 35676 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17637 :
17638 35676 : if (orig_for_stmt != for_stmt)
17639 : break;
17640 25291 : t = build_int_cst (TREE_TYPE (decl), 1);
17641 25291 : if (c)
17642 4470 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17643 25291 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17644 25291 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17645 25291 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17646 25291 : break;
17647 : }
17648 :
17649 3830 : case PREDECREMENT_EXPR:
17650 3830 : case POSTDECREMENT_EXPR:
17651 : /* c_omp_for_incr_canonicalize_ptr() should have been
17652 : called to massage things appropriately. */
17653 3830 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17654 3830 : if (orig_for_stmt != for_stmt)
17655 : break;
17656 1992 : t = build_int_cst (TREE_TYPE (decl), -1);
17657 1992 : if (c)
17658 112 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17659 1992 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17660 1992 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17661 1992 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17662 1992 : break;
17663 :
17664 33437 : case MODIFY_EXPR:
17665 33437 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17666 33437 : TREE_OPERAND (t, 0) = var;
17667 :
17668 33437 : t = TREE_OPERAND (t, 1);
17669 33437 : switch (TREE_CODE (t))
17670 : {
17671 26505 : case PLUS_EXPR:
17672 26505 : if (TREE_OPERAND (t, 1) == decl)
17673 : {
17674 215 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
17675 215 : TREE_OPERAND (t, 0) = var;
17676 215 : break;
17677 : }
17678 :
17679 : /* Fallthru. */
17680 33222 : case MINUS_EXPR:
17681 33222 : case POINTER_PLUS_EXPR:
17682 33222 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17683 33222 : TREE_OPERAND (t, 0) = var;
17684 33222 : break;
17685 0 : default:
17686 0 : gcc_unreachable ();
17687 : }
17688 :
17689 33437 : gimplify_omp_ctxp->in_for_exprs = true;
17690 33437 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17691 : is_gimple_val, fb_rvalue, false);
17692 33437 : ret = MIN (ret, tret);
17693 33437 : if (c)
17694 : {
17695 1573 : tree step = TREE_OPERAND (t, 1);
17696 1573 : tree stept = TREE_TYPE (decl);
17697 1573 : if (POINTER_TYPE_P (stept))
17698 280 : stept = sizetype;
17699 1573 : step = fold_convert (stept, step);
17700 1573 : if (TREE_CODE (t) == MINUS_EXPR)
17701 295 : step = fold_build1 (NEGATE_EXPR, stept, step);
17702 1573 : OMP_CLAUSE_LINEAR_STEP (c) = step;
17703 1573 : if (step != TREE_OPERAND (t, 1))
17704 : {
17705 295 : tret = gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c),
17706 : &for_pre_body, NULL,
17707 : is_gimple_val, fb_rvalue, false);
17708 295 : ret = MIN (ret, tret);
17709 : }
17710 : }
17711 33437 : gimplify_omp_ctxp->in_for_exprs = false;
17712 33437 : break;
17713 :
17714 0 : default:
17715 0 : gcc_unreachable ();
17716 : }
17717 :
17718 72943 : if (c2)
17719 : {
17720 252 : gcc_assert (c);
17721 252 : OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
17722 : }
17723 :
17724 72943 : if ((var != decl || collapse > 1 || tile) && orig_for_stmt == for_stmt)
17725 : {
17726 86698 : for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
17727 65136 : if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
17728 16218 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
17729 56127 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17730 2159 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)
17731 1373 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
17732 75496 : && OMP_CLAUSE_DECL (c) == decl)
17733 : {
17734 7535 : if (is_doacross && (collapse == 1 || i >= collapse))
17735 : t = var;
17736 : else
17737 : {
17738 7462 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17739 7462 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17740 7462 : gcc_assert (TREE_OPERAND (t, 0) == var);
17741 7462 : t = TREE_OPERAND (t, 1);
17742 7462 : gcc_assert (TREE_CODE (t) == PLUS_EXPR
17743 : || TREE_CODE (t) == MINUS_EXPR
17744 : || TREE_CODE (t) == POINTER_PLUS_EXPR);
17745 7462 : gcc_assert (TREE_OPERAND (t, 0) == var);
17746 14822 : t = build2 (TREE_CODE (t), TREE_TYPE (decl),
17747 : is_doacross ? var : decl,
17748 7462 : TREE_OPERAND (t, 1));
17749 : }
17750 7535 : gimple_seq *seq;
17751 7535 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
17752 6939 : seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
17753 : else
17754 596 : seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c);
17755 7535 : push_gimplify_context ();
17756 7535 : gimplify_assign (decl, t, seq);
17757 7535 : gimple *bind = NULL;
17758 7535 : if (gimplify_ctxp->temps)
17759 : {
17760 2072 : bind = gimple_build_bind (NULL_TREE, *seq, NULL_TREE);
17761 2072 : *seq = NULL;
17762 2072 : gimplify_seq_add_stmt (seq, bind);
17763 : }
17764 7535 : pop_gimplify_context (bind);
17765 : }
17766 : }
17767 72943 : if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl)
17768 2609 : for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17769 : {
17770 1197 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17771 1197 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17772 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17773 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17774 336 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17775 1197 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17776 1197 : gcc_assert (COMPARISON_CLASS_P (t));
17777 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17778 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17779 343 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17780 : }
17781 : }
17782 :
17783 51197 : BITMAP_FREE (has_decl_expr);
17784 51472 : delete allocate_uids;
17785 :
17786 51197 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17787 49611 : || (loop_p && orig_for_stmt == for_stmt))
17788 : {
17789 2642 : push_gimplify_context ();
17790 2642 : if (TREE_CODE (OMP_FOR_BODY (orig_for_stmt)) != BIND_EXPR)
17791 : {
17792 1891 : OMP_FOR_BODY (orig_for_stmt)
17793 1891 : = build3 (BIND_EXPR, void_type_node, NULL,
17794 1891 : OMP_FOR_BODY (orig_for_stmt), NULL);
17795 1891 : TREE_SIDE_EFFECTS (OMP_FOR_BODY (orig_for_stmt)) = 1;
17796 : }
17797 : }
17798 :
17799 51197 : gimple *g = gimplify_and_return_first (OMP_FOR_BODY (orig_for_stmt),
17800 : &for_body);
17801 :
17802 51197 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17803 49611 : || (loop_p && orig_for_stmt == for_stmt))
17804 : {
17805 2642 : if (gimple_code (g) == GIMPLE_BIND)
17806 2642 : pop_gimplify_context (g);
17807 : else
17808 0 : pop_gimplify_context (NULL);
17809 : }
17810 :
17811 51197 : if (orig_for_stmt != for_stmt)
17812 36734 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17813 : {
17814 22808 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17815 22808 : decl = TREE_OPERAND (t, 0);
17816 22808 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17817 22808 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17818 772 : gimplify_omp_ctxp = ctx->outer_context;
17819 22808 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17820 22808 : gimplify_omp_ctxp = ctx;
17821 22808 : omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
17822 22808 : TREE_OPERAND (t, 0) = var;
17823 22808 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17824 22808 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17825 22808 : TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
17826 22808 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
17827 791 : for (int j = i + 1;
17828 791 : j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17829 : {
17830 377 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17831 377 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17832 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17833 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17834 : {
17835 133 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17836 133 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17837 : }
17838 377 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17839 377 : gcc_assert (COMPARISON_CLASS_P (t));
17840 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17841 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17842 : {
17843 67 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17844 67 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17845 : }
17846 : }
17847 : }
17848 :
17849 51197 : gimplify_adjust_omp_clauses (pre_p, for_body,
17850 : &OMP_FOR_CLAUSES (orig_for_stmt),
17851 51197 : TREE_CODE (orig_for_stmt));
17852 :
17853 51197 : int kind;
17854 51197 : switch (TREE_CODE (orig_for_stmt))
17855 : {
17856 : case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
17857 10653 : case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
17858 8219 : case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
17859 1586 : case OMP_TASKLOOP: kind = GF_OMP_FOR_KIND_TASKLOOP; break;
17860 12552 : case OACC_LOOP: kind = GF_OMP_FOR_KIND_OACC_LOOP; break;
17861 0 : default:
17862 0 : gcc_unreachable ();
17863 : }
17864 51197 : if (loop_p && kind == GF_OMP_FOR_KIND_SIMD)
17865 : {
17866 1056 : gimplify_seq_add_seq (pre_p, for_pre_body);
17867 1056 : for_pre_body = NULL;
17868 : }
17869 51197 : gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
17870 51197 : TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
17871 : for_pre_body);
17872 51197 : if (orig_for_stmt != for_stmt)
17873 13926 : gimple_omp_for_set_combined_p (gfor, true);
17874 51197 : if (gimplify_omp_ctxp
17875 42569 : && (gimplify_omp_ctxp->combined_loop
17876 35038 : || (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
17877 12299 : && gimplify_omp_ctxp->outer_context
17878 7858 : && gimplify_omp_ctxp->outer_context->combined_loop)))
17879 : {
17880 13926 : gimple_omp_for_set_combined_into_p (gfor, true);
17881 13926 : if (gimplify_omp_ctxp->combined_loop)
17882 7531 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_SIMD);
17883 : else
17884 6395 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_FOR);
17885 : }
17886 :
17887 124140 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17888 : {
17889 72943 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17890 72943 : gimple_omp_for_set_index (gfor, i, TREE_OPERAND (t, 0));
17891 72943 : gimple_omp_for_set_initial (gfor, i, TREE_OPERAND (t, 1));
17892 72943 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17893 72943 : gimple_omp_for_set_cond (gfor, i, TREE_CODE (t));
17894 72943 : gimple_omp_for_set_final (gfor, i, TREE_OPERAND (t, 1));
17895 72943 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17896 72943 : gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1));
17897 : }
17898 :
17899 : /* OMP_TASKLOOP is gimplified as two GIMPLE_OMP_FOR taskloop
17900 : constructs with GIMPLE_OMP_TASK sandwiched in between them.
17901 : The outer taskloop stands for computing the number of iterations,
17902 : counts for collapsed loops and holding taskloop specific clauses.
17903 : The task construct stands for the effect of data sharing on the
17904 : explicit task it creates and the inner taskloop stands for expansion
17905 : of the static loop inside of the explicit task construct. */
17906 51197 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17907 : {
17908 1586 : tree *gfor_clauses_ptr = gimple_omp_for_clauses_ptr (gfor);
17909 1586 : tree task_clauses = NULL_TREE;
17910 1586 : tree c = *gfor_clauses_ptr;
17911 1586 : tree *gtask_clauses_ptr = &task_clauses;
17912 1586 : tree outer_for_clauses = NULL_TREE;
17913 1586 : tree *gforo_clauses_ptr = &outer_for_clauses;
17914 1586 : bitmap lastprivate_uids = NULL;
17915 1586 : if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
17916 : {
17917 36 : c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
17918 36 : if (c)
17919 : {
17920 18 : lastprivate_uids = BITMAP_ALLOC (NULL);
17921 54 : for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
17922 : OMP_CLAUSE_LASTPRIVATE))
17923 18 : bitmap_set_bit (lastprivate_uids,
17924 18 : DECL_UID (OMP_CLAUSE_DECL (c)));
17925 : }
17926 36 : c = *gfor_clauses_ptr;
17927 : }
17928 12252 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17929 10666 : switch (OMP_CLAUSE_CODE (c))
17930 : {
17931 : /* These clauses are allowed on task, move them there. */
17932 6228 : case OMP_CLAUSE_SHARED:
17933 6228 : case OMP_CLAUSE_FIRSTPRIVATE:
17934 6228 : case OMP_CLAUSE_DEFAULT:
17935 6228 : case OMP_CLAUSE_IF:
17936 6228 : case OMP_CLAUSE_UNTIED:
17937 6228 : case OMP_CLAUSE_FINAL:
17938 6228 : case OMP_CLAUSE_MERGEABLE:
17939 6228 : case OMP_CLAUSE_PRIORITY:
17940 6228 : case OMP_CLAUSE_REDUCTION:
17941 6228 : case OMP_CLAUSE_IN_REDUCTION:
17942 6228 : *gtask_clauses_ptr = c;
17943 6228 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17944 6228 : break;
17945 2068 : case OMP_CLAUSE_PRIVATE:
17946 2068 : if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
17947 : {
17948 : /* We want private on outer for and firstprivate
17949 : on task. */
17950 26 : *gtask_clauses_ptr
17951 26 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
17952 : OMP_CLAUSE_FIRSTPRIVATE);
17953 26 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
17954 26 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
17955 : openacc);
17956 26 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
17957 26 : *gforo_clauses_ptr = c;
17958 26 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17959 : }
17960 : else
17961 : {
17962 2042 : *gtask_clauses_ptr = c;
17963 2042 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17964 : }
17965 : break;
17966 : /* These clauses go into outer taskloop clauses. */
17967 533 : case OMP_CLAUSE_GRAINSIZE:
17968 533 : case OMP_CLAUSE_NUM_TASKS:
17969 533 : case OMP_CLAUSE_NOGROUP:
17970 533 : *gforo_clauses_ptr = c;
17971 533 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17972 533 : break;
17973 : /* Collapse clause we duplicate on both taskloops. */
17974 584 : case OMP_CLAUSE_COLLAPSE:
17975 584 : *gfor_clauses_ptr = c;
17976 584 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17977 584 : *gforo_clauses_ptr = copy_node (c);
17978 584 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
17979 584 : break;
17980 : /* For lastprivate, keep the clause on inner taskloop, and add
17981 : a shared clause on task. If the same decl is also firstprivate,
17982 : add also firstprivate clause on the inner taskloop. */
17983 1191 : case OMP_CLAUSE_LASTPRIVATE:
17984 1191 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
17985 : {
17986 : /* For taskloop C++ lastprivate IVs, we want:
17987 : 1) private on outer taskloop
17988 : 2) firstprivate and shared on task
17989 : 3) lastprivate on inner taskloop */
17990 38 : *gtask_clauses_ptr
17991 38 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
17992 : OMP_CLAUSE_FIRSTPRIVATE);
17993 38 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
17994 38 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
17995 : openacc);
17996 38 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
17997 38 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
17998 38 : *gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
17999 : OMP_CLAUSE_PRIVATE);
18000 38 : OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
18001 38 : OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
18002 38 : TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
18003 38 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18004 : }
18005 1191 : *gfor_clauses_ptr = c;
18006 1191 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18007 1191 : *gtask_clauses_ptr
18008 1191 : = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_SHARED);
18009 1191 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18010 1191 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
18011 312 : OMP_CLAUSE_SHARED_FIRSTPRIVATE (*gtask_clauses_ptr) = 1;
18012 1191 : gtask_clauses_ptr
18013 1191 : = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18014 1191 : break;
18015 : /* Allocate clause we duplicate on task and inner taskloop
18016 : if the decl is lastprivate, otherwise just put on task. */
18017 62 : case OMP_CLAUSE_ALLOCATE:
18018 62 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
18019 62 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
18020 : {
18021 : /* Additionally, put firstprivate clause on task
18022 : for the allocator if it is not constant. */
18023 34 : *gtask_clauses_ptr
18024 34 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18025 : OMP_CLAUSE_FIRSTPRIVATE);
18026 34 : OMP_CLAUSE_DECL (*gtask_clauses_ptr)
18027 34 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
18028 34 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18029 : }
18030 62 : if (lastprivate_uids
18031 97 : && bitmap_bit_p (lastprivate_uids,
18032 35 : DECL_UID (OMP_CLAUSE_DECL (c))))
18033 : {
18034 17 : *gfor_clauses_ptr = c;
18035 17 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18036 17 : *gtask_clauses_ptr = copy_node (c);
18037 17 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18038 : }
18039 : else
18040 : {
18041 45 : *gtask_clauses_ptr = c;
18042 45 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18043 : }
18044 : break;
18045 0 : default:
18046 0 : gcc_unreachable ();
18047 : }
18048 1586 : *gfor_clauses_ptr = NULL_TREE;
18049 1586 : *gtask_clauses_ptr = NULL_TREE;
18050 1586 : *gforo_clauses_ptr = NULL_TREE;
18051 1586 : BITMAP_FREE (lastprivate_uids);
18052 1586 : gimple_set_location (gfor, input_location);
18053 1586 : g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
18054 1586 : g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
18055 : NULL_TREE, NULL_TREE, NULL_TREE);
18056 1586 : gimple_set_location (g, input_location);
18057 1586 : gimple_omp_task_set_taskloop_p (g, true);
18058 1586 : g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
18059 1586 : gomp_for *gforo
18060 1586 : = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
18061 : gimple_omp_for_collapse (gfor),
18062 : gimple_omp_for_pre_body (gfor));
18063 1586 : gimple_omp_for_set_pre_body (gfor, NULL);
18064 1586 : gimple_omp_for_set_combined_p (gforo, true);
18065 1586 : gimple_omp_for_set_combined_into_p (gfor, true);
18066 3458 : for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
18067 : {
18068 1872 : tree type = TREE_TYPE (gimple_omp_for_index (gfor, i));
18069 1872 : tree v = create_tmp_var (type);
18070 1872 : gimple_omp_for_set_index (gforo, i, v);
18071 1872 : t = unshare_expr (gimple_omp_for_initial (gfor, i));
18072 1872 : gimple_omp_for_set_initial (gforo, i, t);
18073 1872 : gimple_omp_for_set_cond (gforo, i,
18074 : gimple_omp_for_cond (gfor, i));
18075 1872 : t = unshare_expr (gimple_omp_for_final (gfor, i));
18076 1872 : gimple_omp_for_set_final (gforo, i, t);
18077 1872 : t = unshare_expr (gimple_omp_for_incr (gfor, i));
18078 1872 : gcc_assert (TREE_OPERAND (t, 0) == gimple_omp_for_index (gfor, i));
18079 1872 : TREE_OPERAND (t, 0) = v;
18080 1872 : gimple_omp_for_set_incr (gforo, i, t);
18081 1872 : t = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
18082 1872 : OMP_CLAUSE_DECL (t) = v;
18083 1872 : OMP_CLAUSE_CHAIN (t) = gimple_omp_for_clauses (gforo);
18084 1872 : gimple_omp_for_set_clauses (gforo, t);
18085 1872 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
18086 : {
18087 90 : tree *p1 = NULL, *p2 = NULL;
18088 90 : t = gimple_omp_for_initial (gforo, i);
18089 90 : if (TREE_CODE (t) == TREE_VEC)
18090 34 : p1 = &TREE_VEC_ELT (t, 0);
18091 90 : t = gimple_omp_for_final (gforo, i);
18092 90 : if (TREE_CODE (t) == TREE_VEC)
18093 : {
18094 31 : if (p1)
18095 23 : p2 = &TREE_VEC_ELT (t, 0);
18096 : else
18097 8 : p1 = &TREE_VEC_ELT (t, 0);
18098 : }
18099 90 : if (p1)
18100 : {
18101 : int j;
18102 58 : for (j = 0; j < i; j++)
18103 58 : if (*p1 == gimple_omp_for_index (gfor, j))
18104 : {
18105 42 : *p1 = gimple_omp_for_index (gforo, j);
18106 42 : if (p2)
18107 23 : *p2 = *p1;
18108 : break;
18109 : }
18110 42 : gcc_assert (j < i);
18111 : }
18112 : }
18113 : }
18114 1586 : gimplify_seq_add_stmt (pre_p, gforo);
18115 : }
18116 : else
18117 49611 : gimplify_seq_add_stmt (pre_p, gfor);
18118 :
18119 51197 : if (TREE_CODE (orig_for_stmt) == OMP_FOR)
18120 : {
18121 18187 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
18122 18187 : unsigned lastprivate_conditional = 0;
18123 18187 : while (ctx
18124 18223 : && (ctx->region_type == ORT_TARGET_DATA
18125 14185 : || ctx->region_type == ORT_TASKGROUP))
18126 36 : ctx = ctx->outer_context;
18127 18187 : if (ctx && (ctx->region_type & ORT_PARALLEL) != 0)
18128 13925 : for (tree c = gimple_omp_for_clauses (gfor);
18129 63177 : c; c = OMP_CLAUSE_CHAIN (c))
18130 49252 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18131 49252 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18132 158 : ++lastprivate_conditional;
18133 13925 : if (lastprivate_conditional)
18134 : {
18135 118 : struct omp_for_data fd;
18136 118 : omp_extract_for_data (gfor, &fd, NULL);
18137 118 : tree type = build_array_type_nelts (unsigned_type_for (fd.iter_type),
18138 118 : lastprivate_conditional);
18139 118 : tree var = create_tmp_var_raw (type);
18140 118 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
18141 118 : OMP_CLAUSE_DECL (c) = var;
18142 118 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18143 118 : gimple_omp_for_set_clauses (gfor, c);
18144 118 : omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
18145 : }
18146 : }
18147 33010 : else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
18148 : {
18149 10653 : unsigned lastprivate_conditional = 0;
18150 49159 : for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
18151 38506 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18152 38506 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18153 119 : ++lastprivate_conditional;
18154 10653 : if (lastprivate_conditional)
18155 : {
18156 91 : struct omp_for_data fd;
18157 91 : omp_extract_for_data (gfor, &fd, NULL);
18158 91 : tree type = unsigned_type_for (fd.iter_type);
18159 301 : while (lastprivate_conditional--)
18160 : {
18161 119 : tree c = build_omp_clause (UNKNOWN_LOCATION,
18162 : OMP_CLAUSE__CONDTEMP_);
18163 119 : OMP_CLAUSE_DECL (c) = create_tmp_var (type);
18164 119 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18165 119 : gimple_omp_for_set_clauses (gfor, c);
18166 : }
18167 : }
18168 : }
18169 :
18170 51197 : if (ret != GS_ALL_DONE)
18171 : return GS_ERROR;
18172 51197 : *expr_p = NULL_TREE;
18173 51197 : return GS_ALL_DONE;
18174 : }
18175 :
18176 : /* Helper for gimplify_omp_loop, called through walk_tree. */
18177 :
18178 : static tree
18179 294 : note_no_context_vars (tree *tp, int *, void *data)
18180 : {
18181 294 : if (VAR_P (*tp)
18182 56 : && DECL_CONTEXT (*tp) == NULL_TREE
18183 309 : && !is_global_var (*tp))
18184 : {
18185 15 : vec<tree> *d = (vec<tree> *) data;
18186 15 : d->safe_push (*tp);
18187 15 : DECL_CONTEXT (*tp) = current_function_decl;
18188 : }
18189 294 : return NULL_TREE;
18190 : }
18191 :
18192 : /* Gimplify the gross structure of an OMP_LOOP statement. */
18193 :
18194 : static enum gimplify_status
18195 1056 : gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
18196 : {
18197 1056 : tree for_stmt = *expr_p;
18198 1056 : tree clauses = OMP_FOR_CLAUSES (for_stmt);
18199 1056 : struct gimplify_omp_ctx *octx = gimplify_omp_ctxp;
18200 1056 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18201 1056 : int i;
18202 :
18203 1056 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
18204 1056 : if (*expr_p != for_stmt)
18205 : return GS_OK;
18206 :
18207 : /* If order is not present, the behavior is as if order(concurrent)
18208 : appeared. */
18209 1056 : tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER);
18210 1056 : if (order == NULL_TREE)
18211 : {
18212 799 : order = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_ORDER);
18213 799 : OMP_CLAUSE_CHAIN (order) = clauses;
18214 799 : OMP_FOR_CLAUSES (for_stmt) = clauses = order;
18215 : }
18216 :
18217 1056 : tree bind = omp_find_clause (clauses, OMP_CLAUSE_BIND);
18218 1056 : if (bind == NULL_TREE)
18219 : {
18220 574 : if (!flag_openmp) /* flag_openmp_simd */
18221 : ;
18222 557 : else if (octx && (octx->region_type & ORT_TEAMS) != 0)
18223 : kind = OMP_CLAUSE_BIND_TEAMS;
18224 327 : else if (octx && (octx->region_type & ORT_PARALLEL) != 0)
18225 : kind = OMP_CLAUSE_BIND_PARALLEL;
18226 : else
18227 : {
18228 187 : for (; octx; octx = octx->outer_context)
18229 : {
18230 79 : if ((octx->region_type & ORT_ACC) != 0
18231 79 : || octx->region_type == ORT_NONE
18232 79 : || octx->region_type == ORT_IMPLICIT_TARGET)
18233 0 : continue;
18234 : break;
18235 : }
18236 187 : if (octx == NULL && !in_omp_construct)
18237 4 : error_at (EXPR_LOCATION (for_stmt),
18238 : "%<bind%> clause not specified on a %<loop%> "
18239 : "construct not nested inside another OpenMP construct");
18240 : }
18241 574 : bind = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_BIND);
18242 574 : OMP_CLAUSE_CHAIN (bind) = clauses;
18243 574 : OMP_CLAUSE_BIND_KIND (bind) = kind;
18244 574 : OMP_FOR_CLAUSES (for_stmt) = bind;
18245 : }
18246 : else
18247 482 : switch (OMP_CLAUSE_BIND_KIND (bind))
18248 : {
18249 : case OMP_CLAUSE_BIND_THREAD:
18250 : break;
18251 166 : case OMP_CLAUSE_BIND_PARALLEL:
18252 166 : if (!flag_openmp) /* flag_openmp_simd */
18253 : {
18254 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18255 0 : break;
18256 : }
18257 240 : for (; octx; octx = octx->outer_context)
18258 78 : if (octx->region_type == ORT_SIMD
18259 78 : && omp_find_clause (octx->clauses, OMP_CLAUSE_BIND) == NULL_TREE)
18260 : {
18261 4 : error_at (EXPR_LOCATION (for_stmt),
18262 : "%<bind(parallel)%> on a %<loop%> construct nested "
18263 : "inside %<simd%> construct");
18264 4 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18265 4 : break;
18266 : }
18267 : kind = OMP_CLAUSE_BIND_PARALLEL;
18268 : break;
18269 162 : case OMP_CLAUSE_BIND_TEAMS:
18270 162 : if (!flag_openmp) /* flag_openmp_simd */
18271 : {
18272 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18273 0 : break;
18274 : }
18275 162 : if ((octx
18276 128 : && octx->region_type != ORT_IMPLICIT_TARGET
18277 111 : && octx->region_type != ORT_NONE
18278 111 : && (octx->region_type & ORT_TEAMS) == 0)
18279 110 : || in_omp_construct)
18280 : {
18281 64 : error_at (EXPR_LOCATION (for_stmt),
18282 : "%<bind(teams)%> on a %<loop%> region not strictly "
18283 : "nested inside of a %<teams%> region");
18284 64 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18285 64 : break;
18286 : }
18287 : kind = OMP_CLAUSE_BIND_TEAMS;
18288 : break;
18289 0 : default:
18290 0 : gcc_unreachable ();
18291 : }
18292 :
18293 4280 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
18294 3224 : switch (OMP_CLAUSE_CODE (*pc))
18295 : {
18296 343 : case OMP_CLAUSE_REDUCTION:
18297 343 : if (OMP_CLAUSE_REDUCTION_INSCAN (*pc))
18298 : {
18299 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18300 : "%<inscan%> %<reduction%> clause on "
18301 : "%qs construct", "loop");
18302 4 : OMP_CLAUSE_REDUCTION_INSCAN (*pc) = 0;
18303 : }
18304 343 : if (OMP_CLAUSE_REDUCTION_TASK (*pc))
18305 : {
18306 8 : error_at (OMP_CLAUSE_LOCATION (*pc),
18307 : "invalid %<task%> reduction modifier on construct "
18308 : "other than %<parallel%>, %qs or %<sections%>",
18309 4 : lang_GNU_Fortran () ? "do" : "for");
18310 4 : OMP_CLAUSE_REDUCTION_TASK (*pc) = 0;
18311 : }
18312 343 : pc = &OMP_CLAUSE_CHAIN (*pc);
18313 343 : break;
18314 : case OMP_CLAUSE_LASTPRIVATE:
18315 293 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18316 : {
18317 289 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
18318 289 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
18319 289 : if (OMP_CLAUSE_DECL (*pc) == TREE_OPERAND (t, 0))
18320 : break;
18321 26 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18322 25 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18323 : i)) == TREE_LIST
18324 48 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18325 : i)))
18326 : {
18327 22 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18328 22 : if (OMP_CLAUSE_DECL (*pc) == TREE_PURPOSE (orig))
18329 : break;
18330 : }
18331 : }
18332 289 : if (i == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
18333 : {
18334 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18335 : "%<lastprivate%> clause on a %<loop%> construct refers "
18336 : "to a variable %qD which is not the loop iterator",
18337 4 : OMP_CLAUSE_DECL (*pc));
18338 4 : *pc = OMP_CLAUSE_CHAIN (*pc);
18339 4 : break;
18340 : }
18341 285 : pc = &OMP_CLAUSE_CHAIN (*pc);
18342 285 : break;
18343 2592 : default:
18344 2592 : pc = &OMP_CLAUSE_CHAIN (*pc);
18345 2592 : break;
18346 : }
18347 :
18348 1056 : TREE_SET_CODE (for_stmt, OMP_SIMD);
18349 :
18350 1056 : int last;
18351 1056 : switch (kind)
18352 : {
18353 : case OMP_CLAUSE_BIND_THREAD: last = 0; break;
18354 414 : case OMP_CLAUSE_BIND_PARALLEL: last = 1; break;
18355 220 : case OMP_CLAUSE_BIND_TEAMS: last = 2; break;
18356 : }
18357 1910 : for (int pass = 1; pass <= last; pass++)
18358 : {
18359 854 : if (pass == 2)
18360 : {
18361 220 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL,
18362 : make_node (BLOCK));
18363 220 : append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind));
18364 220 : *expr_p = make_node (OMP_PARALLEL);
18365 220 : TREE_TYPE (*expr_p) = void_type_node;
18366 220 : OMP_PARALLEL_BODY (*expr_p) = bind;
18367 220 : OMP_PARALLEL_COMBINED (*expr_p) = 1;
18368 220 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (for_stmt));
18369 220 : tree *pc = &OMP_PARALLEL_CLAUSES (*expr_p);
18370 452 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18371 232 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18372 232 : && (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i))
18373 : == TREE_LIST))
18374 : {
18375 16 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18376 16 : if (TREE_PURPOSE (elt) && TREE_VALUE (elt))
18377 : {
18378 13 : *pc = build_omp_clause (UNKNOWN_LOCATION,
18379 : OMP_CLAUSE_FIRSTPRIVATE);
18380 13 : OMP_CLAUSE_DECL (*pc) = TREE_VALUE (elt);
18381 13 : pc = &OMP_CLAUSE_CHAIN (*pc);
18382 : }
18383 : }
18384 : }
18385 854 : tree t = make_node (pass == 2 ? OMP_DISTRIBUTE : OMP_FOR);
18386 854 : tree *pc = &OMP_FOR_CLAUSES (t);
18387 854 : TREE_TYPE (t) = void_type_node;
18388 854 : OMP_FOR_BODY (t) = *expr_p;
18389 854 : SET_EXPR_LOCATION (t, EXPR_LOCATION (for_stmt));
18390 3968 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
18391 3114 : switch (OMP_CLAUSE_CODE (c))
18392 : {
18393 1992 : case OMP_CLAUSE_BIND:
18394 1992 : case OMP_CLAUSE_ORDER:
18395 1992 : case OMP_CLAUSE_COLLAPSE:
18396 1992 : *pc = copy_node (c);
18397 1992 : pc = &OMP_CLAUSE_CHAIN (*pc);
18398 1992 : break;
18399 : case OMP_CLAUSE_PRIVATE:
18400 : case OMP_CLAUSE_FIRSTPRIVATE:
18401 : /* Only needed on innermost. */
18402 : break;
18403 351 : case OMP_CLAUSE_LASTPRIVATE:
18404 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) && pass != last)
18405 : {
18406 7 : *pc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18407 : OMP_CLAUSE_FIRSTPRIVATE);
18408 7 : OMP_CLAUSE_DECL (*pc) = OMP_CLAUSE_DECL (c);
18409 7 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18410 7 : pc = &OMP_CLAUSE_CHAIN (*pc);
18411 : }
18412 351 : *pc = copy_node (c);
18413 351 : OMP_CLAUSE_LASTPRIVATE_STMT (*pc) = NULL_TREE;
18414 351 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18415 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18416 : {
18417 22 : if (pass != last)
18418 7 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (*pc) = 1;
18419 : else
18420 15 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18421 22 : OMP_CLAUSE_LASTPRIVATE_LOOP_IV (*pc) = 0;
18422 : }
18423 351 : pc = &OMP_CLAUSE_CHAIN (*pc);
18424 351 : break;
18425 463 : case OMP_CLAUSE_REDUCTION:
18426 463 : *pc = copy_node (c);
18427 463 : OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c));
18428 463 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18429 463 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc))
18430 : {
18431 15 : auto_vec<tree> no_context_vars;
18432 15 : int walk_subtrees = 0;
18433 15 : note_no_context_vars (&OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18434 : &walk_subtrees, &no_context_vars);
18435 15 : if (tree p = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c))
18436 0 : note_no_context_vars (&p, &walk_subtrees, &no_context_vars);
18437 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (c),
18438 : note_no_context_vars,
18439 : &no_context_vars);
18440 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (c),
18441 : note_no_context_vars,
18442 : &no_context_vars);
18443 :
18444 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)
18445 15 : = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
18446 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18447 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)
18448 0 : = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c));
18449 :
18450 15 : hash_map<tree, tree> decl_map;
18451 15 : decl_map.put (OMP_CLAUSE_DECL (c), OMP_CLAUSE_DECL (c));
18452 15 : decl_map.put (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18453 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc));
18454 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18455 0 : decl_map.put (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
18456 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc));
18457 :
18458 15 : copy_body_data id;
18459 15 : memset (&id, 0, sizeof (id));
18460 15 : id.src_fn = current_function_decl;
18461 15 : id.dst_fn = current_function_decl;
18462 15 : id.src_cfun = cfun;
18463 15 : id.decl_map = &decl_map;
18464 15 : id.copy_decl = copy_decl_no_change;
18465 15 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
18466 15 : id.transform_new_cfg = true;
18467 15 : id.transform_return_to_modify = false;
18468 15 : id.eh_lp_nr = 0;
18469 15 : walk_tree (&OMP_CLAUSE_REDUCTION_INIT (*pc), copy_tree_body_r,
18470 : &id, NULL);
18471 15 : walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (*pc), copy_tree_body_r,
18472 : &id, NULL);
18473 :
18474 60 : for (tree d : no_context_vars)
18475 : {
18476 15 : DECL_CONTEXT (d) = NULL_TREE;
18477 15 : DECL_CONTEXT (*decl_map.get (d)) = NULL_TREE;
18478 : }
18479 15 : }
18480 : else
18481 : {
18482 448 : OMP_CLAUSE_REDUCTION_INIT (*pc)
18483 448 : = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c));
18484 448 : OMP_CLAUSE_REDUCTION_MERGE (*pc)
18485 896 : = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c));
18486 : }
18487 463 : pc = &OMP_CLAUSE_CHAIN (*pc);
18488 463 : break;
18489 0 : default:
18490 0 : gcc_unreachable ();
18491 : }
18492 854 : *pc = NULL_TREE;
18493 854 : *expr_p = t;
18494 : }
18495 1056 : return gimplify_expr (expr_p, pre_p, NULL, is_gimple_stmt, fb_none);
18496 : }
18497 :
18498 :
18499 : /* Helper function of optimize_target_teams, find OMP_TEAMS inside
18500 : of OMP_TARGET's body. */
18501 :
18502 : static tree
18503 97157 : find_omp_teams (tree *tp, int *walk_subtrees, void *)
18504 : {
18505 97157 : *walk_subtrees = 0;
18506 97157 : switch (TREE_CODE (*tp))
18507 : {
18508 : case OMP_TEAMS:
18509 : return *tp;
18510 26929 : case BIND_EXPR:
18511 26929 : case STATEMENT_LIST:
18512 26929 : *walk_subtrees = 1;
18513 26929 : break;
18514 : default:
18515 : break;
18516 : }
18517 : return NULL_TREE;
18518 : }
18519 :
18520 : /* Helper function of optimize_target_teams, determine if the expression
18521 : can be computed safely before the target construct on the host. */
18522 :
18523 : static tree
18524 1311 : computable_teams_clause (tree *tp, int *walk_subtrees, void *)
18525 : {
18526 1831 : splay_tree_node n;
18527 :
18528 1831 : if (TYPE_P (*tp))
18529 : {
18530 0 : *walk_subtrees = 0;
18531 0 : return NULL_TREE;
18532 : }
18533 1831 : switch (TREE_CODE (*tp))
18534 : {
18535 990 : case VAR_DECL:
18536 990 : case PARM_DECL:
18537 990 : case RESULT_DECL:
18538 990 : *walk_subtrees = 0;
18539 990 : if (error_operand_p (*tp)
18540 990 : || !INTEGRAL_TYPE_P (TREE_TYPE (*tp))
18541 990 : || DECL_HAS_VALUE_EXPR_P (*tp)
18542 990 : || DECL_THREAD_LOCAL_P (*tp)
18543 990 : || TREE_SIDE_EFFECTS (*tp)
18544 1980 : || TREE_THIS_VOLATILE (*tp))
18545 0 : return *tp;
18546 990 : if (is_global_var (*tp)
18547 990 : && (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (*tp))
18548 0 : || lookup_attribute ("omp declare target link",
18549 0 : DECL_ATTRIBUTES (*tp))))
18550 16 : return *tp;
18551 974 : if (VAR_P (*tp)
18552 668 : && !DECL_SEEN_IN_BIND_EXPR_P (*tp)
18553 50 : && !is_global_var (*tp)
18554 1024 : && decl_function_context (*tp) == current_function_decl)
18555 50 : return *tp;
18556 1848 : n = splay_tree_lookup (gimplify_omp_ctxp->variables,
18557 924 : (splay_tree_key) *tp);
18558 924 : if (n == NULL)
18559 : {
18560 292 : if (gimplify_omp_ctxp->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
18561 : return NULL_TREE;
18562 24 : return *tp;
18563 : }
18564 632 : else if (n->value & GOVD_LOCAL)
18565 0 : return *tp;
18566 632 : else if (n->value & GOVD_FIRSTPRIVATE)
18567 : return NULL_TREE;
18568 112 : else if ((n->value & (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18569 : == (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18570 : return NULL_TREE;
18571 96 : return *tp;
18572 76 : case INTEGER_CST:
18573 76 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18574 : return *tp;
18575 : return NULL_TREE;
18576 520 : case TARGET_EXPR:
18577 520 : if (TARGET_EXPR_INITIAL (*tp)
18578 520 : || TREE_CODE (TARGET_EXPR_SLOT (*tp)) != VAR_DECL)
18579 : return *tp;
18580 520 : return computable_teams_clause (&TARGET_EXPR_SLOT (*tp),
18581 520 : walk_subtrees, NULL);
18582 : /* Allow some reasonable subset of integral arithmetics. */
18583 193 : case PLUS_EXPR:
18584 193 : case MINUS_EXPR:
18585 193 : case MULT_EXPR:
18586 193 : case TRUNC_DIV_EXPR:
18587 193 : case CEIL_DIV_EXPR:
18588 193 : case FLOOR_DIV_EXPR:
18589 193 : case ROUND_DIV_EXPR:
18590 193 : case TRUNC_MOD_EXPR:
18591 193 : case CEIL_MOD_EXPR:
18592 193 : case FLOOR_MOD_EXPR:
18593 193 : case ROUND_MOD_EXPR:
18594 193 : case RDIV_EXPR:
18595 193 : case EXACT_DIV_EXPR:
18596 193 : case MIN_EXPR:
18597 193 : case MAX_EXPR:
18598 193 : case LSHIFT_EXPR:
18599 193 : case RSHIFT_EXPR:
18600 193 : case BIT_IOR_EXPR:
18601 193 : case BIT_XOR_EXPR:
18602 193 : case BIT_AND_EXPR:
18603 193 : case NEGATE_EXPR:
18604 193 : case ABS_EXPR:
18605 193 : case BIT_NOT_EXPR:
18606 193 : case NON_LVALUE_EXPR:
18607 193 : CASE_CONVERT:
18608 193 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18609 : return *tp;
18610 : return NULL_TREE;
18611 : /* And disallow anything else, except for comparisons. */
18612 52 : default:
18613 52 : if (COMPARISON_CLASS_P (*tp))
18614 : return NULL_TREE;
18615 : return *tp;
18616 : }
18617 : }
18618 :
18619 : /* Try to determine if the num_teams and/or thread_limit expressions
18620 : can have their values determined already before entering the
18621 : target construct.
18622 : INTEGER_CSTs trivially are,
18623 : integral decls that are firstprivate (explicitly or implicitly)
18624 : or explicitly map(always, to:) or map(always, tofrom:) on the target
18625 : region too, and expressions involving simple arithmetics on those
18626 : too, function calls are not ok, dereferencing something neither etc.
18627 : Add NUM_TEAMS and THREAD_LIMIT clauses to the OMP_CLAUSES of
18628 : EXPR based on what we find:
18629 : 0 stands for clause not specified at all, use implementation default
18630 : -1 stands for value that can't be determined easily before entering
18631 : the target construct.
18632 : -2 means that no explicit teams construct was specified
18633 : If teams construct is not present at all, use 1 for num_teams
18634 : and 0 for thread_limit (only one team is involved, and the thread
18635 : limit is implementation defined. */
18636 :
18637 : static void
18638 13426 : optimize_target_teams (tree target, gimple_seq *pre_p)
18639 : {
18640 13426 : tree body = OMP_BODY (target);
18641 13426 : tree teams = walk_tree (&body, find_omp_teams, NULL, NULL);
18642 13426 : tree num_teams_lower = NULL_TREE;
18643 13426 : tree num_teams_upper = integer_zero_node;
18644 13426 : tree thread_limit = integer_zero_node;
18645 13426 : location_t num_teams_loc = EXPR_LOCATION (target);
18646 13426 : location_t thread_limit_loc = EXPR_LOCATION (target);
18647 13426 : tree c, *p, expr;
18648 13426 : struct gimplify_omp_ctx *target_ctx = gimplify_omp_ctxp;
18649 :
18650 13426 : if (teams == NULL_TREE)
18651 7305 : num_teams_upper = build_int_cst (integer_type_node, -2);
18652 : else
18653 10587 : for (c = OMP_TEAMS_CLAUSES (teams); c; c = OMP_CLAUSE_CHAIN (c))
18654 : {
18655 4466 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS)
18656 : {
18657 617 : p = &num_teams_upper;
18658 617 : num_teams_loc = OMP_CLAUSE_LOCATION (c);
18659 617 : if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c))
18660 : {
18661 148 : expr = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c);
18662 148 : if (TREE_CODE (expr) == INTEGER_CST)
18663 21 : num_teams_lower = expr;
18664 127 : else if (walk_tree (&expr, computable_teams_clause,
18665 : NULL, NULL))
18666 19 : num_teams_lower = integer_minus_one_node;
18667 : else
18668 : {
18669 108 : num_teams_lower = expr;
18670 108 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18671 108 : if (gimplify_expr (&num_teams_lower, pre_p, NULL,
18672 : is_gimple_val, fb_rvalue, false)
18673 : == GS_ERROR)
18674 : {
18675 0 : gimplify_omp_ctxp = target_ctx;
18676 0 : num_teams_lower = integer_minus_one_node;
18677 : }
18678 : else
18679 : {
18680 108 : gimplify_omp_ctxp = target_ctx;
18681 108 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18682 28 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
18683 56 : = num_teams_lower;
18684 : }
18685 : }
18686 : }
18687 : }
18688 3849 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
18689 : {
18690 471 : p = &thread_limit;
18691 471 : thread_limit_loc = OMP_CLAUSE_LOCATION (c);
18692 : }
18693 : else
18694 3378 : continue;
18695 1088 : expr = OMP_CLAUSE_OPERAND (c, 0);
18696 1088 : if (TREE_CODE (expr) == INTEGER_CST)
18697 : {
18698 173 : *p = expr;
18699 173 : continue;
18700 : }
18701 915 : if (walk_tree (&expr, computable_teams_clause, NULL, NULL))
18702 : {
18703 219 : *p = integer_minus_one_node;
18704 219 : continue;
18705 : }
18706 696 : *p = expr;
18707 696 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18708 696 : if (gimplify_expr (p, pre_p, NULL, is_gimple_val, fb_rvalue, false)
18709 : == GS_ERROR)
18710 : {
18711 0 : gimplify_omp_ctxp = target_ctx;
18712 0 : *p = integer_minus_one_node;
18713 0 : continue;
18714 : }
18715 696 : gimplify_omp_ctxp = target_ctx;
18716 696 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18717 48 : OMP_CLAUSE_OPERAND (c, 0) = *p;
18718 : }
18719 13426 : if (!omp_find_clause (OMP_TARGET_CLAUSES (target), OMP_CLAUSE_THREAD_LIMIT))
18720 : {
18721 13158 : c = build_omp_clause (thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
18722 13158 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
18723 13158 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18724 13158 : OMP_TARGET_CLAUSES (target) = c;
18725 : }
18726 13426 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
18727 13426 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
18728 13426 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
18729 13426 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18730 13426 : OMP_TARGET_CLAUSES (target) = c;
18731 13426 : }
18732 :
18733 : /* Gimplify the gross structure of several OMP constructs. */
18734 :
18735 : static void
18736 39757 : gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
18737 : {
18738 39757 : tree expr = *expr_p;
18739 39757 : gimple *stmt;
18740 39757 : gimple_seq body = NULL;
18741 39757 : enum omp_region_type ort;
18742 :
18743 39757 : switch (TREE_CODE (expr))
18744 : {
18745 : case OMP_SECTIONS:
18746 : case OMP_SINGLE:
18747 : ort = ORT_WORKSHARE;
18748 : break;
18749 214 : case OMP_SCOPE:
18750 214 : ort = ORT_TASKGROUP;
18751 214 : break;
18752 13426 : case OMP_TARGET:
18753 13426 : ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET;
18754 : break;
18755 2543 : case OACC_KERNELS:
18756 2543 : ort = ORT_ACC_KERNELS;
18757 2543 : break;
18758 7901 : case OACC_PARALLEL:
18759 7901 : ort = ORT_ACC_PARALLEL;
18760 7901 : break;
18761 1040 : case OACC_SERIAL:
18762 1040 : ort = ORT_ACC_SERIAL;
18763 1040 : break;
18764 1950 : case OACC_DATA:
18765 1950 : ort = ORT_ACC_DATA;
18766 1950 : break;
18767 1871 : case OMP_TARGET_DATA:
18768 1871 : ort = ORT_TARGET_DATA;
18769 1871 : break;
18770 8793 : case OMP_TEAMS:
18771 8793 : ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS;
18772 8793 : if (gimplify_omp_ctxp == NULL
18773 6161 : || gimplify_omp_ctxp->region_type == ORT_IMPLICIT_TARGET)
18774 2632 : ort = (enum omp_region_type) (ort | ORT_HOST_TEAMS);
18775 : break;
18776 118 : case OACC_HOST_DATA:
18777 118 : ort = ORT_ACC_HOST_DATA;
18778 118 : break;
18779 0 : default:
18780 0 : gcc_unreachable ();
18781 : }
18782 :
18783 39757 : gimple_seq iterator_loops_seq = NULL;
18784 39757 : if (TREE_CODE (expr) == OMP_TARGET || TREE_CODE (expr) == OMP_TARGET_DATA)
18785 : {
18786 15297 : remove_unused_omp_iterator_vars (&OMP_CLAUSES (expr));
18787 15297 : build_omp_iterators_loops (&OMP_CLAUSES (expr), &iterator_loops_seq);
18788 : }
18789 :
18790 39757 : bool save_in_omp_construct = in_omp_construct;
18791 39757 : if ((ort & ORT_ACC) == 0)
18792 26205 : in_omp_construct = false;
18793 39757 : gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
18794 39757 : TREE_CODE (expr), &iterator_loops_seq);
18795 39757 : if (TREE_CODE (expr) == OMP_TARGET)
18796 13426 : optimize_target_teams (expr, pre_p);
18797 39757 : if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
18798 10908 : || (ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18799 : {
18800 31481 : push_gimplify_context ();
18801 31481 : gimple *g = gimplify_and_return_first (OMP_BODY (expr), &body);
18802 31481 : if (gimple_code (g) == GIMPLE_BIND)
18803 31481 : pop_gimplify_context (g);
18804 : else
18805 0 : pop_gimplify_context (NULL);
18806 31481 : if ((ort & ORT_TARGET_DATA) != 0)
18807 : {
18808 3939 : enum built_in_function end_ix;
18809 3939 : switch (TREE_CODE (expr))
18810 : {
18811 : case OACC_DATA:
18812 : case OACC_HOST_DATA:
18813 : end_ix = BUILT_IN_GOACC_DATA_END;
18814 : break;
18815 1871 : case OMP_TARGET_DATA:
18816 1871 : end_ix = BUILT_IN_GOMP_TARGET_END_DATA;
18817 1871 : break;
18818 0 : default:
18819 0 : gcc_unreachable ();
18820 : }
18821 3939 : tree fn = builtin_decl_explicit (end_ix);
18822 3939 : g = gimple_build_call (fn, 0);
18823 3939 : gimple_seq cleanup = NULL;
18824 3939 : gimple_seq_add_stmt (&cleanup, g);
18825 3939 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
18826 3939 : body = NULL;
18827 3939 : gimple_seq_add_stmt (&body, g);
18828 : }
18829 : }
18830 : else
18831 8276 : gimplify_and_add (OMP_BODY (expr), &body);
18832 39757 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
18833 39757 : TREE_CODE (expr), &iterator_loops_seq);
18834 39757 : in_omp_construct = save_in_omp_construct;
18835 :
18836 39757 : switch (TREE_CODE (expr))
18837 : {
18838 1950 : case OACC_DATA:
18839 3900 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_DATA,
18840 1950 : OMP_CLAUSES (expr));
18841 1950 : break;
18842 118 : case OACC_HOST_DATA:
18843 118 : if (omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT))
18844 : {
18845 128 : for (tree c = OMP_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18846 95 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
18847 57 : OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c) = 1;
18848 : }
18849 :
18850 236 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_HOST_DATA,
18851 118 : OMP_CLAUSES (expr));
18852 118 : break;
18853 2543 : case OACC_KERNELS:
18854 5086 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS,
18855 2543 : OMP_CLAUSES (expr));
18856 2543 : break;
18857 7901 : case OACC_PARALLEL:
18858 15802 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_PARALLEL,
18859 7901 : OMP_CLAUSES (expr));
18860 7901 : break;
18861 1040 : case OACC_SERIAL:
18862 2080 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_SERIAL,
18863 1040 : OMP_CLAUSES (expr));
18864 1040 : break;
18865 626 : case OMP_SECTIONS:
18866 626 : stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
18867 626 : break;
18868 1275 : case OMP_SINGLE:
18869 1275 : stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
18870 1275 : break;
18871 214 : case OMP_SCOPE:
18872 214 : stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
18873 214 : break;
18874 13426 : case OMP_TARGET:
18875 26852 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
18876 13426 : OMP_CLAUSES (expr), iterator_loops_seq);
18877 13426 : break;
18878 1871 : case OMP_TARGET_DATA:
18879 : /* Put use_device_{ptr,addr} clauses last, as map clauses are supposed
18880 : to be evaluated before the use_device_{ptr,addr} clauses if they
18881 : refer to the same variables. */
18882 1871 : {
18883 1871 : tree use_device_clauses;
18884 1871 : tree *pc, *uc = &use_device_clauses;
18885 9963 : for (pc = &OMP_CLAUSES (expr); *pc; )
18886 8092 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
18887 8092 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
18888 : {
18889 1959 : *uc = *pc;
18890 1959 : *pc = OMP_CLAUSE_CHAIN (*pc);
18891 1959 : uc = &OMP_CLAUSE_CHAIN (*uc);
18892 : }
18893 : else
18894 6133 : pc = &OMP_CLAUSE_CHAIN (*pc);
18895 1871 : *uc = NULL_TREE;
18896 1871 : *pc = use_device_clauses;
18897 1871 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_DATA,
18898 1871 : OMP_CLAUSES (expr), iterator_loops_seq);
18899 : }
18900 1871 : break;
18901 8793 : case OMP_TEAMS:
18902 8793 : stmt = gimple_build_omp_teams (body, OMP_CLAUSES (expr));
18903 8793 : if ((ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18904 2632 : gimple_omp_teams_set_host (as_a <gomp_teams *> (stmt), true);
18905 : break;
18906 0 : default:
18907 0 : gcc_unreachable ();
18908 : }
18909 :
18910 39757 : gimplify_seq_add_stmt (pre_p, stmt);
18911 39757 : *expr_p = NULL_TREE;
18912 39757 : }
18913 :
18914 : /* Gimplify the gross structure of OpenACC enter/exit data, update, and OpenMP
18915 : target update constructs. */
18916 :
18917 : static void
18918 12270 : gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
18919 : {
18920 12270 : tree expr = *expr_p;
18921 12270 : int kind;
18922 12270 : gomp_target *stmt;
18923 12270 : enum omp_region_type ort = ORT_WORKSHARE;
18924 :
18925 12270 : switch (TREE_CODE (expr))
18926 : {
18927 : case OACC_ENTER_DATA:
18928 : kind = GF_OMP_TARGET_KIND_OACC_ENTER_DATA;
18929 : ort = ORT_ACC;
18930 : break;
18931 : case OACC_EXIT_DATA:
18932 : kind = GF_OMP_TARGET_KIND_OACC_EXIT_DATA;
18933 : ort = ORT_ACC;
18934 : break;
18935 : case OACC_UPDATE:
18936 : kind = GF_OMP_TARGET_KIND_OACC_UPDATE;
18937 : ort = ORT_ACC;
18938 : break;
18939 : case OMP_TARGET_UPDATE:
18940 : kind = GF_OMP_TARGET_KIND_UPDATE;
18941 : break;
18942 : case OMP_TARGET_ENTER_DATA:
18943 : kind = GF_OMP_TARGET_KIND_ENTER_DATA;
18944 : break;
18945 : case OMP_TARGET_EXIT_DATA:
18946 : kind = GF_OMP_TARGET_KIND_EXIT_DATA;
18947 : break;
18948 0 : default:
18949 0 : gcc_unreachable ();
18950 : }
18951 :
18952 12270 : gimple_seq iterator_loops_seq = NULL;
18953 12270 : remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr));
18954 12270 : build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr),
18955 : &iterator_loops_seq);
18956 :
18957 12270 : gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
18958 12270 : ort, TREE_CODE (expr), &iterator_loops_seq);
18959 12270 : gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
18960 12270 : TREE_CODE (expr), &iterator_loops_seq);
18961 12270 : if (TREE_CODE (expr) == OACC_UPDATE
18962 12270 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
18963 : OMP_CLAUSE_IF_PRESENT))
18964 : {
18965 : /* The runtime uses GOMP_MAP_{TO,FROM} to denote the if_present
18966 : clause. */
18967 123 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18968 97 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
18969 47 : switch (OMP_CLAUSE_MAP_KIND (c))
18970 : {
18971 14 : case GOMP_MAP_FORCE_TO:
18972 14 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
18973 14 : break;
18974 24 : case GOMP_MAP_FORCE_FROM:
18975 24 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FROM);
18976 24 : break;
18977 : default:
18978 : break;
18979 : }
18980 : }
18981 12244 : else if (TREE_CODE (expr) == OACC_EXIT_DATA
18982 12244 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
18983 : OMP_CLAUSE_FINALIZE))
18984 : {
18985 : /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote "finalize"
18986 : semantics. */
18987 75 : bool have_clause = false;
18988 275 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18989 200 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
18990 117 : switch (OMP_CLAUSE_MAP_KIND (c))
18991 : {
18992 45 : case GOMP_MAP_FROM:
18993 45 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
18994 45 : have_clause = true;
18995 45 : break;
18996 47 : case GOMP_MAP_RELEASE:
18997 47 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
18998 47 : have_clause = true;
18999 47 : break;
19000 : case GOMP_MAP_TO_PSET:
19001 : /* Fortran arrays with descriptors must map that descriptor when
19002 : doing standalone "attach" operations (in OpenACC). In that
19003 : case GOMP_MAP_TO_PSET appears by itself with no preceding
19004 : clause (see trans-openmp.cc:gfc_trans_omp_clauses). */
19005 : break;
19006 2 : case GOMP_MAP_POINTER:
19007 : /* TODO PR92929: we may see these here, but they'll always follow
19008 : one of the clauses above, and will be handled by libgomp as
19009 : one group, so no handling required here. */
19010 2 : gcc_assert (have_clause);
19011 : break;
19012 22 : case GOMP_MAP_DETACH:
19013 22 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_DETACH);
19014 22 : have_clause = false;
19015 22 : break;
19016 : case GOMP_MAP_STRUCT:
19017 : case GOMP_MAP_STRUCT_UNORD:
19018 22 : have_clause = false;
19019 : break;
19020 0 : default:
19021 0 : gcc_unreachable ();
19022 : }
19023 : }
19024 12270 : stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr),
19025 : iterator_loops_seq);
19026 :
19027 12270 : gimplify_seq_add_stmt (pre_p, stmt);
19028 12270 : *expr_p = NULL_TREE;
19029 12270 : }
19030 :
19031 : /* A subroutine of gimplify_omp_atomic. The front end is supposed to have
19032 : stabilized the lhs of the atomic operation as *ADDR. Return true if
19033 : EXPR is this stabilized form. */
19034 :
19035 : static bool
19036 36791 : goa_lhs_expr_p (tree expr, tree addr)
19037 : {
19038 : /* Also include casts to other type variants. The C front end is fond
19039 : of adding these for e.g. volatile variables. This is like
19040 : STRIP_TYPE_NOPS but includes the main variant lookup. */
19041 36791 : STRIP_USELESS_TYPE_CONVERSION (expr);
19042 :
19043 36791 : if (INDIRECT_REF_P (expr))
19044 : {
19045 5011 : expr = TREE_OPERAND (expr, 0);
19046 5011 : while (expr != addr
19047 92 : && (CONVERT_EXPR_P (expr)
19048 92 : || TREE_CODE (expr) == NON_LVALUE_EXPR)
19049 0 : && TREE_CODE (expr) == TREE_CODE (addr)
19050 5011 : && types_compatible_p (TREE_TYPE (expr), TREE_TYPE (addr)))
19051 : {
19052 0 : expr = TREE_OPERAND (expr, 0);
19053 0 : addr = TREE_OPERAND (addr, 0);
19054 : }
19055 5011 : if (expr == addr)
19056 : return true;
19057 92 : return (TREE_CODE (addr) == ADDR_EXPR
19058 62 : && TREE_CODE (expr) == ADDR_EXPR
19059 92 : && TREE_OPERAND (addr, 0) == TREE_OPERAND (expr, 0));
19060 : }
19061 31780 : if (TREE_CODE (addr) == ADDR_EXPR && expr == TREE_OPERAND (addr, 0))
19062 : return true;
19063 : return false;
19064 : }
19065 :
19066 : /* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR. If an
19067 : expression does not involve the lhs, evaluate it into a temporary.
19068 : Return 1 if the lhs appeared as a subexpression, 0 if it did not,
19069 : or -1 if an error was encountered. */
19070 :
19071 : static int
19072 36791 : goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
19073 : tree lhs_var, tree &target_expr, bool rhs, int depth)
19074 : {
19075 36791 : tree expr = *expr_p;
19076 36791 : int saw_lhs = 0;
19077 :
19078 36791 : if (goa_lhs_expr_p (expr, lhs_addr))
19079 : {
19080 9183 : if (pre_p)
19081 8525 : *expr_p = lhs_var;
19082 9183 : return 1;
19083 : }
19084 27608 : if (is_gimple_val (expr))
19085 : return 0;
19086 :
19087 : /* Maximum depth of lhs in expression is for the
19088 : __builtin_clear_padding (...), __builtin_clear_padding (...),
19089 : __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs; */
19090 17276 : if (++depth > 7)
19091 16 : goto finish;
19092 :
19093 17260 : switch (TREE_CODE_CLASS (TREE_CODE (expr)))
19094 : {
19095 9652 : case tcc_binary:
19096 9652 : case tcc_comparison:
19097 9652 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
19098 : lhs_var, target_expr, true, depth);
19099 : /* FALLTHRU */
19100 11699 : case tcc_unary:
19101 11699 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
19102 : lhs_var, target_expr, true, depth);
19103 11699 : break;
19104 2982 : case tcc_expression:
19105 2982 : switch (TREE_CODE (expr))
19106 : {
19107 836 : case TRUTH_ANDIF_EXPR:
19108 836 : case TRUTH_ORIF_EXPR:
19109 836 : case TRUTH_AND_EXPR:
19110 836 : case TRUTH_OR_EXPR:
19111 836 : case TRUTH_XOR_EXPR:
19112 836 : case BIT_INSERT_EXPR:
19113 836 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19114 : lhs_addr, lhs_var, target_expr, true,
19115 : depth);
19116 : /* FALLTHRU */
19117 888 : case TRUTH_NOT_EXPR:
19118 888 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19119 : lhs_addr, lhs_var, target_expr, true,
19120 : depth);
19121 888 : break;
19122 550 : case MODIFY_EXPR:
19123 550 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19124 : target_expr, true, depth))
19125 : break;
19126 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19127 : lhs_addr, lhs_var, target_expr, true,
19128 : depth);
19129 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19130 : lhs_addr, lhs_var, target_expr, false,
19131 : depth);
19132 544 : break;
19133 : /* FALLTHRU */
19134 164 : case ADDR_EXPR:
19135 164 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19136 : target_expr, true, depth))
19137 : break;
19138 138 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19139 : lhs_addr, lhs_var, target_expr, false,
19140 : depth);
19141 138 : break;
19142 : case COMPOUND_EXPR:
19143 : /* Break out any preevaluations from cp_build_modify_expr. */
19144 76 : for (; TREE_CODE (expr) == COMPOUND_EXPR;
19145 38 : expr = TREE_OPERAND (expr, 1))
19146 : {
19147 : /* Special-case __builtin_clear_padding call before
19148 : __builtin_memcmp. */
19149 38 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
19150 : {
19151 2 : tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
19152 2 : if (fndecl
19153 2 : && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
19154 0 : && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
19155 2 : && (!pre_p
19156 0 : || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
19157 : lhs_addr, lhs_var,
19158 : target_expr, true, depth)))
19159 : {
19160 0 : if (pre_p)
19161 0 : *expr_p = expr;
19162 0 : saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
19163 : pre_p, lhs_addr, lhs_var,
19164 : target_expr, true, depth);
19165 0 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
19166 : pre_p, lhs_addr, lhs_var,
19167 : target_expr, rhs, depth);
19168 0 : return saw_lhs;
19169 : }
19170 : }
19171 :
19172 38 : if (pre_p)
19173 35 : gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
19174 : }
19175 38 : if (!pre_p)
19176 3 : return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
19177 3 : target_expr, rhs, depth);
19178 35 : *expr_p = expr;
19179 35 : return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
19180 35 : target_expr, rhs, depth);
19181 441 : case COND_EXPR:
19182 441 : if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
19183 : lhs_var, target_expr, true, depth))
19184 : break;
19185 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19186 : lhs_addr, lhs_var, target_expr, true,
19187 : depth);
19188 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19189 : lhs_addr, lhs_var, target_expr, true,
19190 : depth);
19191 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
19192 : lhs_addr, lhs_var, target_expr, true,
19193 : depth);
19194 428 : break;
19195 880 : case TARGET_EXPR:
19196 880 : if (TARGET_EXPR_INITIAL (expr))
19197 : {
19198 880 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
19199 : lhs_var, target_expr, true,
19200 : depth))
19201 : break;
19202 702 : if (expr == target_expr)
19203 : saw_lhs = 1;
19204 : else
19205 : {
19206 702 : saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
19207 : pre_p, lhs_addr, lhs_var,
19208 : target_expr, true, depth);
19209 702 : if (saw_lhs && target_expr == NULL_TREE && pre_p)
19210 26 : target_expr = expr;
19211 : }
19212 : }
19213 : break;
19214 : default:
19215 : break;
19216 : }
19217 : break;
19218 556 : case tcc_reference:
19219 556 : if (TREE_CODE (expr) == BIT_FIELD_REF
19220 490 : || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
19221 362 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19222 : lhs_addr, lhs_var, target_expr, true,
19223 : depth);
19224 : break;
19225 58 : case tcc_vl_exp:
19226 58 : if (TREE_CODE (expr) == CALL_EXPR)
19227 : {
19228 58 : if (tree fndecl = get_callee_fndecl (expr))
19229 58 : if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING,
19230 : BUILT_IN_MEMCMP))
19231 : {
19232 56 : int nargs = call_expr_nargs (expr);
19233 224 : for (int i = 0; i < nargs; i++)
19234 168 : saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
19235 : pre_p, lhs_addr, lhs_var,
19236 : target_expr, true, depth);
19237 : }
19238 : }
19239 : break;
19240 : default:
19241 : break;
19242 : }
19243 :
19244 17238 : finish:
19245 17238 : if (saw_lhs == 0 && pre_p)
19246 : {
19247 3485 : enum gimplify_status gs;
19248 3485 : if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
19249 : {
19250 0 : gimplify_stmt (&expr, pre_p);
19251 0 : return saw_lhs;
19252 : }
19253 3485 : else if (rhs)
19254 3307 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
19255 : else
19256 178 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
19257 3485 : if (gs != GS_ALL_DONE)
19258 36791 : saw_lhs = -1;
19259 : }
19260 :
19261 : return saw_lhs;
19262 : }
19263 :
19264 : /* Gimplify an OMP_ATOMIC statement. */
19265 :
19266 : static enum gimplify_status
19267 10236 : gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
19268 : {
19269 10236 : tree addr = TREE_OPERAND (*expr_p, 0);
19270 10236 : tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
19271 10236 : ? NULL : TREE_OPERAND (*expr_p, 1);
19272 10236 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
19273 10236 : tree tmp_load;
19274 10236 : gomp_atomic_load *loadstmt;
19275 10236 : gomp_atomic_store *storestmt;
19276 10236 : tree target_expr = NULL_TREE;
19277 :
19278 10236 : tmp_load = create_tmp_reg (type);
19279 10236 : if (rhs
19280 10236 : && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
19281 : true, 0) < 0)
19282 : return GS_ERROR;
19283 :
19284 10236 : if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
19285 : != GS_ALL_DONE)
19286 : return GS_ERROR;
19287 :
19288 10236 : loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
19289 10236 : OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19290 10236 : gimplify_seq_add_stmt (pre_p, loadstmt);
19291 10236 : if (rhs)
19292 : {
19293 : /* BIT_INSERT_EXPR is not valid for non-integral bitfield
19294 : representatives. Use BIT_FIELD_REF on the lhs instead. */
19295 9055 : tree rhsarg = rhs;
19296 9055 : if (TREE_CODE (rhs) == COND_EXPR)
19297 428 : rhsarg = TREE_OPERAND (rhs, 1);
19298 9055 : if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
19299 9055 : && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
19300 : {
19301 32 : tree bitpos = TREE_OPERAND (rhsarg, 2);
19302 32 : tree op1 = TREE_OPERAND (rhsarg, 1);
19303 32 : tree bitsize;
19304 32 : tree tmp_store = tmp_load;
19305 32 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
19306 12 : tmp_store = get_initialized_tmp_var (tmp_load, pre_p);
19307 32 : if (INTEGRAL_TYPE_P (TREE_TYPE (op1)))
19308 32 : bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
19309 : else
19310 0 : bitsize = TYPE_SIZE (TREE_TYPE (op1));
19311 32 : gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
19312 32 : tree t = build2_loc (EXPR_LOCATION (rhsarg),
19313 : MODIFY_EXPR, void_type_node,
19314 32 : build3_loc (EXPR_LOCATION (rhsarg),
19315 32 : BIT_FIELD_REF, TREE_TYPE (op1),
19316 : tmp_store, bitsize, bitpos), op1);
19317 32 : if (TREE_CODE (rhs) == COND_EXPR)
19318 16 : t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
19319 16 : TREE_OPERAND (rhs, 0), t, void_node);
19320 32 : gimplify_and_add (t, pre_p);
19321 32 : rhs = tmp_store;
19322 : }
19323 9055 : bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
19324 9055 : if (TREE_CODE (rhs) == COND_EXPR)
19325 412 : gimplify_ctxp->allow_rhs_cond_expr = true;
19326 9055 : enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
19327 : is_gimple_val, fb_rvalue);
19328 9055 : gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
19329 9055 : if (gs != GS_ALL_DONE)
19330 : return GS_ERROR;
19331 : }
19332 :
19333 10236 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
19334 1181 : rhs = tmp_load;
19335 10236 : storestmt
19336 10236 : = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19337 10236 : if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
19338 : {
19339 37 : gimple_omp_atomic_set_weak (loadstmt);
19340 37 : gimple_omp_atomic_set_weak (storestmt);
19341 : }
19342 10236 : gimplify_seq_add_stmt (pre_p, storestmt);
19343 10236 : switch (TREE_CODE (*expr_p))
19344 : {
19345 2065 : case OMP_ATOMIC_READ:
19346 2065 : case OMP_ATOMIC_CAPTURE_OLD:
19347 2065 : *expr_p = tmp_load;
19348 2065 : gimple_omp_atomic_set_need_value (loadstmt);
19349 2065 : break;
19350 868 : case OMP_ATOMIC_CAPTURE_NEW:
19351 868 : *expr_p = rhs;
19352 868 : gimple_omp_atomic_set_need_value (storestmt);
19353 868 : break;
19354 7303 : default:
19355 7303 : *expr_p = NULL;
19356 7303 : break;
19357 : }
19358 :
19359 : return GS_ALL_DONE;
19360 : }
19361 :
19362 : /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
19363 : body, and adding some EH bits. */
19364 :
19365 : static enum gimplify_status
19366 478 : gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
19367 : {
19368 478 : tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
19369 478 : gimple *body_stmt;
19370 478 : gtransaction *trans_stmt;
19371 478 : gimple_seq body = NULL;
19372 478 : int subcode = 0;
19373 :
19374 : /* Wrap the transaction body in a BIND_EXPR so we have a context
19375 : where to put decls for OMP. */
19376 478 : if (TREE_CODE (tbody) != BIND_EXPR)
19377 : {
19378 439 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
19379 439 : TREE_SIDE_EFFECTS (bind) = 1;
19380 439 : SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
19381 439 : TRANSACTION_EXPR_BODY (expr) = bind;
19382 : }
19383 :
19384 478 : push_gimplify_context ();
19385 478 : temp = voidify_wrapper_expr (*expr_p, NULL);
19386 :
19387 478 : body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
19388 478 : pop_gimplify_context (body_stmt);
19389 :
19390 478 : trans_stmt = gimple_build_transaction (body);
19391 478 : if (TRANSACTION_EXPR_OUTER (expr))
19392 : subcode = GTMA_IS_OUTER;
19393 447 : else if (TRANSACTION_EXPR_RELAXED (expr))
19394 81 : subcode = GTMA_IS_RELAXED;
19395 478 : gimple_transaction_set_subcode (trans_stmt, subcode);
19396 :
19397 478 : gimplify_seq_add_stmt (pre_p, trans_stmt);
19398 :
19399 478 : if (temp)
19400 : {
19401 76 : *expr_p = temp;
19402 76 : return GS_OK;
19403 : }
19404 :
19405 402 : *expr_p = NULL_TREE;
19406 402 : return GS_ALL_DONE;
19407 : }
19408 :
19409 : /* Gimplify an OMP_ORDERED construct. EXPR is the tree version. BODY
19410 : is the OMP_BODY of the original EXPR (which has already been
19411 : gimplified so it's not present in the EXPR).
19412 :
19413 : Return the gimplified GIMPLE_OMP_ORDERED tuple. */
19414 :
19415 : static gimple *
19416 1950 : gimplify_omp_ordered (tree expr, gimple_seq body)
19417 : {
19418 1950 : tree c, decls;
19419 1950 : int failures = 0;
19420 1950 : unsigned int i;
19421 1950 : tree source_c = NULL_TREE;
19422 1950 : tree sink_c = NULL_TREE;
19423 :
19424 1950 : if (gimplify_omp_ctxp)
19425 : {
19426 3291 : for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19427 1515 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19428 1515 : && gimplify_omp_ctxp->loop_iter_var.is_empty ())
19429 : {
19430 74 : error_at (OMP_CLAUSE_LOCATION (c),
19431 : "%<ordered%> construct with %qs clause must be "
19432 : "closely nested inside a loop with %<ordered%> clause",
19433 74 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
19434 74 : failures++;
19435 : }
19436 1441 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19437 1441 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
19438 : {
19439 642 : bool fail = false;
19440 642 : sink_c = c;
19441 642 : if (OMP_CLAUSE_DECL (c) == NULL_TREE)
19442 72 : continue; /* omp_cur_iteration - 1 */
19443 570 : for (decls = OMP_CLAUSE_DECL (c), i = 0;
19444 3201 : decls && TREE_CODE (decls) == TREE_LIST;
19445 2631 : decls = TREE_CHAIN (decls), ++i)
19446 2631 : if (i >= gimplify_omp_ctxp->loop_iter_var.length () / 2)
19447 4 : continue;
19448 5254 : else if (TREE_VALUE (decls)
19449 2627 : != gimplify_omp_ctxp->loop_iter_var[2 * i])
19450 : {
19451 8 : error_at (OMP_CLAUSE_LOCATION (c),
19452 : "variable %qE is not an iteration "
19453 : "of outermost loop %d, expected %qE",
19454 8 : TREE_VALUE (decls), i + 1,
19455 8 : gimplify_omp_ctxp->loop_iter_var[2 * i]);
19456 8 : fail = true;
19457 8 : failures++;
19458 : }
19459 : else
19460 5238 : TREE_VALUE (decls)
19461 2619 : = gimplify_omp_ctxp->loop_iter_var[2 * i + 1];
19462 1136 : if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
19463 : {
19464 16 : error_at (OMP_CLAUSE_LOCATION (c),
19465 : "number of variables in %qs clause with "
19466 : "%<sink%> modifier does not match number of "
19467 : "iteration variables",
19468 16 : OMP_CLAUSE_DOACROSS_DEPEND (c)
19469 : ? "depend" : "doacross");
19470 16 : failures++;
19471 : }
19472 : }
19473 799 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19474 799 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
19475 : {
19476 475 : if (source_c)
19477 : {
19478 4 : error_at (OMP_CLAUSE_LOCATION (c),
19479 : "more than one %qs clause with %<source%> "
19480 : "modifier on an %<ordered%> construct",
19481 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c)
19482 : ? "depend" : "doacross");
19483 4 : failures++;
19484 : }
19485 : else
19486 : source_c = c;
19487 : }
19488 : }
19489 1950 : if (source_c && sink_c)
19490 : {
19491 4 : error_at (OMP_CLAUSE_LOCATION (source_c),
19492 : "%qs clause with %<source%> modifier specified "
19493 : "together with %qs clauses with %<sink%> modifier "
19494 : "on the same construct",
19495 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
19496 4 : OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
19497 4 : failures++;
19498 : }
19499 :
19500 1950 : if (failures)
19501 102 : return gimple_build_nop ();
19502 1848 : return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
19503 : }
19504 :
19505 : /* Gimplify an OMP_INTEROP statement. */
19506 :
19507 : static enum gimplify_status
19508 612 : gimplify_omp_interop (tree *expr_p, gimple_seq *pre_p)
19509 : {
19510 612 : tree expr = *expr_p;
19511 :
19512 612 : gimplify_scan_omp_clauses (&OMP_INTEROP_CLAUSES (expr), pre_p, ORT_TASK,
19513 : OMP_INTEROP);
19514 612 : gimple *stmt = gimple_build_omp_interop (OMP_INTEROP_CLAUSES (expr));
19515 612 : gimplify_seq_add_stmt (pre_p, stmt);
19516 612 : *expr_p = NULL_TREE;
19517 612 : return GS_ALL_DONE;
19518 : }
19519 :
19520 : /* Callback for walk_tree to find an IFN_GOMP_DISPATCH. */
19521 :
19522 : static tree
19523 3100 : find_ifn_gomp_dispatch (tree *tp, int *, void *modify)
19524 : {
19525 3100 : tree t = *tp;
19526 :
19527 3100 : if (TREE_CODE (t) == CALL_EXPR && CALL_EXPR_IFN (t) == IFN_GOMP_DISPATCH)
19528 1414 : return *(tree *) modify ? *(tree *) modify : *tp;
19529 :
19530 2248 : if (TREE_CODE (t) == MODIFY_EXPR)
19531 513 : *(tree *) modify = *tp;
19532 :
19533 : return NULL_TREE;
19534 : }
19535 :
19536 : /* Gimplify an OMP_DISPATCH construct. */
19537 :
19538 : static enum gimplify_status
19539 852 : gimplify_omp_dispatch (tree *expr_p, gimple_seq *pre_p)
19540 : {
19541 852 : tree expr = *expr_p;
19542 852 : gimple_seq body = NULL;
19543 :
19544 852 : gimplify_scan_omp_clauses (&OMP_DISPATCH_CLAUSES (expr), pre_p, ORT_DISPATCH,
19545 : OMP_DISPATCH);
19546 852 : push_gimplify_context ();
19547 :
19548 : // If device clause, adjust ICV
19549 852 : tree device
19550 852 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_DEVICE);
19551 : // If no device clause exists but an interop clause with a single list
19552 : // item, use it to obtain the device number.
19553 852 : if (device)
19554 272 : device = OMP_CLAUSE_DEVICE_ID (device);
19555 : else
19556 : {
19557 580 : tree first_interop_obj
19558 580 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_INTEROP);
19559 580 : if (first_interop_obj)
19560 96 : for (tree c = TREE_CHAIN (first_interop_obj); c; c = TREE_CHAIN (c))
19561 8 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INTEROP)
19562 : {
19563 : first_interop_obj = NULL_TREE;
19564 : break;
19565 : }
19566 95 : if (first_interop_obj)
19567 : {
19568 88 : device = create_tmp_var (integer_type_node);
19569 88 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (first_interop_obj),
19570 : OMP_CLAUSE_DEVICE);
19571 88 : OMP_CLAUSE_DEVICE_ID (c) = device;
19572 88 : TREE_CHAIN (c) = TREE_CHAIN (first_interop_obj);
19573 88 : TREE_CHAIN (first_interop_obj) = c;
19574 88 : first_interop_obj = OMP_CLAUSE_DECL (first_interop_obj);
19575 : /* device = omp_get_interop_int (obj, omp_ipr_device_num, NULL); */
19576 88 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_INTEROP_INT);
19577 88 : fn = build_call_expr (fn, 3, first_interop_obj,
19578 : build_int_cst (integer_type_node, -5),
19579 : null_pointer_node);
19580 88 : gimplify_assign (device, fold_convert (integer_type_node, fn), &body);
19581 : }
19582 : }
19583 852 : tree saved_device_icv = NULL_TREE;
19584 852 : if (device
19585 852 : && (TREE_CODE (device) != INTEGER_CST
19586 709 : || !wi::eq_p (wi::to_wide (device), -1 /* omp_initial_device */)))
19587 : {
19588 : // Save current default-device-var ICV
19589 360 : saved_device_icv = create_tmp_var (integer_type_node);
19590 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
19591 360 : gcall *call = gimple_build_call (fn, 0);
19592 360 : gimple_call_set_lhs (call, saved_device_icv);
19593 360 : gimplify_seq_add_stmt (&body, call);
19594 :
19595 : // Set default device
19596 360 : fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19597 360 : call = gimple_build_call (fn, 1, device);
19598 360 : gimplify_seq_add_stmt (&body, call);
19599 : }
19600 :
19601 : // If the novariants and nocontext clauses are not compile-time constants,
19602 : // we need to generate code for all possible cases:
19603 : // if (novariants) // implies nocontext
19604 : // base()
19605 : // else if (nocontext)
19606 : // variant1()
19607 : // else
19608 : // variant2()
19609 852 : tree *dispatch_body_p = &OMP_DISPATCH_BODY (expr);
19610 852 : if (TREE_CODE (*dispatch_body_p) == BIND_EXPR)
19611 28 : dispatch_body_p = &BIND_EXPR_BODY (*dispatch_body_p);
19612 852 : tree dispatch_body = *dispatch_body_p;
19613 :
19614 : // Look for IFN_GOMP_DISPATCH and extract the base function call
19615 852 : tree base_call_expr = NULL_TREE;
19616 852 : if (TREE_CODE (dispatch_body) == STATEMENT_LIST)
19617 243 : for (tree_stmt_iterator tsi = tsi_start (dispatch_body); !tsi_end_p (tsi);
19618 187 : tsi_next (&tsi))
19619 : {
19620 243 : tree modify = NULL_TREE;
19621 243 : tree stmt = tsi_stmt (tsi);
19622 243 : base_call_expr
19623 243 : = walk_tree (&stmt, find_ifn_gomp_dispatch, &modify, NULL);
19624 243 : if (base_call_expr != NULL_TREE)
19625 : break;
19626 : }
19627 : else
19628 : {
19629 796 : tree modify = NULL_TREE;
19630 796 : base_call_expr
19631 796 : = walk_tree (dispatch_body_p, find_ifn_gomp_dispatch, &modify, NULL);
19632 : }
19633 852 : gcc_assert (base_call_expr != NULL_TREE);
19634 :
19635 852 : tree dst = NULL_TREE;
19636 852 : if (TREE_CODE (base_call_expr) == MODIFY_EXPR)
19637 : {
19638 290 : dst = TREE_OPERAND (base_call_expr, 0);
19639 290 : base_call_expr = TREE_OPERAND (base_call_expr, 1);
19640 : }
19641 :
19642 880 : while (TREE_CODE (base_call_expr) == FLOAT_EXPR
19643 : || TREE_CODE (base_call_expr) == CONVERT_EXPR
19644 : || TREE_CODE (base_call_expr) == COMPLEX_EXPR
19645 : || TREE_CODE (base_call_expr) == INDIRECT_REF
19646 880 : || TREE_CODE (base_call_expr) == NOP_EXPR)
19647 28 : base_call_expr = TREE_OPERAND (base_call_expr, 0);
19648 :
19649 852 : gcc_assert (CALL_EXPR_IFN (base_call_expr) == IFN_GOMP_DISPATCH);
19650 852 : base_call_expr = CALL_EXPR_ARG (base_call_expr, 0);
19651 :
19652 852 : tree base_fndecl = get_callee_fndecl (base_call_expr);
19653 852 : if (base_fndecl != NULL_TREE)
19654 : {
19655 844 : if (DECL_VIRTUAL_P (base_fndecl))
19656 : {
19657 6 : error_at (
19658 3 : EXPR_LOCATION (base_call_expr),
19659 : "%qD is a virtual function but only a direct call is allowed "
19660 : "in a dispatch construct",
19661 3 : DECL_NAME (base_fndecl));
19662 : }
19663 :
19664 : /* We are not actually going to expand the variant call or use
19665 : the result of omp_get_dynamic candidates here; only check that
19666 : it does not trivially resolve to a call to the base function
19667 : so that we can avoid some extra work in building code that's
19668 : not needed in that case. */
19669 844 : tree construct_context = omp_get_construct_context ();
19670 844 : vec<struct omp_variant> all_candidates
19671 844 : = omp_declare_variant_candidates (base_fndecl, construct_context);
19672 844 : gcc_assert (!all_candidates.is_empty ());
19673 844 : vec<struct omp_variant> candidates
19674 844 : = omp_get_dynamic_candidates (all_candidates, construct_context);
19675 844 : tree variant_fndecl
19676 1676 : = (candidates.length () == 1 ? candidates[0].alternative : NULL_TREE);
19677 :
19678 844 : if (base_fndecl != variant_fndecl
19679 844 : && (omp_has_novariants () == -1 || omp_has_nocontext () == -1))
19680 : {
19681 22 : tree novariants_clause = NULL_TREE, nocontext_clause = NULL_TREE,
19682 22 : novariants_cond = NULL_TREE, nocontext_cond = NULL_TREE;
19683 59 : for (tree c = OMP_DISPATCH_CLAUSES (expr); c; c = TREE_CHAIN (c))
19684 : {
19685 37 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOVARIANTS
19686 37 : && !integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
19687 : {
19688 16 : gcc_assert (novariants_cond == NULL_TREE);
19689 16 : novariants_clause = c;
19690 16 : novariants_cond = OMP_CLAUSE_NOVARIANTS_EXPR (c);
19691 : }
19692 21 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOCONTEXT
19693 21 : && !integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
19694 : {
19695 16 : gcc_assert (nocontext_cond == NULL_TREE);
19696 16 : nocontext_clause = c;
19697 16 : nocontext_cond = OMP_CLAUSE_NOCONTEXT_EXPR (c);
19698 : }
19699 : }
19700 22 : gcc_assert (novariants_cond != NULL_TREE
19701 : || nocontext_cond != NULL_TREE);
19702 :
19703 22 : enum gimplify_status ret
19704 22 : = gimplify_expr (&novariants_cond, &body, NULL, is_gimple_val,
19705 : fb_rvalue);
19706 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19707 0 : return ret;
19708 22 : ret = gimplify_expr (&nocontext_cond, &body, NULL, is_gimple_val,
19709 : fb_rvalue);
19710 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19711 : return ret;
19712 :
19713 22 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19714 :
19715 22 : if (novariants_cond != NULL_TREE)
19716 : {
19717 16 : tree base_label = create_artificial_label (UNKNOWN_LOCATION);
19718 16 : tree cond_label = create_artificial_label (UNKNOWN_LOCATION);
19719 16 : gcond *novariants_cond_stmt
19720 16 : = gimple_build_cond_from_tree (novariants_cond, base_label,
19721 : cond_label);
19722 16 : gimplify_seq_add_stmt (&body, novariants_cond_stmt);
19723 :
19724 16 : gimplify_seq_add_stmt (&body, gimple_build_label (base_label));
19725 16 : tree base_call_expr2 = copy_node (base_call_expr);
19726 16 : base_call_expr2
19727 16 : = build_call_expr_internal_loc (EXPR_LOCATION (base_call_expr2),
19728 : IFN_GOMP_DISPATCH,
19729 16 : TREE_TYPE (base_call_expr2), 1,
19730 : base_call_expr2);
19731 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19732 : {
19733 16 : base_call_expr2 = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19734 : base_call_expr2);
19735 : }
19736 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19737 16 : = boolean_true_node;
19738 16 : gimplify_and_add (base_call_expr2, &body);
19739 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19740 :
19741 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19742 16 : = boolean_false_node;
19743 16 : gimplify_seq_add_stmt (&body, gimple_build_label (cond_label));
19744 : }
19745 :
19746 22 : if (nocontext_cond != NULL_TREE)
19747 : {
19748 16 : tree variant1_label = create_artificial_label (UNKNOWN_LOCATION);
19749 16 : tree variant2_label = create_artificial_label (UNKNOWN_LOCATION);
19750 16 : gcond *nocontext_cond_stmt
19751 16 : = gimple_build_cond_from_tree (nocontext_cond, variant1_label,
19752 : variant2_label);
19753 16 : gimplify_seq_add_stmt (&body, nocontext_cond_stmt);
19754 :
19755 32 : gimplify_seq_add_stmt (&body,
19756 16 : gimple_build_label (variant1_label));
19757 16 : tree variant_call_expr = copy_node (base_call_expr);
19758 32 : variant_call_expr = build_call_expr_internal_loc (
19759 16 : EXPR_LOCATION (variant_call_expr), IFN_GOMP_DISPATCH,
19760 16 : TREE_TYPE (variant_call_expr), 1, variant_call_expr);
19761 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19762 : {
19763 16 : variant_call_expr = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19764 : variant_call_expr);
19765 : }
19766 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_true_node;
19767 16 : gimplify_and_add (variant_call_expr, &body);
19768 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19769 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_false_node;
19770 32 : gimplify_seq_add_stmt (&body,
19771 16 : gimple_build_label (variant2_label));
19772 : }
19773 :
19774 22 : tree variant_call_expr = base_call_expr;
19775 22 : variant_call_expr
19776 22 : = build_call_expr_internal_loc (EXPR_LOCATION (variant_call_expr),
19777 : IFN_GOMP_DISPATCH,
19778 22 : TREE_TYPE (variant_call_expr), 1,
19779 : variant_call_expr);
19780 22 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19781 : {
19782 22 : variant_call_expr
19783 22 : = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, variant_call_expr);
19784 : }
19785 22 : gimplify_and_add (variant_call_expr, &body);
19786 22 : gimplify_seq_add_stmt (&body, gimple_build_label (end_label));
19787 : }
19788 : else
19789 822 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19790 : }
19791 : else
19792 8 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19793 :
19794 : // Restore default-device-var ICV
19795 852 : if (saved_device_icv != NULL_TREE)
19796 : {
19797 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19798 360 : gcall *call = gimple_build_call (fn, 1, saved_device_icv);
19799 360 : gimplify_seq_add_stmt (&body, call);
19800 : }
19801 :
19802 : // Wrap dispatch body into a bind
19803 852 : gimple *bind = gimple_build_bind (NULL_TREE, body, NULL_TREE);
19804 852 : pop_gimplify_context (bind);
19805 :
19806 : // Manually tear down context created by gimplify_scan_omp_clauses to avoid a
19807 : // call to gimplify_adjust_omp_clauses
19808 852 : gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
19809 852 : if (ctx != NULL)
19810 : {
19811 852 : gcc_assert (ctx->code == OMP_DISPATCH);
19812 852 : gimplify_omp_ctxp = ctx->outer_context;
19813 852 : delete_omp_context (ctx);
19814 : }
19815 :
19816 : // Remove nowait as it has no effect on dispatch (OpenMP 5.2), device as it
19817 : // has been handled above, and depend as the front end handled it by inserting
19818 : // taskwait.
19819 852 : tree *dispatch_clauses_ptr = &OMP_DISPATCH_CLAUSES (expr);
19820 1445 : for (tree c = *dispatch_clauses_ptr; c; c = *dispatch_clauses_ptr)
19821 : {
19822 991 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT
19823 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
19824 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE)
19825 : {
19826 398 : *dispatch_clauses_ptr = OMP_CLAUSE_CHAIN (c);
19827 398 : break;
19828 : }
19829 : else
19830 593 : dispatch_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
19831 : }
19832 :
19833 852 : gimple *stmt = gimple_build_omp_dispatch (bind, OMP_DISPATCH_CLAUSES (expr));
19834 852 : gimplify_seq_add_stmt (pre_p, stmt);
19835 852 : *expr_p = NULL_TREE;
19836 852 : return GS_ALL_DONE;
19837 : }
19838 :
19839 : /* Expand a metadirective that has been resolved at gimplification time
19840 : into the candidate directive variants in CANDIDATES. */
19841 :
19842 : static enum gimplify_status
19843 170 : expand_omp_metadirective (vec<struct omp_variant> &candidates,
19844 : gimple_seq *pre_p)
19845 : {
19846 170 : auto_vec<tree> selectors;
19847 170 : auto_vec<tree> directive_labels;
19848 170 : auto_vec<gimple_seq> directive_bodies;
19849 170 : tree body_label = NULL_TREE;
19850 170 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19851 :
19852 : /* Construct bodies for each candidate. */
19853 415 : for (unsigned i = 0; i < candidates.length(); i++)
19854 : {
19855 245 : struct omp_variant &candidate = candidates[i];
19856 245 : gimple_seq body = NULL;
19857 :
19858 245 : selectors.safe_push (omp_dynamic_cond (candidate.selector,
19859 : find_supercontext ()));
19860 245 : directive_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
19861 :
19862 245 : gimplify_seq_add_stmt (&body,
19863 245 : gimple_build_label (directive_labels.last ()));
19864 245 : if (candidate.alternative != NULL_TREE)
19865 245 : gimplify_stmt (&candidate.alternative, &body);
19866 245 : if (candidate.body != NULL_TREE)
19867 : {
19868 35 : if (body_label != NULL_TREE)
19869 0 : gimplify_seq_add_stmt (&body, gimple_build_goto (body_label));
19870 : else
19871 : {
19872 35 : body_label = create_artificial_label (UNKNOWN_LOCATION);
19873 35 : gimplify_seq_add_stmt (&body, gimple_build_label (body_label));
19874 35 : gimplify_stmt (&candidate.body, &body);
19875 : }
19876 : }
19877 :
19878 245 : directive_bodies.safe_push (body);
19879 : }
19880 :
19881 170 : auto_vec<tree> cond_labels;
19882 :
19883 170 : cond_labels.safe_push (NULL_TREE);
19884 376 : for (unsigned i = 1; i < candidates.length () - 1; i++)
19885 18 : cond_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
19886 170 : if (candidates.length () > 1)
19887 57 : cond_labels.safe_push (directive_labels.last ());
19888 :
19889 : /* Generate conditionals to test each dynamic selector in turn, executing
19890 : the directive candidate if successful. */
19891 490 : for (unsigned i = 0; i < candidates.length () - 1; i++)
19892 : {
19893 75 : if (i != 0)
19894 18 : gimplify_seq_add_stmt (pre_p, gimple_build_label (cond_labels [i]));
19895 :
19896 75 : enum gimplify_status ret = gimplify_expr (&selectors[i], pre_p, NULL,
19897 : is_gimple_val, fb_rvalue);
19898 75 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19899 : return ret;
19900 :
19901 75 : gcond *cond_stmt
19902 75 : = gimple_build_cond_from_tree (selectors[i], directive_labels[i],
19903 75 : cond_labels[i + 1]);
19904 :
19905 75 : gimplify_seq_add_stmt (pre_p, cond_stmt);
19906 75 : gimplify_seq_add_seq (pre_p, directive_bodies[i]);
19907 75 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (end_label));
19908 : }
19909 :
19910 170 : gimplify_seq_add_seq (pre_p, directive_bodies.last ());
19911 170 : gimplify_seq_add_stmt (pre_p, gimple_build_label (end_label));
19912 :
19913 170 : return GS_ALL_DONE;
19914 170 : }
19915 :
19916 : /* Expand a variant construct that requires late resolution in the ompdevlow
19917 : pass. It's a bit easier to do this in tree form and then gimplify that,
19918 : than to emit gimple. The output is going to look something like:
19919 :
19920 : switch_var = OMP_NEXT_VARIANT (0, state);
19921 : loop_label:
19922 : switch (switch_var)
19923 : {
19924 : case 1:
19925 : if (dynamic_selector_predicate_1)
19926 : {
19927 : alternative_1;
19928 : goto end_label;
19929 : }
19930 : else
19931 : {
19932 : switch_var = OMP_NEXT_VARIANT (1, state);
19933 : goto loop_label;
19934 : }
19935 : case 2:
19936 : ...
19937 : }
19938 : end_label:
19939 :
19940 : OMP_NEXT_VARIANT is a magic cookie that is replaced with the switch variable
19941 : index of the next variant to try, after late resolution. */
19942 :
19943 : static tree
19944 16 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
19945 : tree construct_context)
19946 : {
19947 16 : tree body_label = NULL_TREE;
19948 16 : tree standalone_body = NULL_TREE;
19949 16 : tree loop_label = create_artificial_label (UNKNOWN_LOCATION);
19950 16 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19951 32 : tree selectors = make_tree_vec (all_candidates.length ());
19952 16 : tree switch_body = NULL_TREE;
19953 16 : tree switch_var = create_tmp_var (integer_type_node, "variant");
19954 16 : tree state = tree_cons (NULL_TREE, construct_context, selectors);
19955 :
19956 92 : for (unsigned int i = 0; i < all_candidates.length (); i++)
19957 : {
19958 76 : tree selector = all_candidates[i].selector;
19959 76 : tree alternative = all_candidates[i].alternative;
19960 76 : tree body = all_candidates[i].body;
19961 76 : TREE_VEC_ELT (selectors, i) = selector;
19962 :
19963 : /* Case label. Numbering is 1-based. */
19964 76 : tree case_val = build_int_cst (integer_type_node, i + 1);
19965 76 : tree case_label
19966 76 : = build_case_label (case_val, NULL_TREE,
19967 : create_artificial_label (UNKNOWN_LOCATION));
19968 76 : append_to_statement_list (case_label, &switch_body);
19969 :
19970 : /* The actual body of the variant. */
19971 76 : tree variant_body = NULL_TREE;
19972 76 : append_to_statement_list (alternative, &variant_body);
19973 :
19974 76 : if (body != NULL_TREE)
19975 : {
19976 0 : if (standalone_body == NULL)
19977 : {
19978 0 : standalone_body = body;
19979 0 : body_label = create_artificial_label (UNKNOWN_LOCATION);
19980 : }
19981 0 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
19982 : body_label),
19983 : &variant_body);
19984 : }
19985 : else
19986 76 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
19987 : end_label),
19988 : &variant_body);
19989 :
19990 : /* If this is a dynamic selector, wrap variant_body with a conditional.
19991 : If the predicate doesn't match, the else clause sets switch_var and
19992 : jumps to loop_var to try again. */
19993 76 : tree dynamic_selector = omp_dynamic_cond (selector, find_supercontext ());
19994 76 : if (dynamic_selector)
19995 : {
19996 20 : tree else_stmt = NULL_TREE;
19997 20 : tree next = build2 (OMP_NEXT_VARIANT, integer_type_node,
19998 : case_val, state);
19999 20 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20000 : switch_var, next),
20001 : &else_stmt);
20002 20 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20003 : loop_label),
20004 : &else_stmt);
20005 20 : variant_body = build3 (COND_EXPR, void_type_node, dynamic_selector,
20006 : variant_body, else_stmt);
20007 : }
20008 76 : append_to_statement_list (variant_body, &switch_body);
20009 : }
20010 :
20011 : /* Put it all together. */
20012 16 : tree result = NULL_TREE;
20013 16 : tree first = build2 (OMP_NEXT_VARIANT, integer_type_node, integer_zero_node,
20014 : state);
20015 16 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20016 : switch_var, first),
20017 : &result);
20018 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, loop_label),
20019 : &result);
20020 16 : append_to_statement_list (build2 (SWITCH_EXPR, integer_type_node,
20021 : switch_var, switch_body),
20022 : &result);
20023 16 : if (standalone_body)
20024 : {
20025 0 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
20026 : body_label),
20027 : &result);
20028 0 : append_to_statement_list (standalone_body, &result);
20029 : }
20030 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, end_label),
20031 : &result);
20032 16 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
20033 16 : return result;
20034 : }
20035 :
20036 :
20037 : /* Gimplify an OMP_METADIRECTIVE construct. EXPR is the tree version.
20038 : The metadirective will be resolved at this point if possible, otherwise
20039 : a GIMPLE_OMP_VARIANT_CONSTRUCT is created. */
20040 :
20041 : static enum gimplify_status
20042 174 : gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *,
20043 : bool (*) (tree), fallback_t)
20044 : {
20045 : /* Try to resolve the metadirective. */
20046 174 : tree construct_context = omp_get_construct_context ();
20047 174 : vec<struct omp_variant> all_candidates
20048 174 : = omp_metadirective_candidates (*expr_p, construct_context);
20049 174 : vec<struct omp_variant> candidates
20050 174 : = omp_get_dynamic_candidates (all_candidates, construct_context);
20051 174 : if (!candidates.is_empty ())
20052 170 : return expand_omp_metadirective (candidates, pre_p);
20053 :
20054 : /* The metadirective cannot be resolved yet. Turn it into a loop with
20055 : a nested switch statement, using OMP_NEXT_VARIANT to set the control
20056 : variable for the switch. */
20057 4 : *expr_p = expand_late_variant_directive (all_candidates, construct_context);
20058 4 : return GS_OK;
20059 : }
20060 :
20061 : /* Gimplify an OMP_DECLARE_MAPPER node (by just removing it). */
20062 :
20063 : static enum gimplify_status
20064 0 : gimplify_omp_declare_mapper (tree *expr_p)
20065 : {
20066 0 : *expr_p = NULL_TREE;
20067 0 : return GS_ALL_DONE;
20068 : }
20069 :
20070 : /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
20071 : expression produces a value to be used as an operand inside a GIMPLE
20072 : statement, the value will be stored back in *EXPR_P. This value will
20073 : be a tree of class tcc_declaration, tcc_constant, tcc_reference or
20074 : an SSA_NAME. The corresponding sequence of GIMPLE statements is
20075 : emitted in PRE_P and POST_P.
20076 :
20077 : Additionally, this process may overwrite parts of the input
20078 : expression during gimplification. Ideally, it should be
20079 : possible to do non-destructive gimplification.
20080 :
20081 : EXPR_P points to the GENERIC expression to convert to GIMPLE. If
20082 : the expression needs to evaluate to a value to be used as
20083 : an operand in a GIMPLE statement, this value will be stored in
20084 : *EXPR_P on exit. This happens when the caller specifies one
20085 : of fb_lvalue or fb_rvalue fallback flags.
20086 :
20087 : PRE_P will contain the sequence of GIMPLE statements corresponding
20088 : to the evaluation of EXPR and all the side-effects that must
20089 : be executed before the main expression. On exit, the last
20090 : statement of PRE_P is the core statement being gimplified. For
20091 : instance, when gimplifying 'if (++a)' the last statement in
20092 : PRE_P will be 'if (t.1)' where t.1 is the result of
20093 : pre-incrementing 'a'.
20094 :
20095 : POST_P will contain the sequence of GIMPLE statements corresponding
20096 : to the evaluation of all the side-effects that must be executed
20097 : after the main expression. If this is NULL, the post
20098 : side-effects are stored at the end of PRE_P.
20099 :
20100 : The reason why the output is split in two is to handle post
20101 : side-effects explicitly. In some cases, an expression may have
20102 : inner and outer post side-effects which need to be emitted in
20103 : an order different from the one given by the recursive
20104 : traversal. For instance, for the expression (*p--)++ the post
20105 : side-effects of '--' must actually occur *after* the post
20106 : side-effects of '++'. However, gimplification will first visit
20107 : the inner expression, so if a separate POST sequence was not
20108 : used, the resulting sequence would be:
20109 :
20110 : 1 t.1 = *p
20111 : 2 p = p - 1
20112 : 3 t.2 = t.1 + 1
20113 : 4 *p = t.2
20114 :
20115 : However, the post-decrement operation in line #2 must not be
20116 : evaluated until after the store to *p at line #4, so the
20117 : correct sequence should be:
20118 :
20119 : 1 t.1 = *p
20120 : 2 t.2 = t.1 + 1
20121 : 3 *p = t.2
20122 : 4 p = p - 1
20123 :
20124 : So, by specifying a separate post queue, it is possible
20125 : to emit the post side-effects in the correct order.
20126 : If POST_P is NULL, an internal queue will be used. Before
20127 : returning to the caller, the sequence POST_P is appended to
20128 : the main output sequence PRE_P.
20129 :
20130 : GIMPLE_TEST_F points to a function that takes a tree T and
20131 : returns nonzero if T is in the GIMPLE form requested by the
20132 : caller. The GIMPLE predicates are in gimple.cc.
20133 :
20134 : FALLBACK tells the function what sort of a temporary we want if
20135 : gimplification cannot produce an expression that complies with
20136 : GIMPLE_TEST_F.
20137 :
20138 : fb_none means that no temporary should be generated
20139 : fb_rvalue means that an rvalue is OK to generate
20140 : fb_lvalue means that an lvalue is OK to generate
20141 : fb_either means that either is OK, but an lvalue is preferable.
20142 : fb_mayfail means that gimplification may fail (in which case
20143 : GS_ERROR will be returned)
20144 :
20145 : The return value is either GS_ERROR or GS_ALL_DONE, since this
20146 : function iterates until EXPR is completely gimplified or an error
20147 : occurs. */
20148 :
20149 : enum gimplify_status
20150 515511271 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
20151 : bool (*gimple_test_f) (tree), fallback_t fallback)
20152 : {
20153 515511271 : tree tmp;
20154 515511271 : gimple_seq internal_pre = NULL;
20155 515511271 : gimple_seq internal_post = NULL;
20156 515511271 : tree save_expr;
20157 515511271 : bool is_statement;
20158 515511271 : location_t saved_location;
20159 515511271 : enum gimplify_status ret;
20160 515511271 : gimple_stmt_iterator pre_last_gsi, post_last_gsi;
20161 515511271 : tree label;
20162 :
20163 515511271 : save_expr = *expr_p;
20164 515511271 : if (save_expr == NULL_TREE)
20165 : return GS_ALL_DONE;
20166 :
20167 : /* If we are gimplifying a top-level statement, PRE_P must be valid. */
20168 463630676 : is_statement = gimple_test_f == is_gimple_stmt;
20169 463630676 : if (is_statement)
20170 100641954 : gcc_assert (pre_p);
20171 :
20172 : /* Consistency checks. */
20173 463630676 : if (gimple_test_f == is_gimple_reg)
20174 6248899 : gcc_assert (fallback & (fb_rvalue | fb_lvalue));
20175 457381777 : else if (gimple_test_f == is_gimple_val
20176 337240218 : || gimple_test_f == is_gimple_call_addr
20177 320971938 : || gimple_test_f == is_gimple_condexpr_for_cond
20178 315394546 : || gimple_test_f == is_gimple_mem_rhs
20179 315250742 : || gimple_test_f == is_gimple_mem_rhs_or_call
20180 304090077 : || gimple_test_f == is_gimple_reg_rhs
20181 303478803 : || gimple_test_f == is_gimple_reg_rhs_or_call
20182 231875020 : || gimple_test_f == is_gimple_asm_val
20183 231835736 : || gimple_test_f == is_gimple_mem_ref_addr)
20184 240802606 : gcc_assert (fallback & fb_rvalue);
20185 216579171 : else if (gimple_test_f == is_gimple_min_lval
20186 186582799 : || gimple_test_f == is_gimple_lvalue)
20187 83247664 : gcc_assert (fallback & fb_lvalue);
20188 133331507 : else if (gimple_test_f == is_gimple_addressable)
20189 32689553 : gcc_assert (fallback & fb_either);
20190 100641954 : else if (gimple_test_f == is_gimple_stmt)
20191 100641954 : gcc_assert (fallback == fb_none);
20192 : else
20193 : {
20194 : /* We should have recognized the GIMPLE_TEST_F predicate to
20195 : know what kind of fallback to use in case a temporary is
20196 : needed to hold the value or address of *EXPR_P. */
20197 0 : gcc_unreachable ();
20198 : }
20199 :
20200 : /* We used to check the predicate here and return immediately if it
20201 : succeeds. This is wrong; the design is for gimplification to be
20202 : idempotent, and for the predicates to only test for valid forms, not
20203 : whether they are fully simplified. */
20204 463630676 : if (pre_p == NULL)
20205 0 : pre_p = &internal_pre;
20206 :
20207 463630676 : if (post_p == NULL)
20208 186437314 : post_p = &internal_post;
20209 :
20210 : /* Remember the last statements added to PRE_P and POST_P. Every
20211 : new statement added by the gimplification helpers needs to be
20212 : annotated with location information. To centralize the
20213 : responsibility, we remember the last statement that had been
20214 : added to both queues before gimplifying *EXPR_P. If
20215 : gimplification produces new statements in PRE_P and POST_P, those
20216 : statements will be annotated with the same location information
20217 : as *EXPR_P. */
20218 463630676 : pre_last_gsi = gsi_last (*pre_p);
20219 463630676 : post_last_gsi = gsi_last (*post_p);
20220 :
20221 463630676 : saved_location = input_location;
20222 463630676 : if (save_expr != error_mark_node
20223 463630676 : && EXPR_HAS_LOCATION (*expr_p))
20224 173576085 : input_location = EXPR_LOCATION (*expr_p);
20225 :
20226 : /* Loop over the specific gimplifiers until the toplevel node
20227 : remains the same. */
20228 481711386 : do
20229 : {
20230 : /* Strip away as many useless type conversions as possible
20231 : at the toplevel. */
20232 481711386 : STRIP_USELESS_TYPE_CONVERSION (*expr_p);
20233 :
20234 : /* Remember the expr. */
20235 481711386 : save_expr = *expr_p;
20236 :
20237 : /* Die, die, die, my darling. */
20238 481711386 : if (error_operand_p (save_expr))
20239 : {
20240 : ret = GS_ERROR;
20241 : break;
20242 : }
20243 :
20244 : /* Do any language-specific gimplification. */
20245 481707801 : ret = ((enum gimplify_status)
20246 481707801 : lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
20247 481707801 : if (ret == GS_OK)
20248 : {
20249 28137799 : if (*expr_p == NULL_TREE)
20250 : break;
20251 28137799 : if (*expr_p != save_expr)
20252 4716535 : continue;
20253 : }
20254 453570002 : else if (ret != GS_UNHANDLED)
20255 : break;
20256 :
20257 : /* Make sure that all the cases set 'ret' appropriately. */
20258 476416773 : ret = GS_UNHANDLED;
20259 476416773 : switch (TREE_CODE (*expr_p))
20260 : {
20261 : /* First deal with the special cases. */
20262 :
20263 1135027 : case POSTINCREMENT_EXPR:
20264 1135027 : case POSTDECREMENT_EXPR:
20265 1135027 : case PREINCREMENT_EXPR:
20266 1135027 : case PREDECREMENT_EXPR:
20267 2270054 : ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
20268 : fallback != fb_none,
20269 1135027 : TREE_TYPE (*expr_p));
20270 1135027 : break;
20271 :
20272 589071 : case VIEW_CONVERT_EXPR:
20273 589071 : if ((fallback & fb_rvalue)
20274 588945 : && is_gimple_reg_type (TREE_TYPE (*expr_p))
20275 1002509 : && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
20276 : {
20277 401688 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20278 : post_p, is_gimple_val, fb_rvalue);
20279 401688 : recalculate_side_effects (*expr_p);
20280 401688 : break;
20281 : }
20282 : /* Fallthru. */
20283 :
20284 29933758 : case ARRAY_REF:
20285 29933758 : case ARRAY_RANGE_REF:
20286 29933758 : case REALPART_EXPR:
20287 29933758 : case IMAGPART_EXPR:
20288 29933758 : case COMPONENT_REF:
20289 29933758 : ret = gimplify_compound_lval (expr_p, pre_p, post_p,
20290 : fallback ? fallback : fb_rvalue);
20291 29933758 : break;
20292 :
20293 6195772 : case COND_EXPR:
20294 6195772 : ret = gimplify_cond_expr (expr_p, pre_p, fallback);
20295 :
20296 : /* C99 code may assign to an array in a structure value of a
20297 : conditional expression, and this has undefined behavior
20298 : only on execution, so create a temporary if an lvalue is
20299 : required. */
20300 6195772 : if (fallback == fb_lvalue)
20301 : {
20302 7 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20303 7 : mark_addressable (*expr_p);
20304 7 : ret = GS_OK;
20305 : }
20306 : break;
20307 :
20308 16791386 : case CALL_EXPR:
20309 16791386 : ret = gimplify_call_expr (expr_p, pre_p, fallback);
20310 :
20311 : /* C99 code may assign to an array in a structure returned
20312 : from a function, and this has undefined behavior only on
20313 : execution, so create a temporary if an lvalue is
20314 : required. */
20315 16791386 : if (fallback == fb_lvalue)
20316 : {
20317 17203 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20318 17203 : mark_addressable (*expr_p);
20319 17203 : ret = GS_OK;
20320 : }
20321 : break;
20322 :
20323 0 : case TREE_LIST:
20324 0 : gcc_unreachable ();
20325 :
20326 0 : case OMP_ARRAY_SECTION:
20327 0 : gcc_unreachable ();
20328 :
20329 479954 : case COMPOUND_EXPR:
20330 479954 : ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
20331 479954 : break;
20332 :
20333 37190 : case COMPOUND_LITERAL_EXPR:
20334 37190 : ret = gimplify_compound_literal_expr (expr_p, pre_p,
20335 : gimple_test_f, fallback);
20336 37190 : break;
20337 :
20338 49932830 : case MODIFY_EXPR:
20339 49932830 : case INIT_EXPR:
20340 49932830 : ret = gimplify_modify_expr (expr_p, pre_p, post_p,
20341 : fallback != fb_none);
20342 49932830 : break;
20343 :
20344 113050 : case TRUTH_ANDIF_EXPR:
20345 113050 : case TRUTH_ORIF_EXPR:
20346 113050 : {
20347 : /* Preserve the original type of the expression and the
20348 : source location of the outer expression. */
20349 113050 : tree org_type = TREE_TYPE (*expr_p);
20350 113050 : *expr_p = gimple_boolify (*expr_p);
20351 113050 : *expr_p = build3_loc (input_location, COND_EXPR,
20352 : org_type, *expr_p,
20353 : fold_convert_loc
20354 : (input_location,
20355 : org_type, boolean_true_node),
20356 : fold_convert_loc
20357 : (input_location,
20358 : org_type, boolean_false_node));
20359 113050 : ret = GS_OK;
20360 113050 : break;
20361 : }
20362 :
20363 230460 : case TRUTH_NOT_EXPR:
20364 230460 : {
20365 230460 : tree type = TREE_TYPE (*expr_p);
20366 : /* The parsers are careful to generate TRUTH_NOT_EXPR
20367 : only with operands that are always zero or one.
20368 : We do not fold here but handle the only interesting case
20369 : manually, as fold may re-introduce the TRUTH_NOT_EXPR. */
20370 230460 : *expr_p = gimple_boolify (*expr_p);
20371 230460 : if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
20372 230460 : *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
20373 230460 : TREE_TYPE (*expr_p),
20374 230460 : TREE_OPERAND (*expr_p, 0));
20375 : else
20376 0 : *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
20377 0 : TREE_TYPE (*expr_p),
20378 0 : TREE_OPERAND (*expr_p, 0),
20379 0 : build_int_cst (TREE_TYPE (*expr_p), 1));
20380 230460 : if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
20381 4893 : *expr_p = fold_convert_loc (input_location, type, *expr_p);
20382 : ret = GS_OK;
20383 : break;
20384 : }
20385 :
20386 32770926 : case ADDR_EXPR:
20387 32770926 : ret = gimplify_addr_expr (expr_p, pre_p, post_p);
20388 32770926 : break;
20389 :
20390 5542 : case ANNOTATE_EXPR:
20391 5542 : {
20392 5542 : tree cond = TREE_OPERAND (*expr_p, 0);
20393 5542 : tree kind = TREE_OPERAND (*expr_p, 1);
20394 5542 : tree data = TREE_OPERAND (*expr_p, 2);
20395 5542 : tree type = TREE_TYPE (cond);
20396 5542 : if (!INTEGRAL_TYPE_P (type))
20397 : {
20398 0 : *expr_p = cond;
20399 0 : ret = GS_OK;
20400 0 : break;
20401 : }
20402 5542 : tree tmp = create_tmp_var (type);
20403 5542 : gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
20404 5542 : gcall *call
20405 5542 : = gimple_build_call_internal (IFN_ANNOTATE, 3, cond, kind, data);
20406 5542 : gimple_call_set_lhs (call, tmp);
20407 5542 : gimplify_seq_add_stmt (pre_p, call);
20408 5542 : *expr_p = tmp;
20409 5542 : ret = GS_ALL_DONE;
20410 5542 : break;
20411 : }
20412 :
20413 50967 : case VA_ARG_EXPR:
20414 50967 : ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
20415 50967 : break;
20416 :
20417 17200099 : CASE_CONVERT:
20418 17200099 : if (IS_EMPTY_STMT (*expr_p))
20419 : {
20420 : ret = GS_ALL_DONE;
20421 : break;
20422 : }
20423 :
20424 15479920 : if (VOID_TYPE_P (TREE_TYPE (*expr_p))
20425 15479920 : || fallback == fb_none)
20426 : {
20427 : /* Just strip a conversion to void (or in void context) and
20428 : try again. */
20429 2620436 : *expr_p = TREE_OPERAND (*expr_p, 0);
20430 2620436 : ret = GS_OK;
20431 2620436 : break;
20432 : }
20433 :
20434 12859484 : ret = gimplify_conversion (expr_p);
20435 12859484 : if (ret == GS_ERROR)
20436 : break;
20437 12859484 : if (*expr_p != save_expr)
20438 : break;
20439 : /* FALLTHRU */
20440 :
20441 12985820 : case FIX_TRUNC_EXPR:
20442 : /* unary_expr: ... | '(' cast ')' val | ... */
20443 12985820 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20444 : is_gimple_val, fb_rvalue);
20445 12985820 : recalculate_side_effects (*expr_p);
20446 12985820 : break;
20447 :
20448 6179239 : case INDIRECT_REF:
20449 6179239 : {
20450 6179239 : bool volatilep = TREE_THIS_VOLATILE (*expr_p);
20451 6179239 : bool notrap = TREE_THIS_NOTRAP (*expr_p);
20452 6179239 : tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
20453 :
20454 6179239 : *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
20455 6179239 : if (*expr_p != save_expr)
20456 : {
20457 : ret = GS_OK;
20458 : break;
20459 : }
20460 :
20461 6161357 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20462 : is_gimple_reg, fb_rvalue);
20463 6161357 : if (ret == GS_ERROR)
20464 : break;
20465 :
20466 6161355 : recalculate_side_effects (*expr_p);
20467 12322710 : *expr_p = fold_build2_loc (input_location, MEM_REF,
20468 6161355 : TREE_TYPE (*expr_p),
20469 6161355 : TREE_OPERAND (*expr_p, 0),
20470 : build_int_cst (saved_ptr_type, 0));
20471 6161355 : TREE_THIS_VOLATILE (*expr_p) = volatilep;
20472 6161355 : TREE_THIS_NOTRAP (*expr_p) = notrap;
20473 6161355 : ret = GS_OK;
20474 6161355 : break;
20475 : }
20476 :
20477 : /* We arrive here through the various re-gimplifcation paths. */
20478 15710703 : case MEM_REF:
20479 : /* First try re-folding the whole thing. */
20480 15710703 : tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
20481 : TREE_OPERAND (*expr_p, 0),
20482 : TREE_OPERAND (*expr_p, 1));
20483 15710703 : if (tmp)
20484 : {
20485 6576 : REF_REVERSE_STORAGE_ORDER (tmp)
20486 3288 : = REF_REVERSE_STORAGE_ORDER (*expr_p);
20487 3288 : *expr_p = tmp;
20488 3288 : recalculate_side_effects (*expr_p);
20489 3288 : ret = GS_OK;
20490 3288 : break;
20491 : }
20492 : /* Avoid re-gimplifying the address operand if it is already
20493 : in suitable form. Re-gimplifying would mark the address
20494 : operand addressable. Always gimplify when not in SSA form
20495 : as we still may have to gimplify decls with value-exprs. */
20496 15707415 : if (!gimplify_ctxp || !gimple_in_ssa_p (cfun)
20497 16714535 : || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
20498 : {
20499 14755227 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20500 : is_gimple_mem_ref_addr, fb_rvalue);
20501 14755227 : if (ret == GS_ERROR)
20502 : break;
20503 : }
20504 15707415 : recalculate_side_effects (*expr_p);
20505 15707415 : ret = GS_ALL_DONE;
20506 15707415 : break;
20507 :
20508 : /* Constants need not be gimplified. */
20509 43943014 : case INTEGER_CST:
20510 43943014 : case REAL_CST:
20511 43943014 : case FIXED_CST:
20512 43943014 : case STRING_CST:
20513 43943014 : case COMPLEX_CST:
20514 43943014 : case VECTOR_CST:
20515 : /* Drop the overflow flag on constants, we do not want
20516 : that in the GIMPLE IL. */
20517 43943014 : if (TREE_OVERFLOW_P (*expr_p))
20518 1224 : *expr_p = drop_tree_overflow (*expr_p);
20519 : ret = GS_ALL_DONE;
20520 : break;
20521 :
20522 117115 : case CONST_DECL:
20523 : /* If we require an lvalue, such as for ADDR_EXPR, retain the
20524 : CONST_DECL node. Otherwise the decl is replaceable by its
20525 : value. */
20526 : /* ??? Should be == fb_lvalue, but ADDR_EXPR passes fb_either. */
20527 117115 : if (fallback & fb_lvalue)
20528 : ret = GS_ALL_DONE;
20529 : else
20530 : {
20531 3226 : *expr_p = DECL_INITIAL (*expr_p);
20532 3226 : ret = GS_OK;
20533 : }
20534 : break;
20535 :
20536 6515579 : case DECL_EXPR:
20537 6515579 : ret = gimplify_decl_expr (expr_p, pre_p);
20538 6515579 : break;
20539 :
20540 5929834 : case BIND_EXPR:
20541 5929834 : ret = gimplify_bind_expr (expr_p, pre_p);
20542 5929834 : break;
20543 :
20544 202742 : case LOOP_EXPR:
20545 202742 : ret = gimplify_loop_expr (expr_p, pre_p);
20546 202742 : break;
20547 :
20548 49454 : case SWITCH_EXPR:
20549 49454 : ret = gimplify_switch_expr (expr_p, pre_p);
20550 49454 : break;
20551 :
20552 3223 : case EXIT_EXPR:
20553 3223 : ret = gimplify_exit_expr (expr_p);
20554 3223 : break;
20555 :
20556 1097546 : case GOTO_EXPR:
20557 : /* If the target is not LABEL, then it is a computed jump
20558 : and the target needs to be gimplified. */
20559 1097546 : if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
20560 : {
20561 1111 : ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
20562 : NULL, is_gimple_val, fb_rvalue);
20563 1111 : if (ret == GS_ERROR)
20564 : break;
20565 : }
20566 2195090 : gimplify_seq_add_stmt (pre_p,
20567 1097545 : gimple_build_goto (GOTO_DESTINATION (*expr_p)));
20568 1097545 : ret = GS_ALL_DONE;
20569 1097545 : break;
20570 :
20571 102213 : case PREDICT_EXPR:
20572 408852 : gimplify_seq_add_stmt (pre_p,
20573 102213 : gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
20574 102213 : PREDICT_EXPR_OUTCOME (*expr_p)));
20575 102213 : ret = GS_ALL_DONE;
20576 102213 : break;
20577 :
20578 2542478 : case LABEL_EXPR:
20579 2542478 : ret = gimplify_label_expr (expr_p, pre_p);
20580 2542478 : label = LABEL_EXPR_LABEL (*expr_p);
20581 2542478 : gcc_assert (decl_function_context (label) == current_function_decl);
20582 :
20583 : /* If the label is used in a goto statement, or address of the label
20584 : is taken, we need to unpoison all variables that were seen so far.
20585 : Doing so would prevent us from reporting a false positives. */
20586 2542478 : if (asan_poisoned_variables
20587 4015 : && asan_used_labels != NULL
20588 1325 : && asan_used_labels->contains (label)
20589 2543390 : && !gimplify_omp_ctxp)
20590 904 : asan_poison_variables (asan_poisoned_variables, false, pre_p);
20591 : break;
20592 :
20593 1033391 : case CASE_LABEL_EXPR:
20594 1033391 : ret = gimplify_case_label_expr (expr_p, pre_p);
20595 :
20596 1033391 : if (gimplify_ctxp->live_switch_vars)
20597 1033204 : asan_poison_variables (gimplify_ctxp->live_switch_vars, false,
20598 : pre_p);
20599 : break;
20600 :
20601 2211446 : case RETURN_EXPR:
20602 2211446 : ret = gimplify_return_expr (*expr_p, pre_p);
20603 2211446 : break;
20604 :
20605 950252 : case CONSTRUCTOR:
20606 : /* Don't reduce this in place; let gimplify_init_constructor work its
20607 : magic. Buf if we're just elaborating this for side effects, just
20608 : gimplify any element that has side-effects. */
20609 950252 : if (fallback == fb_none)
20610 : {
20611 357 : unsigned HOST_WIDE_INT ix;
20612 357 : tree val;
20613 357 : tree temp = NULL_TREE;
20614 374 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
20615 17 : if (TREE_SIDE_EFFECTS (val))
20616 4 : append_to_statement_list (val, &temp);
20617 :
20618 357 : *expr_p = temp;
20619 357 : ret = temp ? GS_OK : GS_ALL_DONE;
20620 : }
20621 : /* C99 code may assign to an array in a constructed
20622 : structure or union, and this has undefined behavior only
20623 : on execution, so create a temporary if an lvalue is
20624 : required. */
20625 949895 : else if (fallback == fb_lvalue)
20626 : {
20627 11 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20628 11 : mark_addressable (*expr_p);
20629 11 : ret = GS_OK;
20630 : }
20631 : else
20632 : ret = GS_ALL_DONE;
20633 : break;
20634 :
20635 : /* The following are special cases that are not handled by the
20636 : original GIMPLE grammar. */
20637 :
20638 : /* SAVE_EXPR nodes are converted into a GIMPLE identifier and
20639 : eliminated. */
20640 439867 : case SAVE_EXPR:
20641 439867 : ret = gimplify_save_expr (expr_p, pre_p, post_p);
20642 439867 : break;
20643 :
20644 379400 : case BIT_FIELD_REF:
20645 379400 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20646 : post_p, is_gimple_lvalue, fb_either);
20647 379400 : recalculate_side_effects (*expr_p);
20648 379400 : break;
20649 :
20650 2448 : case TARGET_MEM_REF:
20651 2448 : {
20652 2448 : enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
20653 :
20654 2448 : if (TMR_BASE (*expr_p))
20655 2448 : r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
20656 : post_p, is_gimple_mem_ref_addr, fb_either);
20657 2448 : if (TMR_INDEX (*expr_p))
20658 1185 : r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
20659 : post_p, is_gimple_val, fb_rvalue);
20660 2448 : if (TMR_INDEX2 (*expr_p))
20661 60 : r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
20662 : post_p, is_gimple_val, fb_rvalue);
20663 : /* TMR_STEP and TMR_OFFSET are always integer constants. */
20664 2448 : ret = MIN (r0, r1);
20665 : }
20666 : break;
20667 :
20668 0 : case NON_LVALUE_EXPR:
20669 : /* This should have been stripped above. */
20670 0 : gcc_unreachable ();
20671 :
20672 97702 : case ASM_EXPR:
20673 97702 : ret = gimplify_asm_expr (expr_p, pre_p, post_p);
20674 97702 : break;
20675 :
20676 494757 : case TRY_FINALLY_EXPR:
20677 494757 : case TRY_CATCH_EXPR:
20678 494757 : {
20679 494757 : gimple_seq eval, cleanup;
20680 494757 : gtry *try_;
20681 :
20682 : /* Calls to destructors are generated automatically in FINALLY/CATCH
20683 : block. They should have location as UNKNOWN_LOCATION. However,
20684 : gimplify_call_expr will reset these call stmts to input_location
20685 : if it finds stmt's location is unknown. To prevent resetting for
20686 : destructors, we set the input_location to unknown.
20687 : Note that this only affects the destructor calls in FINALLY/CATCH
20688 : block, and will automatically reset to its original value by the
20689 : end of gimplify_expr. */
20690 494757 : input_location = UNKNOWN_LOCATION;
20691 494757 : eval = cleanup = NULL;
20692 494757 : gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
20693 494757 : bool save_in_handler_expr = gimplify_ctxp->in_handler_expr;
20694 494757 : if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20695 494757 : && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR)
20696 : {
20697 155 : gimple_seq n = NULL, e = NULL;
20698 155 : gimplify_ctxp->in_handler_expr = true;
20699 155 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20700 : 0), &n);
20701 155 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20702 : 1), &e);
20703 155 : if (!gimple_seq_empty_p (n) || !gimple_seq_empty_p (e))
20704 : {
20705 151 : geh_else *stmt = gimple_build_eh_else (n, e);
20706 151 : gimple_seq_add_stmt (&cleanup, stmt);
20707 : }
20708 : }
20709 : else
20710 : {
20711 494602 : gimplify_ctxp->in_handler_expr = true;
20712 494602 : gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
20713 : }
20714 494757 : gimplify_ctxp->in_handler_expr = save_in_handler_expr;
20715 : /* Don't create bogus GIMPLE_TRY with empty cleanup. */
20716 494757 : if (gimple_seq_empty_p (cleanup))
20717 : {
20718 27307 : gimple_seq_add_seq (pre_p, eval);
20719 27307 : ret = GS_ALL_DONE;
20720 27307 : break;
20721 : }
20722 467450 : try_ = gimple_build_try (eval, cleanup,
20723 467450 : TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20724 : ? GIMPLE_TRY_FINALLY
20725 : : GIMPLE_TRY_CATCH);
20726 467450 : if (EXPR_HAS_LOCATION (save_expr))
20727 855134 : gimple_set_location (try_, EXPR_LOCATION (save_expr));
20728 39883 : else if (LOCATION_LOCUS (saved_location) != UNKNOWN_LOCATION)
20729 29443 : gimple_set_location (try_, saved_location);
20730 467450 : if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
20731 167387 : gimple_try_set_catch_is_cleanup (try_,
20732 167387 : TRY_CATCH_IS_CLEANUP (*expr_p));
20733 467450 : gimplify_seq_add_stmt (pre_p, try_);
20734 467450 : ret = GS_ALL_DONE;
20735 467450 : break;
20736 : }
20737 :
20738 5167005 : case CLEANUP_POINT_EXPR:
20739 5167005 : ret = gimplify_cleanup_point_expr (expr_p, pre_p);
20740 5167005 : break;
20741 :
20742 803585 : case TARGET_EXPR:
20743 803585 : ret = gimplify_target_expr (expr_p, pre_p, post_p);
20744 803585 : break;
20745 :
20746 39914 : case CATCH_EXPR:
20747 39914 : {
20748 39914 : gimple *c;
20749 39914 : gimple_seq handler = NULL;
20750 39914 : gimplify_and_add (CATCH_BODY (*expr_p), &handler);
20751 39914 : c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
20752 39914 : gimplify_seq_add_stmt (pre_p, c);
20753 39914 : ret = GS_ALL_DONE;
20754 39914 : break;
20755 : }
20756 :
20757 5532 : case EH_FILTER_EXPR:
20758 5532 : {
20759 5532 : gimple *ehf;
20760 5532 : gimple_seq failure = NULL;
20761 :
20762 5532 : gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
20763 5532 : ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
20764 5532 : copy_warning (ehf, *expr_p);
20765 5532 : gimplify_seq_add_stmt (pre_p, ehf);
20766 5532 : ret = GS_ALL_DONE;
20767 5532 : break;
20768 : }
20769 :
20770 49686 : case OBJ_TYPE_REF:
20771 49686 : {
20772 49686 : enum gimplify_status r0, r1;
20773 49686 : r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p,
20774 : post_p, is_gimple_val, fb_rvalue);
20775 49686 : r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p,
20776 : post_p, is_gimple_val, fb_rvalue);
20777 49686 : TREE_SIDE_EFFECTS (*expr_p) = 0;
20778 49686 : ret = MIN (r0, r1);
20779 : }
20780 : break;
20781 :
20782 40734 : case LABEL_DECL:
20783 : /* We get here when taking the address of a label. We mark
20784 : the label as "forced"; meaning it can never be removed and
20785 : it is a potential target for any computed goto. */
20786 40734 : FORCED_LABEL (*expr_p) = 1;
20787 40734 : ret = GS_ALL_DONE;
20788 40734 : break;
20789 :
20790 8477107 : case STATEMENT_LIST:
20791 8477107 : ret = gimplify_statement_list (expr_p, pre_p);
20792 8477107 : break;
20793 :
20794 1728 : case WITH_SIZE_EXPR:
20795 1728 : {
20796 2010 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20797 : post_p == &internal_post ? NULL : post_p,
20798 : gimple_test_f, fallback);
20799 1728 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
20800 : is_gimple_val, fb_rvalue);
20801 1728 : ret = GS_ALL_DONE;
20802 : }
20803 1728 : break;
20804 :
20805 108204589 : case VAR_DECL:
20806 108204589 : case PARM_DECL:
20807 108204589 : ret = gimplify_var_or_parm_decl (expr_p);
20808 108204589 : break;
20809 :
20810 338684 : case RESULT_DECL:
20811 : /* When within an OMP context, notice uses of variables. */
20812 338684 : if (gimplify_omp_ctxp)
20813 1412 : omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
20814 : /* Handlers can refer to the function result; if that has been
20815 : moved, we need to track it. */
20816 338684 : if (gimplify_ctxp->in_handler_expr && gimplify_ctxp->return_temp)
20817 50 : *expr_p = gimplify_ctxp->return_temp;
20818 : ret = GS_ALL_DONE;
20819 : break;
20820 :
20821 0 : case DEBUG_EXPR_DECL:
20822 0 : gcc_unreachable ();
20823 :
20824 2460570 : case DEBUG_BEGIN_STMT:
20825 4921140 : gimplify_seq_add_stmt (pre_p,
20826 : gimple_build_debug_begin_stmt
20827 2460570 : (TREE_BLOCK (*expr_p),
20828 2460570 : EXPR_LOCATION (*expr_p)));
20829 2460570 : ret = GS_ALL_DONE;
20830 2460570 : *expr_p = NULL;
20831 2460570 : break;
20832 :
20833 : case SSA_NAME:
20834 : /* Allow callbacks into the gimplifier during optimization. */
20835 : ret = GS_ALL_DONE;
20836 : break;
20837 :
20838 18229 : case OMP_PARALLEL:
20839 18229 : gimplify_omp_parallel (expr_p, pre_p);
20840 18229 : ret = GS_ALL_DONE;
20841 18229 : break;
20842 :
20843 3853 : case OMP_TASK:
20844 3853 : gimplify_omp_task (expr_p, pre_p);
20845 3853 : ret = GS_ALL_DONE;
20846 3853 : break;
20847 :
20848 10683 : case OMP_SIMD:
20849 10683 : {
20850 : /* Temporarily disable into_ssa, as scan_omp_simd
20851 : which calls copy_gimple_seq_and_replace_locals can't deal
20852 : with SSA_NAMEs defined outside of the body properly. */
20853 10683 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
20854 10683 : gimplify_ctxp->into_ssa = false;
20855 10683 : ret = gimplify_omp_for (expr_p, pre_p);
20856 10683 : gimplify_ctxp->into_ssa = saved_into_ssa;
20857 10683 : break;
20858 : }
20859 :
20860 47401 : case OMP_FOR:
20861 47401 : case OMP_DISTRIBUTE:
20862 47401 : case OMP_TASKLOOP:
20863 47401 : case OMP_TILE:
20864 47401 : case OMP_UNROLL:
20865 47401 : case OACC_LOOP:
20866 47401 : ret = gimplify_omp_for (expr_p, pre_p);
20867 47401 : break;
20868 :
20869 1056 : case OMP_LOOP:
20870 1056 : ret = gimplify_omp_loop (expr_p, pre_p);
20871 1056 : break;
20872 :
20873 665 : case OACC_CACHE:
20874 665 : gimplify_oacc_cache (expr_p, pre_p);
20875 665 : ret = GS_ALL_DONE;
20876 665 : break;
20877 :
20878 254 : case OACC_DECLARE:
20879 254 : gimplify_oacc_declare (expr_p, pre_p);
20880 254 : ret = GS_ALL_DONE;
20881 254 : break;
20882 :
20883 39757 : case OACC_HOST_DATA:
20884 39757 : case OACC_DATA:
20885 39757 : case OACC_KERNELS:
20886 39757 : case OACC_PARALLEL:
20887 39757 : case OACC_SERIAL:
20888 39757 : case OMP_SCOPE:
20889 39757 : case OMP_SECTIONS:
20890 39757 : case OMP_SINGLE:
20891 39757 : case OMP_TARGET:
20892 39757 : case OMP_TARGET_DATA:
20893 39757 : case OMP_TEAMS:
20894 39757 : gimplify_omp_workshare (expr_p, pre_p);
20895 39757 : ret = GS_ALL_DONE;
20896 39757 : break;
20897 :
20898 12270 : case OACC_ENTER_DATA:
20899 12270 : case OACC_EXIT_DATA:
20900 12270 : case OACC_UPDATE:
20901 12270 : case OMP_TARGET_UPDATE:
20902 12270 : case OMP_TARGET_ENTER_DATA:
20903 12270 : case OMP_TARGET_EXIT_DATA:
20904 12270 : gimplify_omp_target_update (expr_p, pre_p);
20905 12270 : ret = GS_ALL_DONE;
20906 12270 : break;
20907 :
20908 7037 : case OMP_SECTION:
20909 7037 : case OMP_STRUCTURED_BLOCK:
20910 7037 : case OMP_MASTER:
20911 7037 : case OMP_MASKED:
20912 7037 : case OMP_ORDERED:
20913 7037 : case OMP_CRITICAL:
20914 7037 : case OMP_SCAN:
20915 7037 : {
20916 7037 : gimple_seq body = NULL;
20917 7037 : gimple *g;
20918 7037 : bool saved_in_omp_construct = in_omp_construct;
20919 :
20920 7037 : in_omp_construct = true;
20921 7037 : gimplify_and_add (OMP_BODY (*expr_p), &body);
20922 7037 : in_omp_construct = saved_in_omp_construct;
20923 7037 : switch (TREE_CODE (*expr_p))
20924 : {
20925 1271 : case OMP_SECTION:
20926 1271 : g = gimple_build_omp_section (body);
20927 1271 : break;
20928 791 : case OMP_STRUCTURED_BLOCK:
20929 791 : g = gimple_build_omp_structured_block (body);
20930 791 : break;
20931 874 : case OMP_MASTER:
20932 874 : g = gimple_build_omp_master (body);
20933 874 : break;
20934 1950 : case OMP_ORDERED:
20935 1950 : g = gimplify_omp_ordered (*expr_p, body);
20936 1950 : if (OMP_BODY (*expr_p) == NULL_TREE
20937 1950 : && gimple_code (g) == GIMPLE_OMP_ORDERED)
20938 1025 : gimple_omp_ordered_standalone (g);
20939 : break;
20940 487 : case OMP_MASKED:
20941 487 : gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p),
20942 : pre_p, ORT_WORKSHARE, OMP_MASKED);
20943 487 : gimplify_adjust_omp_clauses (pre_p, body,
20944 : &OMP_MASKED_CLAUSES (*expr_p),
20945 : OMP_MASKED);
20946 974 : g = gimple_build_omp_masked (body,
20947 487 : OMP_MASKED_CLAUSES (*expr_p));
20948 487 : break;
20949 546 : case OMP_CRITICAL:
20950 546 : gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
20951 : pre_p, ORT_WORKSHARE, OMP_CRITICAL);
20952 546 : gimplify_adjust_omp_clauses (pre_p, body,
20953 : &OMP_CRITICAL_CLAUSES (*expr_p),
20954 : OMP_CRITICAL);
20955 1638 : g = gimple_build_omp_critical (body,
20956 546 : OMP_CRITICAL_NAME (*expr_p),
20957 546 : OMP_CRITICAL_CLAUSES (*expr_p));
20958 546 : break;
20959 1118 : case OMP_SCAN:
20960 1118 : gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
20961 : pre_p, ORT_WORKSHARE, OMP_SCAN);
20962 1118 : gimplify_adjust_omp_clauses (pre_p, body,
20963 : &OMP_SCAN_CLAUSES (*expr_p),
20964 : OMP_SCAN);
20965 1118 : g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
20966 1118 : break;
20967 0 : default:
20968 0 : gcc_unreachable ();
20969 : }
20970 7037 : gimplify_seq_add_stmt (pre_p, g);
20971 7037 : ret = GS_ALL_DONE;
20972 7037 : break;
20973 : }
20974 :
20975 611 : case OMP_TASKGROUP:
20976 611 : {
20977 611 : gimple_seq body = NULL;
20978 :
20979 611 : tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p);
20980 611 : bool saved_in_omp_construct = in_omp_construct;
20981 611 : gimplify_scan_omp_clauses (pclauses, pre_p, ORT_TASKGROUP,
20982 : OMP_TASKGROUP);
20983 611 : gimplify_adjust_omp_clauses (pre_p, NULL, pclauses, OMP_TASKGROUP);
20984 :
20985 611 : in_omp_construct = true;
20986 611 : gimplify_and_add (OMP_BODY (*expr_p), &body);
20987 611 : in_omp_construct = saved_in_omp_construct;
20988 611 : gimple_seq cleanup = NULL;
20989 611 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END);
20990 611 : gimple *g = gimple_build_call (fn, 0);
20991 611 : gimple_seq_add_stmt (&cleanup, g);
20992 611 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
20993 611 : body = NULL;
20994 611 : gimple_seq_add_stmt (&body, g);
20995 611 : g = gimple_build_omp_taskgroup (body, *pclauses);
20996 611 : gimplify_seq_add_stmt (pre_p, g);
20997 611 : ret = GS_ALL_DONE;
20998 611 : break;
20999 : }
21000 :
21001 612 : case OMP_INTEROP:
21002 612 : ret = gimplify_omp_interop (expr_p, pre_p);
21003 612 : break;
21004 10236 : case OMP_ATOMIC:
21005 10236 : case OMP_ATOMIC_READ:
21006 10236 : case OMP_ATOMIC_CAPTURE_OLD:
21007 10236 : case OMP_ATOMIC_CAPTURE_NEW:
21008 10236 : ret = gimplify_omp_atomic (expr_p, pre_p);
21009 10236 : break;
21010 :
21011 852 : case OMP_DISPATCH:
21012 852 : ret = gimplify_omp_dispatch (expr_p, pre_p);
21013 852 : break;
21014 :
21015 174 : case OMP_METADIRECTIVE:
21016 174 : ret = gimplify_omp_metadirective (expr_p, pre_p, post_p,
21017 : gimple_test_f, fallback);
21018 174 : break;
21019 :
21020 36 : case OMP_NEXT_VARIANT:
21021 36 : case OMP_TARGET_DEVICE_MATCHES:
21022 : /* These are placeholders for constants. There's nothing to do with
21023 : them here but we must mark the containing function as needing
21024 : to run the ompdevlow pass to resolve them. Note that
21025 : OMP_TARGET_DEVICE_MATCHES, in particular, may be inserted by
21026 : the front ends. */
21027 36 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
21028 36 : ret = GS_ALL_DONE;
21029 36 : break;
21030 :
21031 0 : case OMP_DECLARE_MAPPER:
21032 0 : ret = gimplify_omp_declare_mapper (expr_p);
21033 0 : break;
21034 :
21035 478 : case TRANSACTION_EXPR:
21036 478 : ret = gimplify_transaction (expr_p, pre_p);
21037 478 : break;
21038 :
21039 288631 : case TRUTH_AND_EXPR:
21040 288631 : case TRUTH_OR_EXPR:
21041 288631 : case TRUTH_XOR_EXPR:
21042 288631 : {
21043 288631 : tree orig_type = TREE_TYPE (*expr_p);
21044 288631 : tree new_type, xop0, xop1;
21045 288631 : *expr_p = gimple_boolify (*expr_p);
21046 288631 : new_type = TREE_TYPE (*expr_p);
21047 288631 : if (!useless_type_conversion_p (orig_type, new_type))
21048 : {
21049 1137 : *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
21050 1137 : ret = GS_OK;
21051 1137 : break;
21052 : }
21053 :
21054 : /* Boolified binary truth expressions are semantically equivalent
21055 : to bitwise binary expressions. Canonicalize them to the
21056 : bitwise variant. */
21057 287494 : switch (TREE_CODE (*expr_p))
21058 : {
21059 170805 : case TRUTH_AND_EXPR:
21060 170805 : TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
21061 170805 : break;
21062 116086 : case TRUTH_OR_EXPR:
21063 116086 : TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
21064 116086 : break;
21065 603 : case TRUTH_XOR_EXPR:
21066 603 : TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
21067 603 : break;
21068 : default:
21069 : break;
21070 : }
21071 : /* Now make sure that operands have compatible type to
21072 : expression's new_type. */
21073 287494 : xop0 = TREE_OPERAND (*expr_p, 0);
21074 287494 : xop1 = TREE_OPERAND (*expr_p, 1);
21075 287494 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
21076 326 : TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
21077 : new_type,
21078 : xop0);
21079 287494 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
21080 366 : TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
21081 : new_type,
21082 : xop1);
21083 : /* Continue classified as tcc_binary. */
21084 287494 : goto expr_2;
21085 : }
21086 :
21087 10354 : case VEC_COND_EXPR:
21088 10354 : goto expr_3;
21089 :
21090 133416 : case VEC_PERM_EXPR:
21091 : /* Classified as tcc_expression. */
21092 133416 : goto expr_3;
21093 :
21094 48 : case BIT_INSERT_EXPR:
21095 : /* Argument 3 is a constant. */
21096 48 : goto expr_2;
21097 :
21098 3850869 : case POINTER_PLUS_EXPR:
21099 3850869 : {
21100 3850869 : enum gimplify_status r0, r1;
21101 3850869 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21102 : post_p, is_gimple_val, fb_rvalue);
21103 3850869 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21104 : post_p, is_gimple_val, fb_rvalue);
21105 3850869 : recalculate_side_effects (*expr_p);
21106 3850869 : ret = MIN (r0, r1);
21107 : break;
21108 : }
21109 :
21110 44176111 : default:
21111 44176111 : switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
21112 : {
21113 6959023 : case tcc_comparison:
21114 : /* Handle comparison of objects of non scalar mode aggregates
21115 : with a call to memcmp. It would be nice to only have to do
21116 : this for variable-sized objects, but then we'd have to allow
21117 : the same nest of reference nodes we allow for MODIFY_EXPR and
21118 : that's too complex.
21119 :
21120 : Compare scalar mode aggregates as scalar mode values. Using
21121 : memcmp for them would be very inefficient at best, and is
21122 : plain wrong if bitfields are involved. */
21123 6959023 : if (error_operand_p (TREE_OPERAND (*expr_p, 1)))
21124 : ret = GS_ERROR;
21125 : else
21126 : {
21127 6959023 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
21128 :
21129 : /* Vector comparisons need no boolification. */
21130 6959023 : if (TREE_CODE (type) == VECTOR_TYPE)
21131 12378 : goto expr_2;
21132 6946645 : else if (!AGGREGATE_TYPE_P (type))
21133 : {
21134 6946629 : tree org_type = TREE_TYPE (*expr_p);
21135 6946629 : *expr_p = gimple_boolify (*expr_p);
21136 6946629 : if (!useless_type_conversion_p (org_type,
21137 6946629 : TREE_TYPE (*expr_p)))
21138 : {
21139 56031 : *expr_p = fold_convert_loc (input_location,
21140 : org_type, *expr_p);
21141 56031 : ret = GS_OK;
21142 : }
21143 : else
21144 6890598 : goto expr_2;
21145 : }
21146 16 : else if (SCALAR_INT_MODE_P (TYPE_MODE (type)))
21147 16 : ret = gimplify_scalar_mode_aggregate_compare (expr_p);
21148 : else
21149 0 : ret = gimplify_variable_sized_compare (expr_p);
21150 : }
21151 : break;
21152 :
21153 : /* If *EXPR_P does not need to be special-cased, handle it
21154 : according to its class. */
21155 1585407 : case tcc_unary:
21156 1585407 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21157 : post_p, is_gimple_val, fb_rvalue);
21158 1585407 : break;
21159 :
21160 26295376 : case tcc_binary:
21161 26295376 : expr_2:
21162 26295376 : {
21163 26295376 : enum gimplify_status r0, r1;
21164 :
21165 26295376 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21166 : post_p, is_gimple_val, fb_rvalue);
21167 26295376 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21168 : post_p, is_gimple_val, fb_rvalue);
21169 :
21170 26295376 : ret = MIN (r0, r1);
21171 : break;
21172 : }
21173 :
21174 143770 : expr_3:
21175 143770 : {
21176 143770 : enum gimplify_status r0, r1, r2;
21177 :
21178 143770 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21179 : post_p, is_gimple_val, fb_rvalue);
21180 143770 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21181 : post_p, is_gimple_val, fb_rvalue);
21182 143770 : r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
21183 : post_p, is_gimple_val, fb_rvalue);
21184 :
21185 143770 : ret = MIN (MIN (r0, r1), r2);
21186 : break;
21187 : }
21188 :
21189 16526823 : case tcc_declaration:
21190 16526823 : case tcc_constant:
21191 16526823 : ret = GS_ALL_DONE;
21192 16526823 : goto dont_recalculate;
21193 :
21194 0 : default:
21195 0 : gcc_unreachable ();
21196 : }
21197 :
21198 28080600 : recalculate_side_effects (*expr_p);
21199 :
21200 476416773 : dont_recalculate:
21201 : break;
21202 : }
21203 :
21204 476416773 : gcc_assert (*expr_p || ret != GS_OK);
21205 : }
21206 481133308 : while (ret == GS_OK);
21207 :
21208 : /* If we encountered an error_mark somewhere nested inside, either
21209 : stub out the statement or propagate the error back out. */
21210 463630676 : if (ret == GS_ERROR)
21211 : {
21212 5206 : if (is_statement)
21213 3985 : *expr_p = NULL;
21214 5206 : goto out;
21215 : }
21216 :
21217 : /* This was only valid as a return value from the langhook, which
21218 : we handled. Make sure it doesn't escape from any other context. */
21219 463625470 : gcc_assert (ret != GS_UNHANDLED);
21220 :
21221 463625470 : if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
21222 : {
21223 : /* We aren't looking for a value, and we don't have a valid
21224 : statement. If it doesn't have side-effects, throw it away.
21225 : We can also get here with code such as "*&&L;", where L is
21226 : a LABEL_DECL that is marked as FORCED_LABEL. */
21227 1181020 : if (TREE_CODE (*expr_p) == LABEL_DECL
21228 1181020 : || !TREE_SIDE_EFFECTS (*expr_p))
21229 1180004 : *expr_p = NULL;
21230 1016 : else if (!TREE_THIS_VOLATILE (*expr_p))
21231 : {
21232 : /* This is probably a _REF that contains something nested that
21233 : has side effects. Recurse through the operands to find it. */
21234 0 : enum tree_code code = TREE_CODE (*expr_p);
21235 :
21236 0 : switch (code)
21237 : {
21238 0 : case COMPONENT_REF:
21239 0 : case REALPART_EXPR:
21240 0 : case IMAGPART_EXPR:
21241 0 : case VIEW_CONVERT_EXPR:
21242 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21243 : gimple_test_f, fallback);
21244 0 : break;
21245 :
21246 0 : case ARRAY_REF:
21247 0 : case ARRAY_RANGE_REF:
21248 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21249 : gimple_test_f, fallback);
21250 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
21251 : gimple_test_f, fallback);
21252 0 : break;
21253 :
21254 0 : default:
21255 : /* Anything else with side-effects must be converted to
21256 : a valid statement before we get here. */
21257 0 : gcc_unreachable ();
21258 : }
21259 :
21260 0 : *expr_p = NULL;
21261 : }
21262 1016 : else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
21263 966 : && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode
21264 1969 : && !is_empty_type (TREE_TYPE (*expr_p)))
21265 : {
21266 : /* Historically, the compiler has treated a bare reference
21267 : to a non-BLKmode volatile lvalue as forcing a load. */
21268 893 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
21269 :
21270 : /* Normally, we do not want to create a temporary for a
21271 : TREE_ADDRESSABLE type because such a type should not be
21272 : copied by bitwise-assignment. However, we make an
21273 : exception here, as all we are doing here is ensuring that
21274 : we read the bytes that make up the type. We use
21275 : create_tmp_var_raw because create_tmp_var will abort when
21276 : given a TREE_ADDRESSABLE type. */
21277 893 : tree tmp = create_tmp_var_raw (type, "vol");
21278 893 : gimple_add_tmp_var (tmp);
21279 893 : gimplify_assign (tmp, *expr_p, pre_p);
21280 893 : *expr_p = NULL;
21281 : }
21282 : else
21283 : /* We can't do anything useful with a volatile reference to
21284 : an incomplete type, so just throw it away. Likewise for
21285 : a BLKmode type, since any implicit inner load should
21286 : already have been turned into an explicit one by the
21287 : gimplification process. */
21288 123 : *expr_p = NULL;
21289 : }
21290 :
21291 : /* If we are gimplifying at the statement level, we're done. Tack
21292 : everything together and return. */
21293 463625470 : if (fallback == fb_none || is_statement)
21294 : {
21295 : /* Since *EXPR_P has been converted into a GIMPLE tuple, clear
21296 : it out for GC to reclaim it. */
21297 100637969 : *expr_p = NULL_TREE;
21298 :
21299 100637969 : if (!gimple_seq_empty_p (internal_pre)
21300 100637969 : || !gimple_seq_empty_p (internal_post))
21301 : {
21302 19 : gimplify_seq_add_seq (&internal_pre, internal_post);
21303 19 : gimplify_seq_add_seq (pre_p, internal_pre);
21304 : }
21305 :
21306 : /* The result of gimplifying *EXPR_P is going to be the last few
21307 : statements in *PRE_P and *POST_P. Add location information
21308 : to all the statements that were added by the gimplification
21309 : helpers. */
21310 100637969 : if (!gimple_seq_empty_p (*pre_p))
21311 98169269 : annotate_all_with_location_after (*pre_p, pre_last_gsi, input_location);
21312 :
21313 100637969 : if (!gimple_seq_empty_p (*post_p))
21314 19 : annotate_all_with_location_after (*post_p, post_last_gsi,
21315 : input_location);
21316 :
21317 100637969 : goto out;
21318 : }
21319 :
21320 : #ifdef ENABLE_GIMPLE_CHECKING
21321 362987501 : if (*expr_p)
21322 : {
21323 362987501 : enum tree_code code = TREE_CODE (*expr_p);
21324 : /* These expressions should already be in gimple IR form. */
21325 362987501 : gcc_assert (code != MODIFY_EXPR
21326 : && code != ASM_EXPR
21327 : && code != BIND_EXPR
21328 : && code != CATCH_EXPR
21329 : && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
21330 : && code != EH_FILTER_EXPR
21331 : && code != GOTO_EXPR
21332 : && code != LABEL_EXPR
21333 : && code != LOOP_EXPR
21334 : && code != SWITCH_EXPR
21335 : && code != TRY_FINALLY_EXPR
21336 : && code != EH_ELSE_EXPR
21337 : && code != OACC_PARALLEL
21338 : && code != OACC_KERNELS
21339 : && code != OACC_SERIAL
21340 : && code != OACC_DATA
21341 : && code != OACC_HOST_DATA
21342 : && code != OACC_DECLARE
21343 : && code != OACC_UPDATE
21344 : && code != OACC_ENTER_DATA
21345 : && code != OACC_EXIT_DATA
21346 : && code != OACC_CACHE
21347 : && code != OMP_CRITICAL
21348 : && code != OMP_FOR
21349 : && code != OACC_LOOP
21350 : && code != OMP_MASTER
21351 : && code != OMP_MASKED
21352 : && code != OMP_TASKGROUP
21353 : && code != OMP_ORDERED
21354 : && code != OMP_PARALLEL
21355 : && code != OMP_SCAN
21356 : && code != OMP_SECTIONS
21357 : && code != OMP_SECTION
21358 : && code != OMP_STRUCTURED_BLOCK
21359 : && code != OMP_SINGLE
21360 : && code != OMP_SCOPE
21361 : && code != OMP_DISPATCH);
21362 : }
21363 : #endif
21364 :
21365 : /* Otherwise we're gimplifying a subexpression, so the resulting
21366 : value is interesting. If it's a valid operand that matches
21367 : GIMPLE_TEST_F, we're done. Unless we are handling some
21368 : post-effects internally; if that's the case, we need to copy into
21369 : a temporary before adding the post-effects to POST_P. */
21370 362987501 : if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
21371 337083809 : goto out;
21372 :
21373 : /* Otherwise, we need to create a new temporary for the gimplified
21374 : expression. */
21375 :
21376 : /* We can't return an lvalue if we have an internal postqueue. The
21377 : object the lvalue refers to would (probably) be modified by the
21378 : postqueue; we need to copy the value out first, which means an
21379 : rvalue. */
21380 25903692 : if ((fallback & fb_lvalue)
21381 576573 : && gimple_seq_empty_p (internal_post)
21382 26480265 : && is_gimple_addressable (*expr_p))
21383 : {
21384 : /* An lvalue will do. Take the address of the expression, store it
21385 : in a temporary, and replace the expression with an INDIRECT_REF of
21386 : that temporary. */
21387 15 : tree ref_alias_type = reference_alias_ptr_type (*expr_p);
21388 15 : unsigned int ref_align = get_object_alignment (*expr_p);
21389 15 : tree ref_type = TREE_TYPE (*expr_p);
21390 15 : tmp = build_fold_addr_expr_loc (input_location, *expr_p);
21391 15 : gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
21392 15 : if (TYPE_ALIGN (ref_type) != ref_align)
21393 1 : ref_type = build_aligned_type (ref_type, ref_align);
21394 15 : *expr_p = build2 (MEM_REF, ref_type,
21395 : tmp, build_zero_cst (ref_alias_type));
21396 : }
21397 25903677 : else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
21398 : {
21399 : /* An rvalue will do. Assign the gimplified expression into a
21400 : new temporary TMP and replace the original expression with
21401 : TMP. First, make sure that the expression has a type so that
21402 : it can be assigned into a temporary. */
21403 25903669 : gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
21404 25903669 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
21405 : }
21406 : else
21407 : {
21408 : #ifdef ENABLE_GIMPLE_CHECKING
21409 8 : if (!(fallback & fb_mayfail))
21410 : {
21411 0 : fprintf (stderr, "gimplification failed:\n");
21412 0 : print_generic_expr (stderr, *expr_p);
21413 0 : debug_tree (*expr_p);
21414 0 : internal_error ("gimplification failed");
21415 : }
21416 : #endif
21417 8 : gcc_assert (fallback & fb_mayfail);
21418 :
21419 : /* If this is an asm statement, and the user asked for the
21420 : impossible, don't die. Fail and let gimplify_asm_expr
21421 : issue an error. */
21422 8 : ret = GS_ERROR;
21423 8 : goto out;
21424 : }
21425 :
21426 : /* Make sure the temporary matches our predicate. */
21427 25903684 : gcc_assert ((*gimple_test_f) (*expr_p));
21428 :
21429 25903684 : if (!gimple_seq_empty_p (internal_post))
21430 : {
21431 0 : annotate_all_with_location (internal_post, input_location);
21432 0 : gimplify_seq_add_seq (pre_p, internal_post);
21433 : }
21434 :
21435 25903684 : out:
21436 463630676 : input_location = saved_location;
21437 463630676 : return ret;
21438 : }
21439 :
21440 : /* Like gimplify_expr but make sure the gimplified result is not itself
21441 : a SSA name (but a decl if it were). Temporaries required by
21442 : evaluating *EXPR_P may be still SSA names. */
21443 :
21444 : static enum gimplify_status
21445 33541022 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
21446 : bool (*gimple_test_f) (tree), fallback_t fallback,
21447 : bool allow_ssa)
21448 : {
21449 33541022 : enum gimplify_status ret = gimplify_expr (expr_p, pre_p, post_p,
21450 : gimple_test_f, fallback);
21451 33541022 : if (! allow_ssa
21452 266259 : && TREE_CODE (*expr_p) == SSA_NAME)
21453 68670 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false);
21454 33541022 : return ret;
21455 : }
21456 :
21457 : /* Look through TYPE for variable-sized objects and gimplify each such
21458 : size that we find. Add to LIST_P any statements generated. */
21459 :
21460 : void
21461 8149295 : gimplify_type_sizes (tree type, gimple_seq *list_p)
21462 : {
21463 8149295 : if (type == NULL || type == error_mark_node)
21464 : return;
21465 :
21466 8149049 : const bool ignored_p
21467 8149049 : = TYPE_NAME (type)
21468 4078146 : && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
21469 12001256 : && DECL_IGNORED_P (TYPE_NAME (type));
21470 8149049 : tree t;
21471 :
21472 : /* We first do the main variant, then copy into any other variants. */
21473 8149049 : type = TYPE_MAIN_VARIANT (type);
21474 :
21475 : /* Avoid infinite recursion. */
21476 8149049 : if (TYPE_SIZES_GIMPLIFIED (type))
21477 : return;
21478 :
21479 2424184 : TYPE_SIZES_GIMPLIFIED (type) = 1;
21480 :
21481 2424184 : switch (TREE_CODE (type))
21482 : {
21483 487753 : case INTEGER_TYPE:
21484 487753 : case ENUMERAL_TYPE:
21485 487753 : case BOOLEAN_TYPE:
21486 487753 : case REAL_TYPE:
21487 487753 : case FIXED_POINT_TYPE:
21488 487753 : gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
21489 487753 : gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
21490 :
21491 9786896 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21492 : {
21493 9299143 : TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
21494 9299143 : TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
21495 : }
21496 : break;
21497 :
21498 179780 : case ARRAY_TYPE:
21499 : /* These types may not have declarations, so handle them here. */
21500 179780 : gimplify_type_sizes (TREE_TYPE (type), list_p);
21501 179780 : gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
21502 : /* Ensure VLA bounds aren't removed, for -O0 they should be variables
21503 : with assigned stack slots, for -O1+ -g they should be tracked
21504 : by VTA. */
21505 179780 : if (!ignored_p
21506 179780 : && TYPE_DOMAIN (type)
21507 359335 : && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
21508 : {
21509 179555 : t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
21510 179555 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21511 0 : DECL_IGNORED_P (t) = 0;
21512 179555 : t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
21513 179555 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21514 19011 : DECL_IGNORED_P (t) = 0;
21515 : }
21516 : break;
21517 :
21518 488280 : case RECORD_TYPE:
21519 488280 : case UNION_TYPE:
21520 488280 : case QUAL_UNION_TYPE:
21521 10560543 : for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
21522 10072263 : if (TREE_CODE (field) == FIELD_DECL)
21523 : {
21524 1073277 : gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
21525 : /* Likewise, ensure variable offsets aren't removed. */
21526 1073277 : if (!ignored_p
21527 1073277 : && (t = DECL_FIELD_OFFSET (field))
21528 1073265 : && VAR_P (t)
21529 1073439 : && DECL_ARTIFICIAL (t))
21530 162 : DECL_IGNORED_P (t) = 0;
21531 1073277 : gimplify_one_sizepos (&DECL_SIZE (field), list_p);
21532 1073277 : gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
21533 1073277 : gimplify_type_sizes (TREE_TYPE (field), list_p);
21534 : }
21535 : break;
21536 :
21537 : case POINTER_TYPE:
21538 : case REFERENCE_TYPE:
21539 : /* We used to recurse on the pointed-to type here, which turned out to
21540 : be incorrect because its definition might refer to variables not
21541 : yet initialized at this point if a forward declaration is involved.
21542 :
21543 : It was actually useful for anonymous pointed-to types to ensure
21544 : that the sizes evaluation dominates every possible later use of the
21545 : values. Restricting to such types here would be safe since there
21546 : is no possible forward declaration around, but would introduce an
21547 : undesirable middle-end semantic to anonymity. We then defer to
21548 : front-ends the responsibility of ensuring that the sizes are
21549 : evaluated both early and late enough, e.g. by attaching artificial
21550 : type declarations to the tree. */
21551 : break;
21552 :
21553 : default:
21554 : break;
21555 : }
21556 :
21557 2424184 : gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
21558 2424184 : gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
21559 :
21560 16089280 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21561 : {
21562 13665096 : TYPE_SIZE (t) = TYPE_SIZE (type);
21563 13665096 : TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
21564 13665096 : TYPE_SIZES_GIMPLIFIED (t) = 1;
21565 : }
21566 : }
21567 :
21568 : /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
21569 : a size or position, has had all of its SAVE_EXPRs evaluated.
21570 : We add any required statements to *STMT_P. */
21571 :
21572 : void
21573 9061823 : gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
21574 : {
21575 9061823 : tree expr = *expr_p;
21576 :
21577 : /* We don't do anything if the value isn't there, is constant, or contains
21578 : A PLACEHOLDER_EXPR. We also don't want to do anything if it's already
21579 : a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
21580 : will want to replace it with a new variable, but that will cause problems
21581 : if this type is from outside the function. It's OK to have that here. */
21582 9061823 : if (expr == NULL_TREE
21583 9065708 : || is_gimple_constant (expr)
21584 80935 : || VAR_P (expr)
21585 9138873 : || CONTAINS_PLACEHOLDER_P (expr))
21586 8984773 : return;
21587 :
21588 77050 : *expr_p = unshare_expr (expr);
21589 :
21590 : /* SSA names in decl/type fields are a bad idea - they'll get reclaimed
21591 : if the def vanishes. */
21592 77050 : gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false);
21593 :
21594 : /* If expr wasn't already is_gimple_sizepos or is_gimple_constant from the
21595 : FE, ensure that it is a VAR_DECL, otherwise we might handle some decls
21596 : as gimplify_vla_decl even when they would have all sizes INTEGER_CSTs. */
21597 77050 : if (is_gimple_constant (*expr_p))
21598 548 : *expr_p = get_initialized_tmp_var (*expr_p, stmt_p, NULL, false);
21599 : }
21600 :
21601 : /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
21602 : containing the sequence of corresponding GIMPLE statements. If DO_PARMS
21603 : is true, also gimplify the parameters. */
21604 :
21605 : gbind *
21606 2900892 : gimplify_body (tree fndecl, bool do_parms)
21607 : {
21608 2900892 : location_t saved_location = input_location;
21609 2900892 : gimple_seq parm_stmts, parm_cleanup = NULL, seq;
21610 2900892 : gimple *outer_stmt;
21611 2900892 : gbind *outer_bind;
21612 :
21613 2900892 : timevar_push (TV_TREE_GIMPLIFY);
21614 :
21615 2900892 : init_tree_ssa (cfun);
21616 :
21617 : /* Initialize for optimize_insn_for_s{ize,peed}_p possibly called during
21618 : gimplification. */
21619 2900892 : default_rtl_profile ();
21620 :
21621 2900892 : gcc_assert (gimplify_ctxp == NULL);
21622 2900892 : push_gimplify_context (true);
21623 :
21624 2900892 : if (flag_openacc || flag_openmp)
21625 : {
21626 54623 : gcc_assert (gimplify_omp_ctxp == NULL);
21627 54623 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)))
21628 9729 : gimplify_omp_ctxp = new_omp_context (ORT_IMPLICIT_TARGET);
21629 : }
21630 :
21631 : /* Unshare most shared trees in the body and in that of any nested functions.
21632 : It would seem we don't have to do this for nested functions because
21633 : they are supposed to be output and then the outer function gimplified
21634 : first, but the g++ front end doesn't always do it that way. */
21635 2900892 : unshare_body (fndecl);
21636 2900892 : unvisit_body (fndecl);
21637 :
21638 : /* Make sure input_location isn't set to something weird. */
21639 2900892 : input_location = DECL_SOURCE_LOCATION (fndecl);
21640 :
21641 : /* Resolve callee-copies. This has to be done before processing
21642 : the body so that DECL_VALUE_EXPR gets processed correctly. */
21643 2900892 : parm_stmts = do_parms ? gimplify_parameters (&parm_cleanup) : NULL;
21644 :
21645 : /* Gimplify the function's body. */
21646 2900892 : seq = NULL;
21647 2900892 : gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
21648 2900892 : outer_stmt = gimple_seq_first_nondebug_stmt (seq);
21649 2900892 : if (!outer_stmt)
21650 : {
21651 26066 : outer_stmt = gimple_build_nop ();
21652 26066 : gimplify_seq_add_stmt (&seq, outer_stmt);
21653 : }
21654 :
21655 : /* The body must contain exactly one statement, a GIMPLE_BIND. If this is
21656 : not the case, wrap everything in a GIMPLE_BIND to make it so. */
21657 2900892 : if (gimple_code (outer_stmt) == GIMPLE_BIND
21658 2900892 : && (gimple_seq_first_nondebug_stmt (seq)
21659 1678522 : == gimple_seq_last_nondebug_stmt (seq)))
21660 : {
21661 1614827 : outer_bind = as_a <gbind *> (outer_stmt);
21662 1614827 : if (gimple_seq_first_stmt (seq) != outer_stmt
21663 1614827 : || gimple_seq_last_stmt (seq) != outer_stmt)
21664 : {
21665 : /* If there are debug stmts before or after outer_stmt, move them
21666 : inside of outer_bind body. */
21667 1 : gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq);
21668 1 : gimple_seq second_seq = NULL;
21669 1 : if (gimple_seq_first_stmt (seq) != outer_stmt
21670 2 : && gimple_seq_last_stmt (seq) != outer_stmt)
21671 : {
21672 0 : second_seq = gsi_split_seq_after (gsi);
21673 0 : gsi_remove (&gsi, false);
21674 : }
21675 1 : else if (gimple_seq_first_stmt (seq) != outer_stmt)
21676 1 : gsi_remove (&gsi, false);
21677 : else
21678 : {
21679 0 : gsi_remove (&gsi, false);
21680 0 : second_seq = seq;
21681 0 : seq = NULL;
21682 : }
21683 1 : gimple_seq_add_seq_without_update (&seq,
21684 : gimple_bind_body (outer_bind));
21685 1 : gimple_seq_add_seq_without_update (&seq, second_seq);
21686 1 : gimple_bind_set_body (outer_bind, seq);
21687 : }
21688 : }
21689 : else
21690 1286065 : outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
21691 :
21692 2900892 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
21693 :
21694 : /* If we had callee-copies statements, insert them at the beginning
21695 : of the function and clear DECL_HAS_VALUE_EXPR_P on the parameters. */
21696 2900892 : if (!gimple_seq_empty_p (parm_stmts))
21697 : {
21698 41 : tree parm;
21699 :
21700 41 : gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
21701 41 : if (parm_cleanup)
21702 : {
21703 0 : gtry *g = gimple_build_try (parm_stmts, parm_cleanup,
21704 : GIMPLE_TRY_FINALLY);
21705 0 : parm_stmts = NULL;
21706 0 : gimple_seq_add_stmt (&parm_stmts, g);
21707 : }
21708 41 : gimple_bind_set_body (outer_bind, parm_stmts);
21709 :
21710 41 : for (parm = DECL_ARGUMENTS (current_function_decl);
21711 101 : parm; parm = DECL_CHAIN (parm))
21712 60 : if (DECL_HAS_VALUE_EXPR_P (parm))
21713 : {
21714 0 : DECL_HAS_VALUE_EXPR_P (parm) = 0;
21715 0 : DECL_IGNORED_P (parm) = 0;
21716 : }
21717 : }
21718 :
21719 2900892 : if ((flag_openacc || flag_openmp || flag_openmp_simd)
21720 56879 : && gimplify_omp_ctxp)
21721 : {
21722 9782 : delete_omp_context (gimplify_omp_ctxp);
21723 9782 : gimplify_omp_ctxp = NULL;
21724 : }
21725 :
21726 2900892 : pop_gimplify_context (outer_bind);
21727 2900892 : gcc_assert (gimplify_ctxp == NULL);
21728 :
21729 2900892 : if (flag_checking && !seen_error ())
21730 2851923 : verify_gimple_in_seq (gimple_bind_body (outer_bind));
21731 :
21732 2900892 : timevar_pop (TV_TREE_GIMPLIFY);
21733 2900892 : input_location = saved_location;
21734 :
21735 2900892 : return outer_bind;
21736 : }
21737 :
21738 : typedef char *char_p; /* For DEF_VEC_P. */
21739 :
21740 : /* Return whether we should exclude FNDECL from instrumentation. */
21741 :
21742 : static bool
21743 43 : flag_instrument_functions_exclude_p (tree fndecl)
21744 : {
21745 43 : vec<char_p> *v;
21746 :
21747 43 : v = (vec<char_p> *) flag_instrument_functions_exclude_functions;
21748 44 : if (v && v->length () > 0)
21749 : {
21750 1 : const char *name;
21751 1 : int i;
21752 1 : char *s;
21753 :
21754 1 : name = lang_hooks.decl_printable_name (fndecl, 1);
21755 2 : FOR_EACH_VEC_ELT (*v, i, s)
21756 1 : if (strstr (name, s) != NULL)
21757 2 : return true;
21758 : }
21759 :
21760 42 : v = (vec<char_p> *) flag_instrument_functions_exclude_files;
21761 43 : if (v && v->length () > 0)
21762 : {
21763 1 : const char *name;
21764 1 : int i;
21765 1 : char *s;
21766 :
21767 1 : name = DECL_SOURCE_FILE (fndecl);
21768 1 : FOR_EACH_VEC_ELT (*v, i, s)
21769 1 : if (strstr (name, s) != NULL)
21770 2 : return true;
21771 : }
21772 :
21773 : return false;
21774 : }
21775 :
21776 : /* Build a call to the instrumentation function FNCODE and add it to SEQ.
21777 : If COND_VAR is not NULL, it is a boolean variable guarding the call to
21778 : the instrumentation function. IF STMT is not NULL, it is a statement
21779 : to be executed just before the call to the instrumentation function. */
21780 :
21781 : static void
21782 82 : build_instrumentation_call (gimple_seq *seq, enum built_in_function fncode,
21783 : tree cond_var, gimple *stmt)
21784 : {
21785 : /* The instrumentation hooks aren't going to call the instrumented
21786 : function and the address they receive is expected to be matchable
21787 : against symbol addresses. Make sure we don't create a trampoline,
21788 : in case the current function is nested. */
21789 82 : tree this_fn_addr = build_fold_addr_expr (current_function_decl);
21790 82 : TREE_NO_TRAMPOLINE (this_fn_addr) = 1;
21791 :
21792 82 : tree label_true, label_false;
21793 82 : if (cond_var)
21794 : {
21795 20 : label_true = create_artificial_label (UNKNOWN_LOCATION);
21796 20 : label_false = create_artificial_label (UNKNOWN_LOCATION);
21797 20 : gcond *cond = gimple_build_cond (EQ_EXPR, cond_var, boolean_false_node,
21798 : label_true, label_false);
21799 20 : gimplify_seq_add_stmt (seq, cond);
21800 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_true));
21801 20 : gimplify_seq_add_stmt (seq, gimple_build_predict (PRED_COLD_LABEL,
21802 : NOT_TAKEN));
21803 : }
21804 :
21805 82 : if (stmt)
21806 10 : gimplify_seq_add_stmt (seq, stmt);
21807 :
21808 82 : tree x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
21809 82 : gcall *call = gimple_build_call (x, 1, integer_zero_node);
21810 82 : tree tmp_var = create_tmp_var (ptr_type_node, "return_addr");
21811 82 : gimple_call_set_lhs (call, tmp_var);
21812 82 : gimplify_seq_add_stmt (seq, call);
21813 82 : x = builtin_decl_implicit (fncode);
21814 82 : call = gimple_build_call (x, 2, this_fn_addr, tmp_var);
21815 82 : gimplify_seq_add_stmt (seq, call);
21816 :
21817 82 : if (cond_var)
21818 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_false));
21819 82 : }
21820 :
21821 : /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
21822 : node for the function we want to gimplify.
21823 :
21824 : Return the sequence of GIMPLE statements corresponding to the body
21825 : of FNDECL. */
21826 :
21827 : void
21828 2900388 : gimplify_function_tree (tree fndecl)
21829 : {
21830 2900388 : gimple_seq seq;
21831 2900388 : gbind *bind;
21832 :
21833 2900388 : gcc_assert (!gimple_body (fndecl));
21834 :
21835 2900388 : if (DECL_STRUCT_FUNCTION (fndecl))
21836 2896837 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
21837 : else
21838 3551 : push_struct_function (fndecl);
21839 :
21840 2900388 : reset_cond_uid ();
21841 2900388 : if (cond_uids)
21842 : {
21843 65 : delete cond_uids;
21844 65 : cond_uids = NULL;
21845 : }
21846 :
21847 : /* Tentatively set PROP_gimple_lva here, and reset it in gimplify_va_arg_expr
21848 : if necessary. */
21849 2900388 : cfun->curr_properties |= PROP_gimple_lva;
21850 :
21851 2900388 : if (asan_sanitize_use_after_scope ())
21852 8380 : asan_poisoned_variables = new hash_set<tree> ();
21853 2900388 : if (flag_openmp)
21854 47000 : omp_resolved_variant_calls = new hash_set<tree> ();
21855 :
21856 2900388 : bind = gimplify_body (fndecl, true);
21857 :
21858 2900388 : if (omp_resolved_variant_calls)
21859 : {
21860 47000 : delete omp_resolved_variant_calls;
21861 47000 : omp_resolved_variant_calls = NULL;
21862 : }
21863 2900388 : if (asan_poisoned_variables)
21864 : {
21865 8380 : delete asan_poisoned_variables;
21866 8380 : asan_poisoned_variables = NULL;
21867 : }
21868 :
21869 : /* The tree body of the function is no longer needed, replace it
21870 : with the new GIMPLE body. */
21871 2900388 : seq = NULL;
21872 2900388 : gimple_seq_add_stmt (&seq, bind);
21873 2900388 : gimple_set_body (fndecl, seq);
21874 :
21875 : /* If we're instrumenting function entry/exit, then prepend the call to
21876 : the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
21877 : catch the exit hook. */
21878 : /* ??? Add some way to ignore exceptions for this TFE. */
21879 2900388 : if (flag_instrument_function_entry_exit
21880 97 : && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
21881 : /* Do not instrument extern inline functions. */
21882 44 : && !(DECL_DECLARED_INLINE_P (fndecl)
21883 6 : && DECL_EXTERNAL (fndecl)
21884 1 : && DECL_DISREGARD_INLINE_LIMITS (fndecl))
21885 2900431 : && !flag_instrument_functions_exclude_p (fndecl))
21886 : {
21887 41 : gimple_seq body = NULL, cleanup = NULL;
21888 41 : gassign *assign;
21889 41 : tree cond_var;
21890 :
21891 : /* If -finstrument-functions-once is specified, generate:
21892 :
21893 : static volatile bool C.0 = false;
21894 : bool tmp_called;
21895 :
21896 : tmp_called = C.0;
21897 : if (!tmp_called)
21898 : {
21899 : C.0 = true;
21900 : [call profiling enter function]
21901 : }
21902 :
21903 : without specific protection for data races. */
21904 41 : if (flag_instrument_function_entry_exit > 1)
21905 : {
21906 10 : tree first_var
21907 10 : = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
21908 : VAR_DECL,
21909 : create_tmp_var_name ("C"),
21910 : boolean_type_node);
21911 10 : DECL_ARTIFICIAL (first_var) = 1;
21912 10 : DECL_IGNORED_P (first_var) = 1;
21913 10 : TREE_STATIC (first_var) = 1;
21914 10 : TREE_THIS_VOLATILE (first_var) = 1;
21915 10 : TREE_USED (first_var) = 1;
21916 10 : DECL_INITIAL (first_var) = boolean_false_node;
21917 10 : varpool_node::add (first_var);
21918 :
21919 10 : cond_var = create_tmp_var (boolean_type_node, "tmp_called");
21920 10 : assign = gimple_build_assign (cond_var, first_var);
21921 10 : gimplify_seq_add_stmt (&body, assign);
21922 :
21923 10 : assign = gimple_build_assign (first_var, boolean_true_node);
21924 : }
21925 :
21926 : else
21927 : {
21928 : cond_var = NULL_TREE;
21929 : assign = NULL;
21930 : }
21931 :
21932 41 : build_instrumentation_call (&body, BUILT_IN_PROFILE_FUNC_ENTER,
21933 : cond_var, assign);
21934 :
21935 : /* If -finstrument-functions-once is specified, generate:
21936 :
21937 : if (!tmp_called)
21938 : [call profiling exit function]
21939 :
21940 : without specific protection for data races. */
21941 41 : build_instrumentation_call (&cleanup, BUILT_IN_PROFILE_FUNC_EXIT,
21942 : cond_var, NULL);
21943 :
21944 41 : gimple *tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
21945 41 : gimplify_seq_add_stmt (&body, tf);
21946 41 : gbind *new_bind = gimple_build_bind (NULL, body, NULL);
21947 :
21948 : /* Replace the current function body with the body
21949 : wrapped in the try/finally TF. */
21950 41 : seq = NULL;
21951 41 : gimple_seq_add_stmt (&seq, new_bind);
21952 41 : gimple_set_body (fndecl, seq);
21953 41 : bind = new_bind;
21954 : }
21955 :
21956 2900388 : if (sanitize_flags_p (SANITIZE_THREAD)
21957 2900388 : && param_tsan_instrument_func_entry_exit)
21958 : {
21959 971 : gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
21960 971 : gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
21961 971 : gbind *new_bind = gimple_build_bind (NULL, tf, NULL);
21962 : /* Replace the current function body with the body
21963 : wrapped in the try/finally TF. */
21964 971 : seq = NULL;
21965 971 : gimple_seq_add_stmt (&seq, new_bind);
21966 971 : gimple_set_body (fndecl, seq);
21967 : }
21968 :
21969 2900388 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
21970 2900388 : cfun->curr_properties |= PROP_gimple_any;
21971 :
21972 2900388 : pop_cfun ();
21973 :
21974 2900388 : dump_function (TDI_gimple, fndecl);
21975 2900388 : }
21976 :
21977 : /* Return a dummy expression of type TYPE in order to keep going after an
21978 : error. */
21979 :
21980 : static tree
21981 30 : dummy_object (tree type)
21982 : {
21983 30 : tree t = build_int_cst (build_pointer_type (type), 0);
21984 30 : return build2 (MEM_REF, type, t, t);
21985 : }
21986 :
21987 : /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
21988 : builtin function, but a very special sort of operator. */
21989 :
21990 : enum gimplify_status
21991 50967 : gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
21992 : gimple_seq *post_p ATTRIBUTE_UNUSED)
21993 : {
21994 50967 : tree promoted_type, have_va_type;
21995 50967 : tree valist = TREE_OPERAND (*expr_p, 0);
21996 50967 : tree type = TREE_TYPE (*expr_p);
21997 50967 : tree t, tag, aptag;
21998 50967 : location_t loc = EXPR_LOCATION (*expr_p);
21999 :
22000 : /* Verify that valist is of the proper type. */
22001 50967 : have_va_type = TREE_TYPE (valist);
22002 50967 : if (have_va_type == error_mark_node)
22003 : return GS_ERROR;
22004 50948 : have_va_type = targetm.canonical_va_list_type (have_va_type);
22005 50948 : if (have_va_type == NULL_TREE
22006 50948 : && POINTER_TYPE_P (TREE_TYPE (valist)))
22007 : /* Handle 'Case 1: Not an array type' from c-common.cc/build_va_arg. */
22008 258 : have_va_type
22009 258 : = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
22010 50948 : gcc_assert (have_va_type != NULL_TREE);
22011 :
22012 : /* Generate a diagnostic for requesting data of a type that cannot
22013 : be passed through `...' due to type promotion at the call site. */
22014 50948 : if ((promoted_type = lang_hooks.types.type_promotes_to (type))
22015 : != type)
22016 : {
22017 30 : static bool gave_help;
22018 30 : bool warned;
22019 : /* Use the expansion point to handle cases such as passing bool (defined
22020 : in a system header) through `...'. */
22021 30 : location_t xloc
22022 30 : = expansion_point_location_if_in_system_header (loc);
22023 :
22024 : /* Unfortunately, this is merely undefined, rather than a constraint
22025 : violation, so we cannot make this an error. If this call is never
22026 : executed, the program is still strictly conforming. */
22027 30 : auto_diagnostic_group d;
22028 30 : warned = warning_at (xloc, 0,
22029 : "%qT is promoted to %qT when passed through %<...%>",
22030 : type, promoted_type);
22031 30 : if (!gave_help && warned)
22032 : {
22033 15 : gave_help = true;
22034 15 : inform (xloc, "(so you should pass %qT not %qT to %<va_arg%>)",
22035 : promoted_type, type);
22036 : }
22037 :
22038 : /* We can, however, treat "undefined" any way we please.
22039 : Call abort to encourage the user to fix the program. */
22040 23 : if (warned)
22041 23 : inform (xloc, "if this code is reached, the program will abort");
22042 : /* Before the abort, allow the evaluation of the va_list
22043 : expression to exit or longjmp. */
22044 30 : gimplify_and_add (valist, pre_p);
22045 60 : t = build_call_expr_loc (loc,
22046 : builtin_decl_implicit (BUILT_IN_TRAP), 0);
22047 30 : gimplify_and_add (t, pre_p);
22048 :
22049 : /* This is dead code, but go ahead and finish so that the
22050 : mode of the result comes out right. */
22051 30 : *expr_p = dummy_object (type);
22052 30 : return GS_ALL_DONE;
22053 30 : }
22054 :
22055 50918 : tag = build_int_cst (build_pointer_type (type), 0);
22056 50918 : aptag = build_int_cst (TREE_TYPE (valist), 0);
22057 :
22058 50918 : *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3,
22059 : valist, tag, aptag);
22060 :
22061 : /* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
22062 : needs to be expanded. */
22063 50918 : cfun->curr_properties &= ~PROP_gimple_lva;
22064 :
22065 50918 : return GS_OK;
22066 : }
22067 :
22068 : /* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P.
22069 :
22070 : DST/SRC are the destination and source respectively. You can pass
22071 : ungimplified trees in DST or SRC, in which case they will be
22072 : converted to a gimple operand if necessary.
22073 :
22074 : This function returns the newly created GIMPLE_ASSIGN tuple. */
22075 :
22076 : gimple *
22077 872037 : gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
22078 : {
22079 872037 : tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
22080 872037 : gimplify_and_add (t, seq_p);
22081 872037 : ggc_free (t);
22082 872037 : return gimple_seq_last_stmt (*seq_p);
22083 : }
22084 :
22085 : inline hashval_t
22086 1580928 : gimplify_hasher::hash (const elt_t *p)
22087 : {
22088 1580928 : tree t = p->val;
22089 1580928 : return iterative_hash_expr (t, 0);
22090 : }
22091 :
22092 : inline bool
22093 594105 : gimplify_hasher::equal (const elt_t *p1, const elt_t *p2)
22094 : {
22095 594105 : tree t1 = p1->val;
22096 594105 : tree t2 = p2->val;
22097 594105 : enum tree_code code = TREE_CODE (t1);
22098 :
22099 594105 : if (TREE_CODE (t2) != code
22100 594105 : || TREE_TYPE (t1) != TREE_TYPE (t2))
22101 : return false;
22102 :
22103 363758 : if (!operand_equal_p (t1, t2, 0))
22104 : return false;
22105 :
22106 : return true;
22107 : }
|