Line data Source code
1 : /* Tree lowering pass. This pass converts the GENERIC functions-as-trees
2 : tree representation into the GIMPLE form.
3 : Copyright (C) 2002-2026 Free Software Foundation, Inc.
4 : Major work done by Sebastian Pop <s.pop@laposte.net>,
5 : Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
6 :
7 : This file is part of GCC.
8 :
9 : GCC is free software; you can redistribute it and/or modify it under
10 : the terms of the GNU General Public License as published by the Free
11 : Software Foundation; either version 3, or (at your option) any later
12 : version.
13 :
14 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 : for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GCC; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "config.h"
24 : #include "system.h"
25 : #include "coretypes.h"
26 : #include "backend.h"
27 : #include "target.h"
28 : #include "rtl.h"
29 : #include "tree.h"
30 : #include "memmodel.h"
31 : #include "tm_p.h"
32 : #include "gimple.h"
33 : #include "gimple-predict.h"
34 : #include "tree-pass.h" /* FIXME: only for PROP_gimple_any */
35 : #include "ssa.h"
36 : #include "cgraph.h"
37 : #include "tree-pretty-print.h"
38 : #include "diagnostic-core.h"
39 : #include "diagnostic.h" /* For errorcount. */
40 : #include "alias.h"
41 : #include "fold-const.h"
42 : #include "calls.h"
43 : #include "varasm.h"
44 : #include "stmt.h"
45 : #include "expr.h"
46 : #include "gimple-iterator.h"
47 : #include "gimple-fold.h"
48 : #include "tree-eh.h"
49 : #include "gimplify.h"
50 : #include "stor-layout.h"
51 : #include "print-tree.h"
52 : #include "tree-iterator.h"
53 : #include "tree-inline.h"
54 : #include "langhooks.h"
55 : #include "tree-cfg.h"
56 : #include "tree-ssa.h"
57 : #include "tree-hash-traits.h"
58 : #include "omp-general.h"
59 : #include "omp-low.h"
60 : #include "gimple-low.h"
61 : #include "gomp-constants.h"
62 : #include "splay-tree.h"
63 : #include "gimple-walk.h"
64 : #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
65 : #include "builtins.h"
66 : #include "stringpool.h"
67 : #include "attribs.h"
68 : #include "asan.h"
69 : #include "dbgcnt.h"
70 : #include "omp-offload.h"
71 : #include "context.h"
72 : #include "tree-nested.h"
73 : #include "gcc-urlifier.h"
74 : #include "insn-config.h"
75 : #include "recog.h"
76 : #include "output.h"
77 : #include "gimplify_reg_info.h"
78 : #include "tree-ssa-loop-niter.h" /* For simplify_replace_tree. */
79 :
80 : /* Identifier for a basic condition, mapping it to other basic conditions of
81 : its Boolean expression. Basic conditions given the same uid (in the same
82 : function) are parts of the same ANDIF/ORIF expression. Used for condition
83 : coverage. */
84 : static unsigned nextconduid = 1;
85 :
86 : /* Annotated gconds so that basic conditions in the same expression map to
87 : the same uid. This is used for condition coverage. */
88 : static hash_map <tree, unsigned> *cond_uids;
89 :
90 : /* Get a fresh identifier for a new condition expression. This is used for
91 : condition coverage. */
92 : static unsigned
93 5855803 : next_cond_uid ()
94 : {
95 5855803 : return nextconduid++;
96 : }
97 :
98 : /* Reset the condition uid to the value it should have when compiling a new
99 : function. 0 is already the default/untouched value, so start at non-zero.
100 : A valid and set id should always be > 0. This is used for condition
101 : coverage. */
102 : static void
103 3008701 : reset_cond_uid ()
104 : {
105 3008701 : nextconduid = 1;
106 0 : }
107 :
108 : /* Associate the condition STMT with the discriminator UID. STMTs that are
109 : broken down with ANDIF/ORIF from the same Boolean expression should be given
110 : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
111 : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
112 : for condition coverage. */
113 : static void
114 1217149 : tree_associate_condition_with_expr (tree stmt, unsigned uid)
115 : {
116 1217149 : if (!condition_coverage_flag)
117 : return;
118 :
119 527 : if (!cond_uids)
120 65 : cond_uids = new hash_map <tree, unsigned> ();
121 :
122 527 : cond_uids->put (stmt, uid);
123 : }
124 :
125 : /* Hash set of poisoned variables in a bind expr. */
126 : static hash_set<tree> *asan_poisoned_variables = NULL;
127 :
128 : /* Hash set of already-resolved calls to OpenMP "declare variant"
129 : functions. A call can resolve to the original function and
130 : we don't want to repeat the resolution multiple times. */
131 : static hash_set<tree> *omp_resolved_variant_calls = NULL;
132 :
133 : enum gimplify_omp_var_data
134 : {
135 : GOVD_SEEN = 0x000001,
136 : GOVD_EXPLICIT = 0x000002,
137 : GOVD_SHARED = 0x000004,
138 : GOVD_PRIVATE = 0x000008,
139 : GOVD_FIRSTPRIVATE = 0x000010,
140 : GOVD_LASTPRIVATE = 0x000020,
141 : GOVD_REDUCTION = 0x000040,
142 : GOVD_LOCAL = 0x00080,
143 : GOVD_MAP = 0x000100,
144 : GOVD_DEBUG_PRIVATE = 0x000200,
145 : GOVD_PRIVATE_OUTER_REF = 0x000400,
146 : GOVD_LINEAR = 0x000800,
147 : GOVD_ALIGNED = 0x001000,
148 :
149 : /* Flag for GOVD_MAP: don't copy back. */
150 : GOVD_MAP_TO_ONLY = 0x002000,
151 :
152 : /* Flag for GOVD_LINEAR or GOVD_LASTPRIVATE: no outer reference. */
153 : GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 0x004000,
154 :
155 : GOVD_MAP_0LEN_ARRAY = 0x008000,
156 :
157 : /* Flag for GOVD_MAP, if it is always, to or always, tofrom mapping. */
158 : GOVD_MAP_ALWAYS_TO = 0x010000,
159 :
160 : /* Flag for shared vars that are or might be stored to in the region. */
161 : GOVD_WRITTEN = 0x020000,
162 :
163 : /* Flag for GOVD_MAP, if it is a forced mapping. */
164 : GOVD_MAP_FORCE = 0x040000,
165 :
166 : /* Flag for GOVD_MAP: must be present already. */
167 : GOVD_MAP_FORCE_PRESENT = 0x080000,
168 :
169 : /* Flag for GOVD_MAP: only allocate. */
170 : GOVD_MAP_ALLOC_ONLY = 0x100000,
171 :
172 : /* Flag for GOVD_MAP: only copy back. */
173 : GOVD_MAP_FROM_ONLY = 0x200000,
174 :
175 : GOVD_NONTEMPORAL = 0x400000,
176 :
177 : /* Flag for GOVD_LASTPRIVATE: conditional modifier. */
178 : GOVD_LASTPRIVATE_CONDITIONAL = 0x800000,
179 :
180 : GOVD_CONDTEMP = 0x1000000,
181 :
182 : /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */
183 : GOVD_REDUCTION_INSCAN = 0x2000000,
184 :
185 : /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. */
186 : GOVD_FIRSTPRIVATE_IMPLICIT = 0x4000000,
187 :
188 : /* Flag to indicate this an allocator for the uses_allocators clause. */
189 : GOVD_USES_ALLOCATORS_ALLOCATOR = 0x8000000,
190 :
191 : GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
192 : | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
193 : | GOVD_LOCAL)
194 : };
195 :
196 :
197 : enum omp_region_type
198 : {
199 : ORT_WORKSHARE = 0x00,
200 : ORT_TASKGROUP = 0x01,
201 : ORT_DISPATCH = 0x02,
202 : ORT_SIMD = 0x04,
203 :
204 : ORT_PARALLEL = 0x08,
205 : ORT_COMBINED_PARALLEL = ORT_PARALLEL | 1,
206 :
207 : ORT_TASK = 0x10,
208 : ORT_UNTIED_TASK = ORT_TASK | 1,
209 : ORT_TASKLOOP = ORT_TASK | 2,
210 : ORT_UNTIED_TASKLOOP = ORT_UNTIED_TASK | 2,
211 :
212 : ORT_TEAMS = 0x20,
213 : ORT_COMBINED_TEAMS = ORT_TEAMS | 1,
214 : ORT_HOST_TEAMS = ORT_TEAMS | 2,
215 : ORT_COMBINED_HOST_TEAMS = ORT_COMBINED_TEAMS | 2,
216 :
217 : /* Data region. */
218 : ORT_TARGET_DATA = 0x40,
219 :
220 : /* Data region with offloading. */
221 : ORT_TARGET = 0x80,
222 : ORT_COMBINED_TARGET = ORT_TARGET | 1,
223 : ORT_IMPLICIT_TARGET = ORT_TARGET | 2,
224 :
225 : /* OpenACC variants. */
226 : ORT_ACC = 0x100, /* A generic OpenACC region. */
227 : ORT_ACC_DATA = ORT_ACC | ORT_TARGET_DATA, /* Data construct. */
228 : ORT_ACC_PARALLEL = ORT_ACC | ORT_TARGET, /* Parallel construct */
229 : ORT_ACC_KERNELS = ORT_ACC | ORT_TARGET | 2, /* Kernels construct. */
230 : ORT_ACC_SERIAL = ORT_ACC | ORT_TARGET | 4, /* Serial construct. */
231 : ORT_ACC_HOST_DATA = ORT_ACC | ORT_TARGET_DATA | 2, /* Host data. */
232 :
233 : /* Dummy OpenMP region, used to disable expansion of
234 : DECL_VALUE_EXPRs in taskloop pre body. */
235 : ORT_NONE = 0x200
236 : };
237 :
238 : /* Gimplify hashtable helper. */
239 :
240 : struct gimplify_hasher : free_ptr_hash <elt_t>
241 : {
242 : static inline hashval_t hash (const elt_t *);
243 : static inline bool equal (const elt_t *, const elt_t *);
244 : };
245 :
246 : struct gimplify_ctx
247 : {
248 : struct gimplify_ctx *prev_context;
249 :
250 : vec<gbind *> bind_expr_stack;
251 : tree temps;
252 : gimple_seq conditional_cleanups;
253 : tree exit_label;
254 : tree return_temp;
255 :
256 : vec<tree> case_labels;
257 : hash_set<tree> *live_switch_vars;
258 : /* The formal temporary table. Should this be persistent? */
259 : hash_table<gimplify_hasher> *temp_htab;
260 :
261 : int conditions;
262 : unsigned into_ssa : 1;
263 : unsigned allow_rhs_cond_expr : 1;
264 : unsigned in_cleanup_point_expr : 1;
265 : unsigned keep_stack : 1;
266 : unsigned save_stack : 1;
267 : unsigned in_switch_expr : 1;
268 : unsigned in_handler_expr : 1;
269 : };
270 :
271 : enum gimplify_defaultmap_kind
272 : {
273 : GDMK_SCALAR,
274 : GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only. */
275 : GDMK_AGGREGATE,
276 : GDMK_ALLOCATABLE,
277 : GDMK_POINTER
278 : };
279 :
280 : struct gimplify_omp_ctx
281 : {
282 : struct gimplify_omp_ctx *outer_context;
283 : splay_tree variables;
284 : hash_map<omp_name_type<tree>, tree> *implicit_mappers;
285 : hash_set<tree> *privatized_types;
286 : tree clauses;
287 : /* Iteration variables in an OMP_FOR. */
288 : vec<tree> loop_iter_var;
289 : location_t location;
290 : enum omp_clause_default_kind default_kind;
291 : enum omp_region_type region_type;
292 : enum tree_code code;
293 : bool combined_loop;
294 : bool distribute;
295 : bool target_firstprivatize_array_bases;
296 : bool add_safelen1;
297 : bool order_concurrent;
298 : bool has_depend;
299 : bool in_for_exprs;
300 : bool in_call_args;
301 : int defaultmap[5];
302 : };
303 :
304 : static struct gimplify_ctx *gimplify_ctxp;
305 : static struct gimplify_omp_ctx *gimplify_omp_ctxp;
306 : static bool in_omp_construct;
307 :
308 : /* Forward declaration. */
309 : static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
310 : static hash_map<tree, tree> *oacc_declare_returns;
311 : static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
312 : bool (*) (tree), fallback_t, bool);
313 : static void prepare_gimple_addressable (tree *, gimple_seq *);
314 :
315 : /* Shorter alias name for the above function for use in gimplify.cc
316 : only. */
317 :
318 : static inline void
319 94096175 : gimplify_seq_add_stmt (gimple_seq *seq_p, gimple *gs)
320 : {
321 94096175 : gimple_seq_add_stmt_without_update (seq_p, gs);
322 6797908 : }
323 :
324 : /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
325 : NULL, a new sequence is allocated. This function is
326 : similar to gimple_seq_add_seq, but does not scan the operands.
327 : During gimplification, we need to manipulate statement sequences
328 : before the def/use vectors have been constructed. */
329 :
330 : static void
331 9490155 : gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
332 : {
333 9490155 : gimple_stmt_iterator si;
334 :
335 9490155 : if (src == NULL)
336 4083044 : return;
337 :
338 5407111 : si = gsi_last (*dst_p);
339 5407111 : gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
340 : }
341 :
342 :
343 : /* Pointer to a list of allocated gimplify_ctx structs to be used for pushing
344 : and popping gimplify contexts. */
345 :
346 : static struct gimplify_ctx *ctx_pool = NULL;
347 :
348 : /* Return a gimplify context struct from the pool. */
349 :
350 : static inline struct gimplify_ctx *
351 9179184 : ctx_alloc (void)
352 : {
353 9179184 : struct gimplify_ctx * c = ctx_pool;
354 :
355 9179184 : if (c)
356 8910491 : ctx_pool = c->prev_context;
357 : else
358 268693 : c = XNEW (struct gimplify_ctx);
359 :
360 9179184 : memset (c, '\0', sizeof (*c));
361 9179184 : return c;
362 : }
363 :
364 : /* Put gimplify context C back into the pool. */
365 :
366 : static inline void
367 9179180 : ctx_free (struct gimplify_ctx *c)
368 : {
369 9179180 : c->prev_context = ctx_pool;
370 9179180 : ctx_pool = c;
371 : }
372 :
373 : /* Free allocated ctx stack memory. */
374 :
375 : void
376 236140 : free_gimplify_stack (void)
377 : {
378 236140 : struct gimplify_ctx *c;
379 :
380 474882 : while ((c = ctx_pool))
381 : {
382 238742 : ctx_pool = c->prev_context;
383 238742 : free (c);
384 : }
385 236140 : }
386 :
387 :
388 : /* Set up a context for the gimplifier. */
389 :
390 : void
391 9179184 : push_gimplify_context (bool in_ssa, bool rhs_cond_ok)
392 : {
393 9179184 : struct gimplify_ctx *c = ctx_alloc ();
394 :
395 9179184 : c->prev_context = gimplify_ctxp;
396 9179184 : gimplify_ctxp = c;
397 9179184 : gimplify_ctxp->into_ssa = in_ssa;
398 9179184 : gimplify_ctxp->allow_rhs_cond_expr = rhs_cond_ok;
399 9179184 : }
400 :
401 : /* Tear down a context for the gimplifier. If BODY is non-null, then
402 : put the temporaries into the outer BIND_EXPR. Otherwise, put them
403 : in the local_decls.
404 :
405 : BODY is not a sequence, but the first tuple in a sequence. */
406 :
407 : void
408 9179180 : pop_gimplify_context (gimple *body)
409 : {
410 9179180 : struct gimplify_ctx *c = gimplify_ctxp;
411 :
412 9179180 : gcc_assert (c
413 : && (!c->bind_expr_stack.exists ()
414 : || c->bind_expr_stack.is_empty ()));
415 9179180 : c->bind_expr_stack.release ();
416 9179180 : gimplify_ctxp = c->prev_context;
417 :
418 9179180 : if (body)
419 3133093 : declare_vars (c->temps, body, false);
420 : else
421 6046087 : record_vars (c->temps);
422 :
423 9179180 : delete c->temp_htab;
424 9179180 : c->temp_htab = NULL;
425 9179180 : ctx_free (c);
426 9179180 : }
427 :
428 : /* Push a GIMPLE_BIND tuple onto the stack of bindings. */
429 :
430 : static void
431 6033008 : gimple_push_bind_expr (gbind *bind_stmt)
432 : {
433 6033008 : gimplify_ctxp->bind_expr_stack.reserve (8);
434 6033008 : gimplify_ctxp->bind_expr_stack.safe_push (bind_stmt);
435 6033008 : }
436 :
437 : /* Pop the first element off the stack of bindings. */
438 :
439 : static void
440 6033008 : gimple_pop_bind_expr (void)
441 : {
442 0 : gimplify_ctxp->bind_expr_stack.pop ();
443 2283 : }
444 :
445 : /* Return the first element of the stack of bindings. */
446 :
447 : gbind *
448 0 : gimple_current_bind_expr (void)
449 : {
450 0 : return gimplify_ctxp->bind_expr_stack.last ();
451 : }
452 :
453 : /* Return the stack of bindings created during gimplification. */
454 :
455 : vec<gbind *>
456 359 : gimple_bind_expr_stack (void)
457 : {
458 359 : return gimplify_ctxp->bind_expr_stack;
459 : }
460 :
461 : /* Return true iff there is a COND_EXPR between us and the innermost
462 : CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
463 :
464 : static bool
465 2939411 : gimple_conditional_context (void)
466 : {
467 2939411 : return gimplify_ctxp->conditions > 0;
468 : }
469 :
470 : /* Note that we've entered a COND_EXPR. */
471 :
472 : static void
473 5856238 : gimple_push_condition (void)
474 : {
475 : #ifdef ENABLE_GIMPLE_CHECKING
476 5856238 : if (gimplify_ctxp->conditions == 0)
477 3856492 : gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
478 : #endif
479 5856238 : ++(gimplify_ctxp->conditions);
480 5856238 : }
481 :
482 : /* Note that we've left a COND_EXPR. If we're back at unconditional scope
483 : now, add any conditional cleanups we've seen to the prequeue. */
484 :
485 : static void
486 5856238 : gimple_pop_condition (gimple_seq *pre_p)
487 : {
488 5856238 : int conds = --(gimplify_ctxp->conditions);
489 :
490 5856238 : gcc_assert (conds >= 0);
491 5856238 : if (conds == 0)
492 : {
493 3856492 : gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
494 3856492 : gimplify_ctxp->conditional_cleanups = NULL;
495 : }
496 5856238 : }
497 :
498 : /* A stable comparison routine for use with splay trees and DECLs. */
499 :
500 : static int
501 18283290 : splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
502 : {
503 18283290 : tree a = (tree) xa;
504 18283290 : tree b = (tree) xb;
505 :
506 18283290 : return DECL_UID (a) - DECL_UID (b);
507 : }
508 :
509 : /* Create a new omp construct that deals with variable remapping. */
510 :
511 : static struct gimplify_omp_ctx *
512 140282 : new_omp_context (enum omp_region_type region_type)
513 : {
514 140282 : struct gimplify_omp_ctx *c;
515 :
516 140282 : c = XCNEW (struct gimplify_omp_ctx);
517 140282 : c->outer_context = gimplify_omp_ctxp;
518 140282 : c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
519 140282 : c->implicit_mappers = new hash_map<omp_name_type<tree>, tree>;
520 140282 : c->privatized_types = new hash_set<tree>;
521 140282 : c->location = input_location;
522 140282 : c->region_type = region_type;
523 140282 : if ((region_type & ORT_TASK) == 0)
524 134264 : c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
525 : else
526 6018 : c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
527 140282 : c->defaultmap[GDMK_SCALAR] = GOVD_MAP;
528 140282 : c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP;
529 140282 : c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP;
530 140282 : c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP;
531 140282 : c->defaultmap[GDMK_POINTER] = GOVD_MAP;
532 :
533 140282 : return c;
534 : }
535 :
536 : /* Destroy an omp construct that deals with variable remapping. */
537 :
538 : static void
539 139723 : delete_omp_context (struct gimplify_omp_ctx *c)
540 : {
541 139723 : splay_tree_delete (c->variables);
542 279446 : delete c->privatized_types;
543 279446 : delete c->implicit_mappers;
544 139723 : c->loop_iter_var.release ();
545 139723 : XDELETE (c);
546 139723 : }
547 :
548 : static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
549 : static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
550 :
551 : /* Both gimplify the statement T and append it to *SEQ_P. This function
552 : behaves exactly as gimplify_stmt, but you don't have to pass T as a
553 : reference. */
554 :
555 : void
556 38723276 : gimplify_and_add (tree t, gimple_seq *seq_p)
557 : {
558 38723276 : gimplify_stmt (&t, seq_p);
559 38723276 : }
560 :
561 : /* Gimplify statement T into sequence *SEQ_P, and return the first
562 : tuple in the sequence of generated tuples for this statement.
563 : Return NULL if gimplifying T produced no tuples. */
564 :
565 : static gimple *
566 105291 : gimplify_and_return_first (tree t, gimple_seq *seq_p)
567 : {
568 105291 : gimple_stmt_iterator last = gsi_last (*seq_p);
569 :
570 105291 : gimplify_and_add (t, seq_p);
571 :
572 105291 : if (!gsi_end_p (last))
573 : {
574 4844 : gsi_next (&last);
575 4844 : return gsi_stmt (last);
576 : }
577 : else
578 100447 : return gimple_seq_first_stmt (*seq_p);
579 : }
580 :
581 : /* Returns true iff T is a valid RHS for an assignment to an un-renamed
582 : LHS, or for a call argument. */
583 :
584 : static bool
585 237661 : is_gimple_mem_rhs (tree t)
586 : {
587 : /* If we're dealing with a renamable type, either source or dest must be
588 : a renamed variable. */
589 237661 : if (is_gimple_reg_type (TREE_TYPE (t)))
590 234290 : return is_gimple_val (t);
591 : else
592 3371 : return is_gimple_val (t) || is_gimple_lvalue (t);
593 : }
594 :
595 : /* Return true if T is a CALL_EXPR or an expression that can be
596 : assigned to a temporary. Note that this predicate should only be
597 : used during gimplification. See the rationale for this in
598 : gimplify_modify_expr. */
599 :
600 : static bool
601 99282578 : is_gimple_reg_rhs_or_call (tree t)
602 : {
603 72897515 : return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
604 99282578 : || TREE_CODE (t) == CALL_EXPR);
605 : }
606 :
607 : /* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
608 : this predicate should only be used during gimplification. See the
609 : rationale for this in gimplify_modify_expr. */
610 :
611 : static bool
612 14523521 : is_gimple_mem_rhs_or_call (tree t)
613 : {
614 : /* If we're dealing with a renamable type, either source or dest must be
615 : a renamed variable. */
616 14523521 : if (is_gimple_reg_type (TREE_TYPE (t)))
617 11056446 : return is_gimple_val (t);
618 : else
619 3467075 : return (is_gimple_val (t)
620 1750693 : || is_gimple_lvalue (t)
621 1226648 : || (TREE_CODE (t) == CONSTRUCTOR && CONSTRUCTOR_NELTS (t) == 0)
622 4693331 : || TREE_CODE (t) == CALL_EXPR);
623 : }
624 :
625 : /* Create a temporary with a name derived from VAL. Subroutine of
626 : lookup_tmp_var; nobody else should call this function. */
627 :
628 : static inline tree
629 2188846 : create_tmp_from_val (tree val)
630 : {
631 : /* Drop all qualifiers and address-space information from the value type. */
632 2188846 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
633 2188846 : tree var = create_tmp_var (type, get_name (val));
634 2188846 : return var;
635 : }
636 :
637 : /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
638 : an existing expression temporary. If NOT_GIMPLE_REG, mark it as such. */
639 :
640 : static tree
641 2427671 : lookup_tmp_var (tree val, bool is_formal, bool not_gimple_reg)
642 : {
643 2427671 : tree ret;
644 :
645 : /* We cannot mark a formal temporary with DECL_NOT_GIMPLE_REG_P. */
646 2427671 : gcc_assert (!is_formal || !not_gimple_reg);
647 :
648 : /* If not optimizing, never really reuse a temporary. local-alloc
649 : won't allocate any variable that is used in more than one basic
650 : block, which means it will go into memory, causing much extra
651 : work in reload and final and poorer code generation, outweighing
652 : the extra memory allocation here. */
653 2427671 : if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
654 : {
655 1102850 : ret = create_tmp_from_val (val);
656 1102850 : DECL_NOT_GIMPLE_REG_P (ret) = not_gimple_reg;
657 : }
658 : else
659 : {
660 1324821 : elt_t elt, *elt_p;
661 1324821 : elt_t **slot;
662 :
663 1324821 : elt.val = val;
664 1324821 : if (!gimplify_ctxp->temp_htab)
665 417925 : gimplify_ctxp->temp_htab = new hash_table<gimplify_hasher> (1000);
666 1324821 : slot = gimplify_ctxp->temp_htab->find_slot (&elt, INSERT);
667 1324821 : if (*slot == NULL)
668 : {
669 1085996 : elt_p = XNEW (elt_t);
670 1085996 : elt_p->val = val;
671 1085996 : elt_p->temp = ret = create_tmp_from_val (val);
672 1085996 : *slot = elt_p;
673 : }
674 : else
675 : {
676 238825 : elt_p = *slot;
677 238825 : ret = elt_p->temp;
678 : }
679 : }
680 :
681 2427671 : return ret;
682 : }
683 :
684 : /* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
685 :
686 : static tree
687 26923472 : internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
688 : bool is_formal, bool allow_ssa, bool not_gimple_reg)
689 : {
690 26923472 : tree t, mod;
691 :
692 : /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
693 : can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
694 26923472 : gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
695 : fb_rvalue);
696 :
697 26923472 : if (allow_ssa
698 26653940 : && gimplify_ctxp->into_ssa
699 52106811 : && is_gimple_reg_type (TREE_TYPE (val)))
700 : {
701 24495802 : t = make_ssa_name (TYPE_MAIN_VARIANT (TREE_TYPE (val)));
702 24495802 : if (! gimple_in_ssa_p (cfun))
703 : {
704 21052117 : const char *name = get_name (val);
705 21052117 : if (name)
706 6824932 : SET_SSA_NAME_VAR_OR_IDENTIFIER (t, create_tmp_var_name (name));
707 : }
708 : }
709 : else
710 2427670 : t = lookup_tmp_var (val, is_formal, not_gimple_reg);
711 :
712 26923472 : mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
713 :
714 26923472 : SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location));
715 :
716 : /* gimplify_modify_expr might want to reduce this further. */
717 26923472 : gimplify_and_add (mod, pre_p);
718 26923472 : ggc_free (mod);
719 :
720 : /* If we failed to gimplify VAL then we can end up with the temporary
721 : SSA name not having a definition. In this case return a decl. */
722 26923472 : if (TREE_CODE (t) == SSA_NAME && ! SSA_NAME_DEF_STMT (t))
723 1 : return lookup_tmp_var (val, is_formal, not_gimple_reg);
724 :
725 : return t;
726 : }
727 :
728 : /* Return a formal temporary variable initialized with VAL. PRE_P is as
729 : in gimplify_expr. Only use this function if:
730 :
731 : 1) The value of the unfactored expression represented by VAL will not
732 : change between the initialization and use of the temporary, and
733 : 2) The temporary will not be otherwise modified.
734 :
735 : For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
736 : and #2 means it is inappropriate for && temps.
737 :
738 : For other cases, use get_initialized_tmp_var instead. */
739 :
740 : tree
741 26423698 : get_formal_tmp_var (tree val, gimple_seq *pre_p)
742 : {
743 26423698 : return internal_get_tmp_var (val, pre_p, NULL, true, true, false);
744 : }
745 :
746 : /* Return a temporary variable initialized with VAL. PRE_P and POST_P
747 : are as in gimplify_expr. */
748 :
749 : tree
750 487693 : get_initialized_tmp_var (tree val, gimple_seq *pre_p,
751 : gimple_seq *post_p /* = NULL */,
752 : bool allow_ssa /* = true */)
753 : {
754 487693 : return internal_get_tmp_var (val, pre_p, post_p, false, allow_ssa, false);
755 : }
756 :
757 : /* Declare all the variables in VARS in SCOPE. If DEBUG_INFO is true,
758 : generate debug info for them; otherwise don't. */
759 :
760 : void
761 3141132 : declare_vars (tree vars, gimple *gs, bool debug_info)
762 : {
763 3141132 : tree last = vars;
764 3141132 : if (last)
765 : {
766 1970585 : tree temps, block;
767 :
768 1970585 : gbind *scope = as_a <gbind *> (gs);
769 :
770 1970585 : temps = nreverse (last);
771 :
772 1970585 : block = gimple_bind_block (scope);
773 1970585 : gcc_assert (!block || TREE_CODE (block) == BLOCK);
774 1970585 : if (!block || !debug_info)
775 : {
776 1966846 : DECL_CHAIN (last) = gimple_bind_vars (scope);
777 1966846 : gimple_bind_set_vars (scope, temps);
778 : }
779 : else
780 : {
781 : /* We need to attach the nodes both to the BIND_EXPR and to its
782 : associated BLOCK for debugging purposes. The key point here
783 : is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
784 : is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
785 3739 : if (BLOCK_VARS (block))
786 3546 : BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
787 : else
788 : {
789 193 : gimple_bind_set_vars (scope,
790 : chainon (gimple_bind_vars (scope), temps));
791 193 : BLOCK_VARS (block) = temps;
792 : }
793 : }
794 : }
795 3141132 : }
796 :
797 : /* For VAR a VAR_DECL of variable size, try to find a constant upper bound
798 : for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
799 : no such upper bound can be obtained. */
800 :
801 : static void
802 0 : force_constant_size (tree var)
803 : {
804 : /* The only attempt we make is by querying the maximum size of objects
805 : of the variable's type. */
806 :
807 0 : HOST_WIDE_INT max_size;
808 :
809 0 : gcc_assert (VAR_P (var));
810 :
811 0 : max_size = max_int_size_in_bytes (TREE_TYPE (var));
812 :
813 0 : gcc_assert (max_size >= 0);
814 :
815 0 : DECL_SIZE_UNIT (var)
816 0 : = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
817 0 : DECL_SIZE (var)
818 0 : = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
819 0 : }
820 :
821 : /* Push the temporary variable TMP into the current binding. */
822 :
823 : void
824 27615 : gimple_add_tmp_var_fn (struct function *fn, tree tmp)
825 : {
826 27615 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
827 :
828 : /* Later processing assumes that the object size is constant, which might
829 : not be true at this point. Force the use of a constant upper bound in
830 : this case. */
831 27615 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
832 0 : force_constant_size (tmp);
833 :
834 27615 : DECL_CONTEXT (tmp) = fn->decl;
835 27615 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
836 :
837 27615 : record_vars_into (tmp, fn->decl);
838 27615 : }
839 :
840 : /* Push the temporary variable TMP into the current binding. */
841 :
842 : void
843 16697686 : gimple_add_tmp_var (tree tmp)
844 : {
845 16697686 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
846 :
847 : /* Later processing assumes that the object size is constant, which might
848 : not be true at this point. Force the use of a constant upper bound in
849 : this case. */
850 16697686 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
851 0 : force_constant_size (tmp);
852 :
853 16697686 : DECL_CONTEXT (tmp) = current_function_decl;
854 16697686 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
855 :
856 16697686 : if (gimplify_ctxp)
857 : {
858 5781085 : DECL_CHAIN (tmp) = gimplify_ctxp->temps;
859 5781085 : gimplify_ctxp->temps = tmp;
860 :
861 : /* Mark temporaries local within the nearest enclosing parallel. */
862 5781085 : if (gimplify_omp_ctxp)
863 : {
864 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
865 551490 : int flag = GOVD_LOCAL | GOVD_SEEN;
866 : while (ctx
867 551490 : && (ctx->region_type == ORT_WORKSHARE
868 : || ctx->region_type == ORT_TASKGROUP
869 404755 : || ctx->region_type == ORT_SIMD
870 354552 : || ctx->region_type == ORT_ACC))
871 : {
872 203797 : if (ctx->region_type == ORT_SIMD
873 50203 : && TREE_ADDRESSABLE (tmp)
874 95 : && !TREE_STATIC (tmp))
875 : {
876 95 : if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST)
877 0 : ctx->add_safelen1 = true;
878 95 : else if (ctx->in_for_exprs)
879 : flag = GOVD_PRIVATE;
880 : else
881 : flag = GOVD_PRIVATE | GOVD_SEEN;
882 : break;
883 : }
884 203702 : ctx = ctx->outer_context;
885 : }
886 347693 : if (ctx)
887 320608 : omp_add_variable (ctx, tmp, flag);
888 : }
889 : }
890 10916601 : else if (cfun)
891 10916601 : record_vars (tmp);
892 : else
893 : {
894 0 : gimple_seq body_seq;
895 :
896 : /* This case is for nested functions. We need to expose the locals
897 : they create. */
898 0 : body_seq = gimple_body (current_function_decl);
899 0 : declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
900 : }
901 16697686 : }
902 :
903 : /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
904 : any nested functions. */
905 :
906 : static void
907 3035336 : unshare_body (tree fndecl)
908 : {
909 3035336 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
910 : /* If the language requires deep unsharing, we need a pointer set to make
911 : sure we don't repeatedly unshare subtrees of unshareable nodes. */
912 3035336 : hash_set<tree> *visited
913 3035336 : = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
914 :
915 3035336 : copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
916 3035336 : copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
917 3035336 : copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
918 :
919 3039512 : delete visited;
920 :
921 3035336 : if (cgn)
922 6114588 : for (cgn = first_nested_function (cgn); cgn;
923 26155 : cgn = next_nested_function (cgn))
924 26155 : unshare_body (cgn->decl);
925 3035336 : }
926 :
927 : /* Callback for walk_tree to unmark the visited trees rooted at *TP.
928 : Subtrees are walked until the first unvisited node is encountered. */
929 :
930 : static tree
931 285379033 : unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
932 : {
933 285379033 : tree t = *tp;
934 :
935 : /* If this node has been visited, unmark it and keep looking. */
936 285379033 : if (TREE_VISITED (t))
937 200660187 : TREE_VISITED (t) = 0;
938 :
939 : /* Otherwise, don't look any deeper. */
940 : else
941 84718846 : *walk_subtrees = 0;
942 :
943 285379033 : return NULL_TREE;
944 : }
945 :
946 : /* Unmark the visited trees rooted at *TP. */
947 :
948 : static inline void
949 9106008 : unmark_visited (tree *tp)
950 : {
951 9106008 : walk_tree (tp, unmark_visited_r, NULL, NULL);
952 9106008 : }
953 :
954 : /* Likewise, but mark all trees as not visited. */
955 :
956 : static void
957 3035336 : unvisit_body (tree fndecl)
958 : {
959 3035336 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
960 :
961 3035336 : unmark_visited (&DECL_SAVED_TREE (fndecl));
962 3035336 : unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
963 3035336 : unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
964 :
965 3035336 : if (cgn)
966 3057294 : for (cgn = first_nested_function (cgn);
967 3057294 : cgn; cgn = next_nested_function (cgn))
968 26155 : unvisit_body (cgn->decl);
969 3035336 : }
970 :
971 : /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
972 : one, OR_ELSE otherwise. The location of a STATEMENT_LISTs
973 : comprising at least one DEBUG_BEGIN_STMT followed by exactly one
974 : EXPR is the location of the EXPR. */
975 :
976 : static location_t
977 1191111 : rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
978 : {
979 1191111 : if (!expr)
980 : return or_else;
981 :
982 1191111 : if (EXPR_HAS_LOCATION (expr))
983 830042 : return EXPR_LOCATION (expr);
984 :
985 361069 : if (TREE_CODE (expr) != STATEMENT_LIST)
986 : return or_else;
987 :
988 0 : tree_stmt_iterator i = tsi_start (expr);
989 :
990 0 : bool found = false;
991 0 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
992 : {
993 0 : found = true;
994 0 : tsi_next (&i);
995 : }
996 :
997 361069 : if (!found || !tsi_one_before_end_p (i))
998 : return or_else;
999 :
1000 0 : return rexpr_location (tsi_stmt (i), or_else);
1001 : }
1002 :
1003 : /* Return TRUE iff EXPR (maybe recursively) has a location; see
1004 : rexpr_location for the potential recursion. */
1005 :
1006 : static inline bool
1007 521306 : rexpr_has_location (tree expr)
1008 : {
1009 314461 : return rexpr_location (expr) != UNKNOWN_LOCATION;
1010 : }
1011 :
1012 :
1013 : /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
1014 : contain statements and have a value. Assign its value to a temporary
1015 : and give it void_type_node. Return the temporary, or NULL_TREE if
1016 : WRAPPER was already void. */
1017 :
1018 : tree
1019 20634890 : voidify_wrapper_expr (tree wrapper, tree temp)
1020 : {
1021 20634890 : tree type = TREE_TYPE (wrapper);
1022 20634890 : if (type && !VOID_TYPE_P (type))
1023 : {
1024 : tree *p;
1025 :
1026 : /* Set p to point to the body of the wrapper. Loop until we find
1027 : something that isn't a wrapper. */
1028 797188 : for (p = &wrapper; p && *p; )
1029 : {
1030 797188 : switch (TREE_CODE (*p))
1031 : {
1032 3144 : case BIND_EXPR:
1033 3144 : TREE_SIDE_EFFECTS (*p) = 1;
1034 3144 : TREE_TYPE (*p) = void_type_node;
1035 : /* For a BIND_EXPR, the body is operand 1. */
1036 3144 : p = &BIND_EXPR_BODY (*p);
1037 3144 : break;
1038 :
1039 368739 : case CLEANUP_POINT_EXPR:
1040 368739 : case TRY_FINALLY_EXPR:
1041 368739 : case TRY_CATCH_EXPR:
1042 368739 : TREE_SIDE_EFFECTS (*p) = 1;
1043 368739 : TREE_TYPE (*p) = void_type_node;
1044 368739 : p = &TREE_OPERAND (*p, 0);
1045 368739 : break;
1046 :
1047 17959 : case STATEMENT_LIST:
1048 17959 : {
1049 17959 : tree_stmt_iterator i = tsi_last (*p);
1050 17959 : TREE_SIDE_EFFECTS (*p) = 1;
1051 17959 : TREE_TYPE (*p) = void_type_node;
1052 17959 : p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
1053 : }
1054 17959 : break;
1055 :
1056 : case COMPOUND_EXPR:
1057 : /* Advance to the last statement. Set all container types to
1058 : void. */
1059 64882 : for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
1060 : {
1061 32444 : TREE_SIDE_EFFECTS (*p) = 1;
1062 32444 : TREE_TYPE (*p) = void_type_node;
1063 : }
1064 : break;
1065 :
1066 76 : case TRANSACTION_EXPR:
1067 76 : TREE_SIDE_EFFECTS (*p) = 1;
1068 76 : TREE_TYPE (*p) = void_type_node;
1069 76 : p = &TRANSACTION_EXPR_BODY (*p);
1070 76 : break;
1071 :
1072 374832 : default:
1073 : /* Assume that any tree upon which voidify_wrapper_expr is
1074 : directly called is a wrapper, and that its body is op0. */
1075 374832 : if (p == &wrapper)
1076 : {
1077 33 : TREE_SIDE_EFFECTS (*p) = 1;
1078 33 : TREE_TYPE (*p) = void_type_node;
1079 33 : p = &TREE_OPERAND (*p, 0);
1080 33 : break;
1081 : }
1082 374799 : goto out;
1083 : }
1084 : }
1085 :
1086 0 : out:
1087 374799 : if (p == NULL || IS_EMPTY_STMT (*p))
1088 : temp = NULL_TREE;
1089 374799 : else if (temp)
1090 : {
1091 : /* The wrapper is on the RHS of an assignment that we're pushing
1092 : down. */
1093 1933 : gcc_assert (TREE_CODE (temp) == INIT_EXPR
1094 : || TREE_CODE (temp) == MODIFY_EXPR);
1095 1933 : TREE_OPERAND (temp, 1) = *p;
1096 1933 : *p = temp;
1097 : }
1098 : else
1099 : {
1100 372866 : temp = create_tmp_var (type, "retval");
1101 372866 : *p = build2 (INIT_EXPR, type, temp, *p);
1102 : }
1103 :
1104 374799 : return temp;
1105 : }
1106 :
1107 : return NULL_TREE;
1108 : }
1109 :
1110 : /* Prepare calls to builtins to SAVE and RESTORE the stack as well as
1111 : a temporary through which they communicate. */
1112 :
1113 : static void
1114 7868 : build_stack_save_restore (gcall **save, gcall **restore)
1115 : {
1116 7868 : tree tmp_var;
1117 :
1118 15736 : *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
1119 7868 : tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
1120 7868 : gimple_call_set_lhs (*save, tmp_var);
1121 :
1122 7868 : *restore
1123 7868 : = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1124 : 1, tmp_var);
1125 7868 : }
1126 :
1127 : /* Generate IFN_ASAN_MARK call that poisons shadow memory of the DECL
1128 : variable. */
1129 :
1130 : static tree
1131 478 : build_asan_poison_call_expr (tree decl)
1132 : {
1133 : /* Do not poison variables that have size equal to zero. */
1134 478 : tree unit_size = DECL_SIZE_UNIT (decl);
1135 478 : if (zerop (unit_size))
1136 : return NULL_TREE;
1137 :
1138 478 : tree base = build_fold_addr_expr (decl);
1139 :
1140 478 : return build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_ASAN_MARK,
1141 : void_type_node, 3,
1142 : build_int_cst (integer_type_node,
1143 : ASAN_MARK_POISON),
1144 : base, unit_size);
1145 : }
1146 :
1147 : /* Generate IFN_ASAN_MARK call that would poison or unpoison, depending
1148 : on POISON flag, shadow memory of a DECL variable. The call will be
1149 : put on location identified by IT iterator, where BEFORE flag drives
1150 : position where the stmt will be put. */
1151 :
1152 : static void
1153 5063 : asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
1154 : bool before)
1155 : {
1156 5063 : tree unit_size = DECL_SIZE_UNIT (decl);
1157 5063 : tree base = build_fold_addr_expr (decl);
1158 :
1159 : /* Do not poison variables that have size equal to zero. */
1160 5063 : if (zerop (unit_size))
1161 5063 : return;
1162 :
1163 : /* It's necessary to have all stack variables aligned to ASAN granularity
1164 : bytes. */
1165 5049 : gcc_assert (!hwassist_sanitize_p () || hwassist_sanitize_stack_p ());
1166 5049 : unsigned shadow_granularity
1167 5049 : = (hwassist_sanitize_p ()
1168 5049 : ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY);
1169 5049 : if (DECL_ALIGN_UNIT (decl) <= shadow_granularity)
1170 4847 : SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity);
1171 :
1172 5049 : HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON;
1173 :
1174 5049 : gimple *g
1175 5049 : = gimple_build_call_internal (IFN_ASAN_MARK, 3,
1176 5049 : build_int_cst (integer_type_node, flags),
1177 : base, unit_size);
1178 :
1179 5049 : if (before)
1180 2646 : gsi_insert_before (it, g, GSI_NEW_STMT);
1181 : else
1182 2403 : gsi_insert_after (it, g, GSI_NEW_STMT);
1183 : }
1184 :
1185 : /* Generate IFN_ASAN_MARK internal call that depending on POISON flag
1186 : either poisons or unpoisons a DECL. Created statement is appended
1187 : to SEQ_P gimple sequence. */
1188 :
1189 : static void
1190 4585 : asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
1191 : {
1192 4585 : gimple_stmt_iterator it = gsi_last (*seq_p);
1193 4585 : bool before = false;
1194 :
1195 4585 : if (gsi_end_p (it))
1196 2431 : before = true;
1197 :
1198 4585 : asan_poison_variable (decl, poison, &it, before);
1199 4585 : }
1200 :
1201 : /* Sort pair of VAR_DECLs A and B by DECL_UID. */
1202 :
1203 : static int
1204 135 : sort_by_decl_uid (const void *a, const void *b)
1205 : {
1206 135 : const tree *t1 = (const tree *)a;
1207 135 : const tree *t2 = (const tree *)b;
1208 :
1209 135 : int uid1 = DECL_UID (*t1);
1210 135 : int uid2 = DECL_UID (*t2);
1211 :
1212 135 : if (uid1 < uid2)
1213 : return -1;
1214 50 : else if (uid1 > uid2)
1215 : return 1;
1216 : else
1217 0 : return 0;
1218 : }
1219 :
1220 : /* Generate IFN_ASAN_MARK internal call for all VARIABLES
1221 : depending on POISON flag. Created statement is appended
1222 : to SEQ_P gimple sequence. */
1223 :
1224 : static void
1225 1038578 : asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p)
1226 : {
1227 1038578 : unsigned c = variables->elements ();
1228 1038578 : if (c == 0)
1229 1038304 : return;
1230 :
1231 274 : auto_vec<tree> sorted_variables (c);
1232 :
1233 274 : for (hash_set<tree>::iterator it = variables->begin ();
1234 864 : it != variables->end (); ++it)
1235 295 : sorted_variables.safe_push (*it);
1236 :
1237 274 : sorted_variables.qsort (sort_by_decl_uid);
1238 :
1239 : unsigned i;
1240 : tree var;
1241 843 : FOR_EACH_VEC_ELT (sorted_variables, i, var)
1242 : {
1243 295 : asan_poison_variable (var, poison, seq_p);
1244 :
1245 : /* Add use_after_scope_memory attribute for the variable in order
1246 : to prevent re-written into SSA. */
1247 295 : if (!lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
1248 295 : DECL_ATTRIBUTES (var)))
1249 97 : DECL_ATTRIBUTES (var)
1250 194 : = tree_cons (get_identifier (ASAN_USE_AFTER_SCOPE_ATTRIBUTE),
1251 : integer_one_node,
1252 97 : DECL_ATTRIBUTES (var));
1253 : }
1254 274 : }
1255 :
1256 : /* Gimplify a BIND_EXPR. Just voidify and recurse. */
1257 :
1258 : static enum gimplify_status
1259 6030725 : gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
1260 : {
1261 6030725 : tree bind_expr = *expr_p;
1262 6030725 : bool old_keep_stack = gimplify_ctxp->keep_stack;
1263 6030725 : bool old_save_stack = gimplify_ctxp->save_stack;
1264 6030725 : tree t;
1265 6030725 : gbind *bind_stmt;
1266 6030725 : gimple_seq body, cleanup;
1267 6030725 : gcall *stack_save;
1268 6030725 : location_t start_locus = 0, end_locus = 0;
1269 6030725 : tree ret_clauses = NULL;
1270 :
1271 6030725 : tree temp = voidify_wrapper_expr (bind_expr, NULL);
1272 :
1273 : /* Mark variables seen in this bind expr. */
1274 12993935 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1275 : {
1276 6963210 : if (VAR_P (t))
1277 : {
1278 6290395 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1279 6290395 : tree attr;
1280 :
1281 6290395 : if (flag_openmp
1282 257881 : && !is_global_var (t)
1283 248988 : && !TREE_STATIC (t)
1284 248988 : && DECL_CONTEXT (t) == current_function_decl
1285 248988 : && TREE_USED (t)
1286 6537788 : && (attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1287 : != NULL_TREE)
1288 : {
1289 76 : gcc_assert (!DECL_HAS_VALUE_EXPR_P (t));
1290 76 : tree alloc = TREE_PURPOSE (TREE_VALUE (attr));
1291 76 : tree align = TREE_VALUE (TREE_VALUE (attr));
1292 : /* Allocate directives that appear in a target region must specify
1293 : an allocator clause unless a requires directive with the
1294 : dynamic_allocators clause is present in the same compilation
1295 : unit. */
1296 76 : bool missing_dyn_alloc = false;
1297 76 : if ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0)
1298 : {
1299 : /* This comes too early for omp_discover_declare_target...,
1300 : but should at least catch the most common cases. */
1301 70 : missing_dyn_alloc
1302 70 : = (alloc == NULL_TREE
1303 70 : && cgraph_node::get (current_function_decl)->offloadable);
1304 70 : for (struct gimplify_omp_ctx *ctx2 = ctx;
1305 74 : ctx2 && !missing_dyn_alloc; ctx2 = ctx2->outer_context)
1306 13 : if (ctx2->code == OMP_TARGET)
1307 : {
1308 9 : if (alloc == NULL_TREE)
1309 : missing_dyn_alloc = true;
1310 7 : else if (TREE_CODE (alloc) != INTEGER_CST)
1311 : {
1312 2 : tree alloc2 = alloc;
1313 2 : if (TREE_CODE (alloc2) == MEM_REF
1314 2 : || TREE_CODE (alloc2) == INDIRECT_REF)
1315 0 : alloc2 = TREE_OPERAND (alloc2, 0);
1316 2 : tree c2;
1317 2 : for (c2 = ctx2->clauses; c2;
1318 0 : c2 = OMP_CLAUSE_CHAIN (c2))
1319 1 : if (OMP_CLAUSE_CODE (c2)
1320 : == OMP_CLAUSE_USES_ALLOCATORS)
1321 : {
1322 1 : tree t2
1323 1 : = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c2);
1324 1 : if (operand_equal_p (alloc2, t2))
1325 : break;
1326 : }
1327 2 : if (c2 == NULL_TREE)
1328 1 : error_at (EXPR_LOC_OR_LOC (
1329 : alloc, DECL_SOURCE_LOCATION (t)),
1330 : "%qE in %<allocator%> clause inside a "
1331 : "target region must be specified in an "
1332 : "%<uses_allocators%> clause on the "
1333 : "%<target%> directive", alloc2);
1334 : }
1335 : break;
1336 : }
1337 : }
1338 68 : if (missing_dyn_alloc)
1339 4 : error_at (DECL_SOURCE_LOCATION (t),
1340 : "%<allocate%> directive for %qD inside a target "
1341 : "region must specify an %<allocator%> clause", t);
1342 : /* Skip for omp_default_mem_alloc (= 1),
1343 : unless align is present. For C/C++, there should be always a
1344 : statement list following if TREE_USED, except for, e.g., using
1345 : this decl in a static_assert; in that case, only a single
1346 : DECL_EXPR remains, which can be skipped here. */
1347 72 : else if (!errorcount
1348 55 : && (align != NULL_TREE
1349 55 : || alloc == NULL_TREE
1350 10 : || !integer_onep (alloc))
1351 125 : && (lang_GNU_Fortran ()
1352 25 : || (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1353 : != DECL_EXPR)))
1354 : {
1355 : /* Fortran might already use a pointer type internally;
1356 : use that pointer except for type(C_ptr) and type(C_funptr);
1357 : note that normal proc pointers are rejected. */
1358 53 : tree type = TREE_TYPE (t);
1359 53 : tree tmp, v;
1360 53 : if (lang_GNU_Fortran ()
1361 28 : && POINTER_TYPE_P (type)
1362 8 : && TREE_TYPE (type) != void_type_node
1363 59 : && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
1364 : {
1365 6 : type = TREE_TYPE (type);
1366 6 : v = t;
1367 : }
1368 : else
1369 : {
1370 47 : tmp = build_pointer_type (type);
1371 47 : v = create_tmp_var (tmp, get_name (t));
1372 47 : DECL_IGNORED_P (v) = 0;
1373 47 : DECL_ATTRIBUTES (v)
1374 47 : = tree_cons (get_identifier ("omp allocate var"),
1375 : build_tree_list (NULL_TREE, t),
1376 : remove_attribute ("omp allocate",
1377 47 : DECL_ATTRIBUTES (t)));
1378 47 : tmp = build_fold_indirect_ref (v);
1379 47 : TREE_THIS_NOTRAP (tmp) = 1;
1380 47 : SET_DECL_VALUE_EXPR (t, tmp);
1381 47 : DECL_HAS_VALUE_EXPR_P (t) = 1;
1382 : }
1383 53 : tree sz = TYPE_SIZE_UNIT (type);
1384 : /* The size to use in Fortran might not match TYPE_SIZE_UNIT;
1385 : hence, for some decls, a size variable is saved in the
1386 : attributes; use it, if available. */
1387 53 : if (TREE_CHAIN (TREE_VALUE (attr))
1388 28 : && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))
1389 59 : && TREE_PURPOSE (
1390 : TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))))
1391 : {
1392 6 : sz = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1393 6 : sz = TREE_PURPOSE (sz);
1394 : }
1395 53 : if (alloc == NULL_TREE)
1396 36 : alloc = build_zero_cst (ptr_type_node);
1397 53 : if (align == NULL_TREE)
1398 42 : align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (t));
1399 : else
1400 11 : align = build_int_cst (size_type_node,
1401 11 : MAX (tree_to_uhwi (align),
1402 : DECL_ALIGN_UNIT (t)));
1403 53 : location_t loc = DECL_SOURCE_LOCATION (t);
1404 53 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
1405 53 : tmp = build_call_expr_loc (loc, tmp, 3, align, sz, alloc);
1406 53 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1407 53 : fold_convert (TREE_TYPE (v), tmp));
1408 53 : gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE);
1409 : /* Ensure that either TREE_CHAIN (TREE_VALUE (attr) is set
1410 : and GOMP_FREE added here or that DECL_HAS_VALUE_EXPR_P (t)
1411 : is set, using in a condition much further below. */
1412 59 : gcc_assert (DECL_HAS_VALUE_EXPR_P (t)
1413 : || TREE_CHAIN (TREE_VALUE (attr)));
1414 53 : if (TREE_CHAIN (TREE_VALUE (attr)))
1415 : {
1416 : /* Fortran is special as it does not have properly nest
1417 : declarations in blocks. And as there is no
1418 : initializer, there is also no expression to look for.
1419 : Hence, the FE makes the statement list of the
1420 : try-finally block available. We can put the GOMP_alloc
1421 : at the top, unless an allocator or size expression
1422 : requires to put it afterward; note that the size is
1423 : always later in generated code; for strings, no
1424 : size expr but still an expr might be available.
1425 : As LTO does not handle a statement list, 'sl' has
1426 : to be removed; done so by removing the attribute. */
1427 28 : DECL_ATTRIBUTES (t)
1428 28 : = remove_attribute ("omp allocate",
1429 28 : DECL_ATTRIBUTES (t));
1430 28 : tree sl = TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)));
1431 28 : tree_stmt_iterator e = tsi_start (sl);
1432 28 : tree needle = NULL_TREE;
1433 28 : if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1434 : {
1435 6 : needle = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1436 6 : needle = (TREE_VALUE (needle) ? TREE_VALUE (needle)
1437 : : sz);
1438 : }
1439 22 : else if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1440 : needle = sz;
1441 22 : else if (DECL_P (alloc) && DECL_ARTIFICIAL (alloc))
1442 : needle = alloc;
1443 :
1444 10 : if (needle != NULL_TREE)
1445 : {
1446 49 : while (!tsi_end_p (e))
1447 : {
1448 49 : if (*e == needle
1449 49 : || (TREE_CODE (*e) == MODIFY_EXPR
1450 49 : && TREE_OPERAND (*e, 0) == needle))
1451 : break;
1452 39 : ++e;
1453 : }
1454 10 : gcc_assert (!tsi_end_p (e));
1455 : }
1456 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1457 :
1458 : /* As the cleanup is in BIND_EXPR_BODY, GOMP_free is added
1459 : here; for C/C++ it will be added in the 'cleanup'
1460 : section after gimplification. But Fortran already has
1461 : a try-finally block. */
1462 28 : sl = TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)));
1463 28 : e = tsi_last (sl);
1464 28 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1465 28 : tmp = build_call_expr_loc (EXPR_LOCATION (*e), tmp, 2, v,
1466 : build_zero_cst (ptr_type_node));
1467 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1468 28 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1469 28 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1470 28 : fold_convert (TREE_TYPE (v), tmp));
1471 28 : ++e;
1472 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1473 : }
1474 : else
1475 : {
1476 25 : gcc_assert (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1477 : == STATEMENT_LIST);
1478 25 : tree_stmt_iterator e;
1479 25 : e = tsi_start (BIND_EXPR_BODY (bind_expr));
1480 113 : while (!tsi_end_p (e))
1481 : {
1482 88 : if ((TREE_CODE (*e) == DECL_EXPR
1483 58 : && TREE_OPERAND (*e, 0) == t)
1484 121 : || (TREE_CODE (*e) == CLEANUP_POINT_EXPR
1485 0 : && (TREE_CODE (TREE_OPERAND (*e, 0))
1486 : == DECL_EXPR)
1487 0 : && (TREE_OPERAND (TREE_OPERAND (*e, 0), 0)
1488 : == t)))
1489 : break;
1490 63 : ++e;
1491 : }
1492 25 : gcc_assert (!tsi_end_p (e));
1493 25 : tsi_link_before (&e, tmp, TSI_SAME_STMT);
1494 : }
1495 : }
1496 : }
1497 :
1498 : /* Mark variable as local. */
1499 6290395 : if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t))
1500 : {
1501 100660 : if (! DECL_SEEN_IN_BIND_EXPR_P (t)
1502 100660 : || splay_tree_lookup (ctx->variables,
1503 : (splay_tree_key) t) == NULL)
1504 : {
1505 100660 : int flag = GOVD_LOCAL;
1506 100660 : if (ctx->region_type == ORT_SIMD
1507 4376 : && TREE_ADDRESSABLE (t)
1508 81 : && !TREE_STATIC (t))
1509 : {
1510 69 : if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST)
1511 2 : ctx->add_safelen1 = true;
1512 : else
1513 : flag = GOVD_PRIVATE;
1514 : }
1515 100660 : omp_add_variable (ctx, t, flag | GOVD_SEEN);
1516 : }
1517 : /* Static locals inside of target construct or offloaded
1518 : routines need to be "omp declare target". */
1519 100660 : if (TREE_STATIC (t))
1520 1385 : for (; ctx; ctx = ctx->outer_context)
1521 1206 : if ((ctx->region_type & ORT_TARGET) != 0)
1522 : {
1523 968 : if (!lookup_attribute ("omp declare target",
1524 968 : DECL_ATTRIBUTES (t)))
1525 : {
1526 956 : tree id = get_identifier ("omp declare target");
1527 956 : DECL_ATTRIBUTES (t)
1528 956 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
1529 956 : varpool_node *node = varpool_node::get (t);
1530 956 : if (node)
1531 : {
1532 33 : node->offloadable = 1;
1533 33 : if (ENABLE_OFFLOADING && !DECL_EXTERNAL (t))
1534 : {
1535 : g->have_offload = true;
1536 : if (!in_lto_p)
1537 : vec_safe_push (offload_vars, t);
1538 : }
1539 : }
1540 : }
1541 : break;
1542 : }
1543 : }
1544 :
1545 6290395 : DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
1546 :
1547 6290395 : if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
1548 1088 : cfun->has_local_explicit_reg_vars = true;
1549 : }
1550 : }
1551 :
1552 12061450 : bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
1553 6030725 : BIND_EXPR_BLOCK (bind_expr));
1554 6030725 : gimple_push_bind_expr (bind_stmt);
1555 :
1556 6030725 : gimplify_ctxp->keep_stack = false;
1557 6030725 : gimplify_ctxp->save_stack = false;
1558 :
1559 : /* Gimplify the body into the GIMPLE_BIND tuple's body. */
1560 6030725 : body = NULL;
1561 6030725 : gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
1562 6030725 : gimple_bind_set_body (bind_stmt, body);
1563 :
1564 : /* Source location wise, the cleanup code (stack_restore and clobbers)
1565 : belongs to the end of the block, so propagate what we have. The
1566 : stack_save operation belongs to the beginning of block, which we can
1567 : infer from the bind_expr directly if the block has no explicit
1568 : assignment. */
1569 6030725 : if (BIND_EXPR_BLOCK (bind_expr))
1570 : {
1571 5899236 : end_locus = BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1572 5899236 : start_locus = BLOCK_SOURCE_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1573 : }
1574 5899236 : if (start_locus == 0)
1575 6030725 : start_locus = EXPR_LOCATION (bind_expr);
1576 :
1577 6030725 : cleanup = NULL;
1578 6030725 : stack_save = NULL;
1579 :
1580 : /* Add clobbers for all variables that go out of scope. */
1581 12993935 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1582 : {
1583 6963210 : if (VAR_P (t)
1584 6290395 : && !is_global_var (t)
1585 13032980 : && DECL_CONTEXT (t) == current_function_decl)
1586 : {
1587 6069770 : if (flag_openmp
1588 248969 : && DECL_HAS_VALUE_EXPR_P (t)
1589 1083 : && TREE_USED (t)
1590 6070836 : && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1591 : {
1592 : /* For Fortran, TREE_CHAIN (TREE_VALUE (attr)) is set, which
1593 : causes that the GOMP_free call is already added above;
1594 : and "omp allocate" is removed from DECL_ATTRIBUTES. */
1595 25 : tree v = TREE_OPERAND (DECL_VALUE_EXPR (t), 0);
1596 25 : tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1597 25 : tmp = build_call_expr_loc (end_locus, tmp, 2, v,
1598 : build_zero_cst (ptr_type_node));
1599 25 : gimplify_and_add (tmp, &cleanup);
1600 25 : gimple *clobber_stmt;
1601 25 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1602 25 : clobber_stmt = gimple_build_assign (v, tmp);
1603 25 : gimple_set_location (clobber_stmt, end_locus);
1604 25 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1605 : }
1606 6069770 : if (!DECL_HARD_REGISTER (t)
1607 6068682 : && !TREE_THIS_VOLATILE (t)
1608 6029579 : && !DECL_HAS_VALUE_EXPR_P (t)
1609 : /* Only care for variables that have to be in memory. Others
1610 : will be rewritten into SSA names, hence moved to the
1611 : top-level. */
1612 5904299 : && !is_gimple_reg (t)
1613 7341834 : && flag_stack_reuse != SR_NONE)
1614 : {
1615 1268294 : tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_STORAGE_END);
1616 1268294 : gimple *clobber_stmt;
1617 1268294 : clobber_stmt = gimple_build_assign (t, clobber);
1618 1268294 : gimple_set_location (clobber_stmt, end_locus);
1619 1268294 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1620 : }
1621 :
1622 6069770 : if (flag_openacc && oacc_declare_returns != NULL)
1623 : {
1624 207 : tree key = t;
1625 207 : if (DECL_HAS_VALUE_EXPR_P (key))
1626 : {
1627 8 : key = DECL_VALUE_EXPR (key);
1628 8 : if (INDIRECT_REF_P (key))
1629 8 : key = TREE_OPERAND (key, 0);
1630 : }
1631 207 : tree *c = oacc_declare_returns->get (key);
1632 207 : if (c != NULL)
1633 : {
1634 116 : if (ret_clauses)
1635 64 : OMP_CLAUSE_CHAIN (*c) = ret_clauses;
1636 :
1637 116 : ret_clauses = unshare_expr (*c);
1638 :
1639 116 : oacc_declare_returns->remove (key);
1640 :
1641 116 : if (oacc_declare_returns->is_empty ())
1642 : {
1643 40 : delete oacc_declare_returns;
1644 40 : oacc_declare_returns = NULL;
1645 : }
1646 : }
1647 : }
1648 : }
1649 :
1650 6963210 : if (asan_poisoned_variables != NULL
1651 6963210 : && asan_poisoned_variables->contains (t))
1652 : {
1653 2145 : asan_poisoned_variables->remove (t);
1654 2145 : asan_poison_variable (t, true, &cleanup);
1655 : }
1656 :
1657 6963210 : if (gimplify_ctxp->live_switch_vars != NULL
1658 6963210 : && gimplify_ctxp->live_switch_vars->contains (t))
1659 55 : gimplify_ctxp->live_switch_vars->remove (t);
1660 : }
1661 :
1662 : /* If the code both contains VLAs and calls alloca, then we cannot reclaim
1663 : the stack space allocated to the VLAs. */
1664 6030725 : if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack)
1665 : {
1666 7868 : gcall *stack_restore;
1667 :
1668 : /* Save stack on entry and restore it on exit. Add a try_finally
1669 : block to achieve this. */
1670 7868 : build_stack_save_restore (&stack_save, &stack_restore);
1671 :
1672 7868 : gimple_set_location (stack_save, start_locus);
1673 7868 : gimple_set_location (stack_restore, end_locus);
1674 :
1675 7868 : gimplify_seq_add_stmt (&cleanup, stack_restore);
1676 : }
1677 :
1678 6030725 : if (ret_clauses)
1679 : {
1680 52 : gomp_target *stmt;
1681 52 : gimple_stmt_iterator si = gsi_start (cleanup);
1682 :
1683 52 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
1684 : ret_clauses);
1685 52 : gsi_insert_seq_before_without_update (&si, stmt, GSI_NEW_STMT);
1686 : }
1687 :
1688 6030725 : if (cleanup)
1689 : {
1690 783475 : gtry *gs;
1691 783475 : gimple_seq new_body;
1692 :
1693 783475 : new_body = NULL;
1694 783475 : gs = gimple_build_try (gimple_bind_body (bind_stmt), cleanup,
1695 : GIMPLE_TRY_FINALLY);
1696 :
1697 783475 : if (stack_save)
1698 7868 : gimplify_seq_add_stmt (&new_body, stack_save);
1699 783475 : gimplify_seq_add_stmt (&new_body, gs);
1700 783475 : gimple_bind_set_body (bind_stmt, new_body);
1701 : }
1702 :
1703 : /* keep_stack propagates all the way up to the outermost BIND_EXPR. */
1704 6030725 : if (!gimplify_ctxp->keep_stack)
1705 6015515 : gimplify_ctxp->keep_stack = old_keep_stack;
1706 6030725 : gimplify_ctxp->save_stack = old_save_stack;
1707 :
1708 6030725 : gimple_pop_bind_expr ();
1709 :
1710 6030725 : gimplify_seq_add_stmt (pre_p, bind_stmt);
1711 :
1712 6030725 : if (temp)
1713 : {
1714 1709 : *expr_p = temp;
1715 1709 : return GS_OK;
1716 : }
1717 :
1718 6029016 : *expr_p = NULL_TREE;
1719 6029016 : return GS_ALL_DONE;
1720 : }
1721 :
1722 : /* Maybe add early return predict statement to PRE_P sequence. */
1723 :
1724 : static void
1725 2287082 : maybe_add_early_return_predict_stmt (gimple_seq *pre_p)
1726 : {
1727 : /* If we are not in a conditional context, add PREDICT statement. */
1728 2287082 : if (gimple_conditional_context ())
1729 : {
1730 448088 : gimple *predict = gimple_build_predict (PRED_TREE_EARLY_RETURN,
1731 : NOT_TAKEN);
1732 448088 : gimplify_seq_add_stmt (pre_p, predict);
1733 : }
1734 2287082 : }
1735 :
1736 : /* Gimplify a RETURN_EXPR. If the expression to be returned is not a
1737 : GIMPLE value, it is assigned to a new temporary and the statement is
1738 : re-written to return the temporary.
1739 :
1740 : PRE_P points to the sequence where side effects that must happen before
1741 : STMT should be stored. */
1742 :
1743 : static enum gimplify_status
1744 2287088 : gimplify_return_expr (tree stmt, gimple_seq *pre_p)
1745 : {
1746 2287088 : greturn *ret;
1747 2287088 : tree ret_expr = TREE_OPERAND (stmt, 0);
1748 2287088 : tree result_decl, result;
1749 :
1750 2287088 : if (ret_expr == error_mark_node)
1751 : return GS_ERROR;
1752 :
1753 2287082 : if (!ret_expr
1754 2197178 : || TREE_CODE (ret_expr) == RESULT_DECL)
1755 : {
1756 104400 : maybe_add_early_return_predict_stmt (pre_p);
1757 104400 : greturn *ret = gimple_build_return (ret_expr);
1758 104400 : copy_warning (ret, stmt);
1759 104400 : gimplify_seq_add_stmt (pre_p, ret);
1760 104400 : return GS_ALL_DONE;
1761 : }
1762 :
1763 2182682 : if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
1764 : result_decl = NULL_TREE;
1765 2182357 : else if (TREE_CODE (ret_expr) == COMPOUND_EXPR)
1766 : {
1767 : /* Used in C++ for handling EH cleanup of the return value if a local
1768 : cleanup throws. Assume the front-end knows what it's doing. */
1769 5221 : result_decl = DECL_RESULT (current_function_decl);
1770 : /* But crash if we end up trying to modify ret_expr below. */
1771 5221 : ret_expr = NULL_TREE;
1772 : }
1773 : else
1774 : {
1775 2177136 : result_decl = TREE_OPERAND (ret_expr, 0);
1776 :
1777 : /* See through a return by reference. */
1778 2177136 : if (INDIRECT_REF_P (result_decl))
1779 43639 : result_decl = TREE_OPERAND (result_decl, 0);
1780 :
1781 2177136 : gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
1782 : || TREE_CODE (ret_expr) == INIT_EXPR)
1783 : && TREE_CODE (result_decl) == RESULT_DECL);
1784 : }
1785 :
1786 : /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
1787 : Recall that aggregate_value_p is FALSE for any aggregate type that is
1788 : returned in registers. If we're returning values in registers, then
1789 : we don't want to extend the lifetime of the RESULT_DECL, particularly
1790 : across another call. In addition, for those aggregates for which
1791 : hard_function_value generates a PARALLEL, we'll die during normal
1792 : expansion of structure assignments; there's special code in expand_return
1793 : to handle this case that does not exist in expand_expr. */
1794 5221 : if (!result_decl)
1795 : result = NULL_TREE;
1796 2182357 : else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
1797 : {
1798 181878 : if (!poly_int_tree_p (DECL_SIZE (result_decl)))
1799 : {
1800 48 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
1801 0 : gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
1802 : /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
1803 : should be effectively allocated by the caller, i.e. all calls to
1804 : this function must be subject to the Return Slot Optimization. */
1805 48 : gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
1806 48 : gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
1807 : }
1808 : result = result_decl;
1809 : }
1810 2000479 : else if (gimplify_ctxp->return_temp)
1811 : result = gimplify_ctxp->return_temp;
1812 : else
1813 : {
1814 1503510 : result = create_tmp_reg (TREE_TYPE (result_decl));
1815 :
1816 : /* ??? With complex control flow (usually involving abnormal edges),
1817 : we can wind up warning about an uninitialized value for this. Due
1818 : to how this variable is constructed and initialized, this is never
1819 : true. Give up and never warn. */
1820 1503510 : suppress_warning (result, OPT_Wuninitialized);
1821 :
1822 1503510 : gimplify_ctxp->return_temp = result;
1823 : }
1824 :
1825 : /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
1826 : Then gimplify the whole thing. */
1827 2182682 : if (result != result_decl)
1828 2000479 : TREE_OPERAND (ret_expr, 0) = result;
1829 :
1830 2182682 : gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
1831 :
1832 2182682 : maybe_add_early_return_predict_stmt (pre_p);
1833 2182682 : ret = gimple_build_return (result);
1834 2182682 : copy_warning (ret, stmt);
1835 2182682 : gimplify_seq_add_stmt (pre_p, ret);
1836 :
1837 2182682 : return GS_ALL_DONE;
1838 : }
1839 :
1840 : /* Gimplify a variable-length array DECL. */
1841 :
1842 : static void
1843 8968 : gimplify_vla_decl (tree decl, gimple_seq *seq_p)
1844 : {
1845 : /* This is a variable-sized decl. Simplify its size and mark it
1846 : for deferred expansion. */
1847 8968 : tree t, addr, ptr_type;
1848 :
1849 8968 : gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
1850 8968 : gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
1851 :
1852 : /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */
1853 8968 : if (DECL_HAS_VALUE_EXPR_P (decl))
1854 : return;
1855 :
1856 : /* All occurrences of this decl in final gimplified code will be
1857 : replaced by indirection. Setting DECL_VALUE_EXPR does two
1858 : things: First, it lets the rest of the gimplifier know what
1859 : replacement to use. Second, it lets the debug info know
1860 : where to find the value. */
1861 8963 : ptr_type = build_pointer_type (TREE_TYPE (decl));
1862 8963 : addr = create_tmp_var (ptr_type, get_name (decl));
1863 8963 : DECL_IGNORED_P (addr) = 0;
1864 8963 : t = build_fold_indirect_ref (addr);
1865 8963 : TREE_THIS_NOTRAP (t) = 1;
1866 8963 : SET_DECL_VALUE_EXPR (decl, t);
1867 8963 : DECL_HAS_VALUE_EXPR_P (decl) = 1;
1868 :
1869 8963 : t = build_alloca_call_expr (DECL_SIZE_UNIT (decl), DECL_ALIGN (decl),
1870 8963 : max_int_size_in_bytes (TREE_TYPE (decl)));
1871 : /* The call has been built for a variable-sized object. */
1872 8963 : CALL_ALLOCA_FOR_VAR_P (t) = 1;
1873 8963 : t = fold_convert (ptr_type, t);
1874 8963 : t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
1875 :
1876 8963 : gimplify_and_add (t, seq_p);
1877 :
1878 : /* Record the dynamic allocation associated with DECL if requested. */
1879 8963 : if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
1880 0 : record_dynamic_alloc (decl);
1881 : }
1882 :
1883 : /* A helper function to be called via walk_tree. Mark all labels under *TP
1884 : as being forced. To be called for DECL_INITIAL of static variables. */
1885 :
1886 : static tree
1887 869899 : force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1888 : {
1889 869899 : if (TYPE_P (*tp))
1890 0 : *walk_subtrees = 0;
1891 869899 : if (TREE_CODE (*tp) == LABEL_DECL)
1892 : {
1893 926 : FORCED_LABEL (*tp) = 1;
1894 926 : cfun->has_forced_label_in_static = 1;
1895 : }
1896 :
1897 869899 : return NULL_TREE;
1898 : }
1899 :
1900 : /* Generate an initialization to automatic variable DECL based on INIT_TYPE.
1901 : Build a call to internal const function DEFERRED_INIT:
1902 : 1st argument: SIZE of the DECL;
1903 : 2nd argument: INIT_TYPE;
1904 : 3rd argument: NAME of the DECL;
1905 :
1906 : as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL). */
1907 :
1908 : static void
1909 155429 : gimple_add_init_for_auto_var (tree decl,
1910 : enum auto_init_type init_type,
1911 : gimple_seq *seq_p)
1912 : {
1913 155429 : gcc_assert (auto_var_p (decl));
1914 155429 : gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
1915 :
1916 155429 : const location_t loc = DECL_SOURCE_LOCATION (decl);
1917 155429 : tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
1918 155429 : tree init_type_node = build_int_cst (integer_type_node, (int) init_type);
1919 155429 : tree decl_name;
1920 :
1921 155429 : if (DECL_NAME (decl))
1922 88360 : decl_name = build_string_literal (DECL_NAME (decl));
1923 : else
1924 : {
1925 67069 : char decl_name_anonymous[3 + (HOST_BITS_PER_INT + 2) / 3];
1926 67069 : sprintf (decl_name_anonymous, "D.%u", DECL_UID (decl));
1927 67069 : decl_name = build_string_literal (decl_name_anonymous);
1928 : }
1929 :
1930 155429 : tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT,
1931 155429 : TREE_TYPE (decl), 3,
1932 : decl_size, init_type_node,
1933 : decl_name);
1934 :
1935 155429 : gimplify_assign (decl, call, seq_p);
1936 155429 : }
1937 :
1938 : /* Generate padding initialization for automatic variable DECL.
1939 : C guarantees that brace-init with fewer initializers than members
1940 : aggregate will initialize the rest of the aggregate as-if it were
1941 : static initialization. In turn static initialization guarantees
1942 : that padding is initialized to zero. So, we always initialize paddings
1943 : to zeroes regardless INIT_TYPE.
1944 : To do the padding initialization, we insert a call to
1945 : __builtin_clear_padding (&decl, 0, for_auto_init = true).
1946 : Note, we add an additional dummy argument for __builtin_clear_padding,
1947 : 'for_auto_init' to distinguish whether this call is for automatic
1948 : variable initialization or not.
1949 : */
1950 : static void
1951 116 : gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
1952 : gimple_seq *seq_p)
1953 : {
1954 116 : tree addr_of_decl = NULL_TREE;
1955 116 : tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
1956 :
1957 116 : if (is_vla)
1958 : {
1959 : /* The temporary address variable for this vla should be
1960 : created in gimplify_vla_decl. */
1961 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
1962 0 : gcc_assert (INDIRECT_REF_P (DECL_VALUE_EXPR (decl)));
1963 0 : addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
1964 : }
1965 : else
1966 : {
1967 116 : mark_addressable (decl);
1968 116 : addr_of_decl = build_fold_addr_expr (decl);
1969 : }
1970 :
1971 116 : gimple *call = gimple_build_call (fn, 2, addr_of_decl,
1972 116 : build_one_cst (TREE_TYPE (addr_of_decl)));
1973 116 : gimplify_seq_add_stmt (seq_p, call);
1974 116 : }
1975 :
1976 : /* Return true if the DECL need to be automatically initialized by the
1977 : compiler. */
1978 : static bool
1979 4351854 : var_needs_auto_init_p (tree decl)
1980 : {
1981 4351854 : if (auto_var_p (decl)
1982 4253949 : && (TREE_CODE (decl) != VAR_DECL || !DECL_HARD_REGISTER (decl))
1983 4253241 : && flag_auto_var_init > AUTO_INIT_UNINITIALIZED
1984 349277 : && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
1985 349269 : && !lookup_attribute ("indeterminate", DECL_ATTRIBUTES (decl))
1986 349260 : && !OPAQUE_TYPE_P (TREE_TYPE (decl))
1987 4701114 : && !is_empty_type (TREE_TYPE (decl)))
1988 : return true;
1989 : return false;
1990 : }
1991 :
1992 : /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
1993 : and initialization explicit. */
1994 :
1995 : static enum gimplify_status
1996 6624277 : gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
1997 : {
1998 6624277 : tree stmt = *stmt_p;
1999 6624277 : tree decl = DECL_EXPR_DECL (stmt);
2000 :
2001 6624277 : *stmt_p = NULL_TREE;
2002 :
2003 6624277 : if (TREE_TYPE (decl) == error_mark_node)
2004 : return GS_ERROR;
2005 :
2006 6624199 : if ((TREE_CODE (decl) == TYPE_DECL
2007 6580802 : || VAR_P (decl))
2008 13201915 : && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
2009 : {
2010 713155 : gimplify_type_sizes (TREE_TYPE (decl), seq_p);
2011 713155 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
2012 23345 : gimplify_type_sizes (TREE_TYPE (TREE_TYPE (decl)), seq_p);
2013 : }
2014 :
2015 : /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
2016 : in case its size expressions contain problematic nodes like CALL_EXPR. */
2017 6624199 : if (TREE_CODE (decl) == TYPE_DECL
2018 43397 : && DECL_ORIGINAL_TYPE (decl)
2019 6629520 : && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
2020 : {
2021 0 : gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
2022 0 : if (TREE_CODE (DECL_ORIGINAL_TYPE (decl)) == REFERENCE_TYPE)
2023 0 : gimplify_type_sizes (TREE_TYPE (DECL_ORIGINAL_TYPE (decl)), seq_p);
2024 : }
2025 :
2026 6624199 : if (VAR_P (decl) && !DECL_EXTERNAL (decl))
2027 : {
2028 6577716 : tree init = DECL_INITIAL (decl);
2029 6577716 : bool is_vla = false;
2030 : /* Check whether a decl has FE created VALUE_EXPR here BEFORE
2031 : gimplify_vla_decl creates VALUE_EXPR for a vla decl.
2032 : If the decl has VALUE_EXPR that was created by FE (usually
2033 : C++FE), it's a proxy variable, and FE already initialized
2034 : the VALUE_EXPR of it, we should not initialize it anymore. */
2035 6577716 : bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
2036 :
2037 6577716 : poly_uint64 size;
2038 6577716 : if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
2039 6577716 : || (!TREE_STATIC (decl)
2040 6451823 : && flag_stack_check == GENERIC_STACK_CHECK
2041 234 : && maybe_gt (size,
2042 : (unsigned HOST_WIDE_INT) STACK_CHECK_MAX_VAR_SIZE)))
2043 : {
2044 8841 : gimplify_vla_decl (decl, seq_p);
2045 8841 : is_vla = true;
2046 : }
2047 :
2048 6577716 : if (asan_poisoned_variables
2049 5161 : && !is_vla
2050 4975 : && TREE_ADDRESSABLE (decl)
2051 2440 : && !TREE_STATIC (decl)
2052 2230 : && !DECL_HAS_VALUE_EXPR_P (decl)
2053 2153 : && DECL_ALIGN (decl) <= MAX_SUPPORTED_STACK_ALIGNMENT
2054 2153 : && dbg_cnt (asan_use_after_scope)
2055 2153 : && !gimplify_omp_ctxp
2056 : /* GNAT introduces temporaries to hold return values of calls in
2057 : initializers of variables defined in other units, so the
2058 : declaration of the variable is discarded completely. We do not
2059 : want to issue poison calls for such dropped variables. */
2060 6579861 : && (DECL_SEEN_IN_BIND_EXPR_P (decl)
2061 0 : || (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)))
2062 : {
2063 2145 : asan_poisoned_variables->add (decl);
2064 2145 : asan_poison_variable (decl, false, seq_p);
2065 2145 : if (!DECL_ARTIFICIAL (decl) && gimplify_ctxp->live_switch_vars)
2066 55 : gimplify_ctxp->live_switch_vars->add (decl);
2067 : }
2068 :
2069 : /* Some front ends do not explicitly declare all anonymous
2070 : artificial variables. We compensate here by declaring the
2071 : variables, though it would be better if the front ends would
2072 : explicitly declare them. */
2073 6577716 : if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
2074 6577716 : && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
2075 16564 : gimple_add_tmp_var (decl);
2076 :
2077 6577716 : if (init && init != error_mark_node)
2078 : {
2079 3725856 : if (!TREE_STATIC (decl))
2080 : {
2081 3696074 : DECL_INITIAL (decl) = NULL_TREE;
2082 3696074 : init = build2 (INIT_EXPR, void_type_node, decl, init);
2083 3696074 : gimplify_and_add (init, seq_p);
2084 3696074 : ggc_free (init);
2085 : /* Clear TREE_READONLY if we really have an initialization. */
2086 3696074 : if (!DECL_INITIAL (decl)
2087 3696074 : && !omp_privatize_by_reference (decl))
2088 3673965 : TREE_READONLY (decl) = 0;
2089 : }
2090 : else
2091 : /* We must still examine initializers for static variables
2092 : as they may contain a label address. */
2093 29782 : walk_tree (&init, force_labels_r, NULL, NULL);
2094 : }
2095 : /* When there is no explicit initializer, if the user requested,
2096 : We should insert an artificial initializer for this automatic
2097 : variable. */
2098 2851860 : else if (var_needs_auto_init_p (decl)
2099 2851860 : && !decl_had_value_expr_p)
2100 : {
2101 96363 : gimple_add_init_for_auto_var (decl,
2102 : flag_auto_var_init,
2103 : seq_p);
2104 : /* The expanding of a call to the above .DEFERRED_INIT will apply
2105 : block initialization to the whole space covered by this variable.
2106 : As a result, all the paddings will be initialized to zeroes
2107 : for zero initialization and 0xFE byte-repeatable patterns for
2108 : pattern initialization.
2109 : In order to make the paddings as zeroes for pattern init, We
2110 : should add a call to __builtin_clear_padding to clear the
2111 : paddings to zero in compatible with CLANG.
2112 : We cannot insert this call if the variable is a gimple register
2113 : since __builtin_clear_padding will take the address of the
2114 : variable. As a result, if a long double/_Complex long double
2115 : variable will spilled into stack later, its padding is 0XFE. */
2116 96363 : if (flag_auto_var_init == AUTO_INIT_PATTERN
2117 184 : && !is_gimple_reg (decl)
2118 96461 : && clear_padding_type_may_have_padding_p (TREE_TYPE (decl)))
2119 75 : gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
2120 : }
2121 : }
2122 :
2123 : return GS_ALL_DONE;
2124 : }
2125 :
2126 : /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
2127 : and replacing the LOOP_EXPR with goto, but if the loop contains an
2128 : EXIT_EXPR, we need to append a label for it to jump to. */
2129 :
2130 : static enum gimplify_status
2131 204526 : gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
2132 : {
2133 204526 : tree saved_label = gimplify_ctxp->exit_label;
2134 204526 : tree start_label = create_artificial_label (UNKNOWN_LOCATION);
2135 :
2136 204526 : gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
2137 :
2138 204526 : gimplify_ctxp->exit_label = NULL_TREE;
2139 :
2140 204526 : gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
2141 :
2142 204526 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
2143 :
2144 204526 : if (gimplify_ctxp->exit_label)
2145 6300 : gimplify_seq_add_stmt (pre_p,
2146 3150 : gimple_build_label (gimplify_ctxp->exit_label));
2147 :
2148 204526 : gimplify_ctxp->exit_label = saved_label;
2149 :
2150 204526 : *expr_p = NULL;
2151 204526 : return GS_ALL_DONE;
2152 : }
2153 :
2154 : /* Gimplify a statement list onto a sequence. These may be created either
2155 : by an enlightened front-end, or by shortcut_cond_expr. */
2156 :
2157 : static enum gimplify_status
2158 8631060 : gimplify_statement_list (tree *expr_p, gimple_seq *pre_p)
2159 : {
2160 8631060 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
2161 :
2162 8631060 : tree_stmt_iterator i = tsi_start (*expr_p);
2163 :
2164 55635709 : while (!tsi_end_p (i))
2165 : {
2166 38373589 : gimplify_stmt (tsi_stmt_ptr (i), pre_p);
2167 38373589 : tsi_delink (&i);
2168 : }
2169 :
2170 8631060 : if (temp)
2171 : {
2172 14815 : *expr_p = temp;
2173 14815 : return GS_OK;
2174 : }
2175 :
2176 : return GS_ALL_DONE;
2177 : }
2178 :
2179 :
2180 : /* Emit warning for the unreachable statement STMT if needed.
2181 : Return the gimple itself when the warning is emitted, otherwise
2182 : return NULL. */
2183 : static gimple *
2184 181 : emit_warn_switch_unreachable (gimple *stmt)
2185 : {
2186 181 : if (gimple_code (stmt) == GIMPLE_GOTO
2187 50 : && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL
2188 231 : && DECL_ARTIFICIAL (gimple_goto_dest (stmt)))
2189 : /* Don't warn for compiler-generated gotos. These occur
2190 : in Duff's devices, for example. */
2191 : return NULL;
2192 : else
2193 131 : warning_at (gimple_location (stmt), OPT_Wswitch_unreachable,
2194 : "statement will never be executed");
2195 131 : return stmt;
2196 : }
2197 :
2198 : /* Callback for walk_gimple_seq. */
2199 :
2200 : static tree
2201 49839 : warn_switch_unreachable_and_auto_init_r (gimple_stmt_iterator *gsi_p,
2202 : bool *handled_ops_p,
2203 : struct walk_stmt_info *wi)
2204 : {
2205 49839 : gimple *stmt = gsi_stmt (*gsi_p);
2206 49839 : bool unreachable_issued = wi->info != NULL;
2207 :
2208 49839 : *handled_ops_p = true;
2209 49839 : switch (gimple_code (stmt))
2210 : {
2211 440 : case GIMPLE_TRY:
2212 : /* A compiler-generated cleanup or a user-written try block.
2213 : If it's empty, don't dive into it--that would result in
2214 : worse location info. */
2215 440 : if (gimple_try_eval (stmt) == NULL)
2216 : {
2217 3 : if (warn_switch_unreachable && !unreachable_issued)
2218 3 : wi->info = emit_warn_switch_unreachable (stmt);
2219 :
2220 : /* Stop when auto var init warning is not on. */
2221 3 : if (!warn_trivial_auto_var_init)
2222 3 : return integer_zero_node;
2223 : }
2224 : /* Fall through. */
2225 2465 : case GIMPLE_BIND:
2226 2465 : case GIMPLE_CATCH:
2227 2465 : case GIMPLE_EH_FILTER:
2228 2465 : case GIMPLE_TRANSACTION:
2229 : /* Walk the sub-statements. */
2230 2465 : *handled_ops_p = false;
2231 2465 : break;
2232 :
2233 : case GIMPLE_DEBUG:
2234 : /* Ignore these. We may generate them before declarations that
2235 : are never executed. If there's something to warn about,
2236 : there will be non-debug stmts too, and we'll catch those. */
2237 : break;
2238 :
2239 60 : case GIMPLE_ASSIGN:
2240 : /* See comment below in the GIMPLE_CALL case. */
2241 60 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2242 20 : && gimple_assign_single_p (stmt)
2243 79 : && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
2244 : {
2245 6 : gimple *g = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
2246 6 : if (gimple_call_internal_p (g, IFN_DEFERRED_INIT))
2247 : break;
2248 : }
2249 54 : goto do_default;
2250 :
2251 45920 : case GIMPLE_LABEL:
2252 : /* Stop till the first Label. */
2253 45920 : return integer_zero_node;
2254 62 : case GIMPLE_CALL:
2255 62 : if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2256 : {
2257 8 : *handled_ops_p = false;
2258 8 : break;
2259 : }
2260 : /* Don't warn for compiler-generated initializations for
2261 : -ftrivial-auto-var-init for -Wswitch-unreachable. Though
2262 : do warn for -Wtrivial-auto-var-init.
2263 : There are 3 cases:
2264 : case 1: a call to .DEFERRED_INIT;
2265 : case 2: a call to __builtin_clear_padding with the 2nd argument is
2266 : present and non-zero;
2267 : case 3: a gimple assign store right after the call to .DEFERRED_INIT
2268 : that has the LHS of .DEFERRED_INIT as the RHS as following:
2269 : _1 = .DEFERRED_INIT (4, 2, &"i1"[0]);
2270 : i1 = _1.
2271 : case 3 is handled above in the GIMPLE_ASSIGN case. */
2272 54 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2273 54 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2274 : {
2275 33 : if (warn_trivial_auto_var_init)
2276 : {
2277 : /* Get the variable name from the 3rd argument of call. */
2278 12 : tree var_name = gimple_call_arg (stmt, 2);
2279 12 : var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0);
2280 12 : const char *var_name_str = TREE_STRING_POINTER (var_name);
2281 :
2282 12 : warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init,
2283 : "%qs cannot be initialized with "
2284 : "%<-ftrivial-auto-var_init%>", var_name_str);
2285 : }
2286 : break;
2287 : }
2288 21 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2289 7 : && gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
2290 24 : && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
2291 : break;
2292 : /* Fall through. */
2293 178 : default:
2294 178 : do_default:
2295 : /* check the first "real" statement (not a decl/lexical scope/...), issue
2296 : warning if needed. */
2297 178 : if (warn_switch_unreachable && !unreachable_issued)
2298 178 : wi->info = emit_warn_switch_unreachable (stmt);
2299 : /* Stop when auto var init warning is not on. */
2300 178 : if (!warn_trivial_auto_var_init)
2301 178 : return integer_zero_node;
2302 : break;
2303 : }
2304 : return NULL_TREE;
2305 : }
2306 :
2307 :
2308 : /* Possibly warn about unreachable statements between switch's controlling
2309 : expression and the first case. Also warn about -ftrivial-auto-var-init
2310 : cannot initialize the auto variable under such situation.
2311 : SEQ is the body of a switch expression. */
2312 :
2313 : static void
2314 50003 : maybe_warn_switch_unreachable_and_auto_init (gimple_seq seq)
2315 : {
2316 60 : if ((!warn_switch_unreachable && !warn_trivial_auto_var_init)
2317 : /* This warning doesn't play well with Fortran when optimizations
2318 : are on. */
2319 49943 : || lang_GNU_Fortran ()
2320 96278 : || seq == NULL)
2321 3899 : return;
2322 :
2323 46104 : struct walk_stmt_info wi;
2324 :
2325 46104 : memset (&wi, 0, sizeof (wi));
2326 46104 : walk_gimple_seq (seq, warn_switch_unreachable_and_auto_init_r, NULL, &wi);
2327 : }
2328 :
2329 :
2330 : /* A label entry that pairs label and a location. */
2331 : struct label_entry
2332 : {
2333 : tree label;
2334 : location_t loc;
2335 : };
2336 :
2337 : /* Find LABEL in vector of label entries VEC. */
2338 :
2339 : static struct label_entry *
2340 12270 : find_label_entry (const auto_vec<struct label_entry> *vec, tree label)
2341 : {
2342 12270 : unsigned int i;
2343 12270 : struct label_entry *l;
2344 :
2345 23518 : FOR_EACH_VEC_ELT (*vec, i, l)
2346 20172 : if (l->label == label)
2347 : return l;
2348 : return NULL;
2349 : }
2350 :
2351 : /* Return true if LABEL, a LABEL_DECL, represents a case label
2352 : in a vector of labels CASES. */
2353 :
2354 : static bool
2355 16402 : case_label_p (const vec<tree> *cases, tree label)
2356 : {
2357 16402 : unsigned int i;
2358 16402 : tree l;
2359 :
2360 164739 : FOR_EACH_VEC_ELT (*cases, i, l)
2361 164405 : if (CASE_LABEL (l) == label)
2362 : return true;
2363 : return false;
2364 : }
2365 :
2366 : /* Find the last nondebug statement in a scope STMT. */
2367 :
2368 : static gimple *
2369 2273 : last_stmt_in_scope (gimple *stmt)
2370 : {
2371 4212 : if (!stmt)
2372 : return NULL;
2373 :
2374 6858 : auto last_stmt_in_seq = [] (gimple_seq s)
2375 : {
2376 2657 : gimple_seq_node n;
2377 2657 : for (n = gimple_seq_last (s);
2378 2662 : n && (is_gimple_debug (n)
2379 2649 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2380 110 : && gimple_call_internal_p (n, IFN_DEFERRED_INIT)));
2381 5 : n = n->prev)
2382 7 : if (n == s)
2383 : return (gimple *) NULL;
2384 : return (gimple *) n;
2385 : };
2386 :
2387 4201 : switch (gimple_code (stmt))
2388 : {
2389 1391 : case GIMPLE_BIND:
2390 1391 : {
2391 1391 : gbind *bind = as_a <gbind *> (stmt);
2392 1391 : stmt = last_stmt_in_seq (gimple_bind_body (bind));
2393 1391 : return last_stmt_in_scope (stmt);
2394 : }
2395 :
2396 718 : case GIMPLE_TRY:
2397 718 : {
2398 718 : gtry *try_stmt = as_a <gtry *> (stmt);
2399 718 : stmt = last_stmt_in_seq (gimple_try_eval (try_stmt));
2400 718 : gimple *last_eval = last_stmt_in_scope (stmt);
2401 718 : if (gimple_stmt_may_fallthru (last_eval)
2402 567 : && (last_eval == NULL
2403 564 : || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH))
2404 1278 : && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
2405 : {
2406 548 : stmt = last_stmt_in_seq (gimple_try_cleanup (try_stmt));
2407 548 : return last_stmt_in_scope (stmt);
2408 : }
2409 : else
2410 : return last_eval;
2411 : }
2412 :
2413 0 : case GIMPLE_DEBUG:
2414 0 : gcc_unreachable ();
2415 :
2416 : default:
2417 : return stmt;
2418 : }
2419 : }
2420 :
2421 : /* Collect labels that may fall through into LABELS and return the statement
2422 : preceding another case label, or a user-defined label. Store a location
2423 : useful to give warnings at *PREVLOC (usually the location of the returned
2424 : statement or of its surrounding scope). */
2425 :
2426 : static gimple *
2427 20993 : collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
2428 : auto_vec <struct label_entry> *labels,
2429 : location_t *prevloc)
2430 : {
2431 20993 : gimple *prev = NULL;
2432 :
2433 20993 : *prevloc = UNKNOWN_LOCATION;
2434 101914 : do
2435 : {
2436 101914 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND)
2437 : {
2438 : /* Recognize the special GIMPLE_BIND added by gimplify_switch_expr,
2439 : which starts on a GIMPLE_SWITCH and ends with a break label.
2440 : Handle that as a single statement that can fall through. */
2441 1452 : gbind *bind = as_a <gbind *> (gsi_stmt (*gsi_p));
2442 1452 : gimple *first = gimple_seq_first_stmt (gimple_bind_body (bind));
2443 1452 : gimple *last = gimple_seq_last_stmt (gimple_bind_body (bind));
2444 1446 : if (last
2445 1446 : && gimple_code (first) == GIMPLE_SWITCH
2446 1548 : && gimple_code (last) == GIMPLE_LABEL)
2447 : {
2448 102 : tree label = gimple_label_label (as_a <glabel *> (last));
2449 102 : if (SWITCH_BREAK_LABEL_P (label))
2450 : {
2451 102 : prev = bind;
2452 102 : gsi_next (gsi_p);
2453 102 : continue;
2454 : }
2455 : }
2456 : }
2457 101812 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
2458 101812 : || gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
2459 : {
2460 : /* Nested scope. Only look at the last statement of
2461 : the innermost scope. */
2462 1555 : location_t bind_loc = gimple_location (gsi_stmt (*gsi_p));
2463 1555 : gimple *last = last_stmt_in_scope (gsi_stmt (*gsi_p));
2464 1555 : if (last)
2465 : {
2466 1547 : prev = last;
2467 : /* It might be a label without a location. Use the
2468 : location of the scope then. */
2469 1547 : if (!gimple_has_location (prev))
2470 671 : *prevloc = bind_loc;
2471 : }
2472 1555 : gsi_next (gsi_p);
2473 1555 : continue;
2474 1555 : }
2475 :
2476 : /* Ifs are tricky. */
2477 100257 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
2478 : {
2479 7216 : gcond *cond_stmt = as_a <gcond *> (gsi_stmt (*gsi_p));
2480 7216 : tree false_lab = gimple_cond_false_label (cond_stmt);
2481 7216 : location_t if_loc = gimple_location (cond_stmt);
2482 :
2483 : /* If we have e.g.
2484 : if (i > 1) goto <D.2259>; else goto D;
2485 : we can't do much with the else-branch. */
2486 7216 : if (!DECL_ARTIFICIAL (false_lab))
2487 : break;
2488 :
2489 : /* Go on until the false label, then one step back. */
2490 54886 : for (; !gsi_end_p (*gsi_p); gsi_next (gsi_p))
2491 : {
2492 54886 : gimple *stmt = gsi_stmt (*gsi_p);
2493 54886 : if (gimple_code (stmt) == GIMPLE_LABEL
2494 54886 : && gimple_label_label (as_a <glabel *> (stmt)) == false_lab)
2495 : break;
2496 : }
2497 :
2498 : /* Not found? Oops. */
2499 7216 : if (gsi_end_p (*gsi_p))
2500 : break;
2501 :
2502 : /* A dead label can't fall through. */
2503 7216 : if (!UNUSED_LABEL_P (false_lab))
2504 : {
2505 7169 : struct label_entry l = { false_lab, if_loc };
2506 7169 : labels->safe_push (l);
2507 : }
2508 :
2509 : /* Go to the last statement of the then branch. */
2510 7216 : gsi_prev (gsi_p);
2511 :
2512 : /* if (i != 0) goto <D.1759>; else goto <D.1760>;
2513 : <D.1759>:
2514 : <stmt>;
2515 : goto <D.1761>;
2516 : <D.1760>:
2517 : */
2518 7216 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2519 7216 : && !gimple_has_location (gsi_stmt (*gsi_p)))
2520 : {
2521 : /* Look at the statement before, it might be
2522 : attribute fallthrough, in which case don't warn. */
2523 1614 : gsi_prev (gsi_p);
2524 1614 : bool fallthru_before_dest
2525 1614 : = gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
2526 1614 : gsi_next (gsi_p);
2527 1614 : tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
2528 1614 : if (!fallthru_before_dest)
2529 : {
2530 1557 : struct label_entry l = { goto_dest, if_loc };
2531 1557 : labels->safe_push (l);
2532 : }
2533 : }
2534 : /* This case is about
2535 : if (1 != 0) goto <D.2022>; else goto <D.2023>;
2536 : <D.2022>:
2537 : n = n + 1; // #1
2538 : <D.2023>: // #2
2539 : <D.1988>: // #3
2540 : where #2 is UNUSED_LABEL_P and we want to warn about #1 falling
2541 : through to #3. So set PREV to #1. */
2542 5602 : else if (UNUSED_LABEL_P (false_lab))
2543 47 : prev = gsi_stmt (*gsi_p);
2544 :
2545 : /* And move back. */
2546 7216 : gsi_next (gsi_p);
2547 : }
2548 :
2549 100257 : tree lab;
2550 : /* Remember the last statement. Skip labels that are of no interest
2551 : to us. */
2552 100257 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2553 : {
2554 12052 : tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (*gsi_p)));
2555 12052 : if (find_label_entry (labels, label))
2556 75433 : prev = gsi_stmt (*gsi_p);
2557 : }
2558 88205 : else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
2559 : ;
2560 88205 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2561 88205 : && gimple_call_internal_p (gsi_stmt (*gsi_p),
2562 : IFN_DEFERRED_INIT))
2563 : ;
2564 88199 : else if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_PREDICT)
2565 : ;
2566 86979 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2567 2223 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2568 324 : && (lab = gimple_goto_dest (gsi_stmt (*gsi_p)))
2569 324 : && TREE_CODE (lab) == LABEL_DECL
2570 87302 : && VACUOUS_INIT_LABEL_P (lab))
2571 : ;
2572 86979 : else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
2573 75433 : prev = gsi_stmt (*gsi_p);
2574 100257 : gsi_next (gsi_p);
2575 : }
2576 101914 : while (!gsi_end_p (*gsi_p)
2577 : /* Stop if we find a case or a user-defined label. */
2578 203828 : && (gimple_code (gsi_stmt (*gsi_p)) != GIMPLE_LABEL
2579 21758 : || !gimple_has_location (gsi_stmt (*gsi_p))));
2580 :
2581 20993 : if (prev && gimple_has_location (prev))
2582 20548 : *prevloc = gimple_location (prev);
2583 20993 : return prev;
2584 : }
2585 :
2586 : /* Return true if the switch fallthrough warning should occur. LABEL is
2587 : the label statement that we're falling through to. */
2588 :
2589 : static bool
2590 16915 : should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
2591 : {
2592 16915 : gimple_stmt_iterator gsi = *gsi_p;
2593 :
2594 : /* Don't warn if the label is marked with a "falls through" comment. */
2595 16915 : if (FALLTHROUGH_LABEL_P (label))
2596 : return false;
2597 :
2598 : /* Don't warn for non-case labels followed by a statement:
2599 : case 0:
2600 : foo ();
2601 : label:
2602 : bar ();
2603 : as these are likely intentional. */
2604 16143 : if (!case_label_p (&gimplify_ctxp->case_labels, label))
2605 : {
2606 : tree l;
2607 334 : while (!gsi_end_p (gsi)
2608 334 : && ((gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2609 259 : && (l
2610 259 : = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi))))
2611 259 : && !case_label_p (&gimplify_ctxp->case_labels, l))
2612 153 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2613 31 : && gimple_call_internal_p (gsi_stmt (gsi),
2614 : IFN_DEFERRED_INIT))))
2615 173 : gsi_next_nondebug (&gsi);
2616 161 : if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
2617 : return false;
2618 : }
2619 :
2620 : /* Don't warn for terminated branches, i.e. when the subsequent case labels
2621 : immediately breaks. */
2622 16068 : gsi = *gsi_p;
2623 :
2624 : /* Skip all immediately following labels. */
2625 35757 : while (!gsi_end_p (gsi)
2626 35757 : && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2627 16217 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT
2628 16008 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2629 735 : && gimple_call_internal_p (gsi_stmt (gsi),
2630 : IFN_DEFERRED_INIT))))
2631 19689 : gsi_next_nondebug (&gsi);
2632 :
2633 : /* { ... something; default:; } */
2634 16068 : if (gsi_end_p (gsi)
2635 : /* { ... something; default: break; } or
2636 : { ... something; default: goto L; } */
2637 16002 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
2638 : /* { ... something; default: return; } */
2639 30971 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
2640 : return false;
2641 :
2642 : return true;
2643 : }
2644 :
2645 : /* Callback for walk_gimple_seq. */
2646 :
2647 : static tree
2648 22001 : warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2649 : struct walk_stmt_info *)
2650 : {
2651 22001 : gimple *stmt = gsi_stmt (*gsi_p);
2652 :
2653 22001 : *handled_ops_p = true;
2654 22001 : switch (gimple_code (stmt))
2655 : {
2656 299 : case GIMPLE_TRY:
2657 299 : case GIMPLE_BIND:
2658 299 : case GIMPLE_CATCH:
2659 299 : case GIMPLE_EH_FILTER:
2660 299 : case GIMPLE_TRANSACTION:
2661 : /* Walk the sub-statements. */
2662 299 : *handled_ops_p = false;
2663 299 : break;
2664 :
2665 : /* Find a sequence of form:
2666 :
2667 : GIMPLE_LABEL
2668 : [...]
2669 : <may fallthru stmt>
2670 : GIMPLE_LABEL
2671 :
2672 : and possibly warn. */
2673 : case GIMPLE_LABEL:
2674 : {
2675 : /* Found a label. Skip all immediately following labels. */
2676 49284 : while (!gsi_end_p (*gsi_p)
2677 49284 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2678 28057 : gsi_next_nondebug (gsi_p);
2679 :
2680 : /* There might be no more statements. */
2681 21227 : if (gsi_end_p (*gsi_p))
2682 4305 : return integer_zero_node;
2683 :
2684 : /* Vector of labels that fall through. */
2685 20993 : auto_vec <struct label_entry> labels;
2686 20993 : location_t prevloc;
2687 20993 : gimple *prev = collect_fallthrough_labels (gsi_p, &labels, &prevloc);
2688 :
2689 : /* There might be no more statements. */
2690 20993 : if (gsi_end_p (*gsi_p))
2691 4071 : return integer_zero_node;
2692 :
2693 16922 : gimple *next = gsi_stmt (*gsi_p);
2694 16922 : tree label;
2695 : /* If what follows is a label, then we may have a fallthrough. */
2696 16922 : if (gimple_code (next) == GIMPLE_LABEL
2697 16922 : && gimple_has_location (next)
2698 16922 : && (label = gimple_label_label (as_a <glabel *> (next)))
2699 33844 : && prev != NULL)
2700 : {
2701 16915 : struct label_entry *l;
2702 16915 : bool warned_p = false;
2703 16915 : auto_diagnostic_group d;
2704 16915 : if (!should_warn_for_implicit_fallthrough (gsi_p, label))
2705 : /* Quiet. */;
2706 14876 : else if (gimple_code (prev) == GIMPLE_LABEL
2707 218 : && (label = gimple_label_label (as_a <glabel *> (prev)))
2708 15094 : && (l = find_label_entry (&labels, label)))
2709 198 : warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough_,
2710 : "this statement may fall through");
2711 14678 : else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH)
2712 : /* Try to be clever and don't warn when the statement
2713 : can't actually fall through. */
2714 14118 : && gimple_stmt_may_fallthru (prev)
2715 14979 : && prevloc != UNKNOWN_LOCATION)
2716 301 : warned_p = warning_at (prevloc,
2717 301 : OPT_Wimplicit_fallthrough_,
2718 : "this statement may fall through");
2719 499 : if (warned_p)
2720 499 : inform (gimple_location (next), "here");
2721 :
2722 : /* Mark this label as processed so as to prevent multiple
2723 : warnings in nested switches. */
2724 16915 : FALLTHROUGH_LABEL_P (label) = true;
2725 :
2726 : /* So that next warn_implicit_fallthrough_r will start looking for
2727 : a new sequence starting with this label. */
2728 16915 : gsi_prev (gsi_p);
2729 16915 : }
2730 4071 : }
2731 16922 : break;
2732 : default:
2733 : break;
2734 : }
2735 : return NULL_TREE;
2736 : }
2737 :
2738 : /* Warn when a switch case falls through. */
2739 :
2740 : static void
2741 50003 : maybe_warn_implicit_fallthrough (gimple_seq seq)
2742 : {
2743 50003 : if (!warn_implicit_fallthrough)
2744 45839 : return;
2745 :
2746 : /* This warning is meant for C/C++/ObjC/ObjC++ only. */
2747 4164 : if (!(lang_GNU_C ()
2748 1228 : || lang_GNU_CXX ()
2749 0 : || lang_GNU_OBJC ()))
2750 : return;
2751 :
2752 4164 : struct walk_stmt_info wi;
2753 4164 : memset (&wi, 0, sizeof (wi));
2754 4164 : walk_gimple_seq (seq, warn_implicit_fallthrough_r, NULL, &wi);
2755 : }
2756 :
2757 : /* Callback for walk_gimple_seq. */
2758 :
2759 : static tree
2760 3238248 : expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2761 : struct walk_stmt_info *wi)
2762 : {
2763 3238248 : gimple *stmt = gsi_stmt (*gsi_p);
2764 :
2765 3238248 : *handled_ops_p = true;
2766 3238248 : switch (gimple_code (stmt))
2767 : {
2768 148194 : case GIMPLE_TRY:
2769 148194 : case GIMPLE_BIND:
2770 148194 : case GIMPLE_CATCH:
2771 148194 : case GIMPLE_EH_FILTER:
2772 148194 : case GIMPLE_TRANSACTION:
2773 : /* Walk the sub-statements. */
2774 148194 : *handled_ops_p = false;
2775 148194 : break;
2776 249417 : case GIMPLE_CALL:
2777 249417 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2778 249417 : if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
2779 : {
2780 3021 : location_t loc = gimple_location (stmt);
2781 3021 : gsi_remove (gsi_p, true);
2782 3021 : wi->removed_stmt = true;
2783 :
2784 : /* nothrow flag is added by genericize_c_loop to mark fallthrough
2785 : statement at the end of some loop's body. Those should be
2786 : always diagnosed, either because they indeed don't precede
2787 : a case label or default label, or because the next statement
2788 : is not within the same iteration statement. */
2789 3021 : if ((stmt->subcode & GF_CALL_NOTHROW) != 0)
2790 : {
2791 12 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2792 : "a case label or default label");
2793 12 : break;
2794 : }
2795 :
2796 3009 : if (gsi_end_p (*gsi_p))
2797 : {
2798 32 : static_cast<location_t *>(wi->info)[0] = BUILTINS_LOCATION;
2799 32 : static_cast<location_t *>(wi->info)[1] = loc;
2800 32 : break;
2801 : }
2802 :
2803 2977 : bool found = false;
2804 :
2805 2977 : gimple_stmt_iterator gsi2 = *gsi_p;
2806 2977 : stmt = gsi_stmt (gsi2);
2807 2977 : tree lab;
2808 2977 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2809 1246 : && gimple_code (stmt) == GIMPLE_GOTO
2810 20 : && (lab = gimple_goto_dest (stmt))
2811 20 : && TREE_CODE (lab) == LABEL_DECL
2812 2997 : && VACUOUS_INIT_LABEL_P (lab))
2813 : {
2814 : /* Handle for C++ artificial -ftrivial-auto-var-init=
2815 : sequences. Those look like:
2816 : goto lab1;
2817 : lab2:;
2818 : v1 = .DEFERRED_INIT (...);
2819 : v2 = .DEFERRED_INIT (...);
2820 : lab3:;
2821 : v3 = .DEFERRED_INIT (...);
2822 : lab1:;
2823 : In this case, a case/default label can be either in between
2824 : the GIMPLE_GOTO and the corresponding GIMPLE_LABEL, if jumps
2825 : from the switch condition to the case/default label cross
2826 : vacuous initialization of some variables, or after the
2827 : corresponding GIMPLE_LABEL, if those jumps don't cross
2828 : any such initialization but there is an adjacent named label
2829 : which crosses such initialization. So, for the purpose of
2830 : this function, just ignore the goto but until reaching the
2831 : corresponding GIMPLE_LABEL allow also .DEFERRED_INIT
2832 : calls. */
2833 5 : gsi_next (&gsi2);
2834 : }
2835 2972 : else if (gimple_code (stmt) == GIMPLE_GOTO
2836 2972 : && !gimple_has_location (stmt))
2837 : {
2838 : /* Go on until the artificial label. */
2839 57 : tree goto_dest = gimple_goto_dest (stmt);
2840 414 : for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
2841 : {
2842 357 : if (gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL
2843 357 : && gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)))
2844 : == goto_dest)
2845 : break;
2846 : }
2847 :
2848 : /* Not found? Stop. */
2849 57 : if (gsi_end_p (gsi2))
2850 : break;
2851 :
2852 : /* Look one past it. */
2853 57 : gsi_next (&gsi2);
2854 : }
2855 :
2856 : /* We're looking for a case label or default label here. */
2857 3075 : while (!gsi_end_p (gsi2))
2858 : {
2859 3075 : stmt = gsi_stmt (gsi2);
2860 3075 : if (gimple_code (stmt) == GIMPLE_LABEL)
2861 : {
2862 3032 : tree label = gimple_label_label (as_a <glabel *> (stmt));
2863 3032 : if (gimple_has_location (stmt) && DECL_ARTIFICIAL (label))
2864 : {
2865 : found = true;
2866 : break;
2867 : }
2868 : }
2869 43 : else if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2870 : ;
2871 43 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2872 43 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2873 : ;
2874 43 : else if (!is_gimple_debug (stmt))
2875 : /* Anything else is not expected. */
2876 : break;
2877 98 : gsi_next (&gsi2);
2878 : }
2879 2977 : if (!found)
2880 23 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2881 : "a case label or default label");
2882 : }
2883 : break;
2884 2840637 : default:
2885 2840637 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2886 2840637 : break;
2887 : }
2888 3238248 : return NULL_TREE;
2889 : }
2890 :
2891 : /* Expand all FALLTHROUGH () calls in SEQ. */
2892 :
2893 : static void
2894 48315 : expand_FALLTHROUGH (gimple_seq *seq_p)
2895 : {
2896 48315 : auto_urlify_attributes sentinel;
2897 :
2898 48315 : struct walk_stmt_info wi;
2899 48315 : location_t loc[2];
2900 48315 : memset (&wi, 0, sizeof (wi));
2901 48315 : loc[0] = UNKNOWN_LOCATION;
2902 48315 : loc[1] = UNKNOWN_LOCATION;
2903 48315 : wi.info = (void *) &loc[0];
2904 48315 : walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
2905 48315 : if (loc[0] != UNKNOWN_LOCATION)
2906 : /* We've found [[fallthrough]]; at the end of a switch, which the C++
2907 : standard says is ill-formed; see [dcl.attr.fallthrough]. */
2908 8 : pedwarn (loc[1], 0, "attribute %<fallthrough%> not preceding "
2909 : "a case label or default label");
2910 48315 : }
2911 :
2912 :
2913 : /* Gimplify a SWITCH_EXPR, and collect the vector of labels it can
2914 : branch to. */
2915 :
2916 : static enum gimplify_status
2917 50003 : gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
2918 : {
2919 50003 : tree switch_expr = *expr_p;
2920 50003 : gimple_seq switch_body_seq = NULL;
2921 50003 : enum gimplify_status ret;
2922 50003 : tree index_type = TREE_TYPE (switch_expr);
2923 50003 : if (index_type == NULL_TREE)
2924 11414 : index_type = TREE_TYPE (SWITCH_COND (switch_expr));
2925 :
2926 50003 : ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
2927 : fb_rvalue);
2928 50003 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
2929 : return ret;
2930 :
2931 50003 : if (SWITCH_BODY (switch_expr))
2932 : {
2933 50003 : vec<tree> labels;
2934 50003 : vec<tree> saved_labels;
2935 50003 : hash_set<tree> *saved_live_switch_vars = NULL;
2936 50003 : tree default_case = NULL_TREE;
2937 50003 : gswitch *switch_stmt;
2938 :
2939 : /* Save old labels, get new ones from body, then restore the old
2940 : labels. Save all the things from the switch body to append after. */
2941 50003 : saved_labels = gimplify_ctxp->case_labels;
2942 50003 : gimplify_ctxp->case_labels.create (8);
2943 :
2944 : /* Do not create live_switch_vars if SWITCH_BODY is not a BIND_EXPR. */
2945 50003 : saved_live_switch_vars = gimplify_ctxp->live_switch_vars;
2946 50003 : tree_code body_type = TREE_CODE (SWITCH_BODY (switch_expr));
2947 50003 : if (body_type == BIND_EXPR || body_type == STATEMENT_LIST)
2948 49719 : gimplify_ctxp->live_switch_vars = new hash_set<tree> (4);
2949 : else
2950 284 : gimplify_ctxp->live_switch_vars = NULL;
2951 :
2952 50003 : bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
2953 50003 : gimplify_ctxp->in_switch_expr = true;
2954 :
2955 50003 : gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
2956 :
2957 50003 : gimplify_ctxp->in_switch_expr = old_in_switch_expr;
2958 50003 : maybe_warn_switch_unreachable_and_auto_init (switch_body_seq);
2959 50003 : maybe_warn_implicit_fallthrough (switch_body_seq);
2960 : /* Only do this for the outermost GIMPLE_SWITCH. */
2961 50003 : if (!gimplify_ctxp->in_switch_expr)
2962 48315 : expand_FALLTHROUGH (&switch_body_seq);
2963 :
2964 50003 : labels = gimplify_ctxp->case_labels;
2965 50003 : gimplify_ctxp->case_labels = saved_labels;
2966 :
2967 50003 : if (gimplify_ctxp->live_switch_vars)
2968 : {
2969 49719 : gcc_assert (gimplify_ctxp->live_switch_vars->is_empty ());
2970 49719 : delete gimplify_ctxp->live_switch_vars;
2971 : }
2972 50003 : gimplify_ctxp->live_switch_vars = saved_live_switch_vars;
2973 :
2974 50003 : preprocess_case_label_vec_for_gimple (labels, index_type,
2975 : &default_case);
2976 :
2977 50003 : bool add_bind = false;
2978 50003 : if (!default_case)
2979 : {
2980 14885 : glabel *new_default;
2981 :
2982 14885 : default_case
2983 14885 : = build_case_label (NULL_TREE, NULL_TREE,
2984 : create_artificial_label (UNKNOWN_LOCATION));
2985 14885 : if (old_in_switch_expr)
2986 : {
2987 1085 : SWITCH_BREAK_LABEL_P (CASE_LABEL (default_case)) = 1;
2988 1085 : add_bind = true;
2989 : }
2990 14885 : new_default = gimple_build_label (CASE_LABEL (default_case));
2991 14885 : gimplify_seq_add_stmt (&switch_body_seq, new_default);
2992 : }
2993 35118 : else if (old_in_switch_expr)
2994 : {
2995 603 : gimple *last = gimple_seq_last_stmt (switch_body_seq);
2996 603 : if (last && gimple_code (last) == GIMPLE_LABEL)
2997 : {
2998 338 : tree label = gimple_label_label (as_a <glabel *> (last));
2999 338 : if (SWITCH_BREAK_LABEL_P (label))
3000 50003 : add_bind = true;
3001 : }
3002 : }
3003 :
3004 50003 : switch_stmt = gimple_build_switch (SWITCH_COND (switch_expr),
3005 : default_case, labels);
3006 50003 : gimple_set_location (switch_stmt, EXPR_LOCATION (switch_expr));
3007 : /* For the benefit of -Wimplicit-fallthrough, if switch_body_seq
3008 : ends with a GIMPLE_LABEL holding SWITCH_BREAK_LABEL_P LABEL_DECL,
3009 : wrap the GIMPLE_SWITCH up to that GIMPLE_LABEL into a GIMPLE_BIND,
3010 : so that we can easily find the start and end of the switch
3011 : statement. */
3012 50003 : if (add_bind)
3013 : {
3014 1422 : gimple_seq bind_body = NULL;
3015 1422 : gimplify_seq_add_stmt (&bind_body, switch_stmt);
3016 1422 : gimple_seq_add_seq (&bind_body, switch_body_seq);
3017 1422 : gbind *bind = gimple_build_bind (NULL_TREE, bind_body, NULL_TREE);
3018 1422 : gimple_set_location (bind, EXPR_LOCATION (switch_expr));
3019 1422 : gimplify_seq_add_stmt (pre_p, bind);
3020 : }
3021 : else
3022 : {
3023 48581 : gimplify_seq_add_stmt (pre_p, switch_stmt);
3024 48581 : gimplify_seq_add_seq (pre_p, switch_body_seq);
3025 : }
3026 50003 : labels.release ();
3027 : }
3028 : else
3029 0 : gcc_unreachable ();
3030 :
3031 50003 : return GS_ALL_DONE;
3032 : }
3033 :
3034 : /* Gimplify the LABEL_EXPR pointed to by EXPR_P. */
3035 :
3036 : static enum gimplify_status
3037 2592125 : gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
3038 : {
3039 2592125 : gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
3040 : == current_function_decl);
3041 :
3042 2592125 : tree label = LABEL_EXPR_LABEL (*expr_p);
3043 2592125 : glabel *label_stmt = gimple_build_label (label);
3044 2592125 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3045 2592125 : gimplify_seq_add_stmt (pre_p, label_stmt);
3046 :
3047 2592125 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3048 21 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3049 : NOT_TAKEN));
3050 2592104 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3051 11 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3052 : TAKEN));
3053 :
3054 2592125 : return GS_ALL_DONE;
3055 : }
3056 :
3057 : /* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
3058 :
3059 : static enum gimplify_status
3060 1037861 : gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
3061 : {
3062 1037861 : struct gimplify_ctx *ctxp;
3063 1037861 : glabel *label_stmt;
3064 :
3065 : /* Invalid programs can play Duff's Device type games with, for example,
3066 : #pragma omp parallel. At least in the C front end, we don't
3067 : detect such invalid branches until after gimplification, in the
3068 : diagnose_omp_blocks pass. */
3069 1037871 : for (ctxp = gimplify_ctxp; ; ctxp = ctxp->prev_context)
3070 1037871 : if (ctxp->case_labels.exists ())
3071 : break;
3072 :
3073 1037861 : tree label = CASE_LABEL (*expr_p);
3074 1037861 : label_stmt = gimple_build_label (label);
3075 1037861 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3076 1037861 : ctxp->case_labels.safe_push (*expr_p);
3077 1037861 : gimplify_seq_add_stmt (pre_p, label_stmt);
3078 :
3079 1037861 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3080 16 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3081 : NOT_TAKEN));
3082 1037845 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3083 20 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3084 : TAKEN));
3085 :
3086 1037861 : return GS_ALL_DONE;
3087 : }
3088 :
3089 : /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first
3090 : if necessary. */
3091 :
3092 : tree
3093 1788940 : build_and_jump (tree *label_p)
3094 : {
3095 1788940 : if (label_p == NULL)
3096 : /* If there's nowhere to jump, just fall through. */
3097 : return NULL_TREE;
3098 :
3099 1212821 : if (*label_p == NULL_TREE)
3100 : {
3101 694338 : tree label = create_artificial_label (UNKNOWN_LOCATION);
3102 694338 : *label_p = label;
3103 : }
3104 :
3105 1212821 : return build1 (GOTO_EXPR, void_type_node, *label_p);
3106 : }
3107 :
3108 : /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
3109 : This also involves building a label to jump to and communicating it to
3110 : gimplify_loop_expr through gimplify_ctxp->exit_label. */
3111 :
3112 : static enum gimplify_status
3113 3153 : gimplify_exit_expr (tree *expr_p)
3114 : {
3115 3153 : tree cond = TREE_OPERAND (*expr_p, 0);
3116 3153 : tree expr;
3117 :
3118 3153 : expr = build_and_jump (&gimplify_ctxp->exit_label);
3119 3153 : expr = build3 (COND_EXPR, void_type_node, cond, expr, NULL_TREE);
3120 3153 : *expr_p = expr;
3121 :
3122 3153 : return GS_OK;
3123 : }
3124 :
3125 : /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is
3126 : different from its canonical type, wrap the whole thing inside a
3127 : NOP_EXPR and force the type of the COMPONENT_REF to be the canonical
3128 : type.
3129 :
3130 : The canonical type of a COMPONENT_REF is the type of the field being
3131 : referenced--unless the field is a bit-field which can be read directly
3132 : in a smaller mode, in which case the canonical type is the
3133 : sign-appropriate type corresponding to that mode. */
3134 :
3135 : static void
3136 18820912 : canonicalize_component_ref (tree *expr_p)
3137 : {
3138 18820912 : tree expr = *expr_p;
3139 18820912 : tree type;
3140 :
3141 18820912 : gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
3142 :
3143 18820912 : if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
3144 7583379 : type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
3145 : else
3146 11237533 : type = TREE_TYPE (TREE_OPERAND (expr, 1));
3147 :
3148 : /* One could argue that all the stuff below is not necessary for
3149 : the non-bitfield case and declare it a FE error if type
3150 : adjustment would be needed. */
3151 18820912 : if (TREE_TYPE (expr) != type)
3152 : {
3153 : #ifdef ENABLE_TYPES_CHECKING
3154 798478 : tree old_type = TREE_TYPE (expr);
3155 : #endif
3156 798478 : int type_quals;
3157 :
3158 : /* We need to preserve qualifiers and propagate them from
3159 : operand 0. */
3160 798478 : type_quals = TYPE_QUALS (type)
3161 798478 : | TYPE_QUALS (TREE_TYPE (TREE_OPERAND (expr, 0)));
3162 798478 : if (TYPE_QUALS (type) != type_quals)
3163 798309 : type = build_qualified_type (TYPE_MAIN_VARIANT (type), type_quals);
3164 :
3165 : /* Set the type of the COMPONENT_REF to the underlying type. */
3166 798478 : TREE_TYPE (expr) = type;
3167 :
3168 : #ifdef ENABLE_TYPES_CHECKING
3169 : /* It is now a FE error, if the conversion from the canonical
3170 : type to the original expression type is not useless. */
3171 798478 : gcc_assert (useless_type_conversion_p (old_type, type));
3172 : #endif
3173 : }
3174 18820912 : }
3175 :
3176 : /* If a NOP conversion is changing a pointer to array of foo to a pointer
3177 : to foo, embed that change in the ADDR_EXPR by converting
3178 : T array[U];
3179 : (T *)&array
3180 : ==>
3181 : &array[L]
3182 : where L is the lower bound. For simplicity, only do this for constant
3183 : lower bound.
3184 : The constraint is that the type of &array[L] is trivially convertible
3185 : to T *. */
3186 :
3187 : static void
3188 553402 : canonicalize_addr_expr (tree *expr_p)
3189 : {
3190 553402 : tree expr = *expr_p;
3191 553402 : tree addr_expr = TREE_OPERAND (expr, 0);
3192 553402 : tree datype, ddatype, pddatype;
3193 :
3194 : /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
3195 1106458 : if (!POINTER_TYPE_P (TREE_TYPE (expr))
3196 553402 : || TREE_CODE (addr_expr) != ADDR_EXPR)
3197 : return;
3198 :
3199 : /* The addr_expr type should be a pointer to an array. */
3200 346 : datype = TREE_TYPE (TREE_TYPE (addr_expr));
3201 346 : if (TREE_CODE (datype) != ARRAY_TYPE)
3202 : return;
3203 :
3204 : /* The pointer to element type shall be trivially convertible to
3205 : the expression pointer type. */
3206 28 : ddatype = TREE_TYPE (datype);
3207 28 : pddatype = build_pointer_type (ddatype);
3208 28 : if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
3209 : pddatype))
3210 : return;
3211 :
3212 : /* The lower bound and element sizes must be constant. */
3213 0 : if (!TYPE_SIZE_UNIT (ddatype)
3214 0 : || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
3215 0 : || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
3216 0 : || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
3217 : return;
3218 :
3219 : /* All checks succeeded. Build a new node to merge the cast. */
3220 0 : *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
3221 0 : TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
3222 : NULL_TREE, NULL_TREE);
3223 0 : *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
3224 :
3225 : /* We can have stripped a required restrict qualifier above. */
3226 0 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
3227 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
3228 : }
3229 :
3230 : /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
3231 : underneath as appropriate. */
3232 :
3233 : static enum gimplify_status
3234 13217497 : gimplify_conversion (tree *expr_p)
3235 : {
3236 13217497 : location_t loc = EXPR_LOCATION (*expr_p);
3237 13217497 : gcc_assert (CONVERT_EXPR_P (*expr_p));
3238 :
3239 : /* Then strip away all but the outermost conversion. */
3240 13217497 : STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
3241 :
3242 : /* And remove the outermost conversion if it's useless. */
3243 13217497 : if (tree_ssa_useless_type_conversion (*expr_p))
3244 0 : *expr_p = TREE_OPERAND (*expr_p, 0);
3245 :
3246 : /* If we still have a conversion at the toplevel,
3247 : then canonicalize some constructs. */
3248 13217497 : if (CONVERT_EXPR_P (*expr_p))
3249 : {
3250 13217497 : tree sub = TREE_OPERAND (*expr_p, 0);
3251 :
3252 : /* If a NOP conversion is changing the type of a COMPONENT_REF
3253 : expression, then canonicalize its type now in order to expose more
3254 : redundant conversions. */
3255 13217497 : if (TREE_CODE (sub) == COMPONENT_REF)
3256 273879 : canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0));
3257 :
3258 : /* If a NOP conversion is changing a pointer to array of foo
3259 : to a pointer to foo, embed that change in the ADDR_EXPR. */
3260 12943618 : else if (TREE_CODE (sub) == ADDR_EXPR)
3261 553402 : canonicalize_addr_expr (expr_p);
3262 : }
3263 :
3264 : /* If we have a conversion to a non-register type force the
3265 : use of a VIEW_CONVERT_EXPR instead. */
3266 13217497 : if (CONVERT_EXPR_P (*expr_p) && !is_gimple_reg_type (TREE_TYPE (*expr_p)))
3267 90 : *expr_p = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p),
3268 90 : TREE_OPERAND (*expr_p, 0));
3269 :
3270 : /* Canonicalize CONVERT_EXPR to NOP_EXPR. */
3271 13217497 : if (TREE_CODE (*expr_p) == CONVERT_EXPR)
3272 231181 : TREE_SET_CODE (*expr_p, NOP_EXPR);
3273 :
3274 13217497 : return GS_OK;
3275 : }
3276 :
3277 : /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
3278 : DECL_VALUE_EXPR, and it's worth re-examining things. */
3279 :
3280 : static enum gimplify_status
3281 129223147 : gimplify_var_or_parm_decl (tree *expr_p)
3282 : {
3283 129223147 : tree decl = *expr_p;
3284 :
3285 : /* ??? If this is a local variable, and it has not been seen in any
3286 : outer BIND_EXPR, then it's probably the result of a duplicate
3287 : declaration, for which we've already issued an error. It would
3288 : be really nice if the front end wouldn't leak these at all.
3289 : Currently the only known culprit is C++ destructors, as seen
3290 : in g++.old-deja/g++.jason/binding.C.
3291 : Another possible culpit are size expressions for variably modified
3292 : types which are lost in the FE or not gimplified correctly. */
3293 129223147 : if (VAR_P (decl)
3294 100615401 : && !DECL_SEEN_IN_BIND_EXPR_P (decl)
3295 17200127 : && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
3296 129283081 : && decl_function_context (decl) == current_function_decl)
3297 : {
3298 75 : gcc_assert (seen_error ());
3299 : return GS_ERROR;
3300 : }
3301 :
3302 : /* When within an OMP context, notice uses of variables. */
3303 129223072 : if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
3304 : return GS_ALL_DONE;
3305 :
3306 : /* If the decl is an alias for another expression, substitute it now. */
3307 129217252 : if (DECL_HAS_VALUE_EXPR_P (decl))
3308 : {
3309 454366 : *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
3310 454366 : return GS_OK;
3311 : }
3312 :
3313 : return GS_ALL_DONE;
3314 : }
3315 :
3316 : /* Recalculate the value of the TREE_SIDE_EFFECTS flag for T. */
3317 :
3318 : static void
3319 112467634 : recalculate_side_effects (tree t)
3320 : {
3321 112467634 : enum tree_code code = TREE_CODE (t);
3322 112467634 : int len = TREE_OPERAND_LENGTH (t);
3323 112467634 : int i;
3324 :
3325 112467634 : switch (TREE_CODE_CLASS (code))
3326 : {
3327 668283 : case tcc_expression:
3328 668283 : switch (code)
3329 : {
3330 : case INIT_EXPR:
3331 : case MODIFY_EXPR:
3332 : case VA_ARG_EXPR:
3333 : case PREDECREMENT_EXPR:
3334 : case PREINCREMENT_EXPR:
3335 : case POSTDECREMENT_EXPR:
3336 : case POSTINCREMENT_EXPR:
3337 : /* All of these have side-effects, no matter what their
3338 : operands are. */
3339 : return;
3340 :
3341 : default:
3342 : break;
3343 : }
3344 : /* Fall through. */
3345 :
3346 112467632 : case tcc_comparison: /* a comparison expression */
3347 112467632 : case tcc_unary: /* a unary arithmetic expression */
3348 112467632 : case tcc_binary: /* a binary arithmetic expression */
3349 112467632 : case tcc_reference: /* a reference */
3350 112467632 : case tcc_vl_exp: /* a function call */
3351 112467632 : TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
3352 366220297 : for (i = 0; i < len; ++i)
3353 : {
3354 253752665 : tree op = TREE_OPERAND (t, i);
3355 253752665 : if (op && TREE_SIDE_EFFECTS (op))
3356 1291200 : TREE_SIDE_EFFECTS (t) = 1;
3357 : }
3358 : break;
3359 :
3360 : case tcc_constant:
3361 : /* No side-effects. */
3362 : return;
3363 :
3364 2 : default:
3365 2 : if (code == SSA_NAME)
3366 : /* No side-effects. */
3367 : return;
3368 0 : gcc_unreachable ();
3369 : }
3370 : }
3371 :
3372 : /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
3373 : node *EXPR_P.
3374 :
3375 : compound_lval
3376 : : min_lval '[' val ']'
3377 : | min_lval '.' ID
3378 : | compound_lval '[' val ']'
3379 : | compound_lval '.' ID
3380 :
3381 : This is not part of the original SIMPLE definition, which separates
3382 : array and member references, but it seems reasonable to handle them
3383 : together. Also, this way we don't run into problems with union
3384 : aliasing; gcc requires that for accesses through a union to alias, the
3385 : union reference must be explicit, which was not always the case when we
3386 : were splitting up array and member refs.
3387 :
3388 : PRE_P points to the sequence where side effects that must happen before
3389 : *EXPR_P should be stored.
3390 :
3391 : POST_P points to the sequence where side effects that must happen after
3392 : *EXPR_P should be stored. */
3393 :
3394 : static enum gimplify_status
3395 30521507 : gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3396 : fallback_t fallback)
3397 : {
3398 30521507 : tree *p;
3399 30521507 : enum gimplify_status ret = GS_ALL_DONE, tret;
3400 30521507 : int i;
3401 30521507 : location_t loc = EXPR_LOCATION (*expr_p);
3402 30521507 : tree expr = *expr_p;
3403 :
3404 : /* Create a stack of the subexpressions so later we can walk them in
3405 : order from inner to outer. */
3406 30521507 : auto_vec<tree, 10> expr_stack;
3407 :
3408 : /* We can handle anything that get_inner_reference can deal with. */
3409 73589841 : for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
3410 : {
3411 43068334 : restart:
3412 : /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
3413 73655707 : if (TREE_CODE (*p) == INDIRECT_REF)
3414 4013080 : *p = fold_indirect_ref_loc (loc, *p);
3415 :
3416 73655707 : if (handled_component_p (*p))
3417 : ;
3418 : /* Expand DECL_VALUE_EXPR now. In some cases that may expose
3419 : additional COMPONENT_REFs. */
3420 13463755 : else if ((VAR_P (*p) || TREE_CODE (*p) == PARM_DECL)
3421 32039362 : && gimplify_var_or_parm_decl (p) == GS_OK)
3422 65866 : goto restart;
3423 : else
3424 : break;
3425 :
3426 43068334 : expr_stack.safe_push (*p);
3427 : }
3428 :
3429 30521507 : gcc_assert (expr_stack.length ());
3430 :
3431 : /* Now EXPR_STACK is a stack of pointers to all the refs we've
3432 : walked through and P points to the innermost expression.
3433 :
3434 : Java requires that we elaborated nodes in source order. That
3435 : means we must gimplify the inner expression followed by each of
3436 : the indices, in order. But we can't gimplify the inner
3437 : expression until we deal with any variable bounds, sizes, or
3438 : positions in order to deal with PLACEHOLDER_EXPRs.
3439 :
3440 : The base expression may contain a statement expression that
3441 : has declarations used in size expressions, so has to be
3442 : gimplified before gimplifying the size expressions.
3443 :
3444 : So we do this in three steps. First we deal with variable
3445 : bounds, sizes, and positions, then we gimplify the base and
3446 : ensure it is memory if needed, then we deal with the annotations
3447 : for any variables in the components and any indices, from left
3448 : to right. */
3449 :
3450 30521507 : bool need_non_reg = false;
3451 73589838 : for (i = expr_stack.length () - 1; i >= 0; i--)
3452 : {
3453 43068334 : tree t = expr_stack[i];
3454 :
3455 43068334 : if (error_operand_p (TREE_OPERAND (t, 0)))
3456 : return GS_ERROR;
3457 :
3458 43068331 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3459 : {
3460 : /* Deal with the low bound and element type size and put them into
3461 : the ARRAY_REF. If these values are set, they have already been
3462 : gimplified. */
3463 9028346 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3464 : {
3465 8961407 : tree low = unshare_expr (array_ref_low_bound (t));
3466 8961407 : if (!is_gimple_min_invariant (low))
3467 : {
3468 0 : TREE_OPERAND (t, 2) = low;
3469 : }
3470 : }
3471 :
3472 9028346 : if (TREE_OPERAND (t, 3) == NULL_TREE)
3473 : {
3474 9014821 : tree elmt_size = array_ref_element_size (t);
3475 9014821 : if (!is_gimple_min_invariant (elmt_size))
3476 : {
3477 8497 : elmt_size = unshare_expr (elmt_size);
3478 8497 : tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
3479 8497 : tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
3480 :
3481 : /* Divide the element size by the alignment of the element
3482 : type (above). */
3483 8497 : elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR,
3484 : elmt_size, factor);
3485 :
3486 8497 : TREE_OPERAND (t, 3) = elmt_size;
3487 : }
3488 : }
3489 : need_non_reg = true;
3490 : }
3491 34039985 : else if (TREE_CODE (t) == COMPONENT_REF)
3492 : {
3493 : /* Set the field offset into T and gimplify it. */
3494 32735775 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3495 : {
3496 32735396 : tree offset = component_ref_field_offset (t);
3497 32735396 : if (!is_gimple_min_invariant (offset))
3498 : {
3499 287 : offset = unshare_expr (offset);
3500 287 : tree field = TREE_OPERAND (t, 1);
3501 287 : tree factor
3502 287 : = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
3503 :
3504 : /* Divide the offset by its alignment. */
3505 287 : offset = size_binop_loc (loc, EXACT_DIV_EXPR,
3506 : offset, factor);
3507 :
3508 287 : TREE_OPERAND (t, 2) = offset;
3509 : }
3510 : }
3511 : need_non_reg = true;
3512 : }
3513 1304210 : else if (!is_gimple_reg_type (TREE_TYPE (t)))
3514 : /* When the result of an operation, in particular a VIEW_CONVERT_EXPR
3515 : is a non-register type then require the base object to be a
3516 : non-register as well. */
3517 42045086 : need_non_reg = true;
3518 : }
3519 :
3520 : /* Step 2 is to gimplify the base expression. Make sure lvalue is set
3521 : so as to match the min_lval predicate. Failure to do so may result
3522 : in the creation of large aggregate temporaries. */
3523 30521504 : tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
3524 : fallback | fb_lvalue);
3525 30521504 : ret = MIN (ret, tret);
3526 30521504 : if (ret == GS_ERROR)
3527 : return GS_ERROR;
3528 :
3529 : /* Step 2a: if we have component references we do not support on
3530 : registers then make sure the base isn't a register. Of course
3531 : we can only do so if an rvalue is OK. */
3532 30521504 : if (need_non_reg && (fallback & fb_rvalue))
3533 22733038 : prepare_gimple_addressable (p, pre_p);
3534 :
3535 :
3536 : /* Step 3: gimplify size expressions and the indices and operands of
3537 : ARRAY_REF. During this loop we also remove any useless conversions.
3538 : If we operate on a register also make sure to properly gimplify
3539 : to individual operations. */
3540 :
3541 30521504 : bool reg_operations = is_gimple_reg (*p);
3542 73589835 : for (; expr_stack.length () > 0; )
3543 : {
3544 43068331 : tree t = expr_stack.pop ();
3545 :
3546 43068331 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3547 : {
3548 9028346 : gcc_assert (!reg_operations);
3549 :
3550 : /* Gimplify the low bound and element type size. */
3551 9028346 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3552 : is_gimple_reg, fb_rvalue);
3553 9028346 : ret = MIN (ret, tret);
3554 :
3555 9028346 : tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
3556 : is_gimple_reg, fb_rvalue);
3557 9028346 : ret = MIN (ret, tret);
3558 :
3559 : /* Gimplify the dimension. */
3560 9028346 : tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
3561 : is_gimple_val, fb_rvalue);
3562 9028346 : ret = MIN (ret, tret);
3563 : }
3564 34039985 : else if (TREE_CODE (t) == COMPONENT_REF)
3565 : {
3566 32735775 : gcc_assert (!reg_operations);
3567 :
3568 32735775 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3569 : is_gimple_reg, fb_rvalue);
3570 32735775 : ret = MIN (ret, tret);
3571 : }
3572 1304210 : else if (reg_operations)
3573 : {
3574 904502 : tret = gimplify_expr (&TREE_OPERAND (t, 0), pre_p, post_p,
3575 : is_gimple_val, fb_rvalue);
3576 1304210 : ret = MIN (ret, tret);
3577 : }
3578 :
3579 43068331 : STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
3580 :
3581 : /* The innermost expression P may have originally had
3582 : TREE_SIDE_EFFECTS set which would have caused all the outer
3583 : expressions in *EXPR_P leading to P to also have had
3584 : TREE_SIDE_EFFECTS set. */
3585 43068331 : recalculate_side_effects (t);
3586 : }
3587 :
3588 : /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */
3589 30521504 : if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
3590 : {
3591 18547033 : canonicalize_component_ref (expr_p);
3592 : }
3593 :
3594 30521504 : expr_stack.release ();
3595 :
3596 30521504 : gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
3597 :
3598 : return ret;
3599 30521507 : }
3600 :
3601 : /* Gimplify the self modifying expression pointed to by EXPR_P
3602 : (++, --, +=, -=).
3603 :
3604 : PRE_P points to the list where side effects that must happen before
3605 : *EXPR_P should be stored.
3606 :
3607 : POST_P points to the list where side effects that must happen after
3608 : *EXPR_P should be stored.
3609 :
3610 : WANT_VALUE is nonzero iff we want to use the value of this expression
3611 : in another expression.
3612 :
3613 : ARITH_TYPE is the type the computation should be performed in. */
3614 :
3615 : enum gimplify_status
3616 1147908 : gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3617 : bool want_value, tree arith_type)
3618 : {
3619 1147908 : enum tree_code code;
3620 1147908 : tree lhs, lvalue, rhs, t1;
3621 1147908 : gimple_seq post = NULL, *orig_post_p = post_p;
3622 1147908 : bool postfix;
3623 1147908 : enum tree_code arith_code;
3624 1147908 : enum gimplify_status ret;
3625 1147908 : location_t loc = EXPR_LOCATION (*expr_p);
3626 :
3627 1147908 : code = TREE_CODE (*expr_p);
3628 :
3629 1147908 : gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
3630 : || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
3631 :
3632 : /* Prefix or postfix? */
3633 1147908 : if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
3634 : /* Faster to treat as prefix if result is not used. */
3635 : postfix = want_value;
3636 : else
3637 : postfix = false;
3638 :
3639 : /* For postfix, make sure the inner expression's post side effects
3640 : are executed after side effects from this expression. */
3641 409190 : if (postfix)
3642 1147908 : post_p = &post;
3643 :
3644 : /* Add or subtract? */
3645 1147908 : if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
3646 : arith_code = PLUS_EXPR;
3647 : else
3648 45025 : arith_code = MINUS_EXPR;
3649 :
3650 : /* Gimplify the LHS into a GIMPLE lvalue. */
3651 1147908 : lvalue = TREE_OPERAND (*expr_p, 0);
3652 1147908 : ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
3653 1147908 : if (ret == GS_ERROR)
3654 : return ret;
3655 :
3656 : /* Extract the operands to the arithmetic operation. */
3657 1147903 : lhs = lvalue;
3658 1147903 : rhs = TREE_OPERAND (*expr_p, 1);
3659 :
3660 : /* For postfix operator, we evaluate the LHS to an rvalue and then use
3661 : that as the result value and in the postqueue operation. */
3662 1147903 : if (postfix)
3663 : {
3664 188761 : ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
3665 188761 : if (ret == GS_ERROR)
3666 : return ret;
3667 :
3668 188761 : lhs = get_initialized_tmp_var (lhs, pre_p);
3669 : }
3670 :
3671 : /* For POINTERs increment, use POINTER_PLUS_EXPR. */
3672 1147903 : if (POINTER_TYPE_P (TREE_TYPE (lhs)))
3673 : {
3674 236916 : rhs = convert_to_ptrofftype_loc (loc, rhs);
3675 236916 : if (arith_code == MINUS_EXPR)
3676 9865 : rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
3677 236916 : t1 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
3678 : }
3679 : else
3680 910987 : t1 = fold_convert (TREE_TYPE (*expr_p),
3681 : fold_build2 (arith_code, arith_type,
3682 : fold_convert (arith_type, lhs),
3683 : fold_convert (arith_type, rhs)));
3684 :
3685 1147903 : if (postfix)
3686 : {
3687 188761 : gimplify_assign (lvalue, t1, pre_p);
3688 188761 : gimplify_seq_add_seq (orig_post_p, post);
3689 188761 : *expr_p = lhs;
3690 188761 : return GS_ALL_DONE;
3691 : }
3692 : else
3693 : {
3694 959142 : *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
3695 959142 : return GS_OK;
3696 : }
3697 : }
3698 :
3699 : /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
3700 :
3701 : static void
3702 82869846 : maybe_with_size_expr (tree *expr_p)
3703 : {
3704 82869846 : tree expr = *expr_p;
3705 82869846 : tree type = TREE_TYPE (expr);
3706 82869846 : tree size;
3707 :
3708 : /* If we've already wrapped this or the type is error_mark_node, we can't do
3709 : anything. */
3710 82869846 : if (TREE_CODE (expr) == WITH_SIZE_EXPR
3711 82869721 : || type == error_mark_node)
3712 : return;
3713 :
3714 : /* If the size isn't known or is a constant, we have nothing to do. */
3715 82869573 : size = TYPE_SIZE_UNIT (type);
3716 82869573 : if (!size || poly_int_tree_p (size))
3717 : return;
3718 :
3719 : /* Otherwise, make a WITH_SIZE_EXPR. */
3720 1692 : size = unshare_expr (size);
3721 1692 : size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
3722 1692 : *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
3723 : }
3724 :
3725 : /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P
3726 : Store any side-effects in PRE_P. CALL_LOCATION is the location of
3727 : the CALL_EXPR. If ALLOW_SSA is set the actual parameter may be
3728 : gimplified to an SSA name. */
3729 :
3730 : enum gimplify_status
3731 34501062 : gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
3732 : bool allow_ssa)
3733 : {
3734 34501062 : bool (*test) (tree);
3735 34501062 : fallback_t fb;
3736 :
3737 : /* In general, we allow lvalues for function arguments to avoid
3738 : extra overhead of copying large aggregates out of even larger
3739 : aggregates into temporaries only to copy the temporaries to
3740 : the argument list. Make optimizers happy by pulling out to
3741 : temporaries those types that fit in registers. */
3742 34501062 : if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
3743 : test = is_gimple_val, fb = fb_rvalue;
3744 : else
3745 : {
3746 1606097 : test = is_gimple_lvalue, fb = fb_either;
3747 : /* Also strip a TARGET_EXPR that would force an extra copy. */
3748 1606097 : if (TREE_CODE (*arg_p) == TARGET_EXPR)
3749 : {
3750 328149 : tree init = TARGET_EXPR_INITIAL (*arg_p);
3751 328149 : if (init
3752 328146 : && !VOID_TYPE_P (TREE_TYPE (init))
3753 : /* Currently, due to c++/116015, it is not desirable to
3754 : strip a TARGET_EXPR whose initializer is a {}. The
3755 : problem is that if we do elide it, we also have to
3756 : replace all the occurrences of the slot temporary in the
3757 : initializer with the temporary created for the argument.
3758 : But we do not have that temporary yet so the replacement
3759 : would be quite awkward and it might be needed to resort
3760 : back to a PLACEHOLDER_EXPR. Note that stripping the
3761 : TARGET_EXPR wouldn't help anyway, as gimplify_expr would
3762 : just allocate a temporary to store the CONSTRUCTOR into.
3763 : (FIXME PR116375.)
3764 :
3765 : See convert_for_arg_passing for the C++ code that marks
3766 : the TARGET_EXPR as eliding or not. */
3767 614959 : && TREE_CODE (init) != CONSTRUCTOR)
3768 248691 : *arg_p = init;
3769 : }
3770 : }
3771 :
3772 : /* If this is a variable sized type, we must remember the size. */
3773 34501062 : maybe_with_size_expr (arg_p);
3774 :
3775 : /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */
3776 : /* Make sure arguments have the same location as the function call
3777 : itself. */
3778 34501062 : protected_set_expr_location (*arg_p, call_location);
3779 :
3780 : /* There is a sequence point before a function call. Side effects in
3781 : the argument list must occur before the actual call. So, when
3782 : gimplifying arguments, force gimplify_expr to use an internal
3783 : post queue which is then appended to the end of PRE_P. */
3784 34501062 : return gimplify_expr (arg_p, pre_p, NULL, test, fb, allow_ssa);
3785 : }
3786 :
3787 : /* Don't fold inside offloading or taskreg regions: it can break code by
3788 : adding decl references that weren't in the source. We'll do it during
3789 : omplower pass instead. */
3790 :
3791 : static bool
3792 60075951 : maybe_fold_stmt (gimple_stmt_iterator *gsi)
3793 : {
3794 60075951 : struct gimplify_omp_ctx *ctx;
3795 60602898 : for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
3796 1195461 : if ((ctx->region_type & (ORT_TARGET | ORT_PARALLEL | ORT_TASK)) != 0)
3797 : return false;
3798 531936 : else if ((ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
3799 : return false;
3800 : /* Delay folding of builtins until the IL is in consistent state
3801 : so the diagnostic machinery can do a better job. */
3802 59407437 : if (gimple_call_builtin_p (gsi_stmt (*gsi)))
3803 : return false;
3804 57021466 : return fold_stmt (gsi);
3805 : }
3806 :
3807 : static tree
3808 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
3809 : tree construct_context);
3810 :
3811 :
3812 : /* Helper function for calls to omp_dynamic_cond: find the current
3813 : enclosing block in the gimplification context. */
3814 : static tree
3815 359 : find_supercontext (void)
3816 : {
3817 359 : vec<gbind *>stack = gimple_bind_expr_stack ();
3818 686 : for (int i = stack.length () - 1; i >= 0; i++)
3819 : {
3820 327 : gbind *b = stack[i];
3821 327 : if (b->block)
3822 : return b->block;
3823 : }
3824 : return NULL_TREE;
3825 : }
3826 :
3827 : /* OpenMP: Handle the append_args and adjust_args clauses of
3828 : declare_variant for EXPR, which is a CALL_EXPR whose CALL_EXPR_FN
3829 : is the variant, within a dispatch construct with clauses DISPATCH_CLAUSES.
3830 : WANT_VALUE and POINTERIZE are as for expand_variant_call_expr.
3831 :
3832 : 'append_args' causes interop objects are added after the last regular
3833 : (nonhidden, nonvariadic) arguments of the variant function.
3834 : 'adjust_args' with need_device_{addr,ptr} converts the pointer target of
3835 : a pointer from a host to a device address. This uses either the default
3836 : device or the passed device number, which then sets the default device
3837 : address. */
3838 : static tree
3839 471 : modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
3840 : bool want_value, bool pointerize)
3841 : {
3842 471 : location_t loc = EXPR_LOCATION (expr);
3843 471 : tree fndecl = get_callee_fndecl (expr);
3844 :
3845 : /* Skip processing if we don't get the expected call form. */
3846 471 : if (!fndecl)
3847 : return expr;
3848 :
3849 471 : tree init_code = NULL_TREE;
3850 471 : tree cleanup = NULL_TREE;
3851 471 : tree clobbers = NULL_TREE;
3852 471 : int nargs = call_expr_nargs (expr);
3853 471 : tree dispatch_device_num = NULL_TREE;
3854 471 : tree dispatch_interop = NULL_TREE;
3855 471 : tree dispatch_append_args = NULL_TREE;
3856 471 : int nfirst_args = 0;
3857 471 : tree dispatch_adjust_args_list
3858 471 : = lookup_attribute ("omp declare variant variant args",
3859 471 : DECL_ATTRIBUTES (fndecl));
3860 :
3861 471 : if (dispatch_adjust_args_list)
3862 : {
3863 389 : dispatch_adjust_args_list = TREE_VALUE (dispatch_adjust_args_list);
3864 389 : dispatch_append_args = TREE_CHAIN (dispatch_adjust_args_list);
3865 389 : if (TREE_PURPOSE (dispatch_adjust_args_list) == NULL_TREE
3866 389 : && TREE_VALUE (dispatch_adjust_args_list) == NULL_TREE)
3867 : dispatch_adjust_args_list = NULL_TREE;
3868 : }
3869 389 : if (dispatch_append_args)
3870 : {
3871 245 : nfirst_args = tree_to_shwi (TREE_PURPOSE (dispatch_append_args));
3872 245 : dispatch_append_args = TREE_VALUE (dispatch_append_args);
3873 : }
3874 471 : dispatch_device_num = omp_find_clause (dispatch_clauses, OMP_CLAUSE_DEVICE);
3875 471 : if (dispatch_device_num)
3876 287 : dispatch_device_num = OMP_CLAUSE_DEVICE_ID (dispatch_device_num);
3877 471 : dispatch_interop = omp_find_clause (dispatch_clauses, OMP_CLAUSE_INTEROP);
3878 471 : int nappend = 0, ninterop = 0;
3879 880 : for (tree t = dispatch_append_args; t; t = TREE_CHAIN (t))
3880 409 : nappend++;
3881 :
3882 : /* FIXME: error checking should be taken out of this function and
3883 : handled before any attempt at filtering or resolution happens.
3884 : Otherwise whether or not diagnostics appear is determined by
3885 : GCC internals, how good the front ends are at constant-folding,
3886 : the split between early/late resolution, etc instead of the code
3887 : as written by the user. */
3888 471 : if (dispatch_interop)
3889 861 : for (tree t = dispatch_interop; t; t = TREE_CHAIN (t))
3890 605 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3891 409 : ninterop++;
3892 471 : if (dispatch_interop && !dispatch_device_num)
3893 : {
3894 7 : gcc_checking_assert (ninterop > 1);
3895 7 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3896 : "the %<device%> clause must be present if the %<interop%> "
3897 : "clause has more than one list item");
3898 : }
3899 471 : if (nappend < ninterop)
3900 : {
3901 48 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
3902 : "number of list items in %<interop%> clause (%d) "
3903 : "exceeds the number of %<append_args%> items (%d) for "
3904 : "%<declare variant%> candidate %qD", ninterop, nappend, fndecl);
3905 88 : inform (dispatch_append_args
3906 8 : ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args))
3907 40 : : DECL_SOURCE_LOCATION (fndecl),
3908 : "%<declare variant%> candidate %qD declared here", fndecl);
3909 48 : ninterop = nappend;
3910 : }
3911 471 : if (dispatch_append_args)
3912 : {
3913 245 : tree *buffer = XALLOCAVEC (tree, nargs + nappend);
3914 245 : tree arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
3915 : /* Copy the first arguments; insert then the interop objects,
3916 : and then copy the rest (nargs - nfirst_args) args. */
3917 245 : int i;
3918 679 : for (i = 0; i < nfirst_args; i++)
3919 : {
3920 434 : arg = TREE_CHAIN (arg);
3921 434 : buffer[i] = CALL_EXPR_ARG (expr, i);
3922 : }
3923 : int j = ninterop;
3924 583 : for (tree t = dispatch_interop; t && j > 0; t = TREE_CHAIN (t))
3925 338 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
3926 338 : buffer[i + --j] = OMP_CLAUSE_DECL (t);
3927 245 : gcc_checking_assert (j == 0);
3928 :
3929 : /* Do we need to create additional interop objects? */
3930 245 : if (ninterop < nappend)
3931 : {
3932 56 : if (dispatch_device_num == NULL_TREE)
3933 : /* Not remapping device number. */
3934 22 : dispatch_device_num = build_int_cst (integer_type_node,
3935 : GOMP_DEVICE_DEFAULT_OMP_61);
3936 56 : int nnew = nappend - ninterop;
3937 56 : tree nobjs = build_int_cst (integer_type_node, nnew);
3938 56 : tree a, t;
3939 :
3940 : /* Skip to the append_args clause for the first constructed
3941 : interop argument. */
3942 56 : tree apparg = dispatch_append_args;
3943 83 : for (j = 0; j < ninterop; j++)
3944 27 : apparg = TREE_CHAIN (apparg);
3945 :
3946 : /* omp_interop_t *objs[n]; */
3947 56 : tree objtype = build_pointer_type (pointer_sized_int_node);
3948 56 : t = build_array_type_nelts (objtype, nnew);
3949 56 : tree objs = create_tmp_var (t, "interopobjs");
3950 :
3951 : /* int target_tgtsync[n]; */
3952 56 : t = build_array_type_nelts (integer_type_node, nnew);
3953 56 : tree target_tgtsync = create_tmp_var (t, "tgt_tgtsync");
3954 :
3955 : /* Scan first to determine if we need a prefer_type array. */
3956 56 : tree prefer_type = NULL_TREE;
3957 56 : tree prefer_type_type = NULL_TREE;
3958 141 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3959 64 : if (TREE_VALUE (a) != NULL_TREE)
3960 : {
3961 : /* const char *prefer_type[n]; */
3962 35 : t = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
3963 35 : prefer_type_type = build_pointer_type (t);
3964 35 : t = build_array_type_nelts (prefer_type_type, nnew);
3965 35 : prefer_type = create_tmp_var (t, "pref_type");
3966 35 : break;
3967 : }
3968 :
3969 : /* Initialize the arrays, generating temp vars and clobbers for
3970 : the interop objects. (The constructed array holding the
3971 : pointers to these objects shouldn't need clobbering as there's
3972 : no reason for GOMP_interop to modify its contents.) */
3973 127 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
3974 : {
3975 : /* The allocated temporaries for the interop objects
3976 : have type omp_interop_t, which is an integer type that
3977 : can encode a pointer. */
3978 71 : tree objvar = create_tmp_var (pointer_sized_int_node, "interop");
3979 71 : buffer[i + j] = objvar;
3980 71 : TREE_ADDRESSABLE (objvar) = 1;
3981 : /* Generate a clobber for the temporary for when we're done
3982 : with it. */
3983 71 : tree c = build_clobber (pointer_sized_int_node,
3984 : CLOBBER_OBJECT_END);
3985 71 : c = build2 (MODIFY_EXPR, pointer_sized_int_node, objvar, c);
3986 71 : if (clobbers)
3987 15 : clobbers = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
3988 : c, clobbers);
3989 : else
3990 : clobbers = c;
3991 :
3992 : /* objs[offset] = &objvar; */
3993 71 : tree offset = build_int_cst (integer_type_node, j - ninterop);
3994 71 : tree init = build4 (ARRAY_REF, objtype, objs, offset,
3995 : NULL_TREE, NULL_TREE);
3996 71 : init = build2 (MODIFY_EXPR, objtype, init,
3997 : build_fold_addr_expr (objvar));
3998 71 : if (init_code)
3999 15 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4000 : init_code, init);
4001 : else
4002 : init_code = init;
4003 :
4004 : /* target_tgtsync[offset] = tgt;
4005 : (Don't blame me, I didn't design the encoding of this
4006 : info into the dispatch interop clause data structure,
4007 : but the runtime wants a bit mask.) */
4008 71 : tree tree_tgt = TREE_OPERAND (TREE_PURPOSE (a), 0);
4009 71 : int tgt = 0;
4010 71 : if (TREE_PURPOSE (tree_tgt) == boolean_true_node)
4011 42 : tgt |= GOMP_INTEROP_TARGET;
4012 71 : if (TREE_VALUE (tree_tgt) == boolean_true_node)
4013 36 : tgt |= GOMP_INTEROP_TARGETSYNC;
4014 71 : init = build4 (ARRAY_REF, integer_type_node,
4015 : target_tgtsync, offset, NULL_TREE, NULL_TREE);
4016 71 : init = build2 (MODIFY_EXPR, integer_type_node, init,
4017 71 : build_int_cst (integer_type_node, tgt));
4018 71 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4019 : init_code, init);
4020 :
4021 71 : if (prefer_type)
4022 : {
4023 45 : tree pref = TREE_VALUE (a);
4024 45 : if (pref == NULL_TREE)
4025 6 : pref = null_pointer_node;
4026 : else
4027 39 : pref = build_fold_addr_expr (pref);
4028 45 : init = build4 (ARRAY_REF, prefer_type_type, prefer_type,
4029 : offset, NULL_TREE, NULL_TREE);
4030 45 : init = build2 (MODIFY_EXPR, prefer_type_type, init,
4031 : pref);
4032 45 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4033 : init_code, init);
4034 : }
4035 : }
4036 :
4037 56 : objs = build_fold_addr_expr (objs);
4038 56 : target_tgtsync = build_fold_addr_expr (target_tgtsync);
4039 56 : prefer_type = prefer_type ? build_fold_addr_expr (prefer_type)
4040 : : null_pointer_node;
4041 56 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
4042 56 : tree create
4043 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4044 : nobjs, objs, target_tgtsync, prefer_type,
4045 : integer_zero_node, null_pointer_node,
4046 : integer_zero_node, null_pointer_node,
4047 : integer_zero_node, null_pointer_node);
4048 56 : if (init_code)
4049 56 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (create),
4050 : init_code, create);
4051 : else
4052 : init_code = create;
4053 :
4054 56 : cleanup
4055 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4056 : integer_zero_node, null_pointer_node,
4057 : null_pointer_node, null_pointer_node,
4058 : integer_zero_node, null_pointer_node,
4059 : nobjs, objs,
4060 : integer_zero_node, null_pointer_node);
4061 56 : if (clobbers)
4062 56 : cleanup = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
4063 : cleanup, clobbers);
4064 : }
4065 :
4066 654 : for (j = 0; j < nappend; j++)
4067 : {
4068 : /* Fortran permits by-reference or by-value for the dummy arg
4069 : and by-value, by-reference, ptr by-reference as actual
4070 : argument. Handle this. */
4071 409 : tree obj = buffer[i + j]; // interop object
4072 409 : tree a2 = TREE_VALUE (arg); // parameter type
4073 766 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4074 436 : && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (obj))))
4075 : {
4076 32 : tree t = TREE_TYPE (TREE_TYPE (obj));
4077 32 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (t)));
4078 32 : obj = fold_build1 (INDIRECT_REF, t, obj);
4079 : }
4080 750 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4081 420 : && INTEGRAL_TYPE_P (a2))
4082 : {
4083 43 : tree t = TREE_TYPE (TREE_TYPE (obj));
4084 43 : gcc_checking_assert (INTEGRAL_TYPE_P (t));
4085 43 : obj = fold_build1 (INDIRECT_REF, t, obj);
4086 : }
4087 497 : else if (INTEGRAL_TYPE_P (TREE_TYPE (obj))
4088 461 : && POINTER_TYPE_P (a2))
4089 : {
4090 18 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4091 18 : obj = build_fold_addr_expr (obj);
4092 : }
4093 348 : else if (!INTEGRAL_TYPE_P (a2)
4094 348 : || !INTEGRAL_TYPE_P (TREE_TYPE (obj)))
4095 : {
4096 36 : tree t = TREE_TYPE (obj);
4097 36 : gcc_checking_assert (POINTER_TYPE_P (t)
4098 : && POINTER_TYPE_P (a2)
4099 : && INTEGRAL_TYPE_P (TREE_TYPE (t))
4100 : && INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4101 : }
4102 409 : buffer[i + j] = obj;
4103 409 : arg = TREE_CHAIN (arg);
4104 : }
4105 245 : i += nappend;
4106 534 : for (j = nfirst_args; j < nargs; j++)
4107 289 : buffer[i++] = CALL_EXPR_ARG (expr, j);
4108 245 : nargs += nappend;
4109 245 : tree call = expr;
4110 490 : expr = build_call_array_loc (EXPR_LOCATION (expr), TREE_TYPE (call),
4111 245 : CALL_EXPR_FN (call), nargs, buffer);
4112 :
4113 : /* Copy all CALL_EXPR flags. */
4114 245 : CALL_EXPR_STATIC_CHAIN (expr) = CALL_EXPR_STATIC_CHAIN (call);
4115 245 : CALL_EXPR_TAILCALL (expr) = CALL_EXPR_TAILCALL (call);
4116 245 : CALL_EXPR_RETURN_SLOT_OPT (expr)
4117 245 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4118 245 : CALL_FROM_THUNK_P (expr) = CALL_FROM_THUNK_P (call);
4119 245 : SET_EXPR_LOCATION (expr, EXPR_LOCATION (call));
4120 245 : CALL_EXPR_VA_ARG_PACK (expr) = CALL_EXPR_VA_ARG_PACK (call);
4121 : }
4122 :
4123 : /* Nothing to do for adjust_args? */
4124 471 : if (!dispatch_adjust_args_list || !TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
4125 260 : goto add_cleanup;
4126 :
4127 : /* Handle adjust_args. */
4128 966 : for (int i = 0; i < nargs; i++)
4129 : {
4130 755 : tree *arg_p = &CALL_EXPR_ARG (expr, i);
4131 :
4132 : /* Nothing to do if arg is constant null pointer. */
4133 755 : if (integer_zerop (*arg_p))
4134 6 : continue;
4135 :
4136 : bool need_device_ptr = false;
4137 : bool need_device_addr = false;
4138 2247 : for (int need_addr = 0; need_addr <= 1; need_addr++)
4139 2301 : for (tree arg = (need_addr
4140 1498 : ? TREE_VALUE (dispatch_adjust_args_list)
4141 1498 : : TREE_PURPOSE (dispatch_adjust_args_list));
4142 2301 : arg != NULL; arg = TREE_CHAIN (arg))
4143 : {
4144 1152 : if (TREE_VALUE (arg)
4145 1152 : && TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST
4146 2304 : && wi::eq_p (i, wi::to_wide (TREE_VALUE (arg))))
4147 : {
4148 349 : if (need_addr)
4149 : need_device_addr = true;
4150 : else
4151 349 : need_device_ptr = true;
4152 : break;
4153 : }
4154 : }
4155 :
4156 749 : if (need_device_ptr || need_device_addr)
4157 : {
4158 740 : bool is_device_ptr = false;
4159 740 : bool has_device_addr = false;
4160 :
4161 740 : for (tree c = dispatch_clauses; c; c = TREE_CHAIN (c))
4162 : {
4163 454 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
4164 454 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
4165 : {
4166 164 : tree decl1 = DECL_NAME (OMP_CLAUSE_DECL (c));
4167 164 : tree decl2 = tree_strip_nop_conversions (*arg_p);
4168 164 : if (TREE_CODE (decl2) == ADDR_EXPR)
4169 19 : decl2 = TREE_OPERAND (decl2, 0);
4170 164 : if (VAR_P (decl2) || TREE_CODE (decl2) == PARM_DECL)
4171 : {
4172 140 : decl2 = DECL_NAME (decl2);
4173 140 : if (decl1 == decl2
4174 203 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
4175 : {
4176 58 : if (need_device_addr)
4177 0 : warning_at (OMP_CLAUSE_LOCATION (c),
4178 0 : OPT_Wopenmp,
4179 : "%<is_device_ptr%> for %qD does"
4180 : " not imply %<has_device_addr%> "
4181 : "required for %<need_device_addr%>",
4182 0 : OMP_CLAUSE_DECL (c));
4183 : is_device_ptr = true;
4184 : break;
4185 : }
4186 82 : else if (decl1 == decl2)
4187 : {
4188 5 : if (need_device_ptr)
4189 10 : warning_at (OMP_CLAUSE_LOCATION (c),
4190 5 : OPT_Wopenmp,
4191 : "%<has_device_addr%> for %qD does"
4192 : " not imply %<is_device_ptr%> "
4193 : "required for %<need_device_ptr%>",
4194 5 : OMP_CLAUSE_DECL (c));
4195 : has_device_addr = true;
4196 : break;
4197 : }
4198 : }
4199 : }
4200 : }
4201 :
4202 349 : if ((need_device_ptr && !is_device_ptr)
4203 58 : || (need_device_addr && !has_device_addr))
4204 : {
4205 291 : if (dispatch_device_num == NULL_TREE)
4206 : {
4207 : // device_num = omp_get_default_device ()
4208 105 : tree fn
4209 105 : = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
4210 105 : tree call = build_call_expr (fn, 0);
4211 105 : dispatch_device_num = create_tmp_var_raw (TREE_TYPE (call));
4212 105 : tree init
4213 105 : = build4 (TARGET_EXPR, TREE_TYPE (call),
4214 : dispatch_device_num, call, NULL_TREE, NULL_TREE);
4215 105 : if (init_code)
4216 0 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4217 : init_code, init);
4218 : else
4219 : init_code = init;
4220 : }
4221 :
4222 : // We want to emit the following statement:
4223 : // mapped_arg = omp_get_mapped_ptr (arg,
4224 : // device_num)
4225 : // but arg has to be the actual pointer, not a
4226 : // reference or a conversion expression.
4227 291 : tree actual_ptr
4228 291 : = ((TREE_CODE (*arg_p) == ADDR_EXPR)
4229 291 : ? TREE_OPERAND (*arg_p, 0)
4230 38 : : *arg_p);
4231 291 : if (TREE_CODE (actual_ptr) == NOP_EXPR
4232 291 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (actual_ptr, 0)))
4233 : == REFERENCE_TYPE))
4234 : {
4235 6 : actual_ptr = TREE_OPERAND (actual_ptr, 0);
4236 6 : actual_ptr = build1 (INDIRECT_REF,
4237 6 : TREE_TYPE (actual_ptr),
4238 : actual_ptr);
4239 : }
4240 291 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_MAPPED_PTR);
4241 291 : tree mapped_arg = build_call_expr_loc (loc, fn, 2, actual_ptr,
4242 : dispatch_device_num);
4243 :
4244 291 : if (TREE_CODE (*arg_p) == ADDR_EXPR
4245 291 : || (TREE_CODE (TREE_TYPE (actual_ptr)) == REFERENCE_TYPE))
4246 47 : mapped_arg = build_fold_addr_expr (mapped_arg);
4247 244 : else if (TREE_CODE (*arg_p) == NOP_EXPR)
4248 35 : mapped_arg = build1 (NOP_EXPR, TREE_TYPE (*arg_p),
4249 : mapped_arg);
4250 291 : *arg_p = mapped_arg;
4251 : }
4252 : }
4253 : }
4254 :
4255 471 : add_cleanup:
4256 471 : if (cleanup)
4257 : {
4258 56 : tree result = NULL_TREE;
4259 56 : if (want_value && pointerize)
4260 : {
4261 0 : tree tmp = create_tmp_var (build_pointer_type (TREE_TYPE (expr)),
4262 : "cleanuptmp");
4263 0 : result = build_simple_mem_ref (tmp);
4264 0 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp,
4265 : build_fold_addr_expr (expr));
4266 : }
4267 56 : else if (want_value)
4268 : {
4269 18 : tree tmp = create_tmp_var (TREE_TYPE (expr), "cleanuptmp");
4270 18 : result = tmp;
4271 18 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp, expr);
4272 : }
4273 56 : if (init_code)
4274 56 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4275 56 : expr = build2 (TRY_FINALLY_EXPR, void_type_node, expr, cleanup);
4276 :
4277 56 : if (result)
4278 18 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (result), expr, result);
4279 : }
4280 415 : else if (init_code)
4281 105 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4282 :
4283 : return expr;
4284 : }
4285 :
4286 : /* Helper function for gimplify_call_expr: handle "declare variant"
4287 : resolution and expansion of the CALL_EXPR EXPR. WANT_VALUE is true
4288 : if the result value of the call is needed; POINTERIZE is true if it
4289 : also needs to be pointerized. If OMP_DISPATCH_P is true, apply
4290 : associated transformations using DISPATCH_CLAUSES.
4291 : This function may return either the original call or some other
4292 : expression such as a conditional to select one of multiple calls.
4293 :
4294 : FIXME: this function is written to be independent of gimplifier internals
4295 : so that it could be moved to omp-general.cc and invoked from the
4296 : front ends instead, per PR115076. */
4297 :
4298 : static tree
4299 1326 : expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
4300 : bool omp_dispatch_p, tree dispatch_clauses)
4301 : {
4302 : /* If we've already processed this call, stop now. This can happen
4303 : if the variant call resolves to the original function, or to
4304 : a dynamic conditional that includes the default call to the original
4305 : function. */
4306 1326 : gcc_assert (omp_resolved_variant_calls != NULL);
4307 1326 : if (omp_resolved_variant_calls->contains (expr))
4308 131 : return expr;
4309 :
4310 1195 : tree fndecl = get_callee_fndecl (expr);
4311 1195 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (expr));
4312 1195 : location_t loc = EXPR_LOCATION (expr);
4313 1195 : tree construct_context = omp_get_construct_context ();
4314 1195 : vec<struct omp_variant> all_candidates
4315 1195 : = omp_declare_variant_candidates (fndecl, construct_context);
4316 1195 : gcc_assert (!all_candidates.is_empty ());
4317 1195 : vec<struct omp_variant> candidates
4318 1195 : = omp_get_dynamic_candidates (all_candidates, construct_context);
4319 :
4320 : /* If the variant call could be resolved now, build a nest of COND_EXPRs
4321 : if there are dynamic candidates, and/or a new CALL_EXPR for each
4322 : candidate call. */
4323 1195 : if (!candidates.is_empty ())
4324 : {
4325 1183 : int n = candidates.length ();
4326 1183 : tree tail = NULL_TREE;
4327 :
4328 2404 : for (int i = n - 1; i >= 0; i--)
4329 : {
4330 1221 : if (tail)
4331 38 : gcc_assert (candidates[i].dynamic_selector);
4332 : else
4333 1183 : gcc_assert (!candidates[i].dynamic_selector);
4334 1221 : if (candidates[i].alternative == fndecl)
4335 : {
4336 : /* We should only get the original function back as the
4337 : default. */
4338 261 : gcc_assert (!tail);
4339 261 : omp_resolved_variant_calls->add (expr);
4340 261 : tail = expr;
4341 : }
4342 : else
4343 : {
4344 : /* For the final static selector, we can re-use the old
4345 : CALL_EXPR and just replace the function, unless it may
4346 : need dispatch argument modification. Otherwise,
4347 : make a copy of it. */
4348 960 : tree thiscall = (tail || omp_dispatch_p
4349 960 : ? unshare_expr (expr) : expr);
4350 960 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype,
4351 960 : candidates[i].alternative);
4352 960 : if (omp_dispatch_p)
4353 471 : thiscall = modify_call_for_omp_dispatch (thiscall,
4354 : dispatch_clauses,
4355 : want_value,
4356 : pointerize);
4357 960 : if (!tail)
4358 : tail = thiscall;
4359 : else
4360 76 : tail = build3 (COND_EXPR, TREE_TYPE (expr),
4361 38 : omp_dynamic_cond (candidates[i].selector,
4362 : find_supercontext ()),
4363 : thiscall, tail);
4364 : }
4365 : }
4366 : return tail;
4367 : }
4368 :
4369 : /* If we couldn't resolve the variant call now, expand it into a loop using
4370 : a switch and OMP_NEXT_VARIANT for dispatch. The ompdevlow pass will
4371 : handle OMP_NEXT_VARIANT expansion. */
4372 : else
4373 : {
4374 : /* If we need a usable return value, we need a temporary
4375 : and an assignment in each alternative. This logic was borrowed
4376 : from gimplify_cond_expr. */
4377 12 : tree type = TREE_TYPE (expr);
4378 12 : tree tmp = NULL_TREE, result = NULL_TREE;
4379 :
4380 12 : if (want_value)
4381 : {
4382 12 : if (pointerize)
4383 : {
4384 0 : type = build_pointer_type (type);
4385 0 : tmp = create_tmp_var (type, "iftmp");
4386 0 : result = build_simple_mem_ref_loc (loc, tmp);
4387 : }
4388 : else
4389 : {
4390 12 : tmp = create_tmp_var (type, "iftmp");
4391 12 : result = tmp;
4392 : }
4393 : }
4394 :
4395 : /* Preprocess the all_candidates array so that the alternative field of
4396 : each element holds the actual function call expression and possible
4397 : assignment, instead of just the decl for the variant function. */
4398 60 : for (unsigned int i = 0; i < all_candidates.length (); i++)
4399 : {
4400 48 : tree decl = all_candidates[i].alternative;
4401 48 : tree thiscall;
4402 :
4403 : /* We need to turn the decl from the candidate into a function
4404 : call and possible assignment, and stuff that in
4405 : the directive seq of the gomp_variant. */
4406 48 : if (decl == fndecl)
4407 : {
4408 12 : thiscall = expr;
4409 12 : omp_resolved_variant_calls->add (expr);
4410 : }
4411 : else
4412 : {
4413 36 : thiscall = unshare_expr (expr);
4414 36 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype, decl);
4415 36 : if (omp_dispatch_p)
4416 0 : thiscall = modify_call_for_omp_dispatch (thiscall,
4417 : dispatch_clauses,
4418 : want_value,
4419 : pointerize);
4420 : }
4421 48 : if (pointerize)
4422 0 : thiscall = build_fold_addr_expr_loc (loc, thiscall);
4423 48 : if (want_value)
4424 48 : thiscall = build2 (INIT_EXPR, type, tmp, thiscall);
4425 48 : all_candidates[i].alternative = thiscall;
4426 : }
4427 :
4428 12 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
4429 12 : tree expansion = expand_late_variant_directive (all_candidates,
4430 : construct_context);
4431 12 : if (result)
4432 12 : expansion = build2 (COMPOUND_EXPR, TREE_TYPE (result),
4433 : expansion, result);
4434 12 : return expansion;
4435 : }
4436 : }
4437 :
4438 : /* Wrapper around expand_variant_call_expr to interface with gimplifier
4439 : state. EXPR and OMP_DISPATCH_P are as for expand_variant_call_expr,
4440 : FALLBACK is used to compute the WANT_VALUE and POINTERIZE arguments. */
4441 : static tree
4442 1326 : gimplify_variant_call_expr (tree expr, fallback_t fallback,
4443 : bool omp_dispatch_p)
4444 : {
4445 1326 : tree type = TREE_TYPE (expr);
4446 1326 : bool want_value = (fallback != fb_none && !VOID_TYPE_P (type));
4447 673 : bool pointerize = false;
4448 : /* If the result value must be an lvalue or the result type must
4449 : live in memory, then we have to pointerize it if we need a temporary. */
4450 673 : if (want_value
4451 673 : && ((!(fallback & fb_rvalue) && (fallback & fb_lvalue))
4452 673 : || TREE_ADDRESSABLE (type)))
4453 0 : pointerize = true;
4454 :
4455 1838 : return expand_variant_call_expr (expr, want_value, pointerize,
4456 : omp_dispatch_p,
4457 : (omp_dispatch_p
4458 512 : ? gimplify_omp_ctxp->clauses
4459 1326 : : NULL_TREE));
4460 : }
4461 :
4462 :
4463 : /* Helper function for gimplify_call_expr, called via walk_tree.
4464 : Find used user labels. */
4465 :
4466 : static tree
4467 766 : find_used_user_labels (tree *tp, int *, void *)
4468 : {
4469 766 : if (TREE_CODE (*tp) == LABEL_EXPR
4470 15 : && !DECL_ARTIFICIAL (LABEL_EXPR_LABEL (*tp))
4471 15 : && DECL_NAME (LABEL_EXPR_LABEL (*tp))
4472 781 : && TREE_USED (LABEL_EXPR_LABEL (*tp)))
4473 15 : return *tp;
4474 : return NULL_TREE;
4475 : }
4476 :
4477 :
4478 : /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
4479 : WANT_VALUE is true if the result of the call is desired. */
4480 :
4481 : static enum gimplify_status
4482 17252680 : gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
4483 : {
4484 17252680 : bool want_value = (fallback != fb_none);
4485 17252680 : tree fndecl, parms, p, fnptrtype;
4486 17252680 : enum gimplify_status ret;
4487 17252680 : int i, nargs;
4488 17252680 : gcall *call;
4489 17252680 : bool builtin_va_start_p = false, omp_dispatch_p = false;
4490 17252680 : location_t loc = EXPR_LOCATION (*expr_p);
4491 :
4492 17252680 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4493 :
4494 : /* For reliable diagnostics during inlining, it is necessary that
4495 : every call_expr be annotated with file and line. */
4496 17252680 : if (! EXPR_HAS_LOCATION (*expr_p))
4497 517228 : SET_EXPR_LOCATION (*expr_p, input_location);
4498 :
4499 : /* Gimplify internal functions created in the FEs. */
4500 17252680 : if (CALL_EXPR_FN (*expr_p) == NULL_TREE)
4501 : {
4502 600318 : enum internal_fn ifn = CALL_EXPR_IFN (*expr_p);
4503 600318 : if (ifn == IFN_GOMP_DISPATCH)
4504 : {
4505 884 : gcc_assert (flag_openmp
4506 : && gimplify_omp_ctxp
4507 : && gimplify_omp_ctxp->code == OMP_DISPATCH);
4508 884 : *expr_p = CALL_EXPR_ARG (*expr_p, 0);
4509 884 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4510 884 : if (! EXPR_HAS_LOCATION (*expr_p))
4511 94 : SET_EXPR_LOCATION (*expr_p, input_location);
4512 : omp_dispatch_p = true;
4513 : }
4514 : else
4515 : {
4516 599434 : if (want_value)
4517 : return GS_ALL_DONE;
4518 :
4519 20146 : nargs = call_expr_nargs (*expr_p);
4520 20146 : auto_vec<tree> vargs (nargs);
4521 :
4522 20146 : if (ifn == IFN_ASSUME)
4523 : {
4524 531 : if (simple_condition_p (CALL_EXPR_ARG (*expr_p, 0)))
4525 : {
4526 : /* If the [[assume (cond)]]; condition is simple
4527 : enough and can be evaluated unconditionally
4528 : without side-effects, expand it as
4529 : if (!cond) __builtin_unreachable (); */
4530 311 : tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
4531 311 : *expr_p
4532 622 : = build3 (COND_EXPR, void_type_node,
4533 311 : CALL_EXPR_ARG (*expr_p, 0), void_node,
4534 311 : build_call_expr_loc (EXPR_LOCATION (*expr_p),
4535 : fndecl, 0));
4536 311 : return GS_OK;
4537 : }
4538 : /* If not optimizing, ignore the assumptions unless there
4539 : are used user labels in it. */
4540 220 : if ((!optimize
4541 98 : && !walk_tree_without_duplicates (&CALL_EXPR_ARG (*expr_p,
4542 : 0),
4543 : find_used_user_labels,
4544 : NULL))
4545 235 : || seen_error ())
4546 : {
4547 94 : *expr_p = NULL_TREE;
4548 94 : return GS_ALL_DONE;
4549 : }
4550 : /* Temporarily, until gimple lowering, transform
4551 : .ASSUME (cond);
4552 : into:
4553 : [[assume (guard)]]
4554 : {
4555 : guard = cond;
4556 : }
4557 : such that gimple lowering can outline the condition into
4558 : a separate function easily. */
4559 126 : tree guard = create_tmp_var (boolean_type_node);
4560 126 : *expr_p = build2 (MODIFY_EXPR, void_type_node, guard,
4561 126 : gimple_boolify (CALL_EXPR_ARG (*expr_p, 0)));
4562 126 : *expr_p = build3 (BIND_EXPR, void_type_node, NULL, *expr_p, NULL);
4563 126 : push_gimplify_context ();
4564 126 : gimple_seq body = NULL;
4565 126 : gimple *g = gimplify_and_return_first (*expr_p, &body);
4566 126 : pop_gimplify_context (g);
4567 126 : g = gimple_build_assume (guard, body);
4568 126 : gimple_set_location (g, loc);
4569 126 : gimplify_seq_add_stmt (pre_p, g);
4570 126 : *expr_p = NULL_TREE;
4571 126 : return GS_ALL_DONE;
4572 : }
4573 19615 : else if (ifn == IFN_UBSAN_BOUNDS
4574 19615 : && nargs == 3
4575 19615 : && integer_onep (CALL_EXPR_ARG (*expr_p, 0)))
4576 : {
4577 : /* If first argument is one, add TYPE_MAX_VALUE (TYPE_DOMAIN (t))
4578 : to 3rd argument and change first argument to 0. This is
4579 : done by ubsan_instrument_bounds so that we can use the
4580 : max value from gimplify_type_sizes here instead of original
4581 : expression for VLAs. */
4582 406 : tree type = TREE_TYPE (CALL_EXPR_ARG (*expr_p, 0));
4583 406 : CALL_EXPR_ARG (*expr_p, 0) = build_int_cst (type, 0);
4584 406 : gcc_assert (TREE_CODE (type) == POINTER_TYPE);
4585 406 : type = TREE_TYPE (type);
4586 406 : gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4587 406 : tree maxv = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4588 406 : gcc_assert (maxv);
4589 406 : tree arg3 = CALL_EXPR_ARG (*expr_p, 2);
4590 406 : CALL_EXPR_ARG (*expr_p, 2)
4591 812 : = fold_build2 (PLUS_EXPR, TREE_TYPE (arg3), maxv, arg3);
4592 : }
4593 :
4594 45332 : for (i = 0; i < nargs; i++)
4595 : {
4596 25717 : gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
4597 25717 : EXPR_LOCATION (*expr_p));
4598 25717 : vargs.quick_push (CALL_EXPR_ARG (*expr_p, i));
4599 : }
4600 :
4601 19615 : gcall *call = gimple_build_call_internal_vec (ifn, vargs);
4602 19615 : gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p));
4603 19615 : gimplify_seq_add_stmt (pre_p, call);
4604 19615 : return GS_ALL_DONE;
4605 20146 : }
4606 : }
4607 :
4608 : /* This may be a call to a builtin function.
4609 :
4610 : Builtin function calls may be transformed into different
4611 : (and more efficient) builtin function calls under certain
4612 : circumstances. Unfortunately, gimplification can muck things
4613 : up enough that the builtin expanders are not aware that certain
4614 : transformations are still valid.
4615 :
4616 : So we attempt transformation/gimplification of the call before
4617 : we gimplify the CALL_EXPR. At this time we do not manage to
4618 : transform all calls in the same manner as the expanders do, but
4619 : we do transform most of them. */
4620 16653246 : fndecl = get_callee_fndecl (*expr_p);
4621 16653246 : if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
4622 3953834 : switch (DECL_FUNCTION_CODE (fndecl))
4623 : {
4624 95705 : CASE_BUILT_IN_ALLOCA:
4625 : /* If the call has been built for a variable-sized object, then we
4626 : want to restore the stack level when the enclosing BIND_EXPR is
4627 : exited to reclaim the allocated space; otherwise, we precisely
4628 : need to do the opposite and preserve the latest stack level. */
4629 95705 : if (CALL_ALLOCA_FOR_VAR_P (*expr_p))
4630 8963 : gimplify_ctxp->save_stack = true;
4631 : else
4632 86742 : gimplify_ctxp->keep_stack = true;
4633 : break;
4634 :
4635 20891 : case BUILT_IN_VA_START:
4636 20891 : {
4637 20891 : builtin_va_start_p = true;
4638 20891 : if (call_expr_nargs (*expr_p) < 2)
4639 : {
4640 1 : error ("too few arguments to function %<va_start%>");
4641 1 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4642 1 : return GS_OK;
4643 : }
4644 :
4645 20890 : if (fold_builtin_next_arg (*expr_p, true))
4646 : {
4647 8 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4648 8 : return GS_OK;
4649 : }
4650 : break;
4651 : }
4652 :
4653 30 : case BUILT_IN_EH_RETURN:
4654 30 : cfun->calls_eh_return = true;
4655 30 : break;
4656 :
4657 1030 : case BUILT_IN_CLEAR_PADDING:
4658 1030 : if (call_expr_nargs (*expr_p) == 1)
4659 : {
4660 : /* Remember the original type of the argument in an internal
4661 : dummy second argument, as in GIMPLE pointer conversions are
4662 : useless. Also mark this call as not for automatic
4663 : initialization in the internal dummy third argument. */
4664 515 : p = CALL_EXPR_ARG (*expr_p, 0);
4665 515 : *expr_p
4666 515 : = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
4667 515 : build_zero_cst (TREE_TYPE (p)));
4668 515 : return GS_OK;
4669 : }
4670 : break;
4671 :
4672 : default:
4673 : ;
4674 : }
4675 16652722 : if (fndecl && fndecl_built_in_p (fndecl))
4676 : {
4677 4188742 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4678 4188742 : if (new_tree && new_tree != *expr_p)
4679 : {
4680 : /* There was a transformation of this call which computes the
4681 : same value, but in a more efficient way. Return and try
4682 : again. */
4683 771 : *expr_p = new_tree;
4684 771 : return GS_OK;
4685 : }
4686 : }
4687 :
4688 : /* Remember the original function pointer type. */
4689 16651951 : fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
4690 :
4691 : /* Handle "declare variant" resolution and arglist processing. */
4692 16651951 : if (flag_openmp
4693 388603 : && fndecl
4694 387922 : && cfun
4695 387922 : && (cfun->curr_properties & PROP_gimple_any) == 0
4696 249789 : && !omp_has_novariants ()
4697 16901628 : && lookup_attribute ("omp declare variant base",
4698 249677 : DECL_ATTRIBUTES (fndecl)))
4699 : {
4700 1326 : tree orig = *expr_p;
4701 1326 : *expr_p = gimplify_variant_call_expr (*expr_p, fallback,
4702 : omp_dispatch_p);
4703 :
4704 : /* This may resolve to the same call, or the call expr with just
4705 : the function replaced, in which case we should just continue to
4706 : gimplify it normally. Otherwise, if we get something else back,
4707 : stop here and re-gimplify the whole replacement expr. */
4708 1326 : if (*expr_p != orig)
4709 : return GS_OK;
4710 : }
4711 :
4712 : /* There is a sequence point before the call, so any side effects in
4713 : the calling expression must occur before the actual call. Force
4714 : gimplify_expr to use an internal post queue. */
4715 16651462 : ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
4716 : is_gimple_call_addr, fb_rvalue);
4717 :
4718 16651462 : if (ret == GS_ERROR)
4719 : return GS_ERROR;
4720 :
4721 16651460 : nargs = call_expr_nargs (*expr_p);
4722 :
4723 : /* Get argument types for verification. */
4724 16651460 : fndecl = get_callee_fndecl (*expr_p);
4725 16651460 : parms = NULL_TREE;
4726 16651460 : if (fndecl)
4727 16428732 : parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
4728 : else
4729 222728 : parms = TYPE_ARG_TYPES (TREE_TYPE (fnptrtype));
4730 :
4731 33080192 : if (fndecl && DECL_ARGUMENTS (fndecl))
4732 : p = DECL_ARGUMENTS (fndecl);
4733 7339896 : else if (parms)
4734 : p = parms;
4735 : else
4736 : p = NULL_TREE;
4737 44320713 : for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
4738 : ;
4739 :
4740 : /* If the last argument is __builtin_va_arg_pack () and it is not
4741 : passed as a named argument, decrease the number of CALL_EXPR
4742 : arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */
4743 16651460 : if (!p
4744 16651460 : && i < nargs
4745 16651460 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR)
4746 : {
4747 5953 : tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1);
4748 5953 : tree last_arg_fndecl = get_callee_fndecl (last_arg);
4749 :
4750 5953 : if (last_arg_fndecl
4751 5953 : && fndecl_built_in_p (last_arg_fndecl, BUILT_IN_VA_ARG_PACK))
4752 : {
4753 131 : tree call = *expr_p;
4754 :
4755 131 : --nargs;
4756 262 : *expr_p = build_call_array_loc (loc, TREE_TYPE (call),
4757 131 : CALL_EXPR_FN (call),
4758 131 : nargs, CALL_EXPR_ARGP (call));
4759 :
4760 : /* Copy all CALL_EXPR flags, location and block, except
4761 : CALL_EXPR_VA_ARG_PACK flag. */
4762 131 : CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call);
4763 131 : CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call);
4764 131 : CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
4765 131 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4766 131 : CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
4767 131 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
4768 :
4769 : /* Set CALL_EXPR_VA_ARG_PACK. */
4770 131 : CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
4771 : }
4772 : }
4773 :
4774 : /* If the call returns twice then after building the CFG the call
4775 : argument computations will no longer dominate the call because
4776 : we add an abnormal incoming edge to the call. So do not use SSA
4777 : vars there. */
4778 16651460 : bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE;
4779 :
4780 :
4781 : /* Gimplify the function arguments. */
4782 16651460 : if (nargs > 0)
4783 : {
4784 14557026 : for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
4785 43691014 : PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
4786 29133988 : PUSH_ARGS_REVERSED ? i-- : i++)
4787 : {
4788 29133988 : enum gimplify_status t;
4789 :
4790 : /* Avoid gimplifying the second argument to va_start, which needs to
4791 : be the plain PARM_DECL. */
4792 29133988 : if ((i != 1) || !builtin_va_start_p)
4793 : {
4794 29113106 : tree *arg_p = &CALL_EXPR_ARG (*expr_p, i);
4795 :
4796 29113106 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4797 6687 : gimplify_omp_ctxp->in_call_args = true;
4798 29113106 : t = gimplify_arg (arg_p, pre_p, EXPR_LOCATION (*expr_p),
4799 29113106 : !returns_twice);
4800 29113106 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4801 6687 : gimplify_omp_ctxp->in_call_args = false;
4802 :
4803 29113106 : if (t == GS_ERROR)
4804 29133988 : ret = GS_ERROR;
4805 : }
4806 : }
4807 : }
4808 :
4809 : /* Gimplify the static chain. */
4810 16651460 : if (CALL_EXPR_STATIC_CHAIN (*expr_p))
4811 : {
4812 28853 : if (fndecl && !DECL_STATIC_CHAIN (fndecl))
4813 3 : CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL;
4814 : else
4815 : {
4816 28174 : enum gimplify_status t;
4817 28174 : t = gimplify_arg (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p,
4818 28174 : EXPR_LOCATION (*expr_p), ! returns_twice);
4819 28174 : if (t == GS_ERROR)
4820 16651460 : ret = GS_ERROR;
4821 : }
4822 : }
4823 :
4824 : /* Verify the function result. */
4825 16651460 : if (want_value && fndecl
4826 16651460 : && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
4827 : {
4828 0 : error_at (loc, "using result of function returning %<void%>");
4829 0 : ret = GS_ERROR;
4830 : }
4831 :
4832 : /* Try this again in case gimplification exposed something. */
4833 16651460 : if (ret != GS_ERROR)
4834 : {
4835 16651312 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4836 :
4837 16651312 : if (new_tree && new_tree != *expr_p)
4838 : {
4839 : /* There was a transformation of this call which computes the
4840 : same value, but in a more efficient way. Return and try
4841 : again. */
4842 11459 : *expr_p = new_tree;
4843 11459 : return GS_OK;
4844 : }
4845 : }
4846 : else
4847 : {
4848 148 : *expr_p = error_mark_node;
4849 148 : return GS_ERROR;
4850 : }
4851 :
4852 : /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
4853 : decl. This allows us to eliminate redundant or useless
4854 : calls to "const" functions. */
4855 16639853 : if (TREE_CODE (*expr_p) == CALL_EXPR)
4856 : {
4857 16639853 : int flags = call_expr_flags (*expr_p);
4858 16639853 : if (flags & (ECF_CONST | ECF_PURE)
4859 : /* An infinite loop is considered a side effect. */
4860 2432340 : && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
4861 2029004 : TREE_SIDE_EFFECTS (*expr_p) = 0;
4862 : }
4863 :
4864 : /* If the value is not needed by the caller, emit a new GIMPLE_CALL
4865 : and clear *EXPR_P. Otherwise, leave *EXPR_P in its gimplified
4866 : form and delegate the creation of a GIMPLE_CALL to
4867 : gimplify_modify_expr. This is always possible because when
4868 : WANT_VALUE is true, the caller wants the result of this call into
4869 : a temporary, which means that we will emit an INIT_EXPR in
4870 : internal_get_tmp_var which will then be handled by
4871 : gimplify_modify_expr. */
4872 16639853 : if (!want_value)
4873 : {
4874 : /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
4875 : have to do is replicate it as a GIMPLE_CALL tuple. */
4876 6350105 : gimple_stmt_iterator gsi;
4877 6350105 : call = gimple_build_call_from_tree (*expr_p, fnptrtype);
4878 6350105 : notice_special_calls (call);
4879 6350105 : gimplify_seq_add_stmt (pre_p, call);
4880 6350105 : gsi = gsi_last (*pre_p);
4881 6350105 : maybe_fold_stmt (&gsi);
4882 6350105 : *expr_p = NULL_TREE;
4883 : }
4884 : else
4885 : /* Remember the original function type. */
4886 10289748 : CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
4887 10289748 : CALL_EXPR_FN (*expr_p));
4888 :
4889 : return ret;
4890 : }
4891 :
4892 : /* Handle shortcut semantics in the predicate operand of a COND_EXPR by
4893 : rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs.
4894 :
4895 : TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the
4896 : condition is true or false, respectively. If null, we should generate
4897 : our own to skip over the evaluation of this specific expression.
4898 :
4899 : LOCUS is the source location of the COND_EXPR.
4900 :
4901 : The condition_uid is a discriminator tag for condition coverage used to map
4902 : conditions to its corresponding full Boolean function.
4903 :
4904 : This function is the tree equivalent of do_jump.
4905 :
4906 : shortcut_cond_r should only be called by shortcut_cond_expr. */
4907 :
4908 : static tree
4909 1320406 : shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
4910 : location_t locus, unsigned condition_uid)
4911 : {
4912 1320406 : tree local_label = NULL_TREE;
4913 1320406 : tree t, expr = NULL;
4914 :
4915 : /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
4916 : retain the shortcut semantics. Just insert the gotos here;
4917 : shortcut_cond_expr will append the real blocks later. */
4918 1320406 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
4919 : {
4920 123719 : location_t new_locus;
4921 :
4922 : /* Turn if (a && b) into
4923 :
4924 : if (a); else goto no;
4925 : if (b) goto yes; else goto no;
4926 : (no:) */
4927 :
4928 123719 : if (false_label_p == NULL)
4929 3985 : false_label_p = &local_label;
4930 :
4931 : /* Keep the original source location on the first 'if'. */
4932 123719 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus,
4933 : condition_uid);
4934 123719 : append_to_statement_list (t, &expr);
4935 :
4936 : /* Set the source location of the && on the second 'if'. */
4937 123719 : new_locus = rexpr_location (pred, locus);
4938 123719 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4939 : new_locus, condition_uid);
4940 123719 : append_to_statement_list (t, &expr);
4941 : }
4942 1196687 : else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
4943 : {
4944 382283 : location_t new_locus;
4945 :
4946 : /* Turn if (a || b) into
4947 :
4948 : if (a) goto yes;
4949 : if (b) goto yes; else goto no;
4950 : (yes:) */
4951 :
4952 382283 : if (true_label_p == NULL)
4953 228764 : true_label_p = &local_label;
4954 :
4955 : /* Keep the original source location on the first 'if'. */
4956 382283 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus,
4957 : condition_uid);
4958 382283 : append_to_statement_list (t, &expr);
4959 :
4960 : /* Set the source location of the || on the second 'if'. */
4961 382283 : new_locus = rexpr_location (pred, locus);
4962 382283 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4963 : new_locus, condition_uid);
4964 382283 : append_to_statement_list (t, &expr);
4965 : }
4966 814404 : else if (TREE_CODE (pred) == COND_EXPR
4967 852 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
4968 815256 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
4969 : {
4970 846 : location_t new_locus;
4971 :
4972 : /* As long as we're messing with gotos, turn if (a ? b : c) into
4973 : if (a)
4974 : if (b) goto yes; else goto no;
4975 : else
4976 : if (c) goto yes; else goto no;
4977 :
4978 : Don't do this if one of the arms has void type, which can happen
4979 : in C++ when the arm is throw. */
4980 :
4981 : /* Keep the original source location on the first 'if'. Set the source
4982 : location of the ? on the second 'if'. */
4983 846 : new_locus = rexpr_location (pred, locus);
4984 1692 : expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
4985 846 : shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
4986 : false_label_p, locus, condition_uid),
4987 846 : shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
4988 : false_label_p, new_locus,
4989 : condition_uid));
4990 846 : tree_associate_condition_with_expr (expr, condition_uid);
4991 : }
4992 : else
4993 : {
4994 813558 : expr = build3 (COND_EXPR, void_type_node, pred,
4995 : build_and_jump (true_label_p),
4996 : build_and_jump (false_label_p));
4997 813558 : SET_EXPR_LOCATION (expr, locus);
4998 813558 : tree_associate_condition_with_expr (expr, condition_uid);
4999 : }
5000 :
5001 1320406 : if (local_label)
5002 : {
5003 232749 : t = build1 (LABEL_EXPR, void_type_node, local_label);
5004 232749 : append_to_statement_list (t, &expr);
5005 : }
5006 :
5007 1320406 : return expr;
5008 : }
5009 :
5010 : /* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip
5011 : any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
5012 : statement, if it is the last one. Otherwise, return NULL. */
5013 :
5014 : static tree
5015 11624114 : find_goto (tree expr)
5016 : {
5017 11961818 : if (!expr)
5018 : return NULL_TREE;
5019 :
5020 10008327 : if (TREE_CODE (expr) == GOTO_EXPR)
5021 : return expr;
5022 :
5023 7987123 : if (TREE_CODE (expr) != STATEMENT_LIST)
5024 : return NULL_TREE;
5025 :
5026 1054111 : tree_stmt_iterator i = tsi_start (expr);
5027 :
5028 1415231 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
5029 361120 : tsi_next (&i);
5030 :
5031 10550405 : if (!tsi_one_before_end_p (i))
5032 : return NULL_TREE;
5033 :
5034 337704 : return find_goto (tsi_stmt (i));
5035 : }
5036 :
5037 : /* Same as find_goto, except that it returns NULL if the destination
5038 : is not a LABEL_DECL. */
5039 :
5040 : static inline tree
5041 11624114 : find_goto_label (tree expr)
5042 : {
5043 11624114 : tree dest = find_goto (expr);
5044 13645318 : if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
5045 2021093 : return dest;
5046 : return NULL_TREE;
5047 : }
5048 :
5049 :
5050 : /* Given a multi-term condition (ANDIF, ORIF), walk the predicate PRED and tag
5051 : every basic condition with CONDITION_UID. Two basic conditions share the
5052 : CONDITION_UID discriminator when they belong to the same predicate, which is
5053 : used by the condition coverage. Doing this as an explicit step makes for a
5054 : simpler implementation than weaving it into the splitting code as the
5055 : splitting code eventually calls the entry point gimplfiy_expr which makes
5056 : bookkeeping complicated. */
5057 : static void
5058 569829 : tag_shortcut_cond (tree pred, unsigned condition_uid)
5059 : {
5060 609007 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR
5061 609007 : || TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5062 : {
5063 559488 : tree fst = TREE_OPERAND (pred, 0);
5064 559488 : tree lst = TREE_OPERAND (pred, 1);
5065 :
5066 559488 : if (TREE_CODE (fst) == TRUTH_ANDIF_EXPR
5067 559488 : || TREE_CODE (fst) == TRUTH_ORIF_EXPR)
5068 167773 : tag_shortcut_cond (fst, condition_uid);
5069 391715 : else if (TREE_CODE (fst) == COND_EXPR)
5070 244 : tree_associate_condition_with_expr (fst, condition_uid);
5071 :
5072 559488 : if (TREE_CODE (lst) == TRUTH_ANDIF_EXPR
5073 559488 : || TREE_CODE (lst) == TRUTH_ORIF_EXPR)
5074 : tag_shortcut_cond (lst, condition_uid);
5075 520310 : else if (TREE_CODE (lst) == COND_EXPR)
5076 445 : tree_associate_condition_with_expr (lst, condition_uid);
5077 : }
5078 569829 : }
5079 :
5080 : /* Given a conditional expression EXPR with short-circuit boolean
5081 : predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
5082 : predicate apart into the equivalent sequence of conditionals. CONDITION_UID
5083 : is a the tag/discriminator for this EXPR - all basic conditions in the
5084 : expression will be given the same CONDITION_UID. */
5085 : static tree
5086 402056 : shortcut_cond_expr (tree expr, unsigned condition_uid)
5087 : {
5088 402056 : tree pred = TREE_OPERAND (expr, 0);
5089 402056 : tree then_ = TREE_OPERAND (expr, 1);
5090 402056 : tree else_ = TREE_OPERAND (expr, 2);
5091 402056 : tree true_label, false_label, end_label, t;
5092 402056 : tree *true_label_p;
5093 402056 : tree *false_label_p;
5094 402056 : bool emit_end, emit_false, jump_over_else;
5095 402056 : bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
5096 402056 : bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
5097 :
5098 402056 : tag_shortcut_cond (pred, condition_uid);
5099 :
5100 : /* First do simple transformations. */
5101 402056 : if (!else_se)
5102 : {
5103 : /* If there is no 'else', turn
5104 : if (a && b) then c
5105 : into
5106 : if (a) if (b) then c. */
5107 289135 : while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
5108 : {
5109 : /* Keep the original source location on the first 'if'. */
5110 50370 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5111 50370 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5112 : /* Set the source location of the && on the second 'if'. */
5113 50370 : if (rexpr_has_location (pred))
5114 49346 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5115 50370 : then_ = shortcut_cond_expr (expr, condition_uid);
5116 50370 : then_se = then_ && TREE_SIDE_EFFECTS (then_);
5117 50370 : pred = TREE_OPERAND (pred, 0);
5118 50370 : expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
5119 50370 : SET_EXPR_LOCATION (expr, locus);
5120 : }
5121 : }
5122 :
5123 402056 : if (!then_se)
5124 : {
5125 : /* If there is no 'then', turn
5126 : if (a || b); else d
5127 : into
5128 : if (a); else if (b); else d. */
5129 25564 : while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5130 : {
5131 : /* Keep the original source location on the first 'if'. */
5132 795 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5133 795 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5134 : /* Set the source location of the || on the second 'if'. */
5135 795 : if (rexpr_has_location (pred))
5136 794 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5137 795 : else_ = shortcut_cond_expr (expr, condition_uid);
5138 795 : else_se = else_ && TREE_SIDE_EFFECTS (else_);
5139 795 : pred = TREE_OPERAND (pred, 0);
5140 795 : expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
5141 795 : SET_EXPR_LOCATION (expr, locus);
5142 : }
5143 : }
5144 :
5145 : /* The expr tree should also have the expression id set. */
5146 402056 : tree_associate_condition_with_expr (expr, condition_uid);
5147 :
5148 : /* If we're done, great. */
5149 402056 : if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR
5150 402056 : && TREE_CODE (pred) != TRUTH_ORIF_EXPR)
5151 95346 : return expr;
5152 :
5153 : /* Otherwise we need to mess with gotos. Change
5154 : if (a) c; else d;
5155 : to
5156 : if (a); else goto no;
5157 : c; goto end;
5158 : no: d; end:
5159 : and recursively gimplify the condition. */
5160 :
5161 306710 : true_label = false_label = end_label = NULL_TREE;
5162 :
5163 : /* If our arms just jump somewhere, hijack those labels so we don't
5164 : generate jumps to jumps. */
5165 :
5166 306710 : if (tree then_goto = find_goto_label (then_))
5167 : {
5168 4614 : true_label = GOTO_DESTINATION (then_goto);
5169 4614 : then_ = NULL;
5170 4614 : then_se = false;
5171 : }
5172 :
5173 306710 : if (tree else_goto = find_goto_label (else_))
5174 : {
5175 4207 : false_label = GOTO_DESTINATION (else_goto);
5176 4207 : else_ = NULL;
5177 4207 : else_se = false;
5178 : }
5179 :
5180 : /* If we aren't hijacking a label for the 'then' branch, it falls through. */
5181 306710 : if (true_label)
5182 : true_label_p = &true_label;
5183 : else
5184 302096 : true_label_p = NULL;
5185 :
5186 : /* The 'else' branch also needs a label if it contains interesting code. */
5187 306710 : if (false_label || else_se)
5188 : false_label_p = &false_label;
5189 : else
5190 : false_label_p = NULL;
5191 :
5192 : /* If there was nothing else in our arms, just forward the label(s). */
5193 148593 : if (!then_se && !else_se)
5194 8558 : return shortcut_cond_r (pred, true_label_p, false_label_p,
5195 12837 : EXPR_LOC_OR_LOC (expr, input_location), condition_uid);
5196 :
5197 : /* If our last subexpression already has a terminal label, reuse it. */
5198 302431 : if (else_se)
5199 158117 : t = expr_last (else_);
5200 144314 : else if (then_se)
5201 144314 : t = expr_last (then_);
5202 : else
5203 : t = NULL;
5204 302431 : if (t && TREE_CODE (t) == LABEL_EXPR)
5205 1011 : end_label = LABEL_EXPR_LABEL (t);
5206 :
5207 : /* If we don't care about jumping to the 'else' branch, jump to the end
5208 : if the condition is false. */
5209 302431 : if (!false_label_p)
5210 144072 : false_label_p = &end_label;
5211 :
5212 : /* We only want to emit these labels if we aren't hijacking them. */
5213 302431 : emit_end = (end_label == NULL_TREE);
5214 302431 : emit_false = (false_label == NULL_TREE);
5215 :
5216 : /* We only emit the jump over the else clause if we have to--if the
5217 : then clause may fall through. Otherwise we can wind up with a
5218 : useless jump and a useless label at the end of gimplified code,
5219 : which will cause us to think that this conditional as a whole
5220 : falls through even if it doesn't. If we then inline a function
5221 : which ends with such a condition, that can cause us to issue an
5222 : inappropriate warning about control reaching the end of a
5223 : non-void function. */
5224 302431 : jump_over_else = block_may_fallthru (then_);
5225 :
5226 604239 : pred = shortcut_cond_r (pred, true_label_p, false_label_p,
5227 604239 : EXPR_LOC_OR_LOC (expr, input_location),
5228 : condition_uid);
5229 :
5230 302431 : expr = NULL;
5231 302431 : append_to_statement_list (pred, &expr);
5232 :
5233 302431 : append_to_statement_list (then_, &expr);
5234 302431 : if (else_se)
5235 : {
5236 158117 : if (jump_over_else)
5237 : {
5238 155680 : tree last = expr_last (expr);
5239 155680 : t = build_and_jump (&end_label);
5240 155680 : if (rexpr_has_location (last))
5241 37576 : SET_EXPR_LOCATION (t, rexpr_location (last));
5242 155680 : append_to_statement_list (t, &expr);
5243 : }
5244 158117 : if (emit_false)
5245 : {
5246 158117 : t = build1 (LABEL_EXPR, void_type_node, false_label);
5247 158117 : append_to_statement_list (t, &expr);
5248 : }
5249 158117 : append_to_statement_list (else_, &expr);
5250 : }
5251 302431 : if (emit_end && end_label)
5252 : {
5253 298746 : t = build1 (LABEL_EXPR, void_type_node, end_label);
5254 298746 : append_to_statement_list (t, &expr);
5255 : }
5256 :
5257 302431 : return expr;
5258 : }
5259 :
5260 : /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */
5261 :
5262 : tree
5263 16661496 : gimple_boolify (tree expr)
5264 : {
5265 16661496 : tree type = TREE_TYPE (expr);
5266 16661496 : location_t loc = EXPR_LOCATION (expr);
5267 :
5268 16661496 : if (TREE_CODE (expr) == NE_EXPR
5269 5744870 : && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
5270 17610939 : && integer_zerop (TREE_OPERAND (expr, 1)))
5271 : {
5272 493595 : tree call = TREE_OPERAND (expr, 0);
5273 493595 : tree fn = get_callee_fndecl (call);
5274 :
5275 : /* For __builtin_expect ((long) (x), y) recurse into x as well
5276 : if x is truth_value_p. */
5277 493595 : if (fn
5278 492624 : && fndecl_built_in_p (fn, BUILT_IN_EXPECT)
5279 631876 : && call_expr_nargs (call) == 2)
5280 : {
5281 138281 : tree arg = CALL_EXPR_ARG (call, 0);
5282 138281 : if (arg)
5283 : {
5284 138281 : if (TREE_CODE (arg) == NOP_EXPR
5285 138281 : && TREE_TYPE (arg) == TREE_TYPE (call))
5286 65216 : arg = TREE_OPERAND (arg, 0);
5287 138281 : if (truth_value_p (TREE_CODE (arg)))
5288 : {
5289 114815 : arg = gimple_boolify (arg);
5290 114815 : CALL_EXPR_ARG (call, 0)
5291 229630 : = fold_convert_loc (loc, TREE_TYPE (call), arg);
5292 : }
5293 : }
5294 : }
5295 : }
5296 :
5297 16661496 : switch (TREE_CODE (expr))
5298 : {
5299 1237774 : case TRUTH_AND_EXPR:
5300 1237774 : case TRUTH_OR_EXPR:
5301 1237774 : case TRUTH_XOR_EXPR:
5302 1237774 : case TRUTH_ANDIF_EXPR:
5303 1237774 : case TRUTH_ORIF_EXPR:
5304 : /* Also boolify the arguments of truth exprs. */
5305 1237774 : TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
5306 : /* FALLTHRU */
5307 :
5308 1666880 : case TRUTH_NOT_EXPR:
5309 1666880 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5310 :
5311 : /* These expressions always produce boolean results. */
5312 1666880 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5313 307004 : TREE_TYPE (expr) = boolean_type_node;
5314 : return expr;
5315 :
5316 5299 : case ANNOTATE_EXPR:
5317 5299 : switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)))
5318 : {
5319 5299 : case annot_expr_ivdep_kind:
5320 5299 : case annot_expr_unroll_kind:
5321 5299 : case annot_expr_no_vector_kind:
5322 5299 : case annot_expr_vector_kind:
5323 5299 : case annot_expr_parallel_kind:
5324 5299 : case annot_expr_maybe_infinite_kind:
5325 5299 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5326 5299 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5327 3335 : TREE_TYPE (expr) = boolean_type_node;
5328 : return expr;
5329 0 : default:
5330 0 : gcc_unreachable ();
5331 : }
5332 :
5333 14989317 : default:
5334 14989317 : if (COMPARISON_CLASS_P (expr))
5335 : {
5336 : /* These expressions always produce boolean results. */
5337 13100174 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5338 1597513 : TREE_TYPE (expr) = boolean_type_node;
5339 13100174 : return expr;
5340 : }
5341 : /* Other expressions that get here must have boolean values, but
5342 : might need to be converted to the appropriate mode. */
5343 1889143 : if (TREE_CODE (type) == BOOLEAN_TYPE)
5344 : return expr;
5345 203311 : return fold_convert_loc (loc, boolean_type_node, expr);
5346 : }
5347 : }
5348 :
5349 : /* Given a conditional expression *EXPR_P without side effects, gimplify
5350 : its operands. New statements are inserted to PRE_P. */
5351 :
5352 : static enum gimplify_status
5353 45960 : gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
5354 : {
5355 45960 : tree expr = *expr_p, cond;
5356 45960 : enum gimplify_status ret, tret;
5357 45960 : enum tree_code code;
5358 :
5359 45960 : cond = gimple_boolify (COND_EXPR_COND (expr));
5360 :
5361 : /* We need to handle && and || specially, as their gimplification
5362 : creates pure cond_expr, thus leading to an infinite cycle otherwise. */
5363 45960 : code = TREE_CODE (cond);
5364 45960 : if (code == TRUTH_ANDIF_EXPR)
5365 35 : TREE_SET_CODE (cond, TRUTH_AND_EXPR);
5366 45925 : else if (code == TRUTH_ORIF_EXPR)
5367 4638 : TREE_SET_CODE (cond, TRUTH_OR_EXPR);
5368 45960 : ret = gimplify_expr (&cond, pre_p, NULL, is_gimple_val, fb_rvalue);
5369 45960 : COND_EXPR_COND (*expr_p) = cond;
5370 :
5371 45960 : tret = gimplify_expr (&COND_EXPR_THEN (expr), pre_p, NULL,
5372 : is_gimple_val, fb_rvalue);
5373 45960 : ret = MIN (ret, tret);
5374 45960 : tret = gimplify_expr (&COND_EXPR_ELSE (expr), pre_p, NULL,
5375 : is_gimple_val, fb_rvalue);
5376 :
5377 45960 : return MIN (ret, tret);
5378 : }
5379 :
5380 : /* Return true if evaluating EXPR could trap.
5381 : EXPR is GENERIC, while tree_could_trap_p can be called
5382 : only on GIMPLE. */
5383 :
5384 : bool
5385 16602893 : generic_expr_could_trap_p (tree expr)
5386 : {
5387 16602893 : unsigned i, n;
5388 :
5389 16602893 : if (!expr || is_gimple_val (expr))
5390 7373208 : return false;
5391 :
5392 9229685 : if (!EXPR_P (expr) || tree_could_trap_p (expr))
5393 2440626 : return true;
5394 :
5395 6789059 : n = TREE_OPERAND_LENGTH (expr);
5396 16280552 : for (i = 0; i < n; i++)
5397 11784561 : if (generic_expr_could_trap_p (TREE_OPERAND (expr, i)))
5398 : return true;
5399 :
5400 : return false;
5401 : }
5402 :
5403 : /* Associate the condition STMT with the discriminator UID. STMTs that are
5404 : broken down with ANDIF/ORIF from the same Boolean expression should be given
5405 : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
5406 : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
5407 : for condition coverage. */
5408 : static void
5409 5505347 : gimple_associate_condition_with_expr (struct function *fn, gcond *stmt,
5410 : unsigned uid)
5411 : {
5412 5505347 : if (!condition_coverage_flag)
5413 : return;
5414 :
5415 641 : if (!fn->cond_uids)
5416 139 : fn->cond_uids = new hash_map <gcond*, unsigned> ();
5417 :
5418 641 : fn->cond_uids->put (stmt, uid);
5419 : }
5420 :
5421 : /* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
5422 : into
5423 :
5424 : if (p) if (p)
5425 : t1 = a; a;
5426 : else or else
5427 : t1 = b; b;
5428 : t1;
5429 :
5430 : The second form is used when *EXPR_P is of type void.
5431 :
5432 : PRE_P points to the list where side effects that must happen before
5433 : *EXPR_P should be stored. */
5434 :
5435 : static enum gimplify_status
5436 6274925 : gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
5437 : {
5438 6274925 : tree expr = *expr_p;
5439 6274925 : tree type = TREE_TYPE (expr);
5440 6274925 : location_t loc = EXPR_LOCATION (expr);
5441 6274925 : tree tmp, arm1, arm2;
5442 6274925 : enum gimplify_status ret;
5443 6274925 : tree label_true, label_false, label_cont;
5444 6274925 : bool have_then_clause_p, have_else_clause_p;
5445 6274925 : gcond *cond_stmt;
5446 6274925 : enum tree_code pred_code;
5447 6274925 : gimple_seq seq = NULL;
5448 :
5449 : /* If this COND_EXPR has a value, copy the values into a temporary within
5450 : the arms. */
5451 6274925 : if (!VOID_TYPE_P (type))
5452 : {
5453 417911 : tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
5454 417911 : tree result;
5455 :
5456 : /* If either an rvalue is ok or we do not require an lvalue, create the
5457 : temporary. But we cannot do that if the type is addressable. */
5458 417911 : if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
5459 417904 : && !TREE_ADDRESSABLE (type))
5460 : {
5461 417904 : if (gimplify_ctxp->allow_rhs_cond_expr
5462 : /* If either branch has side effects or could trap, it can't be
5463 : evaluated unconditionally. */
5464 45960 : && !TREE_SIDE_EFFECTS (then_)
5465 45960 : && !generic_expr_could_trap_p (then_)
5466 45960 : && !TREE_SIDE_EFFECTS (else_)
5467 463864 : && !generic_expr_could_trap_p (else_))
5468 45960 : return gimplify_pure_cond_expr (expr_p, pre_p);
5469 :
5470 371944 : tmp = create_tmp_var (type, "iftmp");
5471 371944 : result = tmp;
5472 : }
5473 :
5474 : /* Otherwise, only create and copy references to the values. */
5475 : else
5476 : {
5477 7 : type = build_pointer_type (type);
5478 :
5479 7 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5480 7 : then_ = build_fold_addr_expr_loc (loc, then_);
5481 :
5482 7 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5483 7 : else_ = build_fold_addr_expr_loc (loc, else_);
5484 :
5485 7 : expr
5486 7 : = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
5487 :
5488 7 : tmp = create_tmp_var (type, "iftmp");
5489 7 : result = build_simple_mem_ref_loc (loc, tmp);
5490 : }
5491 :
5492 : /* Build the new then clause, `tmp = then_;'. But don't build the
5493 : assignment if the value is void; in C++ it can be if it's a throw. */
5494 371951 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5495 290391 : TREE_OPERAND (expr, 1) = build2 (INIT_EXPR, type, tmp, then_);
5496 :
5497 : /* Similarly, build the new else clause, `tmp = else_;'. */
5498 371951 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5499 361315 : TREE_OPERAND (expr, 2) = build2 (INIT_EXPR, type, tmp, else_);
5500 :
5501 371951 : TREE_TYPE (expr) = void_type_node;
5502 371951 : recalculate_side_effects (expr);
5503 :
5504 : /* Move the COND_EXPR to the prequeue. */
5505 371951 : gimplify_stmt (&expr, pre_p);
5506 :
5507 371951 : *expr_p = result;
5508 371951 : return GS_ALL_DONE;
5509 : }
5510 :
5511 : /* Remove any COMPOUND_EXPR so the following cases will be caught. */
5512 5872573 : STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
5513 5857014 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
5514 80991 : gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
5515 :
5516 : /* Make sure the condition has BOOLEAN_TYPE. */
5517 5857014 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5518 :
5519 : /* Break apart && and || conditions. */
5520 5857014 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
5521 5857014 : || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
5522 : {
5523 350891 : expr = shortcut_cond_expr (expr, next_cond_uid ());
5524 :
5525 350891 : if (expr != *expr_p)
5526 : {
5527 350891 : *expr_p = expr;
5528 :
5529 : /* We can't rely on gimplify_expr to re-gimplify the expanded
5530 : form properly, as cleanups might cause the target labels to be
5531 : wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to
5532 : set up a conditional context. */
5533 350891 : gimple_push_condition ();
5534 350891 : gimplify_stmt (expr_p, &seq);
5535 350891 : gimple_pop_condition (pre_p);
5536 350891 : gimple_seq_add_seq (pre_p, seq);
5537 :
5538 350891 : return GS_ALL_DONE;
5539 : }
5540 : }
5541 :
5542 : /* Now do the normal gimplification. */
5543 :
5544 : /* Gimplify condition. */
5545 5506123 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
5546 : is_gimple_condexpr_for_cond, fb_rvalue);
5547 5506123 : if (ret == GS_ERROR)
5548 : return GS_ERROR;
5549 5505347 : gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
5550 :
5551 5505347 : gimple_push_condition ();
5552 :
5553 5505347 : have_then_clause_p = have_else_clause_p = false;
5554 5505347 : label_true = find_goto_label (TREE_OPERAND (expr, 1));
5555 5505347 : if (label_true
5556 1287166 : && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
5557 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5558 : have different locations, otherwise we end up with incorrect
5559 : location information on the branches. */
5560 6792513 : && (optimize
5561 237783 : || !EXPR_HAS_LOCATION (expr)
5562 210907 : || !rexpr_has_location (label_true)
5563 75131 : || EXPR_LOCATION (expr) == rexpr_location (label_true)))
5564 : {
5565 1286004 : have_then_clause_p = true;
5566 1286004 : label_true = GOTO_DESTINATION (label_true);
5567 : }
5568 : else
5569 4219343 : label_true = create_artificial_label (UNKNOWN_LOCATION);
5570 5505347 : label_false = find_goto_label (TREE_OPERAND (expr, 2));
5571 5505347 : if (label_false
5572 725106 : && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
5573 : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5574 : have different locations, otherwise we end up with incorrect
5575 : location information on the branches. */
5576 6230453 : && (optimize
5577 104436 : || !EXPR_HAS_LOCATION (expr)
5578 103554 : || !rexpr_has_location (label_false)
5579 110 : || EXPR_LOCATION (expr) == rexpr_location (label_false)))
5580 : {
5581 725008 : have_else_clause_p = true;
5582 725008 : label_false = GOTO_DESTINATION (label_false);
5583 : }
5584 : else
5585 4780339 : label_false = create_artificial_label (UNKNOWN_LOCATION);
5586 :
5587 5505347 : unsigned cond_uid = 0;
5588 5505347 : if (cond_uids)
5589 455 : if (unsigned *v = cond_uids->get (expr))
5590 435 : cond_uid = *v;
5591 435 : if (cond_uid == 0)
5592 5504912 : cond_uid = next_cond_uid ();
5593 :
5594 5505347 : gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
5595 : &arm2);
5596 5505347 : cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
5597 : label_false);
5598 5505347 : gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
5599 5505347 : gimple_associate_condition_with_expr (cfun, cond_stmt, cond_uid);
5600 5505347 : copy_warning (cond_stmt, COND_EXPR_COND (expr));
5601 5505347 : gimplify_seq_add_stmt (&seq, cond_stmt);
5602 5505347 : gimple_stmt_iterator gsi = gsi_last (seq);
5603 5505347 : maybe_fold_stmt (&gsi);
5604 :
5605 5505347 : label_cont = NULL_TREE;
5606 5505347 : if (!have_then_clause_p)
5607 : {
5608 : /* For if (...) {} else { code; } put label_true after
5609 : the else block. */
5610 4219343 : if (TREE_OPERAND (expr, 1) == NULL_TREE
5611 199173 : && !have_else_clause_p
5612 4220111 : && TREE_OPERAND (expr, 2) != NULL_TREE)
5613 : {
5614 : /* For if (0) {} else { code; } tell -Wimplicit-fallthrough
5615 : handling that label_cont == label_true can be only reached
5616 : through fallthrough from { code; }. */
5617 768 : if (integer_zerop (COND_EXPR_COND (expr)))
5618 0 : UNUSED_LABEL_P (label_true) = 1;
5619 : label_cont = label_true;
5620 : }
5621 : else
5622 : {
5623 4218575 : bool then_side_effects
5624 4218575 : = (TREE_OPERAND (expr, 1)
5625 4218575 : && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)));
5626 4218575 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
5627 4218575 : have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
5628 : /* For if (...) { code; } else {} or
5629 : if (...) { code; } else goto label; or
5630 : if (...) { code; return; } else { ... }
5631 : label_cont isn't needed. */
5632 4218575 : if (!have_else_clause_p
5633 4019024 : && TREE_OPERAND (expr, 2) != NULL_TREE
5634 7014325 : && gimple_seq_may_fallthru (seq))
5635 : {
5636 1944209 : gimple *g;
5637 1944209 : label_cont = create_artificial_label (UNKNOWN_LOCATION);
5638 :
5639 : /* For if (0) { non-side-effect-code } else { code }
5640 : tell -Wimplicit-fallthrough handling that label_cont can
5641 : be only reached through fallthrough from { code }. */
5642 1944209 : if (integer_zerop (COND_EXPR_COND (expr)))
5643 : {
5644 75735 : UNUSED_LABEL_P (label_true) = 1;
5645 75735 : if (!then_side_effects)
5646 12428 : UNUSED_LABEL_P (label_cont) = 1;
5647 : }
5648 :
5649 1944209 : g = gimple_build_goto (label_cont);
5650 :
5651 : /* GIMPLE_COND's are very low level; they have embedded
5652 : gotos. This particular embedded goto should not be marked
5653 : with the location of the original COND_EXPR, as it would
5654 : correspond to the COND_EXPR's condition, not the ELSE or the
5655 : THEN arms. To avoid marking it with the wrong location, flag
5656 : it as "no location". */
5657 1944209 : gimple_set_do_not_emit_location (g);
5658 :
5659 1944209 : gimplify_seq_add_stmt (&seq, g);
5660 : }
5661 : }
5662 : }
5663 5505347 : if (!have_else_clause_p)
5664 : {
5665 : /* For if (1) { code } or if (1) { code } else { non-side-effect-code }
5666 : tell -Wimplicit-fallthrough handling that label_false can be only
5667 : reached through fallthrough from { code }. */
5668 4780339 : if (integer_nonzerop (COND_EXPR_COND (expr))
5669 4780339 : && (TREE_OPERAND (expr, 2) == NULL_TREE
5670 56840 : || !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2))))
5671 7855 : UNUSED_LABEL_P (label_false) = 1;
5672 4780339 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_false));
5673 4780339 : have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq);
5674 : }
5675 5505347 : if (label_cont)
5676 1944977 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_cont));
5677 :
5678 5505347 : gimple_pop_condition (pre_p);
5679 5505347 : gimple_seq_add_seq (pre_p, seq);
5680 :
5681 5505347 : if (ret == GS_ERROR)
5682 : ; /* Do nothing. */
5683 5505347 : else if (have_then_clause_p || have_else_clause_p)
5684 : ret = GS_ALL_DONE;
5685 : else
5686 : {
5687 : /* Both arms are empty; replace the COND_EXPR with its predicate. */
5688 2841 : expr = TREE_OPERAND (expr, 0);
5689 2841 : gimplify_stmt (&expr, pre_p);
5690 : }
5691 :
5692 5505347 : *expr_p = NULL;
5693 5505347 : return ret;
5694 : }
5695 :
5696 : /* Prepare the node pointed to by EXPR_P, an is_gimple_addressable expression,
5697 : to be marked addressable.
5698 :
5699 : We cannot rely on such an expression being directly markable if a temporary
5700 : has been created by the gimplification. In this case, we create another
5701 : temporary and initialize it with a copy, which will become a store after we
5702 : mark it addressable. This can happen if the front-end passed us something
5703 : that it could not mark addressable yet, like a Fortran pass-by-reference
5704 : parameter (int) floatvar. */
5705 :
5706 : static void
5707 56438934 : prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
5708 : {
5709 61946983 : while (handled_component_p (*expr_p))
5710 5508049 : expr_p = &TREE_OPERAND (*expr_p, 0);
5711 :
5712 : /* Do not allow an SSA name as the temporary. */
5713 56438934 : if (is_gimple_reg (*expr_p))
5714 12081 : *expr_p = internal_get_tmp_var (*expr_p, seq_p, NULL, false, false, true);
5715 56438934 : }
5716 :
5717 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5718 : a call to __builtin_memcpy. */
5719 :
5720 : static enum gimplify_status
5721 1100 : gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
5722 : gimple_seq *seq_p)
5723 : {
5724 1100 : tree t, to, to_ptr, from, from_ptr;
5725 1100 : gcall *gs;
5726 1100 : location_t loc = EXPR_LOCATION (*expr_p);
5727 :
5728 1100 : to = TREE_OPERAND (*expr_p, 0);
5729 1100 : from = TREE_OPERAND (*expr_p, 1);
5730 1100 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to)))
5731 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))));
5732 :
5733 : /* Mark the RHS addressable. Beware that it may not be possible to do so
5734 : directly if a temporary has been created by the gimplification. */
5735 1100 : prepare_gimple_addressable (&from, seq_p);
5736 :
5737 1100 : mark_addressable (from);
5738 1100 : from_ptr = build_fold_addr_expr_loc (loc, from);
5739 1100 : gimplify_arg (&from_ptr, seq_p, loc);
5740 :
5741 1100 : mark_addressable (to);
5742 1100 : to_ptr = build_fold_addr_expr_loc (loc, to);
5743 1100 : gimplify_arg (&to_ptr, seq_p, loc);
5744 :
5745 1100 : t = builtin_decl_implicit (BUILT_IN_MEMCPY);
5746 :
5747 1100 : gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
5748 1100 : gimple_call_set_alloca_for_var (gs, true);
5749 :
5750 1100 : if (want_value)
5751 : {
5752 : /* tmp = memcpy() */
5753 8 : t = create_tmp_var (TREE_TYPE (to_ptr));
5754 8 : gimple_call_set_lhs (gs, t);
5755 8 : gimplify_seq_add_stmt (seq_p, gs);
5756 :
5757 8 : *expr_p = build_simple_mem_ref (t);
5758 8 : return GS_ALL_DONE;
5759 : }
5760 :
5761 1092 : gimplify_seq_add_stmt (seq_p, gs);
5762 1092 : *expr_p = NULL;
5763 1092 : return GS_ALL_DONE;
5764 : }
5765 :
5766 : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5767 : a call to __builtin_memset. In this case we know that the RHS is
5768 : a CONSTRUCTOR with an empty element list. */
5769 :
5770 : static enum gimplify_status
5771 84 : gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
5772 : gimple_seq *seq_p)
5773 : {
5774 84 : tree t, from, to, to_ptr;
5775 84 : gcall *gs;
5776 84 : location_t loc = EXPR_LOCATION (*expr_p);
5777 :
5778 : /* Assert our assumptions, to abort instead of producing wrong code
5779 : silently if they are not met. Beware that the RHS CONSTRUCTOR might
5780 : not be immediately exposed. */
5781 84 : from = TREE_OPERAND (*expr_p, 1);
5782 84 : if (TREE_CODE (from) == WITH_SIZE_EXPR)
5783 84 : from = TREE_OPERAND (from, 0);
5784 :
5785 84 : gcc_assert (TREE_CODE (from) == CONSTRUCTOR
5786 : && vec_safe_is_empty (CONSTRUCTOR_ELTS (from)));
5787 :
5788 : /* Now proceed. */
5789 84 : to = TREE_OPERAND (*expr_p, 0);
5790 84 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to))));
5791 :
5792 84 : to_ptr = build_fold_addr_expr_loc (loc, to);
5793 84 : gimplify_arg (&to_ptr, seq_p, loc);
5794 84 : t = builtin_decl_implicit (BUILT_IN_MEMSET);
5795 :
5796 84 : gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
5797 :
5798 84 : if (want_value)
5799 : {
5800 : /* tmp = memset() */
5801 0 : t = create_tmp_var (TREE_TYPE (to_ptr));
5802 0 : gimple_call_set_lhs (gs, t);
5803 0 : gimplify_seq_add_stmt (seq_p, gs);
5804 :
5805 0 : *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
5806 0 : return GS_ALL_DONE;
5807 : }
5808 :
5809 84 : gimplify_seq_add_stmt (seq_p, gs);
5810 84 : *expr_p = NULL;
5811 84 : return GS_ALL_DONE;
5812 : }
5813 :
5814 : /* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
5815 : determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
5816 : assignment. Return non-null if we detect a potential overlap. */
5817 :
5818 : struct gimplify_init_ctor_preeval_data
5819 : {
5820 : /* The base decl of the lhs object. May be NULL, in which case we
5821 : have to assume the lhs is indirect. */
5822 : tree lhs_base_decl;
5823 :
5824 : /* The alias set of the lhs object. */
5825 : alias_set_type lhs_alias_set;
5826 : };
5827 :
5828 : static tree
5829 116187 : gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
5830 : {
5831 116187 : struct gimplify_init_ctor_preeval_data *data
5832 : = (struct gimplify_init_ctor_preeval_data *) xdata;
5833 116187 : tree t = *tp;
5834 :
5835 : /* If we find the base object, obviously we have overlap. */
5836 116187 : if (data->lhs_base_decl == t)
5837 : return t;
5838 :
5839 : /* If the constructor component is indirect, determine if we have a
5840 : potential overlap with the lhs. The only bits of information we
5841 : have to go on at this point are addressability and alias sets. */
5842 116186 : if ((INDIRECT_REF_P (t)
5843 116186 : || TREE_CODE (t) == MEM_REF)
5844 651 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5845 116702 : && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
5846 : return t;
5847 :
5848 : /* If the constructor component is a call, determine if it can hide a
5849 : potential overlap with the lhs through an INDIRECT_REF like above.
5850 : ??? Ugh - this is completely broken. In fact this whole analysis
5851 : doesn't look conservative. */
5852 115670 : if (TREE_CODE (t) == CALL_EXPR)
5853 : {
5854 0 : tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
5855 :
5856 0 : for (type = TYPE_ARG_TYPES (fntype); type; type = TREE_CHAIN (type))
5857 0 : if (POINTER_TYPE_P (TREE_VALUE (type))
5858 0 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5859 0 : && alias_sets_conflict_p (data->lhs_alias_set,
5860 : get_alias_set
5861 0 : (TREE_TYPE (TREE_VALUE (type)))))
5862 : return t;
5863 : }
5864 :
5865 115670 : if (IS_TYPE_OR_DECL_P (t))
5866 10968 : *walk_subtrees = 0;
5867 : return NULL;
5868 : }
5869 :
5870 : /* A subroutine of gimplify_init_constructor. Pre-evaluate EXPR,
5871 : force values that overlap with the lhs (as described by *DATA)
5872 : into temporaries. */
5873 :
5874 : static void
5875 414306 : gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
5876 : struct gimplify_init_ctor_preeval_data *data)
5877 : {
5878 414306 : enum gimplify_status one;
5879 :
5880 : /* If the value is constant, then there's nothing to pre-evaluate. */
5881 414306 : if (TREE_CONSTANT (*expr_p))
5882 : {
5883 : /* Ensure it does not have side effects, it might contain a reference to
5884 : the object we're initializing. */
5885 196657 : gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
5886 : return;
5887 : }
5888 :
5889 : /* If the type has non-trivial constructors, we can't pre-evaluate. */
5890 217649 : if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
5891 : return;
5892 :
5893 : /* Recurse for nested constructors. */
5894 217649 : if (TREE_CODE (*expr_p) == CONSTRUCTOR)
5895 : {
5896 73690 : unsigned HOST_WIDE_INT ix;
5897 73690 : constructor_elt *ce;
5898 73690 : vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (*expr_p);
5899 :
5900 271222 : FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
5901 197532 : gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
5902 :
5903 : return;
5904 : }
5905 :
5906 : /* If this is a variable sized type, we must remember the size. */
5907 143959 : maybe_with_size_expr (expr_p);
5908 :
5909 : /* Gimplify the constructor element to something appropriate for the rhs
5910 : of a MODIFY_EXPR. Given that we know the LHS is an aggregate, we know
5911 : the gimplifier will consider this a store to memory. Doing this
5912 : gimplification now means that we won't have to deal with complicated
5913 : language-specific trees, nor trees like SAVE_EXPR that can induce
5914 : exponential search behavior. */
5915 143959 : one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
5916 143959 : if (one == GS_ERROR)
5917 : {
5918 0 : *expr_p = NULL;
5919 0 : return;
5920 : }
5921 :
5922 : /* If we gimplified to a bare decl, we can be sure that it doesn't overlap
5923 : with the lhs, since "a = { .x=a }" doesn't make sense. This will
5924 : always be true for all scalars, since is_gimple_mem_rhs insists on a
5925 : temporary variable for them. */
5926 143959 : if (DECL_P (*expr_p))
5927 : return;
5928 :
5929 : /* If this is of variable size, we have no choice but to assume it doesn't
5930 : overlap since we can't make a temporary for it. */
5931 104623 : if (TREE_CODE (TYPE_SIZE (TREE_TYPE (*expr_p))) != INTEGER_CST)
5932 : return;
5933 :
5934 : /* Otherwise, we must search for overlap ... */
5935 104623 : if (!walk_tree (expr_p, gimplify_init_ctor_preeval_1, data, NULL))
5936 : return;
5937 :
5938 : /* ... and if found, force the value into a temporary. */
5939 517 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
5940 : }
5941 :
5942 : /* A subroutine of gimplify_init_ctor_eval. Create a loop for
5943 : a RANGE_EXPR in a CONSTRUCTOR for an array.
5944 :
5945 : var = lower;
5946 : loop_entry:
5947 : object[var] = value;
5948 : if (var == upper)
5949 : goto loop_exit;
5950 : var = var + 1;
5951 : goto loop_entry;
5952 : loop_exit:
5953 :
5954 : We increment var _after_ the loop exit check because we might otherwise
5955 : fail if upper == TYPE_MAX_VALUE (type for upper).
5956 :
5957 : Note that we never have to deal with SAVE_EXPRs here, because this has
5958 : already been taken care of for us, in gimplify_init_ctor_preeval(). */
5959 :
5960 : static void gimplify_init_ctor_eval (tree, vec<constructor_elt, va_gc> *,
5961 : gimple_seq *, bool);
5962 :
5963 : static void
5964 447 : gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
5965 : tree value, tree array_elt_type,
5966 : gimple_seq *pre_p, bool cleared)
5967 : {
5968 447 : tree loop_entry_label, loop_exit_label, fall_thru_label;
5969 447 : tree var, var_type, cref, tmp;
5970 :
5971 447 : loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
5972 447 : loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
5973 447 : fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
5974 :
5975 : /* Create and initialize the index variable. */
5976 447 : var_type = TREE_TYPE (upper);
5977 447 : var = create_tmp_var (var_type);
5978 447 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
5979 :
5980 : /* Add the loop entry label. */
5981 447 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
5982 :
5983 : /* Build the reference. */
5984 447 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
5985 : var, NULL_TREE, NULL_TREE);
5986 :
5987 : /* If we are a constructor, just call gimplify_init_ctor_eval to do
5988 : the store. Otherwise just assign value to the reference. */
5989 :
5990 447 : if (TREE_CODE (value) == CONSTRUCTOR)
5991 : /* NB we might have to call ourself recursively through
5992 : gimplify_init_ctor_eval if the value is a constructor. */
5993 126 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
5994 : pre_p, cleared);
5995 : else
5996 : {
5997 321 : if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue)
5998 : != GS_ERROR)
5999 321 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
6000 : }
6001 :
6002 : /* We exit the loop when the index var is equal to the upper bound. */
6003 894 : gimplify_seq_add_stmt (pre_p,
6004 447 : gimple_build_cond (EQ_EXPR, var, upper,
6005 : loop_exit_label, fall_thru_label));
6006 :
6007 447 : gimplify_seq_add_stmt (pre_p, gimple_build_label (fall_thru_label));
6008 :
6009 : /* Otherwise, increment the index var... */
6010 447 : tmp = build2 (PLUS_EXPR, var_type, var,
6011 : fold_convert (var_type, integer_one_node));
6012 447 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
6013 :
6014 : /* ...and jump back to the loop entry. */
6015 447 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
6016 :
6017 : /* Add the loop exit label. */
6018 447 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
6019 447 : }
6020 :
6021 : /* A subroutine of gimplify_init_constructor. Generate individual
6022 : MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the
6023 : assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the
6024 : CONSTRUCTOR. CLEARED is true if the entire LHS object has been
6025 : zeroed first. */
6026 :
6027 : static void
6028 1266287 : gimplify_init_ctor_eval (tree object, vec<constructor_elt, va_gc> *elts,
6029 : gimple_seq *pre_p, bool cleared)
6030 : {
6031 1266287 : tree array_elt_type = NULL;
6032 1266287 : unsigned HOST_WIDE_INT ix;
6033 1266287 : tree purpose, value;
6034 :
6035 1266287 : if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
6036 142199 : array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
6037 :
6038 4672855 : FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
6039 : {
6040 3406568 : tree cref;
6041 :
6042 : /* NULL values are created above for gimplification errors. */
6043 3406568 : if (value == NULL)
6044 320835 : continue;
6045 :
6046 3406568 : if (cleared && initializer_zerop (value))
6047 320224 : continue;
6048 :
6049 : /* ??? Here's to hoping the front end fills in all of the indices,
6050 : so we don't have to figure out what's missing ourselves. */
6051 3086344 : gcc_assert (purpose);
6052 :
6053 : /* Skip zero-sized fields, unless value has side-effects. This can
6054 : happen with calls to functions returning a empty type, which
6055 : we shouldn't discard. As a number of downstream passes don't
6056 : expect sets of empty type fields, we rely on the gimplification of
6057 : the MODIFY_EXPR we make below to drop the assignment statement. */
6058 3086344 : if (!TREE_SIDE_EFFECTS (value)
6059 2792107 : && TREE_CODE (purpose) == FIELD_DECL
6060 5407348 : && is_empty_type (TREE_TYPE (purpose)))
6061 164 : continue;
6062 :
6063 : /* If we have a RANGE_EXPR, we have to build a loop to assign the
6064 : whole range. */
6065 3086180 : if (TREE_CODE (purpose) == RANGE_EXPR)
6066 : {
6067 457 : tree lower = TREE_OPERAND (purpose, 0);
6068 457 : tree upper = TREE_OPERAND (purpose, 1);
6069 :
6070 : /* If the lower bound is equal to upper, just treat it as if
6071 : upper was the index. */
6072 457 : if (simple_cst_equal (lower, upper))
6073 : purpose = upper;
6074 : else
6075 : {
6076 447 : gimplify_init_ctor_eval_range (object, lower, upper, value,
6077 : array_elt_type, pre_p, cleared);
6078 447 : continue;
6079 : }
6080 : }
6081 :
6082 3085733 : if (array_elt_type)
6083 : {
6084 : /* Do not use bitsizetype for ARRAY_REF indices. */
6085 561415 : if (TYPE_DOMAIN (TREE_TYPE (object)))
6086 561415 : purpose
6087 561415 : = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
6088 : purpose);
6089 561415 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
6090 : purpose, NULL_TREE, NULL_TREE);
6091 : }
6092 : else
6093 : {
6094 2524318 : gcc_assert (TREE_CODE (purpose) == FIELD_DECL);
6095 2524318 : cref = build3 (COMPONENT_REF, TREE_TYPE (purpose),
6096 : unshare_expr (object), purpose, NULL_TREE);
6097 : }
6098 :
6099 3085733 : if (TREE_CODE (value) == CONSTRUCTOR
6100 3085733 : && TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE)
6101 300525 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
6102 : pre_p, cleared);
6103 2785208 : else if (TREE_CODE (value) == RAW_DATA_CST)
6104 : {
6105 43 : if (RAW_DATA_LENGTH (value) <= 32)
6106 : {
6107 13 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value);
6108 : ++i)
6109 12 : if (!cleared || RAW_DATA_POINTER (value)[i])
6110 : {
6111 12 : if (i)
6112 : {
6113 11 : tree p
6114 11 : = fold_build2 (PLUS_EXPR, TREE_TYPE (purpose),
6115 : purpose,
6116 : build_int_cst (TREE_TYPE (purpose),
6117 : i));
6118 11 : cref = build4 (ARRAY_REF, array_elt_type,
6119 : unshare_expr (object), p, NULL_TREE,
6120 : NULL_TREE);
6121 : }
6122 12 : tree init
6123 12 : = build2 (INIT_EXPR, TREE_TYPE (cref), cref,
6124 12 : build_int_cst (TREE_TYPE (value),
6125 12 : RAW_DATA_UCHAR_ELT (value, i)));
6126 12 : gimplify_and_add (init, pre_p);
6127 12 : ggc_free (init);
6128 : }
6129 : }
6130 : else
6131 : {
6132 42 : tree rtype = build_array_type_nelts (TREE_TYPE (value),
6133 42 : RAW_DATA_LENGTH (value));
6134 42 : tree rctor = build_constructor_single (rtype, bitsize_zero_node,
6135 : value);
6136 42 : tree addr = build_fold_addr_expr (cref);
6137 42 : cref = build2 (MEM_REF, rtype, addr,
6138 : build_int_cst (ptr_type_node, 0));
6139 42 : rctor = tree_output_constant_def (rctor);
6140 42 : if (!useless_type_conversion_p (rtype, TREE_TYPE (rctor)))
6141 4 : rctor = build1 (VIEW_CONVERT_EXPR, rtype, rctor);
6142 42 : if (gimplify_expr (&cref, pre_p, NULL, is_gimple_lvalue,
6143 : fb_lvalue) != GS_ERROR)
6144 84 : gimplify_seq_add_stmt (pre_p,
6145 42 : gimple_build_assign (cref, rctor));
6146 : }
6147 : }
6148 : else
6149 : {
6150 2785165 : tree init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
6151 2785165 : gimplify_and_add (init, pre_p);
6152 2785165 : ggc_free (init);
6153 : }
6154 : }
6155 1266287 : }
6156 :
6157 : /* Return the appropriate RHS predicate for this LHS. */
6158 :
6159 : gimple_predicate
6160 49416096 : rhs_predicate_for (tree lhs)
6161 : {
6162 49416096 : if (is_gimple_reg (lhs))
6163 : return is_gimple_reg_rhs_or_call;
6164 : else
6165 11641283 : return is_gimple_mem_rhs_or_call;
6166 : }
6167 :
6168 : /* Return the initial guess for an appropriate RHS predicate for this LHS,
6169 : before the LHS has been gimplified. */
6170 :
6171 : static gimple_predicate
6172 48224741 : initial_rhs_predicate_for (tree lhs)
6173 : {
6174 48224741 : if (is_gimple_reg_type (TREE_TYPE (lhs)))
6175 : return is_gimple_reg_rhs_or_call;
6176 : else
6177 2436084 : return is_gimple_mem_rhs_or_call;
6178 : }
6179 :
6180 : /* Gimplify a C99 compound literal expression. This just means adding
6181 : the DECL_EXPR before the current statement and using its anonymous
6182 : decl instead. */
6183 :
6184 : static enum gimplify_status
6185 37193 : gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
6186 : bool (*gimple_test_f) (tree),
6187 : fallback_t fallback)
6188 : {
6189 37193 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
6190 37193 : tree decl = DECL_EXPR_DECL (decl_s);
6191 37193 : tree init = DECL_INITIAL (decl);
6192 : /* Mark the decl as addressable if the compound literal
6193 : expression is addressable now, otherwise it is marked too late
6194 : after we gimplify the initialization expression. */
6195 37193 : if (TREE_ADDRESSABLE (*expr_p))
6196 542 : TREE_ADDRESSABLE (decl) = 1;
6197 : /* Otherwise, if we don't need an lvalue and have a literal directly
6198 : substitute it. Check if it matches the gimple predicate, as
6199 : otherwise we'd generate a new temporary, and we can as well just
6200 : use the decl we already have. */
6201 36651 : else if (!TREE_ADDRESSABLE (decl)
6202 36651 : && !TREE_THIS_VOLATILE (decl)
6203 36646 : && init
6204 36638 : && (fallback & fb_lvalue) == 0
6205 73137 : && gimple_test_f (init))
6206 : {
6207 35396 : *expr_p = init;
6208 35396 : return GS_OK;
6209 : }
6210 :
6211 : /* If the decl is not addressable, then it is being used in some
6212 : expression or on the right hand side of a statement, and it can
6213 : be put into a readonly data section. */
6214 1797 : if (!TREE_ADDRESSABLE (decl) && (fallback & fb_lvalue) == 0)
6215 1095 : TREE_READONLY (decl) = 1;
6216 :
6217 : /* This decl isn't mentioned in the enclosing block, so add it to the
6218 : list of temps. FIXME it seems a bit of a kludge to say that
6219 : anonymous artificial vars aren't pushed, but everything else is. */
6220 1797 : if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
6221 2 : gimple_add_tmp_var (decl);
6222 :
6223 1797 : gimplify_and_add (decl_s, pre_p);
6224 1797 : *expr_p = decl;
6225 1797 : return GS_OK;
6226 : }
6227 :
6228 : /* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
6229 : return a new CONSTRUCTOR if something changed. */
6230 :
6231 : static tree
6232 1884086 : optimize_compound_literals_in_ctor (tree orig_ctor)
6233 : {
6234 1884086 : tree ctor = orig_ctor;
6235 1884086 : vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
6236 1884086 : unsigned int idx, num = vec_safe_length (elts);
6237 :
6238 6258285 : for (idx = 0; idx < num; idx++)
6239 : {
6240 4374199 : tree value = (*elts)[idx].value;
6241 4374199 : tree newval = value;
6242 4374199 : if (TREE_CODE (value) == CONSTRUCTOR)
6243 543782 : newval = optimize_compound_literals_in_ctor (value);
6244 3830417 : else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
6245 : {
6246 103 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
6247 103 : tree decl = DECL_EXPR_DECL (decl_s);
6248 103 : tree init = DECL_INITIAL (decl);
6249 :
6250 103 : if (!TREE_ADDRESSABLE (value)
6251 103 : && !TREE_ADDRESSABLE (decl)
6252 103 : && init
6253 103 : && TREE_CODE (init) == CONSTRUCTOR)
6254 52 : newval = optimize_compound_literals_in_ctor (init);
6255 : }
6256 4374199 : if (newval == value)
6257 4374139 : continue;
6258 :
6259 60 : if (ctor == orig_ctor)
6260 : {
6261 49 : ctor = copy_node (orig_ctor);
6262 98 : CONSTRUCTOR_ELTS (ctor) = vec_safe_copy (elts);
6263 49 : elts = CONSTRUCTOR_ELTS (ctor);
6264 : }
6265 60 : (*elts)[idx].value = newval;
6266 : }
6267 1884086 : return ctor;
6268 : }
6269 :
6270 : /* A subroutine of gimplify_modify_expr. Break out elements of a
6271 : CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
6272 :
6273 : Note that we still need to clear any elements that don't have explicit
6274 : initializers, so if not all elements are initialized we keep the
6275 : original MODIFY_EXPR, we just remove all of the constructor elements.
6276 :
6277 : If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
6278 : GS_ERROR if we would have to create a temporary when gimplifying
6279 : this constructor. Otherwise, return GS_OK.
6280 :
6281 : If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
6282 :
6283 : static enum gimplify_status
6284 1340252 : gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
6285 : bool want_value, bool notify_temp_creation)
6286 : {
6287 1340252 : tree object, ctor, type;
6288 1340252 : enum gimplify_status ret;
6289 1340252 : vec<constructor_elt, va_gc> *elts;
6290 1340252 : bool cleared = false;
6291 1340252 : bool is_empty_ctor = false;
6292 1340252 : bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR);
6293 :
6294 1340252 : gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
6295 :
6296 1340252 : if (!notify_temp_creation)
6297 : {
6298 1331703 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
6299 : is_gimple_lvalue, fb_lvalue);
6300 1331703 : if (ret == GS_ERROR)
6301 : return ret;
6302 : }
6303 :
6304 1340252 : object = TREE_OPERAND (*expr_p, 0);
6305 1340252 : ctor = TREE_OPERAND (*expr_p, 1)
6306 1340252 : = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
6307 1340252 : type = TREE_TYPE (ctor);
6308 1340252 : elts = CONSTRUCTOR_ELTS (ctor);
6309 1340252 : ret = GS_ALL_DONE;
6310 :
6311 1340252 : switch (TREE_CODE (type))
6312 : {
6313 1332067 : case RECORD_TYPE:
6314 1332067 : case UNION_TYPE:
6315 1332067 : case QUAL_UNION_TYPE:
6316 1332067 : case ARRAY_TYPE:
6317 1332067 : {
6318 : /* Use readonly data for initializers of this or smaller size
6319 : regardless of the num_nonzero_elements / num_unique_nonzero_elements
6320 : ratio. */
6321 1332067 : const HOST_WIDE_INT min_unique_size = 64;
6322 : /* If num_nonzero_elements / num_unique_nonzero_elements ratio
6323 : is smaller than this, use readonly data. */
6324 1332067 : const int unique_nonzero_ratio = 8;
6325 : /* True if a single access of the object must be ensured. This is the
6326 : case if the target is volatile, the type is non-addressable and more
6327 : than one field need to be assigned. */
6328 1332067 : const bool ensure_single_access
6329 1332067 : = TREE_THIS_VOLATILE (object)
6330 259 : && !TREE_ADDRESSABLE (type)
6331 1332272 : && vec_safe_length (elts) > 1;
6332 1332067 : struct gimplify_init_ctor_preeval_data preeval_data;
6333 1332067 : HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
6334 1332067 : HOST_WIDE_INT num_unique_nonzero_elements;
6335 1332067 : ctor_completeness complete_p;
6336 1332067 : bool valid_const_initializer;
6337 :
6338 : /* Aggregate types must lower constructors to initialization of
6339 : individual elements. The exception is that a CONSTRUCTOR node
6340 : with no elements indicates zero-initialization of the whole. */
6341 1332067 : if (vec_safe_is_empty (elts))
6342 : {
6343 333324 : if (notify_temp_creation)
6344 10132 : return GS_OK;
6345 :
6346 : /* The var will be initialized and so appear on lhs of
6347 : assignment, it can't be TREE_READONLY anymore. */
6348 333276 : if (VAR_P (object))
6349 187029 : TREE_READONLY (object) = 0;
6350 :
6351 : is_empty_ctor = true;
6352 337097 : break;
6353 : }
6354 :
6355 : /* Fetch information about the constructor to direct later processing.
6356 : We might want to make static versions of it in various cases, and
6357 : can only do so if it known to be a valid constant initializer. */
6358 998743 : valid_const_initializer
6359 998743 : = categorize_ctor_elements (ctor, &num_nonzero_elements,
6360 : &num_unique_nonzero_elements,
6361 : &num_ctor_elements, &complete_p);
6362 :
6363 : /* If a const aggregate variable is being initialized, then it
6364 : should never be a lose to promote the variable to be static. */
6365 998743 : if (valid_const_initializer
6366 617031 : && num_nonzero_elements > 1
6367 452278 : && TREE_READONLY (object)
6368 7484 : && VAR_P (object)
6369 7107 : && !DECL_REGISTER (object)
6370 7100 : && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)
6371 5051 : || DECL_MERGEABLE (object))
6372 : /* For ctors that have many repeated nonzero elements
6373 : represented through RANGE_EXPRs, prefer initializing
6374 : those through runtime loops over copies of large amounts
6375 : of data from readonly data section. */
6376 998743 : && (num_unique_nonzero_elements
6377 3821 : > num_nonzero_elements / unique_nonzero_ratio
6378 0 : || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
6379 : <= (unsigned HOST_WIDE_INT) min_unique_size)))
6380 : {
6381 3821 : if (notify_temp_creation)
6382 : return GS_ERROR;
6383 :
6384 3821 : DECL_INITIAL (object) = ctor;
6385 3821 : TREE_STATIC (object) = 1;
6386 3821 : if (!DECL_NAME (object) || DECL_NAMELESS (object))
6387 2957 : DECL_NAME (object) = create_tmp_var_name ("C");
6388 3821 : walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL);
6389 :
6390 : /* ??? C++ doesn't automatically append a .<number> to the
6391 : assembler name, and even when it does, it looks at FE private
6392 : data structures to figure out what that number should be,
6393 : which are not set for this variable. I suppose this is
6394 : important for local statics for inline functions, which aren't
6395 : "local" in the object file sense. So in order to get a unique
6396 : TU-local symbol, we must invoke the lhd version now. */
6397 3821 : lhd_set_decl_assembler_name (object);
6398 :
6399 3821 : *expr_p = NULL_TREE;
6400 3821 : break;
6401 : }
6402 :
6403 : /* The var will be initialized and so appear on lhs of
6404 : assignment, it can't be TREE_READONLY anymore. */
6405 994922 : if (VAR_P (object) && !notify_temp_creation)
6406 787187 : TREE_READONLY (object) = 0;
6407 :
6408 : /* If there are "lots" of initialized elements, even discounting
6409 : those that are not address constants (and thus *must* be
6410 : computed at runtime), then partition the constructor into
6411 : constant and non-constant parts. Block copy the constant
6412 : parts in, then generate code for the non-constant parts. */
6413 : /* TODO. There's code in cp/typeck.cc to do this. */
6414 :
6415 994922 : if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
6416 : /* store_constructor will ignore the clearing of variable-sized
6417 : objects. Initializers for such objects must explicitly set
6418 : every field that needs to be set. */
6419 : cleared = false;
6420 994902 : else if (complete_p.sparse)
6421 : /* If the constructor isn't complete, clear the whole object
6422 : beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
6423 :
6424 : ??? This ought not to be needed. For any element not present
6425 : in the initializer, we should simply set them to zero. Except
6426 : we'd need to *find* the elements that are not present, and that
6427 : requires trickery to avoid quadratic compile-time behavior in
6428 : large cases or excessive memory use in small cases. */
6429 187959 : cleared = !CONSTRUCTOR_NO_CLEARING (ctor);
6430 806943 : else if (num_ctor_elements - num_nonzero_elements
6431 806943 : > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
6432 806943 : && num_nonzero_elements < num_ctor_elements / 4)
6433 : /* If there are "lots" of zeros, it's more efficient to clear
6434 : the memory and then set the nonzero elements. */
6435 : cleared = true;
6436 806063 : else if (ensure_single_access && num_nonzero_elements == 0)
6437 : /* If a single access to the target must be ensured and all elements
6438 : are zero, then it's optimal to clear whatever their number. */
6439 : cleared = true;
6440 : /* If the object is small enough to go in registers, and it's
6441 : not required to be constructed in memory, clear it first.
6442 : That will avoid wasting cycles preserving any padding bits
6443 : that might be there, and if there aren't any, the compiler
6444 : is smart enough to optimize the clearing out. */
6445 806054 : else if ((complete_p.sparse || complete_p.padded_union
6446 805830 : || complete_p.padded_non_union)
6447 14611 : && !TREE_ADDRESSABLE (ctor)
6448 14525 : && !TREE_THIS_VOLATILE (object)
6449 14522 : && (TYPE_MODE (type) != BLKmode || TYPE_NO_FORCE_BLK (type))
6450 812938 : && optimize)
6451 : cleared = true;
6452 : else
6453 : cleared = false;
6454 :
6455 : /* If there are "lots" of initialized elements, and all of them
6456 : are valid address constants, then the entire initializer can
6457 : be dropped to memory, and then memcpy'd out. Don't do this
6458 : for sparse arrays, though, as it's more efficient to follow
6459 : the standard CONSTRUCTOR behavior of memset followed by
6460 : individual element initialization. Also don't do this for small
6461 : all-zero initializers (which aren't big enough to merit
6462 : clearing), and don't try to make bitwise copies of
6463 : TREE_ADDRESSABLE types. */
6464 994922 : if (valid_const_initializer
6465 613210 : && !complete_p.sparse
6466 440277 : && !(cleared || num_nonzero_elements == 0)
6467 344273 : && !TREE_ADDRESSABLE (type))
6468 : {
6469 342443 : HOST_WIDE_INT size = int_size_in_bytes (type);
6470 342443 : unsigned int align;
6471 :
6472 : /* ??? We can still get unbounded array types, at least
6473 : from the C++ front end. This seems wrong, but attempt
6474 : to work around it for now. */
6475 342443 : if (size < 0)
6476 : {
6477 9 : size = int_size_in_bytes (TREE_TYPE (object));
6478 9 : if (size >= 0)
6479 0 : TREE_TYPE (ctor) = type = TREE_TYPE (object);
6480 : }
6481 :
6482 : /* Find the maximum alignment we can assume for the object. */
6483 : /* ??? Make use of DECL_OFFSET_ALIGN. */
6484 342443 : if (DECL_P (object))
6485 328082 : align = DECL_ALIGN (object);
6486 : else
6487 14361 : align = TYPE_ALIGN (type);
6488 :
6489 : /* Do a block move either if the size is so small as to make
6490 : each individual move a sub-unit move on average, or if it
6491 : is so large as to make individual moves inefficient. */
6492 342443 : if (size > 0
6493 342434 : && num_nonzero_elements > 1
6494 : /* For ctors that have many repeated nonzero elements
6495 : represented through RANGE_EXPRs, prefer initializing
6496 : those through runtime loops over copies of large amounts
6497 : of data from readonly data section. */
6498 303420 : && (num_unique_nonzero_elements
6499 303420 : > num_nonzero_elements / unique_nonzero_ratio
6500 56 : || size <= min_unique_size)
6501 645807 : && (size < num_nonzero_elements
6502 303258 : || !can_move_by_pieces (size, align)))
6503 : {
6504 2840 : if (notify_temp_creation)
6505 : return GS_ERROR;
6506 :
6507 1422 : walk_tree (&ctor, force_labels_r, NULL, NULL);
6508 1422 : ctor = tree_output_constant_def (ctor);
6509 1422 : if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
6510 0 : ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
6511 1422 : TREE_OPERAND (*expr_p, 1) = ctor;
6512 :
6513 : /* This is no longer an assignment of a CONSTRUCTOR, but
6514 : we still may have processing to do on the LHS. So
6515 : pretend we didn't do anything here to let that happen. */
6516 1422 : return GS_UNHANDLED;
6517 : }
6518 : }
6519 :
6520 987610 : if (!cleared)
6521 : {
6522 797075 : if (complete_p.padded_non_union
6523 7830 : && warn_zero_init_padding_bits >= ZERO_INIT_PADDING_BITS_ALL)
6524 12 : warning (OPT_Wzero_init_padding_bits_,
6525 : "padding might not be initialized to zero; "
6526 : "if code relies on it being zero, consider "
6527 : "using %<-fzero-init-padding-bits=all%>");
6528 797063 : else if (complete_p.padded_union
6529 116 : && warn_zero_init_padding_bits
6530 : >= ZERO_INIT_PADDING_BITS_UNIONS)
6531 14 : warning (OPT_Wzero_init_padding_bits_,
6532 : "padding might not be initialized to zero; "
6533 : "if code relies on it being zero, consider "
6534 : "using %<-fzero-init-padding-bits=unions%> "
6535 : "or %<-fzero-init-padding-bits=all%>");
6536 : }
6537 :
6538 : /* If a single access to the target must be ensured and there are
6539 : nonzero elements or the zero elements are not assigned en masse,
6540 : initialize the target from a temporary. */
6541 992082 : if (ensure_single_access && (num_nonzero_elements > 0 || !cleared))
6542 : {
6543 167 : if (notify_temp_creation)
6544 : return GS_ERROR;
6545 :
6546 161 : tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type));
6547 161 : TREE_OPERAND (*expr_p, 0) = temp;
6548 161 : *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
6549 : *expr_p,
6550 : build2 (MODIFY_EXPR, void_type_node,
6551 : object, temp));
6552 161 : return GS_OK;
6553 : }
6554 :
6555 991915 : if (notify_temp_creation)
6556 : return GS_OK;
6557 :
6558 : /* If there are nonzero elements and if needed, pre-evaluate to capture
6559 : elements overlapping with the lhs into temporaries. We must do this
6560 : before clearing to fetch the values before they are zeroed-out. */
6561 984838 : if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
6562 : {
6563 216774 : preeval_data.lhs_base_decl = get_base_address (object);
6564 216774 : if (!DECL_P (preeval_data.lhs_base_decl))
6565 41213 : preeval_data.lhs_base_decl = NULL;
6566 216774 : preeval_data.lhs_alias_set = get_alias_set (object);
6567 :
6568 216774 : gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
6569 : pre_p, post_p, &preeval_data);
6570 : }
6571 :
6572 984838 : bool ctor_has_side_effects_p
6573 984838 : = TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1));
6574 :
6575 984838 : if (cleared)
6576 : {
6577 : /* Zap the CONSTRUCTOR element list, which simplifies this case.
6578 : Note that we still have to gimplify, in order to handle the
6579 : case of variable sized types. Avoid shared tree structures. */
6580 194770 : CONSTRUCTOR_ELTS (ctor) = NULL;
6581 194770 : TREE_SIDE_EFFECTS (ctor) = 0;
6582 194770 : object = unshare_expr (object);
6583 194770 : gimplify_stmt (expr_p, pre_p);
6584 : }
6585 :
6586 : /* If we have not block cleared the object, or if there are nonzero
6587 : elements in the constructor, or if the constructor has side effects,
6588 : add assignments to the individual scalar fields of the object. */
6589 194770 : if (!cleared
6590 194770 : || num_nonzero_elements > 0
6591 19597 : || ctor_has_side_effects_p)
6592 965636 : gimplify_init_ctor_eval (object, elts, pre_p, cleared);
6593 :
6594 984838 : *expr_p = NULL_TREE;
6595 : }
6596 984838 : break;
6597 :
6598 0 : case COMPLEX_TYPE:
6599 0 : {
6600 0 : tree r, i;
6601 :
6602 0 : if (notify_temp_creation)
6603 : return GS_OK;
6604 :
6605 : /* Extract the real and imaginary parts out of the ctor. */
6606 0 : gcc_assert (elts->length () == 2);
6607 0 : r = (*elts)[0].value;
6608 0 : i = (*elts)[1].value;
6609 0 : if (r == NULL || i == NULL)
6610 : {
6611 0 : tree zero = build_zero_cst (TREE_TYPE (type));
6612 0 : if (r == NULL)
6613 0 : r = zero;
6614 0 : if (i == NULL)
6615 0 : i = zero;
6616 : }
6617 :
6618 : /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to
6619 : represent creation of a complex value. */
6620 0 : if (TREE_CONSTANT (r) && TREE_CONSTANT (i))
6621 : {
6622 0 : ctor = build_complex (type, r, i);
6623 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6624 : }
6625 : else
6626 : {
6627 0 : ctor = build2 (COMPLEX_EXPR, type, r, i);
6628 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6629 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1),
6630 : pre_p,
6631 : post_p,
6632 0 : rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
6633 : fb_rvalue);
6634 : }
6635 : }
6636 : break;
6637 :
6638 8185 : case VECTOR_TYPE:
6639 8185 : {
6640 8185 : unsigned HOST_WIDE_INT ix;
6641 8185 : constructor_elt *ce;
6642 :
6643 8185 : if (notify_temp_creation)
6644 1340252 : return GS_OK;
6645 :
6646 : /* Vector types use CONSTRUCTOR all the way through gimple
6647 : compilation as a general initializer. */
6648 71768 : FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
6649 : {
6650 63583 : enum gimplify_status tret;
6651 63583 : tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
6652 : fb_rvalue);
6653 63583 : if (tret == GS_ERROR)
6654 : ret = GS_ERROR;
6655 63582 : else if (TREE_STATIC (ctor)
6656 63614 : && !initializer_constant_valid_p (ce->value,
6657 32 : TREE_TYPE (ce->value)))
6658 32 : TREE_STATIC (ctor) = 0;
6659 : }
6660 8185 : recompute_constructor_flags (ctor);
6661 :
6662 : /* Go ahead and simplify constant constructors to VECTOR_CST. */
6663 8185 : if (TREE_CONSTANT (ctor))
6664 : {
6665 2705 : bool constant_p = true;
6666 : tree value;
6667 :
6668 : /* Even when ctor is constant, it might contain non-*_CST
6669 : elements, such as addresses or trapping values like
6670 : 1.0/0.0 - 1.0/0.0. Such expressions don't belong
6671 : in VECTOR_CST nodes. */
6672 2705 : FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
6673 2483 : if (!CONSTANT_CLASS_P (value))
6674 : {
6675 : constant_p = false;
6676 : break;
6677 : }
6678 :
6679 222 : if (constant_p)
6680 : {
6681 222 : TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts);
6682 222 : break;
6683 : }
6684 : }
6685 :
6686 7963 : if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
6687 933 : TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
6688 : }
6689 : break;
6690 :
6691 0 : default:
6692 : /* So how did we get a CONSTRUCTOR for a scalar type? */
6693 0 : gcc_unreachable ();
6694 : }
6695 :
6696 1330120 : if (ret == GS_ERROR)
6697 : return GS_ERROR;
6698 : /* If we have gimplified both sides of the initializer but have
6699 : not emitted an assignment, do so now. */
6700 1330119 : if (*expr_p
6701 : /* If the type is an empty type, we don't need to emit the
6702 : assignment. */
6703 1330119 : && !is_empty_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
6704 : {
6705 337586 : tree lhs = TREE_OPERAND (*expr_p, 0);
6706 337586 : tree rhs = TREE_OPERAND (*expr_p, 1);
6707 337586 : if (want_value && object == lhs)
6708 12 : lhs = unshare_expr (lhs);
6709 337586 : gassign *init = gimple_build_assign (lhs, rhs);
6710 337586 : gimplify_seq_add_stmt (pre_p, init);
6711 : }
6712 1330119 : if (want_value)
6713 : {
6714 19 : *expr_p = object;
6715 19 : ret = GS_OK;
6716 : }
6717 : else
6718 : {
6719 1330100 : *expr_p = NULL;
6720 1330100 : ret = GS_ALL_DONE;
6721 : }
6722 :
6723 : /* If the user requests to initialize automatic variables, we
6724 : should initialize paddings inside the variable. Add a call to
6725 : __builtin_clear_pading (&object, 0, for_auto_init = true) to
6726 : initialize paddings of object always to zero regardless of
6727 : INIT_TYPE. Note, we will not insert this call if the aggregate
6728 : variable has be completely cleared already or it's initialized
6729 : with an empty constructor. We cannot insert this call if the
6730 : variable is a gimple register since __builtin_clear_padding will take
6731 : the address of the variable. As a result, if a long double/_Complex long
6732 : double variable will be spilled into stack later, its padding cannot
6733 : be cleared with __builtin_clear_padding. We should clear its padding
6734 : when it is spilled into memory. */
6735 1330119 : if (is_init_expr
6736 949454 : && !is_gimple_reg (object)
6737 944036 : && clear_padding_type_may_have_padding_p (type)
6738 898944 : && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
6739 225457 : || !AGGREGATE_TYPE_P (type))
6740 673487 : && var_needs_auto_init_p (object)
6741 1365252 : && flag_auto_var_init != AUTO_INIT_CXX26)
6742 41 : gimple_add_padding_init_for_auto_var (object, false, pre_p);
6743 :
6744 : return ret;
6745 : }
6746 :
6747 : /* Given a pointer value OP0, return a simplified version of an
6748 : indirection through OP0, or NULL_TREE if no simplification is
6749 : possible. This may only be applied to a rhs of an expression.
6750 : Note that the resulting type may be different from the type pointed
6751 : to in the sense that it is still compatible from the langhooks
6752 : point of view. */
6753 :
6754 : static tree
6755 529186 : gimple_fold_indirect_ref_rhs (tree t)
6756 : {
6757 0 : return gimple_fold_indirect_ref (t);
6758 : }
6759 :
6760 : /* Subroutine of gimplify_modify_expr to do simplifications of
6761 : MODIFY_EXPRs based on the code of the RHS. We loop for as long as
6762 : something changes. */
6763 :
6764 : static enum gimplify_status
6765 98514542 : gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
6766 : gimple_seq *pre_p, gimple_seq *post_p,
6767 : bool want_value)
6768 : {
6769 98514542 : enum gimplify_status ret = GS_UNHANDLED;
6770 99169243 : bool changed;
6771 :
6772 97687890 : do
6773 : {
6774 99169243 : changed = false;
6775 99169243 : switch (TREE_CODE (*from_p))
6776 : {
6777 11980189 : case VAR_DECL:
6778 : /* If we're assigning from a read-only variable initialized with
6779 : a constructor and not volatile, do the direct assignment from
6780 : the constructor, but only if the target is not volatile either
6781 : since this latter assignment might end up being done on a per
6782 : field basis. However, if the target is volatile and the type
6783 : is aggregate and non-addressable, gimplify_init_constructor
6784 : knows that it needs to ensure a single access to the target
6785 : and it will return GS_OK only in this case. */
6786 11980189 : if (TREE_READONLY (*from_p)
6787 94630 : && DECL_INITIAL (*from_p)
6788 61439 : && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR
6789 8549 : && !TREE_THIS_VOLATILE (*from_p)
6790 11988738 : && (!TREE_THIS_VOLATILE (*to_p)
6791 6 : || (AGGREGATE_TYPE_P (TREE_TYPE (*to_p))
6792 6 : && !TREE_ADDRESSABLE (TREE_TYPE (*to_p)))))
6793 : {
6794 8549 : tree old_from = *from_p;
6795 8549 : enum gimplify_status subret;
6796 :
6797 : /* Move the constructor into the RHS. */
6798 8549 : *from_p = unshare_expr (DECL_INITIAL (*from_p));
6799 :
6800 : /* Let's see if gimplify_init_constructor will need to put
6801 : it in memory. */
6802 8549 : subret = gimplify_init_constructor (expr_p, NULL, NULL,
6803 : false, true);
6804 8549 : if (subret == GS_ERROR)
6805 : {
6806 : /* If so, revert the change. */
6807 1424 : *from_p = old_from;
6808 : }
6809 : else
6810 : {
6811 : ret = GS_OK;
6812 : changed = true;
6813 : }
6814 : }
6815 : break;
6816 537050 : case INDIRECT_REF:
6817 537050 : if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
6818 : /* If we have code like
6819 :
6820 : *(const A*)(A*)&x
6821 :
6822 : where the type of "x" is a (possibly cv-qualified variant
6823 : of "A"), treat the entire expression as identical to "x".
6824 : This kind of code arises in C++ when an object is bound
6825 : to a const reference, and if "x" is a TARGET_EXPR we want
6826 : to take advantage of the optimization below. But not if
6827 : the type is TREE_ADDRESSABLE; then C++17 says that the
6828 : TARGET_EXPR needs to be a temporary. */
6829 1058372 : if (tree t
6830 529186 : = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)))
6831 : {
6832 127815 : bool volatile_p = TREE_THIS_VOLATILE (*from_p);
6833 127815 : if (TREE_THIS_VOLATILE (t) != volatile_p)
6834 : {
6835 5 : if (DECL_P (t))
6836 0 : t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
6837 : build_fold_addr_expr (t));
6838 5 : if (REFERENCE_CLASS_P (t))
6839 5 : TREE_THIS_VOLATILE (t) = volatile_p;
6840 : }
6841 127815 : *from_p = t;
6842 127815 : ret = GS_OK;
6843 127815 : changed = true;
6844 : }
6845 : break;
6846 :
6847 198962 : case TARGET_EXPR:
6848 198962 : {
6849 : /* If we are initializing something from a TARGET_EXPR, strip the
6850 : TARGET_EXPR and initialize it directly, if possible. This can't
6851 : be done if the initializer is void, since that implies that the
6852 : temporary is set in some non-trivial way.
6853 :
6854 : ??? What about code that pulls out the temp and uses it
6855 : elsewhere? I think that such code never uses the TARGET_EXPR as
6856 : an initializer. If I'm wrong, we'll die because the temp won't
6857 : have any RTL. In that case, I guess we'll need to replace
6858 : references somehow. */
6859 198962 : tree init = TARGET_EXPR_INITIAL (*from_p);
6860 :
6861 198962 : if (init
6862 198246 : && (TREE_CODE (*expr_p) != MODIFY_EXPR
6863 50113 : || !TARGET_EXPR_NO_ELIDE (*from_p))
6864 397002 : && !VOID_TYPE_P (TREE_TYPE (init)))
6865 : {
6866 183024 : *from_p = init;
6867 183024 : ret = GS_OK;
6868 183024 : changed = true;
6869 : }
6870 : }
6871 : break;
6872 :
6873 336374 : case COMPOUND_EXPR:
6874 : /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
6875 : caught. */
6876 336374 : gimplify_compound_expr (from_p, pre_p, true);
6877 336374 : ret = GS_OK;
6878 336374 : changed = true;
6879 336374 : break;
6880 :
6881 1356805 : case CONSTRUCTOR:
6882 : /* If we already made some changes, let the front end have a
6883 : crack at this before we break it down. */
6884 1356805 : if (ret != GS_UNHANDLED)
6885 : break;
6886 :
6887 : /* If we're initializing from a CONSTRUCTOR, break this into
6888 : individual MODIFY_EXPRs. */
6889 1331703 : ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
6890 : false);
6891 1331703 : return ret;
6892 :
6893 224929 : case COND_EXPR:
6894 : /* If we're assigning to a non-register type, push the assignment
6895 : down into the branches. This is mandatory for ADDRESSABLE types,
6896 : since we cannot generate temporaries for such, but it saves a
6897 : copy in other cases as well.
6898 : Also avoid an extra temporary and copy when assigning to
6899 : a register. */
6900 224929 : if (!is_gimple_reg_type (TREE_TYPE (*from_p))
6901 224929 : || (is_gimple_reg (*to_p) && !gimplify_ctxp->allow_rhs_cond_expr))
6902 : {
6903 : /* This code should mirror the code in gimplify_cond_expr. */
6904 143286 : enum tree_code code = TREE_CODE (*expr_p);
6905 143286 : tree cond = *from_p;
6906 143286 : tree result = *to_p;
6907 :
6908 143286 : ret = gimplify_expr (&result, pre_p, post_p,
6909 : is_gimple_lvalue, fb_lvalue);
6910 143286 : if (ret != GS_ERROR)
6911 143286 : ret = GS_OK;
6912 :
6913 : /* If we are going to write RESULT more than once, clear
6914 : TREE_READONLY flag, otherwise we might incorrectly promote
6915 : the variable to static const and initialize it at compile
6916 : time in one of the branches. */
6917 143286 : if (VAR_P (result)
6918 142252 : && TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node
6919 276465 : && TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6920 133087 : TREE_READONLY (result) = 0;
6921 143286 : if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
6922 134077 : TREE_OPERAND (cond, 1)
6923 268154 : = build2 (code, void_type_node, result,
6924 134077 : TREE_OPERAND (cond, 1));
6925 143286 : if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6926 143194 : TREE_OPERAND (cond, 2)
6927 286388 : = build2 (code, void_type_node, unshare_expr (result),
6928 143194 : TREE_OPERAND (cond, 2));
6929 :
6930 143286 : TREE_TYPE (cond) = void_type_node;
6931 143286 : recalculate_side_effects (cond);
6932 :
6933 143286 : if (want_value)
6934 : {
6935 68 : gimplify_and_add (cond, pre_p);
6936 68 : *expr_p = unshare_expr (result);
6937 : }
6938 : else
6939 143218 : *expr_p = cond;
6940 143286 : return ret;
6941 : }
6942 : break;
6943 :
6944 10183319 : case CALL_EXPR:
6945 : /* For calls that return in memory, give *to_p as the CALL_EXPR's
6946 : return slot so that we don't generate a temporary. */
6947 10183319 : if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
6948 10183319 : && aggregate_value_p (*from_p, *from_p))
6949 : {
6950 252779 : bool use_target;
6951 :
6952 252779 : if (!(rhs_predicate_for (*to_p))(*from_p))
6953 : /* If we need a temporary, *to_p isn't accurate. */
6954 : use_target = false;
6955 : /* It's OK to use the return slot directly unless it's an NRV. */
6956 251969 : else if (TREE_CODE (*to_p) == RESULT_DECL
6957 6654 : && DECL_NAME (*to_p) == NULL_TREE
6958 258479 : && needs_to_live_in_memory (*to_p))
6959 : use_target = true;
6960 245459 : else if (is_gimple_reg_type (TREE_TYPE (*to_p))
6961 245459 : || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
6962 : /* Don't force regs into memory. */
6963 : use_target = false;
6964 230945 : else if (TREE_CODE (*expr_p) == INIT_EXPR)
6965 : /* It's OK to use the target directly if it's being
6966 : initialized. */
6967 : use_target = true;
6968 14488 : else if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p)))
6969 : != INTEGER_CST)
6970 : /* Always use the target and thus RSO for variable-sized types.
6971 : GIMPLE cannot deal with a variable-sized assignment
6972 : embedded in a call statement. */
6973 : use_target = true;
6974 14460 : else if (TREE_CODE (*to_p) != SSA_NAME
6975 14460 : && (!is_gimple_variable (*to_p)
6976 11150 : || needs_to_live_in_memory (*to_p)))
6977 : /* Don't use the original target if it's already addressable;
6978 : if its address escapes, and the called function uses the
6979 : NRV optimization, a conforming program could see *to_p
6980 : change before the called function returns; see c++/19317.
6981 : When optimizing, the return_slot pass marks more functions
6982 : as safe after we have escape info. */
6983 : use_target = false;
6984 : else
6985 : use_target = true;
6986 :
6987 : if (use_target)
6988 : {
6989 225093 : CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
6990 225093 : mark_addressable (*to_p);
6991 : }
6992 : }
6993 : break;
6994 :
6995 1554 : case WITH_SIZE_EXPR:
6996 : /* Likewise for calls that return an aggregate of non-constant size,
6997 : since we would not be able to generate a temporary at all. */
6998 1554 : if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
6999 : {
7000 350 : *from_p = TREE_OPERAND (*from_p, 0);
7001 : /* We don't change ret in this case because the
7002 : WITH_SIZE_EXPR might have been added in
7003 : gimplify_modify_expr, so returning GS_OK would lead to an
7004 : infinite loop. */
7005 350 : changed = true;
7006 : }
7007 : break;
7008 :
7009 : /* If we're initializing from a container, push the initialization
7010 : inside it. */
7011 1933 : case CLEANUP_POINT_EXPR:
7012 1933 : case BIND_EXPR:
7013 1933 : case STATEMENT_LIST:
7014 1933 : {
7015 1933 : tree wrap = *from_p;
7016 1933 : tree t;
7017 :
7018 1933 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
7019 : fb_lvalue);
7020 1933 : if (ret != GS_ERROR)
7021 1933 : ret = GS_OK;
7022 :
7023 1933 : t = voidify_wrapper_expr (wrap, *expr_p);
7024 1933 : gcc_assert (t == *expr_p);
7025 :
7026 1933 : if (want_value)
7027 : {
7028 6 : gimplify_and_add (wrap, pre_p);
7029 6 : *expr_p = unshare_expr (*to_p);
7030 : }
7031 : else
7032 1927 : *expr_p = wrap;
7033 : return GS_OK;
7034 : }
7035 :
7036 9758875 : case NOP_EXPR:
7037 : /* Pull out compound literal expressions from a NOP_EXPR.
7038 : Those are created in the C FE to drop qualifiers during
7039 : lvalue conversion. */
7040 9758875 : if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR)
7041 9758875 : && tree_ssa_useless_type_conversion (*from_p))
7042 : {
7043 13 : *from_p = TREE_OPERAND (*from_p, 0);
7044 13 : ret = GS_OK;
7045 13 : changed = true;
7046 : }
7047 : break;
7048 :
7049 4431 : case COMPOUND_LITERAL_EXPR:
7050 4431 : {
7051 4431 : tree complit = TREE_OPERAND (*expr_p, 1);
7052 4431 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
7053 4431 : tree decl = DECL_EXPR_DECL (decl_s);
7054 4431 : tree init = DECL_INITIAL (decl);
7055 :
7056 : /* struct T x = (struct T) { 0, 1, 2 } can be optimized
7057 : into struct T x = { 0, 1, 2 } if the address of the
7058 : compound literal has never been taken. */
7059 4431 : if (!TREE_ADDRESSABLE (complit)
7060 4431 : && !TREE_ADDRESSABLE (decl)
7061 4431 : && init)
7062 : {
7063 4431 : *expr_p = copy_node (*expr_p);
7064 4431 : TREE_OPERAND (*expr_p, 1) = init;
7065 4431 : return GS_OK;
7066 : }
7067 : }
7068 :
7069 : default:
7070 : break;
7071 : }
7072 : }
7073 : while (changed);
7074 :
7075 : return ret;
7076 : }
7077 :
7078 :
7079 : /* Return true if T looks like a valid GIMPLE statement. */
7080 :
7081 : static bool
7082 19484961 : is_gimple_stmt (tree t)
7083 : {
7084 19484961 : const enum tree_code code = TREE_CODE (t);
7085 :
7086 19484961 : switch (code)
7087 : {
7088 1748922 : case NOP_EXPR:
7089 : /* The only valid NOP_EXPR is the empty statement. */
7090 1748922 : return IS_EMPTY_STMT (t);
7091 :
7092 0 : case BIND_EXPR:
7093 0 : case COND_EXPR:
7094 : /* These are only valid if they're void. */
7095 0 : return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
7096 :
7097 : case SWITCH_EXPR:
7098 : case GOTO_EXPR:
7099 : case RETURN_EXPR:
7100 : case LABEL_EXPR:
7101 : case CASE_LABEL_EXPR:
7102 : case TRY_CATCH_EXPR:
7103 : case TRY_FINALLY_EXPR:
7104 : case EH_FILTER_EXPR:
7105 : case CATCH_EXPR:
7106 : case ASM_EXPR:
7107 : case STATEMENT_LIST:
7108 : case OACC_PARALLEL:
7109 : case OACC_KERNELS:
7110 : case OACC_SERIAL:
7111 : case OACC_DATA:
7112 : case OACC_HOST_DATA:
7113 : case OACC_DECLARE:
7114 : case OACC_UPDATE:
7115 : case OACC_ENTER_DATA:
7116 : case OACC_EXIT_DATA:
7117 : case OACC_CACHE:
7118 : case OMP_PARALLEL:
7119 : case OMP_FOR:
7120 : case OMP_SIMD:
7121 : case OMP_DISTRIBUTE:
7122 : case OMP_LOOP:
7123 : case OMP_TILE:
7124 : case OMP_UNROLL:
7125 : case OACC_LOOP:
7126 : case OMP_SCAN:
7127 : case OMP_SCOPE:
7128 : case OMP_DISPATCH:
7129 : case OMP_SECTIONS:
7130 : case OMP_SECTION:
7131 : case OMP_STRUCTURED_BLOCK:
7132 : case OMP_SINGLE:
7133 : case OMP_MASTER:
7134 : case OMP_MASKED:
7135 : case OMP_TASKGROUP:
7136 : case OMP_ORDERED:
7137 : case OMP_CRITICAL:
7138 : case OMP_METADIRECTIVE:
7139 : case OMP_TASK:
7140 : case OMP_TARGET:
7141 : case OMP_TARGET_DATA:
7142 : case OMP_TARGET_UPDATE:
7143 : case OMP_TARGET_ENTER_DATA:
7144 : case OMP_TARGET_EXIT_DATA:
7145 : case OMP_TASKLOOP:
7146 : case OMP_TEAMS:
7147 : /* These are always void. */
7148 : return true;
7149 :
7150 : case CALL_EXPR:
7151 : case MODIFY_EXPR:
7152 : case PREDICT_EXPR:
7153 : /* These are valid regardless of their type. */
7154 : return true;
7155 :
7156 : default:
7157 : return false;
7158 : }
7159 : }
7160 :
7161 :
7162 : /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
7163 : a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
7164 :
7165 : IMPORTANT NOTE: This promotion is performed by introducing a load of the
7166 : other, unmodified part of the complex object just before the total store.
7167 : As a consequence, if the object is still uninitialized, an undefined value
7168 : will be loaded into a register, which may result in a spurious exception
7169 : if the register is floating-point and the value happens to be a signaling
7170 : NaN for example. Then the fully-fledged complex operations lowering pass
7171 : followed by a DCE pass are necessary in order to fix things up. */
7172 :
7173 : static enum gimplify_status
7174 1942 : gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
7175 : bool want_value)
7176 : {
7177 1942 : enum tree_code code, ocode;
7178 1942 : tree lhs, rhs, new_rhs, other, realpart, imagpart;
7179 :
7180 1942 : lhs = TREE_OPERAND (*expr_p, 0);
7181 1942 : rhs = TREE_OPERAND (*expr_p, 1);
7182 1942 : code = TREE_CODE (lhs);
7183 1942 : lhs = TREE_OPERAND (lhs, 0);
7184 :
7185 1942 : ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
7186 1942 : other = build1 (ocode, TREE_TYPE (rhs), lhs);
7187 1942 : suppress_warning (other);
7188 1942 : other = get_formal_tmp_var (other, pre_p);
7189 :
7190 1942 : realpart = code == REALPART_EXPR ? rhs : other;
7191 957 : imagpart = code == REALPART_EXPR ? other : rhs;
7192 :
7193 1942 : if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
7194 0 : new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
7195 : else
7196 1942 : new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
7197 :
7198 1942 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
7199 1942 : *expr_p = (want_value) ? rhs : NULL_TREE;
7200 :
7201 1942 : return GS_ALL_DONE;
7202 : }
7203 :
7204 : /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
7205 :
7206 : modify_expr
7207 : : varname '=' rhs
7208 : | '*' ID '=' rhs
7209 :
7210 : PRE_P points to the list where side effects that must happen before
7211 : *EXPR_P should be stored.
7212 :
7213 : POST_P points to the list where side effects that must happen after
7214 : *EXPR_P should be stored.
7215 :
7216 : WANT_VALUE is nonzero iff we want to use the value of this expression
7217 : in another expression. */
7218 :
7219 : static enum gimplify_status
7220 50908341 : gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
7221 : bool want_value)
7222 : {
7223 50908341 : tree *from_p = &TREE_OPERAND (*expr_p, 1);
7224 50908341 : tree *to_p = &TREE_OPERAND (*expr_p, 0);
7225 50908341 : enum gimplify_status ret = GS_UNHANDLED;
7226 50908341 : gimple *assign;
7227 50908341 : location_t loc = EXPR_LOCATION (*expr_p);
7228 50908341 : gimple_stmt_iterator gsi;
7229 :
7230 50908341 : if (error_operand_p (*from_p) || error_operand_p (*to_p))
7231 : return GS_ERROR;
7232 :
7233 50908313 : gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
7234 : || TREE_CODE (*expr_p) == INIT_EXPR);
7235 :
7236 : /* Trying to simplify a clobber using normal logic doesn't work,
7237 : so handle it here. */
7238 50908313 : if (TREE_CLOBBER_P (*from_p))
7239 : {
7240 618191 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7241 618191 : if (ret == GS_ERROR)
7242 : return ret;
7243 618191 : gcc_assert (!want_value);
7244 618191 : if (!VAR_P (*to_p) && TREE_CODE (*to_p) != MEM_REF)
7245 : {
7246 206 : tree addr = get_initialized_tmp_var (build_fold_addr_expr (*to_p),
7247 : pre_p, post_p);
7248 206 : *to_p = build_simple_mem_ref_loc (EXPR_LOCATION (*to_p), addr);
7249 : }
7250 618191 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
7251 618191 : *expr_p = NULL;
7252 618191 : return GS_ALL_DONE;
7253 : }
7254 :
7255 : /* Convert initialization from an empty variable-size CONSTRUCTOR to
7256 : memset. */
7257 50290122 : if (TREE_TYPE (*from_p) != error_mark_node
7258 50290122 : && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
7259 50290122 : && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
7260 1587 : && TREE_CODE (*from_p) == CONSTRUCTOR
7261 50290226 : && CONSTRUCTOR_NELTS (*from_p) == 0)
7262 : {
7263 84 : maybe_with_size_expr (from_p);
7264 84 : gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
7265 84 : return gimplify_modify_expr_to_memset (expr_p,
7266 84 : TREE_OPERAND (*from_p, 1),
7267 84 : want_value, pre_p);
7268 : }
7269 :
7270 : /* Insert pointer conversions required by the middle-end that are not
7271 : required by the frontend. This fixes middle-end type checking for
7272 : for example gcc.dg/redecl-6.c. */
7273 50290038 : if (POINTER_TYPE_P (TREE_TYPE (*to_p)))
7274 : {
7275 13659990 : STRIP_USELESS_TYPE_CONVERSION (*from_p);
7276 13659990 : if (!useless_type_conversion_p (TREE_TYPE (*to_p), TREE_TYPE (*from_p)))
7277 754 : *from_p = fold_convert_loc (loc, TREE_TYPE (*to_p), *from_p);
7278 : }
7279 :
7280 : /* See if any simplifications can be done based on what the RHS is. */
7281 50290038 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7282 : want_value);
7283 50290038 : if (ret != GS_UNHANDLED)
7284 : return ret;
7285 :
7286 : /* For empty types only gimplify the left hand side and right hand
7287 : side as statements and throw away the assignment. Do this after
7288 : gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable
7289 : types properly. */
7290 48226851 : if (is_empty_type (TREE_TYPE (*from_p))
7291 13744 : && !want_value
7292 : /* Don't do this for calls that return addressable types, expand_call
7293 : relies on those having a lhs. */
7294 48240588 : && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
7295 11627 : && TREE_CODE (*from_p) == CALL_EXPR))
7296 : {
7297 2110 : suppress_warning (*from_p, OPT_Wunused_result);
7298 2110 : gimplify_stmt (from_p, pre_p);
7299 2110 : gimplify_stmt (to_p, pre_p);
7300 2110 : *expr_p = NULL_TREE;
7301 2110 : return GS_ALL_DONE;
7302 : }
7303 :
7304 : /* If the value being copied is of variable width, compute the length
7305 : of the copy into a WITH_SIZE_EXPR. Note that we need to do this
7306 : before gimplifying any of the operands so that we can resolve any
7307 : PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
7308 : the size of the expression to be copied, not of the destination, so
7309 : that is what we must do here. */
7310 48224741 : maybe_with_size_expr (from_p);
7311 :
7312 : /* As a special case, we have to temporarily allow for assignments
7313 : with a CALL_EXPR on the RHS. Since in GIMPLE a function call is
7314 : a toplevel statement, when gimplifying the GENERIC expression
7315 : MODIFY_EXPR <a, CALL_EXPR <foo>>, we cannot create the tuple
7316 : GIMPLE_ASSIGN <a, GIMPLE_CALL <foo>>.
7317 :
7318 : Instead, we need to create the tuple GIMPLE_CALL <a, foo>. To
7319 : prevent gimplify_expr from trying to create a new temporary for
7320 : foo's LHS, we tell it that it should only gimplify until it
7321 : reaches the CALL_EXPR. On return from gimplify_expr, the newly
7322 : created GIMPLE_CALL <foo> will be the last statement in *PRE_P
7323 : and all we need to do here is set 'a' to be its LHS. */
7324 :
7325 : /* Gimplify the RHS first for C++17 and bug 71104. */
7326 48224741 : gimple_predicate initial_pred = initial_rhs_predicate_for (*to_p);
7327 48224741 : ret = gimplify_expr (from_p, pre_p, post_p, initial_pred, fb_rvalue);
7328 48224741 : if (ret == GS_ERROR)
7329 : return ret;
7330 :
7331 : /* Then gimplify the LHS. */
7332 : /* If we gimplified the RHS to a CALL_EXPR and that call may return
7333 : twice we have to make sure to gimplify into non-SSA as otherwise
7334 : the abnormal edge added later will make those defs not dominate
7335 : their uses.
7336 : ??? Technically this applies only to the registers used in the
7337 : resulting non-register *TO_P. */
7338 48224579 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
7339 48224579 : if (saved_into_ssa
7340 45839242 : && TREE_CODE (*from_p) == CALL_EXPR
7341 53417248 : && call_expr_flags (*from_p) & ECF_RETURNS_TWICE)
7342 1530 : gimplify_ctxp->into_ssa = false;
7343 48224579 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7344 48224579 : gimplify_ctxp->into_ssa = saved_into_ssa;
7345 48224579 : if (ret == GS_ERROR)
7346 : return ret;
7347 :
7348 : /* Now that the LHS is gimplified, re-gimplify the RHS if our initial
7349 : guess for the predicate was wrong. */
7350 48224504 : gimple_predicate final_pred = rhs_predicate_for (*to_p);
7351 48224504 : if (final_pred != initial_pred)
7352 : {
7353 8196932 : ret = gimplify_expr (from_p, pre_p, post_p, final_pred, fb_rvalue);
7354 8196932 : if (ret == GS_ERROR)
7355 : return ret;
7356 : }
7357 :
7358 : /* In case of va_arg internal fn wrapped in a WITH_SIZE_EXPR, add the type
7359 : size as argument to the call. */
7360 48224504 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7361 : {
7362 1451 : tree call = TREE_OPERAND (*from_p, 0);
7363 1451 : tree vlasize = TREE_OPERAND (*from_p, 1);
7364 :
7365 1451 : if (TREE_CODE (call) == CALL_EXPR
7366 1451 : && CALL_EXPR_IFN (call) == IFN_VA_ARG)
7367 : {
7368 95 : int nargs = call_expr_nargs (call);
7369 95 : tree type = TREE_TYPE (call);
7370 95 : tree ap = CALL_EXPR_ARG (call, 0);
7371 95 : tree tag = CALL_EXPR_ARG (call, 1);
7372 95 : tree aptag = CALL_EXPR_ARG (call, 2);
7373 95 : tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
7374 : IFN_VA_ARG, type,
7375 : nargs + 1, ap, tag,
7376 : aptag, vlasize);
7377 95 : TREE_OPERAND (*from_p, 0) = newcall;
7378 : }
7379 : }
7380 :
7381 : /* Now see if the above changed *from_p to something we handle specially. */
7382 48224504 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7383 : want_value);
7384 48224504 : if (ret != GS_UNHANDLED)
7385 : return ret;
7386 :
7387 : /* If we've got a variable sized assignment between two lvalues (i.e. does
7388 : not involve a call), then we can make things a bit more straightforward
7389 : by converting the assignment to memcpy or memset. */
7390 48223541 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7391 : {
7392 1101 : tree from = TREE_OPERAND (*from_p, 0);
7393 1101 : tree size = TREE_OPERAND (*from_p, 1);
7394 :
7395 1101 : if (TREE_CODE (from) == CONSTRUCTOR)
7396 0 : return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
7397 1101 : else if (is_gimple_addressable (from)
7398 1101 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (*to_p)))
7399 2201 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))))
7400 : {
7401 1100 : *from_p = from;
7402 1100 : return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
7403 1100 : pre_p);
7404 : }
7405 : }
7406 :
7407 : /* Transform partial stores to non-addressable complex variables into
7408 : total stores. This allows us to use real instead of virtual operands
7409 : for these variables, which improves optimization. */
7410 48222441 : if ((TREE_CODE (*to_p) == REALPART_EXPR
7411 48222441 : || TREE_CODE (*to_p) == IMAGPART_EXPR)
7412 48222441 : && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
7413 1942 : return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
7414 :
7415 : /* Try to alleviate the effects of the gimplification creating artificial
7416 : temporaries (see for example is_gimple_reg_rhs) on the debug info, but
7417 : make sure not to create DECL_DEBUG_EXPR links across functions. */
7418 48220499 : if (!gimplify_ctxp->into_ssa
7419 2384417 : && VAR_P (*from_p)
7420 470689 : && DECL_IGNORED_P (*from_p)
7421 349954 : && DECL_P (*to_p)
7422 138032 : && !DECL_IGNORED_P (*to_p)
7423 37966 : && decl_function_context (*to_p) == current_function_decl
7424 48252901 : && decl_function_context (*from_p) == current_function_decl)
7425 : {
7426 32397 : if (!DECL_NAME (*from_p) && DECL_NAME (*to_p))
7427 27151 : DECL_NAME (*from_p)
7428 54302 : = create_tmp_var_name (IDENTIFIER_POINTER (DECL_NAME (*to_p)));
7429 32397 : DECL_HAS_DEBUG_EXPR_P (*from_p) = 1;
7430 32397 : SET_DECL_DEBUG_EXPR (*from_p, *to_p);
7431 : }
7432 :
7433 48220499 : if (want_value && TREE_THIS_VOLATILE (*to_p))
7434 526 : *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
7435 :
7436 48220499 : if (TREE_CODE (*from_p) == CALL_EXPR)
7437 : {
7438 : /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
7439 : instead of a GIMPLE_ASSIGN. */
7440 4872550 : gcall *call_stmt;
7441 4872550 : if (CALL_EXPR_FN (*from_p) == NULL_TREE)
7442 : {
7443 : /* Gimplify internal functions created in the FEs. */
7444 340605 : int nargs = call_expr_nargs (*from_p), i;
7445 340605 : enum internal_fn ifn = CALL_EXPR_IFN (*from_p);
7446 340605 : auto_vec<tree> vargs (nargs);
7447 :
7448 1715015 : for (i = 0; i < nargs; i++)
7449 : {
7450 1033805 : gimplify_arg (&CALL_EXPR_ARG (*from_p, i), pre_p,
7451 1033805 : EXPR_LOCATION (*from_p));
7452 1033805 : vargs.quick_push (CALL_EXPR_ARG (*from_p, i));
7453 : }
7454 340605 : call_stmt = gimple_build_call_internal_vec (ifn, vargs);
7455 340605 : gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p));
7456 681210 : gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p));
7457 340605 : }
7458 : else
7459 : {
7460 4531945 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
7461 4531945 : CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
7462 4531945 : STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
7463 4531945 : tree fndecl = get_callee_fndecl (*from_p);
7464 4531945 : if (fndecl
7465 4416717 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
7466 4668677 : && call_expr_nargs (*from_p) == 3)
7467 66679 : call_stmt = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3,
7468 66679 : CALL_EXPR_ARG (*from_p, 0),
7469 66679 : CALL_EXPR_ARG (*from_p, 1),
7470 66679 : CALL_EXPR_ARG (*from_p, 2));
7471 : else
7472 : {
7473 4465266 : call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
7474 : }
7475 : }
7476 4872550 : notice_special_calls (call_stmt);
7477 4872550 : if (!gimple_call_noreturn_p (call_stmt) || !should_remove_lhs_p (*to_p))
7478 4872306 : gimple_call_set_lhs (call_stmt, *to_p);
7479 244 : else if (TREE_CODE (*to_p) == SSA_NAME)
7480 : /* The above is somewhat premature, avoid ICEing later for a
7481 : SSA name w/o a definition. We may have uses in the GIMPLE IL.
7482 : ??? This doesn't make it a default-def. */
7483 137 : SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop ();
7484 :
7485 : assign = call_stmt;
7486 : }
7487 : else
7488 : {
7489 43347949 : assign = gimple_build_assign (*to_p, *from_p);
7490 43347949 : gimple_set_location (assign, EXPR_LOCATION (*expr_p));
7491 43347949 : if (COMPARISON_CLASS_P (*from_p))
7492 1255528 : copy_warning (assign, *from_p);
7493 : }
7494 :
7495 48220499 : if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
7496 : {
7497 : /* We should have got an SSA name from the start. */
7498 35680876 : gcc_assert (TREE_CODE (*to_p) == SSA_NAME
7499 : || ! gimple_in_ssa_p (cfun));
7500 : }
7501 :
7502 48220499 : gimplify_seq_add_stmt (pre_p, assign);
7503 48220499 : gsi = gsi_last (*pre_p);
7504 48220499 : maybe_fold_stmt (&gsi);
7505 :
7506 48220499 : if (want_value)
7507 : {
7508 679626 : *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
7509 679626 : return GS_OK;
7510 : }
7511 : else
7512 47540873 : *expr_p = NULL;
7513 :
7514 47540873 : return GS_ALL_DONE;
7515 : }
7516 :
7517 : /* Gimplify a comparison between two variable-sized objects. Do this
7518 : with a call to BUILT_IN_MEMCMP. */
7519 :
7520 : static enum gimplify_status
7521 0 : gimplify_variable_sized_compare (tree *expr_p)
7522 : {
7523 0 : location_t loc = EXPR_LOCATION (*expr_p);
7524 0 : tree op0 = TREE_OPERAND (*expr_p, 0);
7525 0 : tree op1 = TREE_OPERAND (*expr_p, 1);
7526 0 : tree t, arg, dest, src, expr;
7527 :
7528 0 : arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
7529 0 : arg = unshare_expr (arg);
7530 0 : arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
7531 0 : src = build_fold_addr_expr_loc (loc, op1);
7532 0 : dest = build_fold_addr_expr_loc (loc, op0);
7533 0 : t = builtin_decl_implicit (BUILT_IN_MEMCMP);
7534 0 : t = build_call_expr_loc (loc, t, 3, dest, src, arg);
7535 :
7536 0 : expr
7537 0 : = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
7538 0 : SET_EXPR_LOCATION (expr, loc);
7539 0 : *expr_p = expr;
7540 :
7541 0 : return GS_OK;
7542 : }
7543 :
7544 : /* Gimplify a comparison between two aggregate objects of integral scalar
7545 : mode as a comparison between the bitwise equivalent scalar values. */
7546 :
7547 : static enum gimplify_status
7548 16 : gimplify_scalar_mode_aggregate_compare (tree *expr_p)
7549 : {
7550 16 : const location_t loc = EXPR_LOCATION (*expr_p);
7551 16 : const enum tree_code code = TREE_CODE (*expr_p);
7552 16 : tree op0 = TREE_OPERAND (*expr_p, 0);
7553 16 : tree op1 = TREE_OPERAND (*expr_p, 1);
7554 16 : tree type = TREE_TYPE (op0);
7555 16 : tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
7556 :
7557 16 : op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
7558 16 : op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
7559 :
7560 : /* We need to perform ordering comparisons in memory order like memcmp and,
7561 : therefore, may need to byte-swap operands for little-endian targets. */
7562 16 : if (code != EQ_EXPR && code != NE_EXPR)
7563 : {
7564 0 : gcc_assert (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN);
7565 0 : gcc_assert (TREE_CODE (scalar_type) == INTEGER_TYPE);
7566 0 : tree fndecl;
7567 :
7568 0 : if (BYTES_BIG_ENDIAN)
7569 : fndecl = NULL_TREE;
7570 : else
7571 0 : switch (int_size_in_bytes (scalar_type))
7572 : {
7573 : case 1:
7574 : fndecl = NULL_TREE;
7575 : break;
7576 0 : case 2:
7577 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP16);
7578 0 : break;
7579 0 : case 4:
7580 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP32);
7581 0 : break;
7582 0 : case 8:
7583 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP64);
7584 0 : break;
7585 0 : case 16:
7586 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP128);
7587 0 : break;
7588 0 : default:
7589 0 : gcc_unreachable ();
7590 : }
7591 :
7592 0 : if (fndecl)
7593 : {
7594 0 : op0 = build_call_expr_loc (loc, fndecl, 1, op0);
7595 0 : op1 = build_call_expr_loc (loc, fndecl, 1, op1);
7596 : }
7597 : }
7598 :
7599 16 : *expr_p = fold_build2_loc (loc, code, TREE_TYPE (*expr_p), op0, op1);
7600 :
7601 16 : return GS_OK;
7602 : }
7603 :
7604 : /* Gimplify an expression sequence. This function gimplifies each
7605 : expression and rewrites the original expression with the last
7606 : expression of the sequence in GIMPLE form.
7607 :
7608 : PRE_P points to the list where the side effects for all the
7609 : expressions in the sequence will be emitted.
7610 :
7611 : WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
7612 :
7613 : static enum gimplify_status
7614 1119587 : gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
7615 : {
7616 1119587 : tree t = *expr_p;
7617 :
7618 1209628 : do
7619 : {
7620 1209628 : tree *sub_p = &TREE_OPERAND (t, 0);
7621 :
7622 1209628 : if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
7623 208586 : gimplify_compound_expr (sub_p, pre_p, false);
7624 : else
7625 1001042 : gimplify_stmt (sub_p, pre_p);
7626 :
7627 1209628 : t = TREE_OPERAND (t, 1);
7628 : }
7629 1209628 : while (TREE_CODE (t) == COMPOUND_EXPR);
7630 :
7631 1119587 : *expr_p = t;
7632 1119587 : if (want_value)
7633 : return GS_OK;
7634 : else
7635 : {
7636 616459 : gimplify_stmt (expr_p, pre_p);
7637 616459 : return GS_ALL_DONE;
7638 : }
7639 : }
7640 :
7641 : /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
7642 : gimplify. After gimplification, EXPR_P will point to a new temporary
7643 : that holds the original value of the SAVE_EXPR node.
7644 :
7645 : PRE_P points to the list where side effects that must happen before
7646 : *EXPR_P should be stored. */
7647 :
7648 : static enum gimplify_status
7649 442533 : gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7650 : {
7651 442533 : enum gimplify_status ret = GS_ALL_DONE;
7652 442533 : tree val;
7653 :
7654 442533 : gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
7655 442533 : val = TREE_OPERAND (*expr_p, 0);
7656 :
7657 442533 : if (val && TREE_TYPE (val) == error_mark_node)
7658 : return GS_ERROR;
7659 :
7660 : /* If the SAVE_EXPR has not been resolved, then evaluate it once. */
7661 442531 : if (!SAVE_EXPR_RESOLVED_P (*expr_p))
7662 : {
7663 : /* The operand may be a void-valued expression. It is
7664 : being executed only for its side-effects. */
7665 169803 : if (TREE_TYPE (val) == void_type_node)
7666 : {
7667 750 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7668 : is_gimple_stmt, fb_none);
7669 750 : val = NULL;
7670 : }
7671 : else
7672 : /* The temporary may not be an SSA name as later abnormal and EH
7673 : control flow may invalidate use/def domination. When in SSA
7674 : form then assume there are no such issues and SAVE_EXPRs only
7675 : appear via GENERIC foldings. */
7676 338106 : val = get_initialized_tmp_var (val, pre_p, post_p,
7677 338106 : gimple_in_ssa_p (cfun));
7678 :
7679 169803 : TREE_OPERAND (*expr_p, 0) = val;
7680 169803 : SAVE_EXPR_RESOLVED_P (*expr_p) = 1;
7681 : }
7682 :
7683 442531 : *expr_p = val;
7684 :
7685 442531 : return ret;
7686 : }
7687 :
7688 : /* Rewrite the ADDR_EXPR node pointed to by EXPR_P
7689 :
7690 : unary_expr
7691 : : ...
7692 : | '&' varname
7693 : ...
7694 :
7695 : PRE_P points to the list where side effects that must happen before
7696 : *EXPR_P should be stored.
7697 :
7698 : POST_P points to the list where side effects that must happen after
7699 : *EXPR_P should be stored. */
7700 :
7701 : static enum gimplify_status
7702 33783823 : gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7703 : {
7704 33783823 : tree expr = *expr_p;
7705 33783823 : tree op0 = TREE_OPERAND (expr, 0);
7706 33783823 : enum gimplify_status ret;
7707 33783823 : location_t loc = EXPR_LOCATION (*expr_p);
7708 :
7709 33783823 : switch (TREE_CODE (op0))
7710 : {
7711 96111 : case INDIRECT_REF:
7712 96111 : do_indirect_ref:
7713 : /* Check if we are dealing with an expression of the form '&*ptr'.
7714 : While the front end folds away '&*ptr' into 'ptr', these
7715 : expressions may be generated internally by the compiler (e.g.,
7716 : builtins like __builtin_va_end). */
7717 : /* Caution: the silent array decomposition semantics we allow for
7718 : ADDR_EXPR means we can't always discard the pair. */
7719 : /* Gimplification of the ADDR_EXPR operand may drop
7720 : cv-qualification conversions, so make sure we add them if
7721 : needed. */
7722 96111 : {
7723 96111 : tree op00 = TREE_OPERAND (op0, 0);
7724 96111 : tree t_expr = TREE_TYPE (expr);
7725 96111 : tree t_op00 = TREE_TYPE (op00);
7726 :
7727 96111 : if (!useless_type_conversion_p (t_expr, t_op00))
7728 0 : op00 = fold_convert_loc (loc, TREE_TYPE (expr), op00);
7729 96111 : *expr_p = op00;
7730 96111 : ret = GS_OK;
7731 : }
7732 96111 : break;
7733 :
7734 0 : case VIEW_CONVERT_EXPR:
7735 : /* Take the address of our operand and then convert it to the type of
7736 : this ADDR_EXPR.
7737 :
7738 : ??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
7739 : all clear. The impact of this transformation is even less clear. */
7740 :
7741 : /* If the operand is a useless conversion, look through it. Doing so
7742 : guarantees that the ADDR_EXPR and its operand will remain of the
7743 : same type. */
7744 0 : if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
7745 0 : op0 = TREE_OPERAND (op0, 0);
7746 :
7747 0 : *expr_p = fold_convert_loc (loc, TREE_TYPE (expr),
7748 : build_fold_addr_expr_loc (loc,
7749 0 : TREE_OPERAND (op0, 0)));
7750 0 : ret = GS_OK;
7751 0 : break;
7752 :
7753 66220 : case MEM_REF:
7754 66220 : if (integer_zerop (TREE_OPERAND (op0, 1)))
7755 37182 : goto do_indirect_ref;
7756 :
7757 : /* fall through */
7758 :
7759 33704781 : default:
7760 : /* If we see a call to a declared builtin or see its address
7761 : being taken (we can unify those cases here) then we can mark
7762 : the builtin for implicit generation by GCC. */
7763 33704781 : if (TREE_CODE (op0) == FUNCTION_DECL
7764 16776392 : && fndecl_built_in_p (op0, BUILT_IN_NORMAL)
7765 37658101 : && builtin_decl_declared_p (DECL_FUNCTION_CODE (op0)))
7766 1297970 : set_builtin_decl_implicit_p (DECL_FUNCTION_CODE (op0), true);
7767 :
7768 : /* We use fb_either here because the C frontend sometimes takes
7769 : the address of a call that returns a struct; see
7770 : gcc.dg/c99-array-lval-1.c. The gimplifier will correctly make
7771 : the implied temporary explicit. */
7772 :
7773 : /* Make the operand addressable. */
7774 33704781 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
7775 : is_gimple_addressable, fb_either);
7776 33704781 : if (ret == GS_ERROR)
7777 : break;
7778 :
7779 : /* Then mark it. Beware that it may not be possible to do so directly
7780 : if a temporary has been created by the gimplification. */
7781 33704779 : prepare_gimple_addressable (&TREE_OPERAND (expr, 0), pre_p);
7782 :
7783 33704779 : op0 = TREE_OPERAND (expr, 0);
7784 :
7785 : /* For various reasons, the gimplification of the expression
7786 : may have made a new INDIRECT_REF. */
7787 33704779 : if (INDIRECT_REF_P (op0)
7788 33704779 : || (TREE_CODE (op0) == MEM_REF
7789 46107 : && integer_zerop (TREE_OPERAND (op0, 1))))
7790 17069 : goto do_indirect_ref;
7791 :
7792 33687710 : mark_addressable (TREE_OPERAND (expr, 0));
7793 :
7794 : /* The FEs may end up building ADDR_EXPRs early on a decl with
7795 : an incomplete type. Re-build ADDR_EXPRs in canonical form
7796 : here. */
7797 33687710 : if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
7798 149421 : *expr_p = build_fold_addr_expr (op0);
7799 :
7800 : /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */
7801 33687710 : if (TREE_CODE (*expr_p) == ADDR_EXPR)
7802 33687709 : recompute_tree_invariant_for_addr_expr (*expr_p);
7803 :
7804 : /* If we re-built the ADDR_EXPR add a conversion to the original type
7805 : if required. */
7806 33687710 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
7807 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
7808 :
7809 : break;
7810 : }
7811 :
7812 33783823 : return ret;
7813 : }
7814 :
7815 : /* Return the number of times character C occurs in string S. */
7816 :
7817 : static int
7818 94334 : num_occurrences (int c, const char *s)
7819 : {
7820 94334 : int n = 0;
7821 255707 : while (*s)
7822 161373 : n += (*s++ == c);
7823 94334 : return n;
7824 : }
7825 :
7826 : /* A subroutine of gimplify_asm_expr. Check that all operands have
7827 : the same number of alternatives. Return -1 if this is violated. Otherwise
7828 : return the number of alternatives. */
7829 :
7830 : static int
7831 196124 : num_alternatives (const_tree link)
7832 : {
7833 196124 : if (link == nullptr)
7834 : return 0;
7835 :
7836 48576 : const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7837 48576 : int num = num_occurrences (',', constraint);
7838 :
7839 48576 : if (num + 1 > MAX_RECOG_ALTERNATIVES)
7840 : return -1;
7841 :
7842 94334 : for (link = TREE_CHAIN (link); link; link = TREE_CHAIN (link))
7843 : {
7844 45758 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7845 91516 : if (num_occurrences (',', constraint) != num)
7846 : return -1;
7847 : }
7848 48576 : return num + 1;
7849 : }
7850 :
7851 : /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple
7852 : value; output operands should be a gimple lvalue. */
7853 :
7854 : static enum gimplify_status
7855 98062 : gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7856 : {
7857 98062 : tree expr;
7858 98062 : int noutputs;
7859 98062 : const char **oconstraints;
7860 98062 : int i;
7861 98062 : tree link;
7862 98062 : const char *constraint;
7863 98062 : bool allows_mem, allows_reg, is_inout;
7864 98062 : enum gimplify_status ret, tret;
7865 98062 : gasm *stmt;
7866 98062 : vec<tree, va_gc> *inputs;
7867 98062 : vec<tree, va_gc> *outputs;
7868 98062 : vec<tree, va_gc> *clobbers;
7869 98062 : vec<tree, va_gc> *labels;
7870 98062 : tree link_next;
7871 :
7872 98062 : expr = *expr_p;
7873 98062 : noutputs = list_length (ASM_OUTPUTS (expr));
7874 98062 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
7875 :
7876 98062 : inputs = NULL;
7877 98062 : outputs = NULL;
7878 98062 : clobbers = NULL;
7879 98062 : labels = NULL;
7880 :
7881 98062 : int num_alternatives_out = num_alternatives (ASM_OUTPUTS (expr));
7882 98062 : int num_alternatives_in = num_alternatives (ASM_INPUTS (expr));
7883 98062 : if (num_alternatives_out == -1 || num_alternatives_in == -1
7884 98062 : || (num_alternatives_out > 0 && num_alternatives_in > 0
7885 17203 : && num_alternatives_out != num_alternatives_in))
7886 : {
7887 0 : error ("operand constraints for %<asm%> differ "
7888 : "in number of alternatives");
7889 0 : return GS_ERROR;
7890 : }
7891 98062 : int num_alternatives = MAX (num_alternatives_out, num_alternatives_in);
7892 :
7893 98062 : gimplify_reg_info reg_info (num_alternatives, noutputs);
7894 :
7895 98062 : link_next = NULL_TREE;
7896 193538 : for (link = ASM_CLOBBERS (expr); link; link = link_next)
7897 : {
7898 : /* The clobber entry could also be an error marker. */
7899 95476 : if (TREE_CODE (TREE_VALUE (link)) == STRING_CST)
7900 : {
7901 95453 : const char *regname= TREE_STRING_POINTER (TREE_VALUE (link));
7902 95453 : int regno = decode_reg_name (regname);
7903 95453 : if (regno >= 0)
7904 41262 : reg_info.set_clobbered (regno);
7905 : }
7906 95476 : link_next = TREE_CHAIN (link);
7907 95476 : TREE_CHAIN (link) = NULL_TREE;
7908 95476 : vec_safe_push (clobbers, link);
7909 : }
7910 :
7911 98062 : ret = GS_ALL_DONE;
7912 98062 : link_next = NULL_TREE;
7913 158781 : for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
7914 : {
7915 60752 : bool ok;
7916 60752 : size_t constraint_len;
7917 :
7918 60752 : if (error_operand_p (TREE_VALUE (link)))
7919 : return GS_ERROR;
7920 60731 : link_next = TREE_CHAIN (link);
7921 :
7922 121462 : oconstraints[i]
7923 60731 : = constraint
7924 60731 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7925 60731 : constraint_len = strlen (constraint);
7926 60731 : if (constraint_len == 0)
7927 0 : continue;
7928 :
7929 60731 : reg_info.operand = TREE_VALUE (link);
7930 60731 : ok = parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
7931 : &allows_reg, &is_inout, ®_info);
7932 60731 : if (!ok)
7933 : {
7934 11 : ret = GS_ERROR;
7935 11 : is_inout = false;
7936 : }
7937 :
7938 : /* If we can't make copies, we can only accept memory.
7939 : Similarly for VLAs. */
7940 60731 : tree outtype = TREE_TYPE (TREE_VALUE (link));
7941 60731 : if (TREE_ADDRESSABLE (outtype)
7942 60708 : || !COMPLETE_TYPE_P (outtype)
7943 121398 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (outtype)))
7944 : {
7945 382 : if (allows_mem)
7946 370 : allows_reg = 0;
7947 : else
7948 : {
7949 12 : error ("impossible constraint in %<asm%>");
7950 12 : error ("non-memory output %d must stay in memory", i);
7951 12 : return GS_ERROR;
7952 : }
7953 : }
7954 :
7955 60719 : if (!allows_reg && allows_mem)
7956 2169 : mark_addressable (TREE_VALUE (link));
7957 :
7958 60719 : tree orig = TREE_VALUE (link);
7959 112770 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
7960 : is_inout ? is_gimple_min_lval : is_gimple_lvalue,
7961 : fb_lvalue | fb_mayfail);
7962 60719 : if (tret == GS_ERROR)
7963 : {
7964 0 : if (orig != error_mark_node)
7965 0 : error ("invalid lvalue in %<asm%> output %d", i);
7966 : ret = tret;
7967 : }
7968 :
7969 : /* If the gimplified operand is a register we do not allow memory. */
7970 60719 : if (allows_reg
7971 58547 : && allows_mem
7972 67007 : && (is_gimple_reg (TREE_VALUE (link))
7973 267 : || (handled_component_p (TREE_VALUE (link))
7974 36 : && is_gimple_reg (TREE_OPERAND (TREE_VALUE (link), 0)))))
7975 6022 : allows_mem = 0;
7976 :
7977 : /* If the constraint does not allow memory make sure we gimplify
7978 : it to a register if it is not already but its base is. This
7979 : happens for complex and vector components. */
7980 60719 : if (!allows_mem)
7981 : {
7982 58284 : tree op = TREE_VALUE (link);
7983 58284 : if (! is_gimple_val (op)
7984 21086 : && is_gimple_reg_type (TREE_TYPE (op))
7985 79369 : && is_gimple_reg (get_base_address (op)))
7986 : {
7987 19 : tree tem = create_tmp_reg (TREE_TYPE (op));
7988 19 : tree ass;
7989 19 : if (is_inout)
7990 : {
7991 7 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem),
7992 : tem, unshare_expr (op));
7993 7 : gimplify_and_add (ass, pre_p);
7994 : }
7995 19 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem), op, tem);
7996 19 : gimplify_and_add (ass, post_p);
7997 :
7998 19 : TREE_VALUE (link) = tem;
7999 19 : tret = GS_OK;
8000 : }
8001 : }
8002 :
8003 60719 : vec_safe_push (outputs, link);
8004 60719 : TREE_CHAIN (link) = NULL_TREE;
8005 :
8006 60719 : if (is_inout)
8007 : {
8008 : /* An input/output operand. To give the optimizers more
8009 : flexibility, split it into separate input and output
8010 : operands. */
8011 8668 : tree input;
8012 : /* Buffer big enough to format a 32-bit UINT_MAX into. */
8013 8668 : char buf[11];
8014 :
8015 : /* Turn the in/out constraint into an output constraint. */
8016 8668 : char *p = xstrdup (constraint);
8017 8668 : p[0] = '=';
8018 8668 : TREE_PURPOSE (link) = unshare_expr (TREE_PURPOSE (link));
8019 8668 : TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
8020 :
8021 : /* And add a matching input constraint. */
8022 8668 : if (allows_reg)
8023 : {
8024 8167 : sprintf (buf, "%u", i);
8025 :
8026 : /* If there are multiple alternatives in the constraint,
8027 : handle each of them individually. Those that allow register
8028 : will be replaced with operand number, the others will stay
8029 : unchanged. */
8030 8167 : if (strchr (p, ',') != NULL)
8031 : {
8032 100 : size_t len = 0, buflen = strlen (buf);
8033 100 : char *beg, *end, *str, *dst;
8034 :
8035 100 : for (beg = p + 1;;)
8036 : {
8037 200 : end = strchr (beg, ',');
8038 200 : if (end == NULL)
8039 100 : end = strchr (beg, '\0');
8040 200 : if ((size_t) (end - beg) < buflen)
8041 28 : len += buflen + 1;
8042 : else
8043 172 : len += end - beg + 1;
8044 200 : if (*end)
8045 100 : beg = end + 1;
8046 : else
8047 : break;
8048 : }
8049 :
8050 100 : str = (char *) alloca (len);
8051 100 : for (beg = p + 1, dst = str;;)
8052 : {
8053 200 : const char *tem;
8054 200 : bool mem_p, reg_p, inout_p;
8055 :
8056 200 : end = strchr (beg, ',');
8057 200 : if (end)
8058 100 : *end = '\0';
8059 200 : beg[-1] = '=';
8060 200 : tem = beg - 1;
8061 200 : parse_output_constraint (&tem, i, 0, 0, &mem_p, ®_p,
8062 : &inout_p, nullptr);
8063 200 : if (dst != str)
8064 100 : *dst++ = ',';
8065 200 : if (reg_p)
8066 : {
8067 115 : memcpy (dst, buf, buflen);
8068 115 : dst += buflen;
8069 : }
8070 : else
8071 : {
8072 85 : if (end)
8073 0 : len = end - beg;
8074 : else
8075 85 : len = strlen (beg);
8076 85 : memcpy (dst, beg, len);
8077 85 : dst += len;
8078 : }
8079 200 : if (end)
8080 100 : beg = end + 1;
8081 : else
8082 : break;
8083 100 : }
8084 100 : *dst = '\0';
8085 100 : input = build_string (dst - str, str);
8086 : }
8087 : else
8088 8067 : input = build_string (strlen (buf), buf);
8089 : }
8090 : else
8091 501 : input = build_string (constraint_len - 1, constraint + 1);
8092 :
8093 8668 : free (p);
8094 :
8095 8668 : input = build_tree_list (build_tree_list (NULL_TREE, input),
8096 8668 : unshare_expr (TREE_VALUE (link)));
8097 8668 : ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
8098 : }
8099 : }
8100 :
8101 : /* After all output operands have been gimplified, verify that each output
8102 : operand is used at most once in case of hard register constraints. Thus,
8103 : error out in cases like
8104 : asm ("" : "={0}" (x), "={1}" (x));
8105 : or even for
8106 : asm ("" : "=r" (x), "={1}" (x));
8107 :
8108 : FIXME: Ideally we would also error out for cases like
8109 : int x;
8110 : asm ("" : "=r" (x), "=r" (x));
8111 : However, since code like that was previously accepted, erroring out now might
8112 : break existing code. On the other hand, we already error out for register
8113 : asm like
8114 : register int x asm ("0");
8115 : asm ("" : "=r" (x), "=r" (x));
8116 : Thus, maybe it wouldn't be too bad to also error out in the former
8117 : non-register-asm case.
8118 : */
8119 158744 : for (unsigned i = 0; i < vec_safe_length (outputs); ++i)
8120 : {
8121 60717 : tree link = (*outputs)[i];
8122 60717 : tree op1 = TREE_VALUE (link);
8123 60717 : const char *constraint
8124 60717 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8125 60717 : if (strchr (constraint, '{') != nullptr)
8126 236 : for (unsigned j = 0; j < vec_safe_length (outputs); ++j)
8127 : {
8128 142 : if (i == j)
8129 95 : continue;
8130 47 : tree link2 = (*outputs)[j];
8131 47 : tree op2 = TREE_VALUE (link2);
8132 47 : if (op1 == op2)
8133 : {
8134 2 : error ("multiple outputs to lvalue %qE", op2);
8135 2 : return GS_ERROR;
8136 : }
8137 : }
8138 : }
8139 :
8140 98027 : link_next = NULL_TREE;
8141 98027 : int input_num = 0;
8142 140215 : for (link = ASM_INPUTS (expr); link; ++input_num, ++i, link = link_next)
8143 : {
8144 42246 : if (error_operand_p (TREE_VALUE (link)))
8145 : return GS_ERROR;
8146 42197 : link_next = TREE_CHAIN (link);
8147 42197 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8148 42197 : reg_info.operand = TREE_VALUE (link);
8149 42197 : bool ok = parse_input_constraint (&constraint, input_num, 0, noutputs, 0,
8150 : oconstraints, &allows_mem, &allows_reg,
8151 : ®_info);
8152 42197 : if (!ok)
8153 : {
8154 30 : ret = GS_ERROR;
8155 30 : is_inout = false;
8156 : }
8157 :
8158 : /* If we can't make copies, we can only accept memory. */
8159 42197 : tree intype = TREE_TYPE (TREE_VALUE (link));
8160 42197 : if (TREE_ADDRESSABLE (intype)
8161 42171 : || !COMPLETE_TYPE_P (intype)
8162 84313 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (intype)))
8163 : {
8164 391 : if (allows_mem)
8165 382 : allows_reg = 0;
8166 : else
8167 : {
8168 9 : error ("impossible constraint in %<asm%>");
8169 9 : error ("non-memory input %d must stay in memory", i);
8170 9 : return GS_ERROR;
8171 : }
8172 : }
8173 :
8174 : /* If the operand is a memory input, it should be an lvalue. */
8175 42188 : if (!allows_reg && allows_mem)
8176 : {
8177 2480 : tree inputv = TREE_VALUE (link);
8178 2480 : STRIP_NOPS (inputv);
8179 2480 : if (TREE_CODE (inputv) == PREDECREMENT_EXPR
8180 : || TREE_CODE (inputv) == PREINCREMENT_EXPR
8181 : || TREE_CODE (inputv) == POSTDECREMENT_EXPR
8182 2480 : || TREE_CODE (inputv) == POSTINCREMENT_EXPR
8183 2468 : || TREE_CODE (inputv) == MODIFY_EXPR
8184 4946 : || VOID_TYPE_P (TREE_TYPE (inputv)))
8185 38 : TREE_VALUE (link) = error_mark_node;
8186 2480 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8187 : is_gimple_lvalue, fb_lvalue | fb_mayfail);
8188 2480 : if (tret != GS_ERROR)
8189 : {
8190 : /* Unlike output operands, memory inputs are not guaranteed
8191 : to be lvalues by the FE, and while the expressions are
8192 : marked addressable there, if it is e.g. a statement
8193 : expression, temporaries in it might not end up being
8194 : addressable. They might be already used in the IL and thus
8195 : it is too late to make them addressable now though. */
8196 2434 : tree x = TREE_VALUE (link);
8197 2576 : while (handled_component_p (x))
8198 142 : x = TREE_OPERAND (x, 0);
8199 2434 : if (TREE_CODE (x) == MEM_REF
8200 2434 : && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
8201 0 : x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
8202 2434 : if ((VAR_P (x)
8203 : || TREE_CODE (x) == PARM_DECL
8204 : || TREE_CODE (x) == RESULT_DECL)
8205 1483 : && !TREE_ADDRESSABLE (x)
8206 23 : && is_gimple_reg (x))
8207 : {
8208 17 : warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link),
8209 17 : input_location), 0,
8210 : "memory input %d is not directly addressable",
8211 : i);
8212 17 : prepare_gimple_addressable (&TREE_VALUE (link), pre_p);
8213 : }
8214 : }
8215 2480 : mark_addressable (TREE_VALUE (link));
8216 2480 : if (tret == GS_ERROR)
8217 : {
8218 46 : if (inputv != error_mark_node)
8219 46 : error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
8220 : "memory input %d is not directly addressable", i);
8221 : ret = tret;
8222 : }
8223 : }
8224 : else
8225 : {
8226 39708 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8227 : is_gimple_asm_val, fb_rvalue);
8228 39708 : if (tret == GS_ERROR)
8229 46 : ret = tret;
8230 : }
8231 :
8232 42188 : TREE_CHAIN (link) = NULL_TREE;
8233 42188 : vec_safe_push (inputs, link);
8234 : }
8235 :
8236 97969 : link_next = NULL_TREE;
8237 98867 : for (link = ASM_LABELS (expr); link; link = link_next)
8238 : {
8239 898 : link_next = TREE_CHAIN (link);
8240 898 : TREE_CHAIN (link) = NULL_TREE;
8241 898 : vec_safe_push (labels, link);
8242 : }
8243 :
8244 : /* Do not add ASMs with errors to the gimple IL stream. */
8245 97969 : if (ret != GS_ERROR)
8246 : {
8247 97886 : stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
8248 : inputs, outputs, clobbers, labels);
8249 :
8250 : /* asm is volatile if it was marked by the user as volatile or
8251 : there are no outputs or this is an asm goto. */
8252 195772 : gimple_asm_set_volatile (stmt,
8253 97886 : ASM_VOLATILE_P (expr)
8254 7519 : || noutputs == 0
8255 105391 : || labels);
8256 97886 : gimple_asm_set_basic (stmt, ASM_BASIC_P (expr));
8257 97886 : gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
8258 :
8259 97886 : gimplify_seq_add_stmt (pre_p, stmt);
8260 : }
8261 :
8262 : return ret;
8263 98062 : }
8264 :
8265 : /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding
8266 : GIMPLE_WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
8267 : gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we
8268 : return to this function.
8269 :
8270 : FIXME should we complexify the prequeue handling instead? Or use flags
8271 : for all the cleanups and let the optimizer tighten them up? The current
8272 : code seems pretty fragile; it will break on a cleanup within any
8273 : non-conditional nesting. But any such nesting would be broken, anyway;
8274 : we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
8275 : and continues out of it. We can do that at the RTL level, though, so
8276 : having an optimizer to tighten up try/finally regions would be a Good
8277 : Thing. */
8278 :
8279 : static enum gimplify_status
8280 5389181 : gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
8281 : {
8282 5389181 : gimple_stmt_iterator iter;
8283 5389181 : gimple_seq body_sequence = NULL;
8284 :
8285 5389181 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
8286 :
8287 : /* We only care about the number of conditions between the innermost
8288 : CLEANUP_POINT_EXPR and the cleanup. So save and reset the count and
8289 : any cleanups collected outside the CLEANUP_POINT_EXPR. */
8290 5389181 : int old_conds = gimplify_ctxp->conditions;
8291 5389181 : gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
8292 5389181 : bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
8293 5389181 : gimplify_ctxp->conditions = 0;
8294 5389181 : gimplify_ctxp->conditional_cleanups = NULL;
8295 5389181 : gimplify_ctxp->in_cleanup_point_expr = true;
8296 :
8297 5389181 : gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
8298 :
8299 5389181 : gimplify_ctxp->conditions = old_conds;
8300 5389181 : gimplify_ctxp->conditional_cleanups = old_cleanups;
8301 5389181 : gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
8302 :
8303 27950604 : for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
8304 : {
8305 17217218 : gimple *wce = gsi_stmt (iter);
8306 :
8307 17217218 : if (gimple_code (wce) == GIMPLE_WITH_CLEANUP_EXPR)
8308 : {
8309 652329 : if (gsi_one_before_end_p (iter))
8310 : {
8311 : /* Note that gsi_insert_seq_before and gsi_remove do not
8312 : scan operands, unlike some other sequence mutators. */
8313 3138 : if (!gimple_wce_cleanup_eh_only (wce))
8314 3138 : gsi_insert_seq_before_without_update (&iter,
8315 : gimple_wce_cleanup (wce),
8316 : GSI_SAME_STMT);
8317 3138 : gsi_remove (&iter, true);
8318 3138 : break;
8319 : }
8320 : else
8321 : {
8322 649191 : gtry *gtry;
8323 649191 : gimple_seq seq;
8324 649191 : enum gimple_try_flags kind;
8325 :
8326 649191 : if (gimple_wce_cleanup_eh_only (wce))
8327 : kind = GIMPLE_TRY_CATCH;
8328 : else
8329 634484 : kind = GIMPLE_TRY_FINALLY;
8330 649191 : seq = gsi_split_seq_after (iter);
8331 :
8332 649191 : gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
8333 : /* Do not use gsi_replace here, as it may scan operands.
8334 : We want to do a simple structural modification only. */
8335 649191 : gsi_set_stmt (&iter, gtry);
8336 1298382 : iter = gsi_start (gtry->eval);
8337 : }
8338 : }
8339 : else
8340 16564889 : gsi_next (&iter);
8341 : }
8342 :
8343 5389181 : gimplify_seq_add_seq (pre_p, body_sequence);
8344 5389181 : if (temp)
8345 : {
8346 356233 : *expr_p = temp;
8347 356233 : return GS_OK;
8348 : }
8349 : else
8350 : {
8351 5032948 : *expr_p = NULL;
8352 5032948 : return GS_ALL_DONE;
8353 : }
8354 : }
8355 :
8356 : /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
8357 : is the cleanup action required. EH_ONLY is true if the cleanup should
8358 : only be executed if an exception is thrown, not on normal exit.
8359 : If FORCE_UNCOND is true perform the cleanup unconditionally; this is
8360 : only valid for clobbers. */
8361 :
8362 : static void
8363 657322 : gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
8364 : bool force_uncond = false)
8365 : {
8366 657322 : gimple *wce;
8367 657322 : gimple_seq cleanup_stmts = NULL;
8368 :
8369 : /* Errors can result in improperly nested cleanups. Which results in
8370 : confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
8371 657322 : if (seen_error ())
8372 4993 : return;
8373 :
8374 652329 : if (gimple_conditional_context ())
8375 : {
8376 : /* If we're in a conditional context, this is more complex. We only
8377 : want to run the cleanup if we actually ran the initialization that
8378 : necessitates it, but we want to run it after the end of the
8379 : conditional context. So we wrap the try/finally around the
8380 : condition and use a flag to determine whether or not to actually
8381 : run the destructor. Thus
8382 :
8383 : test ? f(A()) : 0
8384 :
8385 : becomes (approximately)
8386 :
8387 : flag = 0;
8388 : try {
8389 : if (test) { A::A(temp); flag = 1; val = f(temp); }
8390 : else { val = 0; }
8391 : } finally {
8392 : if (flag) A::~A(temp);
8393 : }
8394 : val
8395 : */
8396 15723 : if (force_uncond)
8397 : {
8398 14837 : gimplify_stmt (&cleanup, &cleanup_stmts);
8399 14837 : wce = gimple_build_wce (cleanup_stmts);
8400 14837 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8401 : }
8402 : else
8403 : {
8404 886 : tree flag = create_tmp_var (boolean_type_node, "cleanup");
8405 886 : gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
8406 886 : gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
8407 :
8408 886 : cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
8409 886 : gimplify_stmt (&cleanup, &cleanup_stmts);
8410 886 : wce = gimple_build_wce (cleanup_stmts);
8411 886 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8412 :
8413 886 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
8414 886 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8415 886 : gimplify_seq_add_stmt (pre_p, ftrue);
8416 :
8417 : /* Because of this manipulation, and the EH edges that jump
8418 : threading cannot redirect, the temporary (VAR) will appear
8419 : to be used uninitialized. Don't warn. */
8420 886 : suppress_warning (var, OPT_Wuninitialized);
8421 : }
8422 : }
8423 : else
8424 : {
8425 636606 : gimplify_stmt (&cleanup, &cleanup_stmts);
8426 636606 : wce = gimple_build_wce (cleanup_stmts);
8427 636606 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8428 636606 : gimplify_seq_add_stmt (pre_p, wce);
8429 : }
8430 : }
8431 :
8432 : /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
8433 :
8434 : static enum gimplify_status
8435 860707 : gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
8436 : {
8437 860707 : tree targ = *expr_p;
8438 860707 : tree temp = TARGET_EXPR_SLOT (targ);
8439 860707 : tree init = TARGET_EXPR_INITIAL (targ);
8440 860707 : enum gimplify_status ret;
8441 :
8442 860707 : bool unpoison_empty_seq = false;
8443 860707 : gimple_stmt_iterator unpoison_it;
8444 :
8445 860707 : if (init)
8446 : {
8447 826507 : gimple_seq init_pre_p = NULL;
8448 826507 : bool is_vla = false;
8449 :
8450 : /* TARGET_EXPR temps aren't part of the enclosing block, so add it
8451 : to the temps list. Handle also variable length TARGET_EXPRs. */
8452 826507 : if (!poly_int_tree_p (DECL_SIZE (temp)))
8453 : {
8454 44 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
8455 1 : gimplify_type_sizes (TREE_TYPE (temp), &init_pre_p);
8456 : /* FIXME: this is correct only when the size of the type does
8457 : not depend on expressions evaluated in init. */
8458 44 : gimplify_vla_decl (temp, &init_pre_p);
8459 44 : is_vla = true;
8460 : }
8461 : else
8462 : {
8463 : /* Save location where we need to place unpoisoning. It's possible
8464 : that a variable will be converted to needs_to_live_in_memory. */
8465 826463 : unpoison_it = gsi_last (*pre_p);
8466 826463 : unpoison_empty_seq = gsi_end_p (unpoison_it);
8467 :
8468 826463 : gimple_add_tmp_var (temp);
8469 : }
8470 :
8471 826507 : if (var_needs_auto_init_p (temp) && VOID_TYPE_P (TREE_TYPE (init)))
8472 : {
8473 59066 : gimple_add_init_for_auto_var (temp, flag_auto_var_init, &init_pre_p);
8474 59066 : if (flag_auto_var_init == AUTO_INIT_PATTERN
8475 0 : && !is_gimple_reg (temp)
8476 59066 : && clear_padding_type_may_have_padding_p (TREE_TYPE (temp)))
8477 0 : gimple_add_padding_init_for_auto_var (temp, is_vla, &init_pre_p);
8478 : }
8479 :
8480 : /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
8481 : expression is supposed to initialize the slot. */
8482 826507 : if (VOID_TYPE_P (TREE_TYPE (init)))
8483 291156 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8484 : fb_none);
8485 : else
8486 : {
8487 535351 : tree init_expr = build2 (INIT_EXPR, void_type_node, temp, init);
8488 535351 : init = init_expr;
8489 535351 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8490 : fb_none);
8491 535351 : init = NULL;
8492 535351 : ggc_free (init_expr);
8493 : }
8494 826507 : if (ret == GS_ERROR)
8495 : {
8496 : /* PR c++/28266 Make sure this is expanded only once. */
8497 10 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8498 10 : return GS_ERROR;
8499 : }
8500 :
8501 826497 : if (init)
8502 0 : gimplify_and_add (init, &init_pre_p);
8503 :
8504 : /* Add a clobber for the temporary going out of scope, like
8505 : gimplify_bind_expr. But only if we did not promote the
8506 : temporary to static storage. */
8507 826497 : if (gimplify_ctxp->in_cleanup_point_expr
8508 682535 : && !TREE_STATIC (temp)
8509 1507476 : && needs_to_live_in_memory (temp))
8510 : {
8511 503508 : if (flag_stack_reuse == SR_ALL)
8512 : {
8513 503022 : tree clobber = build_clobber (TREE_TYPE (temp),
8514 : CLOBBER_STORAGE_END);
8515 503022 : clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
8516 503022 : gimple_push_cleanup (temp, clobber, false, pre_p, true);
8517 : }
8518 503508 : if (asan_poisoned_variables
8519 486 : && DECL_ALIGN (temp) <= MAX_SUPPORTED_STACK_ALIGNMENT
8520 486 : && !TREE_STATIC (temp)
8521 486 : && dbg_cnt (asan_use_after_scope)
8522 503994 : && !gimplify_omp_ctxp)
8523 : {
8524 478 : tree asan_cleanup = build_asan_poison_call_expr (temp);
8525 478 : if (asan_cleanup)
8526 : {
8527 478 : if (unpoison_empty_seq)
8528 223 : unpoison_it = gsi_start (*pre_p);
8529 :
8530 478 : asan_poison_variable (temp, false, &unpoison_it,
8531 : unpoison_empty_seq);
8532 478 : gimple_push_cleanup (temp, asan_cleanup, false, pre_p);
8533 : }
8534 : }
8535 : }
8536 :
8537 826497 : gimple_seq_add_seq (pre_p, init_pre_p);
8538 :
8539 : /* If needed, push the cleanup for the temp. */
8540 826497 : if (TARGET_EXPR_CLEANUP (targ))
8541 153822 : gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
8542 153822 : CLEANUP_EH_ONLY (targ), pre_p);
8543 :
8544 : /* Only expand this once. */
8545 826497 : TREE_OPERAND (targ, 3) = init;
8546 826497 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8547 : }
8548 : else
8549 : /* We should have expanded this before. */
8550 34200 : gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
8551 :
8552 860697 : *expr_p = temp;
8553 860697 : return GS_OK;
8554 : }
8555 :
8556 : /* Gimplification of expression trees. */
8557 :
8558 : /* Gimplify an expression which appears at statement context. The
8559 : corresponding GIMPLE statements are added to *SEQ_P. If *SEQ_P is
8560 : NULL, a new sequence is allocated.
8561 :
8562 : Return true if we actually added a statement to the queue. */
8563 :
8564 : bool
8565 103769853 : gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
8566 : {
8567 103769853 : gimple_seq_node last;
8568 :
8569 103769853 : last = gimple_seq_last (*seq_p);
8570 103769853 : gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
8571 103769853 : return last != gimple_seq_last (*seq_p);
8572 : }
8573 :
8574 : /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
8575 : to CTX. If entries already exist, force them to be some flavor of private.
8576 : If there is no enclosing parallel, do nothing. */
8577 :
8578 : void
8579 124161 : omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
8580 : {
8581 124161 : splay_tree_node n;
8582 :
8583 124161 : if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE)
8584 : return;
8585 :
8586 36856 : do
8587 : {
8588 36856 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8589 36856 : if (n != NULL)
8590 : {
8591 4268 : if (n->value & GOVD_SHARED)
8592 183 : n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
8593 4085 : else if (n->value & GOVD_MAP)
8594 58 : n->value |= GOVD_MAP_TO_ONLY;
8595 : else
8596 : return;
8597 : }
8598 32588 : else if ((ctx->region_type & ORT_TARGET) != 0)
8599 : {
8600 7020 : if (ctx->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
8601 4261 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8602 : else
8603 2759 : omp_add_variable (ctx, decl, GOVD_MAP | GOVD_MAP_TO_ONLY);
8604 : }
8605 25568 : else if (ctx->region_type != ORT_WORKSHARE
8606 : && ctx->region_type != ORT_TASKGROUP
8607 23739 : && ctx->region_type != ORT_SIMD
8608 23115 : && ctx->region_type != ORT_ACC
8609 22998 : && !(ctx->region_type & ORT_TARGET_DATA))
8610 14417 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8611 :
8612 32829 : ctx = ctx->outer_context;
8613 : }
8614 32829 : while (ctx);
8615 : }
8616 :
8617 : /* Similarly for each of the type sizes of TYPE. */
8618 :
8619 : static void
8620 39563 : omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
8621 : {
8622 39563 : if (type == NULL || type == error_mark_node)
8623 : return;
8624 39559 : type = TYPE_MAIN_VARIANT (type);
8625 :
8626 39559 : if (ctx->privatized_types->add (type))
8627 : return;
8628 :
8629 30702 : switch (TREE_CODE (type))
8630 : {
8631 13320 : case INTEGER_TYPE:
8632 13320 : case ENUMERAL_TYPE:
8633 13320 : case BOOLEAN_TYPE:
8634 13320 : case REAL_TYPE:
8635 13320 : case FIXED_POINT_TYPE:
8636 13320 : omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
8637 13320 : omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
8638 13320 : break;
8639 :
8640 5333 : case ARRAY_TYPE:
8641 5333 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8642 5333 : omp_firstprivatize_type_sizes (ctx, TYPE_DOMAIN (type));
8643 5333 : break;
8644 :
8645 2502 : case RECORD_TYPE:
8646 2502 : case UNION_TYPE:
8647 2502 : case QUAL_UNION_TYPE:
8648 2502 : {
8649 2502 : tree field;
8650 26645 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
8651 24143 : if (TREE_CODE (field) == FIELD_DECL)
8652 : {
8653 8997 : omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
8654 8997 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (field));
8655 : }
8656 : }
8657 : break;
8658 :
8659 8897 : case POINTER_TYPE:
8660 8897 : case REFERENCE_TYPE:
8661 8897 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8662 8897 : break;
8663 :
8664 : default:
8665 : break;
8666 : }
8667 :
8668 30702 : omp_firstprivatize_variable (ctx, TYPE_SIZE (type));
8669 30702 : omp_firstprivatize_variable (ctx, TYPE_SIZE_UNIT (type));
8670 30702 : lang_hooks.types.omp_firstprivatize_type_sizes (ctx, type);
8671 : }
8672 :
8673 : /* Add an entry for DECL in the OMP context CTX with FLAGS. */
8674 :
8675 : static void
8676 714643 : omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
8677 : {
8678 714643 : splay_tree_node n;
8679 714643 : unsigned int nflags;
8680 714643 : tree t;
8681 :
8682 714643 : if (error_operand_p (decl) || ctx->region_type == ORT_NONE)
8683 : return;
8684 :
8685 : /* Never elide decls whose type has TREE_ADDRESSABLE set. This means
8686 : there are constructors involved somewhere. Exception is a shared clause,
8687 : there is nothing privatized in that case. */
8688 714498 : if ((flags & GOVD_SHARED) == 0
8689 714498 : && (TREE_ADDRESSABLE (TREE_TYPE (decl))
8690 654324 : || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
8691 7766 : flags |= GOVD_SEEN;
8692 :
8693 714498 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8694 714498 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
8695 : {
8696 : /* We shouldn't be re-adding the decl with the same data
8697 : sharing class. */
8698 828 : gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
8699 828 : nflags = n->value | flags;
8700 : /* The only combination of data sharing classes we should see is
8701 : FIRSTPRIVATE and LASTPRIVATE. However, OpenACC permits
8702 : reduction variables to be used in data sharing clauses. */
8703 828 : gcc_assert ((ctx->region_type & ORT_ACC) != 0
8704 : || ((nflags & GOVD_DATA_SHARE_CLASS)
8705 : == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE))
8706 : || (flags & GOVD_DATA_SHARE_CLASS) == 0);
8707 828 : n->value = nflags;
8708 828 : return;
8709 : }
8710 :
8711 : /* When adding a variable-sized variable, we have to handle all sorts
8712 : of additional bits of data: the pointer replacement variable, and
8713 : the parameters of the type. */
8714 713670 : if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl)))
8715 : {
8716 : /* Add the pointer replacement variable as PRIVATE if the variable
8717 : replacement is private, else FIRSTPRIVATE since we'll need the
8718 : address of the original variable either for SHARED, or for the
8719 : copy into or out of the context. */
8720 1330 : if (!(flags & GOVD_LOCAL) && ctx->region_type != ORT_TASKGROUP)
8721 : {
8722 1238 : if (flags & GOVD_MAP)
8723 : nflags = GOVD_MAP | GOVD_MAP_TO_ONLY | GOVD_EXPLICIT;
8724 531 : else if (flags & GOVD_PRIVATE)
8725 : nflags = GOVD_PRIVATE;
8726 441 : else if (((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
8727 50 : && (flags & GOVD_FIRSTPRIVATE))
8728 431 : || (ctx->region_type == ORT_TARGET_DATA
8729 6 : && (flags & GOVD_DATA_SHARE_CLASS) == 0))
8730 : nflags = GOVD_PRIVATE | GOVD_EXPLICIT;
8731 : else
8732 1238 : nflags = GOVD_FIRSTPRIVATE;
8733 1238 : nflags |= flags & GOVD_SEEN;
8734 1238 : t = DECL_VALUE_EXPR (decl);
8735 1238 : gcc_assert (INDIRECT_REF_P (t));
8736 1238 : t = TREE_OPERAND (t, 0);
8737 1238 : gcc_assert (DECL_P (t));
8738 1238 : omp_add_variable (ctx, t, nflags);
8739 : }
8740 :
8741 : /* Add all of the variable and type parameters (which should have
8742 : been gimplified to a formal temporary) as FIRSTPRIVATE. */
8743 1330 : omp_firstprivatize_variable (ctx, DECL_SIZE_UNIT (decl));
8744 1330 : omp_firstprivatize_variable (ctx, DECL_SIZE (decl));
8745 1330 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8746 :
8747 : /* The variable-sized variable itself is never SHARED, only some form
8748 : of PRIVATE. The sharing would take place via the pointer variable
8749 : which we remapped above. */
8750 1330 : if (flags & GOVD_SHARED)
8751 284 : flags = GOVD_SHARED | GOVD_DEBUG_PRIVATE
8752 284 : | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
8753 :
8754 : /* We're going to make use of the TYPE_SIZE_UNIT at least in the
8755 : alloca statement we generate for the variable, so make sure it
8756 : is available. This isn't automatically needed for the SHARED
8757 : case, since we won't be allocating local storage then.
8758 : For local variables TYPE_SIZE_UNIT might not be gimplified yet,
8759 : in this case omp_notice_variable will be called later
8760 : on when it is gimplified. */
8761 1046 : else if (! (flags & (GOVD_LOCAL | GOVD_MAP))
8762 1046 : && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
8763 275 : omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
8764 : }
8765 712340 : else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
8766 712340 : && omp_privatize_by_reference (decl))
8767 : {
8768 9673 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8769 :
8770 : /* Similar to the direct variable sized case above, we'll need the
8771 : size of references being privatized. */
8772 9673 : if ((flags & GOVD_SHARED) == 0)
8773 : {
8774 6103 : t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
8775 6103 : if (t && DECL_P (t))
8776 1385 : omp_notice_variable (ctx, t, true);
8777 : }
8778 : }
8779 :
8780 713670 : if (n != NULL)
8781 1862 : n->value |= flags;
8782 : else
8783 711808 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
8784 :
8785 : /* For reductions clauses in OpenACC loop directives, by default create a
8786 : copy clause on the enclosing parallel construct for carrying back the
8787 : results. */
8788 713670 : if (ctx->region_type == ORT_ACC && (flags & GOVD_REDUCTION))
8789 : {
8790 4716 : struct gimplify_omp_ctx *outer_ctx = ctx->outer_context;
8791 6454 : while (outer_ctx)
8792 : {
8793 5788 : n = splay_tree_lookup (outer_ctx->variables, (splay_tree_key)decl);
8794 5788 : if (n != NULL)
8795 : {
8796 : /* Ignore local variables and explicitly declared clauses. */
8797 3990 : if (n->value & (GOVD_LOCAL | GOVD_EXPLICIT))
8798 : break;
8799 443 : else if (outer_ctx->region_type == ORT_ACC_KERNELS)
8800 : {
8801 : /* According to the OpenACC spec, such a reduction variable
8802 : should already have a copy map on a kernels construct,
8803 : verify that here. */
8804 143 : gcc_assert (!(n->value & GOVD_FIRSTPRIVATE)
8805 : && (n->value & GOVD_MAP));
8806 : }
8807 300 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8808 : {
8809 : /* Remove firstprivate and make it a copy map. */
8810 150 : n->value &= ~GOVD_FIRSTPRIVATE;
8811 150 : n->value |= GOVD_MAP;
8812 : }
8813 : }
8814 1798 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8815 : {
8816 503 : splay_tree_insert (outer_ctx->variables, (splay_tree_key)decl,
8817 : GOVD_MAP | GOVD_SEEN);
8818 503 : break;
8819 : }
8820 1738 : outer_ctx = outer_ctx->outer_context;
8821 : }
8822 : }
8823 : }
8824 :
8825 : /* Notice a threadprivate variable DECL used in OMP context CTX.
8826 : This just prints out diagnostics about threadprivate variable uses
8827 : in untied tasks. If DECL2 is non-NULL, prevent this warning
8828 : on that variable. */
8829 :
8830 : static bool
8831 14183 : omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
8832 : tree decl2)
8833 : {
8834 14183 : splay_tree_node n;
8835 14183 : struct gimplify_omp_ctx *octx;
8836 :
8837 28798 : for (octx = ctx; octx; octx = octx->outer_context)
8838 14615 : if ((octx->region_type & ORT_TARGET) != 0
8839 14615 : || octx->order_concurrent)
8840 : {
8841 112 : n = splay_tree_lookup (octx->variables, (splay_tree_key)decl);
8842 112 : if (n == NULL)
8843 : {
8844 20 : if (octx->order_concurrent)
8845 : {
8846 20 : error ("threadprivate variable %qE used in a region with"
8847 20 : " %<order(concurrent)%> clause", DECL_NAME (decl));
8848 20 : inform (octx->location, "enclosing region");
8849 : }
8850 : else
8851 : {
8852 0 : error ("threadprivate variable %qE used in target region",
8853 0 : DECL_NAME (decl));
8854 0 : inform (octx->location, "enclosing target region");
8855 : }
8856 20 : splay_tree_insert (octx->variables, (splay_tree_key)decl, 0);
8857 : }
8858 112 : if (decl2)
8859 0 : splay_tree_insert (octx->variables, (splay_tree_key)decl2, 0);
8860 : }
8861 :
8862 14183 : if (ctx->region_type != ORT_UNTIED_TASK)
8863 : return false;
8864 37 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8865 37 : if (n == NULL)
8866 : {
8867 6 : error ("threadprivate variable %qE used in untied task",
8868 6 : DECL_NAME (decl));
8869 6 : inform (ctx->location, "enclosing task");
8870 6 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
8871 : }
8872 37 : if (decl2)
8873 4 : splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
8874 : return false;
8875 : }
8876 :
8877 : /* Return true if global var DECL is device resident. */
8878 :
8879 : static bool
8880 642 : device_resident_p (tree decl)
8881 : {
8882 642 : tree attr = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (decl));
8883 :
8884 642 : if (!attr)
8885 : return false;
8886 :
8887 0 : for (tree t = TREE_VALUE (attr); t; t = TREE_PURPOSE (t))
8888 : {
8889 0 : tree c = TREE_VALUE (t);
8890 0 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DEVICE_RESIDENT)
8891 : return true;
8892 : }
8893 :
8894 : return false;
8895 : }
8896 :
8897 : /* Return true if DECL has an ACC DECLARE attribute. */
8898 :
8899 : static bool
8900 9101 : is_oacc_declared (tree decl)
8901 : {
8902 9101 : tree t = TREE_CODE (decl) == MEM_REF ? TREE_OPERAND (decl, 0) : decl;
8903 9101 : tree declared = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (t));
8904 9101 : return declared != NULL_TREE;
8905 : }
8906 :
8907 : /* Determine outer default flags for DECL mentioned in an OMP region
8908 : but not declared in an enclosing clause.
8909 :
8910 : ??? Some compiler-generated variables (like SAVE_EXPRs) could be
8911 : remapped firstprivate instead of shared. To some extent this is
8912 : addressed in omp_firstprivatize_type_sizes, but not
8913 : effectively. */
8914 :
8915 : static unsigned
8916 47699 : omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
8917 : bool in_code, unsigned flags)
8918 : {
8919 47699 : enum omp_clause_default_kind default_kind = ctx->default_kind;
8920 47699 : enum omp_clause_default_kind kind;
8921 :
8922 47699 : kind = lang_hooks.decls.omp_predetermined_sharing (decl);
8923 47699 : if (ctx->region_type & ORT_TASK)
8924 : {
8925 3932 : tree detach_clause = omp_find_clause (ctx->clauses, OMP_CLAUSE_DETACH);
8926 :
8927 : /* The event-handle specified by a detach clause should always be firstprivate,
8928 : regardless of the current default. */
8929 4144 : if (detach_clause && OMP_CLAUSE_DECL (detach_clause) == decl)
8930 : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
8931 : }
8932 47699 : if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
8933 : default_kind = kind;
8934 44912 : else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
8935 : default_kind = OMP_CLAUSE_DEFAULT_SHARED;
8936 : /* For C/C++ default({,first}private), variables with static storage duration
8937 : declared in a namespace or global scope and referenced in construct
8938 : must be explicitly specified, i.e. acts as default(none). */
8939 44911 : else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
8940 44911 : || default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
8941 365 : && VAR_P (decl)
8942 322 : && is_global_var (decl)
8943 184 : && (DECL_FILE_SCOPE_P (decl)
8944 104 : || (DECL_CONTEXT (decl)
8945 104 : && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
8946 45039 : && !lang_GNU_Fortran ())
8947 : default_kind = OMP_CLAUSE_DEFAULT_NONE;
8948 :
8949 47570 : switch (default_kind)
8950 : {
8951 267 : case OMP_CLAUSE_DEFAULT_NONE:
8952 267 : {
8953 267 : const char *rtype;
8954 :
8955 267 : if (ctx->region_type & ORT_PARALLEL)
8956 : rtype = "parallel";
8957 108 : else if ((ctx->region_type & ORT_TASKLOOP) == ORT_TASKLOOP)
8958 : rtype = "taskloop";
8959 72 : else if (ctx->region_type & ORT_TASK)
8960 : rtype = "task";
8961 36 : else if (ctx->region_type & ORT_TEAMS)
8962 : rtype = "teams";
8963 : else
8964 0 : gcc_unreachable ();
8965 :
8966 267 : error ("%qE not specified in enclosing %qs",
8967 267 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)), rtype);
8968 267 : inform (ctx->location, "enclosing %qs", rtype);
8969 : }
8970 : /* FALLTHRU */
8971 44092 : case OMP_CLAUSE_DEFAULT_SHARED:
8972 44092 : flags |= GOVD_SHARED;
8973 44092 : break;
8974 155 : case OMP_CLAUSE_DEFAULT_PRIVATE:
8975 155 : flags |= GOVD_PRIVATE;
8976 155 : break;
8977 274 : case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
8978 274 : flags |= GOVD_FIRSTPRIVATE;
8979 274 : break;
8980 3178 : case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
8981 : /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */
8982 3178 : gcc_assert ((ctx->region_type & ORT_TASK) != 0);
8983 3178 : if (struct gimplify_omp_ctx *octx = ctx->outer_context)
8984 : {
8985 2140 : omp_notice_variable (octx, decl, in_code);
8986 2970 : for (; octx; octx = octx->outer_context)
8987 : {
8988 2914 : splay_tree_node n2;
8989 :
8990 2914 : n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
8991 2914 : if ((octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)) != 0
8992 5 : && (n2 == NULL || (n2->value & GOVD_DATA_SHARE_CLASS) == 0))
8993 5 : continue;
8994 2909 : if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
8995 : {
8996 898 : flags |= GOVD_FIRSTPRIVATE;
8997 898 : goto found_outer;
8998 : }
8999 2011 : if ((octx->region_type & (ORT_PARALLEL | ORT_TEAMS)) != 0)
9000 : {
9001 1186 : flags |= GOVD_SHARED;
9002 1186 : goto found_outer;
9003 : }
9004 : }
9005 : }
9006 :
9007 1094 : if (TREE_CODE (decl) == PARM_DECL
9008 1094 : || (!is_global_var (decl)
9009 288 : && DECL_CONTEXT (decl) == current_function_decl))
9010 714 : flags |= GOVD_FIRSTPRIVATE;
9011 : else
9012 380 : flags |= GOVD_SHARED;
9013 47699 : found_outer:
9014 : break;
9015 :
9016 0 : default:
9017 0 : gcc_unreachable ();
9018 : }
9019 :
9020 47699 : return flags;
9021 : }
9022 :
9023 : /* Return string name for types of OpenACC constructs from ORT_* values. */
9024 :
9025 : static const char *
9026 570 : oacc_region_type_name (enum omp_region_type region_type)
9027 : {
9028 570 : switch (region_type)
9029 : {
9030 : case ORT_ACC_DATA:
9031 : return "data";
9032 140 : case ORT_ACC_PARALLEL:
9033 140 : return "parallel";
9034 140 : case ORT_ACC_KERNELS:
9035 140 : return "kernels";
9036 140 : case ORT_ACC_SERIAL:
9037 140 : return "serial";
9038 0 : default:
9039 0 : gcc_unreachable ();
9040 : }
9041 : }
9042 :
9043 : /* Determine outer default flags for DECL mentioned in an OACC region
9044 : but not declared in an enclosing clause. */
9045 :
9046 : static unsigned
9047 8839 : oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
9048 : {
9049 8839 : struct gimplify_omp_ctx *ctx_default = ctx;
9050 : /* If no 'default' clause appears on this compute construct... */
9051 8839 : if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED)
9052 : {
9053 : /* ..., see if one appears on a lexically containing 'data'
9054 : construct. */
9055 9618 : while ((ctx_default = ctx_default->outer_context))
9056 : {
9057 1534 : if (ctx_default->region_type == ORT_ACC_DATA
9058 1534 : && ctx_default->default_kind != OMP_CLAUSE_DEFAULT_SHARED)
9059 : break;
9060 : }
9061 : /* If not, reset. */
9062 8260 : if (!ctx_default)
9063 8663 : ctx_default = ctx;
9064 : }
9065 :
9066 8839 : bool on_device = false;
9067 8839 : bool is_private = false;
9068 8839 : bool declared = is_oacc_declared (decl);
9069 8839 : tree type = TREE_TYPE (decl);
9070 :
9071 8839 : if (omp_privatize_by_reference (decl))
9072 338 : type = TREE_TYPE (type);
9073 :
9074 : /* For Fortran COMMON blocks, only used variables in those blocks are
9075 : transferred and remapped. The block itself will have a private clause to
9076 : avoid transferring the data twice.
9077 : The hook evaluates to false by default. For a variable in Fortran's COMMON
9078 : or EQUIVALENCE block, returns 'true' (as we have shared=false) - as only
9079 : the variables in such a COMMON/EQUIVALENCE block shall be privatized not
9080 : the whole block. For C++ and Fortran, it can also be true under certain
9081 : other conditions, if DECL_HAS_VALUE_EXPR. */
9082 8839 : if (RECORD_OR_UNION_TYPE_P (type))
9083 983 : is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false);
9084 :
9085 8839 : if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0
9086 8839 : && is_global_var (decl)
9087 642 : && device_resident_p (decl)
9088 8839 : && !is_private)
9089 : {
9090 0 : on_device = true;
9091 0 : flags |= GOVD_MAP_TO_ONLY;
9092 : }
9093 :
9094 8839 : switch (ctx->region_type)
9095 : {
9096 1460 : case ORT_ACC_KERNELS:
9097 1460 : if (is_private)
9098 0 : flags |= GOVD_FIRSTPRIVATE;
9099 1460 : else if (AGGREGATE_TYPE_P (type))
9100 : {
9101 : /* Aggregates default to 'present_or_copy', or 'present'. */
9102 415 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9103 397 : flags |= GOVD_MAP;
9104 : else
9105 18 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9106 : }
9107 : else
9108 : /* Scalars default to 'copy'. */
9109 1045 : flags |= GOVD_MAP | GOVD_MAP_FORCE;
9110 :
9111 : break;
9112 :
9113 7379 : case ORT_ACC_PARALLEL:
9114 7379 : case ORT_ACC_SERIAL:
9115 7379 : if (is_private)
9116 0 : flags |= GOVD_FIRSTPRIVATE;
9117 7379 : else if (on_device || declared)
9118 17 : flags |= GOVD_MAP;
9119 7362 : else if (AGGREGATE_TYPE_P (type))
9120 : {
9121 : /* Aggregates default to 'present_or_copy', or 'present'. */
9122 3697 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9123 3431 : flags |= GOVD_MAP;
9124 : else
9125 266 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9126 : }
9127 : else
9128 : /* Scalars default to 'firstprivate'. */
9129 3665 : flags |= GOVD_FIRSTPRIVATE;
9130 :
9131 : break;
9132 :
9133 0 : default:
9134 0 : gcc_unreachable ();
9135 : }
9136 :
9137 8839 : if (DECL_ARTIFICIAL (decl))
9138 : ; /* We can get compiler-generated decls, and should not complain
9139 : about them. */
9140 8528 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_NONE)
9141 : {
9142 420 : error ("%qE not specified in enclosing OpenACC %qs construct",
9143 210 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)),
9144 : oacc_region_type_name (ctx->region_type));
9145 210 : if (ctx_default != ctx)
9146 150 : inform (ctx->location, "enclosing OpenACC %qs construct and",
9147 : oacc_region_type_name (ctx->region_type));
9148 210 : inform (ctx_default->location,
9149 : "enclosing OpenACC %qs construct with %qs clause",
9150 : oacc_region_type_name (ctx_default->region_type),
9151 : "default(none)");
9152 : }
9153 8318 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_PRESENT)
9154 : ; /* Handled above. */
9155 : else
9156 7785 : gcc_checking_assert (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED);
9157 :
9158 8839 : return flags;
9159 : }
9160 :
9161 : /* Record the fact that DECL was used within the OMP context CTX.
9162 : IN_CODE is true when real code uses DECL, and false when we should
9163 : merely emit default(none) errors. Return true if DECL is going to
9164 : be remapped and thus DECL shouldn't be gimplified into its
9165 : DECL_VALUE_EXPR (if any). */
9166 :
9167 : static bool
9168 3902274 : omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
9169 : {
9170 3902274 : splay_tree_node n;
9171 3902274 : unsigned flags = in_code ? GOVD_SEEN : 0;
9172 3902274 : bool ret = false, shared;
9173 :
9174 3902274 : if (error_operand_p (decl))
9175 : return false;
9176 :
9177 3902274 : if (DECL_ARTIFICIAL (decl))
9178 : {
9179 2228638 : tree attr = lookup_attribute ("omp allocate var", DECL_ATTRIBUTES (decl));
9180 2228638 : if (attr)
9181 531 : decl = TREE_VALUE (TREE_VALUE (attr));
9182 : }
9183 :
9184 3902274 : if (ctx->region_type == ORT_NONE)
9185 248 : return lang_hooks.decls.omp_disregard_value_expr (decl, false);
9186 :
9187 3902026 : if (is_global_var (decl))
9188 : {
9189 : /* Threadprivate variables are predetermined. */
9190 501876 : if (DECL_THREAD_LOCAL_P (decl))
9191 13565 : return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
9192 :
9193 488311 : if (DECL_HAS_VALUE_EXPR_P (decl))
9194 : {
9195 4380 : if (ctx->region_type & ORT_ACC)
9196 : /* For OpenACC, defer expansion of value to avoid transferring
9197 : privatized common block data instead of im-/explicitly
9198 : transferred variables which are in common blocks. */
9199 : ;
9200 : else
9201 : {
9202 2104 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
9203 :
9204 2104 : if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
9205 618 : return omp_notice_threadprivate_variable (ctx, decl, value);
9206 : }
9207 : }
9208 :
9209 487693 : if (gimplify_omp_ctxp->outer_context == NULL
9210 113784 : && VAR_P (decl)
9211 601477 : && oacc_get_fn_attrib (current_function_decl))
9212 : {
9213 765 : location_t loc = DECL_SOURCE_LOCATION (decl);
9214 :
9215 765 : if (lookup_attribute ("omp declare target link",
9216 765 : DECL_ATTRIBUTES (decl)))
9217 : {
9218 48 : error_at (loc,
9219 : "%qE with %<link%> clause used in %<routine%> function",
9220 24 : DECL_NAME (decl));
9221 24 : return false;
9222 : }
9223 741 : else if (!lookup_attribute ("omp declare target",
9224 741 : DECL_ATTRIBUTES (decl)))
9225 : {
9226 132 : error_at (loc,
9227 : "%qE requires a %<declare%> directive for use "
9228 66 : "in a %<routine%> function", DECL_NAME (decl));
9229 66 : return false;
9230 : }
9231 : }
9232 : }
9233 :
9234 3887753 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9235 3887753 : if ((ctx->region_type & ORT_TARGET) != 0)
9236 : {
9237 851280 : if (n == NULL)
9238 : {
9239 45048 : unsigned nflags = flags;
9240 45048 : if ((ctx->region_type & ORT_ACC) == 0)
9241 : {
9242 34094 : bool is_declare_target = false;
9243 34094 : if (is_global_var (decl)
9244 34094 : && varpool_node::get_create (decl)->offloadable)
9245 : {
9246 7002 : struct gimplify_omp_ctx *octx;
9247 7002 : for (octx = ctx->outer_context;
9248 7010 : octx; octx = octx->outer_context)
9249 : {
9250 9 : n = splay_tree_lookup (octx->variables,
9251 : (splay_tree_key)decl);
9252 9 : if (n
9253 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED
9254 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
9255 : break;
9256 : }
9257 7002 : is_declare_target = octx == NULL;
9258 : }
9259 7002 : if (!is_declare_target)
9260 : {
9261 27093 : int gdmk;
9262 27093 : enum omp_clause_defaultmap_kind kind;
9263 27093 : if (lang_hooks.decls.omp_allocatable_p (decl))
9264 : gdmk = GDMK_ALLOCATABLE;
9265 26744 : else if (lang_hooks.decls.omp_scalar_target_p (decl))
9266 : gdmk = GDMK_SCALAR_TARGET;
9267 26669 : else if (lang_hooks.decls.omp_scalar_p (decl, false))
9268 : gdmk = GDMK_SCALAR;
9269 11164 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
9270 11164 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
9271 3102 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
9272 : == POINTER_TYPE)))
9273 : gdmk = GDMK_POINTER;
9274 : else
9275 : gdmk = GDMK_AGGREGATE;
9276 27093 : kind = lang_hooks.decls.omp_predetermined_mapping (decl);
9277 27093 : if (kind != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
9278 : {
9279 1096 : if (kind == OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE)
9280 101 : nflags |= GOVD_FIRSTPRIVATE;
9281 995 : else if (kind == OMP_CLAUSE_DEFAULTMAP_TO)
9282 995 : nflags |= GOVD_MAP | GOVD_MAP_TO_ONLY;
9283 : else
9284 0 : gcc_unreachable ();
9285 : }
9286 25997 : else if (ctx->defaultmap[gdmk] == 0)
9287 : {
9288 75 : tree d = lang_hooks.decls.omp_report_decl (decl);
9289 75 : error ("%qE not specified in enclosing %<target%>",
9290 75 : DECL_NAME (d));
9291 75 : inform (ctx->location, "enclosing %<target%>");
9292 : }
9293 25922 : else if (ctx->defaultmap[gdmk]
9294 25922 : & (GOVD_MAP_0LEN_ARRAY | GOVD_FIRSTPRIVATE))
9295 9118 : nflags |= ctx->defaultmap[gdmk];
9296 16804 : else if (ctx->defaultmap[gdmk] & GOVD_MAP_FORCE_PRESENT)
9297 : {
9298 42 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9299 42 : nflags |= ctx->defaultmap[gdmk] | GOVD_MAP_ALLOC_ONLY;
9300 : }
9301 : else
9302 : {
9303 16762 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9304 16762 : nflags |= ctx->defaultmap[gdmk] & ~GOVD_MAP;
9305 : }
9306 : }
9307 : }
9308 :
9309 45048 : struct gimplify_omp_ctx *octx = ctx->outer_context;
9310 45048 : if ((ctx->region_type & ORT_ACC) && octx)
9311 : {
9312 : /* Look in outer OpenACC contexts, to see if there's a
9313 : data attribute for this variable. */
9314 3535 : omp_notice_variable (octx, decl, in_code);
9315 :
9316 5307 : for (; octx; octx = octx->outer_context)
9317 : {
9318 3883 : if (!(octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)))
9319 : break;
9320 3883 : splay_tree_node n2
9321 3883 : = splay_tree_lookup (octx->variables,
9322 : (splay_tree_key) decl);
9323 3883 : if (n2)
9324 : {
9325 2111 : if (octx->region_type == ORT_ACC_HOST_DATA)
9326 4 : error ("variable %qE declared in enclosing "
9327 4 : "%<host_data%> region", DECL_NAME (decl));
9328 2111 : nflags |= GOVD_MAP;
9329 2111 : if (octx->region_type == ORT_ACC_DATA
9330 2107 : && (n2->value & GOVD_MAP_0LEN_ARRAY))
9331 288 : nflags |= GOVD_MAP_0LEN_ARRAY;
9332 2111 : goto found_outer;
9333 : }
9334 : }
9335 : }
9336 :
9337 42937 : if ((nflags & ~(GOVD_MAP_TO_ONLY | GOVD_MAP_FROM_ONLY
9338 : | GOVD_MAP_ALLOC_ONLY)) == flags)
9339 : {
9340 32681 : tree type = TREE_TYPE (decl);
9341 32681 : location_t loc = DECL_SOURCE_LOCATION (decl);
9342 :
9343 32681 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases
9344 32681 : && omp_privatize_by_reference (decl))
9345 28 : type = TREE_TYPE (type);
9346 :
9347 32681 : if (!verify_type_context (loc, TCTX_OMP_MAP_IMP_REF, type))
9348 : /* Check if TYPE can appear in a target region.
9349 : verify_type_context has already issued an error if it
9350 : can't. */
9351 0 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9352 32681 : else if (!omp_mappable_type (type))
9353 : {
9354 8 : error ("%qD referenced in target region does not have "
9355 : "a mappable type", decl);
9356 8 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9357 : }
9358 : else
9359 : {
9360 32673 : if ((ctx->region_type & ORT_ACC) != 0)
9361 8839 : nflags = oacc_default_clause (ctx, decl, flags);
9362 : else
9363 23834 : nflags |= GOVD_MAP;
9364 : }
9365 : }
9366 10256 : found_outer:
9367 45048 : omp_add_variable (ctx, decl, nflags);
9368 45048 : if (ctx->region_type & ORT_ACC)
9369 : /* For OpenACC, as remarked above, defer expansion. */
9370 : shared = false;
9371 : else
9372 34094 : shared = (nflags & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9373 45048 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9374 : }
9375 : else
9376 : {
9377 806232 : if (ctx->region_type & ORT_ACC)
9378 : /* For OpenACC, as remarked above, defer expansion. */
9379 : shared = false;
9380 : else
9381 509807 : shared = ((n->value | flags)
9382 509807 : & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9383 806232 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9384 : /* If nothing changed, there's nothing left to do. */
9385 806232 : if ((n->value & flags) == flags)
9386 : return ret;
9387 16561 : flags |= n->value;
9388 16561 : n->value = flags;
9389 : }
9390 61609 : goto do_outer;
9391 : }
9392 :
9393 3036473 : if (n == NULL)
9394 : {
9395 1179388 : if (ctx->region_type == ORT_WORKSHARE
9396 : || ctx->region_type == ORT_TASKGROUP
9397 560639 : || ctx->region_type == ORT_SIMD
9398 288605 : || ctx->region_type == ORT_ACC
9399 92352 : || (ctx->region_type & ORT_TARGET_DATA) != 0)
9400 1131689 : goto do_outer;
9401 :
9402 47699 : flags = omp_default_clause (ctx, decl, in_code, flags);
9403 :
9404 47699 : if ((flags & GOVD_PRIVATE)
9405 47699 : && lang_hooks.decls.omp_private_outer_ref (decl))
9406 6 : flags |= GOVD_PRIVATE_OUTER_REF;
9407 :
9408 47699 : omp_add_variable (ctx, decl, flags);
9409 :
9410 47699 : shared = (flags & GOVD_SHARED) != 0;
9411 47699 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9412 47699 : goto do_outer;
9413 : }
9414 :
9415 : /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd
9416 : lb, b or incr expressions, those shouldn't be turned into simd arrays. */
9417 1857085 : if (ctx->region_type == ORT_SIMD
9418 151160 : && ctx->in_for_exprs
9419 70 : && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT))
9420 : == GOVD_PRIVATE))
9421 1857085 : flags &= ~GOVD_SEEN;
9422 :
9423 1857085 : if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
9424 31706 : && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
9425 1888752 : && DECL_SIZE (decl))
9426 : {
9427 31666 : tree size;
9428 31666 : if (!poly_int_tree_p (DECL_SIZE (decl)))
9429 : {
9430 148 : splay_tree_node n2;
9431 148 : tree t = DECL_VALUE_EXPR (decl);
9432 148 : gcc_assert (INDIRECT_REF_P (t));
9433 148 : t = TREE_OPERAND (t, 0);
9434 148 : gcc_assert (DECL_P (t));
9435 148 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
9436 148 : n2->value |= GOVD_SEEN;
9437 : }
9438 31518 : else if (omp_privatize_by_reference (decl)
9439 4145 : && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
9440 35626 : && !poly_int_tree_p (size))
9441 : {
9442 1325 : splay_tree_node n2;
9443 1325 : gcc_assert (DECL_P (size));
9444 1325 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size);
9445 1325 : if (n2)
9446 617 : omp_notice_variable (ctx, size, true);
9447 : }
9448 : }
9449 :
9450 1857085 : if (ctx->region_type & ORT_ACC)
9451 : /* For OpenACC, as remarked above, defer expansion. */
9452 : shared = false;
9453 : else
9454 1675150 : shared = ((flags | n->value) & GOVD_SHARED) != 0;
9455 1857085 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9456 :
9457 : /* If nothing changed, there's nothing left to do. */
9458 1857085 : if ((n->value & flags) == flags)
9459 : return ret;
9460 31667 : flags |= n->value;
9461 31667 : n->value = flags;
9462 :
9463 1272664 : do_outer:
9464 : /* If the variable is private in the current context, then we don't
9465 : need to propagate anything to an outer context. */
9466 1272664 : if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF))
9467 : return ret;
9468 1262330 : if ((flags & (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9469 : == (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9470 : return ret;
9471 1262270 : if ((flags & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
9472 : | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9473 : == (GOVD_LASTPRIVATE | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9474 : return ret;
9475 1262270 : if (ctx->outer_context
9476 1262270 : && omp_notice_variable (ctx->outer_context, decl, in_code))
9477 : return true;
9478 : return ret;
9479 : }
9480 :
9481 : /* Verify that DECL is private within CTX. If there's specific information
9482 : to the contrary in the innermost scope, generate an error. */
9483 :
9484 : static bool
9485 50088 : omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd)
9486 : {
9487 95749 : splay_tree_node n;
9488 :
9489 95749 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9490 95749 : if (n != NULL)
9491 : {
9492 17915 : if (n->value & GOVD_SHARED)
9493 : {
9494 407 : if (ctx == gimplify_omp_ctxp)
9495 : {
9496 0 : if (simd)
9497 0 : error ("iteration variable %qE is predetermined linear",
9498 0 : DECL_NAME (decl));
9499 : else
9500 0 : error ("iteration variable %qE should be private",
9501 0 : DECL_NAME (decl));
9502 0 : n->value = GOVD_PRIVATE;
9503 0 : return true;
9504 : }
9505 : else
9506 : return false;
9507 : }
9508 17508 : else if ((n->value & GOVD_EXPLICIT) != 0
9509 9666 : && (ctx == gimplify_omp_ctxp
9510 339 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9511 220 : && gimplify_omp_ctxp->outer_context == ctx)))
9512 : {
9513 9547 : if ((n->value & GOVD_FIRSTPRIVATE) != 0)
9514 4 : error ("iteration variable %qE should not be firstprivate",
9515 4 : DECL_NAME (decl));
9516 9543 : else if ((n->value & GOVD_REDUCTION) != 0)
9517 8 : error ("iteration variable %qE should not be reduction",
9518 8 : DECL_NAME (decl));
9519 9535 : else if (simd != 1 && (n->value & GOVD_LINEAR) != 0)
9520 58 : error ("iteration variable %qE should not be linear",
9521 58 : DECL_NAME (decl));
9522 : }
9523 17508 : return (ctx == gimplify_omp_ctxp
9524 17508 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9525 19390 : && gimplify_omp_ctxp->outer_context == ctx));
9526 : }
9527 :
9528 77834 : if (ctx->region_type != ORT_WORKSHARE
9529 : && ctx->region_type != ORT_TASKGROUP
9530 49387 : && ctx->region_type != ORT_SIMD
9531 36122 : && ctx->region_type != ORT_ACC)
9532 : return false;
9533 53885 : else if (ctx->outer_context)
9534 : return omp_is_private (ctx->outer_context, decl, simd);
9535 : return false;
9536 : }
9537 :
9538 : /* Return true if DECL is private within a parallel region
9539 : that binds to the current construct's context or in parallel
9540 : region's REDUCTION clause. */
9541 :
9542 : static bool
9543 11498 : omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
9544 : {
9545 11570 : splay_tree_node n;
9546 :
9547 11570 : do
9548 : {
9549 11570 : ctx = ctx->outer_context;
9550 11570 : if (ctx == NULL)
9551 : {
9552 2776 : if (is_global_var (decl))
9553 : return false;
9554 :
9555 : /* References might be private, but might be shared too,
9556 : when checking for copyprivate, assume they might be
9557 : private, otherwise assume they might be shared. */
9558 1290 : if (copyprivate)
9559 : return true;
9560 :
9561 1244 : if (omp_privatize_by_reference (decl))
9562 : return false;
9563 :
9564 : /* Treat C++ privatized non-static data members outside
9565 : of the privatization the same. */
9566 1198 : if (omp_member_access_dummy_var (decl))
9567 : return false;
9568 :
9569 : return true;
9570 : }
9571 :
9572 8794 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
9573 :
9574 8794 : if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
9575 1291 : && (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0))
9576 : {
9577 242 : if ((ctx->region_type & ORT_TARGET_DATA) != 0
9578 238 : || n == NULL
9579 230 : || (n->value & GOVD_MAP) == 0)
9580 12 : continue;
9581 : return false;
9582 : }
9583 :
9584 7503 : if (n != NULL)
9585 : {
9586 5299 : if ((n->value & GOVD_LOCAL) != 0
9587 5299 : && omp_member_access_dummy_var (decl))
9588 : return false;
9589 5260 : return (n->value & GOVD_SHARED) == 0;
9590 : }
9591 :
9592 3253 : if (ctx->region_type == ORT_WORKSHARE
9593 : || ctx->region_type == ORT_TASKGROUP
9594 3197 : || ctx->region_type == ORT_SIMD
9595 3193 : || ctx->region_type == ORT_ACC)
9596 60 : continue;
9597 :
9598 : break;
9599 : }
9600 : while (1);
9601 : return false;
9602 : }
9603 :
9604 : /* Callback for walk_tree to find a DECL_EXPR for the given DECL. */
9605 :
9606 : static tree
9607 3148 : find_decl_expr (tree *tp, int *walk_subtrees, void *data)
9608 : {
9609 3148 : tree t = *tp;
9610 :
9611 : /* If this node has been visited, unmark it and keep looking. */
9612 3148 : if (TREE_CODE (t) == DECL_EXPR && DECL_EXPR_DECL (t) == (tree) data)
9613 : return t;
9614 :
9615 2724 : if (IS_TYPE_OR_DECL_P (t))
9616 452 : *walk_subtrees = 0;
9617 : return NULL_TREE;
9618 : }
9619 :
9620 :
9621 : /* Gimplify the affinity clause but effectively ignore it.
9622 : Generate:
9623 : var = begin;
9624 : if ((step > 1) ? var <= end : var > end)
9625 : locatator_var_expr; */
9626 :
9627 : static void
9628 374 : gimplify_omp_affinity (tree *list_p, gimple_seq *pre_p)
9629 : {
9630 374 : tree last_iter = NULL_TREE;
9631 374 : tree last_bind = NULL_TREE;
9632 374 : tree label = NULL_TREE;
9633 374 : tree *last_body = NULL;
9634 1011 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9635 637 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
9636 : {
9637 637 : tree t = OMP_CLAUSE_DECL (c);
9638 637 : if (OMP_ITERATOR_DECL_P (t))
9639 : {
9640 389 : if (TREE_VALUE (t) == null_pointer_node)
9641 201 : continue;
9642 188 : if (TREE_PURPOSE (t) != last_iter)
9643 : {
9644 127 : if (last_bind)
9645 : {
9646 9 : append_to_statement_list (label, last_body);
9647 9 : gimplify_and_add (last_bind, pre_p);
9648 9 : last_bind = NULL_TREE;
9649 : }
9650 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9651 : {
9652 147 : if (gimplify_expr (&OMP_ITERATOR_BEGIN (it), pre_p, NULL,
9653 : is_gimple_val, fb_rvalue) == GS_ERROR
9654 147 : || gimplify_expr (&OMP_ITERATOR_END (it), pre_p, NULL,
9655 : is_gimple_val, fb_rvalue) == GS_ERROR
9656 147 : || gimplify_expr (&OMP_ITERATOR_STEP (it), pre_p, NULL,
9657 : is_gimple_val, fb_rvalue) == GS_ERROR
9658 294 : || (gimplify_expr (&OMP_ITERATOR_ORIG_STEP (it), pre_p,
9659 : NULL, is_gimple_val, fb_rvalue)
9660 : == GS_ERROR))
9661 0 : return;
9662 : }
9663 127 : last_iter = TREE_PURPOSE (t);
9664 127 : tree block = OMP_ITERATOR_BLOCK (TREE_PURPOSE (t));
9665 127 : last_bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
9666 : NULL, block);
9667 127 : last_body = &BIND_EXPR_BODY (last_bind);
9668 127 : tree cond = NULL_TREE;
9669 127 : location_t loc = OMP_CLAUSE_LOCATION (c);
9670 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9671 : {
9672 147 : tree var = OMP_ITERATOR_VAR (it);
9673 147 : tree begin = OMP_ITERATOR_BEGIN (it);
9674 147 : tree end = OMP_ITERATOR_END (it);
9675 147 : tree step = OMP_ITERATOR_STEP (it);
9676 147 : loc = DECL_SOURCE_LOCATION (var);
9677 147 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
9678 : var, begin);
9679 147 : append_to_statement_list_force (tem, last_body);
9680 :
9681 147 : tree cond1 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9682 147 : step, build_zero_cst (TREE_TYPE (step)));
9683 147 : tree cond2 = fold_build2_loc (loc, LE_EXPR, boolean_type_node,
9684 : var, end);
9685 147 : tree cond3 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9686 : var, end);
9687 147 : cond1 = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
9688 : cond1, cond2, cond3);
9689 147 : if (cond)
9690 20 : cond = fold_build2_loc (loc, TRUTH_AND_EXPR,
9691 : boolean_type_node, cond, cond1);
9692 : else
9693 : cond = cond1;
9694 : }
9695 127 : tree cont_label = create_artificial_label (loc);
9696 127 : label = build1 (LABEL_EXPR, void_type_node, cont_label);
9697 127 : tree tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9698 : void_node,
9699 : build_and_jump (&cont_label));
9700 127 : append_to_statement_list_force (tem, last_body);
9701 : }
9702 188 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
9703 : {
9704 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t), 0),
9705 : last_body);
9706 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
9707 : }
9708 188 : if (error_operand_p (TREE_VALUE (t)))
9709 : return;
9710 188 : append_to_statement_list_force (TREE_VALUE (t), last_body);
9711 188 : TREE_VALUE (t) = null_pointer_node;
9712 : }
9713 : else
9714 : {
9715 248 : if (last_bind)
9716 : {
9717 9 : append_to_statement_list (label, last_body);
9718 9 : gimplify_and_add (last_bind, pre_p);
9719 9 : last_bind = NULL_TREE;
9720 : }
9721 248 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
9722 : {
9723 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
9724 : NULL, is_gimple_val, fb_rvalue);
9725 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
9726 : }
9727 248 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
9728 : return;
9729 248 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
9730 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
9731 : return;
9732 248 : gimplify_and_add (OMP_CLAUSE_DECL (c), pre_p);
9733 : }
9734 : }
9735 374 : if (last_bind)
9736 : {
9737 109 : append_to_statement_list (label, last_body);
9738 109 : gimplify_and_add (last_bind, pre_p);
9739 : }
9740 : return;
9741 : }
9742 :
9743 : /* Returns a tree expression containing the total iteration count of the
9744 : OpenMP iterator IT. */
9745 :
9746 : static tree
9747 379 : compute_omp_iterator_count (tree it, gimple_seq *pre_p)
9748 : {
9749 379 : tree tcnt = size_one_node;
9750 837 : for (; it; it = TREE_CHAIN (it))
9751 : {
9752 458 : if (gimplify_expr (&OMP_ITERATOR_BEGIN (it), pre_p, NULL,
9753 : is_gimple_val, fb_rvalue) == GS_ERROR
9754 458 : || gimplify_expr (&OMP_ITERATOR_END (it), pre_p, NULL,
9755 : is_gimple_val, fb_rvalue) == GS_ERROR
9756 458 : || gimplify_expr (&OMP_ITERATOR_STEP (it), pre_p, NULL,
9757 : is_gimple_val, fb_rvalue) == GS_ERROR
9758 916 : || (gimplify_expr (&OMP_ITERATOR_ORIG_STEP (it), pre_p, NULL,
9759 : is_gimple_val, fb_rvalue) == GS_ERROR))
9760 0 : return NULL_TREE;
9761 458 : tree var = OMP_ITERATOR_VAR (it);
9762 458 : tree begin = OMP_ITERATOR_BEGIN (it);
9763 458 : tree end = OMP_ITERATOR_END (it);
9764 458 : tree step = OMP_ITERATOR_STEP (it);
9765 458 : tree orig_step = OMP_ITERATOR_ORIG_STEP (it);
9766 458 : tree type = TREE_TYPE (var);
9767 458 : tree stype = TREE_TYPE (step);
9768 458 : location_t loc = DECL_SOURCE_LOCATION (var);
9769 458 : tree endmbegin;
9770 : /* Compute count for this iterator as
9771 : orig_step > 0
9772 : ? (begin < end ? (end - begin + (step - 1)) / step : 0)
9773 : : (begin > end ? (end - begin + (step + 1)) / step : 0)
9774 : and compute product of those for the entire clause. */
9775 458 : if (POINTER_TYPE_P (type))
9776 42 : endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR, stype, end, begin);
9777 : else
9778 416 : endmbegin = fold_build2_loc (loc, MINUS_EXPR, type, end, begin);
9779 : /* Account for iteration stopping on the end value in Fortran rather
9780 : than before it. */
9781 458 : tree stepm1 = step;
9782 458 : tree stepp1 = step;
9783 458 : if (!lang_GNU_Fortran ())
9784 : {
9785 360 : stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype, step,
9786 : build_int_cst (stype, 1));
9787 360 : stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
9788 : build_int_cst (stype, 1));
9789 : }
9790 458 : tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
9791 : unshare_expr (endmbegin), stepm1);
9792 458 : pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, pos, step);
9793 458 : tree neg = fold_build2_loc (loc, PLUS_EXPR, stype, endmbegin, stepp1);
9794 458 : if (TYPE_UNSIGNED (stype))
9795 : {
9796 31 : neg = fold_build1_loc (loc, NEGATE_EXPR, stype, neg);
9797 31 : step = fold_build1_loc (loc, NEGATE_EXPR, stype, step);
9798 : }
9799 458 : neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, neg, step);
9800 458 : step = NULL_TREE;
9801 458 : tree_code cmp_op = lang_GNU_Fortran () ? LE_EXPR : LT_EXPR;
9802 458 : tree cond = fold_build2_loc (loc, cmp_op, boolean_type_node, begin, end);
9803 458 : pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
9804 : build_int_cst (stype, 0));
9805 458 : cond = fold_build2_loc (loc, cmp_op, boolean_type_node, end, begin);
9806 458 : neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
9807 : build_int_cst (stype, 0));
9808 458 : tree osteptype = TREE_TYPE (orig_step);
9809 458 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9810 : build_int_cst (osteptype, 0));
9811 458 : tree cnt = fold_build3_loc (loc, COND_EXPR, stype, cond, pos, neg);
9812 458 : cnt = fold_convert_loc (loc, sizetype, cnt);
9813 458 : if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
9814 : fb_rvalue) == GS_ERROR)
9815 : return NULL_TREE;
9816 458 : tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
9817 : }
9818 379 : if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
9819 : return NULL_TREE;
9820 :
9821 379 : return tcnt;
9822 : }
9823 :
9824 : /* Build loops iterating over the space defined by the OpenMP iterator IT.
9825 : Returns a pointer to the BIND_EXPR_BODY in the innermost loop body.
9826 : LAST_BIND is set to point to the BIND_EXPR containing the whole loop. */
9827 :
9828 : static tree *
9829 379 : build_omp_iterator_loop (tree it, gimple_seq *pre_p, tree *last_bind)
9830 : {
9831 379 : if (*last_bind)
9832 31 : gimplify_and_add (*last_bind, pre_p);
9833 379 : tree block = OMP_ITERATOR_BLOCK (it);
9834 464 : tree block_stmts = lang_GNU_Fortran () ? BLOCK_SUBBLOCKS (block) : NULL_TREE;
9835 379 : *last_bind = build3 (BIND_EXPR, void_type_node,
9836 379 : BLOCK_VARS (block), NULL, block);
9837 379 : TREE_SIDE_EFFECTS (*last_bind) = 1;
9838 379 : tree *p = &BIND_EXPR_BODY (*last_bind);
9839 837 : for (; it; it = TREE_CHAIN (it))
9840 : {
9841 458 : tree var = OMP_ITERATOR_VAR (it);
9842 458 : tree begin = OMP_ITERATOR_BEGIN (it);
9843 458 : tree end = OMP_ITERATOR_END (it);
9844 458 : tree step = OMP_ITERATOR_STEP (it);
9845 458 : tree orig_step = OMP_ITERATOR_ORIG_STEP (it);
9846 458 : block = OMP_ITERATOR_BLOCK (it);
9847 458 : tree type = TREE_TYPE (var);
9848 458 : location_t loc = DECL_SOURCE_LOCATION (var);
9849 : /* Emit:
9850 : var = begin;
9851 : goto cond_label;
9852 : beg_label:
9853 : ...
9854 : var = var + step;
9855 : cond_label:
9856 : if (orig_step > 0) {
9857 : if (var < end) goto beg_label; // <= for Fortran
9858 : } else {
9859 : if (var > end) goto beg_label; // >= for Fortran
9860 : }
9861 : for each iterator, with inner iterators added to
9862 : the ... above. */
9863 458 : tree beg_label = create_artificial_label (loc);
9864 458 : tree cond_label = NULL_TREE;
9865 458 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, begin);
9866 458 : append_to_statement_list_force (tem, p);
9867 458 : tem = build_and_jump (&cond_label);
9868 458 : append_to_statement_list_force (tem, p);
9869 458 : tem = build1 (LABEL_EXPR, void_type_node, beg_label);
9870 458 : append_to_statement_list (tem, p);
9871 458 : tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
9872 : NULL_TREE, NULL_TREE);
9873 458 : TREE_SIDE_EFFECTS (bind) = 1;
9874 458 : SET_EXPR_LOCATION (bind, loc);
9875 458 : append_to_statement_list_force (bind, p);
9876 458 : if (POINTER_TYPE_P (type))
9877 42 : tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
9878 : var, fold_convert_loc (loc, sizetype, step));
9879 : else
9880 416 : tem = build2_loc (loc, PLUS_EXPR, type, var, step);
9881 458 : tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, tem);
9882 458 : append_to_statement_list_force (tem, p);
9883 458 : tem = build1 (LABEL_EXPR, void_type_node, cond_label);
9884 458 : append_to_statement_list (tem, p);
9885 818 : tree cond = fold_build2_loc (loc, lang_GNU_Fortran () ? LE_EXPR : LT_EXPR,
9886 : boolean_type_node, var, end);
9887 458 : tree pos = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9888 : build_and_jump (&beg_label), void_node);
9889 818 : cond = fold_build2_loc (loc, lang_GNU_Fortran () ? GE_EXPR : GT_EXPR,
9890 : boolean_type_node, var, end);
9891 458 : tree neg = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9892 : build_and_jump (&beg_label), void_node);
9893 458 : tree osteptype = TREE_TYPE (orig_step);
9894 458 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9895 : build_int_cst (osteptype, 0));
9896 458 : tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, pos, neg);
9897 458 : append_to_statement_list_force (tem, p);
9898 458 : p = &BIND_EXPR_BODY (bind);
9899 : /* The Fortran front-end stashes statements into the BLOCK_SUBBLOCKS
9900 : of the last element of the first iterator. These should go into the
9901 : body of the innermost loop. */
9902 458 : if (!TREE_CHAIN (it))
9903 379 : append_to_statement_list_force (block_stmts, p);
9904 : }
9905 :
9906 379 : return p;
9907 : }
9908 :
9909 :
9910 : /* Callback for walk_tree to find a VAR_DECL (stored in DATA) in the
9911 : tree TP. */
9912 :
9913 : static tree
9914 3813 : find_var_decl (tree *tp, int *, void *data)
9915 : {
9916 3813 : if (*tp == (tree) data)
9917 357 : return *tp;
9918 :
9919 : return NULL_TREE;
9920 : }
9921 :
9922 : /* Returns an element-by-element copy of OMP iterator tree IT. If
9923 : EXPAND is true, force the result to be an expanded iterator; otherwise
9924 : it makes the copy the same size as IT. */
9925 : static tree
9926 337 : copy_omp_iterator (tree it, bool expand = false)
9927 : {
9928 337 : int elem_count = TREE_VEC_LENGTH (it);
9929 337 : tree new_it =
9930 337 : (expand ? make_expanded_omp_iterator () : make_tree_vec (elem_count));
9931 2359 : for (int i = 0; i < TREE_VEC_LENGTH (it); i++)
9932 2022 : TREE_VEC_ELT (new_it, i) = TREE_VEC_ELT (it, i);
9933 337 : return new_it;
9934 : }
9935 :
9936 : /* Helper function for walk_tree in remap_omp_iterator_var. */
9937 :
9938 : static tree
9939 1063 : remap_omp_iterator_var_1 (tree *tp, int *, void *data)
9940 : {
9941 1063 : tree old_var = ((tree *) data)[0];
9942 1063 : tree new_var = ((tree *) data)[1];
9943 :
9944 1063 : if (*tp == old_var)
9945 106 : *tp = new_var;
9946 1063 : return NULL_TREE;
9947 : }
9948 :
9949 : /* Replace instances of OLD_VAR in TP with NEW_VAR. */
9950 :
9951 : static void
9952 212 : remap_omp_iterator_var (tree *tp, tree old_var, tree new_var)
9953 : {
9954 212 : tree vars[2] = { old_var, new_var };
9955 212 : walk_tree (tp, remap_omp_iterator_var_1, vars, NULL);
9956 212 : }
9957 :
9958 : /* Scan through all clauses using OpenMP iterators in LIST_P. If any
9959 : clauses have iterators with variables that are not used by the clause
9960 : decl or size, issue a warning and replace the iterator with a copy with
9961 : the unused variables removed. */
9962 :
9963 : static void
9964 27646 : remove_unused_omp_iterator_vars (tree *list_p)
9965 : {
9966 27646 : auto_vec< vec<tree> > iter_vars;
9967 27646 : auto_vec<tree> new_iterators;
9968 :
9969 80622 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9970 : {
9971 52976 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
9972 52912 : continue;
9973 276 : auto_vec<tree> vars;
9974 276 : bool need_new_iterators = false;
9975 710 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
9976 : {
9977 434 : tree var = OMP_ITERATOR_VAR (it);
9978 434 : tree t = walk_tree (&OMP_CLAUSE_DECL (c), find_var_decl, var, NULL);
9979 434 : if (t == NULL_TREE)
9980 143 : t = walk_tree (&OMP_CLAUSE_SIZE (c), find_var_decl, var, NULL);
9981 143 : if (t == NULL_TREE)
9982 : need_new_iterators = true;
9983 : else
9984 357 : vars.safe_push (var);
9985 : }
9986 276 : if (!need_new_iterators)
9987 199 : continue;
9988 77 : if (vars.is_empty ())
9989 : {
9990 : /* No iteration variables are used in the clause - remove the
9991 : iterator from the clause. */
9992 13 : OMP_CLAUSE_ITERATORS (c) = NULL_TREE;
9993 13 : continue;
9994 : }
9995 :
9996 : /* If a new iterator has been created for the current set of used
9997 : iterator variables, then use that as the iterator. Otherwise,
9998 : create a new iterator for the current iterator variable set. */
9999 : unsigned i;
10000 106 : for (i = 0; i < iter_vars.length (); i++)
10001 : {
10002 124 : if (vars.length () != iter_vars[i].length ())
10003 0 : continue;
10004 : bool identical_p = true;
10005 150 : for (unsigned j = 0; j < vars.length () && identical_p; j++)
10006 88 : identical_p = vars[j] == iter_vars[i][j];
10007 :
10008 62 : if (identical_p)
10009 : break;
10010 : }
10011 64 : if (i < iter_vars.length ())
10012 20 : OMP_CLAUSE_ITERATORS (c) = new_iterators[i];
10013 : else
10014 : {
10015 44 : tree new_iters = NULL_TREE;
10016 44 : tree *new_iters_p = &new_iters;
10017 44 : tree new_vars = NULL_TREE;
10018 44 : tree *new_vars_p = &new_vars;
10019 44 : i = 0;
10020 140 : for (tree it = OMP_CLAUSE_ITERATORS (c); it && i < vars.length();
10021 96 : it = TREE_CHAIN (it))
10022 : {
10023 96 : tree var = OMP_ITERATOR_VAR (it);
10024 96 : if (var == vars[i])
10025 : {
10026 74 : *new_iters_p = copy_omp_iterator (it);
10027 74 : *new_vars_p = build_decl (OMP_CLAUSE_LOCATION (c), VAR_DECL,
10028 74 : DECL_NAME (var), TREE_TYPE (var));
10029 74 : DECL_ARTIFICIAL (*new_vars_p) = 1;
10030 74 : DECL_CONTEXT (*new_vars_p) = DECL_CONTEXT (var);
10031 74 : OMP_ITERATOR_VAR (*new_iters_p) = *new_vars_p;
10032 74 : new_iters_p = &TREE_CHAIN (*new_iters_p);
10033 74 : new_vars_p = &DECL_CHAIN (*new_vars_p);
10034 74 : i++;
10035 : }
10036 : }
10037 44 : tree old_block = OMP_ITERATOR_BLOCK (OMP_CLAUSE_ITERATORS (c));
10038 44 : tree new_block = make_node (BLOCK);
10039 44 : BLOCK_VARS (new_block) = new_vars;
10040 44 : if (BLOCK_SUBBLOCKS (old_block))
10041 : {
10042 4 : BLOCK_SUBBLOCKS (new_block) = BLOCK_SUBBLOCKS (old_block);
10043 4 : BLOCK_SUBBLOCKS (old_block) = NULL_TREE;
10044 : }
10045 44 : OMP_ITERATOR_BLOCK (new_iters) = new_block;
10046 44 : new_iterators.safe_push (new_iters);
10047 44 : iter_vars.safe_push (vars.copy ());
10048 44 : OMP_CLAUSE_ITERATORS (c) = new_iters;
10049 : }
10050 :
10051 : /* Remap clause to use the new variables. */
10052 64 : i = 0;
10053 170 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
10054 : {
10055 106 : tree old_var = vars[i++];
10056 106 : tree new_var = OMP_ITERATOR_VAR (it);
10057 106 : remap_omp_iterator_var (&OMP_CLAUSE_DECL (c), old_var, new_var);
10058 106 : remap_omp_iterator_var (&OMP_CLAUSE_SIZE (c), old_var, new_var);
10059 : }
10060 276 : }
10061 :
10062 27690 : for (unsigned i = 0; i < iter_vars.length (); i++)
10063 44 : iter_vars[i].release ();
10064 27646 : }
10065 :
10066 248 : struct iterator_loop_info_t
10067 : {
10068 : tree bind;
10069 : tree count;
10070 : tree index;
10071 : tree body_label;
10072 : auto_vec<tree> clauses;
10073 : };
10074 :
10075 : typedef hash_map<tree, iterator_loop_info_t> iterator_loop_info_map_t;
10076 :
10077 : /* Builds a loop to expand any OpenMP iterators in the clauses in LIST_P,
10078 : reusing any previously built loops if they use the same set of iterators.
10079 : Generated Gimple statements are placed into LOOPS_SEQ_P. The clause
10080 : iterators are updated with information on how and where to insert code into
10081 : the loop body. */
10082 :
10083 : static void
10084 27646 : build_omp_iterators_loops (tree *list_p, gimple_seq *loops_seq_p)
10085 : {
10086 27646 : iterator_loop_info_map_t loops;
10087 :
10088 80622 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10089 : {
10090 52976 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10091 52713 : continue;
10092 :
10093 263 : bool built_p;
10094 263 : iterator_loop_info_t &loop
10095 263 : = loops.get_or_insert (OMP_CLAUSE_ITERATORS (c), &built_p);
10096 :
10097 263 : if (!built_p)
10098 : {
10099 124 : loop.count = compute_omp_iterator_count (OMP_CLAUSE_ITERATORS (c),
10100 : loops_seq_p);
10101 124 : if (!loop.count)
10102 0 : continue;
10103 124 : if (integer_zerop (loop.count))
10104 8 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
10105 : "iteration count is zero");
10106 :
10107 124 : loop.bind = NULL_TREE;
10108 124 : tree *body = build_omp_iterator_loop (OMP_CLAUSE_ITERATORS (c),
10109 : loops_seq_p, &loop.bind);
10110 :
10111 124 : loop.index = create_tmp_var (sizetype);
10112 124 : SET_EXPR_LOCATION (loop.bind, OMP_CLAUSE_LOCATION (c));
10113 :
10114 : /* BEFORE LOOP: */
10115 : /* idx = -1; */
10116 : /* This should be initialized to before the individual elements,
10117 : as idx is pre-incremented in the loop body. */
10118 124 : gimple *assign = gimple_build_assign (loop.index, size_int (-1));
10119 124 : gimple_seq_add_stmt (loops_seq_p, assign);
10120 :
10121 : /* IN LOOP BODY: */
10122 : /* Create a label so we can find this point later. */
10123 124 : loop.body_label = create_artificial_label (OMP_CLAUSE_LOCATION (c));
10124 124 : tree tem = build1 (LABEL_EXPR, void_type_node, loop.body_label);
10125 124 : append_to_statement_list_force (tem, body);
10126 :
10127 : /* idx += 2; */
10128 124 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10129 : void_type_node, loop.index,
10130 : size_binop (PLUS_EXPR, loop.index, size_int (2)));
10131 124 : append_to_statement_list_force (tem, body);
10132 : }
10133 :
10134 : /* Create array to hold expanded values. */
10135 263 : tree last_count_2 = size_binop (MULT_EXPR, loop.count, size_int (2));
10136 263 : tree arr_length = size_binop (PLUS_EXPR, last_count_2, size_int (1));
10137 263 : tree elems = NULL_TREE;
10138 263 : if (TREE_CONSTANT (arr_length))
10139 : {
10140 263 : tree type = build_array_type (ptr_type_node,
10141 : build_index_type (arr_length));
10142 263 : elems = create_tmp_var_raw (type, "omp_iter_data");
10143 263 : TREE_ADDRESSABLE (elems) = 1;
10144 263 : gimple_add_tmp_var (elems);
10145 : }
10146 : else
10147 : {
10148 : /* Handle dynamic sizes. */
10149 0 : sorry ("dynamic iterator sizes not implemented yet");
10150 : }
10151 :
10152 : /* BEFORE LOOP: */
10153 : /* elems[0] = count; */
10154 263 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, size_int (0),
10155 : NULL_TREE, NULL_TREE);
10156 263 : tree tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10157 : void_type_node, lhs, loop.count);
10158 263 : gimplify_and_add (tem, loops_seq_p);
10159 :
10160 : /* Make a copy of the iterator with extra info at the end. */
10161 263 : tree new_iterator = copy_omp_iterator (OMP_CLAUSE_ITERATORS (c), true);
10162 263 : OMP_ITERATOR_LABEL (new_iterator) = loop.body_label;
10163 263 : OMP_ITERATOR_INDEX (new_iterator) = loop.index;
10164 263 : OMP_ITERATOR_ELEMS (new_iterator) = elems;
10165 263 : TREE_CHAIN (new_iterator) = TREE_CHAIN (OMP_CLAUSE_ITERATORS (c));
10166 263 : OMP_CLAUSE_ITERATORS (c) = new_iterator;
10167 :
10168 263 : loop.clauses.safe_push (c);
10169 : }
10170 :
10171 : /* Now gimplify and add all the loops that were built. */
10172 27770 : for (hash_map<tree, iterator_loop_info_t>::iterator it = loops.begin ();
10173 55540 : it != loops.end (); ++it)
10174 124 : gimplify_and_add ((*it).second.bind, loops_seq_p);
10175 27646 : }
10176 :
10177 : /* Helper function for enter_omp_iterator_loop_context. */
10178 :
10179 : static gimple_seq *
10180 2981 : enter_omp_iterator_loop_context_1 (tree iterator, gimple_seq *loops_seq_p)
10181 : {
10182 : /* Drill into the nested bind expressions to get to the loop body. */
10183 2981 : for (gimple_stmt_iterator gsi = gsi_start (*loops_seq_p);
10184 19666 : !gsi_end_p (gsi); gsi_next (&gsi))
10185 : {
10186 19031 : gimple *stmt = gsi_stmt (gsi);
10187 :
10188 19031 : switch (gimple_code (stmt))
10189 : {
10190 2283 : case GIMPLE_BIND:
10191 2283 : {
10192 2283 : gbind *bind_stmt = as_a<gbind *> (stmt);
10193 2283 : gimple_push_bind_expr (bind_stmt);
10194 2283 : gimple_seq *bind_body_p = gimple_bind_body_ptr (bind_stmt);
10195 2283 : gimple_seq *seq =
10196 2283 : enter_omp_iterator_loop_context_1 (iterator, bind_body_p);
10197 2283 : if (seq)
10198 : return seq;
10199 635 : gimple_pop_bind_expr ();
10200 : }
10201 635 : break;
10202 3 : case GIMPLE_TRY:
10203 3 : {
10204 3 : gimple_seq *try_eval_p = gimple_try_eval_ptr (stmt);
10205 3 : gimple_seq *seq =
10206 3 : enter_omp_iterator_loop_context_1 (iterator, try_eval_p);
10207 3 : if (seq)
10208 : return seq;
10209 : }
10210 : break;
10211 3045 : case GIMPLE_LABEL:
10212 3045 : {
10213 3045 : glabel *label_stmt = as_a<glabel *> (stmt);
10214 3045 : tree label = gimple_label_label (label_stmt);
10215 3045 : if (label == OMP_ITERATOR_LABEL (iterator))
10216 : return loops_seq_p;
10217 : }
10218 : break;
10219 : default:
10220 : break;
10221 : }
10222 : }
10223 :
10224 : return NULL;
10225 : }
10226 :
10227 : /* Enter the Gimplification context in LOOPS_SEQ_P for the iterator loop
10228 : associated with OpenMP clause C. Returns the gimple_seq for the loop body
10229 : if C has OpenMP iterators, or ALT_SEQ_P if not. */
10230 :
10231 : static gimple_seq *
10232 65020 : enter_omp_iterator_loop_context (tree c, gimple_seq *loops_seq_p,
10233 : gimple_seq *alt_seq_p)
10234 : {
10235 65020 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10236 : return alt_seq_p;
10237 :
10238 695 : push_gimplify_context ();
10239 :
10240 695 : gimple_seq *seq = enter_omp_iterator_loop_context_1 (OMP_CLAUSE_ITERATORS (c),
10241 : loops_seq_p);
10242 695 : gcc_assert (seq);
10243 : return seq;
10244 : }
10245 :
10246 : /* Enter the Gimplification context in STMT for the iterator loop associated
10247 : with OpenMP clause C. Returns the gimple_seq for the loop body if C has
10248 : OpenMP iterators, or ALT_SEQ_P if not. */
10249 :
10250 : gimple_seq *
10251 434 : enter_omp_iterator_loop_context (tree c, gomp_target *stmt,
10252 : gimple_seq *alt_seq_p)
10253 : {
10254 434 : gimple_seq *loops_seq_p = gimple_omp_target_iterator_loops_ptr (stmt);
10255 434 : return enter_omp_iterator_loop_context (c, loops_seq_p, alt_seq_p);
10256 : }
10257 :
10258 : /* Exit the Gimplification context for the OpenMP clause C. */
10259 :
10260 : void
10261 65110 : exit_omp_iterator_loop_context (tree c)
10262 : {
10263 65110 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10264 : return;
10265 2343 : while (!gimplify_ctxp->bind_expr_stack.is_empty ())
10266 1648 : gimple_pop_bind_expr ();
10267 695 : pop_gimplify_context (NULL);
10268 : }
10269 :
10270 : /* If *LIST_P contains any OpenMP depend clauses with iterators,
10271 : lower all the depend clauses by populating corresponding depend
10272 : array. Returns 0 if there are no such depend clauses, or
10273 : 2 if all depend clauses should be removed, 1 otherwise. */
10274 :
10275 : static int
10276 1905 : gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
10277 : {
10278 1905 : tree c;
10279 1905 : gimple *g;
10280 1905 : size_t n[5] = { 0, 0, 0, 0, 0 };
10281 1905 : bool unused[5];
10282 1905 : tree counts[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
10283 1905 : tree last_iter = NULL_TREE, last_count = NULL_TREE;
10284 1905 : size_t i, j;
10285 1905 : location_t first_loc = UNKNOWN_LOCATION;
10286 :
10287 6250 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10288 4345 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10289 : {
10290 2207 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10291 : {
10292 : case OMP_CLAUSE_DEPEND_IN:
10293 : i = 2;
10294 : break;
10295 : case OMP_CLAUSE_DEPEND_OUT:
10296 : case OMP_CLAUSE_DEPEND_INOUT:
10297 : i = 0;
10298 : break;
10299 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10300 : i = 1;
10301 : break;
10302 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10303 : i = 3;
10304 : break;
10305 : case OMP_CLAUSE_DEPEND_INOUTSET:
10306 : i = 4;
10307 : break;
10308 0 : default:
10309 0 : gcc_unreachable ();
10310 : }
10311 2207 : tree t = OMP_CLAUSE_DECL (c);
10312 2207 : if (first_loc == UNKNOWN_LOCATION)
10313 1905 : first_loc = OMP_CLAUSE_LOCATION (c);
10314 2207 : if (OMP_ITERATOR_DECL_P (t))
10315 : {
10316 302 : if (TREE_PURPOSE (t) != last_iter)
10317 : {
10318 255 : tree tcnt = compute_omp_iterator_count (TREE_PURPOSE (t),
10319 : pre_p);
10320 255 : if (!tcnt)
10321 : return 2;
10322 255 : last_iter = TREE_PURPOSE (t);
10323 255 : last_count = tcnt;
10324 : }
10325 302 : if (counts[i] == NULL_TREE)
10326 248 : counts[i] = last_count;
10327 : else
10328 54 : counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
10329 : PLUS_EXPR, counts[i], last_count);
10330 : }
10331 : else
10332 1905 : n[i]++;
10333 : }
10334 10620 : for (i = 0; i < 5; i++)
10335 8925 : if (counts[i])
10336 : break;
10337 1905 : if (i == 5)
10338 : return 0;
10339 :
10340 210 : tree total = size_zero_node;
10341 1260 : for (i = 0; i < 5; i++)
10342 : {
10343 1050 : unused[i] = counts[i] == NULL_TREE && n[i] == 0;
10344 1050 : if (counts[i] == NULL_TREE)
10345 802 : counts[i] = size_zero_node;
10346 1050 : if (n[i])
10347 44 : counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
10348 1050 : if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
10349 : fb_rvalue) == GS_ERROR)
10350 : return 2;
10351 1050 : total = size_binop (PLUS_EXPR, total, counts[i]);
10352 : }
10353 :
10354 210 : if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
10355 : == GS_ERROR)
10356 : return 2;
10357 210 : bool is_old = unused[1] && unused[3] && unused[4];
10358 210 : tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
10359 : size_int (is_old ? 1 : 4));
10360 210 : if (!unused[4])
10361 3 : totalpx = size_binop (PLUS_EXPR, totalpx,
10362 : size_binop (MULT_EXPR, counts[4], size_int (2)));
10363 210 : tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
10364 210 : tree array = create_tmp_var_raw (type);
10365 210 : TREE_ADDRESSABLE (array) = 1;
10366 210 : if (!poly_int_tree_p (totalpx))
10367 : {
10368 83 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
10369 83 : gimplify_type_sizes (TREE_TYPE (array), pre_p);
10370 83 : if (gimplify_omp_ctxp)
10371 : {
10372 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
10373 : while (ctx
10374 22 : && (ctx->region_type == ORT_WORKSHARE
10375 : || ctx->region_type == ORT_TASKGROUP
10376 22 : || ctx->region_type == ORT_SIMD
10377 22 : || ctx->region_type == ORT_ACC))
10378 0 : ctx = ctx->outer_context;
10379 22 : if (ctx)
10380 22 : omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
10381 : }
10382 83 : gimplify_vla_decl (array, pre_p);
10383 : }
10384 : else
10385 127 : gimple_add_tmp_var (array);
10386 210 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
10387 : NULL_TREE);
10388 210 : tree tem;
10389 210 : if (!is_old)
10390 : {
10391 31 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10392 : build_int_cst (ptr_type_node, 0));
10393 31 : gimplify_and_add (tem, pre_p);
10394 31 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
10395 : NULL_TREE);
10396 : }
10397 210 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10398 : fold_convert (ptr_type_node, total));
10399 210 : gimplify_and_add (tem, pre_p);
10400 816 : for (i = 1; i < (is_old ? 2 : 4); i++)
10401 : {
10402 272 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
10403 : NULL_TREE, NULL_TREE);
10404 272 : tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
10405 272 : gimplify_and_add (tem, pre_p);
10406 : }
10407 :
10408 : tree cnts[6];
10409 740 : for (j = 5; j; j--)
10410 740 : if (!unused[j - 1])
10411 : break;
10412 1260 : for (i = 0; i < 5; i++)
10413 : {
10414 1050 : if (i && (i >= j || unused[i - 1]))
10415 : {
10416 790 : cnts[i] = cnts[i - 1];
10417 790 : continue;
10418 : }
10419 260 : cnts[i] = create_tmp_var (sizetype);
10420 260 : if (i == 0)
10421 241 : g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
10422 : else
10423 : {
10424 50 : tree t;
10425 50 : if (is_old)
10426 38 : t = size_binop (PLUS_EXPR, counts[0], size_int (2));
10427 : else
10428 12 : t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
10429 50 : if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
10430 : == GS_ERROR)
10431 0 : return 2;
10432 50 : g = gimple_build_assign (cnts[i], t);
10433 : }
10434 260 : gimple_seq_add_stmt (pre_p, g);
10435 : }
10436 210 : if (unused[4])
10437 207 : cnts[5] = NULL_TREE;
10438 : else
10439 : {
10440 3 : tree t = size_binop (PLUS_EXPR, total, size_int (5));
10441 3 : cnts[5] = create_tmp_var (sizetype);
10442 3 : g = gimple_build_assign (cnts[i], t);
10443 3 : gimple_seq_add_stmt (pre_p, g);
10444 : }
10445 :
10446 210 : last_iter = NULL_TREE;
10447 210 : tree last_bind = NULL_TREE;
10448 210 : tree *last_body = NULL;
10449 573 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10450 363 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10451 : {
10452 348 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10453 : {
10454 : case OMP_CLAUSE_DEPEND_IN:
10455 : i = 2;
10456 : break;
10457 : case OMP_CLAUSE_DEPEND_OUT:
10458 : case OMP_CLAUSE_DEPEND_INOUT:
10459 : i = 0;
10460 : break;
10461 : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10462 : i = 1;
10463 : break;
10464 : case OMP_CLAUSE_DEPEND_DEPOBJ:
10465 : i = 3;
10466 : break;
10467 : case OMP_CLAUSE_DEPEND_INOUTSET:
10468 : i = 4;
10469 : break;
10470 0 : default:
10471 0 : gcc_unreachable ();
10472 : }
10473 348 : tree t = OMP_CLAUSE_DECL (c);
10474 348 : if (OMP_ITERATOR_DECL_P (t))
10475 : {
10476 302 : if (TREE_PURPOSE (t) != last_iter)
10477 : {
10478 255 : last_body = build_omp_iterator_loop (TREE_PURPOSE (t), pre_p,
10479 : &last_bind);
10480 255 : SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
10481 : }
10482 302 : last_iter = TREE_PURPOSE (t);
10483 302 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
10484 : {
10485 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
10486 : 0), last_body);
10487 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
10488 : }
10489 302 : if (error_operand_p (TREE_VALUE (t)))
10490 : return 2;
10491 302 : if (TREE_VALUE (t) != null_pointer_node)
10492 296 : TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
10493 302 : if (i == 4)
10494 : {
10495 3 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10496 : NULL_TREE, NULL_TREE);
10497 3 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10498 : NULL_TREE, NULL_TREE);
10499 3 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10500 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10501 : void_type_node, r, r2);
10502 3 : append_to_statement_list_force (tem, last_body);
10503 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10504 : void_type_node, cnts[i],
10505 : size_binop (PLUS_EXPR, cnts[i],
10506 : size_int (1)));
10507 3 : append_to_statement_list_force (tem, last_body);
10508 3 : i = 5;
10509 : }
10510 302 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10511 : NULL_TREE, NULL_TREE);
10512 604 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10513 302 : void_type_node, r, TREE_VALUE (t));
10514 302 : append_to_statement_list_force (tem, last_body);
10515 302 : if (i == 5)
10516 : {
10517 3 : r = build4 (ARRAY_REF, ptr_type_node, array,
10518 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10519 : NULL_TREE, NULL_TREE);
10520 3 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10521 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10522 : void_type_node, r, tem);
10523 3 : append_to_statement_list_force (tem, last_body);
10524 : }
10525 302 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10526 : void_type_node, cnts[i],
10527 302 : size_binop (PLUS_EXPR, cnts[i],
10528 : size_int (1 + (i == 5))));
10529 302 : append_to_statement_list_force (tem, last_body);
10530 302 : TREE_VALUE (t) = null_pointer_node;
10531 : }
10532 : else
10533 : {
10534 46 : if (last_bind)
10535 : {
10536 18 : gimplify_and_add (last_bind, pre_p);
10537 18 : last_bind = NULL_TREE;
10538 : }
10539 46 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
10540 : {
10541 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
10542 : NULL, is_gimple_val, fb_rvalue);
10543 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
10544 : }
10545 46 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
10546 : return 2;
10547 46 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
10548 46 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
10549 46 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
10550 : is_gimple_val, fb_rvalue) == GS_ERROR)
10551 : return 2;
10552 46 : if (i == 4)
10553 : {
10554 0 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10555 : NULL_TREE, NULL_TREE);
10556 0 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10557 : NULL_TREE, NULL_TREE);
10558 0 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10559 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, r2);
10560 0 : gimplify_and_add (tem, pre_p);
10561 0 : g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR,
10562 : cnts[i],
10563 : size_int (1)));
10564 0 : gimple_seq_add_stmt (pre_p, g);
10565 0 : i = 5;
10566 : }
10567 46 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10568 : NULL_TREE, NULL_TREE);
10569 46 : tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
10570 46 : gimplify_and_add (tem, pre_p);
10571 46 : if (i == 5)
10572 : {
10573 0 : r = build4 (ARRAY_REF, ptr_type_node, array,
10574 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10575 : NULL_TREE, NULL_TREE);
10576 0 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10577 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, tem);
10578 0 : append_to_statement_list_force (tem, last_body);
10579 0 : gimplify_and_add (tem, pre_p);
10580 : }
10581 46 : g = gimple_build_assign (cnts[i],
10582 46 : size_binop (PLUS_EXPR, cnts[i],
10583 : size_int (1 + (i == 5))));
10584 46 : gimple_seq_add_stmt (pre_p, g);
10585 : }
10586 : }
10587 210 : if (last_bind)
10588 206 : gimplify_and_add (last_bind, pre_p);
10589 210 : tree cond = boolean_false_node;
10590 210 : if (is_old)
10591 : {
10592 179 : if (!unused[0])
10593 92 : cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
10594 : size_binop_loc (first_loc, PLUS_EXPR, counts[0],
10595 : size_int (2)));
10596 179 : if (!unused[2])
10597 125 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10598 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10599 : cnts[2],
10600 : size_binop_loc (first_loc, PLUS_EXPR,
10601 : totalpx,
10602 : size_int (1))));
10603 : }
10604 : else
10605 : {
10606 31 : tree prev = size_int (5);
10607 186 : for (i = 0; i < 5; i++)
10608 : {
10609 155 : if (unused[i])
10610 112 : continue;
10611 43 : prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
10612 43 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10613 : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10614 : cnts[i], unshare_expr (prev)));
10615 : }
10616 : }
10617 210 : tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
10618 : build_call_expr_loc (first_loc,
10619 : builtin_decl_explicit (BUILT_IN_TRAP),
10620 : 0), void_node);
10621 210 : gimplify_and_add (tem, pre_p);
10622 210 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10623 210 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
10624 210 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10625 210 : OMP_CLAUSE_CHAIN (c) = *list_p;
10626 210 : *list_p = c;
10627 210 : return 1;
10628 : }
10629 :
10630 : /* True if mapping node C maps, or unmaps, a (Fortran) array descriptor. */
10631 :
10632 : static bool
10633 125757 : omp_map_clause_descriptor_p (tree c)
10634 : {
10635 125757 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
10636 : return false;
10637 :
10638 125753 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)
10639 : return true;
10640 :
10641 82535 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
10642 74497 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE)
10643 83017 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (c))
10644 6135 : return true;
10645 :
10646 : return false;
10647 : }
10648 :
10649 : /* For a set of mappings describing an array section pointed to by a struct
10650 : (or derived type, etc.) component, create an "alloc" or "release" node to
10651 : insert into a list following a GOMP_MAP_STRUCT node. For some types of
10652 : mapping (e.g. Fortran arrays with descriptors), an additional mapping may
10653 : be created that is inserted into the list of mapping nodes attached to the
10654 : directive being processed -- not part of the sorted list of nodes after
10655 : GOMP_MAP_STRUCT.
10656 :
10657 : CODE is the code of the directive being processed. GRP_START and GRP_END
10658 : are the first and last of two or three nodes representing this array section
10659 : mapping (e.g. a data movement node like GOMP_MAP_{TO,FROM}, optionally a
10660 : GOMP_MAP_TO_PSET, and finally a GOMP_MAP_ALWAYS_POINTER). EXTRA_NODE is
10661 : filled with the additional node described above, if needed.
10662 :
10663 : This function does not add the new nodes to any lists itself. It is the
10664 : responsibility of the caller to do that. */
10665 :
10666 : static tree
10667 1729 : build_omp_struct_comp_nodes (enum tree_code code, tree grp_start, tree grp_end,
10668 : tree *extra_node)
10669 : {
10670 1524 : enum gomp_map_kind mkind
10671 1729 : = (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
10672 1729 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
10673 :
10674 1729 : gcc_assert (grp_start != grp_end);
10675 :
10676 1729 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10677 1729 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
10678 1729 : OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (grp_end));
10679 1729 : OMP_CLAUSE_CHAIN (c2) = NULL_TREE;
10680 1729 : tree grp_mid = NULL_TREE;
10681 1729 : if (OMP_CLAUSE_CHAIN (grp_start) != grp_end)
10682 197 : grp_mid = OMP_CLAUSE_CHAIN (grp_start);
10683 :
10684 197 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
10685 0 : OMP_CLAUSE_SIZE (c2) = OMP_CLAUSE_SIZE (grp_mid);
10686 : else
10687 1729 : OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node);
10688 :
10689 1729 : if (grp_mid
10690 197 : && OMP_CLAUSE_CODE (grp_mid) == OMP_CLAUSE_MAP
10691 1926 : && OMP_CLAUSE_MAP_KIND (grp_mid) == GOMP_MAP_ALWAYS_POINTER)
10692 : {
10693 0 : tree c3
10694 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10695 0 : OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
10696 0 : OMP_CLAUSE_DECL (c3) = unshare_expr (OMP_CLAUSE_DECL (grp_mid));
10697 0 : OMP_CLAUSE_SIZE (c3) = TYPE_SIZE_UNIT (ptr_type_node);
10698 0 : OMP_CLAUSE_CHAIN (c3) = NULL_TREE;
10699 :
10700 0 : *extra_node = c3;
10701 : }
10702 : else
10703 1729 : *extra_node = NULL_TREE;
10704 :
10705 1729 : return c2;
10706 : }
10707 :
10708 : /* Strip ARRAY_REFS or an indirect ref off BASE, find the containing object,
10709 : and set *BITPOSP and *POFFSETP to the bit offset of the access.
10710 : If BASE_REF is non-NULL and the containing object is a reference, set
10711 : *BASE_REF to that reference before dereferencing the object.
10712 : If BASE_REF is NULL, check that the containing object is a COMPONENT_REF or
10713 : has array type, else return NULL. */
10714 :
10715 : static tree
10716 7739 : extract_base_bit_offset (tree base, poly_int64 *bitposp,
10717 : poly_offset_int *poffsetp,
10718 : bool *variable_offset,
10719 : tree iterator)
10720 : {
10721 7739 : tree offset;
10722 7739 : poly_int64 bitsize, bitpos;
10723 7739 : machine_mode mode;
10724 7739 : int unsignedp, reversep, volatilep = 0;
10725 7739 : poly_offset_int poffset;
10726 :
10727 7739 : STRIP_NOPS (base);
10728 :
10729 7739 : if (iterator)
10730 : {
10731 : /* Replace any iterator variables with the lower bound of the iterator.
10732 : This will give us the nominal offset and bit position of the first
10733 : element, which is all we should need to lay out the mappings. The
10734 : actual locations of the iterated mappings are elsewhere. */
10735 : tree it;
10736 72 : for (it = iterator; it; it = TREE_CHAIN (it))
10737 39 : base = simplify_replace_tree (base, OMP_ITERATOR_VAR (it),
10738 39 : OMP_ITERATOR_BEGIN (it));
10739 : }
10740 :
10741 7739 : base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
10742 : &unsignedp, &reversep, &volatilep);
10743 :
10744 7739 : STRIP_NOPS (base);
10745 :
10746 7739 : if (offset && poly_int_tree_p (offset))
10747 : {
10748 0 : poffset = wi::to_poly_offset (offset);
10749 0 : *variable_offset = false;
10750 : }
10751 : else
10752 : {
10753 7739 : poffset = 0;
10754 7739 : *variable_offset = (offset != NULL_TREE);
10755 : }
10756 :
10757 7739 : if (maybe_ne (bitpos, 0))
10758 5627 : poffset += bits_to_bytes_round_down (bitpos);
10759 :
10760 7739 : *bitposp = bitpos;
10761 7739 : *poffsetp = poffset;
10762 :
10763 7739 : return base;
10764 : }
10765 :
10766 : /* Used for topological sorting of mapping groups. UNVISITED means we haven't
10767 : started processing the group yet. The TEMPORARY mark is used when we first
10768 : encounter a group on a depth-first traversal, and the PERMANENT mark is used
10769 : when we have processed all the group's children (i.e. all the base pointers
10770 : referred to by the group's mapping nodes, recursively). */
10771 :
10772 : enum omp_tsort_mark {
10773 : UNVISITED,
10774 : TEMPORARY,
10775 : PERMANENT
10776 : };
10777 :
10778 : /* Hash for trees based on operand_equal_p. Like tree_operand_hash
10779 : but ignores side effects in the equality comparisons. */
10780 :
10781 : struct tree_operand_hash_no_se : tree_operand_hash
10782 : {
10783 : static inline bool equal (const value_type &,
10784 : const compare_type &);
10785 : };
10786 :
10787 : inline bool
10788 401868 : tree_operand_hash_no_se::equal (const value_type &t1,
10789 : const compare_type &t2)
10790 : {
10791 401868 : return operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS);
10792 : }
10793 :
10794 : /* A group of OMP_CLAUSE_MAP nodes that correspond to a single "map"
10795 : clause. */
10796 :
10797 : struct omp_mapping_group {
10798 : tree *grp_start;
10799 : tree grp_end;
10800 : omp_tsort_mark mark;
10801 : /* If we've removed the group but need to reindex, mark the group as
10802 : deleted. */
10803 : bool deleted;
10804 : /* The group points to an already-created "GOMP_MAP_STRUCT
10805 : GOMP_MAP_ATTACH_DETACH" pair. */
10806 : bool reprocess_struct;
10807 : /* The group should use "zero-length" allocations for pointers that are not
10808 : mapped "to" on the same directive. */
10809 : bool fragile;
10810 : struct omp_mapping_group *sibling;
10811 : struct omp_mapping_group *next;
10812 : };
10813 :
10814 : DEBUG_FUNCTION void
10815 0 : debug_mapping_group (omp_mapping_group *grp)
10816 : {
10817 0 : tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end);
10818 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = NULL;
10819 0 : debug_generic_expr (*grp->grp_start);
10820 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = tmp;
10821 0 : }
10822 :
10823 : /* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there
10824 : isn't one. */
10825 :
10826 : static tree
10827 36347 : omp_get_base_pointer (tree expr)
10828 : {
10829 36347 : while (TREE_CODE (expr) == ARRAY_REF
10830 43586 : || TREE_CODE (expr) == COMPONENT_REF)
10831 7239 : expr = TREE_OPERAND (expr, 0);
10832 :
10833 36347 : if (INDIRECT_REF_P (expr)
10834 36347 : || (TREE_CODE (expr) == MEM_REF
10835 1 : && integer_zerop (TREE_OPERAND (expr, 1))))
10836 : {
10837 10583 : expr = TREE_OPERAND (expr, 0);
10838 10620 : while (TREE_CODE (expr) == COMPOUND_EXPR)
10839 37 : expr = TREE_OPERAND (expr, 1);
10840 10583 : if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
10841 841 : expr = TREE_OPERAND (expr, 0);
10842 10583 : if (TREE_CODE (expr) == SAVE_EXPR)
10843 31 : expr = TREE_OPERAND (expr, 0);
10844 10583 : STRIP_NOPS (expr);
10845 10583 : return expr;
10846 : }
10847 :
10848 : return NULL_TREE;
10849 : }
10850 :
10851 : /* An attach or detach operation depends directly on the address being
10852 : attached/detached. Return that address, or none if there are no
10853 : attachments/detachments. */
10854 :
10855 : static tree
10856 16825 : omp_get_attachment (omp_mapping_group *grp)
10857 : {
10858 16825 : tree node = *grp->grp_start;
10859 :
10860 16825 : switch (OMP_CLAUSE_MAP_KIND (node))
10861 : {
10862 13871 : case GOMP_MAP_TO:
10863 13871 : case GOMP_MAP_FROM:
10864 13871 : case GOMP_MAP_TOFROM:
10865 13871 : case GOMP_MAP_ALWAYS_FROM:
10866 13871 : case GOMP_MAP_ALWAYS_TO:
10867 13871 : case GOMP_MAP_ALWAYS_TOFROM:
10868 13871 : case GOMP_MAP_FORCE_FROM:
10869 13871 : case GOMP_MAP_FORCE_TO:
10870 13871 : case GOMP_MAP_FORCE_TOFROM:
10871 13871 : case GOMP_MAP_FORCE_PRESENT:
10872 13871 : case GOMP_MAP_PRESENT_ALLOC:
10873 13871 : case GOMP_MAP_PRESENT_FROM:
10874 13871 : case GOMP_MAP_PRESENT_TO:
10875 13871 : case GOMP_MAP_PRESENT_TOFROM:
10876 13871 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
10877 13871 : case GOMP_MAP_ALWAYS_PRESENT_TO:
10878 13871 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
10879 13871 : case GOMP_MAP_ALLOC:
10880 13871 : case GOMP_MAP_RELEASE:
10881 13871 : case GOMP_MAP_DELETE:
10882 13871 : case GOMP_MAP_FORCE_ALLOC:
10883 13871 : if (node == grp->grp_end)
10884 : return NULL_TREE;
10885 :
10886 6614 : node = OMP_CLAUSE_CHAIN (node);
10887 6614 : if (node && omp_map_clause_descriptor_p (node))
10888 : {
10889 1038 : gcc_assert (node != grp->grp_end);
10890 1038 : node = OMP_CLAUSE_CHAIN (node);
10891 : }
10892 6614 : if (node)
10893 6614 : switch (OMP_CLAUSE_MAP_KIND (node))
10894 : {
10895 : case GOMP_MAP_POINTER:
10896 : case GOMP_MAP_ALWAYS_POINTER:
10897 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
10898 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
10899 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
10900 : case GOMP_MAP_USES_ALLOCATORS:
10901 : return NULL_TREE;
10902 :
10903 2555 : case GOMP_MAP_ATTACH_DETACH:
10904 2555 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10905 2555 : case GOMP_MAP_DETACH:
10906 2555 : return OMP_CLAUSE_DECL (node);
10907 :
10908 0 : default:
10909 0 : internal_error ("unexpected mapping node");
10910 : }
10911 0 : return error_mark_node;
10912 :
10913 0 : case GOMP_MAP_TO_PSET:
10914 0 : gcc_assert (node != grp->grp_end);
10915 0 : node = OMP_CLAUSE_CHAIN (node);
10916 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
10917 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
10918 0 : return OMP_CLAUSE_DECL (node);
10919 : else
10920 0 : internal_error ("unexpected mapping node");
10921 : return error_mark_node;
10922 :
10923 537 : case GOMP_MAP_ATTACH:
10924 537 : case GOMP_MAP_DETACH:
10925 537 : node = OMP_CLAUSE_CHAIN (node);
10926 537 : if (!node || *grp->grp_start == grp->grp_end)
10927 537 : return OMP_CLAUSE_DECL (*grp->grp_start);
10928 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
10929 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
10930 0 : return OMP_CLAUSE_DECL (*grp->grp_start);
10931 : else
10932 0 : internal_error ("unexpected mapping node");
10933 : return error_mark_node;
10934 :
10935 : case GOMP_MAP_STRUCT:
10936 : case GOMP_MAP_STRUCT_UNORD:
10937 : case GOMP_MAP_FORCE_DEVICEPTR:
10938 : case GOMP_MAP_DEVICE_RESIDENT:
10939 : case GOMP_MAP_LINK:
10940 : case GOMP_MAP_IF_PRESENT:
10941 : case GOMP_MAP_FIRSTPRIVATE:
10942 : case GOMP_MAP_FIRSTPRIVATE_INT:
10943 : case GOMP_MAP_USE_DEVICE_PTR:
10944 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10945 : case GOMP_MAP_USES_ALLOCATORS:
10946 : return NULL_TREE;
10947 :
10948 0 : default:
10949 0 : internal_error ("unexpected mapping node");
10950 : }
10951 :
10952 : return error_mark_node;
10953 : }
10954 :
10955 : /* Given a pointer START_P to the start of a group of related (e.g. pointer)
10956 : mappings, return the chain pointer to the end of that group in the list. */
10957 :
10958 : static tree *
10959 111188 : omp_group_last (tree *start_p)
10960 : {
10961 111188 : tree c = *start_p, nc, *grp_last_p = start_p;
10962 :
10963 111188 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
10964 :
10965 111188 : nc = OMP_CLAUSE_CHAIN (c);
10966 :
10967 194059 : if (!nc || OMP_CLAUSE_CODE (nc) != OMP_CLAUSE_MAP)
10968 : return grp_last_p;
10969 :
10970 70646 : switch (OMP_CLAUSE_MAP_KIND (c))
10971 : {
10972 : default:
10973 : while (nc
10974 113564 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
10975 238513 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
10976 106386 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
10977 95797 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH
10978 82986 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
10979 56902 : || (OMP_CLAUSE_MAP_KIND (nc)
10980 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
10981 56886 : || (OMP_CLAUSE_MAP_KIND (nc)
10982 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)
10983 56519 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH
10984 56464 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER
10985 54552 : || omp_map_clause_descriptor_p (nc)))
10986 : {
10987 66935 : tree nc2 = OMP_CLAUSE_CHAIN (nc);
10988 66935 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH)
10989 : {
10990 : /* In the specific case we're doing "exit data" on an array
10991 : slice of a reference-to-pointer struct component, we will see
10992 : DETACH followed by ATTACH_DETACH here. We want to treat that
10993 : as a single group. In other cases DETACH might represent a
10994 : stand-alone "detach" clause, so we don't want to consider
10995 : that part of the group. */
10996 55 : if (nc2
10997 16 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
10998 71 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH)
10999 0 : goto consume_two_nodes;
11000 : else
11001 : break;
11002 : }
11003 66880 : if (nc2
11004 48986 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
11005 42473 : && (OMP_CLAUSE_MAP_KIND (nc)
11006 : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
11007 66896 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH)
11008 : {
11009 16 : consume_two_nodes:
11010 16 : grp_last_p = &OMP_CLAUSE_CHAIN (nc);
11011 16 : c = nc2;
11012 16 : nc = OMP_CLAUSE_CHAIN (nc2);
11013 : }
11014 : else
11015 : {
11016 66864 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11017 66864 : c = nc;
11018 66864 : nc = nc2;
11019 : }
11020 : }
11021 : break;
11022 :
11023 302 : case GOMP_MAP_ATTACH:
11024 302 : case GOMP_MAP_DETACH:
11025 : /* This is a weird artifact of how directives are parsed: bare attach or
11026 : detach clauses get a subsequent (meaningless) FIRSTPRIVATE_POINTER or
11027 : FIRSTPRIVATE_REFERENCE node. FIXME. */
11028 302 : if (nc
11029 302 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11030 302 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11031 302 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER))
11032 0 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11033 : break;
11034 :
11035 39 : case GOMP_MAP_TO_PSET:
11036 39 : if (OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11037 39 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH
11038 12 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH))
11039 39 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11040 : break;
11041 :
11042 5723 : case GOMP_MAP_STRUCT:
11043 5723 : case GOMP_MAP_STRUCT_UNORD:
11044 5723 : {
11045 5723 : unsigned HOST_WIDE_INT num_mappings
11046 5723 : = tree_to_uhwi (OMP_CLAUSE_SIZE (c));
11047 5723 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
11048 5385 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11049 10626 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH)
11050 1134 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11051 14389 : for (unsigned i = 0; i < num_mappings; i++)
11052 8666 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11053 : }
11054 : break;
11055 : }
11056 :
11057 : return grp_last_p;
11058 : }
11059 :
11060 : /* Walk through LIST_P, and return a list of groups of mappings found (e.g.
11061 : OMP_CLAUSE_MAP with GOMP_MAP_{TO/FROM/TOFROM} followed by one or two
11062 : associated GOMP_MAP_POINTER mappings). Return a vector of omp_mapping_group
11063 : if we have more than one such group, else return NULL. */
11064 :
11065 : static void
11066 89613 : omp_gather_mapping_groups_1 (tree *list_p, vec<omp_mapping_group> *groups,
11067 : tree gather_sentinel)
11068 : {
11069 89613 : for (tree *cp = list_p;
11070 267828 : *cp && *cp != gather_sentinel;
11071 178215 : cp = &OMP_CLAUSE_CHAIN (*cp))
11072 : {
11073 178215 : if (OMP_CLAUSE_CODE (*cp) != OMP_CLAUSE_MAP)
11074 98725 : continue;
11075 :
11076 79490 : tree *grp_last_p = omp_group_last (cp);
11077 79490 : omp_mapping_group grp;
11078 :
11079 79490 : grp.grp_start = cp;
11080 79490 : grp.grp_end = *grp_last_p;
11081 79490 : grp.mark = UNVISITED;
11082 79490 : grp.sibling = NULL;
11083 79490 : grp.deleted = false;
11084 79490 : grp.reprocess_struct = false;
11085 79490 : grp.fragile = false;
11086 79490 : grp.next = NULL;
11087 79490 : groups->safe_push (grp);
11088 :
11089 79490 : cp = grp_last_p;
11090 : }
11091 89613 : }
11092 :
11093 : static vec<omp_mapping_group> *
11094 89295 : omp_gather_mapping_groups (tree *list_p)
11095 : {
11096 89295 : vec<omp_mapping_group> *groups = new vec<omp_mapping_group> ();
11097 :
11098 89295 : omp_gather_mapping_groups_1 (list_p, groups, NULL_TREE);
11099 :
11100 89295 : if (groups->length () > 0)
11101 : return groups;
11102 : else
11103 : {
11104 44604 : delete groups;
11105 44604 : return NULL;
11106 : }
11107 : }
11108 :
11109 : /* A pointer mapping group GRP may define a block of memory starting at some
11110 : base address, and maybe also define a firstprivate pointer or firstprivate
11111 : reference that points to that block. The return value is a node containing
11112 : the former, and the *FIRSTPRIVATE pointer is set if we have the latter.
11113 : If we define several base pointers, i.e. for a GOMP_MAP_STRUCT mapping,
11114 : return the number of consecutive chained nodes in CHAINED. */
11115 :
11116 : static tree
11117 79884 : omp_group_base (omp_mapping_group *grp, unsigned int *chained,
11118 : tree *firstprivate)
11119 : {
11120 79884 : tree node = *grp->grp_start;
11121 :
11122 79884 : *firstprivate = NULL_TREE;
11123 79884 : *chained = 1;
11124 :
11125 79884 : switch (OMP_CLAUSE_MAP_KIND (node))
11126 : {
11127 75700 : case GOMP_MAP_TO:
11128 75700 : case GOMP_MAP_FROM:
11129 75700 : case GOMP_MAP_TOFROM:
11130 75700 : case GOMP_MAP_ALWAYS_FROM:
11131 75700 : case GOMP_MAP_ALWAYS_TO:
11132 75700 : case GOMP_MAP_ALWAYS_TOFROM:
11133 75700 : case GOMP_MAP_FORCE_FROM:
11134 75700 : case GOMP_MAP_FORCE_TO:
11135 75700 : case GOMP_MAP_FORCE_TOFROM:
11136 75700 : case GOMP_MAP_FORCE_PRESENT:
11137 75700 : case GOMP_MAP_PRESENT_ALLOC:
11138 75700 : case GOMP_MAP_PRESENT_FROM:
11139 75700 : case GOMP_MAP_PRESENT_TO:
11140 75700 : case GOMP_MAP_PRESENT_TOFROM:
11141 75700 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
11142 75700 : case GOMP_MAP_ALWAYS_PRESENT_TO:
11143 75700 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
11144 75700 : case GOMP_MAP_ALLOC:
11145 75700 : case GOMP_MAP_RELEASE:
11146 75700 : case GOMP_MAP_DELETE:
11147 75700 : case GOMP_MAP_FORCE_ALLOC:
11148 75700 : case GOMP_MAP_IF_PRESENT:
11149 75700 : if (node == grp->grp_end)
11150 : return node;
11151 :
11152 34759 : node = OMP_CLAUSE_CHAIN (node);
11153 34759 : if (!node)
11154 0 : internal_error ("unexpected mapping node");
11155 34759 : if (omp_map_clause_descriptor_p (node))
11156 : {
11157 10754 : if (node == grp->grp_end)
11158 0 : return *grp->grp_start;
11159 10754 : node = OMP_CLAUSE_CHAIN (node);
11160 : }
11161 34759 : switch (OMP_CLAUSE_MAP_KIND (node))
11162 : {
11163 23458 : case GOMP_MAP_POINTER:
11164 23458 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11165 23458 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11166 23458 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11167 23458 : *firstprivate = OMP_CLAUSE_DECL (node);
11168 23458 : return *grp->grp_start;
11169 :
11170 11301 : case GOMP_MAP_ALWAYS_POINTER:
11171 11301 : case GOMP_MAP_ATTACH_DETACH:
11172 11301 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11173 11301 : case GOMP_MAP_DETACH:
11174 11301 : return *grp->grp_start;
11175 :
11176 0 : default:
11177 0 : internal_error ("unexpected mapping node");
11178 : }
11179 : return error_mark_node;
11180 :
11181 26 : case GOMP_MAP_TO_PSET:
11182 26 : gcc_assert (node != grp->grp_end);
11183 26 : node = OMP_CLAUSE_CHAIN (node);
11184 26 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
11185 26 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
11186 : return NULL_TREE;
11187 : else
11188 0 : internal_error ("unexpected mapping node");
11189 : return error_mark_node;
11190 :
11191 1097 : case GOMP_MAP_ATTACH:
11192 1097 : case GOMP_MAP_DETACH:
11193 1097 : node = OMP_CLAUSE_CHAIN (node);
11194 1097 : if (!node || *grp->grp_start == grp->grp_end)
11195 : return NULL_TREE;
11196 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11197 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11198 : {
11199 : /* We're mapping the base pointer itself in a bare attach or detach
11200 : node. This is a side effect of how parsing works, and the mapping
11201 : will be removed anyway (at least for enter/exit data directives).
11202 : We should ignore the mapping here. FIXME. */
11203 : return NULL_TREE;
11204 : }
11205 : else
11206 0 : internal_error ("unexpected mapping node");
11207 : return error_mark_node;
11208 :
11209 2777 : case GOMP_MAP_STRUCT:
11210 2777 : case GOMP_MAP_STRUCT_UNORD:
11211 2777 : {
11212 2777 : unsigned HOST_WIDE_INT num_mappings
11213 2777 : = tree_to_uhwi (OMP_CLAUSE_SIZE (node));
11214 2777 : node = OMP_CLAUSE_CHAIN (node);
11215 2777 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11216 2777 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11217 : {
11218 393 : *firstprivate = OMP_CLAUSE_DECL (node);
11219 393 : node = OMP_CLAUSE_CHAIN (node);
11220 : }
11221 2384 : else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH_DETACH)
11222 314 : node = OMP_CLAUSE_CHAIN (node);
11223 2777 : *chained = num_mappings;
11224 2777 : return node;
11225 : }
11226 :
11227 : case GOMP_MAP_FORCE_DEVICEPTR:
11228 : case GOMP_MAP_DEVICE_RESIDENT:
11229 : case GOMP_MAP_LINK:
11230 : case GOMP_MAP_FIRSTPRIVATE:
11231 : case GOMP_MAP_FIRSTPRIVATE_INT:
11232 : case GOMP_MAP_USE_DEVICE_PTR:
11233 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11234 : case GOMP_MAP_USES_ALLOCATORS:
11235 : return NULL_TREE;
11236 :
11237 0 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11238 0 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11239 0 : case GOMP_MAP_POINTER:
11240 0 : case GOMP_MAP_ALWAYS_POINTER:
11241 0 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11242 : /* These shouldn't appear by themselves. */
11243 0 : if (!seen_error ())
11244 0 : internal_error ("unexpected pointer mapping node");
11245 0 : return error_mark_node;
11246 :
11247 0 : default:
11248 0 : gcc_unreachable ();
11249 : }
11250 :
11251 : return error_mark_node;
11252 : }
11253 :
11254 : /* Given a vector of omp_mapping_groups, build a hash table so we can look up
11255 : nodes by tree_operand_hash_no_se. */
11256 :
11257 : static void
11258 45175 : omp_index_mapping_groups_1 (hash_map<tree_operand_hash_no_se,
11259 : omp_mapping_group *> *grpmap,
11260 : vec<omp_mapping_group> *groups,
11261 : tree reindex_sentinel)
11262 : {
11263 45175 : omp_mapping_group *grp;
11264 45175 : unsigned int i;
11265 45175 : bool reindexing = reindex_sentinel != NULL_TREE, above_hwm = false;
11266 :
11267 125513 : FOR_EACH_VEC_ELT (*groups, i, grp)
11268 : {
11269 80338 : if (reindexing && *grp->grp_start == reindex_sentinel)
11270 80338 : above_hwm = true;
11271 :
11272 80338 : if (reindexing && !above_hwm)
11273 56487 : continue;
11274 :
11275 80038 : if (grp->reprocess_struct)
11276 154 : continue;
11277 :
11278 79884 : tree fpp;
11279 79884 : unsigned int chained;
11280 79884 : tree node = omp_group_base (grp, &chained, &fpp);
11281 :
11282 79884 : if (node == error_mark_node || (!node && !fpp))
11283 1407 : continue;
11284 :
11285 : for (unsigned j = 0;
11286 158398 : node && j < chained;
11287 79921 : node = OMP_CLAUSE_CHAIN (node), j++)
11288 : {
11289 79921 : tree decl = OMP_CLAUSE_DECL (node);
11290 : /* Sometimes we see zero-offset MEM_REF instead of INDIRECT_REF,
11291 : meaning node-hash lookups don't work. This is a workaround for
11292 : that, but ideally we should just create the INDIRECT_REF at
11293 : source instead. FIXME. */
11294 79921 : if (TREE_CODE (decl) == MEM_REF
11295 79921 : && integer_zerop (TREE_OPERAND (decl, 1)))
11296 0 : decl = build_fold_indirect_ref (TREE_OPERAND (decl, 0));
11297 :
11298 79921 : omp_mapping_group **prev = grpmap->get (decl);
11299 :
11300 79921 : if (prev && *prev == grp)
11301 : /* Empty. */;
11302 79921 : else if (prev)
11303 : {
11304 : /* Mapping the same thing twice is normally diagnosed as an error,
11305 : but can happen under some circumstances, e.g. in pr99928-16.c,
11306 : the directive:
11307 :
11308 : #pragma omp target simd reduction(+:a[:3]) \
11309 : map(always, tofrom: a[:6])
11310 : ...
11311 :
11312 : will result in two "a[0]" mappings (of different sizes). */
11313 :
11314 326 : grp->sibling = (*prev)->sibling;
11315 326 : (*prev)->sibling = grp;
11316 : }
11317 : else
11318 79595 : grpmap->put (decl, grp);
11319 : }
11320 :
11321 78477 : if (!fpp)
11322 54626 : continue;
11323 :
11324 23851 : omp_mapping_group **prev = grpmap->get (fpp);
11325 23851 : if (prev && *prev != grp)
11326 : {
11327 12 : grp->sibling = (*prev)->sibling;
11328 12 : (*prev)->sibling = grp;
11329 : }
11330 : else
11331 23839 : grpmap->put (fpp, grp);
11332 : }
11333 45175 : }
11334 :
11335 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11336 44691 : omp_index_mapping_groups (vec<omp_mapping_group> *groups)
11337 : {
11338 44691 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11339 44691 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11340 :
11341 44691 : omp_index_mapping_groups_1 (grpmap, groups, NULL_TREE);
11342 :
11343 44691 : return grpmap;
11344 : }
11345 :
11346 : /* Rebuild group map from partially-processed clause list (during
11347 : omp_build_struct_sibling_lists). We have already processed nodes up until
11348 : a high-water mark (HWM). This is a bit tricky because the list is being
11349 : reordered as it is scanned, but we know:
11350 :
11351 : 1. The list after HWM has not been touched yet, so we can reindex it safely.
11352 :
11353 : 2. The list before and including HWM has been altered, but remains
11354 : well-formed throughout the sibling-list building operation.
11355 :
11356 : so, we can do the reindex operation in two parts, on the processed and
11357 : then the unprocessed halves of the list. */
11358 :
11359 : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11360 318 : omp_reindex_mapping_groups (tree *list_p,
11361 : vec<omp_mapping_group> *groups,
11362 : vec<omp_mapping_group> *processed_groups,
11363 : tree sentinel)
11364 : {
11365 318 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11366 318 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11367 :
11368 318 : processed_groups->truncate (0);
11369 :
11370 318 : omp_gather_mapping_groups_1 (list_p, processed_groups, sentinel);
11371 318 : omp_index_mapping_groups_1 (grpmap, processed_groups, NULL_TREE);
11372 318 : if (sentinel)
11373 166 : omp_index_mapping_groups_1 (grpmap, groups, sentinel);
11374 :
11375 318 : return grpmap;
11376 : }
11377 :
11378 : /* Find the immediately-containing struct for a component ref (etc.)
11379 : expression EXPR. */
11380 :
11381 : static tree
11382 47995 : omp_containing_struct (tree expr)
11383 : {
11384 47995 : tree expr0 = expr;
11385 :
11386 47995 : STRIP_NOPS (expr);
11387 :
11388 : /* Note: don't strip NOPs unless we're also stripping off array refs or a
11389 : component ref. */
11390 47995 : if (TREE_CODE (expr) != ARRAY_REF && TREE_CODE (expr) != COMPONENT_REF)
11391 : return expr0;
11392 :
11393 27225 : while (TREE_CODE (expr) == ARRAY_REF)
11394 3675 : expr = TREE_OPERAND (expr, 0);
11395 :
11396 23550 : if (TREE_CODE (expr) == COMPONENT_REF)
11397 21096 : expr = TREE_OPERAND (expr, 0);
11398 :
11399 : return expr;
11400 : }
11401 :
11402 : /* Return TRUE if DECL describes a component that is part of a whole structure
11403 : that is mapped elsewhere in GRPMAP. *MAPPED_BY_GROUP is set to the group
11404 : that maps that structure, if present. */
11405 :
11406 : static bool
11407 25687 : omp_mapped_by_containing_struct (hash_map<tree_operand_hash_no_se,
11408 : omp_mapping_group *> *grpmap,
11409 : tree decl,
11410 : omp_mapping_group **mapped_by_group)
11411 : {
11412 25687 : tree wsdecl = NULL_TREE;
11413 :
11414 25687 : *mapped_by_group = NULL;
11415 :
11416 47995 : while (true)
11417 : {
11418 47995 : wsdecl = omp_containing_struct (decl);
11419 47995 : if (wsdecl == decl)
11420 : break;
11421 23550 : omp_mapping_group **wholestruct = grpmap->get (wsdecl);
11422 23550 : if (!wholestruct
11423 20978 : && TREE_CODE (wsdecl) == MEM_REF
11424 23551 : && integer_zerop (TREE_OPERAND (wsdecl, 1)))
11425 : {
11426 1 : tree deref = TREE_OPERAND (wsdecl, 0);
11427 1 : deref = build_fold_indirect_ref (deref);
11428 1 : wholestruct = grpmap->get (deref);
11429 : }
11430 23550 : if (wholestruct)
11431 : {
11432 : /* An intermediate descriptor should not match here because the
11433 : pointee is actually not mapped by this group -- it is just a
11434 : zero-length alloc. */
11435 2572 : tree desc = OMP_CLAUSE_CHAIN (*(*wholestruct)->grp_start);
11436 2572 : if (desc != NULL_TREE && omp_map_clause_descriptor_p (desc))
11437 1330 : goto next;
11438 1242 : *mapped_by_group = *wholestruct;
11439 1242 : return true;
11440 : }
11441 20978 : next:
11442 : decl = wsdecl;
11443 : }
11444 :
11445 : return false;
11446 : }
11447 :
11448 : /* Helper function for omp_tsort_mapping_groups. Returns TRUE on success, or
11449 : FALSE on error. */
11450 :
11451 : static bool
11452 20161 : omp_tsort_mapping_groups_1 (omp_mapping_group ***outlist,
11453 : vec<omp_mapping_group> *groups,
11454 : hash_map<tree_operand_hash_no_se,
11455 : omp_mapping_group *> *grpmap,
11456 : omp_mapping_group *grp)
11457 : {
11458 20161 : if (grp->mark == PERMANENT)
11459 : return true;
11460 16825 : if (grp->mark == TEMPORARY)
11461 : {
11462 0 : fprintf (stderr, "when processing group:\n");
11463 0 : debug_mapping_group (grp);
11464 0 : internal_error ("base pointer cycle detected");
11465 : return false;
11466 : }
11467 16825 : grp->mark = TEMPORARY;
11468 :
11469 16825 : tree attaches_to = omp_get_attachment (grp);
11470 :
11471 16825 : if (attaches_to)
11472 : {
11473 3092 : omp_mapping_group **basep = grpmap->get (attaches_to);
11474 :
11475 3092 : if (basep && *basep != grp)
11476 : {
11477 2920 : for (omp_mapping_group *w = *basep; w; w = w->sibling)
11478 1460 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11479 : return false;
11480 : }
11481 : }
11482 :
11483 16825 : tree decl = OMP_CLAUSE_DECL (*grp->grp_start);
11484 :
11485 23039 : while (decl)
11486 : {
11487 23039 : tree base = omp_get_base_pointer (decl);
11488 :
11489 23039 : if (!base)
11490 : break;
11491 :
11492 8975 : omp_mapping_group **innerp = grpmap->get (base);
11493 8975 : omp_mapping_group *wholestruct;
11494 :
11495 : /* We should treat whole-structure mappings as if all (pointer, in this
11496 : case) members are mapped as individual list items. Check if we have
11497 : such a whole-structure mapping, if we don't have an explicit reference
11498 : to the pointer member itself. */
11499 8975 : if (!innerp
11500 4166 : && TREE_CODE (base) == COMPONENT_REF
11501 11207 : && omp_mapped_by_containing_struct (grpmap, base, &wholestruct))
11502 : innerp = &wholestruct;
11503 :
11504 8975 : if (innerp && *innerp != grp)
11505 : {
11506 5534 : for (omp_mapping_group *w = *innerp; w; w = w->sibling)
11507 2773 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11508 0 : return false;
11509 : break;
11510 : }
11511 :
11512 6214 : decl = base;
11513 : }
11514 :
11515 16825 : grp->mark = PERMANENT;
11516 :
11517 : /* Emit grp to output list. */
11518 :
11519 16825 : **outlist = grp;
11520 16825 : *outlist = &grp->next;
11521 :
11522 16825 : return true;
11523 : }
11524 :
11525 : /* Topologically sort GROUPS, so that OMP 5.0-defined base pointers come
11526 : before mappings that use those pointers. This is an implementation of the
11527 : depth-first search algorithm, described e.g. at:
11528 :
11529 : https://en.wikipedia.org/wiki/Topological_sorting
11530 : */
11531 :
11532 : static omp_mapping_group *
11533 8522 : omp_tsort_mapping_groups (vec<omp_mapping_group> *groups,
11534 : hash_map<tree_operand_hash_no_se, omp_mapping_group *>
11535 : *grpmap,
11536 : bool enter_exit_data)
11537 : {
11538 8522 : omp_mapping_group *grp, *outlist = NULL, **cursor;
11539 8522 : unsigned int i;
11540 8522 : bool saw_runtime_implicit = false;
11541 :
11542 8522 : cursor = &outlist;
11543 :
11544 25347 : FOR_EACH_VEC_ELT (*groups, i, grp)
11545 : {
11546 16825 : if (grp->mark != PERMANENT)
11547 : {
11548 15952 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11549 : {
11550 683 : saw_runtime_implicit = true;
11551 683 : continue;
11552 : }
11553 15269 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11554 : return NULL;
11555 : }
11556 : }
11557 :
11558 8522 : if (!saw_runtime_implicit)
11559 8240 : return outlist;
11560 :
11561 1634 : FOR_EACH_VEC_ELT (*groups, i, grp)
11562 : {
11563 1352 : if (grp->mark != PERMANENT
11564 1352 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11565 : {
11566 : /* Clear the flag for enter/exit data because it is currently
11567 : meaningless for those operations in libgomp. */
11568 659 : if (enter_exit_data)
11569 446 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start) = 0;
11570 :
11571 659 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11572 : return NULL;
11573 : }
11574 : }
11575 :
11576 282 : return outlist;
11577 : }
11578 :
11579 : /* Split INLIST into three parts:
11580 :
11581 : - "present" alloc/to/from groups
11582 : - other to/from groups
11583 : - other alloc/release/delete groups
11584 :
11585 : These sub-lists are then concatenated together to form the final list.
11586 : Each sub-list retains the order of the original list.
11587 : Note that ATTACH nodes are later moved to the end of the list in
11588 : gimplify_adjust_omp_clauses, for target regions. */
11589 :
11590 : static omp_mapping_group *
11591 8522 : omp_segregate_mapping_groups (omp_mapping_group *inlist)
11592 : {
11593 8522 : omp_mapping_group *ard_groups = NULL, *tf_groups = NULL;
11594 8522 : omp_mapping_group *p_groups = NULL;
11595 8522 : omp_mapping_group **ard_tail = &ard_groups, **tf_tail = &tf_groups;
11596 8522 : omp_mapping_group **p_tail = &p_groups;
11597 :
11598 25347 : for (omp_mapping_group *w = inlist; w;)
11599 : {
11600 16825 : tree c = *w->grp_start;
11601 16825 : omp_mapping_group *next = w->next;
11602 :
11603 16825 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
11604 :
11605 16825 : switch (OMP_CLAUSE_MAP_KIND (c))
11606 : {
11607 1939 : case GOMP_MAP_ALLOC:
11608 1939 : case GOMP_MAP_RELEASE:
11609 1939 : case GOMP_MAP_DELETE:
11610 1939 : *ard_tail = w;
11611 1939 : w->next = NULL;
11612 1939 : ard_tail = &w->next;
11613 1939 : break;
11614 :
11615 : /* These map types are all semantically identical, so are moved into a
11616 : single group. They will each be changed into GOMP_MAP_FORCE_PRESENT
11617 : in gimplify_adjust_omp_clauses. */
11618 149 : case GOMP_MAP_PRESENT_ALLOC:
11619 149 : case GOMP_MAP_PRESENT_FROM:
11620 149 : case GOMP_MAP_PRESENT_TO:
11621 149 : case GOMP_MAP_PRESENT_TOFROM:
11622 149 : *p_tail = w;
11623 149 : w->next = NULL;
11624 149 : p_tail = &w->next;
11625 149 : break;
11626 :
11627 14737 : default:
11628 14737 : *tf_tail = w;
11629 14737 : w->next = NULL;
11630 14737 : tf_tail = &w->next;
11631 : }
11632 :
11633 : w = next;
11634 : }
11635 :
11636 : /* Now splice the lists together... */
11637 8522 : *tf_tail = ard_groups;
11638 8522 : *p_tail = tf_groups;
11639 :
11640 8522 : return p_groups;
11641 : }
11642 :
11643 : /* Given a list LIST_P containing groups of mappings given by GROUPS, reorder
11644 : those groups based on the output list of omp_tsort_mapping_groups --
11645 : singly-linked, threaded through each element's NEXT pointer starting at
11646 : HEAD. Each list element appears exactly once in that linked list.
11647 :
11648 : Each element of GROUPS may correspond to one or several mapping nodes.
11649 : Node groups are kept together, and in the reordered list, the positions of
11650 : the original groups are reused for the positions of the reordered list.
11651 : Hence if we have e.g.
11652 :
11653 : {to ptr ptr} firstprivate {tofrom ptr} ...
11654 : ^ ^ ^
11655 : first group non-"map" second group
11656 :
11657 : and say the second group contains a base pointer for the first so must be
11658 : moved before it, the resulting list will contain:
11659 :
11660 : {tofrom ptr} firstprivate {to ptr ptr} ...
11661 : ^ prev. second group ^ prev. first group
11662 : */
11663 :
11664 : static tree *
11665 8522 : omp_reorder_mapping_groups (vec<omp_mapping_group> *groups,
11666 : omp_mapping_group *head,
11667 : tree *list_p)
11668 : {
11669 8522 : omp_mapping_group *grp;
11670 8522 : unsigned int i;
11671 8522 : unsigned numgroups = groups->length ();
11672 8522 : auto_vec<tree> old_heads (numgroups);
11673 8522 : auto_vec<tree *> old_headps (numgroups);
11674 8522 : auto_vec<tree> new_heads (numgroups);
11675 8522 : auto_vec<tree> old_succs (numgroups);
11676 8522 : bool map_at_start = (list_p == (*groups)[0].grp_start);
11677 :
11678 8522 : tree *new_grp_tail = NULL;
11679 :
11680 : /* Stash the start & end nodes of each mapping group before we start
11681 : modifying the list. */
11682 25347 : FOR_EACH_VEC_ELT (*groups, i, grp)
11683 : {
11684 16825 : old_headps.quick_push (grp->grp_start);
11685 16825 : old_heads.quick_push (*grp->grp_start);
11686 16825 : old_succs.quick_push (OMP_CLAUSE_CHAIN (grp->grp_end));
11687 : }
11688 :
11689 : /* And similarly, the heads of the groups in the order we want to rearrange
11690 : the list to. */
11691 25347 : for (omp_mapping_group *w = head; w; w = w->next)
11692 16825 : new_heads.quick_push (*w->grp_start);
11693 :
11694 25347 : FOR_EACH_VEC_ELT (*groups, i, grp)
11695 : {
11696 16825 : gcc_assert (head);
11697 :
11698 16825 : if (new_grp_tail && old_succs[i - 1] == old_heads[i])
11699 : {
11700 : /* a {b c d} {e f g} h i j (original)
11701 : -->
11702 : a {k l m} {e f g} h i j (inserted new group on last iter)
11703 : -->
11704 : a {k l m} {n o p} h i j (this time, chain last group to new one)
11705 : ^new_grp_tail
11706 : */
11707 7681 : *new_grp_tail = new_heads[i];
11708 : }
11709 9144 : else if (new_grp_tail)
11710 : {
11711 : /* a {b c d} e {f g h} i j k (original)
11712 : -->
11713 : a {l m n} e {f g h} i j k (gap after last iter's group)
11714 : -->
11715 : a {l m n} e {o p q} h i j (chain last group to old successor)
11716 : ^new_grp_tail
11717 : */
11718 622 : *new_grp_tail = old_succs[i - 1];
11719 622 : *old_headps[i] = new_heads[i];
11720 : }
11721 : else
11722 : {
11723 : /* The first inserted group -- point to new group, and leave end
11724 : open.
11725 : a {b c d} e f
11726 : -->
11727 : a {g h i...
11728 : */
11729 8522 : *grp->grp_start = new_heads[i];
11730 : }
11731 :
11732 16825 : new_grp_tail = &OMP_CLAUSE_CHAIN (head->grp_end);
11733 :
11734 16825 : head = head->next;
11735 : }
11736 :
11737 8522 : if (new_grp_tail)
11738 8522 : *new_grp_tail = old_succs[numgroups - 1];
11739 :
11740 8522 : gcc_assert (!head);
11741 :
11742 11917 : return map_at_start ? (*groups)[0].grp_start : list_p;
11743 8522 : }
11744 :
11745 : /* DECL is supposed to have lastprivate semantics in the outer contexts
11746 : of combined/composite constructs, starting with OCTX.
11747 : Add needed lastprivate, shared or map clause if no data sharing or
11748 : mapping clause are present. IMPLICIT_P is true if it is an implicit
11749 : clause (IV on simd), in which case the lastprivate will not be
11750 : copied to some constructs. */
11751 :
11752 : static void
11753 14580 : omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx,
11754 : tree decl, bool implicit_p)
11755 : {
11756 14580 : struct gimplify_omp_ctx *orig_octx = octx;
11757 26901 : for (; octx; octx = octx->outer_context)
11758 : {
11759 25829 : if ((octx->region_type == ORT_COMBINED_PARALLEL
11760 20793 : || (octx->region_type & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS)
11761 25260 : && splay_tree_lookup (octx->variables,
11762 : (splay_tree_key) decl) == NULL)
11763 : {
11764 3887 : omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN);
11765 3887 : continue;
11766 : }
11767 18303 : if ((octx->region_type & ORT_TASK) != 0
11768 575 : && octx->combined_loop
11769 18584 : && splay_tree_lookup (octx->variables,
11770 : (splay_tree_key) decl) == NULL)
11771 : {
11772 248 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11773 248 : continue;
11774 : }
11775 22639 : if (implicit_p
11776 13619 : && octx->region_type == ORT_WORKSHARE
11777 10405 : && octx->combined_loop
11778 10300 : && splay_tree_lookup (octx->variables,
11779 : (splay_tree_key) decl) == NULL
11780 10300 : && octx->outer_context
11781 8907 : && octx->outer_context->region_type == ORT_COMBINED_PARALLEL
11782 22646 : && splay_tree_lookup (octx->outer_context->variables,
11783 : (splay_tree_key) decl) == NULL)
11784 : {
11785 4832 : octx = octx->outer_context;
11786 4832 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11787 4832 : continue;
11788 : }
11789 5493 : if ((octx->region_type == ORT_WORKSHARE || octx->region_type == ORT_ACC)
11790 7482 : && octx->combined_loop
11791 7295 : && splay_tree_lookup (octx->variables,
11792 : (splay_tree_key) decl) == NULL
11793 19000 : && !omp_check_private (octx, decl, false))
11794 : {
11795 3354 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11796 3354 : continue;
11797 : }
11798 9621 : if (octx->region_type == ORT_COMBINED_TARGET)
11799 : {
11800 2008 : splay_tree_node n = splay_tree_lookup (octx->variables,
11801 : (splay_tree_key) decl);
11802 2008 : if (n == NULL)
11803 : {
11804 1986 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11805 1986 : octx = octx->outer_context;
11806 : }
11807 22 : else if (!implicit_p
11808 22 : && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT))
11809 : {
11810 12 : n->value &= ~(GOVD_FIRSTPRIVATE
11811 : | GOVD_FIRSTPRIVATE_IMPLICIT
11812 : | GOVD_EXPLICIT);
11813 12 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11814 12 : octx = octx->outer_context;
11815 : }
11816 : }
11817 : break;
11818 : }
11819 14580 : if (octx && (implicit_p || octx != orig_octx))
11820 4046 : omp_notice_variable (octx, decl, true);
11821 14580 : }
11822 :
11823 : /* We might have indexed several groups for DECL, e.g. a "TO" mapping and also
11824 : a "FIRSTPRIVATE" mapping. Return the one that isn't firstprivate, etc. */
11825 :
11826 : static omp_mapping_group *
11827 5978 : omp_get_nonfirstprivate_group (hash_map<tree_operand_hash_no_se,
11828 : omp_mapping_group *> *grpmap,
11829 : tree decl, bool allow_deleted = false)
11830 : {
11831 5978 : omp_mapping_group **to_group_p = grpmap->get (decl);
11832 :
11833 5978 : if (!to_group_p)
11834 : return NULL;
11835 :
11836 2449 : omp_mapping_group *to_group = *to_group_p;
11837 :
11838 3776 : for (; to_group; to_group = to_group->sibling)
11839 : {
11840 2486 : tree grp_end = to_group->grp_end;
11841 2486 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
11842 : {
11843 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11844 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11845 : break;
11846 :
11847 1161 : default:
11848 1161 : if (allow_deleted || !to_group->deleted)
11849 : return to_group;
11850 : }
11851 : }
11852 :
11853 : return NULL;
11854 : }
11855 :
11856 : /* Return TRUE if the directive (whose clauses are described by the hash table
11857 : of mapping groups, GRPMAP) maps DECL explicitly. If TO_SPECIFICALLY is
11858 : true, only count TO mappings. If ALLOW_DELETED is true, ignore the
11859 : "deleted" flag for groups. If CONTAINED_IN_STRUCT is true, also return
11860 : TRUE if DECL is mapped as a member of a whole-struct mapping. */
11861 :
11862 : static bool
11863 4446 : omp_directive_maps_explicitly (hash_map<tree_operand_hash_no_se,
11864 : omp_mapping_group *> *grpmap,
11865 : tree decl, omp_mapping_group **base_group,
11866 : bool to_specifically, bool allow_deleted,
11867 : bool contained_in_struct)
11868 : {
11869 4446 : omp_mapping_group *decl_group
11870 4446 : = omp_get_nonfirstprivate_group (grpmap, decl, allow_deleted);
11871 :
11872 4446 : *base_group = NULL;
11873 :
11874 4446 : if (decl_group)
11875 : {
11876 1042 : tree grp_first = *decl_group->grp_start;
11877 : /* We might be called during omp_build_struct_sibling_lists, when
11878 : GOMP_MAP_STRUCT might have been inserted at the start of the group.
11879 : Skip over that, and also possibly the node after it. */
11880 1042 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT
11881 1042 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT_UNORD)
11882 : {
11883 6 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11884 6 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_FIRSTPRIVATE_POINTER
11885 6 : || (OMP_CLAUSE_MAP_KIND (grp_first)
11886 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11887 12 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_ATTACH_DETACH)
11888 0 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11889 : }
11890 1042 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
11891 1042 : if (!to_specifically
11892 592 : || GOMP_MAP_COPY_TO_P (first_kind)
11893 382 : || first_kind == GOMP_MAP_ALLOC)
11894 : {
11895 960 : *base_group = decl_group;
11896 960 : return true;
11897 : }
11898 : }
11899 :
11900 3486 : if (contained_in_struct
11901 3486 : && omp_mapped_by_containing_struct (grpmap, decl, base_group))
11902 : return true;
11903 :
11904 : return false;
11905 : }
11906 :
11907 : /* If we have mappings INNER and OUTER, where INNER is a component access and
11908 : OUTER is a mapping of the whole containing struct, check that the mappings
11909 : are compatible. We'll be deleting the inner mapping, so we need to make
11910 : sure the outer mapping does (at least) the same transfers to/from the device
11911 : as the inner mapping. */
11912 :
11913 : bool
11914 172 : omp_check_mapping_compatibility (location_t loc,
11915 : omp_mapping_group *outer,
11916 : omp_mapping_group *inner)
11917 : {
11918 172 : tree first_outer = *outer->grp_start, first_inner = *inner->grp_start;
11919 :
11920 172 : gcc_assert (OMP_CLAUSE_CODE (first_outer) == OMP_CLAUSE_MAP);
11921 172 : gcc_assert (OMP_CLAUSE_CODE (first_inner) == OMP_CLAUSE_MAP);
11922 :
11923 172 : enum gomp_map_kind outer_kind = OMP_CLAUSE_MAP_KIND (first_outer);
11924 172 : enum gomp_map_kind inner_kind = OMP_CLAUSE_MAP_KIND (first_inner);
11925 :
11926 172 : if (outer_kind == inner_kind)
11927 : return true;
11928 :
11929 70 : switch (outer_kind)
11930 : {
11931 0 : case GOMP_MAP_ALWAYS_TO:
11932 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11933 0 : || inner_kind == GOMP_MAP_ALLOC
11934 0 : || inner_kind == GOMP_MAP_TO)
11935 : return true;
11936 : break;
11937 :
11938 0 : case GOMP_MAP_ALWAYS_FROM:
11939 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11940 0 : || inner_kind == GOMP_MAP_RELEASE
11941 : || inner_kind == GOMP_MAP_FROM)
11942 : return true;
11943 : break;
11944 :
11945 10 : case GOMP_MAP_TO:
11946 10 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11947 10 : || inner_kind == GOMP_MAP_ALLOC)
11948 : return true;
11949 : break;
11950 :
11951 8 : case GOMP_MAP_FROM:
11952 8 : if (inner_kind == GOMP_MAP_RELEASE
11953 8 : || inner_kind == GOMP_MAP_FORCE_PRESENT)
11954 : return true;
11955 : break;
11956 :
11957 32 : case GOMP_MAP_ALWAYS_TOFROM:
11958 32 : case GOMP_MAP_TOFROM:
11959 32 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11960 32 : || inner_kind == GOMP_MAP_ALLOC
11961 : || inner_kind == GOMP_MAP_TO
11962 24 : || inner_kind == GOMP_MAP_FROM
11963 12 : || inner_kind == GOMP_MAP_TOFROM)
11964 : return true;
11965 : break;
11966 :
11967 28 : default:
11968 28 : ;
11969 : }
11970 :
11971 84 : error_at (loc, "data movement for component %qE is not compatible with "
11972 28 : "movement for struct %qE", OMP_CLAUSE_DECL (first_inner),
11973 28 : OMP_CLAUSE_DECL (first_outer));
11974 :
11975 28 : return false;
11976 : }
11977 :
11978 : /* This function handles several cases where clauses on a mapping directive
11979 : can interact with each other.
11980 :
11981 : If we have a FIRSTPRIVATE_POINTER node and we're also mapping the pointer
11982 : on the same directive, change the mapping of the first node to
11983 : ATTACH_DETACH. We should have detected that this will happen already in
11984 : c-omp.cc:c_omp_adjust_map_clauses and marked the appropriate decl
11985 : as addressable. (If we didn't, bail out.)
11986 :
11987 : If we have a FIRSTPRIVATE_REFERENCE (for a reference to pointer) and we're
11988 : mapping the base pointer also, we may need to change the mapping type to
11989 : ATTACH_DETACH and synthesize an alloc node for the reference itself.
11990 :
11991 : If we have an ATTACH_DETACH node, this is an array section with a pointer
11992 : base. If we're mapping the base on the same directive too, we can drop its
11993 : mapping. However, if we have a reference to pointer, make other appropriate
11994 : adjustments to the mapping nodes instead.
11995 :
11996 : If we have an ATTACH_DETACH node with a Fortran pointer-set (array
11997 : descriptor) mapping for a derived-type component, and we're also mapping the
11998 : whole of the derived-type variable on another clause, the pointer-set
11999 : mapping is removed.
12000 :
12001 : If we have a component access but we're also mapping the whole of the
12002 : containing struct, drop the former access.
12003 :
12004 : If the expression is a component access, and we're also mapping a base
12005 : pointer used in that component access in the same expression, change the
12006 : mapping type of the latter to ALLOC (ready for processing by
12007 : omp_build_struct_sibling_lists). */
12008 :
12009 : void
12010 8522 : omp_resolve_clause_dependencies (enum tree_code code,
12011 : vec<omp_mapping_group> *groups,
12012 : hash_map<tree_operand_hash_no_se,
12013 : omp_mapping_group *> *grpmap)
12014 : {
12015 8522 : int i;
12016 8522 : omp_mapping_group *grp;
12017 8522 : bool repair_chain = false;
12018 :
12019 24283 : FOR_EACH_VEC_ELT (*groups, i, grp)
12020 : {
12021 15761 : tree grp_end = grp->grp_end;
12022 15761 : tree decl = OMP_CLAUSE_DECL (grp_end);
12023 :
12024 15761 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12025 :
12026 15761 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
12027 : {
12028 1216 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
12029 1216 : {
12030 1216 : omp_mapping_group *to_group
12031 1216 : = omp_get_nonfirstprivate_group (grpmap, decl);
12032 :
12033 1216 : if (!to_group || to_group == grp)
12034 1191 : continue;
12035 :
12036 25 : tree grp_first = *to_group->grp_start;
12037 25 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12038 :
12039 25 : if ((GOMP_MAP_COPY_TO_P (first_kind)
12040 7 : || first_kind == GOMP_MAP_ALLOC)
12041 50 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12042 : != GOMP_MAP_FIRSTPRIVATE_POINTER))
12043 : {
12044 25 : gcc_assert (TREE_ADDRESSABLE (OMP_CLAUSE_DECL (grp_end)));
12045 25 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12046 : }
12047 : }
12048 : break;
12049 :
12050 160 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
12051 160 : {
12052 160 : tree ptr = build_fold_indirect_ref (decl);
12053 :
12054 160 : omp_mapping_group *to_group
12055 160 : = omp_get_nonfirstprivate_group (grpmap, ptr);
12056 :
12057 160 : if (!to_group || to_group == grp)
12058 156 : continue;
12059 :
12060 4 : tree grp_first = *to_group->grp_start;
12061 4 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12062 :
12063 4 : if (GOMP_MAP_COPY_TO_P (first_kind)
12064 4 : || first_kind == GOMP_MAP_ALLOC)
12065 : {
12066 4 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12067 4 : OMP_CLAUSE_DECL (grp_end) = ptr;
12068 4 : if ((OMP_CLAUSE_CHAIN (*to_group->grp_start)
12069 4 : == to_group->grp_end)
12070 4 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12071 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
12072 : {
12073 0 : gcc_assert (TREE_ADDRESSABLE
12074 : (OMP_CLAUSE_DECL (to_group->grp_end)));
12075 0 : OMP_CLAUSE_SET_MAP_KIND (to_group->grp_end,
12076 : GOMP_MAP_ATTACH_DETACH);
12077 :
12078 0 : location_t loc = OMP_CLAUSE_LOCATION (to_group->grp_end);
12079 0 : tree alloc
12080 0 : = build_omp_clause (loc, OMP_CLAUSE_MAP);
12081 0 : OMP_CLAUSE_SET_MAP_KIND (alloc, GOMP_MAP_ALLOC);
12082 0 : tree tmp = build_fold_addr_expr (OMP_CLAUSE_DECL
12083 : (to_group->grp_end));
12084 0 : tree char_ptr_type = build_pointer_type (char_type_node);
12085 0 : OMP_CLAUSE_DECL (alloc)
12086 0 : = build2 (MEM_REF, char_type_node,
12087 : tmp,
12088 : build_int_cst (char_ptr_type, 0));
12089 0 : OMP_CLAUSE_SIZE (alloc) = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
12090 :
12091 0 : OMP_CLAUSE_CHAIN (alloc)
12092 0 : = OMP_CLAUSE_CHAIN (*to_group->grp_start);
12093 0 : OMP_CLAUSE_CHAIN (*to_group->grp_start) = alloc;
12094 : }
12095 : }
12096 : }
12097 : break;
12098 :
12099 : case GOMP_MAP_ATTACH_DETACH:
12100 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
12101 : {
12102 2622 : tree base_ptr, referenced_ptr_node = NULL_TREE;
12103 :
12104 2622 : while (TREE_CODE (decl) == ARRAY_REF)
12105 0 : decl = TREE_OPERAND (decl, 0);
12106 :
12107 2622 : if (TREE_CODE (decl) == INDIRECT_REF)
12108 13 : decl = TREE_OPERAND (decl, 0);
12109 :
12110 : /* Only component accesses. */
12111 2622 : if (DECL_P (decl))
12112 226 : continue;
12113 :
12114 : /* We want the pointer itself when checking if the base pointer is
12115 : mapped elsewhere in the same directive -- if we have a
12116 : reference to the pointer, don't use that. */
12117 :
12118 2396 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12119 2396 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12120 : {
12121 394 : referenced_ptr_node = OMP_CLAUSE_CHAIN (*grp->grp_start);
12122 394 : base_ptr = OMP_CLAUSE_DECL (referenced_ptr_node);
12123 : }
12124 : else
12125 : base_ptr = decl;
12126 :
12127 1978 : gomp_map_kind zlas_kind
12128 2396 : = (code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
12129 2396 : ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION;
12130 :
12131 2396 : if (TREE_CODE (TREE_TYPE (base_ptr)) == POINTER_TYPE)
12132 : {
12133 : /* If we map the base TO, and we're doing an attachment, we can
12134 : skip the TO mapping altogether and create an ALLOC mapping
12135 : instead, since the attachment will overwrite the device
12136 : pointer in that location immediately anyway. Otherwise,
12137 : change our mapping to
12138 : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION in case the
12139 : attachment target has not been copied to the device already
12140 : by some earlier directive. */
12141 :
12142 1972 : bool base_mapped_to = false;
12143 :
12144 1972 : omp_mapping_group *base_group;
12145 :
12146 1972 : if (omp_directive_maps_explicitly (grpmap, base_ptr,
12147 : &base_group, false, true,
12148 : false))
12149 : {
12150 450 : if (referenced_ptr_node)
12151 : {
12152 129 : base_mapped_to = true;
12153 129 : if ((OMP_CLAUSE_MAP_KIND (base_group->grp_end)
12154 : == GOMP_MAP_ATTACH_DETACH)
12155 129 : && (OMP_CLAUSE_CHAIN (*base_group->grp_start)
12156 : == base_group->grp_end))
12157 : {
12158 258 : OMP_CLAUSE_CHAIN (*base_group->grp_start)
12159 129 : = OMP_CLAUSE_CHAIN (base_group->grp_end);
12160 129 : base_group->grp_end = *base_group->grp_start;
12161 129 : repair_chain = true;
12162 : }
12163 : }
12164 : else
12165 : {
12166 321 : base_group->deleted = true;
12167 321 : OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end) = 1;
12168 : }
12169 : }
12170 :
12171 : /* We're dealing with a reference to a pointer, and we are
12172 : attaching both the reference and the pointer. We know the
12173 : reference itself is on the target, because we are going to
12174 : create an ALLOC node for it in accumulate_sibling_list. The
12175 : pointer might be on the target already or it might not, but
12176 : if it isn't then it's not an error, so use
12177 : GOMP_MAP_ATTACH_ZLAS for it. */
12178 1972 : if (!base_mapped_to && referenced_ptr_node)
12179 56 : OMP_CLAUSE_SET_MAP_KIND (referenced_ptr_node, zlas_kind);
12180 :
12181 1972 : omp_mapping_group *struct_group;
12182 1972 : tree desc;
12183 1972 : if ((desc = OMP_CLAUSE_CHAIN (*grp->grp_start))
12184 1972 : && omp_map_clause_descriptor_p (desc)
12185 3050 : && omp_mapped_by_containing_struct (grpmap, decl,
12186 : &struct_group))
12187 : /* If we have a pointer set but we're mapping (or unmapping)
12188 : the whole of the containing struct, we can remove the
12189 : pointer set mapping. */
12190 15 : OMP_CLAUSE_CHAIN (*grp->grp_start) = OMP_CLAUSE_CHAIN (desc);
12191 : }
12192 424 : else if (TREE_CODE (TREE_TYPE (base_ptr)) == REFERENCE_TYPE
12193 424 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (base_ptr)))
12194 : == ARRAY_TYPE)
12195 562 : && OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION
12196 : (*grp->grp_start))
12197 92 : OMP_CLAUSE_SET_MAP_KIND (grp->grp_end, zlas_kind);
12198 : }
12199 : break;
12200 :
12201 : case GOMP_MAP_ATTACH:
12202 : /* Ignore standalone attach here. */
12203 : break;
12204 :
12205 11700 : default:
12206 11700 : {
12207 11700 : omp_mapping_group *struct_group;
12208 11700 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12209 11700 : && *grp->grp_start == grp_end)
12210 : {
12211 94 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12212 : struct_group, grp);
12213 : /* Remove the whole of this mapping -- redundant. */
12214 94 : grp->deleted = true;
12215 : }
12216 :
12217 : tree base = decl;
12218 13308 : while ((base = omp_get_base_pointer (base)))
12219 : {
12220 1608 : omp_mapping_group *base_group;
12221 :
12222 1608 : if (omp_directive_maps_explicitly (grpmap, base, &base_group,
12223 : true, true, false))
12224 : {
12225 343 : tree grp_first = *base_group->grp_start;
12226 343 : OMP_CLAUSE_SET_MAP_KIND (grp_first, GOMP_MAP_ALLOC);
12227 : }
12228 : }
12229 : }
12230 : }
12231 : }
12232 :
12233 8522 : if (repair_chain)
12234 : {
12235 : /* Group start pointers may have become detached from the
12236 : OMP_CLAUSE_CHAIN of previous groups if elements were removed from the
12237 : end of those groups. Fix that now. */
12238 : tree *new_next = NULL;
12239 716 : FOR_EACH_VEC_ELT (*groups, i, grp)
12240 : {
12241 587 : if (new_next)
12242 458 : grp->grp_start = new_next;
12243 :
12244 587 : new_next = &OMP_CLAUSE_CHAIN (grp->grp_end);
12245 : }
12246 : }
12247 8522 : }
12248 :
12249 : /* Similar to omp_resolve_clause_dependencies, but for OpenACC. The only
12250 : clause dependencies we handle for now are struct element mappings and
12251 : whole-struct mappings on the same directive, and duplicate clause
12252 : detection. */
12253 :
12254 : void
12255 9462 : oacc_resolve_clause_dependencies (vec<omp_mapping_group> *groups,
12256 : hash_map<tree_operand_hash_no_se,
12257 : omp_mapping_group *> *grpmap)
12258 : {
12259 9462 : int i;
12260 9462 : omp_mapping_group *grp;
12261 9462 : hash_set<tree_operand_hash> *seen_components = NULL;
12262 9462 : hash_set<tree_operand_hash> *shown_error = NULL;
12263 :
12264 24643 : FOR_EACH_VEC_ELT (*groups, i, grp)
12265 : {
12266 15181 : tree grp_end = grp->grp_end;
12267 15181 : tree decl = OMP_CLAUSE_DECL (grp_end);
12268 :
12269 15181 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12270 :
12271 15181 : if (DECL_P (grp_end))
12272 14664 : continue;
12273 :
12274 15181 : tree c = OMP_CLAUSE_DECL (*grp->grp_start);
12275 16806 : while (TREE_CODE (c) == ARRAY_REF)
12276 1625 : c = TREE_OPERAND (c, 0);
12277 15181 : if (TREE_CODE (c) != COMPONENT_REF)
12278 14664 : continue;
12279 517 : if (!seen_components)
12280 474 : seen_components = new hash_set<tree_operand_hash> ();
12281 517 : if (!shown_error)
12282 474 : shown_error = new hash_set<tree_operand_hash> ();
12283 517 : if (seen_components->contains (c)
12284 517 : && !shown_error->contains (c))
12285 : {
12286 10 : error_at (OMP_CLAUSE_LOCATION (grp_end),
12287 : "%qE appears more than once in map clauses",
12288 5 : OMP_CLAUSE_DECL (grp_end));
12289 5 : shown_error->add (c);
12290 : }
12291 : else
12292 512 : seen_components->add (c);
12293 :
12294 517 : omp_mapping_group *struct_group;
12295 517 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12296 517 : && *grp->grp_start == grp_end)
12297 : {
12298 78 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12299 : struct_group, grp);
12300 : /* Remove the whole of this mapping -- redundant. */
12301 78 : grp->deleted = true;
12302 : }
12303 : }
12304 :
12305 9462 : if (seen_components)
12306 474 : delete seen_components;
12307 9462 : if (shown_error)
12308 474 : delete shown_error;
12309 9462 : }
12310 :
12311 : /* Link node NEWNODE so it is pointed to by chain INSERT_AT. NEWNODE's chain
12312 : is linked to the previous node pointed to by INSERT_AT. */
12313 :
12314 : static tree *
12315 1133 : omp_siblist_insert_node_after (tree newnode, tree *insert_at)
12316 : {
12317 1133 : OMP_CLAUSE_CHAIN (newnode) = *insert_at;
12318 1133 : *insert_at = newnode;
12319 1133 : return &OMP_CLAUSE_CHAIN (newnode);
12320 : }
12321 :
12322 : /* Move NODE (which is currently pointed to by the chain OLD_POS) so it is
12323 : pointed to by chain MOVE_AFTER instead. */
12324 :
12325 : static void
12326 1320 : omp_siblist_move_node_after (tree node, tree *old_pos, tree *move_after)
12327 : {
12328 1320 : gcc_assert (node == *old_pos);
12329 1320 : *old_pos = OMP_CLAUSE_CHAIN (node);
12330 1320 : OMP_CLAUSE_CHAIN (node) = *move_after;
12331 1320 : *move_after = node;
12332 1320 : }
12333 :
12334 : /* Move nodes from FIRST_PTR (pointed to by previous node's chain) to
12335 : LAST_NODE to after MOVE_AFTER chain. Similar to below function, but no
12336 : new nodes are prepended to the list before splicing into the new position.
12337 : Return the position we should continue scanning the list at, or NULL to
12338 : stay where we were. */
12339 :
12340 : static tree *
12341 254 : omp_siblist_move_nodes_after (tree *first_ptr, tree last_node,
12342 : tree *move_after)
12343 : {
12344 254 : if (first_ptr == move_after)
12345 : return NULL;
12346 :
12347 243 : tree tmp = *first_ptr;
12348 243 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12349 243 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12350 243 : *move_after = tmp;
12351 :
12352 243 : return first_ptr;
12353 : }
12354 :
12355 : /* Concatenate two lists described by [FIRST_NEW, LAST_NEW_TAIL] and
12356 : [FIRST_PTR, LAST_NODE], and insert them in the OMP clause list after chain
12357 : pointer MOVE_AFTER.
12358 :
12359 : The latter list was previously part of the OMP clause list, and the former
12360 : (prepended) part is comprised of new nodes.
12361 :
12362 : We start with a list of nodes starting with a struct mapping node. We
12363 : rearrange the list so that new nodes starting from FIRST_NEW and whose last
12364 : node's chain is LAST_NEW_TAIL comes directly after MOVE_AFTER, followed by
12365 : the group of mapping nodes we are currently processing (from the chain
12366 : FIRST_PTR to LAST_NODE). The return value is the pointer to the next chain
12367 : we should continue processing from, or NULL to stay where we were.
12368 :
12369 : The transformation (in the case where MOVE_AFTER and FIRST_PTR are
12370 : different) is worked through below. Here we are processing LAST_NODE, and
12371 : FIRST_PTR points at the preceding mapping clause:
12372 :
12373 : #. mapping node chain
12374 : ---------------------------------------------------
12375 : A. struct_node [->B]
12376 : B. comp_1 [->C]
12377 : C. comp_2 [->D (move_after)]
12378 : D. map_to_3 [->E]
12379 : E. attach_3 [->F (first_ptr)]
12380 : F. map_to_4 [->G (continue_at)]
12381 : G. attach_4 (last_node) [->H]
12382 : H. ...
12383 :
12384 : *last_new_tail = *first_ptr;
12385 :
12386 : I. new_node (first_new) [->F (last_new_tail)]
12387 :
12388 : *first_ptr = OMP_CLAUSE_CHAIN (last_node)
12389 :
12390 : #. mapping node chain
12391 : ----------------------------------------------------
12392 : A. struct_node [->B]
12393 : B. comp_1 [->C]
12394 : C. comp_2 [->D (move_after)]
12395 : D. map_to_3 [->E]
12396 : E. attach_3 [->H (first_ptr)]
12397 : F. map_to_4 [->G (continue_at)]
12398 : G. attach_4 (last_node) [->H]
12399 : H. ...
12400 :
12401 : I. new_node (first_new) [->F (last_new_tail)]
12402 :
12403 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12404 :
12405 : #. mapping node chain
12406 : ---------------------------------------------------
12407 : A. struct_node [->B]
12408 : B. comp_1 [->C]
12409 : C. comp_2 [->D (move_after)]
12410 : D. map_to_3 [->E]
12411 : E. attach_3 [->H (continue_at)]
12412 : F. map_to_4 [->G]
12413 : G. attach_4 (last_node) [->D]
12414 : H. ...
12415 :
12416 : I. new_node (first_new) [->F (last_new_tail)]
12417 :
12418 : *move_after = first_new;
12419 :
12420 : #. mapping node chain
12421 : ---------------------------------------------------
12422 : A. struct_node [->B]
12423 : B. comp_1 [->C]
12424 : C. comp_2 [->I (move_after)]
12425 : D. map_to_3 [->E]
12426 : E. attach_3 [->H (continue_at)]
12427 : F. map_to_4 [->G]
12428 : G. attach_4 (last_node) [->D]
12429 : H. ...
12430 : I. new_node (first_new) [->F (last_new_tail)]
12431 :
12432 : or, in order:
12433 :
12434 : #. mapping node chain
12435 : ---------------------------------------------------
12436 : A. struct_node [->B]
12437 : B. comp_1 [->C]
12438 : C. comp_2 [->I (move_after)]
12439 : I. new_node (first_new) [->F (last_new_tail)]
12440 : F. map_to_4 [->G]
12441 : G. attach_4 (last_node) [->D]
12442 : D. map_to_3 [->E]
12443 : E. attach_3 [->H (continue_at)]
12444 : H. ...
12445 : */
12446 :
12447 : static tree *
12448 71 : omp_siblist_move_concat_nodes_after (tree first_new, tree *last_new_tail,
12449 : tree *first_ptr, tree last_node,
12450 : tree *move_after)
12451 : {
12452 71 : tree *continue_at = NULL;
12453 71 : *last_new_tail = *first_ptr;
12454 71 : if (first_ptr == move_after)
12455 12 : *move_after = first_new;
12456 : else
12457 : {
12458 59 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12459 59 : continue_at = first_ptr;
12460 59 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12461 59 : *move_after = first_new;
12462 : }
12463 71 : return continue_at;
12464 : }
12465 :
12466 : static omp_addr_token *
12467 11541 : omp_first_chained_access_token (vec<omp_addr_token *> &addr_tokens)
12468 : {
12469 11541 : using namespace omp_addr_tokenizer;
12470 11541 : int idx = addr_tokens.length () - 1;
12471 11541 : gcc_assert (idx >= 0);
12472 11541 : if (addr_tokens[idx]->type != ACCESS_METHOD)
12473 : return addr_tokens[idx];
12474 11568 : while (idx > 0 && addr_tokens[idx - 1]->type == ACCESS_METHOD)
12475 : idx--;
12476 11541 : return addr_tokens[idx];
12477 : }
12478 :
12479 : /* Mapping struct members causes an additional set of nodes to be created,
12480 : starting with GOMP_MAP_STRUCT followed by a number of mappings equal to the
12481 : number of members being mapped, in order of ascending position (address or
12482 : bitwise).
12483 :
12484 : We scan through the list of mapping clauses, calling this function for each
12485 : struct member mapping we find, and build up the list of mappings after the
12486 : initial GOMP_MAP_STRUCT node. For pointer members, these will be
12487 : newly-created ALLOC nodes. For non-pointer members, the existing mapping is
12488 : moved into place in the sorted list.
12489 :
12490 : struct {
12491 : int *a;
12492 : int *b;
12493 : int c;
12494 : int *d;
12495 : };
12496 :
12497 : #pragma (acc|omp directive) copy(struct.a[0:n], struct.b[0:n], struct.c,
12498 : struct.d[0:n])
12499 :
12500 : GOMP_MAP_STRUCT (4)
12501 : [GOMP_MAP_FIRSTPRIVATE_REFERENCE -- for refs to structs]
12502 : GOMP_MAP_ALLOC (struct.a)
12503 : GOMP_MAP_ALLOC (struct.b)
12504 : GOMP_MAP_TO (struct.c)
12505 : GOMP_MAP_ALLOC (struct.d)
12506 : ...
12507 :
12508 : In the case where we are mapping references to pointers, or in Fortran if
12509 : we are mapping an array with a descriptor, additional nodes may be created
12510 : after the struct node list also.
12511 :
12512 : The return code is either a pointer to the next node to process (if the
12513 : list has been rearranged), else NULL to continue with the next node in the
12514 : original list. */
12515 :
12516 : static tree *
12517 4765 : omp_accumulate_sibling_list (enum omp_region_type region_type,
12518 : enum tree_code code,
12519 : hash_map<tree_operand_hash, tree>
12520 : *&struct_map_to_clause,
12521 : hash_map<tree_operand_hash_no_se,
12522 : omp_mapping_group *> *group_map,
12523 : tree *grp_start_p, tree grp_end,
12524 : vec<omp_addr_token *> &addr_tokens, tree **inner,
12525 : bool *fragile_p, bool reprocessing_struct,
12526 : tree **added_tail)
12527 : {
12528 4765 : using namespace omp_addr_tokenizer;
12529 4765 : poly_offset_int coffset;
12530 4765 : poly_int64 cbitpos;
12531 4765 : tree ocd = OMP_CLAUSE_DECL (grp_end);
12532 4765 : bool openmp = !(region_type & ORT_ACC);
12533 4765 : bool target = (region_type & ORT_TARGET) != 0;
12534 4765 : tree *continue_at = NULL;
12535 :
12536 5078 : while (TREE_CODE (ocd) == ARRAY_REF)
12537 313 : ocd = TREE_OPERAND (ocd, 0);
12538 :
12539 4765 : if (*fragile_p)
12540 : {
12541 156 : omp_mapping_group *to_group
12542 156 : = omp_get_nonfirstprivate_group (group_map, ocd, true);
12543 :
12544 156 : if (to_group)
12545 : return NULL;
12546 : }
12547 :
12548 4677 : omp_addr_token *last_token = omp_first_chained_access_token (addr_tokens);
12549 4677 : if (last_token->type == ACCESS_METHOD)
12550 : {
12551 4677 : switch (last_token->u.access_kind)
12552 : {
12553 735 : case ACCESS_REF:
12554 735 : case ACCESS_REF_TO_POINTER:
12555 735 : case ACCESS_REF_TO_POINTER_OFFSET:
12556 735 : case ACCESS_INDEXED_REF_TO_ARRAY:
12557 : /* We may see either a bare reference or a dereferenced
12558 : "convert_from_reference"-like one here. Handle either way. */
12559 735 : if (TREE_CODE (ocd) == INDIRECT_REF)
12560 64 : ocd = TREE_OPERAND (ocd, 0);
12561 735 : gcc_assert (TREE_CODE (TREE_TYPE (ocd)) == REFERENCE_TYPE);
12562 : break;
12563 :
12564 : default:
12565 : ;
12566 : }
12567 : }
12568 :
12569 4677 : bool variable_offset;
12570 9354 : tree iterators = OMP_CLAUSE_HAS_ITERATORS (grp_end)
12571 4710 : ? OMP_CLAUSE_ITERATORS (grp_end) : NULL_TREE;
12572 4677 : tree base
12573 4677 : = extract_base_bit_offset (ocd, &cbitpos, &coffset, &variable_offset,
12574 4677 : iterators);
12575 :
12576 4677 : int base_token;
12577 23897 : for (base_token = addr_tokens.length () - 1; base_token >= 0; base_token--)
12578 : {
12579 19220 : if (addr_tokens[base_token]->type == ARRAY_BASE
12580 19220 : || addr_tokens[base_token]->type == STRUCTURE_BASE)
12581 : break;
12582 : }
12583 :
12584 : /* The two expressions in the assertion below aren't quite the same: if we
12585 : have 'struct_base_decl access_indexed_array' for something like
12586 : "myvar[2].x" then base will be "myvar" and addr_tokens[base_token]->expr
12587 : will be "myvar[2]" -- the actual base of the structure.
12588 : The former interpretation leads to a strange situation where we get
12589 : struct(myvar) alloc(myvar[2].ptr1)
12590 : That is, the array of structures is kind of treated as one big structure
12591 : for the purposes of gathering sibling lists, etc. */
12592 : /* gcc_assert (base == addr_tokens[base_token]->expr); */
12593 :
12594 4677 : bool attach_detach = ((OMP_CLAUSE_MAP_KIND (grp_end)
12595 : == GOMP_MAP_ATTACH_DETACH)
12596 4677 : || (OMP_CLAUSE_MAP_KIND (grp_end)
12597 4677 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
12598 4677 : bool has_descriptor = false;
12599 4677 : if (OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
12600 : {
12601 3137 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
12602 3137 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
12603 : has_descriptor = true;
12604 : }
12605 :
12606 4677 : if (!struct_map_to_clause || struct_map_to_clause->get (base) == NULL)
12607 : {
12608 3058 : enum gomp_map_kind str_kind = GOMP_MAP_STRUCT;
12609 :
12610 3058 : if (struct_map_to_clause == NULL)
12611 2495 : struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
12612 :
12613 3058 : if (variable_offset)
12614 274 : str_kind = GOMP_MAP_STRUCT_UNORD;
12615 :
12616 3058 : tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
12617 :
12618 3058 : OMP_CLAUSE_SET_MAP_KIND (l, str_kind);
12619 3058 : OMP_CLAUSE_DECL (l) = unshare_expr (base);
12620 3058 : OMP_CLAUSE_SIZE (l) = size_int (1);
12621 :
12622 3058 : struct_map_to_clause->put (base, l);
12623 :
12624 : /* On first iterating through the clause list, we insert the struct node
12625 : just before the component access node that triggers the initial
12626 : omp_accumulate_sibling_list call for a particular sibling list (and
12627 : it then forms the first entry in that list). When reprocessing
12628 : struct bases that are themselves component accesses, we insert the
12629 : struct node on an off-side list to avoid inserting the new
12630 : GOMP_MAP_STRUCT into the middle of the old one. */
12631 3058 : tree *insert_node_pos = reprocessing_struct ? *added_tail : grp_start_p;
12632 :
12633 3058 : if (has_descriptor)
12634 : {
12635 759 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
12636 759 : if (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
12637 187 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
12638 759 : tree sc = *insert_node_pos;
12639 759 : OMP_CLAUSE_CHAIN (l) = desc;
12640 759 : OMP_CLAUSE_CHAIN (*grp_start_p) = OMP_CLAUSE_CHAIN (desc);
12641 759 : OMP_CLAUSE_CHAIN (desc) = sc;
12642 759 : *insert_node_pos = l;
12643 : }
12644 2299 : else if (attach_detach)
12645 : {
12646 1396 : tree extra_node;
12647 1396 : tree alloc_node
12648 1396 : = build_omp_struct_comp_nodes (code, *grp_start_p, grp_end,
12649 : &extra_node);
12650 1396 : tree *tail;
12651 1396 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12652 :
12653 1396 : if (extra_node)
12654 : {
12655 0 : OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos;
12656 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
12657 0 : tail = &OMP_CLAUSE_CHAIN (extra_node);
12658 : }
12659 : else
12660 : {
12661 1396 : OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
12662 1396 : tail = &OMP_CLAUSE_CHAIN (alloc_node);
12663 : }
12664 :
12665 : /* For OpenMP semantics, we don't want to implicitly allocate
12666 : space for the pointer here for non-compute regions (e.g. "enter
12667 : data"). A FRAGILE_P node is only being created so that
12668 : omp-low.cc is able to rewrite the struct properly.
12669 : For references (to pointers), we want to actually allocate the
12670 : space for the reference itself in the sorted list following the
12671 : struct node.
12672 : For pointers, we want to allocate space if we had an explicit
12673 : mapping of the attachment point, but not otherwise. */
12674 1396 : if (*fragile_p
12675 1396 : || (openmp
12676 : && !target
12677 : && attach_detach
12678 234 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
12679 88 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
12680 : {
12681 133 : if (!lang_GNU_Fortran ())
12682 : /* In Fortran, pointers are dereferenced automatically, but may
12683 : be unassociated. So we still want to allocate space for the
12684 : pointer (as the base for an attach operation that should be
12685 : present in the same directive's clause list also). */
12686 103 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
12687 133 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
12688 : }
12689 :
12690 1396 : *insert_node_pos = l;
12691 :
12692 1396 : if (reprocessing_struct)
12693 : {
12694 : /* When reprocessing a struct node group used as the base of a
12695 : subcomponent access, if we have a reference-to-pointer base,
12696 : we will see:
12697 : struct(**ptr) attach(*ptr)
12698 : whereas for a non-reprocess-struct group, we see, e.g.:
12699 : tofrom(**ptr) attach(*ptr) attach(ptr)
12700 : and we create the "alloc" for the second "attach", i.e.
12701 : for the reference itself. When reprocessing a struct group we
12702 : thus change the pointer attachment into a reference attachment
12703 : by stripping the indirection. (The attachment of the
12704 : referenced pointer must happen elsewhere, either on the same
12705 : directive, or otherwise.) */
12706 180 : tree adecl = OMP_CLAUSE_DECL (alloc_node);
12707 :
12708 180 : if ((TREE_CODE (adecl) == INDIRECT_REF
12709 148 : || (TREE_CODE (adecl) == MEM_REF
12710 0 : && integer_zerop (TREE_OPERAND (adecl, 1))))
12711 32 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (adecl, 0)))
12712 : == REFERENCE_TYPE)
12713 212 : && (TREE_CODE (TREE_TYPE (TREE_TYPE
12714 : (TREE_OPERAND (adecl, 0)))) == POINTER_TYPE))
12715 32 : OMP_CLAUSE_DECL (alloc_node) = TREE_OPERAND (adecl, 0);
12716 :
12717 180 : *added_tail = tail;
12718 : }
12719 : }
12720 : else
12721 : {
12722 903 : gcc_assert (*grp_start_p == grp_end);
12723 903 : if (reprocessing_struct)
12724 : {
12725 : /* If we don't have an attach/detach node, this is a
12726 : "target data" directive or similar, not an offload region.
12727 : Synthesize an "alloc" node using just the initiating
12728 : GOMP_MAP_STRUCT decl. */
12729 16 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
12730 32 : || code == OACC_EXIT_DATA)
12731 32 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
12732 32 : tree alloc_node
12733 32 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12734 : OMP_CLAUSE_MAP);
12735 32 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
12736 32 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
12737 64 : OMP_CLAUSE_SIZE (alloc_node)
12738 32 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
12739 :
12740 32 : OMP_CLAUSE_CHAIN (alloc_node) = OMP_CLAUSE_CHAIN (l);
12741 32 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12742 32 : *insert_node_pos = l;
12743 32 : *added_tail = &OMP_CLAUSE_CHAIN (alloc_node);
12744 : }
12745 : else
12746 871 : grp_start_p = omp_siblist_insert_node_after (l, insert_node_pos);
12747 : }
12748 :
12749 3058 : unsigned last_access = base_token + 1;
12750 :
12751 3058 : while (last_access + 1 < addr_tokens.length ()
12752 3393 : && addr_tokens[last_access + 1]->type == ACCESS_METHOD)
12753 : last_access++;
12754 :
12755 3058 : if ((region_type & ORT_TARGET)
12756 3058 : && addr_tokens[base_token + 1]->type == ACCESS_METHOD)
12757 : {
12758 1708 : bool base_ref = false;
12759 1708 : access_method_kinds access_kind
12760 1708 : = addr_tokens[last_access]->u.access_kind;
12761 :
12762 1708 : switch (access_kind)
12763 : {
12764 : case ACCESS_DIRECT:
12765 : case ACCESS_INDEXED_ARRAY:
12766 1060 : return NULL;
12767 :
12768 403 : case ACCESS_REF:
12769 403 : case ACCESS_REF_TO_POINTER:
12770 403 : case ACCESS_REF_TO_POINTER_OFFSET:
12771 403 : case ACCESS_INDEXED_REF_TO_ARRAY:
12772 403 : base_ref = true;
12773 403 : break;
12774 :
12775 866 : default:
12776 866 : ;
12777 : }
12778 866 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12779 : OMP_CLAUSE_MAP);
12780 866 : enum gomp_map_kind mkind;
12781 866 : omp_mapping_group *decl_group;
12782 866 : tree use_base;
12783 866 : switch (access_kind)
12784 : {
12785 463 : case ACCESS_POINTER:
12786 463 : case ACCESS_POINTER_OFFSET:
12787 463 : use_base = addr_tokens[last_access]->expr;
12788 463 : break;
12789 198 : case ACCESS_REF_TO_POINTER:
12790 198 : case ACCESS_REF_TO_POINTER_OFFSET:
12791 198 : use_base
12792 198 : = build_fold_indirect_ref (addr_tokens[last_access]->expr);
12793 198 : break;
12794 205 : default:
12795 205 : use_base = addr_tokens[base_token]->expr;
12796 : }
12797 866 : bool mapped_to_p
12798 866 : = omp_directive_maps_explicitly (group_map, use_base, &decl_group,
12799 : true, false, true);
12800 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12801 866 : && DECL_P (addr_tokens[last_access]->expr)
12802 1372 : && !mapped_to_p)
12803 444 : mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
12804 : : GOMP_MAP_FIRSTPRIVATE_POINTER;
12805 : else
12806 : mkind = GOMP_MAP_ATTACH_DETACH;
12807 :
12808 866 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
12809 : /* If we have a reference to pointer base, we want to attach the
12810 : pointer here, not the reference. The reference attachment happens
12811 : elsewhere. */
12812 866 : bool ref_to_ptr
12813 866 : = (access_kind == ACCESS_REF_TO_POINTER
12814 866 : || access_kind == ACCESS_REF_TO_POINTER_OFFSET);
12815 866 : tree sdecl = addr_tokens[last_access]->expr;
12816 866 : tree sdecl_ptr = ref_to_ptr ? build_fold_indirect_ref (sdecl)
12817 : : sdecl;
12818 : /* For the FIRSTPRIVATE_REFERENCE after the struct node, we
12819 : want to use the reference itself for the decl, but we
12820 : still want to use the pointer to calculate the bias. */
12821 866 : OMP_CLAUSE_DECL (c2) = (mkind == GOMP_MAP_ATTACH_DETACH)
12822 866 : ? sdecl_ptr : sdecl;
12823 866 : sdecl = sdecl_ptr;
12824 866 : tree baddr = build_fold_addr_expr (base);
12825 866 : baddr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12826 : ptrdiff_type_node, baddr);
12827 866 : tree decladdr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12828 : ptrdiff_type_node, sdecl);
12829 866 : OMP_CLAUSE_SIZE (c2)
12830 866 : = fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR,
12831 : ptrdiff_type_node, baddr, decladdr);
12832 : /* Insert after struct node. */
12833 866 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
12834 866 : OMP_CLAUSE_CHAIN (l) = c2;
12835 :
12836 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12837 866 : && (addr_tokens[base_token]->u.structure_base_kind
12838 : == BASE_COMPONENT_EXPR)
12839 286 : && mkind == GOMP_MAP_ATTACH_DETACH
12840 1152 : && addr_tokens[last_access]->u.access_kind != ACCESS_REF)
12841 : {
12842 218 : *inner = insert_node_pos;
12843 218 : if (openmp)
12844 166 : *fragile_p = true;
12845 218 : return NULL;
12846 : }
12847 : }
12848 :
12849 1998 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12850 1998 : && (addr_tokens[base_token]->u.structure_base_kind
12851 : == BASE_COMPONENT_EXPR)
12852 2465 : && addr_tokens[last_access]->u.access_kind == ACCESS_REF)
12853 100 : *inner = insert_node_pos;
12854 :
12855 1998 : return NULL;
12856 : }
12857 1619 : else if (struct_map_to_clause)
12858 : {
12859 1619 : tree *osc = struct_map_to_clause->get (base);
12860 1619 : tree *sc = NULL, *scp = NULL;
12861 :
12862 1619 : unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
12863 1619 : sc = &OMP_CLAUSE_CHAIN (*osc);
12864 : /* The struct mapping might be immediately followed by a
12865 : FIRSTPRIVATE_POINTER, FIRSTPRIVATE_REFERENCE or an ATTACH_DETACH --
12866 : if it's an indirect access or a reference, or if the structure base
12867 : is not a decl. The FIRSTPRIVATE_* nodes are removed in omp-low.cc
12868 : after they have been processed there, and ATTACH_DETACH nodes are
12869 : recomputed and moved out of the GOMP_MAP_STRUCT construct once
12870 : sibling list building is complete. */
12871 1619 : if (OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_POINTER
12872 1574 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
12873 3148 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_ATTACH_DETACH)
12874 201 : sc = &OMP_CLAUSE_CHAIN (*sc);
12875 4108 : for (i = 0; i < elems; i++, sc = &OMP_CLAUSE_CHAIN (*sc))
12876 3062 : if (attach_detach && sc == grp_start_p)
12877 : break;
12878 3062 : else if (TREE_CODE (OMP_CLAUSE_DECL (*sc)) != COMPONENT_REF
12879 182 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != INDIRECT_REF
12880 3244 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != ARRAY_REF)
12881 : break;
12882 : else
12883 : {
12884 3062 : tree sc_decl = OMP_CLAUSE_DECL (*sc);
12885 3062 : poly_offset_int offset;
12886 3062 : poly_int64 bitpos;
12887 :
12888 3062 : if (TREE_CODE (sc_decl) == ARRAY_REF)
12889 : {
12890 366 : while (TREE_CODE (sc_decl) == ARRAY_REF)
12891 184 : sc_decl = TREE_OPERAND (sc_decl, 0);
12892 182 : if (TREE_CODE (sc_decl) != COMPONENT_REF
12893 182 : || TREE_CODE (TREE_TYPE (sc_decl)) != ARRAY_TYPE)
12894 : break;
12895 : }
12896 2880 : else if (INDIRECT_REF_P (sc_decl)
12897 0 : && TREE_CODE (TREE_OPERAND (sc_decl, 0)) == COMPONENT_REF
12898 2880 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (sc_decl, 0)))
12899 : == REFERENCE_TYPE))
12900 0 : sc_decl = TREE_OPERAND (sc_decl, 0);
12901 :
12902 3062 : bool variable_offset2;
12903 3062 : tree iterators2 = OMP_CLAUSE_HAS_ITERATORS (*sc)
12904 3062 : ? OMP_CLAUSE_ITERATORS (*sc) : NULL_TREE;
12905 :
12906 3062 : tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset,
12907 : &variable_offset2,
12908 : iterators2);
12909 3062 : if (!base2 || !operand_equal_p (base2, base, 0))
12910 : break;
12911 3062 : if (scp)
12912 469 : continue;
12913 2842 : if (variable_offset2)
12914 : {
12915 341 : OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
12916 :
12917 341 : if (has_descriptor)
12918 : {
12919 : /* Sort mapped components by offset. This is needed for
12920 : libgomp to handle Fortran derived-type allocatable
12921 : components transparently. */
12922 :
12923 323 : poly_int64 bitsize;
12924 323 : tree offset, coffset;
12925 323 : machine_mode mode;
12926 323 : int unsignedp, reversep, volatilep;
12927 323 : tree inner_ref1
12928 323 : = get_inner_reference (sc_decl, &bitsize, &bitpos,
12929 : &offset, &mode, &unsignedp,
12930 : &reversep, &volatilep);
12931 323 : tree osc_decl = ocd;
12932 323 : STRIP_NOPS (osc_decl);
12933 323 : tree inner_ref2
12934 323 : = get_inner_reference (osc_decl, &bitsize, &bitpos,
12935 : &coffset, &mode, &unsignedp,
12936 : &reversep, &volatilep);
12937 323 : gcc_assert (operand_equal_p (inner_ref1, inner_ref2, 0));
12938 323 : tree offset_diff
12939 323 : = fold_binary_to_constant (MINUS_EXPR, size_type_node,
12940 : coffset, offset);
12941 572 : if (offset_diff == NULL_TREE
12942 323 : || TREE_INT_CST_ELT (offset_diff, 0) > 0)
12943 249 : continue;
12944 : else
12945 : break;
12946 : }
12947 : }
12948 2501 : else if ((region_type & ORT_ACC) != 0)
12949 : {
12950 : /* For OpenACC, allow (ignore) duplicate struct accesses in
12951 : the middle of a mapping clause, e.g. "mystruct->foo" in:
12952 : copy(mystruct->foo->bar) copy(mystruct->foo->qux). */
12953 223 : if (reprocessing_struct
12954 8 : && known_eq (coffset, offset)
12955 223 : && known_eq (cbitpos, bitpos))
12956 16 : return NULL;
12957 : }
12958 2278 : else if (known_eq (coffset, offset)
12959 2278 : && known_eq (cbitpos, bitpos))
12960 : {
12961 : /* Having two struct members at the same offset doesn't work,
12962 : so make sure we don't. (We're allowed to ignore this.
12963 : Should we report the error?) */
12964 : /*error_at (OMP_CLAUSE_LOCATION (grp_end),
12965 : "duplicate struct member %qE in map clauses",
12966 : OMP_CLAUSE_DECL (grp_end));*/
12967 : return NULL;
12968 : }
12969 2503 : if (maybe_lt (coffset, offset)
12970 4231 : || (known_eq (coffset, offset)
12971 20 : && maybe_lt (cbitpos, bitpos)))
12972 : {
12973 775 : if (attach_detach)
12974 : scp = sc;
12975 : else
12976 : break;
12977 : }
12978 : }
12979 :
12980 1603 : OMP_CLAUSE_SIZE (*osc)
12981 1603 : = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
12982 :
12983 1603 : if (reprocessing_struct)
12984 : {
12985 : /* If we're reprocessing a struct node, we don't want to do most of
12986 : the list manipulation below. We only need to handle the (pointer
12987 : or reference) attach/detach case. */
12988 8 : tree extra_node, alloc_node;
12989 8 : if (has_descriptor)
12990 0 : gcc_unreachable ();
12991 8 : else if (attach_detach)
12992 8 : alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
12993 : grp_end, &extra_node);
12994 : else
12995 : {
12996 : /* If we don't have an attach/detach node, this is a
12997 : "target data" directive or similar, not an offload region.
12998 : Synthesize an "alloc" node using just the initiating
12999 : GOMP_MAP_STRUCT decl. */
13000 0 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
13001 0 : || code == OACC_EXIT_DATA)
13002 0 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
13003 0 : alloc_node
13004 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
13005 : OMP_CLAUSE_MAP);
13006 0 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
13007 0 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
13008 0 : OMP_CLAUSE_SIZE (alloc_node)
13009 0 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
13010 : }
13011 :
13012 8 : if (scp)
13013 0 : omp_siblist_insert_node_after (alloc_node, scp);
13014 : else
13015 : {
13016 8 : tree *new_end = omp_siblist_insert_node_after (alloc_node, sc);
13017 8 : if (sc == *added_tail)
13018 8 : *added_tail = new_end;
13019 : }
13020 :
13021 8 : return NULL;
13022 : }
13023 :
13024 1595 : if (has_descriptor)
13025 : {
13026 538 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
13027 538 : if (code == OMP_TARGET_EXIT_DATA
13028 538 : || code == OACC_EXIT_DATA)
13029 105 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
13030 1076 : omp_siblist_move_node_after (desc,
13031 538 : &OMP_CLAUSE_CHAIN (*grp_start_p),
13032 : scp ? scp : sc);
13033 : }
13034 1057 : else if (attach_detach)
13035 : {
13036 325 : tree cl = NULL_TREE, extra_node;
13037 325 : tree alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
13038 : grp_end, &extra_node);
13039 325 : tree *tail_chain = NULL;
13040 :
13041 325 : if (*fragile_p
13042 325 : || (openmp
13043 : && !target
13044 : && attach_detach
13045 62 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
13046 23 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
13047 : {
13048 6 : if (!lang_GNU_Fortran ())
13049 6 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
13050 6 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
13051 : }
13052 :
13053 : /* Here, we have:
13054 :
13055 : grp_end : the last (or only) node in this group.
13056 : grp_start_p : pointer to the first node in a pointer mapping group
13057 : up to and including GRP_END.
13058 : sc : pointer to the chain for the end of the struct component
13059 : list.
13060 : scp : pointer to the chain for the sorted position at which we
13061 : should insert in the middle of the struct component list
13062 : (else NULL to insert at end).
13063 : alloc_node : the "alloc" node for the structure (pointer-type)
13064 : component. We insert at SCP (if present), else SC
13065 : (the end of the struct component list).
13066 : extra_node : a newly-synthesized node for an additional indirect
13067 : pointer mapping or a Fortran pointer set, if needed.
13068 : cl : first node to prepend before grp_start_p.
13069 : tail_chain : pointer to chain of last prepended node.
13070 :
13071 : The general idea is we move the nodes for this struct mapping
13072 : together: the alloc node goes into the sorted list directly after
13073 : the struct mapping, and any extra nodes (together with the nodes
13074 : mapping arrays pointed to by struct components) get moved after
13075 : that list. When SCP is NULL, we insert the nodes at SC, i.e. at
13076 : the end of the struct component mapping list. It's important that
13077 : the alloc_node comes first in that case because it's part of the
13078 : sorted component mapping list (but subsequent nodes are not!). */
13079 :
13080 325 : if (scp)
13081 254 : omp_siblist_insert_node_after (alloc_node, scp);
13082 :
13083 : /* Make [cl,tail_chain] a list of the alloc node (if we haven't
13084 : already inserted it) and the extra_node (if it is present). The
13085 : list can be empty if we added alloc_node above and there is no
13086 : extra node. */
13087 254 : if (scp && extra_node)
13088 : {
13089 0 : cl = extra_node;
13090 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13091 : }
13092 325 : else if (extra_node)
13093 : {
13094 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
13095 0 : cl = alloc_node;
13096 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13097 : }
13098 325 : else if (!scp)
13099 : {
13100 71 : cl = alloc_node;
13101 71 : tail_chain = &OMP_CLAUSE_CHAIN (alloc_node);
13102 : }
13103 :
13104 325 : continue_at
13105 71 : = cl ? omp_siblist_move_concat_nodes_after (cl, tail_chain,
13106 : grp_start_p, grp_end,
13107 : sc)
13108 254 : : omp_siblist_move_nodes_after (grp_start_p, grp_end, sc);
13109 : }
13110 732 : else if (*sc != grp_end)
13111 : {
13112 692 : gcc_assert (*grp_start_p == grp_end);
13113 :
13114 : /* We are moving the current node back to a previous struct node:
13115 : the node that used to point to the current node will now point to
13116 : the next node. */
13117 692 : continue_at = grp_start_p;
13118 : /* In the non-pointer case, the mapping clause itself is moved into
13119 : the correct position in the struct component list, which in this
13120 : case is just SC. */
13121 692 : omp_siblist_move_node_after (*grp_start_p, grp_start_p, sc);
13122 : }
13123 : }
13124 : return continue_at;
13125 : }
13126 :
13127 : /* Scan through GROUPS, and create sorted structure sibling lists without
13128 : gimplifying. */
13129 :
13130 : static bool
13131 17984 : omp_build_struct_sibling_lists (enum tree_code code,
13132 : enum omp_region_type region_type,
13133 : vec<omp_mapping_group> *groups,
13134 : hash_map<tree_operand_hash_no_se,
13135 : omp_mapping_group *> **grpmap,
13136 : tree *list_p)
13137 : {
13138 17984 : using namespace omp_addr_tokenizer;
13139 17984 : unsigned i;
13140 17984 : omp_mapping_group *grp;
13141 17984 : hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
13142 17984 : bool success = true;
13143 17984 : tree *new_next = NULL;
13144 35968 : tree *tail = &OMP_CLAUSE_CHAIN ((*groups)[groups->length () - 1].grp_end);
13145 17984 : tree added_nodes = NULL_TREE;
13146 17984 : tree *added_tail = &added_nodes;
13147 17984 : auto_vec<omp_mapping_group> pre_hwm_groups;
13148 :
13149 67228 : FOR_EACH_VEC_ELT (*groups, i, grp)
13150 : {
13151 31260 : tree c = grp->grp_end;
13152 31260 : tree decl = OMP_CLAUSE_DECL (c);
13153 31260 : tree grp_end = grp->grp_end;
13154 31260 : auto_vec<omp_addr_token *> addr_tokens;
13155 31260 : tree sentinel = OMP_CLAUSE_CHAIN (grp_end);
13156 :
13157 31260 : if (new_next && !grp->reprocess_struct)
13158 622 : grp->grp_start = new_next;
13159 :
13160 31260 : new_next = NULL;
13161 :
13162 31260 : tree *grp_start_p = grp->grp_start;
13163 :
13164 31260 : if (DECL_P (decl))
13165 21127 : continue;
13166 :
13167 : /* Skip groups we marked for deletion in
13168 : {omp,oacc}_resolve_clause_dependencies. */
13169 10133 : if (grp->deleted)
13170 462 : continue;
13171 :
13172 9671 : if (OMP_CLAUSE_CHAIN (*grp_start_p)
13173 9671 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
13174 : {
13175 : /* Don't process an array descriptor that isn't inside a derived type
13176 : as a struct (the GOMP_MAP_POINTER following will have the form
13177 : "var.data", but such mappings are handled specially). */
13178 6111 : tree grpmid = OMP_CLAUSE_CHAIN (*grp_start_p);
13179 6111 : if (omp_map_clause_descriptor_p (grpmid)
13180 10262 : && DECL_P (OMP_CLAUSE_DECL (grpmid)))
13181 2807 : continue;
13182 : }
13183 :
13184 : tree expr = decl;
13185 :
13186 7877 : while (TREE_CODE (expr) == ARRAY_REF)
13187 1013 : expr = TREE_OPERAND (expr, 0);
13188 :
13189 6864 : if (!omp_parse_expr (addr_tokens, expr))
13190 0 : continue;
13191 :
13192 6864 : omp_addr_token *last_token
13193 6864 : = omp_first_chained_access_token (addr_tokens);
13194 :
13195 : /* A mapping of a reference to a pointer member that doesn't specify an
13196 : array section, etc., like this:
13197 : *mystruct.ref_to_ptr
13198 : should not be processed by the struct sibling-list handling code --
13199 : it just transfers the referenced pointer.
13200 :
13201 : In contrast, the quite similar-looking construct:
13202 : *mystruct.ptr
13203 : which is equivalent to e.g.
13204 : mystruct.ptr[0]
13205 : *does* trigger sibling-list processing.
13206 :
13207 : An exception for the former case is for "fragile" groups where the
13208 : reference itself is not handled otherwise; this is subject to special
13209 : handling in omp_accumulate_sibling_list also. */
13210 :
13211 6864 : if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
13212 3398 : && last_token->type == ACCESS_METHOD
13213 3398 : && last_token->u.access_kind == ACCESS_REF
13214 7146 : && !grp->fragile)
13215 217 : continue;
13216 :
13217 6647 : tree d = decl;
13218 6647 : if (TREE_CODE (d) == ARRAY_REF)
13219 : {
13220 1974 : while (TREE_CODE (d) == ARRAY_REF)
13221 998 : d = TREE_OPERAND (d, 0);
13222 976 : if (TREE_CODE (d) == COMPONENT_REF
13223 976 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
13224 : decl = d;
13225 : }
13226 6647 : if (d == decl
13227 5982 : && INDIRECT_REF_P (decl)
13228 734 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
13229 105 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
13230 : == REFERENCE_TYPE)
13231 6744 : && (OMP_CLAUSE_MAP_KIND (c)
13232 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
13233 97 : decl = TREE_OPERAND (decl, 0);
13234 :
13235 6647 : STRIP_NOPS (decl);
13236 :
13237 6647 : if (TREE_CODE (decl) != COMPONENT_REF)
13238 1343 : continue;
13239 :
13240 : /* If we're mapping the whole struct in another node, skip adding this
13241 : node to a sibling list. */
13242 5304 : omp_mapping_group *wholestruct;
13243 5304 : if (omp_mapped_by_containing_struct (*grpmap, OMP_CLAUSE_DECL (c),
13244 : &wholestruct))
13245 : {
13246 178 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
13247 161 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
13248 178 : continue;
13249 : }
13250 :
13251 5126 : if (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
13252 5126 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
13253 5023 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
13254 : && code != OACC_UPDATE
13255 10082 : && code != OMP_TARGET_UPDATE)
13256 : {
13257 4765 : if (error_operand_p (decl))
13258 : {
13259 0 : success = false;
13260 0 : goto error_out;
13261 : }
13262 :
13263 4765 : tree stype = TREE_TYPE (decl);
13264 4765 : if (TREE_CODE (stype) == REFERENCE_TYPE)
13265 768 : stype = TREE_TYPE (stype);
13266 4765 : if (TYPE_SIZE_UNIT (stype) == NULL
13267 4765 : || TREE_CODE (TYPE_SIZE_UNIT (stype)) != INTEGER_CST)
13268 : {
13269 0 : error_at (OMP_CLAUSE_LOCATION (c),
13270 : "mapping field %qE of variable length "
13271 0 : "structure", OMP_CLAUSE_DECL (c));
13272 0 : success = false;
13273 0 : goto error_out;
13274 : }
13275 :
13276 4765 : tree *inner = NULL;
13277 4765 : bool fragile_p = grp->fragile;
13278 :
13279 4765 : new_next
13280 9530 : = omp_accumulate_sibling_list (region_type, code,
13281 : struct_map_to_clause, *grpmap,
13282 : grp_start_p, grp_end, addr_tokens,
13283 : &inner, &fragile_p,
13284 4765 : grp->reprocess_struct, &added_tail);
13285 :
13286 4765 : if (inner)
13287 : {
13288 318 : omp_mapping_group newgrp;
13289 318 : newgrp.grp_start = inner;
13290 318 : if (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (*inner))
13291 : == GOMP_MAP_ATTACH_DETACH)
13292 286 : newgrp.grp_end = OMP_CLAUSE_CHAIN (*inner);
13293 : else
13294 32 : newgrp.grp_end = *inner;
13295 318 : newgrp.mark = UNVISITED;
13296 318 : newgrp.sibling = NULL;
13297 318 : newgrp.deleted = false;
13298 318 : newgrp.reprocess_struct = true;
13299 318 : newgrp.fragile = fragile_p;
13300 318 : newgrp.next = NULL;
13301 318 : groups->safe_push (newgrp);
13302 :
13303 : /* !!! Growing GROUPS might invalidate the pointers in the group
13304 : map. Rebuild it here. This is a bit inefficient, but
13305 : shouldn't happen very often. */
13306 636 : delete (*grpmap);
13307 318 : *grpmap
13308 318 : = omp_reindex_mapping_groups (list_p, groups, &pre_hwm_groups,
13309 : sentinel);
13310 : }
13311 : }
13312 31260 : }
13313 :
13314 : /* Delete groups marked for deletion above. At this point the order of the
13315 : groups may no longer correspond to the order of the underlying list,
13316 : which complicates this a little. First clear out OMP_CLAUSE_DECL for
13317 : deleted nodes... */
13318 :
13319 49244 : FOR_EACH_VEC_ELT (*groups, i, grp)
13320 31260 : if (grp->deleted)
13321 462 : for (tree d = *grp->grp_start;
13322 924 : d != OMP_CLAUSE_CHAIN (grp->grp_end);
13323 462 : d = OMP_CLAUSE_CHAIN (d))
13324 462 : OMP_CLAUSE_DECL (d) = NULL_TREE;
13325 :
13326 : /* ...then sweep through the list removing the now-empty nodes. */
13327 :
13328 : tail = list_p;
13329 95930 : while (*tail)
13330 : {
13331 77946 : if (OMP_CLAUSE_CODE (*tail) == OMP_CLAUSE_MAP
13332 77946 : && OMP_CLAUSE_DECL (*tail) == NULL_TREE)
13333 462 : *tail = OMP_CLAUSE_CHAIN (*tail);
13334 : else
13335 77484 : tail = &OMP_CLAUSE_CHAIN (*tail);
13336 : }
13337 :
13338 : /* Tack on the struct nodes added during nested struct reprocessing. */
13339 17984 : if (added_nodes)
13340 : {
13341 192 : *tail = added_nodes;
13342 192 : tail = added_tail;
13343 : }
13344 :
13345 : /* Find each attach node whose bias needs to be adjusted and move it to the
13346 : group containing its pointee, right after the struct node, so that it can
13347 : be picked up by the adjustment code further down in this function. */
13348 17984 : bool attach_bias_needs_adjustment;
13349 17984 : attach_bias_needs_adjustment = false;
13350 67228 : FOR_EACH_VEC_ELT_REVERSE (*groups, i, grp)
13351 : {
13352 31260 : tree c = *grp->grp_start;
13353 30321 : if (c != NULL && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13354 30306 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
13355 27235 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
13356 3351 : && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c)) == GOMP_MAP_TO_PSET
13357 560 : && OMP_CLAUSE_MAP_KIND (grp->grp_end) == GOMP_MAP_ATTACH_DETACH
13358 31820 : && OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end))
13359 : {
13360 90 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (grp->grp_end) = 0;
13361 90 : attach_bias_needs_adjustment = true;
13362 90 : tree *cp;
13363 90 : for (cp = &OMP_CLAUSE_CHAIN (c); cp != NULL;
13364 206 : cp = &OMP_CLAUSE_CHAIN (*cp))
13365 296 : if (*cp == grp->grp_end)
13366 : {
13367 : c = *cp;
13368 : break;
13369 : }
13370 :
13371 90 : tree base = OMP_CLAUSE_DECL (c);
13372 90 : gcc_assert (TREE_CODE (base) == NOP_EXPR);
13373 90 : base = build_fold_indirect_ref (base);
13374 90 : tree *struct_node = struct_map_to_clause->get (base);
13375 90 : omp_siblist_move_node_after (c, cp, &OMP_CLAUSE_CHAIN (*struct_node));
13376 : }
13377 : }
13378 :
13379 : /* Now we have finished building the struct sibling lists, reprocess
13380 : newly-added "attach" nodes: we need the address of the first
13381 : mapped element of each struct sibling list for the bias of the attach
13382 : operation -- not necessarily the base address of the whole struct. */
13383 17984 : if (struct_map_to_clause)
13384 5553 : for (hash_map<tree_operand_hash, tree>::iterator iter
13385 2495 : = struct_map_to_clause->begin ();
13386 8048 : iter != struct_map_to_clause->end ();
13387 3058 : ++iter)
13388 : {
13389 3058 : tree struct_node = (*iter).second;
13390 3058 : gcc_assert (OMP_CLAUSE_CODE (struct_node) == OMP_CLAUSE_MAP);
13391 3058 : tree attach = OMP_CLAUSE_CHAIN (struct_node);
13392 :
13393 3058 : if (OMP_CLAUSE_CODE (attach) != OMP_CLAUSE_MAP
13394 3058 : || OMP_CLAUSE_MAP_KIND (attach) != GOMP_MAP_ATTACH_DETACH)
13395 2546 : continue;
13396 :
13397 512 : OMP_CLAUSE_SET_MAP_KIND (attach, GOMP_MAP_ATTACH);
13398 :
13399 : /* Sanity check: the standalone attach node will not work if we have
13400 : an "enter data" operation (because for those, variables need to be
13401 : mapped separately and attach nodes must be grouped together with the
13402 : base they attach to). We should only have created the
13403 : ATTACH_DETACH node either after GOMP_MAP_STRUCT for a target region
13404 : or for an intermediate descriptor that needs adjustment -- so this
13405 : should never be true. */
13406 512 : gcc_assert ((region_type & ORT_TARGET) != 0
13407 : || attach_bias_needs_adjustment);
13408 :
13409 : /* This is the first sorted node in the struct sibling list. Use it
13410 : to recalculate the correct bias to use.
13411 : (&first_node - attach_decl).
13412 : For GOMP_MAP_STRUCT_UNORD, we need e.g. the
13413 : min(min(min(first,second),third),fourth) element, because the
13414 : elements aren't in any particular order. */
13415 512 : tree lowest_addr;
13416 512 : if (OMP_CLAUSE_MAP_KIND (struct_node) == GOMP_MAP_STRUCT_UNORD)
13417 : {
13418 94 : tree first_node = OMP_CLAUSE_CHAIN (attach);
13419 94 : unsigned HOST_WIDE_INT num_mappings
13420 94 : = tree_to_uhwi (OMP_CLAUSE_SIZE (struct_node));
13421 94 : lowest_addr = OMP_CLAUSE_DECL (first_node);
13422 94 : lowest_addr = build_fold_addr_expr (lowest_addr);
13423 94 : lowest_addr = fold_convert (pointer_sized_int_node, lowest_addr);
13424 94 : tree next_node = OMP_CLAUSE_CHAIN (first_node);
13425 185 : while (num_mappings > 1)
13426 : {
13427 91 : tree tmp = OMP_CLAUSE_DECL (next_node);
13428 91 : tmp = build_fold_addr_expr (tmp);
13429 91 : tmp = fold_convert (pointer_sized_int_node, tmp);
13430 91 : lowest_addr = fold_build2 (MIN_EXPR, pointer_sized_int_node,
13431 : lowest_addr, tmp);
13432 91 : next_node = OMP_CLAUSE_CHAIN (next_node);
13433 91 : num_mappings--;
13434 : }
13435 94 : lowest_addr = fold_convert (ptrdiff_type_node, lowest_addr);
13436 : }
13437 : else
13438 : {
13439 418 : tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
13440 418 : first_node = build_fold_addr_expr (first_node);
13441 418 : lowest_addr = fold_convert (ptrdiff_type_node, first_node);
13442 : }
13443 512 : tree attach_decl = OMP_CLAUSE_DECL (attach);
13444 512 : attach_decl = fold_convert (ptrdiff_type_node, attach_decl);
13445 512 : OMP_CLAUSE_SIZE (attach)
13446 512 : = fold_build2 (MINUS_EXPR, ptrdiff_type_node, lowest_addr,
13447 : attach_decl);
13448 :
13449 : /* Remove GOMP_MAP_ATTACH node from after struct node. */
13450 512 : OMP_CLAUSE_CHAIN (struct_node) = OMP_CLAUSE_CHAIN (attach);
13451 : /* ...and re-insert it at the end of our clause list. */
13452 512 : *tail = attach;
13453 512 : OMP_CLAUSE_CHAIN (attach) = NULL_TREE;
13454 512 : tail = &OMP_CLAUSE_CHAIN (attach);
13455 : }
13456 :
13457 15489 : error_out:
13458 17984 : if (struct_map_to_clause)
13459 2495 : delete struct_map_to_clause;
13460 :
13461 17984 : return success;
13462 17984 : }
13463 :
13464 : struct instantiate_mapper_info
13465 : {
13466 : tree *mapper_clauses_p;
13467 : struct gimplify_omp_ctx *omp_ctx;
13468 : gimple_seq *pre_p;
13469 : };
13470 :
13471 : /* Helper function for omp_instantiate_mapper. */
13472 :
13473 : static tree
13474 1592 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
13475 : {
13476 1592 : copy_body_data *id = (copy_body_data *) data;
13477 :
13478 1592 : if (DECL_P (*tp))
13479 : {
13480 724 : tree replacement = remap_decl (*tp, id);
13481 724 : if (*tp != replacement)
13482 : {
13483 369 : *tp = unshare_expr (replacement);
13484 369 : *walk_subtrees = 0;
13485 : }
13486 : }
13487 :
13488 1592 : return NULL_TREE;
13489 : }
13490 :
13491 : /* A copy_decl implementation (for use with tree-inline.cc functions) that
13492 : only transform decls or SSA names that are part of a map we already
13493 : prepared. */
13494 :
13495 : static tree
13496 126 : omp_mapper_copy_decl (tree var, copy_body_data *cb)
13497 : {
13498 126 : tree *repl = cb->decl_map->get (var);
13499 :
13500 126 : if (repl)
13501 0 : return *repl;
13502 :
13503 126 : return var;
13504 : }
13505 :
13506 : static tree *
13507 90 : omp_instantiate_mapper (gimple_seq *pre_p,
13508 : hash_map<omp_name_type<tree>, tree> *implicit_mappers,
13509 : tree mapperfn, tree expr, enum gomp_map_kind outer_kind,
13510 : tree *mapper_clauses_p)
13511 : {
13512 90 : tree mapper_name = NULL_TREE;
13513 90 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapperfn);
13514 90 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
13515 :
13516 90 : tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
13517 90 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
13518 :
13519 : /* The "extraction map" is used to map the mapper variable in the "declare
13520 : mapper" directive, and also any temporary variables that have been created
13521 : as part of expanding the mapper function's body (which are expanded as a
13522 : "bind" expression in the pre_p sequence). */
13523 90 : hash_map<tree, tree> extraction_map;
13524 :
13525 90 : extraction_map.put (dummy_var, expr);
13526 90 : extraction_map.put (expr, expr);
13527 :
13528 : /* This copy_body_data is only used to remap the decls in the
13529 : OMP_DECLARE_MAPPER tree node expansion itself. All relevant decls should
13530 : already be in the current function. */
13531 90 : copy_body_data id;
13532 90 : memset (&id, 0, sizeof (id));
13533 90 : id.src_fn = current_function_decl;
13534 90 : id.dst_fn = current_function_decl;
13535 90 : id.src_cfun = cfun;
13536 90 : id.decl_map = &extraction_map;
13537 90 : id.copy_decl = omp_mapper_copy_decl;
13538 90 : id.transform_call_graph_edges = CB_CGE_DUPLICATE; // ???
13539 90 : id.transform_new_cfg = true; // ???
13540 :
13541 282 : for (; clause; clause = OMP_CLAUSE_CHAIN (clause))
13542 : {
13543 192 : enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (clause);
13544 192 : tree *nested_mapper_p = NULL;
13545 :
13546 192 : if (map_kind == GOMP_MAP_PUSH_MAPPER_NAME)
13547 : {
13548 0 : mapper_name = OMP_CLAUSE_DECL (clause);
13549 25 : continue;
13550 : }
13551 192 : else if (map_kind == GOMP_MAP_POP_MAPPER_NAME)
13552 : {
13553 0 : mapper_name = NULL_TREE;
13554 0 : continue;
13555 : }
13556 :
13557 192 : if (OMP_CLAUSE_HAS_ITERATORS (clause))
13558 : {
13559 2 : sorry_at (OMP_CLAUSE_LOCATION (clause),
13560 : "user-defined mapper that uses a %<map%> clause "
13561 : "with %<iterator%>");
13562 2 : continue;
13563 : }
13564 :
13565 190 : tree decl = OMP_CLAUSE_DECL (clause);
13566 190 : tree unshared, type;
13567 190 : bool nonunit_array_with_mapper = false;
13568 :
13569 190 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
13570 : {
13571 62 : location_t loc = OMP_CLAUSE_LOCATION (clause);
13572 62 : tree tmp = lang_hooks.decls.omp_map_array_section (loc, decl);
13573 62 : if (tmp == decl)
13574 : {
13575 48 : unshared = unshare_expr (clause);
13576 48 : nonunit_array_with_mapper = true;
13577 48 : type = TREE_TYPE (TREE_TYPE (decl));
13578 : }
13579 : else
13580 : {
13581 14 : unshared = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
13582 14 : OMP_CLAUSE_CODE (clause));
13583 14 : OMP_CLAUSE_DECL (unshared) = tmp;
13584 14 : OMP_CLAUSE_SIZE (unshared)
13585 28 : = DECL_P (tmp) ? DECL_SIZE_UNIT (tmp)
13586 14 : : TYPE_SIZE_UNIT (TREE_TYPE (tmp));
13587 14 : type = TREE_TYPE (tmp);
13588 : }
13589 : }
13590 : else
13591 : {
13592 128 : unshared = unshare_expr (clause);
13593 128 : type = TREE_TYPE (decl);
13594 : }
13595 :
13596 190 : walk_tree (&unshared, remap_mapper_decl_1, &id, NULL);
13597 :
13598 190 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
13599 28 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
13600 :
13601 190 : decl = OMP_CLAUSE_DECL (unshared);
13602 190 : type = TYPE_MAIN_VARIANT (type);
13603 :
13604 190 : nested_mapper_p = implicit_mappers->get ({ mapper_name, type });
13605 :
13606 190 : if (nested_mapper_p && *nested_mapper_p != mapperfn)
13607 : {
13608 23 : if (nonunit_array_with_mapper)
13609 : {
13610 8 : sorry ("user-defined mapper with non-unit length array section");
13611 8 : continue;
13612 : }
13613 :
13614 15 : if (map_kind == GOMP_MAP_UNSET)
13615 0 : map_kind = outer_kind;
13616 :
13617 15 : mapper_clauses_p
13618 15 : = omp_instantiate_mapper (pre_p, implicit_mappers,
13619 : *nested_mapper_p, decl, map_kind,
13620 : mapper_clauses_p);
13621 15 : continue;
13622 : }
13623 :
13624 167 : *mapper_clauses_p = unshared;
13625 167 : mapper_clauses_p = &OMP_CLAUSE_CHAIN (unshared);
13626 : }
13627 :
13628 90 : return mapper_clauses_p;
13629 90 : }
13630 :
13631 : static int
13632 138233 : omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
13633 : {
13634 138233 : tree decl = (tree) n->key;
13635 138233 : instantiate_mapper_info *im_info = (instantiate_mapper_info *) data;
13636 138233 : gimplify_omp_ctx *ctx = im_info->omp_ctx;
13637 138233 : tree *mapper_p = NULL;
13638 138233 : tree type = TREE_TYPE (decl);
13639 138233 : bool ref_p = false;
13640 138233 : unsigned flags = n->value;
13641 :
13642 138233 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
13643 : return 0;
13644 23709 : if ((flags & GOVD_SEEN) == 0)
13645 : return 0;
13646 : /* If we already have clauses pertaining to a struct variable, then we don't
13647 : want to implicitly invoke a user-defined mapper. */
13648 20179 : if ((flags & GOVD_EXPLICIT) != 0 && AGGREGATE_TYPE_P (TREE_TYPE (decl)))
13649 : return 0;
13650 :
13651 20179 : if (TREE_CODE (type) == REFERENCE_TYPE)
13652 : {
13653 900 : ref_p = true;
13654 900 : type = TREE_TYPE (type);
13655 : }
13656 :
13657 20179 : type = TYPE_MAIN_VARIANT (type);
13658 :
13659 20179 : if (DECL_P (decl) && type && AGGREGATE_TYPE_P (type))
13660 : {
13661 5300 : gcc_assert (ctx);
13662 5300 : mapper_p = ctx->implicit_mappers->get ({ NULL_TREE, type });
13663 : }
13664 :
13665 5300 : if (mapper_p)
13666 : {
13667 : /* If we have a reference, map the pointed-to object rather than the
13668 : reference itself. */
13669 75 : if (ref_p)
13670 2 : decl = build_fold_indirect_ref (decl);
13671 :
13672 75 : im_info->mapper_clauses_p
13673 75 : = omp_instantiate_mapper (im_info->pre_p, ctx->implicit_mappers,
13674 : *mapper_p, decl, GOMP_MAP_TOFROM,
13675 : im_info->mapper_clauses_p);
13676 : /* Make sure we don't map the same variable implicitly in
13677 : gimplify_adjust_omp_clauses_1 also. */
13678 75 : n->value |= GOVD_EXPLICIT;
13679 : }
13680 :
13681 : return 0;
13682 : }
13683 :
13684 : /* Scan the OMP clauses in *LIST_P, installing mappings into a new
13685 : and previous omp contexts. */
13686 :
13687 : static void
13688 130549 : gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
13689 : enum omp_region_type region_type,
13690 : enum tree_code code,
13691 : gimple_seq *loops_seq_p = NULL)
13692 : {
13693 130549 : using namespace omp_addr_tokenizer;
13694 130549 : struct gimplify_omp_ctx *ctx, *outer_ctx;
13695 130549 : tree c;
13696 130549 : tree *orig_list_p = list_p;
13697 130549 : int handled_depend_iterators = -1;
13698 130549 : int nowait = -1;
13699 :
13700 130549 : ctx = new_omp_context (region_type);
13701 130549 : ctx->code = code;
13702 130549 : outer_ctx = ctx->outer_context;
13703 130549 : if (code == OMP_TARGET)
13704 : {
13705 13475 : if (!lang_GNU_Fortran ())
13706 11115 : ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
13707 13475 : ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE;
13708 26950 : ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran ()
13709 13475 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
13710 : }
13711 130549 : if (!lang_GNU_Fortran ())
13712 99484 : switch (code)
13713 : {
13714 18560 : case OMP_TARGET:
13715 18560 : case OMP_TARGET_DATA:
13716 18560 : case OMP_TARGET_ENTER_DATA:
13717 18560 : case OMP_TARGET_EXIT_DATA:
13718 18560 : case OACC_DECLARE:
13719 18560 : case OACC_HOST_DATA:
13720 18560 : case OACC_PARALLEL:
13721 18560 : case OACC_KERNELS:
13722 18560 : ctx->target_firstprivatize_array_bases = true;
13723 : default:
13724 : break;
13725 : }
13726 :
13727 130549 : vec<omp_mapping_group> *groups = NULL;
13728 130549 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
13729 130549 : unsigned grpnum = 0;
13730 130549 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
13731 :
13732 130549 : if (code == OMP_TARGET
13733 130549 : || code == OMP_TARGET_DATA
13734 130549 : || code == OMP_TARGET_ENTER_DATA
13735 : || code == OMP_TARGET_EXIT_DATA
13736 : || code == OACC_DATA
13737 : || code == OACC_KERNELS
13738 : || code == OACC_PARALLEL
13739 : || code == OACC_SERIAL
13740 : || code == OACC_ENTER_DATA
13741 : || code == OACC_EXIT_DATA
13742 : || code == OACC_UPDATE
13743 : || code == OACC_DECLARE)
13744 : {
13745 33846 : if (!(region_type & ORT_ACC))
13746 17334 : *list_p = omp_remove_duplicate_maps (*list_p, false);
13747 33846 : groups = omp_gather_mapping_groups (list_p);
13748 :
13749 33846 : if (groups)
13750 18185 : grpmap = omp_index_mapping_groups (groups);
13751 : }
13752 :
13753 335605 : while ((c = *list_p) != NULL)
13754 : {
13755 205056 : bool remove = false;
13756 205056 : bool notice_outer = true;
13757 205056 : bool map_descriptor;
13758 205056 : const char *check_non_private = NULL;
13759 205056 : unsigned int flags;
13760 205056 : tree decl;
13761 205056 : auto_vec<omp_addr_token *, 10> addr_tokens;
13762 205056 : tree op = NULL_TREE;
13763 205056 : location_t loc = OMP_CLAUSE_LOCATION (c);
13764 :
13765 242557 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
13766 : {
13767 : grp_start_p = NULL;
13768 : grp_end = NULL_TREE;
13769 : }
13770 :
13771 205056 : if (code == OMP_TARGET
13772 : || code == OMP_TARGET_DATA
13773 : || code == OMP_TARGET_ENTER_DATA
13774 172420 : || code == OMP_TARGET_EXIT_DATA)
13775 : /* Do some target-specific type checks for map operands. */
13776 35060 : switch (OMP_CLAUSE_CODE (c))
13777 : {
13778 25627 : case OMP_CLAUSE_MAP:
13779 25627 : op = OMP_CLAUSE_OPERAND (c, 0);
13780 25627 : verify_type_context (loc, TCTX_OMP_MAP, TREE_TYPE (op));
13781 25627 : break;
13782 180 : case OMP_CLAUSE_PRIVATE:
13783 180 : op = OMP_CLAUSE_OPERAND (c, 0);
13784 180 : verify_type_context (loc, TCTX_OMP_PRIVATE, TREE_TYPE (op));
13785 180 : break;
13786 1360 : case OMP_CLAUSE_FIRSTPRIVATE:
13787 1360 : op = OMP_CLAUSE_OPERAND (c, 0);
13788 1360 : verify_type_context (loc, TCTX_OMP_FIRSTPRIVATE, TREE_TYPE (op));
13789 1360 : break;
13790 2922 : case OMP_CLAUSE_IS_DEVICE_PTR:
13791 2922 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13792 2922 : case OMP_CLAUSE_USE_DEVICE_PTR:
13793 2922 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13794 2922 : op = OMP_CLAUSE_OPERAND (c, 0);
13795 2922 : verify_type_context (loc, TCTX_OMP_DEVICE_ADDR, TREE_TYPE (op));
13796 2922 : break;
13797 : default:
13798 : break;
13799 : }
13800 :
13801 205056 : switch (OMP_CLAUSE_CODE (c))
13802 : {
13803 12178 : case OMP_CLAUSE_PRIVATE:
13804 12178 : flags = GOVD_PRIVATE | GOVD_EXPLICIT;
13805 12178 : if (lang_hooks.decls.omp_private_outer_ref (OMP_CLAUSE_DECL (c)))
13806 : {
13807 167 : flags |= GOVD_PRIVATE_OUTER_REF;
13808 167 : OMP_CLAUSE_PRIVATE_OUTER_REF (c) = 1;
13809 : }
13810 : else
13811 : notice_outer = false;
13812 12178 : goto do_add;
13813 5506 : case OMP_CLAUSE_SHARED:
13814 5506 : flags = GOVD_SHARED | GOVD_EXPLICIT;
13815 5506 : goto do_add;
13816 7985 : case OMP_CLAUSE_FIRSTPRIVATE:
13817 7985 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
13818 7985 : check_non_private = "firstprivate";
13819 7985 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13820 : {
13821 380 : gcc_assert (code == OMP_TARGET);
13822 : flags |= GOVD_FIRSTPRIVATE_IMPLICIT;
13823 : }
13824 7985 : goto do_add;
13825 7260 : case OMP_CLAUSE_LASTPRIVATE:
13826 7260 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13827 490 : switch (code)
13828 : {
13829 25 : case OMP_DISTRIBUTE:
13830 25 : error_at (OMP_CLAUSE_LOCATION (c),
13831 : "conditional %<lastprivate%> clause on "
13832 : "%qs construct", "distribute");
13833 25 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13834 25 : break;
13835 13 : case OMP_TASKLOOP:
13836 13 : error_at (OMP_CLAUSE_LOCATION (c),
13837 : "conditional %<lastprivate%> clause on "
13838 : "%qs construct", "taskloop");
13839 13 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13840 13 : break;
13841 : default:
13842 : break;
13843 : }
13844 7260 : flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
13845 7260 : if (code != OMP_LOOP)
13846 6909 : check_non_private = "lastprivate";
13847 7260 : decl = OMP_CLAUSE_DECL (c);
13848 7260 : if (error_operand_p (decl))
13849 0 : goto do_add;
13850 7260 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
13851 7260 : && !lang_hooks.decls.omp_scalar_p (decl, true))
13852 : {
13853 5 : error_at (OMP_CLAUSE_LOCATION (c),
13854 : "non-scalar variable %qD in conditional "
13855 : "%<lastprivate%> clause", decl);
13856 5 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13857 : }
13858 7260 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13859 447 : flags |= GOVD_LASTPRIVATE_CONDITIONAL;
13860 7260 : omp_lastprivate_for_combined_outer_constructs (outer_ctx, decl,
13861 : false);
13862 7260 : goto do_add;
13863 15247 : case OMP_CLAUSE_REDUCTION:
13864 15247 : if (OMP_CLAUSE_REDUCTION_TASK (c))
13865 : {
13866 595 : if (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
13867 : {
13868 408 : if (nowait == -1)
13869 293 : nowait = omp_find_clause (*list_p,
13870 293 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
13871 408 : if (nowait
13872 15 : && (outer_ctx == NULL
13873 0 : || outer_ctx->region_type != ORT_COMBINED_PARALLEL))
13874 : {
13875 15 : error_at (OMP_CLAUSE_LOCATION (c),
13876 : "%<task%> reduction modifier on a construct "
13877 : "with a %<nowait%> clause");
13878 15 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13879 : }
13880 : }
13881 187 : else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL)
13882 : {
13883 40 : error_at (OMP_CLAUSE_LOCATION (c),
13884 : "invalid %<task%> reduction modifier on construct "
13885 : "other than %<parallel%>, %qs, %<sections%> or "
13886 20 : "%<scope%>", lang_GNU_Fortran () ? "do" : "for");
13887 20 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13888 : }
13889 : }
13890 15247 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
13891 835 : switch (code)
13892 : {
13893 4 : case OMP_SECTIONS:
13894 4 : error_at (OMP_CLAUSE_LOCATION (c),
13895 : "%<inscan%> %<reduction%> clause on "
13896 : "%qs construct", "sections");
13897 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13898 4 : break;
13899 4 : case OMP_PARALLEL:
13900 4 : error_at (OMP_CLAUSE_LOCATION (c),
13901 : "%<inscan%> %<reduction%> clause on "
13902 : "%qs construct", "parallel");
13903 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13904 4 : break;
13905 4 : case OMP_TEAMS:
13906 4 : error_at (OMP_CLAUSE_LOCATION (c),
13907 : "%<inscan%> %<reduction%> clause on "
13908 : "%qs construct", "teams");
13909 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13910 4 : break;
13911 4 : case OMP_TASKLOOP:
13912 4 : error_at (OMP_CLAUSE_LOCATION (c),
13913 : "%<inscan%> %<reduction%> clause on "
13914 : "%qs construct", "taskloop");
13915 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13916 4 : break;
13917 4 : case OMP_SCOPE:
13918 4 : error_at (OMP_CLAUSE_LOCATION (c),
13919 : "%<inscan%> %<reduction%> clause on "
13920 : "%qs construct", "scope");
13921 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13922 4 : break;
13923 : default:
13924 : break;
13925 : }
13926 : /* FALLTHRU */
13927 17851 : case OMP_CLAUSE_IN_REDUCTION:
13928 17851 : case OMP_CLAUSE_TASK_REDUCTION:
13929 17851 : flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
13930 : /* OpenACC permits reductions on private variables. */
13931 17851 : if (!(region_type & ORT_ACC)
13932 : /* taskgroup is actually not a worksharing region. */
13933 12332 : && code != OMP_TASKGROUP)
13934 11802 : check_non_private = omp_clause_code_name[OMP_CLAUSE_CODE (c)];
13935 17851 : decl = OMP_CLAUSE_DECL (c);
13936 17851 : if (TREE_CODE (decl) == MEM_REF)
13937 : {
13938 2539 : tree type = TREE_TYPE (decl);
13939 2539 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
13940 2539 : gimplify_ctxp->into_ssa = false;
13941 2539 : if (gimplify_expr (&TYPE_MAX_VALUE (TYPE_DOMAIN (type)), pre_p,
13942 : NULL, is_gimple_val, fb_rvalue, false)
13943 : == GS_ERROR)
13944 : {
13945 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13946 0 : remove = true;
13947 0 : break;
13948 : }
13949 2539 : gimplify_ctxp->into_ssa = saved_into_ssa;
13950 2539 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
13951 2539 : if (DECL_P (v))
13952 : {
13953 571 : omp_firstprivatize_variable (ctx, v);
13954 571 : omp_notice_variable (ctx, v, true);
13955 : }
13956 2539 : decl = TREE_OPERAND (decl, 0);
13957 2539 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
13958 : {
13959 477 : gimplify_ctxp->into_ssa = false;
13960 477 : if (gimplify_expr (&TREE_OPERAND (decl, 1), pre_p,
13961 : NULL, is_gimple_val, fb_rvalue, false)
13962 : == GS_ERROR)
13963 : {
13964 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13965 0 : remove = true;
13966 0 : break;
13967 : }
13968 477 : gimplify_ctxp->into_ssa = saved_into_ssa;
13969 477 : v = TREE_OPERAND (decl, 1);
13970 477 : if (DECL_P (v))
13971 : {
13972 477 : omp_firstprivatize_variable (ctx, v);
13973 477 : omp_notice_variable (ctx, v, true);
13974 : }
13975 477 : decl = TREE_OPERAND (decl, 0);
13976 : }
13977 2539 : if (TREE_CODE (decl) == ADDR_EXPR
13978 1163 : || TREE_CODE (decl) == INDIRECT_REF)
13979 1474 : decl = TREE_OPERAND (decl, 0);
13980 : }
13981 17851 : goto do_add_decl;
13982 2644 : case OMP_CLAUSE_LINEAR:
13983 2644 : if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
13984 : is_gimple_val, fb_rvalue) == GS_ERROR)
13985 : {
13986 : remove = true;
13987 : break;
13988 : }
13989 : else
13990 : {
13991 2644 : if (code == OMP_SIMD
13992 2644 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
13993 : {
13994 1154 : struct gimplify_omp_ctx *octx = outer_ctx;
13995 1154 : if (octx
13996 741 : && octx->region_type == ORT_WORKSHARE
13997 500 : && octx->combined_loop
13998 500 : && !octx->distribute)
13999 : {
14000 492 : if (octx->outer_context
14001 430 : && (octx->outer_context->region_type
14002 : == ORT_COMBINED_PARALLEL))
14003 393 : octx = octx->outer_context->outer_context;
14004 : else
14005 : octx = octx->outer_context;
14006 : }
14007 905 : if (octx
14008 316 : && octx->region_type == ORT_WORKSHARE
14009 16 : && octx->combined_loop
14010 16 : && octx->distribute)
14011 : {
14012 16 : error_at (OMP_CLAUSE_LOCATION (c),
14013 : "%<linear%> clause for variable other than "
14014 : "loop iterator specified on construct "
14015 : "combined with %<distribute%>");
14016 16 : remove = true;
14017 16 : break;
14018 : }
14019 : }
14020 : /* For combined #pragma omp parallel for simd, need to put
14021 : lastprivate and perhaps firstprivate too on the
14022 : parallel. Similarly for #pragma omp for simd. */
14023 : struct gimplify_omp_ctx *octx = outer_ctx;
14024 : bool taskloop_seen = false;
14025 : decl = NULL_TREE;
14026 3419 : do
14027 : {
14028 3419 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14029 3419 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14030 : break;
14031 3359 : decl = OMP_CLAUSE_DECL (c);
14032 3359 : if (error_operand_p (decl))
14033 : {
14034 : decl = NULL_TREE;
14035 : break;
14036 : }
14037 3359 : flags = GOVD_SEEN;
14038 3359 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14039 1648 : flags |= GOVD_FIRSTPRIVATE;
14040 3359 : if (!OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14041 3359 : flags |= GOVD_LASTPRIVATE;
14042 3359 : if (octx
14043 2482 : && octx->region_type == ORT_WORKSHARE
14044 1213 : && octx->combined_loop)
14045 : {
14046 1207 : if (octx->outer_context
14047 1037 : && (octx->outer_context->region_type
14048 : == ORT_COMBINED_PARALLEL))
14049 : octx = octx->outer_context;
14050 476 : else if (omp_check_private (octx, decl, false))
14051 : break;
14052 : }
14053 : else if (octx
14054 1275 : && (octx->region_type & ORT_TASK) != 0
14055 307 : && octx->combined_loop)
14056 : taskloop_seen = true;
14057 : else if (octx
14058 972 : && octx->region_type == ORT_COMBINED_PARALLEL
14059 295 : && ((ctx->region_type == ORT_WORKSHARE
14060 195 : && octx == outer_ctx)
14061 100 : || taskloop_seen))
14062 : flags = GOVD_SEEN | GOVD_SHARED;
14063 : else if (octx
14064 677 : && ((octx->region_type & ORT_COMBINED_TEAMS)
14065 : == ORT_COMBINED_TEAMS))
14066 : flags = GOVD_SEEN | GOVD_SHARED;
14067 522 : else if (octx
14068 522 : && octx->region_type == ORT_COMBINED_TARGET)
14069 : {
14070 195 : if (flags & GOVD_LASTPRIVATE)
14071 195 : flags = GOVD_SEEN | GOVD_MAP;
14072 : }
14073 : else
14074 : break;
14075 2065 : splay_tree_node on
14076 2065 : = splay_tree_lookup (octx->variables,
14077 : (splay_tree_key) decl);
14078 2065 : if (on && (on->value & GOVD_DATA_SHARE_CLASS) != 0)
14079 : {
14080 : octx = NULL;
14081 : break;
14082 : }
14083 2061 : omp_add_variable (octx, decl, flags);
14084 2061 : if (octx->outer_context == NULL)
14085 : break;
14086 : octx = octx->outer_context;
14087 : }
14088 : while (1);
14089 2628 : if (octx
14090 2628 : && decl
14091 2628 : && (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14092 728 : || !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
14093 1687 : omp_notice_variable (octx, decl, true);
14094 : }
14095 2628 : flags = GOVD_LINEAR | GOVD_EXPLICIT;
14096 2628 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14097 2628 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14098 : {
14099 : notice_outer = false;
14100 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
14101 : }
14102 2628 : goto do_add;
14103 :
14104 51212 : case OMP_CLAUSE_MAP:
14105 51212 : if (!grp_start_p)
14106 : {
14107 31037 : grp_start_p = list_p;
14108 31037 : grp_end = (*groups)[grpnum].grp_end;
14109 31037 : grpnum++;
14110 : }
14111 51212 : decl = OMP_CLAUSE_DECL (c);
14112 :
14113 51212 : if (error_operand_p (decl))
14114 : {
14115 : remove = true;
14116 : break;
14117 : }
14118 :
14119 51212 : if (!omp_parse_expr (addr_tokens, decl))
14120 : {
14121 : remove = true;
14122 : break;
14123 : }
14124 :
14125 51212 : if (remove)
14126 : break;
14127 51212 : if (DECL_P (decl) && outer_ctx && (region_type & ORT_ACC))
14128 : {
14129 : struct gimplify_omp_ctx *octx;
14130 1167 : for (octx = outer_ctx; octx; octx = octx->outer_context)
14131 : {
14132 1167 : if (octx->region_type != ORT_ACC_HOST_DATA)
14133 : break;
14134 12 : splay_tree_node n2
14135 12 : = splay_tree_lookup (octx->variables,
14136 : (splay_tree_key) decl);
14137 12 : if (n2)
14138 4 : error_at (OMP_CLAUSE_LOCATION (c), "variable %qE "
14139 : "declared in enclosing %<host_data%> region",
14140 4 : DECL_NAME (decl));
14141 : }
14142 : }
14143 :
14144 51212 : map_descriptor = false;
14145 :
14146 : /* This condition checks if we're mapping an array descriptor that
14147 : isn't inside a derived type -- these have special handling, and
14148 : are not handled as structs in omp_build_struct_sibling_lists.
14149 : See that function for further details. */
14150 51212 : if (*grp_start_p != grp_end
14151 34172 : && OMP_CLAUSE_CHAIN (*grp_start_p)
14152 85384 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
14153 : {
14154 17096 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
14155 17096 : if (omp_map_clause_descriptor_p (grp_mid)
14156 32365 : && DECL_P (OMP_CLAUSE_DECL (grp_mid)))
14157 : map_descriptor = true;
14158 : }
14159 34116 : else if (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP
14160 34116 : && (OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_RELEASE
14161 33372 : || OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_DELETE)
14162 35038 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (grp_end))
14163 : map_descriptor = true;
14164 :
14165 : /* Adding the decl for a struct access: we haven't created
14166 : GOMP_MAP_STRUCT nodes yet, so this statement needs to predict
14167 : whether they will be created in gimplify_adjust_omp_clauses.
14168 : NOTE: Technically we should probably look through DECL_VALUE_EXPR
14169 : here because something that looks like a DECL_P may actually be a
14170 : struct access, e.g. variables in a lambda closure
14171 : (__closure->__foo) or class members (this->foo). Currently in both
14172 : those cases we map the whole of the containing object (directly in
14173 : the C++ FE) though, so struct nodes are not created. */
14174 51212 : if (c == grp_end
14175 31037 : && addr_tokens[0]->type == STRUCTURE_BASE
14176 8397 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14177 59609 : && !map_descriptor)
14178 : {
14179 5593 : gcc_assert (addr_tokens[1]->type == ACCESS_METHOD);
14180 : /* If we got to this struct via a chain of pointers, maybe we
14181 : want to map it implicitly instead. */
14182 5593 : if (omp_access_chain_p (addr_tokens, 1))
14183 : break;
14184 5432 : omp_mapping_group *wholestruct;
14185 5432 : if (!(region_type & ORT_ACC)
14186 9589 : && omp_mapped_by_containing_struct (grpmap,
14187 4157 : OMP_CLAUSE_DECL (c),
14188 : &wholestruct))
14189 : break;
14190 5195 : decl = addr_tokens[1]->expr;
14191 5195 : if (splay_tree_lookup (ctx->variables, (splay_tree_key) decl))
14192 : break;
14193 : /* Standalone attach or detach clauses for a struct element
14194 : should not inhibit implicit mapping of the whole struct. */
14195 2983 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
14196 2983 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
14197 : break;
14198 2833 : flags = GOVD_MAP | GOVD_EXPLICIT;
14199 :
14200 2833 : gcc_assert (addr_tokens[1]->u.access_kind != ACCESS_DIRECT
14201 : || TREE_ADDRESSABLE (decl));
14202 2833 : goto do_add_decl;
14203 : }
14204 :
14205 45619 : if (!DECL_P (decl))
14206 : {
14207 21081 : tree d = decl, *pd;
14208 21081 : if (TREE_CODE (d) == ARRAY_REF)
14209 : {
14210 5022 : while (TREE_CODE (d) == ARRAY_REF)
14211 2568 : d = TREE_OPERAND (d, 0);
14212 2454 : if (TREE_CODE (d) == COMPONENT_REF
14213 2454 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
14214 : decl = d;
14215 : }
14216 21081 : pd = &OMP_CLAUSE_DECL (c);
14217 21081 : if (d == decl
14218 18673 : && TREE_CODE (decl) == INDIRECT_REF
14219 13937 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
14220 1070 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
14221 : == REFERENCE_TYPE)
14222 21732 : && (OMP_CLAUSE_MAP_KIND (c)
14223 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
14224 : {
14225 647 : pd = &TREE_OPERAND (decl, 0);
14226 647 : decl = TREE_OPERAND (decl, 0);
14227 : }
14228 :
14229 21081 : if (addr_tokens[0]->type == STRUCTURE_BASE
14230 11440 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14231 11439 : && addr_tokens[1]->type == ACCESS_METHOD
14232 11439 : && (addr_tokens[1]->u.access_kind == ACCESS_POINTER
14233 10941 : || (addr_tokens[1]->u.access_kind
14234 : == ACCESS_POINTER_OFFSET))
14235 21661 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)))
14236 : {
14237 0 : tree base = addr_tokens[1]->expr;
14238 0 : splay_tree_node n
14239 0 : = splay_tree_lookup (ctx->variables,
14240 : (splay_tree_key) base);
14241 0 : n->value |= GOVD_SEEN;
14242 : }
14243 :
14244 21081 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
14245 : {
14246 : /* Don't gimplify *pd fully at this point, as the base
14247 : will need to be adjusted during omp lowering. */
14248 88 : auto_vec<tree, 10> expr_stack;
14249 88 : tree *p = pd;
14250 88 : while (handled_component_p (*p)
14251 : || TREE_CODE (*p) == INDIRECT_REF
14252 : || TREE_CODE (*p) == ADDR_EXPR
14253 : || TREE_CODE (*p) == MEM_REF
14254 224 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
14255 : {
14256 136 : expr_stack.safe_push (*p);
14257 136 : p = &TREE_OPERAND (*p, 0);
14258 : }
14259 312 : for (int i = expr_stack.length () - 1; i >= 0; i--)
14260 : {
14261 136 : tree t = expr_stack[i];
14262 136 : if (TREE_CODE (t) == ARRAY_REF
14263 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14264 : {
14265 56 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14266 : {
14267 56 : tree low = unshare_expr (array_ref_low_bound (t));
14268 56 : if (!is_gimple_min_invariant (low))
14269 : {
14270 0 : TREE_OPERAND (t, 2) = low;
14271 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14272 : pre_p, NULL,
14273 : is_gimple_reg,
14274 : fb_rvalue) == GS_ERROR)
14275 0 : remove = true;
14276 : }
14277 : }
14278 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14279 : NULL, is_gimple_reg,
14280 : fb_rvalue) == GS_ERROR)
14281 0 : remove = true;
14282 56 : if (TREE_OPERAND (t, 3) == NULL_TREE)
14283 : {
14284 56 : tree elmt_size = array_ref_element_size (t);
14285 56 : if (!is_gimple_min_invariant (elmt_size))
14286 : {
14287 0 : elmt_size = unshare_expr (elmt_size);
14288 0 : tree elmt_type
14289 0 : = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t,
14290 : 0)));
14291 0 : tree factor
14292 0 : = size_int (TYPE_ALIGN_UNIT (elmt_type));
14293 0 : elmt_size
14294 0 : = size_binop (EXACT_DIV_EXPR, elmt_size,
14295 : factor);
14296 0 : TREE_OPERAND (t, 3) = elmt_size;
14297 0 : if (gimplify_expr (&TREE_OPERAND (t, 3),
14298 : pre_p, NULL,
14299 : is_gimple_reg,
14300 : fb_rvalue) == GS_ERROR)
14301 0 : remove = true;
14302 : }
14303 : }
14304 0 : else if (gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
14305 : NULL, is_gimple_reg,
14306 : fb_rvalue) == GS_ERROR)
14307 0 : remove = true;
14308 : }
14309 80 : else if (TREE_CODE (t) == COMPONENT_REF)
14310 : {
14311 0 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14312 : {
14313 0 : tree offset = component_ref_field_offset (t);
14314 0 : if (!is_gimple_min_invariant (offset))
14315 : {
14316 0 : offset = unshare_expr (offset);
14317 0 : tree field = TREE_OPERAND (t, 1);
14318 0 : tree factor
14319 0 : = size_int (DECL_OFFSET_ALIGN (field)
14320 : / BITS_PER_UNIT);
14321 0 : offset = size_binop (EXACT_DIV_EXPR, offset,
14322 : factor);
14323 0 : TREE_OPERAND (t, 2) = offset;
14324 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14325 : pre_p, NULL,
14326 : is_gimple_reg,
14327 : fb_rvalue) == GS_ERROR)
14328 0 : remove = true;
14329 : }
14330 : }
14331 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14332 : NULL, is_gimple_reg,
14333 : fb_rvalue) == GS_ERROR)
14334 0 : remove = true;
14335 : }
14336 : }
14337 224 : for (; expr_stack.length () > 0; )
14338 : {
14339 136 : tree t = expr_stack.pop ();
14340 :
14341 136 : if (TREE_CODE (t) == ARRAY_REF
14342 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14343 : {
14344 56 : if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))
14345 56 : && gimplify_expr (&TREE_OPERAND (t, 1), pre_p,
14346 : NULL, is_gimple_val,
14347 : fb_rvalue) == GS_ERROR)
14348 144 : remove = true;
14349 : }
14350 : }
14351 88 : }
14352 : break;
14353 : }
14354 :
14355 24538 : if ((code == OMP_TARGET
14356 : || code == OMP_TARGET_DATA
14357 : || code == OMP_TARGET_ENTER_DATA
14358 14224 : || code == OMP_TARGET_EXIT_DATA)
14359 25175 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14360 : {
14361 : /* If we have attach/detach but the decl we have is a pointer to
14362 : pointer, we're probably mapping the "base level" array
14363 : implicitly. Make sure we don't add the decl as if we mapped
14364 : it explicitly. That is,
14365 :
14366 : int **arr;
14367 : [...]
14368 : #pragma omp target map(arr[a][b:c])
14369 :
14370 : should *not* map "arr" explicitly. That way we get a
14371 : zero-length "alloc" mapping for it, and assuming it's been
14372 : mapped by some previous directive, etc., things work as they
14373 : should. */
14374 :
14375 213 : tree basetype = TREE_TYPE (addr_tokens[0]->expr);
14376 :
14377 213 : if (TREE_CODE (basetype) == REFERENCE_TYPE)
14378 34 : basetype = TREE_TYPE (basetype);
14379 :
14380 213 : if (code == OMP_TARGET
14381 54 : && addr_tokens[0]->type == ARRAY_BASE
14382 54 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14383 54 : && TREE_CODE (basetype) == POINTER_TYPE
14384 267 : && TREE_CODE (TREE_TYPE (basetype)) == POINTER_TYPE)
14385 : break;
14386 : }
14387 :
14388 24516 : flags = GOVD_MAP | GOVD_EXPLICIT;
14389 24516 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
14390 24381 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM
14391 23877 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TO
14392 48363 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TOFROM)
14393 : flags |= GOVD_MAP_ALWAYS_TO;
14394 :
14395 24516 : goto do_add;
14396 :
14397 374 : case OMP_CLAUSE_AFFINITY:
14398 374 : gimplify_omp_affinity (list_p, pre_p);
14399 374 : remove = true;
14400 374 : break;
14401 8 : case OMP_CLAUSE_DOACROSS:
14402 8 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
14403 : {
14404 4 : tree deps = OMP_CLAUSE_DECL (c);
14405 8 : while (deps && TREE_CODE (deps) == TREE_LIST)
14406 : {
14407 4 : if (TREE_CODE (TREE_PURPOSE (deps)) == TRUNC_DIV_EXPR
14408 4 : && DECL_P (TREE_OPERAND (TREE_PURPOSE (deps), 1)))
14409 0 : gimplify_expr (&TREE_OPERAND (TREE_PURPOSE (deps), 1),
14410 : pre_p, NULL, is_gimple_val, fb_rvalue);
14411 4 : deps = TREE_CHAIN (deps);
14412 : }
14413 : }
14414 : else
14415 4 : gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
14416 : == OMP_CLAUSE_DOACROSS_SOURCE);
14417 : break;
14418 2207 : case OMP_CLAUSE_DEPEND:
14419 2207 : if (handled_depend_iterators == -1)
14420 1905 : handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
14421 2207 : if (handled_depend_iterators)
14422 : {
14423 348 : if (handled_depend_iterators == 2)
14424 0 : remove = true;
14425 : break;
14426 : }
14427 1859 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
14428 : {
14429 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
14430 : NULL, is_gimple_val, fb_rvalue);
14431 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
14432 : }
14433 1859 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
14434 : {
14435 : remove = true;
14436 : break;
14437 : }
14438 1859 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
14439 : {
14440 1828 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
14441 1828 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
14442 : is_gimple_val, fb_rvalue) == GS_ERROR)
14443 : {
14444 : remove = true;
14445 : break;
14446 : }
14447 : }
14448 1859 : if (code == OMP_TASK)
14449 1401 : ctx->has_depend = true;
14450 : break;
14451 :
14452 8335 : case OMP_CLAUSE_TO:
14453 8335 : case OMP_CLAUSE_FROM:
14454 8335 : case OMP_CLAUSE__CACHE_:
14455 8335 : decl = OMP_CLAUSE_DECL (c);
14456 8335 : if (error_operand_p (decl))
14457 : {
14458 : remove = true;
14459 : break;
14460 : }
14461 8335 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14462 7661 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
14463 796 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
14464 8335 : gimple_seq *seq_p;
14465 8335 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
14466 8335 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
14467 : is_gimple_val, fb_rvalue) == GS_ERROR)
14468 : {
14469 0 : remove = true;
14470 0 : exit_omp_iterator_loop_context (c);
14471 0 : break;
14472 : }
14473 8335 : if (!DECL_P (decl))
14474 : {
14475 2145 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
14476 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
14477 0 : remove = true;
14478 2145 : exit_omp_iterator_loop_context (c);
14479 2145 : break;
14480 : }
14481 6190 : exit_omp_iterator_loop_context (c);
14482 6190 : goto do_notice;
14483 :
14484 135 : case OMP_CLAUSE__MAPPER_BINDING_:
14485 135 : {
14486 135 : tree name = OMP_CLAUSE__MAPPER_BINDING__ID (c);
14487 135 : tree var = OMP_CLAUSE__MAPPER_BINDING__DECL (c);
14488 135 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (var));
14489 135 : tree fndecl = OMP_CLAUSE__MAPPER_BINDING__MAPPER (c);
14490 135 : ctx->implicit_mappers->put ({ name, type }, fndecl);
14491 135 : remove = true;
14492 135 : break;
14493 : }
14494 :
14495 2118 : case OMP_CLAUSE_USE_DEVICE_PTR:
14496 2118 : case OMP_CLAUSE_USE_DEVICE_ADDR:
14497 2118 : flags = GOVD_EXPLICIT;
14498 2118 : goto do_add;
14499 :
14500 557 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14501 557 : decl = OMP_CLAUSE_DECL (c);
14502 557 : while (TREE_CODE (decl) == INDIRECT_REF
14503 606 : || TREE_CODE (decl) == ARRAY_REF)
14504 49 : decl = TREE_OPERAND (decl, 0);
14505 557 : flags = GOVD_EXPLICIT;
14506 557 : goto do_add_decl;
14507 :
14508 500 : case OMP_CLAUSE_IS_DEVICE_PTR:
14509 500 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
14510 500 : goto do_add;
14511 :
14512 62881 : do_add:
14513 62881 : decl = OMP_CLAUSE_DECL (c);
14514 84122 : do_add_decl:
14515 84122 : if (error_operand_p (decl))
14516 : {
14517 : remove = true;
14518 : break;
14519 : }
14520 84114 : if (DECL_NAME (decl) == NULL_TREE && (flags & GOVD_SHARED) == 0)
14521 : {
14522 1755 : tree t = omp_member_access_dummy_var (decl);
14523 1755 : if (t)
14524 : {
14525 668 : tree v = DECL_VALUE_EXPR (decl);
14526 668 : DECL_NAME (decl) = DECL_NAME (TREE_OPERAND (v, 1));
14527 668 : if (outer_ctx)
14528 140 : omp_notice_variable (outer_ctx, t, true);
14529 : }
14530 : }
14531 84114 : if (code == OACC_DATA
14532 2402 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14533 86516 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14534 307 : flags |= GOVD_MAP_0LEN_ARRAY;
14535 84114 : omp_add_variable (ctx, decl, flags);
14536 84114 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14537 68867 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
14538 66793 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
14539 86718 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
14540 : {
14541 2087 : struct gimplify_omp_ctx *pctx
14542 2147 : = code == OMP_TARGET ? outer_ctx : ctx;
14543 2147 : if (pctx)
14544 2117 : omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
14545 : GOVD_LOCAL | GOVD_SEEN);
14546 2117 : if (pctx
14547 2117 : && OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
14548 632 : && walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
14549 : find_decl_expr,
14550 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14551 : NULL) == NULL_TREE)
14552 208 : omp_add_variable (pctx,
14553 208 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14554 : GOVD_LOCAL | GOVD_SEEN);
14555 2147 : gimplify_omp_ctxp = pctx;
14556 2147 : push_gimplify_context ();
14557 :
14558 2147 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
14559 2147 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
14560 :
14561 2147 : gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
14562 2147 : &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
14563 2147 : pop_gimplify_context
14564 2147 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)));
14565 2147 : push_gimplify_context ();
14566 4294 : gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
14567 2147 : &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
14568 2147 : pop_gimplify_context
14569 2147 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
14570 2147 : OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
14571 2147 : OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
14572 :
14573 2147 : gimplify_omp_ctxp = outer_ctx;
14574 : }
14575 81967 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
14576 81967 : && OMP_CLAUSE_LASTPRIVATE_STMT (c))
14577 : {
14578 303 : gimplify_omp_ctxp = ctx;
14579 303 : push_gimplify_context ();
14580 303 : if (TREE_CODE (OMP_CLAUSE_LASTPRIVATE_STMT (c)) != BIND_EXPR)
14581 : {
14582 303 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14583 : NULL, NULL);
14584 303 : TREE_SIDE_EFFECTS (bind) = 1;
14585 303 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LASTPRIVATE_STMT (c);
14586 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = bind;
14587 : }
14588 606 : gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c),
14589 303 : &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
14590 303 : pop_gimplify_context
14591 303 : (gimple_seq_first_stmt (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)));
14592 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL_TREE;
14593 :
14594 303 : gimplify_omp_ctxp = outer_ctx;
14595 : }
14596 81664 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14597 81664 : && OMP_CLAUSE_LINEAR_STMT (c))
14598 : {
14599 60 : gimplify_omp_ctxp = ctx;
14600 60 : push_gimplify_context ();
14601 60 : if (TREE_CODE (OMP_CLAUSE_LINEAR_STMT (c)) != BIND_EXPR)
14602 : {
14603 60 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14604 : NULL, NULL);
14605 60 : TREE_SIDE_EFFECTS (bind) = 1;
14606 60 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LINEAR_STMT (c);
14607 60 : OMP_CLAUSE_LINEAR_STMT (c) = bind;
14608 : }
14609 120 : gimplify_and_add (OMP_CLAUSE_LINEAR_STMT (c),
14610 60 : &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
14611 60 : pop_gimplify_context
14612 60 : (gimple_seq_first_stmt (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)));
14613 60 : OMP_CLAUSE_LINEAR_STMT (c) = NULL_TREE;
14614 :
14615 60 : gimplify_omp_ctxp = outer_ctx;
14616 : }
14617 84114 : if (notice_outer)
14618 72043 : goto do_notice;
14619 : break;
14620 :
14621 910 : case OMP_CLAUSE_COPYIN:
14622 910 : case OMP_CLAUSE_COPYPRIVATE:
14623 910 : decl = OMP_CLAUSE_DECL (c);
14624 910 : if (error_operand_p (decl))
14625 : {
14626 : remove = true;
14627 : break;
14628 : }
14629 910 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
14630 : && !remove
14631 910 : && !omp_check_private (ctx, decl, true))
14632 : {
14633 35 : remove = true;
14634 35 : if (is_global_var (decl))
14635 : {
14636 30 : if (DECL_THREAD_LOCAL_P (decl))
14637 : remove = false;
14638 10 : else if (DECL_HAS_VALUE_EXPR_P (decl))
14639 : {
14640 2 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
14641 :
14642 2 : if (value
14643 2 : && DECL_P (value)
14644 4 : && DECL_THREAD_LOCAL_P (value))
14645 : remove = false;
14646 : }
14647 : }
14648 : if (remove)
14649 13 : error_at (OMP_CLAUSE_LOCATION (c),
14650 : "copyprivate variable %qE is not threadprivate"
14651 13 : " or private in outer context", DECL_NAME (decl));
14652 : }
14653 79143 : do_notice:
14654 79143 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14655 63896 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
14656 55911 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
14657 30492 : && outer_ctx
14658 17457 : && ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
14659 16118 : || (region_type == ORT_WORKSHARE
14660 3811 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14661 1085 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
14662 910 : || code == OMP_LOOP)))
14663 81088 : && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
14664 857 : || (code == OMP_LOOP
14665 138 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14666 138 : && ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
14667 : == ORT_COMBINED_TEAMS))))
14668 : {
14669 1209 : splay_tree_node on
14670 1209 : = splay_tree_lookup (outer_ctx->variables,
14671 : (splay_tree_key)decl);
14672 1209 : if (on == NULL || (on->value & GOVD_DATA_SHARE_CLASS) == 0)
14673 : {
14674 891 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14675 705 : && TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14676 1003 : && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
14677 56 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
14678 0 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
14679 : == POINTER_TYPE))))
14680 56 : omp_firstprivatize_variable (outer_ctx, decl);
14681 : else
14682 : {
14683 835 : omp_add_variable (outer_ctx, decl,
14684 : GOVD_SEEN | GOVD_SHARED);
14685 835 : if (outer_ctx->outer_context)
14686 235 : omp_notice_variable (outer_ctx->outer_context, decl,
14687 : true);
14688 : }
14689 : }
14690 : }
14691 78543 : if (outer_ctx)
14692 29469 : omp_notice_variable (outer_ctx, decl, true);
14693 79143 : if (check_non_private
14694 26696 : && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
14695 4698 : && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
14696 1655 : || decl == OMP_CLAUSE_DECL (c)
14697 224 : || (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14698 224 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14699 : == ADDR_EXPR
14700 103 : || (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14701 : == POINTER_PLUS_EXPR
14702 22 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND
14703 : (OMP_CLAUSE_DECL (c), 0), 0))
14704 : == ADDR_EXPR)))))
14705 83753 : && omp_check_private (ctx, decl, false))
14706 : {
14707 58 : error ("%s variable %qE is private in outer context",
14708 29 : check_non_private, DECL_NAME (decl));
14709 29 : remove = true;
14710 : }
14711 : break;
14712 :
14713 190 : case OMP_CLAUSE_DETACH:
14714 190 : flags = GOVD_FIRSTPRIVATE | GOVD_SEEN;
14715 190 : goto do_add;
14716 :
14717 4108 : case OMP_CLAUSE_IF:
14718 4108 : if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK
14719 4108 : && OMP_CLAUSE_IF_MODIFIER (c) != code)
14720 : {
14721 : const char *p[2];
14722 168 : for (int i = 0; i < 2; i++)
14723 112 : switch (i ? OMP_CLAUSE_IF_MODIFIER (c) : code)
14724 : {
14725 8 : case VOID_CST: p[i] = "cancel"; break;
14726 24 : case OMP_PARALLEL: p[i] = "parallel"; break;
14727 4 : case OMP_SIMD: p[i] = "simd"; break;
14728 12 : case OMP_TASK: p[i] = "task"; break;
14729 12 : case OMP_TASKLOOP: p[i] = "taskloop"; break;
14730 8 : case OMP_TARGET_DATA: p[i] = "target data"; break;
14731 12 : case OMP_TARGET: p[i] = "target"; break;
14732 12 : case OMP_TARGET_UPDATE: p[i] = "target update"; break;
14733 8 : case OMP_TARGET_ENTER_DATA:
14734 8 : p[i] = "target enter data"; break;
14735 12 : case OMP_TARGET_EXIT_DATA: p[i] = "target exit data"; break;
14736 0 : default: gcc_unreachable ();
14737 : }
14738 56 : error_at (OMP_CLAUSE_LOCATION (c),
14739 : "expected %qs %<if%> clause modifier rather than %qs",
14740 : p[0], p[1]);
14741 56 : remove = true;
14742 : }
14743 : /* Fall through. */
14744 :
14745 4818 : case OMP_CLAUSE_SELF:
14746 4818 : case OMP_CLAUSE_FINAL:
14747 4818 : OMP_CLAUSE_OPERAND (c, 0)
14748 9636 : = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
14749 : /* Fall through. */
14750 :
14751 5724 : case OMP_CLAUSE_NUM_TEAMS:
14752 5724 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
14753 906 : && OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14754 5969 : && !is_gimple_min_invariant (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14755 : {
14756 208 : if (error_operand_p (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14757 : {
14758 : remove = true;
14759 : break;
14760 : }
14761 208 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14762 416 : = get_initialized_tmp_var (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c),
14763 : pre_p, NULL, true);
14764 : }
14765 : /* Fall through. */
14766 :
14767 21836 : case OMP_CLAUSE_SCHEDULE:
14768 21836 : case OMP_CLAUSE_NUM_THREADS:
14769 21836 : case OMP_CLAUSE_THREAD_LIMIT:
14770 21836 : case OMP_CLAUSE_DIST_SCHEDULE:
14771 21836 : case OMP_CLAUSE_DEVICE:
14772 21836 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14773 21836 : && OMP_CLAUSE_DEVICE_ANCESTOR (c))
14774 : {
14775 125 : if (code != OMP_TARGET)
14776 : {
14777 20 : error_at (OMP_CLAUSE_LOCATION (c),
14778 : "%<device%> clause with %<ancestor%> is only "
14779 : "allowed on %<target%> construct");
14780 20 : remove = true;
14781 20 : break;
14782 : }
14783 :
14784 105 : tree clauses = *orig_list_p;
14785 330 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
14786 236 : if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE
14787 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE
14788 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE
14789 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP
14790 : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP
14791 : )
14792 : {
14793 11 : error_at (OMP_CLAUSE_LOCATION (c),
14794 : "with %<ancestor%>, only the %<device%>, "
14795 : "%<firstprivate%>, %<private%>, %<defaultmap%>, "
14796 : "and %<map%> clauses may appear on the "
14797 : "construct");
14798 11 : remove = true;
14799 11 : break;
14800 : }
14801 : }
14802 21711 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14803 21711 : && code == OMP_DISPATCH)
14804 : {
14805 272 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
14806 272 : gimplify_ctxp->into_ssa = false;
14807 272 : if (gimplify_expr (&OMP_CLAUSE_DEVICE_ID (c), pre_p, NULL,
14808 : is_gimple_val, fb_rvalue)
14809 : == GS_ERROR)
14810 : remove = true;
14811 272 : else if (DECL_P (OMP_CLAUSE_DEVICE_ID (c)))
14812 55 : omp_add_variable (ctx, OMP_CLAUSE_DEVICE_ID (c),
14813 : GOVD_SHARED | GOVD_SEEN);
14814 272 : gimplify_ctxp->into_ssa = saved_into_ssa;
14815 272 : break;
14816 : }
14817 : /* Fall through. */
14818 :
14819 31285 : case OMP_CLAUSE_PRIORITY:
14820 31285 : case OMP_CLAUSE_GRAINSIZE:
14821 31285 : case OMP_CLAUSE_NUM_TASKS:
14822 31285 : case OMP_CLAUSE_FILTER:
14823 31285 : case OMP_CLAUSE_HINT:
14824 31285 : case OMP_CLAUSE_ASYNC:
14825 31285 : case OMP_CLAUSE_WAIT:
14826 31285 : case OMP_CLAUSE_NUM_GANGS:
14827 31285 : case OMP_CLAUSE_NUM_WORKERS:
14828 31285 : case OMP_CLAUSE_VECTOR_LENGTH:
14829 31285 : case OMP_CLAUSE_WORKER:
14830 31285 : case OMP_CLAUSE_VECTOR:
14831 31285 : if (OMP_CLAUSE_OPERAND (c, 0)
14832 31285 : && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0)))
14833 : {
14834 7777 : if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0)))
14835 : {
14836 : remove = true;
14837 : break;
14838 : }
14839 : /* All these clauses care about value, not a particular decl,
14840 : so try to force it into a SSA_NAME or fresh temporary. */
14841 7770 : OMP_CLAUSE_OPERAND (c, 0)
14842 15540 : = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0),
14843 : pre_p, NULL, true);
14844 : }
14845 : break;
14846 :
14847 2332 : case OMP_CLAUSE_GANG:
14848 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
14849 : is_gimple_val, fb_rvalue) == GS_ERROR)
14850 0 : remove = true;
14851 2332 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL,
14852 : is_gimple_val, fb_rvalue) == GS_ERROR)
14853 0 : remove = true;
14854 : break;
14855 :
14856 13086 : case OMP_CLAUSE_NOWAIT:
14857 13086 : nowait = 1;
14858 13086 : break;
14859 :
14860 93 : case OMP_CLAUSE_USES_ALLOCATORS:
14861 93 : if (TREE_CODE (OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c))
14862 : != INTEGER_CST)
14863 : {
14864 90 : decl = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (c);
14865 90 : omp_add_variable (ctx, decl,
14866 : GOVD_SEEN | GOVD_USES_ALLOCATORS_ALLOCATOR);
14867 : }
14868 : else
14869 : remove = true;
14870 : break;
14871 :
14872 : case OMP_CLAUSE_ORDERED:
14873 : case OMP_CLAUSE_UNTIED:
14874 : case OMP_CLAUSE_COLLAPSE:
14875 : case OMP_CLAUSE_TILE:
14876 : case OMP_CLAUSE_AUTO:
14877 : case OMP_CLAUSE_SEQ:
14878 : case OMP_CLAUSE_INDEPENDENT:
14879 : case OMP_CLAUSE_MERGEABLE:
14880 : case OMP_CLAUSE_PROC_BIND:
14881 : case OMP_CLAUSE_SAFELEN:
14882 : case OMP_CLAUSE_SIMDLEN:
14883 : case OMP_CLAUSE_NOGROUP:
14884 : case OMP_CLAUSE_THREADS:
14885 : case OMP_CLAUSE_SIMD:
14886 : case OMP_CLAUSE_BIND:
14887 : case OMP_CLAUSE_IF_PRESENT:
14888 : case OMP_CLAUSE_FINALIZE:
14889 : case OMP_CLAUSE_INTEROP:
14890 : case OMP_CLAUSE_INIT:
14891 : case OMP_CLAUSE_USE:
14892 : case OMP_CLAUSE_DESTROY:
14893 : case OMP_CLAUSE_DEVICE_TYPE:
14894 : break;
14895 :
14896 52 : case OMP_CLAUSE_DYN_GROUPPRIVATE:
14897 52 : remove = true;
14898 52 : sorry_at (OMP_CLAUSE_LOCATION (c),"%<dyn_groupprivate%> clause");
14899 52 : break;
14900 :
14901 3976 : case OMP_CLAUSE_ORDER:
14902 3976 : ctx->order_concurrent = true;
14903 3976 : break;
14904 :
14905 1017 : case OMP_CLAUSE_DEFAULTMAP:
14906 1017 : enum gimplify_defaultmap_kind gdmkmin, gdmkmax;
14907 1017 : switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c))
14908 : {
14909 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
14910 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
14911 : gdmkmin = GDMK_SCALAR;
14912 : gdmkmax = GDMK_POINTER;
14913 : break;
14914 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
14915 : gdmkmin = GDMK_SCALAR;
14916 : gdmkmax = GDMK_SCALAR_TARGET;
14917 : break;
14918 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
14919 : gdmkmin = gdmkmax = GDMK_AGGREGATE;
14920 : break;
14921 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE:
14922 : gdmkmin = gdmkmax = GDMK_ALLOCATABLE;
14923 : break;
14924 : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
14925 : gdmkmin = gdmkmax = GDMK_POINTER;
14926 : break;
14927 0 : default:
14928 0 : gcc_unreachable ();
14929 : }
14930 4513 : for (int gdmk = gdmkmin; gdmk <= gdmkmax; gdmk++)
14931 3496 : switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (c))
14932 : {
14933 91 : case OMP_CLAUSE_DEFAULTMAP_ALLOC:
14934 91 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_ALLOC_ONLY;
14935 91 : break;
14936 96 : case OMP_CLAUSE_DEFAULTMAP_TO:
14937 96 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_TO_ONLY;
14938 96 : break;
14939 28 : case OMP_CLAUSE_DEFAULTMAP_FROM:
14940 28 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FROM_ONLY;
14941 28 : break;
14942 671 : case OMP_CLAUSE_DEFAULTMAP_TOFROM:
14943 671 : ctx->defaultmap[gdmk] = GOVD_MAP;
14944 671 : break;
14945 380 : case OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE:
14946 380 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14947 380 : break;
14948 2129 : case OMP_CLAUSE_DEFAULTMAP_NONE:
14949 2129 : ctx->defaultmap[gdmk] = 0;
14950 2129 : break;
14951 45 : case OMP_CLAUSE_DEFAULTMAP_PRESENT:
14952 45 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
14953 45 : break;
14954 56 : case OMP_CLAUSE_DEFAULTMAP_DEFAULT:
14955 56 : switch (gdmk)
14956 : {
14957 11 : case GDMK_SCALAR:
14958 11 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14959 11 : break;
14960 11 : case GDMK_SCALAR_TARGET:
14961 11 : ctx->defaultmap[gdmk] = (lang_GNU_Fortran ()
14962 11 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
14963 11 : break;
14964 14 : case GDMK_AGGREGATE:
14965 14 : case GDMK_ALLOCATABLE:
14966 14 : ctx->defaultmap[gdmk] = GOVD_MAP;
14967 14 : break;
14968 20 : case GDMK_POINTER:
14969 20 : ctx->defaultmap[gdmk] = GOVD_MAP;
14970 20 : if (!lang_GNU_Fortran ())
14971 12 : ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY;
14972 : break;
14973 : default:
14974 : gcc_unreachable ();
14975 : }
14976 : break;
14977 0 : default:
14978 0 : gcc_unreachable ();
14979 : }
14980 : break;
14981 :
14982 824 : case OMP_CLAUSE_ALIGNED:
14983 824 : decl = OMP_CLAUSE_DECL (c);
14984 824 : if (error_operand_p (decl))
14985 : {
14986 : remove = true;
14987 : break;
14988 : }
14989 824 : if (gimplify_expr (&OMP_CLAUSE_ALIGNED_ALIGNMENT (c), pre_p, NULL,
14990 : is_gimple_val, fb_rvalue) == GS_ERROR)
14991 : {
14992 : remove = true;
14993 : break;
14994 : }
14995 824 : if (!is_global_var (decl)
14996 824 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
14997 592 : omp_add_variable (ctx, decl, GOVD_ALIGNED);
14998 : break;
14999 :
15000 489 : case OMP_CLAUSE_NONTEMPORAL:
15001 489 : decl = OMP_CLAUSE_DECL (c);
15002 489 : if (error_operand_p (decl))
15003 : {
15004 : remove = true;
15005 : break;
15006 : }
15007 489 : omp_add_variable (ctx, decl, GOVD_NONTEMPORAL);
15008 489 : break;
15009 :
15010 3323 : case OMP_CLAUSE_ALLOCATE:
15011 3323 : decl = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
15012 3323 : if (decl
15013 1554 : && TREE_CODE (decl) == INTEGER_CST
15014 3352 : && wi::eq_p (wi::to_widest (decl), GOMP_OMP_PREDEF_ALLOC_THREAD)
15015 3352 : && (code == OMP_TARGET || code == OMP_TASK || code == OMP_TASKLOOP))
15016 35 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
15017 : "allocator with access trait set to %<thread%> "
15018 : "results in undefined behavior for %qs directive",
15019 : code == OMP_TARGET ? "target"
15020 : : (code == OMP_TASK
15021 15 : ? "task" : "taskloop"));
15022 3323 : decl = OMP_CLAUSE_DECL (c);
15023 3323 : if (error_operand_p (decl))
15024 : {
15025 : remove = true;
15026 : break;
15027 : }
15028 3323 : if ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS) == 0
15029 3311 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
15030 4877 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST)
15031 : {
15032 353 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
15033 353 : tree clauses = NULL_TREE;
15034 :
15035 : /* Get clause list of the nearest enclosing target construct. */
15036 353 : if (ctx->code == OMP_TARGET)
15037 2 : clauses = *orig_list_p;
15038 : else
15039 : {
15040 351 : struct gimplify_omp_ctx *tctx = ctx->outer_context;
15041 538 : while (tctx && tctx->code != OMP_TARGET)
15042 187 : tctx = tctx->outer_context;
15043 351 : if (tctx)
15044 18 : clauses = tctx->clauses;
15045 : }
15046 :
15047 20 : if (clauses)
15048 : {
15049 18 : tree uc;
15050 18 : if (TREE_CODE (allocator) == MEM_REF
15051 18 : || TREE_CODE (allocator) == INDIRECT_REF)
15052 0 : allocator = TREE_OPERAND (allocator, 0);
15053 60 : for (uc = clauses; uc; uc = OMP_CLAUSE_CHAIN (uc))
15054 59 : if (OMP_CLAUSE_CODE (uc) == OMP_CLAUSE_USES_ALLOCATORS)
15055 : {
15056 17 : tree uc_allocator
15057 17 : = OMP_CLAUSE_USES_ALLOCATORS_ALLOCATOR (uc);
15058 17 : if (operand_equal_p (allocator, uc_allocator))
15059 : break;
15060 : }
15061 18 : if (uc == NULL_TREE)
15062 : {
15063 1 : error_at (OMP_CLAUSE_LOCATION (c), "allocator %qE "
15064 : "requires %<uses_allocators(%E)%> clause in "
15065 : "target region", allocator, allocator);
15066 1 : remove = true;
15067 1 : break;
15068 : }
15069 : }
15070 : }
15071 3322 : if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL,
15072 : is_gimple_val, fb_rvalue) == GS_ERROR)
15073 : {
15074 : remove = true;
15075 : break;
15076 : }
15077 3322 : else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
15078 3322 : || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
15079 : == INTEGER_CST))
15080 : ;
15081 352 : else if (code == OMP_TASKLOOP
15082 352 : || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
15083 66 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
15084 132 : = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
15085 : pre_p, NULL, false);
15086 : break;
15087 :
15088 4359 : case OMP_CLAUSE_DEFAULT:
15089 4359 : ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
15090 4359 : break;
15091 :
15092 644 : case OMP_CLAUSE_INCLUSIVE:
15093 644 : case OMP_CLAUSE_EXCLUSIVE:
15094 644 : decl = OMP_CLAUSE_DECL (c);
15095 644 : {
15096 644 : splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
15097 : (splay_tree_key) decl);
15098 644 : if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
15099 : {
15100 5 : error_at (OMP_CLAUSE_LOCATION (c),
15101 : "%qD specified in %qs clause but not in %<inscan%> "
15102 : "%<reduction%> clause on the containing construct",
15103 5 : decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
15104 5 : remove = true;
15105 : }
15106 : else
15107 : {
15108 639 : n->value |= GOVD_REDUCTION_INSCAN;
15109 639 : if (outer_ctx->region_type == ORT_SIMD
15110 520 : && outer_ctx->outer_context
15111 107 : && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
15112 : {
15113 107 : n = splay_tree_lookup (outer_ctx->outer_context->variables,
15114 : (splay_tree_key) decl);
15115 107 : if (n && (n->value & GOVD_REDUCTION) != 0)
15116 107 : n->value |= GOVD_REDUCTION_INSCAN;
15117 : }
15118 : }
15119 : }
15120 : break;
15121 :
15122 103 : case OMP_CLAUSE_NOVARIANTS:
15123 103 : OMP_CLAUSE_NOVARIANTS_EXPR (c)
15124 103 : = gimple_boolify (OMP_CLAUSE_NOVARIANTS_EXPR (c));
15125 103 : break;
15126 115 : case OMP_CLAUSE_NOCONTEXT:
15127 115 : OMP_CLAUSE_NOCONTEXT_EXPR (c)
15128 115 : = gimple_boolify (OMP_CLAUSE_NOCONTEXT_EXPR (c));
15129 115 : break;
15130 0 : case OMP_CLAUSE_NOHOST:
15131 0 : default:
15132 0 : gcc_unreachable ();
15133 : }
15134 :
15135 205056 : if (code == OACC_DATA
15136 5123 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15137 209867 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15138 4504 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15139 : remove = true;
15140 204749 : if (remove)
15141 1037 : *list_p = OMP_CLAUSE_CHAIN (c);
15142 : else
15143 204019 : list_p = &OMP_CLAUSE_CHAIN (c);
15144 205056 : }
15145 :
15146 130549 : if (groups)
15147 : {
15148 36370 : delete grpmap;
15149 18185 : delete groups;
15150 : }
15151 :
15152 130549 : ctx->clauses = *orig_list_p;
15153 130549 : gimplify_omp_ctxp = ctx;
15154 130549 : }
15155 :
15156 : /* Return true if DECL is a candidate for shared to firstprivate
15157 : optimization. We only consider non-addressable scalars, not
15158 : too big, and not references. */
15159 :
15160 : static bool
15161 403984 : omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
15162 : {
15163 403984 : if (TREE_ADDRESSABLE (decl))
15164 : return false;
15165 355282 : tree type = TREE_TYPE (decl);
15166 355282 : if (!is_gimple_reg_type (type)
15167 330463 : || TREE_CODE (type) == REFERENCE_TYPE
15168 681562 : || TREE_ADDRESSABLE (type))
15169 : return false;
15170 : /* Don't optimize too large decls, as each thread/task will have
15171 : its own. */
15172 326280 : HOST_WIDE_INT len = int_size_in_bytes (type);
15173 326280 : if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
15174 : return false;
15175 326263 : if (omp_privatize_by_reference (decl))
15176 : return false;
15177 : return true;
15178 : }
15179 :
15180 : /* Helper function of omp_find_stores_op and gimplify_adjust_omp_clauses*.
15181 : For omp_shared_to_firstprivate_optimizable_decl_p decl mark it as
15182 : GOVD_WRITTEN in outer contexts. */
15183 :
15184 : static void
15185 303414 : omp_mark_stores (struct gimplify_omp_ctx *ctx, tree decl)
15186 : {
15187 464963 : for (; ctx; ctx = ctx->outer_context)
15188 : {
15189 447909 : splay_tree_node n = splay_tree_lookup (ctx->variables,
15190 : (splay_tree_key) decl);
15191 447909 : if (n == NULL)
15192 157970 : continue;
15193 289939 : else if (n->value & GOVD_SHARED)
15194 : {
15195 9157 : n->value |= GOVD_WRITTEN;
15196 9157 : return;
15197 : }
15198 280782 : else if (n->value & GOVD_DATA_SHARE_CLASS)
15199 : return;
15200 : }
15201 : }
15202 :
15203 : /* Helper callback for walk_gimple_seq to discover possible stores
15204 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15205 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15206 : for those. */
15207 :
15208 : static tree
15209 1122927 : omp_find_stores_op (tree *tp, int *walk_subtrees, void *data)
15210 : {
15211 1122927 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15212 :
15213 1122927 : *walk_subtrees = 0;
15214 1122927 : if (!wi->is_lhs)
15215 : return NULL_TREE;
15216 :
15217 320973 : tree op = *tp;
15218 399789 : do
15219 : {
15220 399789 : if (handled_component_p (op))
15221 78816 : op = TREE_OPERAND (op, 0);
15222 320973 : else if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
15223 320973 : && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
15224 0 : op = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
15225 : else
15226 : break;
15227 : }
15228 : while (1);
15229 320973 : if (!DECL_P (op) || !omp_shared_to_firstprivate_optimizable_decl_p (op))
15230 57941 : return NULL_TREE;
15231 :
15232 263032 : omp_mark_stores (gimplify_omp_ctxp, op);
15233 263032 : return NULL_TREE;
15234 : }
15235 :
15236 : /* Helper callback for walk_gimple_seq to discover possible stores
15237 : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15238 : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15239 : for those. */
15240 :
15241 : static tree
15242 624202 : omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
15243 : bool *handled_ops_p,
15244 : struct walk_stmt_info *wi)
15245 : {
15246 624202 : gimple *stmt = gsi_stmt (*gsi_p);
15247 624202 : switch (gimple_code (stmt))
15248 : {
15249 : /* Don't recurse on OpenMP constructs for which
15250 : gimplify_adjust_omp_clauses already handled the bodies,
15251 : except handle gimple_omp_for_pre_body. */
15252 26625 : case GIMPLE_OMP_FOR:
15253 26625 : *handled_ops_p = true;
15254 26625 : if (gimple_omp_for_pre_body (stmt))
15255 1780 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15256 : omp_find_stores_stmt, omp_find_stores_op, wi);
15257 : break;
15258 8540 : case GIMPLE_OMP_PARALLEL:
15259 8540 : case GIMPLE_OMP_TASK:
15260 8540 : case GIMPLE_OMP_SECTIONS:
15261 8540 : case GIMPLE_OMP_SINGLE:
15262 8540 : case GIMPLE_OMP_SCOPE:
15263 8540 : case GIMPLE_OMP_TARGET:
15264 8540 : case GIMPLE_OMP_TEAMS:
15265 8540 : case GIMPLE_OMP_CRITICAL:
15266 8540 : *handled_ops_p = true;
15267 8540 : break;
15268 : default:
15269 : break;
15270 : }
15271 624202 : return NULL_TREE;
15272 : }
15273 :
15274 : struct gimplify_adjust_omp_clauses_data
15275 : {
15276 : tree *list_p;
15277 : gimple_seq *pre_p;
15278 : };
15279 :
15280 : /* For all variables that were not actually used within the context,
15281 : remove PRIVATE, SHARED, and FIRSTPRIVATE clauses. */
15282 :
15283 : static int
15284 672169 : gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
15285 : {
15286 672169 : tree *list_p = ((struct gimplify_adjust_omp_clauses_data *) data)->list_p;
15287 672169 : gimple_seq *pre_p
15288 : = ((struct gimplify_adjust_omp_clauses_data *) data)->pre_p;
15289 672169 : tree decl = (tree) n->key;
15290 672169 : unsigned flags = n->value;
15291 672169 : enum omp_clause_code code;
15292 672169 : tree clause;
15293 672169 : bool private_debug;
15294 :
15295 672169 : if (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
15296 132667 : && (flags & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
15297 : flags = GOVD_SHARED | GOVD_SEEN | GOVD_WRITTEN;
15298 672044 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
15299 : return 0;
15300 178419 : if ((flags & GOVD_SEEN) == 0)
15301 : return 0;
15302 157403 : if (flags & GOVD_DEBUG_PRIVATE)
15303 : {
15304 260 : gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_SHARED);
15305 : private_debug = true;
15306 : }
15307 157143 : else if (flags & GOVD_MAP)
15308 : private_debug = false;
15309 : else
15310 138961 : private_debug
15311 138961 : = lang_hooks.decls.omp_private_debug_clause (decl,
15312 138961 : !!(flags & GOVD_SHARED));
15313 138961 : if (private_debug)
15314 : code = OMP_CLAUSE_PRIVATE;
15315 157021 : else if (flags & GOVD_MAP)
15316 : {
15317 18182 : code = OMP_CLAUSE_MAP;
15318 18182 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15319 18182 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15320 : {
15321 2 : error ("%<_Atomic%> %qD in implicit %<map%> clause", decl);
15322 2 : return 0;
15323 : }
15324 18180 : if (VAR_P (decl)
15325 16242 : && DECL_IN_CONSTANT_POOL (decl)
15326 18181 : && !lookup_attribute ("omp declare target",
15327 1 : DECL_ATTRIBUTES (decl)))
15328 : {
15329 1 : tree id = get_identifier ("omp declare target");
15330 1 : DECL_ATTRIBUTES (decl)
15331 1 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
15332 1 : varpool_node *node = varpool_node::get (decl);
15333 1 : if (node)
15334 : {
15335 1 : node->offloadable = 1;
15336 1 : if (ENABLE_OFFLOADING)
15337 : g->have_offload = true;
15338 : }
15339 : }
15340 : }
15341 138839 : else if (flags & GOVD_SHARED)
15342 : {
15343 48872 : if (is_global_var (decl))
15344 : {
15345 16142 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15346 25329 : while (ctx != NULL)
15347 : {
15348 17604 : splay_tree_node on
15349 17604 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15350 17604 : if (on && (on->value & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
15351 : | GOVD_PRIVATE | GOVD_REDUCTION
15352 : | GOVD_LINEAR | GOVD_MAP)) != 0)
15353 : break;
15354 9187 : ctx = ctx->outer_context;
15355 : }
15356 16142 : if (ctx == NULL)
15357 : return 0;
15358 : }
15359 41147 : code = OMP_CLAUSE_SHARED;
15360 : /* Don't optimize shared into firstprivate for read-only vars
15361 : on tasks with depend clause, we shouldn't try to copy them
15362 : until the dependencies are satisfied. */
15363 41147 : if (gimplify_omp_ctxp->has_depend)
15364 350 : flags |= GOVD_WRITTEN;
15365 : }
15366 89967 : else if (flags & GOVD_PRIVATE)
15367 : code = OMP_CLAUSE_PRIVATE;
15368 31556 : else if (flags & GOVD_FIRSTPRIVATE)
15369 : {
15370 22071 : code = OMP_CLAUSE_FIRSTPRIVATE;
15371 22071 : if ((gimplify_omp_ctxp->region_type & ORT_TARGET)
15372 14020 : && (gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15373 32410 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15374 : {
15375 1 : error ("%<_Atomic%> %qD in implicit %<firstprivate%> clause on "
15376 : "%<target%> construct", decl);
15377 1 : return 0;
15378 : }
15379 : }
15380 9485 : else if (flags & GOVD_LASTPRIVATE)
15381 : code = OMP_CLAUSE_LASTPRIVATE;
15382 325 : else if (flags & (GOVD_ALIGNED | GOVD_NONTEMPORAL))
15383 : return 0;
15384 202 : else if (flags & GOVD_CONDTEMP)
15385 : {
15386 112 : code = OMP_CLAUSE__CONDTEMP_;
15387 112 : gimple_add_tmp_var (decl);
15388 : }
15389 90 : else if (flags & GOVD_USES_ALLOCATORS_ALLOCATOR)
15390 : return 0;
15391 : else
15392 0 : gcc_unreachable ();
15393 :
15394 140302 : if (((flags & GOVD_LASTPRIVATE)
15395 139612 : || (code == OMP_CLAUSE_SHARED && (flags & GOVD_WRITTEN)))
15396 155551 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15397 15235 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15398 :
15399 149462 : tree chain = *list_p;
15400 149462 : clause = build_omp_clause (input_location, code);
15401 149462 : OMP_CLAUSE_DECL (clause) = decl;
15402 149462 : OMP_CLAUSE_CHAIN (clause) = chain;
15403 149462 : if (private_debug)
15404 382 : OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
15405 149080 : else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
15406 6 : OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
15407 149074 : else if (code == OMP_CLAUSE_SHARED
15408 41147 : && (flags & GOVD_WRITTEN) == 0
15409 184132 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15410 21044 : OMP_CLAUSE_SHARED_READONLY (clause) = 1;
15411 128030 : else if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_EXPLICIT) == 0)
15412 22070 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clause) = 1;
15413 105960 : else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
15414 : {
15415 626 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
15416 626 : OMP_CLAUSE_DECL (nc) = decl;
15417 626 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
15418 626 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
15419 15 : OMP_CLAUSE_DECL (clause)
15420 30 : = build_fold_indirect_ref_loc (input_location, decl);
15421 626 : OMP_CLAUSE_DECL (clause)
15422 626 : = build2 (MEM_REF, char_type_node, OMP_CLAUSE_DECL (clause),
15423 : build_int_cst (build_pointer_type (char_type_node), 0));
15424 626 : OMP_CLAUSE_SIZE (clause) = size_zero_node;
15425 626 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15426 626 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
15427 626 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
15428 626 : tree dtype = TREE_TYPE (decl);
15429 626 : if (TREE_CODE (dtype) == REFERENCE_TYPE)
15430 15 : dtype = TREE_TYPE (dtype);
15431 : /* FIRSTPRIVATE_POINTER doesn't work well if we have a
15432 : multiply-indirected pointer. If we have a reference to a pointer to
15433 : a pointer, it's possible that this should really be
15434 : GOMP_MAP_FIRSTPRIVATE_REFERENCE -- but that also doesn't work at the
15435 : moment, so stick with this. (See PR113279 and testcases
15436 : baseptrs-{4,6}.C:ref2ptrptr_offset_decl_member_slice). */
15437 626 : if (TREE_CODE (dtype) == POINTER_TYPE
15438 626 : && TREE_CODE (TREE_TYPE (dtype)) == POINTER_TYPE)
15439 19 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15440 : else
15441 607 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15442 626 : OMP_CLAUSE_CHAIN (nc) = chain;
15443 626 : OMP_CLAUSE_CHAIN (clause) = nc;
15444 626 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15445 626 : gimplify_omp_ctxp = ctx->outer_context;
15446 626 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0),
15447 : pre_p, NULL, is_gimple_val, fb_rvalue);
15448 626 : gimplify_omp_ctxp = ctx;
15449 626 : }
15450 17554 : else if (code == OMP_CLAUSE_MAP)
15451 : {
15452 17554 : int kind;
15453 : /* Not all combinations of these GOVD_MAP flags are actually valid. */
15454 17554 : switch (flags & (GOVD_MAP_TO_ONLY
15455 : | GOVD_MAP_FORCE
15456 : | GOVD_MAP_FORCE_PRESENT
15457 : | GOVD_MAP_ALLOC_ONLY
15458 : | GOVD_MAP_FROM_ONLY))
15459 : {
15460 : case 0:
15461 : kind = GOMP_MAP_TOFROM;
15462 : break;
15463 1042 : case GOVD_MAP_FORCE:
15464 1042 : kind = GOMP_MAP_TOFROM | GOMP_MAP_FLAG_FORCE;
15465 1042 : break;
15466 1015 : case GOVD_MAP_TO_ONLY:
15467 1015 : kind = GOMP_MAP_TO;
15468 1015 : break;
15469 16 : case GOVD_MAP_FROM_ONLY:
15470 16 : kind = GOMP_MAP_FROM;
15471 16 : break;
15472 37 : case GOVD_MAP_ALLOC_ONLY:
15473 37 : kind = GOMP_MAP_ALLOC;
15474 37 : break;
15475 3 : case GOVD_MAP_TO_ONLY | GOVD_MAP_FORCE:
15476 3 : kind = GOMP_MAP_TO | GOMP_MAP_FLAG_FORCE;
15477 3 : break;
15478 : case GOVD_MAP_FORCE_PRESENT:
15479 326 : kind = GOMP_MAP_FORCE_PRESENT;
15480 : break;
15481 : case GOVD_MAP_FORCE_PRESENT | GOVD_MAP_ALLOC_ONLY:
15482 326 : kind = GOMP_MAP_FORCE_PRESENT;
15483 : break;
15484 0 : default:
15485 0 : gcc_unreachable ();
15486 : }
15487 17554 : OMP_CLAUSE_SET_MAP_KIND (clause, kind);
15488 : /* Setting of the implicit flag for the runtime is currently disabled for
15489 : OpenACC. */
15490 17554 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
15491 10020 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1;
15492 17554 : if (DECL_SIZE (decl)
15493 17554 : && !poly_int_tree_p (DECL_SIZE (decl)))
15494 : {
15495 535 : tree decl2 = DECL_VALUE_EXPR (decl);
15496 535 : gcc_assert (INDIRECT_REF_P (decl2));
15497 535 : decl2 = TREE_OPERAND (decl2, 0);
15498 535 : gcc_assert (DECL_P (decl2));
15499 535 : tree mem = build_simple_mem_ref (decl2);
15500 535 : OMP_CLAUSE_DECL (clause) = mem;
15501 535 : OMP_CLAUSE_SIZE (clause) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
15502 535 : if (gimplify_omp_ctxp->outer_context)
15503 : {
15504 446 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15505 446 : omp_notice_variable (ctx, decl2, true);
15506 446 : omp_notice_variable (ctx, OMP_CLAUSE_SIZE (clause), true);
15507 : }
15508 535 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15509 : OMP_CLAUSE_MAP);
15510 535 : OMP_CLAUSE_DECL (nc) = decl;
15511 535 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15512 535 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases)
15513 535 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15514 : else
15515 0 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15516 535 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15517 535 : OMP_CLAUSE_CHAIN (clause) = nc;
15518 : }
15519 17019 : else if (gimplify_omp_ctxp->target_firstprivatize_array_bases
15520 17019 : && omp_privatize_by_reference (decl))
15521 : {
15522 28 : OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl);
15523 28 : OMP_CLAUSE_SIZE (clause)
15524 28 : = unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))));
15525 28 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15526 28 : gimplify_omp_ctxp = ctx->outer_context;
15527 28 : gimplify_expr (&OMP_CLAUSE_SIZE (clause),
15528 : pre_p, NULL, is_gimple_val, fb_rvalue);
15529 28 : gimplify_omp_ctxp = ctx;
15530 28 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15531 : OMP_CLAUSE_MAP);
15532 28 : OMP_CLAUSE_DECL (nc) = decl;
15533 28 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15534 28 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
15535 28 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15536 28 : OMP_CLAUSE_CHAIN (clause) = nc;
15537 : }
15538 : else
15539 16991 : OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
15540 : }
15541 149462 : if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
15542 : {
15543 690 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
15544 690 : OMP_CLAUSE_DECL (nc) = decl;
15545 690 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
15546 690 : OMP_CLAUSE_CHAIN (nc) = chain;
15547 690 : OMP_CLAUSE_CHAIN (clause) = nc;
15548 690 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15549 690 : gimplify_omp_ctxp = ctx->outer_context;
15550 690 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
15551 690 : (ctx->region_type & ORT_ACC) != 0);
15552 690 : gimplify_omp_ctxp = ctx;
15553 : }
15554 149462 : *list_p = clause;
15555 149462 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15556 149462 : gimplify_omp_ctxp = ctx->outer_context;
15557 : /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
15558 : in simd. Those are only added for the local vars inside of simd body
15559 : and they don't need to be e.g. default constructible. */
15560 149462 : if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
15561 141412 : lang_hooks.decls.omp_finish_clause (clause, pre_p,
15562 141412 : (ctx->region_type & ORT_ACC) != 0);
15563 149462 : if (gimplify_omp_ctxp)
15564 183855 : for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
15565 93340 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
15566 93340 : && DECL_P (OMP_CLAUSE_SIZE (clause)))
15567 1241 : omp_notice_variable (gimplify_omp_ctxp, OMP_CLAUSE_SIZE (clause),
15568 : true);
15569 149462 : gimplify_omp_ctxp = ctx;
15570 149462 : return 0;
15571 : }
15572 :
15573 : static void
15574 129085 : gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
15575 : enum tree_code code,
15576 : gimple_seq *loops_seq_p = NULL)
15577 : {
15578 129085 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15579 129085 : tree *orig_list_p = list_p;
15580 129085 : tree c, decl;
15581 129085 : bool has_inscan_reductions = false;
15582 :
15583 129085 : if (body)
15584 : {
15585 : struct gimplify_omp_ctx *octx;
15586 224932 : for (octx = ctx; octx; octx = octx->outer_context)
15587 173577 : if ((octx->region_type & (ORT_PARALLEL | ORT_TASK | ORT_TEAMS)) != 0)
15588 : break;
15589 111501 : if (octx)
15590 : {
15591 60146 : struct walk_stmt_info wi;
15592 60146 : memset (&wi, 0, sizeof (wi));
15593 60146 : walk_gimple_seq (body, omp_find_stores_stmt,
15594 : omp_find_stores_op, &wi);
15595 : }
15596 : }
15597 :
15598 129085 : if (ctx->add_safelen1)
15599 : {
15600 : /* If there are VLAs in the body of simd loop, prevent
15601 : vectorization. */
15602 2 : gcc_assert (ctx->region_type == ORT_SIMD);
15603 2 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
15604 2 : OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node;
15605 2 : OMP_CLAUSE_CHAIN (c) = *list_p;
15606 2 : *list_p = c;
15607 2 : list_p = &OMP_CLAUSE_CHAIN (c);
15608 : }
15609 :
15610 129085 : if (ctx->region_type == ORT_WORKSHARE
15611 39684 : && ctx->outer_context
15612 27837 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
15613 : {
15614 24858 : for (c = ctx->outer_context->clauses; c; c = OMP_CLAUSE_CHAIN (c))
15615 12516 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15616 12516 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
15617 : {
15618 125 : decl = OMP_CLAUSE_DECL (c);
15619 125 : splay_tree_node n
15620 125 : = splay_tree_lookup (ctx->outer_context->variables,
15621 : (splay_tree_key) decl);
15622 125 : gcc_checking_assert (!splay_tree_lookup (ctx->variables,
15623 : (splay_tree_key) decl));
15624 125 : omp_add_variable (ctx, decl, n->value);
15625 125 : tree c2 = copy_node (c);
15626 125 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15627 125 : *list_p = c2;
15628 125 : if ((n->value & GOVD_FIRSTPRIVATE) == 0)
15629 103 : continue;
15630 22 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
15631 : OMP_CLAUSE_FIRSTPRIVATE);
15632 22 : OMP_CLAUSE_DECL (c2) = decl;
15633 22 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15634 22 : *list_p = c2;
15635 : }
15636 : }
15637 :
15638 129085 : if (code == OMP_TARGET
15639 129085 : || code == OMP_TARGET_DATA
15640 129085 : || code == OMP_TARGET_ENTER_DATA
15641 112791 : || code == OMP_TARGET_EXIT_DATA)
15642 : {
15643 17080 : tree mapper_clauses = NULL_TREE;
15644 17080 : instantiate_mapper_info im_info;
15645 :
15646 17080 : im_info.mapper_clauses_p = &mapper_clauses;
15647 17080 : im_info.omp_ctx = ctx;
15648 17080 : im_info.pre_p = pre_p;
15649 :
15650 17080 : splay_tree_foreach (ctx->variables,
15651 : omp_instantiate_implicit_mappers,
15652 : (void *) &im_info);
15653 :
15654 17080 : if (mapper_clauses)
15655 : {
15656 53 : mapper_clauses
15657 53 : = lang_hooks.decls.omp_finish_mapper_clauses (mapper_clauses);
15658 :
15659 : /* Stick the implicitly-expanded mapper clauses at the end of the
15660 : clause list. */
15661 53 : tree *tail = list_p;
15662 163 : while (*tail)
15663 110 : tail = &OMP_CLAUSE_CHAIN (*tail);
15664 53 : *tail = mapper_clauses;
15665 : }
15666 :
15667 17080 : vec<omp_mapping_group> *groups;
15668 17080 : groups = omp_gather_mapping_groups (list_p);
15669 17080 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
15670 :
15671 17080 : if (groups)
15672 : {
15673 8522 : grpmap = omp_index_mapping_groups (groups);
15674 :
15675 8522 : omp_resolve_clause_dependencies (code, groups, grpmap);
15676 8522 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15677 : &grpmap, list_p);
15678 :
15679 8522 : omp_mapping_group *outlist = NULL;
15680 :
15681 17044 : delete grpmap;
15682 8522 : delete groups;
15683 :
15684 : /* Rebuild now we have struct sibling lists. */
15685 8522 : groups = omp_gather_mapping_groups (list_p);
15686 8522 : grpmap = omp_index_mapping_groups (groups);
15687 :
15688 8522 : bool enter_exit = (code == OMP_TARGET_ENTER_DATA
15689 8522 : || code == OMP_TARGET_EXIT_DATA);
15690 :
15691 8522 : outlist = omp_tsort_mapping_groups (groups, grpmap, enter_exit);
15692 8522 : outlist = omp_segregate_mapping_groups (outlist);
15693 8522 : list_p = omp_reorder_mapping_groups (groups, outlist, list_p);
15694 :
15695 8522 : delete grpmap;
15696 8522 : delete groups;
15697 : }
15698 17080 : }
15699 112005 : else if (ctx->region_type & ORT_ACC)
15700 : {
15701 29847 : vec<omp_mapping_group> *groups;
15702 29847 : groups = omp_gather_mapping_groups (list_p);
15703 29847 : if (groups)
15704 : {
15705 9462 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap;
15706 9462 : grpmap = omp_index_mapping_groups (groups);
15707 :
15708 9462 : oacc_resolve_clause_dependencies (groups, grpmap);
15709 9462 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15710 : &grpmap, list_p);
15711 :
15712 9462 : delete groups;
15713 18924 : delete grpmap;
15714 : }
15715 : }
15716 :
15717 129085 : tree attach_list = NULL_TREE;
15718 129085 : tree *attach_tail = &attach_list;
15719 :
15720 129085 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
15721 :
15722 377602 : while ((c = *list_p) != NULL)
15723 : {
15724 248517 : splay_tree_node n;
15725 248517 : bool remove = false;
15726 248517 : bool move_attach = false;
15727 :
15728 291114 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
15729 : grp_end = NULL_TREE;
15730 :
15731 248517 : switch (OMP_CLAUSE_CODE (c))
15732 : {
15733 8001 : case OMP_CLAUSE_FIRSTPRIVATE:
15734 8001 : if ((ctx->region_type & ORT_TARGET)
15735 1966 : && (ctx->region_type & ORT_ACC) == 0
15736 9361 : && TYPE_ATOMIC (strip_array_types
15737 : (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
15738 : {
15739 4 : error_at (OMP_CLAUSE_LOCATION (c),
15740 : "%<_Atomic%> %qD in %<firstprivate%> clause on "
15741 2 : "%<target%> construct", OMP_CLAUSE_DECL (c));
15742 2 : remove = true;
15743 2 : break;
15744 : }
15745 7999 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
15746 : {
15747 380 : decl = OMP_CLAUSE_DECL (c);
15748 380 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15749 380 : if ((n->value & GOVD_MAP) != 0)
15750 : {
15751 : remove = true;
15752 : break;
15753 : }
15754 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0;
15755 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0;
15756 : }
15757 : /* FALLTHRU */
15758 36694 : case OMP_CLAUSE_PRIVATE:
15759 36694 : case OMP_CLAUSE_SHARED:
15760 36694 : case OMP_CLAUSE_LINEAR:
15761 36694 : decl = OMP_CLAUSE_DECL (c);
15762 36694 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15763 36694 : remove = !(n->value & GOVD_SEEN);
15764 36694 : if ((n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0
15765 48 : && code == OMP_PARALLEL
15766 36716 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15767 : remove = true;
15768 36672 : if (! remove)
15769 : {
15770 32073 : bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
15771 32073 : if ((n->value & GOVD_DEBUG_PRIVATE)
15772 32073 : || lang_hooks.decls.omp_private_debug_clause (decl, shared))
15773 : {
15774 87 : gcc_assert ((n->value & GOVD_DEBUG_PRIVATE) == 0
15775 : || ((n->value & GOVD_DATA_SHARE_CLASS)
15776 : == GOVD_SHARED));
15777 87 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
15778 87 : OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
15779 : }
15780 32073 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15781 4129 : && ctx->has_depend
15782 32631 : && DECL_P (decl))
15783 558 : n->value |= GOVD_WRITTEN;
15784 32073 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15785 4129 : && (n->value & GOVD_WRITTEN) == 0
15786 3012 : && DECL_P (decl)
15787 35085 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15788 526 : OMP_CLAUSE_SHARED_READONLY (c) = 1;
15789 31547 : else if (DECL_P (decl)
15790 31547 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15791 3603 : && (n->value & GOVD_WRITTEN) != 0)
15792 30430 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15793 9008 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
15794 38561 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15795 5734 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15796 : }
15797 : else
15798 4621 : n->value &= ~GOVD_EXPLICIT;
15799 : break;
15800 :
15801 12932 : case OMP_CLAUSE_LASTPRIVATE:
15802 : /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
15803 : accurately reflect the presence of a FIRSTPRIVATE clause. */
15804 12932 : decl = OMP_CLAUSE_DECL (c);
15805 12932 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15806 12932 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
15807 12932 : = (n->value & GOVD_FIRSTPRIVATE) != 0;
15808 12932 : if (code == OMP_DISTRIBUTE
15809 12932 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
15810 : {
15811 4 : remove = true;
15812 4 : error_at (OMP_CLAUSE_LOCATION (c),
15813 : "same variable used in %<firstprivate%> and "
15814 : "%<lastprivate%> clauses on %<distribute%> "
15815 : "construct");
15816 : }
15817 12932 : if (!remove
15818 12928 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15819 12928 : && DECL_P (decl)
15820 12928 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15821 11411 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15822 12932 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && code == OMP_PARALLEL)
15823 : remove = true;
15824 : break;
15825 :
15826 824 : case OMP_CLAUSE_ALIGNED:
15827 824 : decl = OMP_CLAUSE_DECL (c);
15828 824 : if (!is_global_var (decl))
15829 : {
15830 738 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15831 738 : remove = n == NULL || !(n->value & GOVD_SEEN);
15832 88 : if (!remove && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
15833 : {
15834 88 : struct gimplify_omp_ctx *octx;
15835 88 : if (n != NULL
15836 88 : && (n->value & (GOVD_DATA_SHARE_CLASS
15837 : & ~GOVD_FIRSTPRIVATE)))
15838 : remove = true;
15839 : else
15840 100 : for (octx = ctx->outer_context; octx;
15841 12 : octx = octx->outer_context)
15842 : {
15843 24 : n = splay_tree_lookup (octx->variables,
15844 : (splay_tree_key) decl);
15845 24 : if (n == NULL)
15846 12 : continue;
15847 12 : if (n->value & GOVD_LOCAL)
15848 : break;
15849 : /* We have to avoid assigning a shared variable
15850 : to itself when trying to add
15851 : __builtin_assume_aligned. */
15852 12 : if (n->value & GOVD_SHARED)
15853 : {
15854 : remove = true;
15855 : break;
15856 : }
15857 : }
15858 : }
15859 : }
15860 86 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
15861 : {
15862 86 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15863 86 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
15864 : remove = true;
15865 : }
15866 : break;
15867 :
15868 552 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
15869 552 : decl = OMP_CLAUSE_DECL (c);
15870 552 : while (INDIRECT_REF_P (decl)
15871 601 : || TREE_CODE (decl) == ARRAY_REF)
15872 49 : decl = TREE_OPERAND (decl, 0);
15873 552 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15874 552 : remove = n == NULL || !(n->value & GOVD_SEEN);
15875 : break;
15876 :
15877 900 : case OMP_CLAUSE_IS_DEVICE_PTR:
15878 900 : case OMP_CLAUSE_NONTEMPORAL:
15879 900 : decl = OMP_CLAUSE_DECL (c);
15880 900 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15881 900 : remove = n == NULL || !(n->value & GOVD_SEEN);
15882 : break;
15883 :
15884 56676 : case OMP_CLAUSE_MAP:
15885 56676 : if (OMP_CLAUSE_MAP_GIMPLE_ONLY (c))
15886 : {
15887 90 : remove = true;
15888 90 : goto end_adjust_omp_map_clause;
15889 : }
15890 56586 : decl = OMP_CLAUSE_DECL (c);
15891 56586 : if (!grp_end)
15892 : {
15893 31698 : grp_start_p = list_p;
15894 31698 : grp_end = *omp_group_last (grp_start_p);
15895 : }
15896 56586 : switch (OMP_CLAUSE_MAP_KIND (c))
15897 : {
15898 181 : case GOMP_MAP_PRESENT_ALLOC:
15899 181 : case GOMP_MAP_PRESENT_TO:
15900 181 : case GOMP_MAP_PRESENT_FROM:
15901 181 : case GOMP_MAP_PRESENT_TOFROM:
15902 181 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_PRESENT);
15903 181 : break;
15904 : default:
15905 : break;
15906 : }
15907 56586 : switch (code)
15908 : {
15909 4563 : case OACC_DATA:
15910 4563 : if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
15911 : break;
15912 : /* Fallthrough. */
15913 19222 : case OACC_HOST_DATA:
15914 19222 : case OACC_ENTER_DATA:
15915 19222 : case OACC_EXIT_DATA:
15916 19222 : case OMP_TARGET_DATA:
15917 19222 : case OMP_TARGET_ENTER_DATA:
15918 19222 : case OMP_TARGET_EXIT_DATA:
15919 19222 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15920 19222 : || (OMP_CLAUSE_MAP_KIND (c)
15921 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15922 : /* For target {,enter ,exit }data only the array slice is
15923 : mapped, but not the pointer to it. */
15924 : remove = true;
15925 19222 : if (code == OMP_TARGET_EXIT_DATA
15926 19222 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
15927 2794 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER))
15928 : remove = true;
15929 : break;
15930 : case OMP_TARGET:
15931 : break;
15932 : default:
15933 : break;
15934 : }
15935 19220 : if (remove)
15936 : break;
15937 56251 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
15938 : {
15939 : /* Sanity check: attach/detach map kinds use the size as a bias,
15940 : and it's never right to use the decl size for such
15941 : mappings. */
15942 17719 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
15943 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
15944 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DETACH
15945 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
15946 : && (OMP_CLAUSE_MAP_KIND (c)
15947 : != GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
15948 21775 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
15949 4056 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
15950 : }
15951 56251 : gimplify_omp_ctxp = ctx->outer_context;
15952 56251 : gimple_seq *seq_p;
15953 56251 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
15954 56251 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
15955 : is_gimple_val, fb_rvalue) == GS_ERROR)
15956 : {
15957 0 : gimplify_omp_ctxp = ctx;
15958 0 : remove = true;
15959 0 : goto end_adjust_omp_map_clause;
15960 : }
15961 56251 : else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15962 53356 : || (OMP_CLAUSE_MAP_KIND (c)
15963 : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15964 52943 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15965 62864 : && TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
15966 : {
15967 912 : OMP_CLAUSE_SIZE (c)
15968 912 : = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), seq_p, NULL,
15969 : false);
15970 912 : if ((ctx->region_type & ORT_TARGET) != 0)
15971 703 : omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
15972 : GOVD_FIRSTPRIVATE | GOVD_SEEN);
15973 : }
15974 56251 : gimplify_omp_ctxp = ctx;
15975 : /* Data clauses associated with reductions must be
15976 : compatible with present_or_copy. Warn and adjust the clause
15977 : if that is not the case. */
15978 56251 : if (ctx->region_type == ORT_ACC_PARALLEL
15979 47272 : || ctx->region_type == ORT_ACC_SERIAL)
15980 : {
15981 9535 : tree t = DECL_P (decl) ? decl : TREE_OPERAND (decl, 0);
15982 9535 : n = NULL;
15983 :
15984 9535 : if (DECL_P (t))
15985 7770 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
15986 :
15987 7770 : if (n && (n->value & GOVD_REDUCTION))
15988 : {
15989 809 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
15990 :
15991 809 : OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1;
15992 809 : if ((kind & GOMP_MAP_TOFROM) != GOMP_MAP_TOFROM
15993 159 : && kind != GOMP_MAP_FORCE_PRESENT
15994 159 : && kind != GOMP_MAP_POINTER)
15995 : {
15996 120 : warning_at (OMP_CLAUSE_LOCATION (c), 0,
15997 : "incompatible data clause with reduction "
15998 : "on %qE; promoting to %<present_or_copy%>",
15999 120 : DECL_NAME (t));
16000 120 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
16001 : }
16002 : }
16003 : }
16004 56251 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
16005 53467 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
16006 56525 : && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
16007 : {
16008 534 : remove = true;
16009 534 : goto end_adjust_omp_map_clause;
16010 : }
16011 : /* If we have a DECL_VALUE_EXPR (e.g. this is a class member and/or
16012 : a variable captured in a lambda closure), look through that now
16013 : before the DECL_P check below. (A code other than COMPONENT_REF,
16014 : i.e. INDIRECT_REF, will be a VLA/variable-length array
16015 : section. A global var may be a variable in a common block. We
16016 : don't want to do this here for either of those.) */
16017 55717 : if ((ctx->region_type & ORT_ACC) == 0
16018 29510 : && DECL_P (decl)
16019 12621 : && !is_global_var (decl)
16020 11229 : && DECL_HAS_VALUE_EXPR_P (decl)
16021 55907 : && TREE_CODE (DECL_VALUE_EXPR (decl)) == COMPONENT_REF)
16022 0 : decl = OMP_CLAUSE_DECL (c) = DECL_VALUE_EXPR (decl);
16023 55717 : if (TREE_CODE (decl) == TARGET_EXPR)
16024 : {
16025 0 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
16026 : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
16027 26180 : remove = true;
16028 : }
16029 55717 : else if (!DECL_P (decl))
16030 : {
16031 29537 : if ((ctx->region_type & ORT_TARGET) != 0
16032 29537 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
16033 : {
16034 24 : if (INDIRECT_REF_P (decl)
16035 0 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
16036 24 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
16037 : == REFERENCE_TYPE))
16038 0 : decl = TREE_OPERAND (decl, 0);
16039 24 : if (TREE_CODE (decl) == COMPONENT_REF)
16040 : {
16041 0 : while (TREE_CODE (decl) == COMPONENT_REF)
16042 0 : decl = TREE_OPERAND (decl, 0);
16043 0 : if (DECL_P (decl))
16044 : {
16045 0 : n = splay_tree_lookup (ctx->variables,
16046 : (splay_tree_key) decl);
16047 0 : if (!(n->value & GOVD_SEEN))
16048 29537 : remove = true;
16049 : }
16050 : }
16051 : }
16052 :
16053 29537 : tree d = decl, *pd;
16054 29537 : if (TREE_CODE (d) == ARRAY_REF)
16055 : {
16056 5726 : while (TREE_CODE (d) == ARRAY_REF)
16057 2923 : d = TREE_OPERAND (d, 0);
16058 2803 : if (TREE_CODE (d) == COMPONENT_REF
16059 2803 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
16060 : decl = d;
16061 : }
16062 29537 : pd = &OMP_CLAUSE_DECL (c);
16063 29537 : if (d == decl
16064 27091 : && TREE_CODE (decl) == INDIRECT_REF
16065 15451 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
16066 1471 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
16067 : == REFERENCE_TYPE)
16068 30337 : && (OMP_CLAUSE_MAP_KIND (c)
16069 : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
16070 : {
16071 796 : pd = &TREE_OPERAND (decl, 0);
16072 796 : decl = TREE_OPERAND (decl, 0);
16073 : }
16074 :
16075 29537 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16076 3067 : switch (code)
16077 : {
16078 427 : case OACC_ENTER_DATA:
16079 427 : case OACC_EXIT_DATA:
16080 427 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
16081 : == ARRAY_TYPE)
16082 : remove = true;
16083 417 : else if (code == OACC_ENTER_DATA)
16084 263 : goto change_to_attach;
16085 : /* Fallthrough. */
16086 605 : case OMP_TARGET_EXIT_DATA:
16087 605 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DETACH);
16088 605 : OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c) = 0;
16089 605 : break;
16090 71 : case OACC_UPDATE:
16091 : /* An "attach/detach" operation on an update directive
16092 : should behave as a GOMP_MAP_ALWAYS_POINTER. Note that
16093 : both GOMP_MAP_ATTACH_DETACH and GOMP_MAP_ALWAYS_POINTER
16094 : kinds depend on the previous mapping (for non-TARGET
16095 : regions). */
16096 71 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
16097 71 : break;
16098 2391 : default:
16099 2391 : change_to_attach:
16100 2391 : gcc_assert (!OMP_CLAUSE_MAP_SIZE_NEEDS_ADJUSTMENT (c));
16101 2391 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH);
16102 2391 : if ((ctx->region_type & ORT_TARGET) != 0)
16103 1803 : move_attach = true;
16104 : }
16105 26470 : else if ((ctx->region_type & ORT_TARGET) != 0
16106 26470 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16107 11798 : || (OMP_CLAUSE_MAP_KIND (c)
16108 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16109 : move_attach = true;
16110 :
16111 : /* If we have e.g. map(struct: *var), don't gimplify the
16112 : argument since omp-low.cc wants to see the decl itself. */
16113 29537 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
16114 1136 : goto end_adjust_omp_map_clause;
16115 :
16116 : /* We've already partly gimplified this in
16117 : gimplify_scan_omp_clauses. Don't do any more. */
16118 28401 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
16119 88 : goto end_adjust_omp_map_clause;
16120 :
16121 28313 : gimplify_omp_ctxp = ctx->outer_context;
16122 28313 : if (gimplify_expr (pd, seq_p, NULL, is_gimple_lvalue,
16123 : fb_lvalue) == GS_ERROR)
16124 0 : remove = true;
16125 28313 : gimplify_omp_ctxp = ctx;
16126 28313 : goto end_adjust_omp_map_clause;
16127 : }
16128 :
16129 26180 : if ((code == OMP_TARGET
16130 : || code == OMP_TARGET_DATA
16131 : || code == OMP_TARGET_ENTER_DATA
16132 14448 : || code == OMP_TARGET_EXIT_DATA)
16133 26807 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16134 : {
16135 238 : bool firstprivatize = false;
16136 :
16137 243 : for (struct gimplify_omp_ctx *octx = ctx->outer_context; octx;
16138 5 : octx = octx->outer_context)
16139 : {
16140 6 : splay_tree_node n
16141 12 : = splay_tree_lookup (octx->variables,
16142 6 : (splay_tree_key) OMP_CLAUSE_DECL (c));
16143 : /* If this is contained in an outer OpenMP region as a
16144 : firstprivate value, remove the attach/detach. */
16145 6 : if (n && (n->value & GOVD_FIRSTPRIVATE))
16146 : {
16147 : firstprivatize = true;
16148 : break;
16149 : }
16150 : }
16151 :
16152 238 : enum gomp_map_kind map_kind;
16153 238 : if (firstprivatize)
16154 : map_kind = GOMP_MAP_FIRSTPRIVATE_POINTER;
16155 237 : else if (code == OMP_TARGET_EXIT_DATA)
16156 : map_kind = GOMP_MAP_DETACH;
16157 : else
16158 186 : map_kind = GOMP_MAP_ATTACH;
16159 238 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16160 : }
16161 25942 : else if ((ctx->region_type & ORT_ACC) != 0
16162 25942 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16163 : {
16164 0 : enum gomp_map_kind map_kind = (code == OACC_EXIT_DATA
16165 0 : ? GOMP_MAP_DETACH
16166 : : GOMP_MAP_ATTACH);
16167 0 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16168 : }
16169 :
16170 26180 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16171 26180 : if ((ctx->region_type & ORT_TARGET) != 0
16172 16266 : && !(n->value & GOVD_SEEN)
16173 1487 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) == 0
16174 27420 : && (!is_global_var (decl)
16175 75 : || !lookup_attribute ("omp declare target link",
16176 75 : DECL_ATTRIBUTES (decl))))
16177 : {
16178 1228 : remove = true;
16179 : /* For struct element mapping, if struct is never referenced
16180 : in target block and none of the mapping has always modifier,
16181 : remove all the struct element mappings, which immediately
16182 : follow the GOMP_MAP_STRUCT map clause. */
16183 1228 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
16184 1228 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
16185 : {
16186 30 : HOST_WIDE_INT cnt = tree_to_shwi (OMP_CLAUSE_SIZE (c));
16187 80 : while (cnt--)
16188 50 : OMP_CLAUSE_CHAIN (c)
16189 50 : = OMP_CLAUSE_CHAIN (OMP_CLAUSE_CHAIN (c));
16190 : }
16191 : }
16192 24952 : else if (DECL_SIZE (decl)
16193 24928 : && !poly_int_tree_p (DECL_SIZE (decl))
16194 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER
16195 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
16196 25003 : && (OMP_CLAUSE_MAP_KIND (c)
16197 : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
16198 : {
16199 : /* For GOMP_MAP_FORCE_DEVICEPTR, we'll never enter here, because
16200 : for these, TREE_CODE (DECL_SIZE (decl)) will always be
16201 : INTEGER_CST. */
16202 51 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
16203 :
16204 51 : tree decl2 = DECL_VALUE_EXPR (decl);
16205 51 : gcc_assert (INDIRECT_REF_P (decl2));
16206 51 : decl2 = TREE_OPERAND (decl2, 0);
16207 51 : gcc_assert (DECL_P (decl2));
16208 51 : tree mem = build_simple_mem_ref (decl2);
16209 51 : OMP_CLAUSE_DECL (c) = mem;
16210 51 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16211 51 : if (ctx->outer_context)
16212 : {
16213 15 : omp_notice_variable (ctx->outer_context, decl2, true);
16214 30 : omp_notice_variable (ctx->outer_context,
16215 15 : OMP_CLAUSE_SIZE (c), true);
16216 : }
16217 51 : if (((ctx->region_type & ORT_TARGET) != 0
16218 24 : || !ctx->target_firstprivatize_array_bases)
16219 34 : && ((n->value & GOVD_SEEN) == 0
16220 30 : || (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0))
16221 : {
16222 34 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16223 : OMP_CLAUSE_MAP);
16224 34 : OMP_CLAUSE_DECL (nc) = decl;
16225 34 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
16226 34 : if (ctx->target_firstprivatize_array_bases)
16227 27 : OMP_CLAUSE_SET_MAP_KIND (nc,
16228 : GOMP_MAP_FIRSTPRIVATE_POINTER);
16229 : else
16230 7 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
16231 34 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
16232 34 : OMP_CLAUSE_CHAIN (c) = nc;
16233 34 : c = nc;
16234 : }
16235 : }
16236 : else
16237 : {
16238 24901 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16239 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16240 24901 : gcc_assert ((n->value & GOVD_SEEN) == 0
16241 : || ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16242 : == 0));
16243 : }
16244 :
16245 : /* If we have a target region, we can push all the attaches to the
16246 : end of the list (we may have standalone "attach" operations
16247 : synthesized for GOMP_MAP_STRUCT nodes that must be processed after
16248 : the attachment point AND the pointed-to block have been mapped).
16249 : If we have something else, e.g. "enter data", we need to keep
16250 : "attach" nodes together with the previous node they attach to so
16251 : that separate "exit data" operations work properly (see
16252 : libgomp/target.c). */
16253 26180 : if ((ctx->region_type & ORT_TARGET) != 0
16254 26180 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16255 16150 : || (OMP_CLAUSE_MAP_KIND (c)
16256 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16257 : move_attach = true;
16258 :
16259 56341 : end_adjust_omp_map_clause:
16260 56341 : exit_omp_iterator_loop_context (c);
16261 56341 : break;
16262 :
16263 8335 : case OMP_CLAUSE_TO:
16264 8335 : case OMP_CLAUSE_FROM:
16265 8335 : case OMP_CLAUSE__CACHE_:
16266 8335 : decl = OMP_CLAUSE_DECL (c);
16267 8335 : if (!DECL_P (decl))
16268 : break;
16269 6190 : if (DECL_SIZE (decl)
16270 6190 : && !poly_int_tree_p (DECL_SIZE (decl)))
16271 : {
16272 4 : tree decl2 = DECL_VALUE_EXPR (decl);
16273 4 : gcc_assert (INDIRECT_REF_P (decl2));
16274 4 : decl2 = TREE_OPERAND (decl2, 0);
16275 4 : gcc_assert (DECL_P (decl2));
16276 4 : tree mem = build_simple_mem_ref (decl2);
16277 4 : OMP_CLAUSE_DECL (c) = mem;
16278 4 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16279 4 : if (ctx->outer_context)
16280 : {
16281 4 : omp_notice_variable (ctx->outer_context, decl2, true);
16282 4 : omp_notice_variable (ctx->outer_context,
16283 4 : OMP_CLAUSE_SIZE (c), true);
16284 : }
16285 : }
16286 6186 : else if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16287 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16288 : break;
16289 :
16290 15242 : case OMP_CLAUSE_REDUCTION:
16291 15242 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
16292 : {
16293 815 : decl = OMP_CLAUSE_DECL (c);
16294 815 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16295 815 : if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
16296 : {
16297 69 : remove = true;
16298 69 : error_at (OMP_CLAUSE_LOCATION (c),
16299 : "%qD specified in %<inscan%> %<reduction%> clause "
16300 : "but not in %<scan%> directive clause", decl);
16301 69 : break;
16302 : }
16303 : has_inscan_reductions = true;
16304 : }
16305 : /* FALLTHRU */
16306 17777 : case OMP_CLAUSE_IN_REDUCTION:
16307 17777 : case OMP_CLAUSE_TASK_REDUCTION:
16308 17777 : decl = OMP_CLAUSE_DECL (c);
16309 : /* OpenACC reductions need a present_or_copy data clause.
16310 : Add one if necessary. Emit error when the reduction is private. */
16311 17777 : if (ctx->region_type == ORT_ACC_PARALLEL
16312 17245 : || ctx->region_type == ORT_ACC_SERIAL)
16313 : {
16314 803 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16315 803 : if (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16316 : {
16317 13 : remove = true;
16318 13 : error_at (OMP_CLAUSE_LOCATION (c), "invalid private "
16319 13 : "reduction on %qE", DECL_NAME (decl));
16320 : }
16321 790 : else if ((n->value & GOVD_MAP) == 0)
16322 : {
16323 524 : tree next = OMP_CLAUSE_CHAIN (c);
16324 524 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP);
16325 524 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM);
16326 524 : OMP_CLAUSE_DECL (nc) = decl;
16327 524 : OMP_CLAUSE_CHAIN (c) = nc;
16328 524 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
16329 524 : (ctx->region_type
16330 : & ORT_ACC) != 0);
16331 550 : while (1)
16332 : {
16333 537 : OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1;
16334 537 : if (OMP_CLAUSE_CHAIN (nc) == NULL)
16335 : break;
16336 13 : nc = OMP_CLAUSE_CHAIN (nc);
16337 : }
16338 524 : OMP_CLAUSE_CHAIN (nc) = next;
16339 524 : n->value |= GOVD_MAP;
16340 : }
16341 : }
16342 17777 : if (DECL_P (decl)
16343 17777 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
16344 8002 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
16345 : break;
16346 :
16347 3322 : case OMP_CLAUSE_ALLOCATE:
16348 3322 : decl = OMP_CLAUSE_DECL (c);
16349 3322 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16350 3322 : if (n != NULL && !(n->value & GOVD_SEEN))
16351 : {
16352 1176 : if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
16353 : != 0
16354 1176 : && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
16355 : remove = true;
16356 : }
16357 : if (!remove
16358 2146 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
16359 1126 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
16360 332 : && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
16361 233 : || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
16362 197 : || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
16363 : {
16364 153 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
16365 153 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
16366 153 : if (n == NULL)
16367 : {
16368 68 : enum omp_clause_default_kind default_kind
16369 : = ctx->default_kind;
16370 68 : ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
16371 68 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16372 : true);
16373 68 : ctx->default_kind = default_kind;
16374 : }
16375 : else
16376 85 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16377 : true);
16378 : }
16379 : break;
16380 :
16381 : case OMP_CLAUSE_COPYIN:
16382 : case OMP_CLAUSE_COPYPRIVATE:
16383 : case OMP_CLAUSE_IF:
16384 : case OMP_CLAUSE_SELF:
16385 : case OMP_CLAUSE_NUM_THREADS:
16386 : case OMP_CLAUSE_NUM_TEAMS:
16387 : case OMP_CLAUSE_THREAD_LIMIT:
16388 : case OMP_CLAUSE_DIST_SCHEDULE:
16389 : case OMP_CLAUSE_DEVICE:
16390 : case OMP_CLAUSE_SCHEDULE:
16391 : case OMP_CLAUSE_NOWAIT:
16392 : case OMP_CLAUSE_ORDERED:
16393 : case OMP_CLAUSE_DEFAULT:
16394 : case OMP_CLAUSE_UNTIED:
16395 : case OMP_CLAUSE_COLLAPSE:
16396 : case OMP_CLAUSE_FINAL:
16397 : case OMP_CLAUSE_MERGEABLE:
16398 : case OMP_CLAUSE_PROC_BIND:
16399 : case OMP_CLAUSE_SAFELEN:
16400 : case OMP_CLAUSE_SIMDLEN:
16401 : case OMP_CLAUSE_DEPEND:
16402 : case OMP_CLAUSE_DOACROSS:
16403 : case OMP_CLAUSE_PRIORITY:
16404 : case OMP_CLAUSE_GRAINSIZE:
16405 : case OMP_CLAUSE_NUM_TASKS:
16406 : case OMP_CLAUSE_NOGROUP:
16407 : case OMP_CLAUSE_THREADS:
16408 : case OMP_CLAUSE_SIMD:
16409 : case OMP_CLAUSE_FILTER:
16410 : case OMP_CLAUSE_HINT:
16411 : case OMP_CLAUSE_DEFAULTMAP:
16412 : case OMP_CLAUSE_ORDER:
16413 : case OMP_CLAUSE_BIND:
16414 : case OMP_CLAUSE_DETACH:
16415 : case OMP_CLAUSE_USE_DEVICE_PTR:
16416 : case OMP_CLAUSE_USE_DEVICE_ADDR:
16417 : case OMP_CLAUSE_ASYNC:
16418 : case OMP_CLAUSE_WAIT:
16419 : case OMP_CLAUSE_INDEPENDENT:
16420 : case OMP_CLAUSE_NUM_GANGS:
16421 : case OMP_CLAUSE_NUM_WORKERS:
16422 : case OMP_CLAUSE_VECTOR_LENGTH:
16423 : case OMP_CLAUSE_GANG:
16424 : case OMP_CLAUSE_WORKER:
16425 : case OMP_CLAUSE_VECTOR:
16426 : case OMP_CLAUSE_AUTO:
16427 : case OMP_CLAUSE_SEQ:
16428 : case OMP_CLAUSE_TILE:
16429 : case OMP_CLAUSE_IF_PRESENT:
16430 : case OMP_CLAUSE_FINALIZE:
16431 : case OMP_CLAUSE_INCLUSIVE:
16432 : case OMP_CLAUSE_EXCLUSIVE:
16433 : case OMP_CLAUSE_USES_ALLOCATORS:
16434 : case OMP_CLAUSE_DEVICE_TYPE:
16435 : break;
16436 :
16437 0 : case OMP_CLAUSE_NOHOST:
16438 0 : default:
16439 0 : gcc_unreachable ();
16440 : }
16441 :
16442 129206 : if (remove)
16443 9908 : *list_p = OMP_CLAUSE_CHAIN (c);
16444 238609 : else if (move_attach)
16445 : {
16446 : /* Remove attach node from here, separate out into its own list. */
16447 2360 : *attach_tail = c;
16448 2360 : *list_p = OMP_CLAUSE_CHAIN (c);
16449 2360 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
16450 2360 : attach_tail = &OMP_CLAUSE_CHAIN (c);
16451 : }
16452 : else
16453 236249 : list_p = &OMP_CLAUSE_CHAIN (c);
16454 : }
16455 :
16456 : /* Splice attach nodes at the end of the list. */
16457 129085 : if (attach_list)
16458 : {
16459 1127 : *list_p = attach_list;
16460 1127 : list_p = attach_tail;
16461 : }
16462 :
16463 : /* Add in any implicit data sharing. */
16464 129085 : struct gimplify_adjust_omp_clauses_data data;
16465 129085 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
16466 : {
16467 : /* OpenMP. Implicit clauses are added at the start of the clause list,
16468 : but after any non-map clauses. */
16469 : tree *implicit_add_list_p = orig_list_p;
16470 252128 : while (*implicit_add_list_p
16471 252128 : && OMP_CLAUSE_CODE (*implicit_add_list_p) != OMP_CLAUSE_MAP)
16472 152890 : implicit_add_list_p = &OMP_CLAUSE_CHAIN (*implicit_add_list_p);
16473 99238 : data.list_p = implicit_add_list_p;
16474 : }
16475 : else
16476 : /* OpenACC. */
16477 29847 : data.list_p = list_p;
16478 129085 : data.pre_p = pre_p;
16479 129085 : splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
16480 :
16481 129085 : if (has_inscan_reductions)
16482 2443 : for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
16483 1830 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
16484 1830 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
16485 : {
16486 5 : error_at (OMP_CLAUSE_LOCATION (c),
16487 : "%<inscan%> %<reduction%> clause used together with "
16488 : "%<linear%> clause for a variable other than loop "
16489 : "iterator");
16490 5 : break;
16491 : }
16492 :
16493 129085 : gimplify_omp_ctxp = ctx->outer_context;
16494 129085 : delete_omp_context (ctx);
16495 129085 : }
16496 :
16497 : /* Try to evaluate a novariants clause. Return 1 if true, 0 if false or absent,
16498 : * -1 if run-time evaluation is needed. */
16499 :
16500 : int
16501 250280 : omp_has_novariants (void)
16502 : {
16503 250280 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16504 250280 : if (ctx != NULL && ctx->code == OMP_DISPATCH && !ctx->in_call_args)
16505 : {
16506 3290 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOVARIANTS);
16507 3290 : if (c != NULL_TREE)
16508 : {
16509 299 : if (integer_nonzerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16510 : return 1;
16511 171 : else if (integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16512 : return 0;
16513 : else
16514 : return -1;
16515 : }
16516 : return 0;
16517 : }
16518 : return 0;
16519 : }
16520 :
16521 : /* Try to evaluate a nocontext clause. Return 1 if true, 0 if false or absent,
16522 : * -1 if run-time evaluation is needed. */
16523 :
16524 : static int
16525 1903 : omp_has_nocontext (void)
16526 : {
16527 1903 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16528 1903 : if (ctx != NULL && ctx->code == OMP_DISPATCH)
16529 : {
16530 1903 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOCONTEXT);
16531 1903 : if (c != NULL_TREE)
16532 : {
16533 256 : if (integer_nonzerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16534 : return 1;
16535 94 : else if (integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16536 : return 0;
16537 : else
16538 : return -1;
16539 : }
16540 : return 0;
16541 : }
16542 : return 0;
16543 : }
16544 :
16545 : /* Collect a list of traits for enclosing constructs in the current
16546 : OpenMP context. The list is in the same format as the trait selector
16547 : list of construct trait sets built by the front ends.
16548 :
16549 : Per the OpenMP specification, the construct trait set includes constructs
16550 : up to an enclosing "target" construct. If there is no "target" construct,
16551 : then additional things may be added to the construct trait set (simd for
16552 : simd clones, additional constructs associated with "declare variant",
16553 : the target trait for "declare target"); those are not handled here.
16554 : In particular simd clones are not known during gimplification so
16555 : matching/scoring of context selectors that might involve them needs
16556 : to be deferred to the omp_device_lower pass. */
16557 :
16558 : tree
16559 2213 : omp_get_construct_context (void)
16560 : {
16561 2213 : tree result = NULL_TREE;
16562 4184 : for (struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; ctx;)
16563 : {
16564 2092 : if (((ctx->region_type & (ORT_TARGET | ORT_IMPLICIT_TARGET | ORT_ACC))
16565 : == ORT_TARGET)
16566 121 : && ctx->code == OMP_TARGET)
16567 : {
16568 121 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TARGET,
16569 : NULL_TREE, NULL_TREE, result);
16570 : /* We're not interested in any outer constructs. */
16571 121 : break;
16572 : }
16573 1971 : else if ((ctx->region_type & ORT_PARALLEL) && ctx->code == OMP_PARALLEL)
16574 214 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_PARALLEL,
16575 : NULL_TREE, NULL_TREE, result);
16576 1757 : else if ((ctx->region_type & ORT_TEAMS) && ctx->code == OMP_TEAMS)
16577 75 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TEAMS,
16578 : NULL_TREE, NULL_TREE, result);
16579 1682 : else if (ctx->region_type == ORT_WORKSHARE && ctx->code == OMP_FOR)
16580 164 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_FOR,
16581 : NULL_TREE, NULL_TREE, result);
16582 1518 : else if (ctx->code == OMP_DISPATCH && omp_has_nocontext () != 1)
16583 1279 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_DISPATCH,
16584 : NULL_TREE, NULL_TREE, result);
16585 239 : else if (ctx->region_type == ORT_SIMD
16586 32 : && ctx->code == OMP_SIMD
16587 271 : && !omp_find_clause (ctx->clauses, OMP_CLAUSE_BIND))
16588 : {
16589 32 : tree props = NULL_TREE;
16590 32 : tree *last = &props;
16591 72 : for (tree c = ctx->clauses; c; c = OMP_CLAUSE_CHAIN (c))
16592 40 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMDLEN
16593 32 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INBRANCH
16594 72 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOTINBRANCH)
16595 : {
16596 8 : *last = unshare_expr (c);
16597 8 : last = &(OMP_CLAUSE_CHAIN (c));
16598 : }
16599 32 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_SIMD,
16600 : NULL_TREE, props, result);
16601 : }
16602 207 : else if (ctx->region_type == ORT_WORKSHARE
16603 5 : && ctx->code == OMP_LOOP
16604 0 : && ctx->outer_context
16605 0 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL
16606 0 : && ctx->outer_context->outer_context
16607 0 : && ctx->outer_context->outer_context->code == OMP_LOOP
16608 0 : && ctx->outer_context->outer_context->distribute)
16609 1971 : ctx = ctx->outer_context->outer_context;
16610 1971 : ctx = ctx->outer_context;
16611 : }
16612 :
16613 2213 : return result;
16614 : }
16615 :
16616 : /* Gimplify OACC_CACHE. */
16617 :
16618 : static void
16619 665 : gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
16620 : {
16621 665 : tree expr = *expr_p;
16622 :
16623 665 : gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_ACC,
16624 : OACC_CACHE);
16625 665 : gimplify_adjust_omp_clauses (pre_p, NULL, &OACC_CACHE_CLAUSES (expr),
16626 : OACC_CACHE);
16627 :
16628 : /* TODO: Do something sensible with this information. */
16629 :
16630 665 : *expr_p = NULL_TREE;
16631 665 : }
16632 :
16633 : /* Helper function of gimplify_oacc_declare. The helper's purpose is to,
16634 : if required, translate 'kind' in CLAUSE into an 'entry' kind and 'exit'
16635 : kind. The entry kind will replace the one in CLAUSE, while the exit
16636 : kind will be used in a new omp_clause and returned to the caller. */
16637 :
16638 : static tree
16639 190 : gimplify_oacc_declare_1 (tree clause)
16640 : {
16641 190 : HOST_WIDE_INT kind, new_op;
16642 190 : bool ret = false;
16643 190 : tree c = NULL;
16644 :
16645 190 : kind = OMP_CLAUSE_MAP_KIND (clause);
16646 :
16647 190 : switch (kind)
16648 : {
16649 : case GOMP_MAP_ALLOC:
16650 : new_op = GOMP_MAP_RELEASE;
16651 : ret = true;
16652 : break;
16653 :
16654 29 : case GOMP_MAP_FROM:
16655 29 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_ALLOC);
16656 29 : new_op = GOMP_MAP_FROM;
16657 29 : ret = true;
16658 29 : break;
16659 :
16660 40 : case GOMP_MAP_TOFROM:
16661 40 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_TO);
16662 40 : new_op = GOMP_MAP_FROM;
16663 40 : ret = true;
16664 40 : break;
16665 :
16666 : case GOMP_MAP_DEVICE_RESIDENT:
16667 : case GOMP_MAP_FORCE_DEVICEPTR:
16668 : case GOMP_MAP_FORCE_PRESENT:
16669 : case GOMP_MAP_LINK:
16670 : case GOMP_MAP_POINTER:
16671 : case GOMP_MAP_TO:
16672 : break;
16673 :
16674 0 : default:
16675 0 : gcc_unreachable ();
16676 69 : break;
16677 : }
16678 :
16679 69 : if (ret)
16680 : {
16681 116 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clause), OMP_CLAUSE_MAP);
16682 116 : OMP_CLAUSE_SET_MAP_KIND (c, new_op);
16683 116 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clause);
16684 : }
16685 :
16686 190 : return c;
16687 : }
16688 :
16689 : /* Gimplify OACC_DECLARE. */
16690 :
16691 : static void
16692 254 : gimplify_oacc_declare (tree *expr_p, gimple_seq *pre_p)
16693 : {
16694 254 : tree expr = *expr_p;
16695 254 : gomp_target *stmt;
16696 254 : tree clauses, t, decl;
16697 :
16698 254 : clauses = OACC_DECLARE_CLAUSES (expr);
16699 :
16700 254 : gimplify_scan_omp_clauses (&clauses, pre_p, ORT_TARGET_DATA, OACC_DECLARE);
16701 254 : gimplify_adjust_omp_clauses (pre_p, NULL, &clauses, OACC_DECLARE);
16702 :
16703 516 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16704 : {
16705 262 : decl = OMP_CLAUSE_DECL (t);
16706 :
16707 262 : if (TREE_CODE (decl) == MEM_REF)
16708 8 : decl = TREE_OPERAND (decl, 0);
16709 :
16710 262 : if (VAR_P (decl) && !is_oacc_declared (decl))
16711 : {
16712 262 : tree attr = get_identifier ("oacc declare target");
16713 262 : DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE,
16714 262 : DECL_ATTRIBUTES (decl));
16715 : }
16716 :
16717 262 : if (VAR_P (decl)
16718 262 : && !is_global_var (decl)
16719 452 : && DECL_CONTEXT (decl) == current_function_decl)
16720 : {
16721 190 : tree c = gimplify_oacc_declare_1 (t);
16722 190 : if (c)
16723 : {
16724 116 : if (oacc_declare_returns == NULL)
16725 40 : oacc_declare_returns = new hash_map<tree, tree>;
16726 :
16727 116 : oacc_declare_returns->put (decl, c);
16728 : }
16729 : }
16730 :
16731 262 : if (gimplify_omp_ctxp)
16732 72 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_SEEN);
16733 : }
16734 :
16735 254 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
16736 : clauses);
16737 :
16738 254 : gimplify_seq_add_stmt (pre_p, stmt);
16739 :
16740 254 : *expr_p = NULL_TREE;
16741 254 : }
16742 :
16743 : /* Gimplify the contents of an OMP_PARALLEL statement. This involves
16744 : gimplification of the body, as well as scanning the body for used
16745 : variables. We need to do this scan now, because variable-sized
16746 : decls will be decomposed during gimplification. */
16747 :
16748 : static void
16749 18239 : gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
16750 : {
16751 18239 : tree expr = *expr_p;
16752 18239 : gimple *g;
16753 18239 : gimple_seq body = NULL;
16754 :
16755 36478 : gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
16756 18239 : OMP_PARALLEL_COMBINED (expr)
16757 : ? ORT_COMBINED_PARALLEL
16758 : : ORT_PARALLEL, OMP_PARALLEL);
16759 :
16760 18239 : push_gimplify_context ();
16761 :
16762 18239 : g = gimplify_and_return_first (OMP_PARALLEL_BODY (expr), &body);
16763 18239 : if (gimple_code (g) == GIMPLE_BIND)
16764 18239 : pop_gimplify_context (g);
16765 : else
16766 0 : pop_gimplify_context (NULL);
16767 :
16768 18239 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_PARALLEL_CLAUSES (expr),
16769 : OMP_PARALLEL);
16770 :
16771 36478 : g = gimple_build_omp_parallel (body,
16772 18239 : OMP_PARALLEL_CLAUSES (expr),
16773 : NULL_TREE, NULL_TREE);
16774 18239 : if (OMP_PARALLEL_COMBINED (expr))
16775 12529 : gimple_omp_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
16776 18239 : gimplify_seq_add_stmt (pre_p, g);
16777 18239 : *expr_p = NULL_TREE;
16778 18239 : }
16779 :
16780 : /* Gimplify the contents of an OMP_TASK statement. This involves
16781 : gimplification of the body, as well as scanning the body for used
16782 : variables. We need to do this scan now, because variable-sized
16783 : decls will be decomposed during gimplification. */
16784 :
16785 : static void
16786 3825 : gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
16787 : {
16788 3825 : tree expr = *expr_p;
16789 3825 : gimple *g;
16790 3825 : gimple_seq body = NULL;
16791 3825 : bool nowait = false;
16792 3825 : bool has_depend = false;
16793 :
16794 3825 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16795 : {
16796 242 : for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
16797 153 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
16798 : {
16799 111 : has_depend = true;
16800 111 : if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
16801 : {
16802 9 : error_at (OMP_CLAUSE_LOCATION (c),
16803 : "%<mutexinoutset%> kind in %<depend%> clause on a "
16804 : "%<taskwait%> construct");
16805 9 : break;
16806 : }
16807 : }
16808 42 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT)
16809 42 : nowait = true;
16810 98 : if (nowait && !has_depend)
16811 : {
16812 5 : error_at (EXPR_LOCATION (expr),
16813 : "%<taskwait%> construct with %<nowait%> clause but no "
16814 : "%<depend%> clauses");
16815 5 : *expr_p = NULL_TREE;
16816 5 : return;
16817 : }
16818 : }
16819 :
16820 11460 : gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
16821 3820 : omp_find_clause (OMP_TASK_CLAUSES (expr),
16822 : OMP_CLAUSE_UNTIED)
16823 : ? ORT_UNTIED_TASK : ORT_TASK, OMP_TASK);
16824 :
16825 3820 : if (OMP_TASK_BODY (expr))
16826 : {
16827 3727 : push_gimplify_context ();
16828 :
16829 3727 : g = gimplify_and_return_first (OMP_TASK_BODY (expr), &body);
16830 3727 : if (gimple_code (g) == GIMPLE_BIND)
16831 3727 : pop_gimplify_context (g);
16832 : else
16833 0 : pop_gimplify_context (NULL);
16834 : }
16835 :
16836 3820 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_TASK_CLAUSES (expr),
16837 : OMP_TASK);
16838 :
16839 7640 : g = gimple_build_omp_task (body,
16840 3820 : OMP_TASK_CLAUSES (expr),
16841 : NULL_TREE, NULL_TREE,
16842 : NULL_TREE, NULL_TREE, NULL_TREE);
16843 3820 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16844 93 : gimple_omp_task_set_taskwait_p (g, true);
16845 3820 : gimplify_seq_add_stmt (pre_p, g);
16846 3820 : *expr_p = NULL_TREE;
16847 : }
16848 :
16849 : /* Helper function for gimplify_omp_for. If *TP is not a gimple constant,
16850 : force it into a temporary initialized in PRE_P and add firstprivate clause
16851 : to ORIG_FOR_STMT. */
16852 :
16853 : static void
16854 4399 : gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p,
16855 : tree orig_for_stmt)
16856 : {
16857 4399 : if (*tp == NULL || is_gimple_constant (*tp))
16858 : return;
16859 :
16860 779 : if (TREE_CODE (*tp) == SAVE_EXPR)
16861 135 : gimplify_save_expr (tp, pre_p, NULL);
16862 : else
16863 644 : *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false);
16864 : /* Reference to pointer conversion is considered useless,
16865 : but is significant for firstprivate clause. Force it
16866 : here. */
16867 779 : if (type
16868 687 : && TREE_CODE (type) == POINTER_TYPE
16869 869 : && TREE_CODE (TREE_TYPE (*tp)) == REFERENCE_TYPE)
16870 : {
16871 2 : tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
16872 2 : tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, *tp);
16873 2 : gimplify_and_add (m, pre_p);
16874 2 : *tp = v;
16875 : }
16876 :
16877 779 : tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
16878 779 : OMP_CLAUSE_DECL (c) = *tp;
16879 779 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (orig_for_stmt);
16880 779 : OMP_FOR_CLAUSES (orig_for_stmt) = c;
16881 : }
16882 :
16883 : /* Helper function of gimplify_omp_for, find OMP_ORDERED with
16884 : null OMP_ORDERED_BODY inside of OMP_FOR's body. */
16885 :
16886 : static tree
16887 16496 : find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
16888 : {
16889 16496 : switch (TREE_CODE (*tp))
16890 : {
16891 901 : case OMP_ORDERED:
16892 901 : if (OMP_ORDERED_BODY (*tp) == NULL_TREE)
16893 : return *tp;
16894 : break;
16895 23 : case OMP_SIMD:
16896 23 : case OMP_PARALLEL:
16897 23 : case OMP_TARGET:
16898 23 : *walk_subtrees = 0;
16899 23 : break;
16900 : default:
16901 : break;
16902 : }
16903 : return NULL_TREE;
16904 : }
16905 :
16906 : /* Gimplify standalone loop transforming directive which has the
16907 : transformations applied already. So, all that is needed is gimplify
16908 : the remaining loops as normal loops. */
16909 :
16910 : static enum gimplify_status
16911 2264 : gimplify_omp_loop_xform (tree *expr_p, gimple_seq *pre_p)
16912 : {
16913 2264 : tree for_stmt = *expr_p;
16914 :
16915 2264 : if (OMP_FOR_PRE_BODY (for_stmt))
16916 759 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), pre_p);
16917 :
16918 2264 : gimple_seq pre_body = NULL, post_body = NULL;
16919 5203 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16920 : {
16921 2939 : if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE)
16922 1707 : continue;
16923 1283 : tree iters = NULL_TREE;
16924 1283 : if (i == 0
16925 826 : && TREE_CODE (for_stmt) == OMP_UNROLL
16926 1771 : && !omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_PARTIAL))
16927 : {
16928 311 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL))
16929 269 : iters = omp_loop_number_of_iterations (for_stmt, 0, NULL);
16930 : else
16931 42 : iters = build_int_cst (integer_type_node, 8);
16932 : }
16933 1283 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
16934 1283 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
16935 1283 : tree decl = TREE_OPERAND (t, 0);
16936 1283 : gcc_assert (DECL_P (decl));
16937 1283 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
16938 : || POINTER_TYPE_P (TREE_TYPE (decl)));
16939 1283 : if (DECL_ARTIFICIAL (decl)
16940 876 : && TREE_PRIVATE (t)
16941 867 : && gimplify_omp_ctxp
16942 1613 : && gimplify_omp_ctxp->region_type != ORT_NONE)
16943 : {
16944 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16945 504 : do
16946 : {
16947 504 : splay_tree_node n
16948 504 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16949 504 : if (n != NULL)
16950 : break;
16951 346 : else if (ctx->region_type != ORT_WORKSHARE
16952 : && ctx->region_type != ORT_TASKGROUP
16953 62 : && ctx->region_type != ORT_SIMD
16954 38 : && ctx->region_type != ORT_ACC
16955 38 : && !(ctx->region_type & ORT_TARGET_DATA))
16956 : {
16957 38 : omp_add_variable (ctx, decl, GOVD_PRIVATE);
16958 38 : break;
16959 : }
16960 308 : ctx = ctx->outer_context;
16961 : }
16962 308 : while (ctx);
16963 : }
16964 1283 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16965 : {
16966 23 : gcc_assert (seen_error ());
16967 23 : continue;
16968 : }
16969 1260 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16970 : fb_rvalue);
16971 1260 : gimplify_and_add (t, &pre_body);
16972 1260 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16973 1260 : gcc_assert (TREE_OPERAND (t, 0) == decl);
16974 1260 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16975 : {
16976 28 : gcc_assert (seen_error ());
16977 28 : continue;
16978 : }
16979 1232 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16980 : fb_rvalue);
16981 1232 : tree l1 = create_artificial_label (UNKNOWN_LOCATION);
16982 1232 : tree l2 = create_artificial_label (UNKNOWN_LOCATION);
16983 1232 : tree l3 = create_artificial_label (UNKNOWN_LOCATION);
16984 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_goto (l2));
16985 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_label (l1));
16986 1232 : gimple_seq this_post_body = NULL;
16987 1232 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
16988 1232 : if (TREE_CODE (t) == MODIFY_EXPR)
16989 : {
16990 975 : t = TREE_OPERAND (t, 1);
16991 975 : if (TREE_CODE (t) == PLUS_EXPR
16992 975 : && TREE_OPERAND (t, 1) == decl)
16993 : {
16994 0 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
16995 0 : TREE_OPERAND (t, 0) = decl;
16996 : }
16997 975 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16998 : fb_rvalue);
16999 : }
17000 1232 : gimplify_and_add (TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i),
17001 : &this_post_body);
17002 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l2));
17003 1232 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17004 1232 : gcond *cond = NULL;
17005 1232 : tree d = decl;
17006 1232 : gimplify_expr (&d, &this_post_body, NULL, is_gimple_val, fb_rvalue);
17007 1232 : if (iters && tree_fits_uhwi_p (iters))
17008 : {
17009 299 : unsigned HOST_WIDE_INT niters = tree_to_uhwi (iters);
17010 299 : if ((unsigned HOST_WIDE_INT) (int) niters == niters
17011 299 : && (int) niters > 0)
17012 : {
17013 299 : t = build2 (TREE_CODE (t), boolean_type_node, d,
17014 299 : TREE_OPERAND (t, 1));
17015 299 : t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t,
17016 : build_int_cst (integer_type_node,
17017 : annot_expr_unroll_kind),
17018 299 : build_int_cst (integer_type_node, niters));
17019 299 : gimplify_expr (&t, &this_post_body, NULL, is_gimple_val,
17020 : fb_rvalue);
17021 299 : cond = gimple_build_cond (NE_EXPR, t, boolean_false_node,
17022 : l1, l3);
17023 : }
17024 : }
17025 299 : if (cond == NULL)
17026 933 : cond = gimple_build_cond (TREE_CODE (t), d, TREE_OPERAND (t, 1),
17027 : l1, l3);
17028 1232 : gimplify_seq_add_stmt (&this_post_body, cond);
17029 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l3));
17030 1232 : gimplify_seq_add_seq (&this_post_body, post_body);
17031 1232 : post_body = this_post_body;
17032 : }
17033 2264 : gimplify_seq_add_seq (pre_p, pre_body);
17034 2264 : gimplify_and_add (OMP_FOR_BODY (for_stmt), pre_p);
17035 2264 : gimplify_seq_add_seq (pre_p, post_body);
17036 :
17037 2264 : *expr_p = NULL_TREE;
17038 2264 : return GS_ALL_DONE;
17039 : }
17040 :
17041 : /* Gimplify the gross structure of an OMP_FOR statement. */
17042 :
17043 : static enum gimplify_status
17044 58054 : gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
17045 : {
17046 58054 : tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t;
17047 58054 : enum gimplify_status ret = GS_ALL_DONE;
17048 58054 : enum gimplify_status tret;
17049 58054 : gomp_for *gfor;
17050 58054 : gimple_seq for_body, for_pre_body;
17051 58054 : int i;
17052 58054 : bitmap has_decl_expr = NULL;
17053 58054 : enum omp_region_type ort = ORT_WORKSHARE;
17054 58054 : bool openacc = TREE_CODE (*expr_p) == OACC_LOOP;
17055 :
17056 58054 : orig_for_stmt = for_stmt = *expr_p;
17057 :
17058 58054 : bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND)
17059 58054 : != NULL_TREE);
17060 58125 : while (OMP_FOR_INIT (for_stmt) == NULL_TREE)
17061 : {
17062 17737 : tree *data[4] = { NULL, NULL, NULL, NULL };
17063 17737 : gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
17064 17737 : inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt),
17065 : find_combined_omp_for, data, NULL);
17066 17737 : if (inner_for_stmt == NULL_TREE)
17067 : {
17068 36 : gcc_assert (seen_error ());
17069 36 : *expr_p = NULL_TREE;
17070 3740 : return GS_ERROR;
17071 : }
17072 17701 : gcc_assert (inner_for_stmt == *data[3]);
17073 17701 : omp_maybe_apply_loop_xforms (data[3],
17074 17701 : data[2]
17075 4279 : ? OMP_FOR_CLAUSES (*data[2])
17076 13422 : : TREE_CODE (for_stmt) == OMP_FOR
17077 13422 : ? OMP_FOR_CLAUSES (for_stmt)
17078 : : NULL_TREE);
17079 17701 : if (inner_for_stmt != *data[3])
17080 71 : continue;
17081 17630 : if (data[2] && OMP_FOR_PRE_BODY (*data[2]))
17082 : {
17083 2 : append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]),
17084 : &OMP_FOR_PRE_BODY (for_stmt));
17085 2 : OMP_FOR_PRE_BODY (*data[2]) = NULL_TREE;
17086 : }
17087 17630 : if (OMP_FOR_PRE_BODY (inner_for_stmt))
17088 : {
17089 7193 : append_to_statement_list_force (OMP_FOR_PRE_BODY (inner_for_stmt),
17090 : &OMP_FOR_PRE_BODY (for_stmt));
17091 7193 : OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
17092 : }
17093 :
17094 17630 : if (data[0])
17095 : {
17096 : /* We have some statements or variable declarations in between
17097 : the composite construct directives. Move them around the
17098 : inner_for_stmt. */
17099 3704 : data[0] = expr_p;
17100 14816 : for (i = 0; i < 3; i++)
17101 11112 : if (data[i])
17102 : {
17103 7026 : tree t = *data[i];
17104 7026 : if (i < 2 && data[i + 1] == &OMP_BODY (t))
17105 1005 : data[i + 1] = data[i];
17106 7026 : *data[i] = OMP_BODY (t);
17107 7026 : tree body = build3 (BIND_EXPR, void_type_node, NULL_TREE,
17108 : NULL_TREE, make_node (BLOCK));
17109 7026 : OMP_BODY (t) = body;
17110 7026 : append_to_statement_list_force (inner_for_stmt,
17111 : &BIND_EXPR_BODY (body));
17112 7026 : *data[3] = t;
17113 7026 : data[3] = tsi_stmt_ptr (tsi_start (BIND_EXPR_BODY (body)));
17114 7026 : gcc_assert (*data[3] == inner_for_stmt);
17115 : }
17116 : return GS_OK;
17117 : }
17118 :
17119 36734 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17120 22808 : if (!loop_p
17121 21927 : && OMP_FOR_ORIG_DECLS (inner_for_stmt)
17122 11098 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17123 : i)) == TREE_LIST
17124 22876 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17125 : i)))
17126 : {
17127 40 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17128 : /* Class iterators aren't allowed on OMP_SIMD, so the only
17129 : case we need to solve is distribute parallel for. They are
17130 : allowed on the loop construct, but that is already handled
17131 : in gimplify_omp_loop. */
17132 40 : gcc_assert (TREE_CODE (inner_for_stmt) == OMP_FOR
17133 : && TREE_CODE (for_stmt) == OMP_DISTRIBUTE
17134 : && data[1]);
17135 40 : tree orig_decl = TREE_PURPOSE (orig);
17136 40 : tree last = TREE_VALUE (orig);
17137 40 : tree *pc;
17138 40 : for (pc = &OMP_FOR_CLAUSES (inner_for_stmt);
17139 74 : *pc; pc = &OMP_CLAUSE_CHAIN (*pc))
17140 42 : if ((OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE
17141 35 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE)
17142 43 : && OMP_CLAUSE_DECL (*pc) == orig_decl)
17143 : break;
17144 40 : if (*pc == NULL_TREE)
17145 : {
17146 32 : tree *spc;
17147 32 : for (spc = &OMP_PARALLEL_CLAUSES (*data[1]);
17148 98 : *spc; spc = &OMP_CLAUSE_CHAIN (*spc))
17149 67 : if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE
17150 67 : && OMP_CLAUSE_DECL (*spc) == orig_decl)
17151 : break;
17152 32 : if (*spc)
17153 : {
17154 1 : tree c = *spc;
17155 1 : *spc = OMP_CLAUSE_CHAIN (c);
17156 1 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
17157 1 : *pc = c;
17158 : }
17159 : }
17160 40 : if (*pc == NULL_TREE)
17161 : ;
17162 9 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE)
17163 : {
17164 : /* private clause will appear only on inner_for_stmt.
17165 : Change it into firstprivate, and add private clause
17166 : on for_stmt. */
17167 8 : tree c = copy_node (*pc);
17168 8 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17169 8 : OMP_FOR_CLAUSES (for_stmt) = c;
17170 8 : OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE;
17171 8 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17172 : }
17173 : else
17174 : {
17175 : /* lastprivate clause will appear on both inner_for_stmt
17176 : and for_stmt. Add firstprivate clause to
17177 : inner_for_stmt. */
17178 1 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (*pc),
17179 : OMP_CLAUSE_FIRSTPRIVATE);
17180 1 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc);
17181 1 : OMP_CLAUSE_CHAIN (c) = *pc;
17182 1 : *pc = c;
17183 1 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17184 : }
17185 40 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17186 : OMP_CLAUSE_FIRSTPRIVATE);
17187 40 : OMP_CLAUSE_DECL (c) = last;
17188 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17189 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17190 40 : c = build_omp_clause (UNKNOWN_LOCATION,
17191 40 : *pc ? OMP_CLAUSE_SHARED
17192 : : OMP_CLAUSE_FIRSTPRIVATE);
17193 40 : OMP_CLAUSE_DECL (c) = orig_decl;
17194 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17195 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17196 : }
17197 : /* Similarly, take care of C++ range for temporaries, those should
17198 : be firstprivate on OMP_PARALLEL if any. */
17199 13926 : if (data[1])
17200 17503 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17201 11108 : if (OMP_FOR_ORIG_DECLS (inner_for_stmt)
17202 5733 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17203 : i)) == TREE_LIST
17204 11184 : && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17205 : i)))
17206 : {
17207 49 : tree orig
17208 49 : = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17209 49 : tree v = TREE_CHAIN (orig);
17210 49 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17211 : OMP_CLAUSE_FIRSTPRIVATE);
17212 : /* First add firstprivate clause for the __for_end artificial
17213 : decl. */
17214 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 1);
17215 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17216 : == REFERENCE_TYPE)
17217 0 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17218 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17219 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17220 49 : if (TREE_VEC_ELT (v, 0))
17221 : {
17222 : /* And now the same for __for_range artificial decl if it
17223 : exists. */
17224 49 : c = build_omp_clause (UNKNOWN_LOCATION,
17225 : OMP_CLAUSE_FIRSTPRIVATE);
17226 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 0);
17227 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17228 : == REFERENCE_TYPE)
17229 49 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17230 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17231 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17232 : }
17233 : }
17234 13926 : break;
17235 : }
17236 54314 : if (OMP_FOR_INIT (for_stmt) != NULL_TREE)
17237 : {
17238 40388 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
17239 40388 : if (*expr_p != for_stmt)
17240 : return GS_OK;
17241 : }
17242 :
17243 53432 : switch (TREE_CODE (for_stmt))
17244 : {
17245 18137 : case OMP_FOR:
17246 30305 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17247 : {
17248 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17249 : OMP_CLAUSE_SCHEDULE))
17250 47 : error_at (EXPR_LOCATION (for_stmt),
17251 : "%qs clause may not appear on non-rectangular %qs",
17252 27 : "schedule", lang_GNU_Fortran () ? "do" : "for");
17253 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED))
17254 34 : error_at (EXPR_LOCATION (for_stmt),
17255 : "%qs clause may not appear on non-rectangular %qs",
17256 18 : "ordered", lang_GNU_Fortran () ? "do" : "for");
17257 : }
17258 : break;
17259 8240 : case OMP_DISTRIBUTE:
17260 9172 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)
17261 8240 : && omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17262 : OMP_CLAUSE_DIST_SCHEDULE))
17263 29 : error_at (EXPR_LOCATION (for_stmt),
17264 : "%qs clause may not appear on non-rectangular %qs",
17265 : "dist_schedule", "distribute");
17266 : break;
17267 : case OACC_LOOP:
17268 : ort = ORT_ACC;
17269 : break;
17270 1586 : case OMP_TASKLOOP:
17271 2523 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17272 : {
17273 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17274 : OMP_CLAUSE_GRAINSIZE))
17275 11 : error_at (EXPR_LOCATION (for_stmt),
17276 : "%qs clause may not appear on non-rectangular %qs",
17277 : "grainsize", "taskloop");
17278 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17279 : OMP_CLAUSE_NUM_TASKS))
17280 6 : error_at (EXPR_LOCATION (for_stmt),
17281 : "%qs clause may not appear on non-rectangular %qs",
17282 : "num_tasks", "taskloop");
17283 : }
17284 1586 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED))
17285 : ort = ORT_UNTIED_TASKLOOP;
17286 : else
17287 : ort = ORT_TASKLOOP;
17288 : break;
17289 10653 : case OMP_SIMD:
17290 10653 : ort = ORT_SIMD;
17291 10653 : break;
17292 2264 : case OMP_TILE:
17293 2264 : case OMP_UNROLL:
17294 2264 : gcc_assert (inner_for_stmt == NULL_TREE);
17295 2264 : return gimplify_omp_loop_xform (expr_p, pre_p);
17296 0 : default:
17297 0 : gcc_unreachable ();
17298 : }
17299 :
17300 : /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear
17301 : clause for the IV. */
17302 10700 : if (ort == ORT_SIMD && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17303 : {
17304 7825 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0);
17305 7825 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17306 7825 : decl = TREE_OPERAND (t, 0);
17307 18635 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
17308 11924 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17309 11924 : && OMP_CLAUSE_DECL (c) == decl)
17310 : {
17311 1114 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17312 1114 : break;
17313 : }
17314 : }
17315 :
17316 51168 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP)
17317 51492 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort,
17318 1910 : loop_p && TREE_CODE (for_stmt) != OMP_SIMD
17319 : ? OMP_LOOP : TREE_CODE (for_stmt));
17320 :
17321 51168 : if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE)
17322 8240 : gimplify_omp_ctxp->distribute = true;
17323 :
17324 : /* Handle OMP_FOR_INIT. */
17325 51168 : for_pre_body = NULL;
17326 51168 : if ((ort == ORT_SIMD
17327 40515 : || (inner_for_stmt && TREE_CODE (inner_for_stmt) == OMP_SIMD))
17328 61908 : && OMP_FOR_PRE_BODY (for_stmt))
17329 : {
17330 6784 : has_decl_expr = BITMAP_ALLOC (NULL);
17331 6784 : if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR
17332 6784 : && VAR_P (DECL_EXPR_DECL (OMP_FOR_PRE_BODY (for_stmt))))
17333 : {
17334 18 : t = OMP_FOR_PRE_BODY (for_stmt);
17335 18 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17336 : }
17337 6766 : else if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == STATEMENT_LIST)
17338 : {
17339 6764 : tree_stmt_iterator si;
17340 11234 : for (si = tsi_start (OMP_FOR_PRE_BODY (for_stmt)); !tsi_end_p (si);
17341 4470 : tsi_next (&si))
17342 : {
17343 4470 : t = tsi_stmt (si);
17344 4470 : if (TREE_CODE (t) == DECL_EXPR
17345 4470 : && VAR_P (DECL_EXPR_DECL (t)))
17346 4397 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17347 : }
17348 : }
17349 : }
17350 51168 : if (OMP_FOR_PRE_BODY (for_stmt))
17351 : {
17352 21027 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp)
17353 20302 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17354 : else
17355 : {
17356 725 : struct gimplify_omp_ctx ctx;
17357 725 : memset (&ctx, 0, sizeof (ctx));
17358 725 : ctx.region_type = ORT_NONE;
17359 725 : gimplify_omp_ctxp = &ctx;
17360 725 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17361 725 : gimplify_omp_ctxp = NULL;
17362 : }
17363 : }
17364 51168 : OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
17365 :
17366 51168 : if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
17367 13926 : for_stmt = inner_for_stmt;
17368 :
17369 : /* For taskloop, need to gimplify the start, end and step before the
17370 : taskloop, outside of the taskloop omp context. */
17371 51168 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17372 : {
17373 3458 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17374 : {
17375 1872 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17376 1872 : gimple_seq *for_pre_p = (gimple_seq_empty_p (for_pre_body)
17377 1872 : ? pre_p : &for_pre_body);
17378 1872 : tree type = TREE_TYPE (TREE_OPERAND (t, 0));
17379 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17380 : {
17381 34 : tree v = TREE_OPERAND (t, 1);
17382 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17383 : for_pre_p, orig_for_stmt);
17384 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17385 : for_pre_p, orig_for_stmt);
17386 : }
17387 : else
17388 1838 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17389 : orig_for_stmt);
17390 :
17391 : /* Handle OMP_FOR_COND. */
17392 1872 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17393 1872 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17394 : {
17395 31 : tree v = TREE_OPERAND (t, 1);
17396 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17397 : for_pre_p, orig_for_stmt);
17398 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17399 : for_pre_p, orig_for_stmt);
17400 : }
17401 : else
17402 1841 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17403 : orig_for_stmt);
17404 :
17405 : /* Handle OMP_FOR_INCR. */
17406 1872 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17407 1872 : if (TREE_CODE (t) == MODIFY_EXPR)
17408 : {
17409 590 : decl = TREE_OPERAND (t, 0);
17410 590 : t = TREE_OPERAND (t, 1);
17411 590 : tree *tp = &TREE_OPERAND (t, 1);
17412 590 : if (TREE_CODE (t) == PLUS_EXPR && *tp == decl)
17413 22 : tp = &TREE_OPERAND (t, 0);
17414 :
17415 590 : gimplify_omp_taskloop_expr (NULL_TREE, tp, for_pre_p,
17416 : orig_for_stmt);
17417 : }
17418 : }
17419 :
17420 1586 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort,
17421 : OMP_TASKLOOP);
17422 : }
17423 :
17424 51168 : if (orig_for_stmt != for_stmt)
17425 13926 : gimplify_omp_ctxp->combined_loop = true;
17426 :
17427 51168 : for_body = NULL;
17428 51168 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17429 : == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
17430 51168 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17431 : == TREE_VEC_LENGTH (OMP_FOR_INCR (for_stmt)));
17432 :
17433 51168 : tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
17434 51168 : bool is_doacross = false;
17435 51168 : if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
17436 : find_standalone_omp_ordered, NULL))
17437 : {
17438 531 : OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
17439 531 : is_doacross = true;
17440 531 : int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
17441 531 : gimplify_omp_ctxp->loop_iter_var.create (len * 2);
17442 2200 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
17443 1669 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
17444 : {
17445 10 : error_at (OMP_CLAUSE_LOCATION (*pc),
17446 : "%<linear%> clause may not be specified together "
17447 : "with %<ordered%> clause if stand-alone %<ordered%> "
17448 : "construct is nested in it");
17449 10 : *pc = OMP_CLAUSE_CHAIN (*pc);
17450 : }
17451 : else
17452 1659 : pc = &OMP_CLAUSE_CHAIN (*pc);
17453 : }
17454 51168 : int collapse = 1, tile = 0;
17455 51168 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
17456 51168 : if (c)
17457 13709 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
17458 51168 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
17459 51168 : if (c)
17460 384 : tile = list_length (OMP_CLAUSE_TILE_LIST (c));
17461 51168 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
17462 51168 : hash_set<tree> *allocate_uids = NULL;
17463 51168 : if (c)
17464 : {
17465 233 : allocate_uids = new hash_set<tree>;
17466 1442 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17467 976 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
17468 358 : allocate_uids->add (OMP_CLAUSE_DECL (c));
17469 : }
17470 124064 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17471 : {
17472 72896 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17473 72896 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17474 72896 : decl = TREE_OPERAND (t, 0);
17475 72896 : gcc_assert (DECL_P (decl));
17476 72896 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
17477 : || POINTER_TYPE_P (TREE_TYPE (decl)));
17478 72896 : if (is_doacross)
17479 : {
17480 1654 : if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt))
17481 : {
17482 960 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17483 960 : if (TREE_CODE (orig_decl) == TREE_LIST)
17484 : {
17485 15 : orig_decl = TREE_PURPOSE (orig_decl);
17486 15 : if (!orig_decl)
17487 0 : orig_decl = decl;
17488 : }
17489 960 : gimplify_omp_ctxp->loop_iter_var.quick_push (orig_decl);
17490 : }
17491 : else
17492 694 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17493 1654 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17494 : }
17495 :
17496 72896 : if (for_stmt == orig_for_stmt)
17497 : {
17498 50088 : tree orig_decl = decl;
17499 50088 : if (OMP_FOR_ORIG_DECLS (for_stmt))
17500 : {
17501 23964 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17502 23964 : if (TREE_CODE (orig_decl) == TREE_LIST)
17503 : {
17504 : orig_decl = TREE_PURPOSE (orig_decl);
17505 : if (!orig_decl)
17506 : orig_decl = decl;
17507 : }
17508 : }
17509 50088 : if (is_global_var (orig_decl) && DECL_THREAD_LOCAL_P (orig_decl))
17510 36 : error_at (EXPR_LOCATION (for_stmt),
17511 : "threadprivate iteration variable %qD", orig_decl);
17512 : }
17513 :
17514 : /* Make sure the iteration variable is private. */
17515 72896 : tree c = NULL_TREE;
17516 72896 : tree c2 = NULL_TREE;
17517 72896 : if (orig_for_stmt != for_stmt)
17518 : {
17519 : /* Preserve this information until we gimplify the inner simd. */
17520 22808 : if (has_decl_expr
17521 22808 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17522 3413 : TREE_PRIVATE (t) = 1;
17523 : }
17524 50088 : else if (ort == ORT_SIMD)
17525 : {
17526 15726 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17527 : (splay_tree_key) decl);
17528 15726 : omp_is_private (gimplify_omp_ctxp, decl,
17529 15726 : 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17530 : != 1));
17531 15726 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
17532 : {
17533 2518 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17534 2518 : if (n->value & GOVD_LASTPRIVATE_CONDITIONAL)
17535 0 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17536 : OMP_CLAUSE_LASTPRIVATE);
17537 0 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17538 : OMP_CLAUSE_LASTPRIVATE))
17539 0 : if (OMP_CLAUSE_DECL (c3) == decl)
17540 : {
17541 0 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17542 : "conditional %<lastprivate%> on loop "
17543 : "iterator %qD ignored", decl);
17544 0 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17545 0 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17546 : }
17547 : }
17548 13208 : else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1 && !loop_p)
17549 : {
17550 5637 : c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17551 5637 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17552 5637 : unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN;
17553 5637 : if ((has_decl_expr
17554 1309 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17555 6321 : || TREE_PRIVATE (t))
17556 : {
17557 2281 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17558 2281 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17559 : }
17560 5637 : struct gimplify_omp_ctx *outer
17561 5637 : = gimplify_omp_ctxp->outer_context;
17562 5637 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17563 : {
17564 2433 : if (outer->region_type == ORT_WORKSHARE
17565 2193 : && outer->combined_loop)
17566 : {
17567 2142 : n = splay_tree_lookup (outer->variables,
17568 : (splay_tree_key)decl);
17569 2142 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17570 : {
17571 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17572 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17573 : }
17574 : else
17575 : {
17576 2142 : struct gimplify_omp_ctx *octx = outer->outer_context;
17577 2142 : if (octx
17578 1714 : && octx->region_type == ORT_COMBINED_PARALLEL
17579 1476 : && octx->outer_context
17580 1209 : && (octx->outer_context->region_type
17581 : == ORT_WORKSHARE)
17582 1079 : && octx->outer_context->combined_loop)
17583 : {
17584 1079 : octx = octx->outer_context;
17585 1079 : n = splay_tree_lookup (octx->variables,
17586 : (splay_tree_key)decl);
17587 1079 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17588 : {
17589 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17590 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17591 : }
17592 : }
17593 : }
17594 : }
17595 : }
17596 :
17597 5637 : OMP_CLAUSE_DECL (c) = decl;
17598 5637 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17599 5637 : OMP_FOR_CLAUSES (for_stmt) = c;
17600 5637 : omp_add_variable (gimplify_omp_ctxp, decl, flags);
17601 5637 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17602 2433 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17603 : true);
17604 : }
17605 : else
17606 : {
17607 7571 : bool lastprivate
17608 : = (!has_decl_expr
17609 7571 : || !bitmap_bit_p (has_decl_expr, DECL_UID (decl)));
17610 7571 : if (TREE_PRIVATE (t))
17611 1787 : lastprivate = false;
17612 7571 : if (loop_p && OMP_FOR_ORIG_DECLS (for_stmt))
17613 : {
17614 509 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17615 509 : if (TREE_CODE (elt) == TREE_LIST && TREE_PURPOSE (elt))
17616 : lastprivate = false;
17617 : }
17618 :
17619 7571 : struct gimplify_omp_ctx *outer
17620 7571 : = gimplify_omp_ctxp->outer_context;
17621 7571 : if (outer && lastprivate)
17622 4887 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17623 : true);
17624 :
17625 9577 : c = build_omp_clause (input_location,
17626 : lastprivate ? OMP_CLAUSE_LASTPRIVATE
17627 : : OMP_CLAUSE_PRIVATE);
17628 7571 : OMP_CLAUSE_DECL (c) = decl;
17629 7571 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17630 7571 : OMP_FOR_CLAUSES (for_stmt) = c;
17631 7571 : omp_add_variable (gimplify_omp_ctxp, decl,
17632 : (lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE)
17633 : | GOVD_EXPLICIT | GOVD_SEEN);
17634 7571 : c = NULL_TREE;
17635 : }
17636 : }
17637 34362 : else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
17638 : {
17639 8691 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17640 8691 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17641 : (splay_tree_key) decl);
17642 8691 : if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL))
17643 80 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17644 : OMP_CLAUSE_LASTPRIVATE);
17645 80 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17646 : OMP_CLAUSE_LASTPRIVATE))
17647 40 : if (OMP_CLAUSE_DECL (c3) == decl)
17648 : {
17649 40 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17650 : "conditional %<lastprivate%> on loop "
17651 : "iterator %qD ignored", decl);
17652 40 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17653 40 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17654 : }
17655 : }
17656 : else
17657 25671 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
17658 :
17659 : /* If DECL is not a gimple register, create a temporary variable to act
17660 : as an iteration counter. This is valid, since DECL cannot be
17661 : modified in the body of the loop. Similarly for any iteration vars
17662 : in simd with collapse > 1 where the iterator vars must be
17663 : lastprivate. And similarly for vars mentioned in allocate clauses. */
17664 72896 : if (orig_for_stmt != for_stmt)
17665 22808 : var = decl;
17666 50088 : else if (!is_gimple_reg (decl)
17667 46876 : || (ort == ORT_SIMD
17668 14125 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
17669 89894 : || (allocate_uids && allocate_uids->contains (decl)))
17670 : {
17671 10314 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17672 : /* Make sure omp_add_variable is not called on it prematurely.
17673 : We call it ourselves a few lines later. */
17674 10314 : gimplify_omp_ctxp = NULL;
17675 10314 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17676 10314 : gimplify_omp_ctxp = ctx;
17677 10314 : TREE_OPERAND (t, 0) = var;
17678 :
17679 10314 : gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
17680 :
17681 10314 : if (ort == ORT_SIMD
17682 10314 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17683 : {
17684 770 : c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17685 770 : OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1;
17686 770 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1;
17687 770 : OMP_CLAUSE_DECL (c2) = var;
17688 770 : OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt);
17689 770 : OMP_FOR_CLAUSES (for_stmt) = c2;
17690 770 : omp_add_variable (gimplify_omp_ctxp, var,
17691 : GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
17692 770 : if (c == NULL_TREE)
17693 : {
17694 518 : c = c2;
17695 518 : c2 = NULL_TREE;
17696 : }
17697 : }
17698 : else
17699 9544 : omp_add_variable (gimplify_omp_ctxp, var,
17700 : GOVD_PRIVATE | GOVD_SEEN);
17701 : }
17702 : else
17703 : var = decl;
17704 :
17705 72896 : gimplify_omp_ctxp->in_for_exprs = true;
17706 72896 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17707 : {
17708 719 : tree lb = TREE_OPERAND (t, 1);
17709 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL,
17710 : is_gimple_val, fb_rvalue, false);
17711 719 : ret = MIN (ret, tret);
17712 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL,
17713 : is_gimple_val, fb_rvalue, false);
17714 : }
17715 : else
17716 72177 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17717 : is_gimple_val, fb_rvalue, false);
17718 72896 : gimplify_omp_ctxp->in_for_exprs = false;
17719 72896 : ret = MIN (ret, tret);
17720 72896 : if (ret == GS_ERROR)
17721 : return ret;
17722 :
17723 : /* Handle OMP_FOR_COND. */
17724 72896 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17725 72896 : gcc_assert (COMPARISON_CLASS_P (t));
17726 72896 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17727 :
17728 72896 : gimplify_omp_ctxp->in_for_exprs = true;
17729 72896 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17730 : {
17731 599 : tree ub = TREE_OPERAND (t, 1);
17732 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL,
17733 : is_gimple_val, fb_rvalue, false);
17734 599 : ret = MIN (ret, tret);
17735 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL,
17736 : is_gimple_val, fb_rvalue, false);
17737 : }
17738 : else
17739 72297 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17740 : is_gimple_val, fb_rvalue, false);
17741 72896 : gimplify_omp_ctxp->in_for_exprs = false;
17742 72896 : ret = MIN (ret, tret);
17743 :
17744 : /* Handle OMP_FOR_INCR. */
17745 72896 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17746 72896 : switch (TREE_CODE (t))
17747 : {
17748 35736 : case PREINCREMENT_EXPR:
17749 35736 : case POSTINCREMENT_EXPR:
17750 35736 : {
17751 35736 : tree decl = TREE_OPERAND (t, 0);
17752 : /* c_omp_for_incr_canonicalize_ptr() should have been
17753 : called to massage things appropriately. */
17754 35736 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17755 :
17756 35736 : if (orig_for_stmt != for_stmt)
17757 : break;
17758 25351 : t = build_int_cst (TREE_TYPE (decl), 1);
17759 25351 : if (c)
17760 4470 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17761 25351 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17762 25351 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17763 25351 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17764 25351 : break;
17765 : }
17766 :
17767 3830 : case PREDECREMENT_EXPR:
17768 3830 : case POSTDECREMENT_EXPR:
17769 : /* c_omp_for_incr_canonicalize_ptr() should have been
17770 : called to massage things appropriately. */
17771 3830 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17772 3830 : if (orig_for_stmt != for_stmt)
17773 : break;
17774 1992 : t = build_int_cst (TREE_TYPE (decl), -1);
17775 1992 : if (c)
17776 112 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17777 1992 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17778 1992 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17779 1992 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17780 1992 : break;
17781 :
17782 33330 : case MODIFY_EXPR:
17783 33330 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17784 33330 : TREE_OPERAND (t, 0) = var;
17785 :
17786 33330 : t = TREE_OPERAND (t, 1);
17787 33330 : switch (TREE_CODE (t))
17788 : {
17789 26398 : case PLUS_EXPR:
17790 26398 : if (TREE_OPERAND (t, 1) == decl)
17791 : {
17792 215 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
17793 215 : TREE_OPERAND (t, 0) = var;
17794 215 : break;
17795 : }
17796 :
17797 : /* Fallthru. */
17798 33115 : case MINUS_EXPR:
17799 33115 : case POINTER_PLUS_EXPR:
17800 33115 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17801 33115 : TREE_OPERAND (t, 0) = var;
17802 33115 : break;
17803 0 : default:
17804 0 : gcc_unreachable ();
17805 : }
17806 :
17807 33330 : gimplify_omp_ctxp->in_for_exprs = true;
17808 33330 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17809 : is_gimple_val, fb_rvalue, false);
17810 33330 : ret = MIN (ret, tret);
17811 33330 : if (c)
17812 : {
17813 1573 : tree step = TREE_OPERAND (t, 1);
17814 1573 : tree stept = TREE_TYPE (decl);
17815 1573 : if (POINTER_TYPE_P (stept))
17816 280 : stept = sizetype;
17817 1573 : step = fold_convert (stept, step);
17818 1573 : if (TREE_CODE (t) == MINUS_EXPR)
17819 295 : step = fold_build1 (NEGATE_EXPR, stept, step);
17820 1573 : OMP_CLAUSE_LINEAR_STEP (c) = step;
17821 1573 : if (step != TREE_OPERAND (t, 1))
17822 : {
17823 295 : tret = gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c),
17824 : &for_pre_body, NULL,
17825 : is_gimple_val, fb_rvalue, false);
17826 295 : ret = MIN (ret, tret);
17827 : }
17828 : }
17829 33330 : gimplify_omp_ctxp->in_for_exprs = false;
17830 33330 : break;
17831 :
17832 0 : default:
17833 0 : gcc_unreachable ();
17834 : }
17835 :
17836 72896 : if (c2)
17837 : {
17838 252 : gcc_assert (c);
17839 252 : OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
17840 : }
17841 :
17842 72896 : if ((var != decl || collapse > 1 || tile) && orig_for_stmt == for_stmt)
17843 : {
17844 86242 : for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
17845 64735 : if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
17846 16092 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
17847 55834 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17848 2123 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)
17849 1337 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
17850 74951 : && OMP_CLAUSE_DECL (c) == decl)
17851 : {
17852 7493 : if (is_doacross && (collapse == 1 || i >= collapse))
17853 : t = var;
17854 : else
17855 : {
17856 7420 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17857 7420 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17858 7420 : gcc_assert (TREE_OPERAND (t, 0) == var);
17859 7420 : t = TREE_OPERAND (t, 1);
17860 7420 : gcc_assert (TREE_CODE (t) == PLUS_EXPR
17861 : || TREE_CODE (t) == MINUS_EXPR
17862 : || TREE_CODE (t) == POINTER_PLUS_EXPR);
17863 7420 : gcc_assert (TREE_OPERAND (t, 0) == var);
17864 14738 : t = build2 (TREE_CODE (t), TREE_TYPE (decl),
17865 : is_doacross ? var : decl,
17866 7420 : TREE_OPERAND (t, 1));
17867 : }
17868 7493 : gimple_seq *seq;
17869 7493 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
17870 6897 : seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
17871 : else
17872 596 : seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c);
17873 7493 : push_gimplify_context ();
17874 7493 : gimplify_assign (decl, t, seq);
17875 7493 : gimple *bind = NULL;
17876 7493 : if (gimplify_ctxp->temps)
17877 : {
17878 2030 : bind = gimple_build_bind (NULL_TREE, *seq, NULL_TREE);
17879 2030 : *seq = NULL;
17880 2030 : gimplify_seq_add_stmt (seq, bind);
17881 : }
17882 7493 : pop_gimplify_context (bind);
17883 : }
17884 : }
17885 72896 : if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl)
17886 2609 : for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17887 : {
17888 1197 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17889 1197 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17890 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17891 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17892 336 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17893 1197 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17894 1197 : gcc_assert (COMPARISON_CLASS_P (t));
17895 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17896 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17897 343 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17898 : }
17899 : }
17900 :
17901 51168 : BITMAP_FREE (has_decl_expr);
17902 51401 : delete allocate_uids;
17903 :
17904 51168 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17905 49582 : || (loop_p && orig_for_stmt == for_stmt))
17906 : {
17907 2642 : push_gimplify_context ();
17908 2642 : if (TREE_CODE (OMP_FOR_BODY (orig_for_stmt)) != BIND_EXPR)
17909 : {
17910 1891 : OMP_FOR_BODY (orig_for_stmt)
17911 1891 : = build3 (BIND_EXPR, void_type_node, NULL,
17912 1891 : OMP_FOR_BODY (orig_for_stmt), NULL);
17913 1891 : TREE_SIDE_EFFECTS (OMP_FOR_BODY (orig_for_stmt)) = 1;
17914 : }
17915 : }
17916 :
17917 51168 : gimple *g = gimplify_and_return_first (OMP_FOR_BODY (orig_for_stmt),
17918 : &for_body);
17919 :
17920 51168 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17921 49582 : || (loop_p && orig_for_stmt == for_stmt))
17922 : {
17923 2642 : if (gimple_code (g) == GIMPLE_BIND)
17924 2642 : pop_gimplify_context (g);
17925 : else
17926 0 : pop_gimplify_context (NULL);
17927 : }
17928 :
17929 51168 : if (orig_for_stmt != for_stmt)
17930 36734 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17931 : {
17932 22808 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17933 22808 : decl = TREE_OPERAND (t, 0);
17934 22808 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17935 22808 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17936 772 : gimplify_omp_ctxp = ctx->outer_context;
17937 22808 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17938 22808 : gimplify_omp_ctxp = ctx;
17939 22808 : omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
17940 22808 : TREE_OPERAND (t, 0) = var;
17941 22808 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17942 22808 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17943 22808 : TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
17944 22808 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
17945 791 : for (int j = i + 1;
17946 791 : j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17947 : {
17948 377 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17949 377 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17950 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17951 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17952 : {
17953 133 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17954 133 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17955 : }
17956 377 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17957 377 : gcc_assert (COMPARISON_CLASS_P (t));
17958 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17959 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17960 : {
17961 67 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17962 67 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17963 : }
17964 : }
17965 : }
17966 :
17967 51168 : gimplify_adjust_omp_clauses (pre_p, for_body,
17968 : &OMP_FOR_CLAUSES (orig_for_stmt),
17969 51168 : TREE_CODE (orig_for_stmt));
17970 :
17971 51168 : int kind;
17972 51168 : switch (TREE_CODE (orig_for_stmt))
17973 : {
17974 : case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
17975 10653 : case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
17976 8240 : case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
17977 1586 : case OMP_TASKLOOP: kind = GF_OMP_FOR_KIND_TASKLOOP; break;
17978 12552 : case OACC_LOOP: kind = GF_OMP_FOR_KIND_OACC_LOOP; break;
17979 0 : default:
17980 0 : gcc_unreachable ();
17981 : }
17982 51168 : if (loop_p && kind == GF_OMP_FOR_KIND_SIMD)
17983 : {
17984 1056 : gimplify_seq_add_seq (pre_p, for_pre_body);
17985 1056 : for_pre_body = NULL;
17986 : }
17987 51168 : gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
17988 51168 : TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
17989 : for_pre_body);
17990 51168 : if (orig_for_stmt != for_stmt)
17991 13926 : gimple_omp_for_set_combined_p (gfor, true);
17992 51168 : if (gimplify_omp_ctxp
17993 42505 : && (gimplify_omp_ctxp->combined_loop
17994 34974 : || (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
17995 12292 : && gimplify_omp_ctxp->outer_context
17996 7856 : && gimplify_omp_ctxp->outer_context->combined_loop)))
17997 : {
17998 13926 : gimple_omp_for_set_combined_into_p (gfor, true);
17999 13926 : if (gimplify_omp_ctxp->combined_loop)
18000 7531 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_SIMD);
18001 : else
18002 6395 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_FOR);
18003 : }
18004 :
18005 124064 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18006 : {
18007 72896 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
18008 72896 : gimple_omp_for_set_index (gfor, i, TREE_OPERAND (t, 0));
18009 72896 : gimple_omp_for_set_initial (gfor, i, TREE_OPERAND (t, 1));
18010 72896 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
18011 72896 : gimple_omp_for_set_cond (gfor, i, TREE_CODE (t));
18012 72896 : gimple_omp_for_set_final (gfor, i, TREE_OPERAND (t, 1));
18013 72896 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
18014 72896 : gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1));
18015 : }
18016 :
18017 : /* OMP_TASKLOOP is gimplified as two GIMPLE_OMP_FOR taskloop
18018 : constructs with GIMPLE_OMP_TASK sandwiched in between them.
18019 : The outer taskloop stands for computing the number of iterations,
18020 : counts for collapsed loops and holding taskloop specific clauses.
18021 : The task construct stands for the effect of data sharing on the
18022 : explicit task it creates and the inner taskloop stands for expansion
18023 : of the static loop inside of the explicit task construct. */
18024 51168 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
18025 : {
18026 1586 : tree *gfor_clauses_ptr = gimple_omp_for_clauses_ptr (gfor);
18027 1586 : tree task_clauses = NULL_TREE;
18028 1586 : tree c = *gfor_clauses_ptr;
18029 1586 : tree *gtask_clauses_ptr = &task_clauses;
18030 1586 : tree outer_for_clauses = NULL_TREE;
18031 1586 : tree *gforo_clauses_ptr = &outer_for_clauses;
18032 1586 : bitmap lastprivate_uids = NULL;
18033 1586 : if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
18034 : {
18035 36 : c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
18036 36 : if (c)
18037 : {
18038 18 : lastprivate_uids = BITMAP_ALLOC (NULL);
18039 54 : for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
18040 : OMP_CLAUSE_LASTPRIVATE))
18041 18 : bitmap_set_bit (lastprivate_uids,
18042 18 : DECL_UID (OMP_CLAUSE_DECL (c)));
18043 : }
18044 36 : c = *gfor_clauses_ptr;
18045 : }
18046 12254 : for (; c; c = OMP_CLAUSE_CHAIN (c))
18047 10668 : switch (OMP_CLAUSE_CODE (c))
18048 : {
18049 : /* These clauses are allowed on task, move them there. */
18050 6230 : case OMP_CLAUSE_SHARED:
18051 6230 : case OMP_CLAUSE_FIRSTPRIVATE:
18052 6230 : case OMP_CLAUSE_DEFAULT:
18053 6230 : case OMP_CLAUSE_IF:
18054 6230 : case OMP_CLAUSE_UNTIED:
18055 6230 : case OMP_CLAUSE_FINAL:
18056 6230 : case OMP_CLAUSE_MERGEABLE:
18057 6230 : case OMP_CLAUSE_PRIORITY:
18058 6230 : case OMP_CLAUSE_REDUCTION:
18059 6230 : case OMP_CLAUSE_IN_REDUCTION:
18060 6230 : *gtask_clauses_ptr = c;
18061 6230 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18062 6230 : break;
18063 2068 : case OMP_CLAUSE_PRIVATE:
18064 2068 : if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
18065 : {
18066 : /* We want private on outer for and firstprivate
18067 : on task. */
18068 26 : *gtask_clauses_ptr
18069 26 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18070 : OMP_CLAUSE_FIRSTPRIVATE);
18071 26 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18072 26 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
18073 : openacc);
18074 26 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18075 26 : *gforo_clauses_ptr = c;
18076 26 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18077 : }
18078 : else
18079 : {
18080 2042 : *gtask_clauses_ptr = c;
18081 2042 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18082 : }
18083 : break;
18084 : /* These clauses go into outer taskloop clauses. */
18085 533 : case OMP_CLAUSE_GRAINSIZE:
18086 533 : case OMP_CLAUSE_NUM_TASKS:
18087 533 : case OMP_CLAUSE_NOGROUP:
18088 533 : *gforo_clauses_ptr = c;
18089 533 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18090 533 : break;
18091 : /* Collapse clause we duplicate on both taskloops. */
18092 584 : case OMP_CLAUSE_COLLAPSE:
18093 584 : *gfor_clauses_ptr = c;
18094 584 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18095 584 : *gforo_clauses_ptr = copy_node (c);
18096 584 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18097 584 : break;
18098 : /* For lastprivate, keep the clause on inner taskloop, and add
18099 : a shared clause on task. If the same decl is also firstprivate,
18100 : add also firstprivate clause on the inner taskloop. */
18101 1191 : case OMP_CLAUSE_LASTPRIVATE:
18102 1191 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18103 : {
18104 : /* For taskloop C++ lastprivate IVs, we want:
18105 : 1) private on outer taskloop
18106 : 2) firstprivate and shared on task
18107 : 3) lastprivate on inner taskloop */
18108 38 : *gtask_clauses_ptr
18109 38 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18110 : OMP_CLAUSE_FIRSTPRIVATE);
18111 38 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18112 38 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
18113 : openacc);
18114 38 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18115 38 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
18116 38 : *gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18117 : OMP_CLAUSE_PRIVATE);
18118 38 : OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
18119 38 : OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
18120 38 : TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
18121 38 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18122 : }
18123 1191 : *gfor_clauses_ptr = c;
18124 1191 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18125 1191 : *gtask_clauses_ptr
18126 1191 : = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_SHARED);
18127 1191 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18128 1191 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
18129 312 : OMP_CLAUSE_SHARED_FIRSTPRIVATE (*gtask_clauses_ptr) = 1;
18130 1191 : gtask_clauses_ptr
18131 1191 : = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18132 1191 : break;
18133 : /* Allocate clause we duplicate on task and inner taskloop
18134 : if the decl is lastprivate, otherwise just put on task. */
18135 62 : case OMP_CLAUSE_ALLOCATE:
18136 62 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
18137 62 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
18138 : {
18139 : /* Additionally, put firstprivate clause on task
18140 : for the allocator if it is not constant. */
18141 34 : *gtask_clauses_ptr
18142 34 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18143 : OMP_CLAUSE_FIRSTPRIVATE);
18144 34 : OMP_CLAUSE_DECL (*gtask_clauses_ptr)
18145 34 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
18146 34 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18147 : }
18148 62 : if (lastprivate_uids
18149 97 : && bitmap_bit_p (lastprivate_uids,
18150 35 : DECL_UID (OMP_CLAUSE_DECL (c))))
18151 : {
18152 17 : *gfor_clauses_ptr = c;
18153 17 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18154 17 : *gtask_clauses_ptr = copy_node (c);
18155 17 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18156 : }
18157 : else
18158 : {
18159 45 : *gtask_clauses_ptr = c;
18160 45 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18161 : }
18162 : break;
18163 0 : default:
18164 0 : gcc_unreachable ();
18165 : }
18166 1586 : *gfor_clauses_ptr = NULL_TREE;
18167 1586 : *gtask_clauses_ptr = NULL_TREE;
18168 1586 : *gforo_clauses_ptr = NULL_TREE;
18169 1586 : BITMAP_FREE (lastprivate_uids);
18170 1586 : gimple_set_location (gfor, input_location);
18171 1586 : g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
18172 1586 : g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
18173 : NULL_TREE, NULL_TREE, NULL_TREE);
18174 1586 : gimple_set_location (g, input_location);
18175 1586 : gimple_omp_task_set_taskloop_p (g, true);
18176 1586 : g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
18177 1586 : gomp_for *gforo
18178 1586 : = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
18179 : gimple_omp_for_collapse (gfor),
18180 : gimple_omp_for_pre_body (gfor));
18181 1586 : gimple_omp_for_set_pre_body (gfor, NULL);
18182 1586 : gimple_omp_for_set_combined_p (gforo, true);
18183 1586 : gimple_omp_for_set_combined_into_p (gfor, true);
18184 3458 : for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
18185 : {
18186 1872 : tree type = TREE_TYPE (gimple_omp_for_index (gfor, i));
18187 1872 : tree v = create_tmp_var (type);
18188 1872 : gimple_omp_for_set_index (gforo, i, v);
18189 1872 : t = unshare_expr (gimple_omp_for_initial (gfor, i));
18190 1872 : gimple_omp_for_set_initial (gforo, i, t);
18191 1872 : gimple_omp_for_set_cond (gforo, i,
18192 : gimple_omp_for_cond (gfor, i));
18193 1872 : t = unshare_expr (gimple_omp_for_final (gfor, i));
18194 1872 : gimple_omp_for_set_final (gforo, i, t);
18195 1872 : t = unshare_expr (gimple_omp_for_incr (gfor, i));
18196 1872 : gcc_assert (TREE_OPERAND (t, 0) == gimple_omp_for_index (gfor, i));
18197 1872 : TREE_OPERAND (t, 0) = v;
18198 1872 : gimple_omp_for_set_incr (gforo, i, t);
18199 1872 : t = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
18200 1872 : OMP_CLAUSE_DECL (t) = v;
18201 1872 : OMP_CLAUSE_CHAIN (t) = gimple_omp_for_clauses (gforo);
18202 1872 : gimple_omp_for_set_clauses (gforo, t);
18203 1872 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
18204 : {
18205 90 : tree *p1 = NULL, *p2 = NULL;
18206 90 : t = gimple_omp_for_initial (gforo, i);
18207 90 : if (TREE_CODE (t) == TREE_VEC)
18208 34 : p1 = &TREE_VEC_ELT (t, 0);
18209 90 : t = gimple_omp_for_final (gforo, i);
18210 90 : if (TREE_CODE (t) == TREE_VEC)
18211 : {
18212 31 : if (p1)
18213 23 : p2 = &TREE_VEC_ELT (t, 0);
18214 : else
18215 8 : p1 = &TREE_VEC_ELT (t, 0);
18216 : }
18217 90 : if (p1)
18218 : {
18219 : int j;
18220 58 : for (j = 0; j < i; j++)
18221 58 : if (*p1 == gimple_omp_for_index (gfor, j))
18222 : {
18223 42 : *p1 = gimple_omp_for_index (gforo, j);
18224 42 : if (p2)
18225 23 : *p2 = *p1;
18226 : break;
18227 : }
18228 42 : gcc_assert (j < i);
18229 : }
18230 : }
18231 : }
18232 1586 : gimplify_seq_add_stmt (pre_p, gforo);
18233 : }
18234 : else
18235 49582 : gimplify_seq_add_stmt (pre_p, gfor);
18236 :
18237 51168 : if (TREE_CODE (orig_for_stmt) == OMP_FOR)
18238 : {
18239 18137 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
18240 18137 : unsigned lastprivate_conditional = 0;
18241 18137 : while (ctx
18242 18173 : && (ctx->region_type == ORT_TARGET_DATA
18243 14099 : || ctx->region_type == ORT_TASKGROUP))
18244 36 : ctx = ctx->outer_context;
18245 18137 : if (ctx && (ctx->region_type & ORT_PARALLEL) != 0)
18246 13839 : for (tree c = gimple_omp_for_clauses (gfor);
18247 62715 : c; c = OMP_CLAUSE_CHAIN (c))
18248 48876 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18249 48876 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18250 152 : ++lastprivate_conditional;
18251 13839 : if (lastprivate_conditional)
18252 : {
18253 112 : struct omp_for_data fd;
18254 112 : omp_extract_for_data (gfor, &fd, NULL);
18255 112 : tree type = build_array_type_nelts (unsigned_type_for (fd.iter_type),
18256 112 : lastprivate_conditional);
18257 112 : tree var = create_tmp_var_raw (type);
18258 112 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
18259 112 : OMP_CLAUSE_DECL (c) = var;
18260 112 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18261 112 : gimple_omp_for_set_clauses (gfor, c);
18262 112 : omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
18263 : }
18264 : }
18265 33031 : else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
18266 : {
18267 10653 : unsigned lastprivate_conditional = 0;
18268 49159 : for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
18269 38506 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18270 38506 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18271 119 : ++lastprivate_conditional;
18272 10653 : if (lastprivate_conditional)
18273 : {
18274 91 : struct omp_for_data fd;
18275 91 : omp_extract_for_data (gfor, &fd, NULL);
18276 91 : tree type = unsigned_type_for (fd.iter_type);
18277 301 : while (lastprivate_conditional--)
18278 : {
18279 119 : tree c = build_omp_clause (UNKNOWN_LOCATION,
18280 : OMP_CLAUSE__CONDTEMP_);
18281 119 : OMP_CLAUSE_DECL (c) = create_tmp_var (type);
18282 119 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18283 119 : gimple_omp_for_set_clauses (gfor, c);
18284 : }
18285 : }
18286 : }
18287 :
18288 51168 : if (ret != GS_ALL_DONE)
18289 : return GS_ERROR;
18290 51168 : *expr_p = NULL_TREE;
18291 51168 : return GS_ALL_DONE;
18292 : }
18293 :
18294 : /* Helper for gimplify_omp_loop, called through walk_tree. */
18295 :
18296 : static tree
18297 294 : note_no_context_vars (tree *tp, int *, void *data)
18298 : {
18299 294 : if (VAR_P (*tp)
18300 56 : && DECL_CONTEXT (*tp) == NULL_TREE
18301 309 : && !is_global_var (*tp))
18302 : {
18303 15 : vec<tree> *d = (vec<tree> *) data;
18304 15 : d->safe_push (*tp);
18305 15 : DECL_CONTEXT (*tp) = current_function_decl;
18306 : }
18307 294 : return NULL_TREE;
18308 : }
18309 :
18310 : /* Gimplify the gross structure of an OMP_LOOP statement. */
18311 :
18312 : static enum gimplify_status
18313 1056 : gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
18314 : {
18315 1056 : tree for_stmt = *expr_p;
18316 1056 : tree clauses = OMP_FOR_CLAUSES (for_stmt);
18317 1056 : struct gimplify_omp_ctx *octx = gimplify_omp_ctxp;
18318 1056 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18319 1056 : int i;
18320 :
18321 1056 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
18322 1056 : if (*expr_p != for_stmt)
18323 : return GS_OK;
18324 :
18325 : /* If order is not present, the behavior is as if order(concurrent)
18326 : appeared. */
18327 1056 : tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER);
18328 1056 : if (order == NULL_TREE)
18329 : {
18330 799 : order = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_ORDER);
18331 799 : OMP_CLAUSE_CHAIN (order) = clauses;
18332 799 : OMP_FOR_CLAUSES (for_stmt) = clauses = order;
18333 : }
18334 :
18335 1056 : tree bind = omp_find_clause (clauses, OMP_CLAUSE_BIND);
18336 1056 : if (bind == NULL_TREE)
18337 : {
18338 574 : if (!flag_openmp) /* flag_openmp_simd */
18339 : ;
18340 557 : else if (octx && (octx->region_type & ORT_TEAMS) != 0)
18341 : kind = OMP_CLAUSE_BIND_TEAMS;
18342 327 : else if (octx && (octx->region_type & ORT_PARALLEL) != 0)
18343 : kind = OMP_CLAUSE_BIND_PARALLEL;
18344 : else
18345 : {
18346 187 : for (; octx; octx = octx->outer_context)
18347 : {
18348 79 : if ((octx->region_type & ORT_ACC) != 0
18349 79 : || octx->region_type == ORT_NONE
18350 79 : || octx->region_type == ORT_IMPLICIT_TARGET)
18351 0 : continue;
18352 : break;
18353 : }
18354 187 : if (octx == NULL && !in_omp_construct)
18355 4 : error_at (EXPR_LOCATION (for_stmt),
18356 : "%<bind%> clause not specified on a %<loop%> "
18357 : "construct not nested inside another OpenMP construct");
18358 : }
18359 574 : bind = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_BIND);
18360 574 : OMP_CLAUSE_CHAIN (bind) = clauses;
18361 574 : OMP_CLAUSE_BIND_KIND (bind) = kind;
18362 574 : OMP_FOR_CLAUSES (for_stmt) = bind;
18363 : }
18364 : else
18365 482 : switch (OMP_CLAUSE_BIND_KIND (bind))
18366 : {
18367 : case OMP_CLAUSE_BIND_THREAD:
18368 : break;
18369 166 : case OMP_CLAUSE_BIND_PARALLEL:
18370 166 : if (!flag_openmp) /* flag_openmp_simd */
18371 : {
18372 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18373 0 : break;
18374 : }
18375 240 : for (; octx; octx = octx->outer_context)
18376 78 : if (octx->region_type == ORT_SIMD
18377 78 : && omp_find_clause (octx->clauses, OMP_CLAUSE_BIND) == NULL_TREE)
18378 : {
18379 4 : error_at (EXPR_LOCATION (for_stmt),
18380 : "%<bind(parallel)%> on a %<loop%> construct nested "
18381 : "inside %<simd%> construct");
18382 4 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18383 4 : break;
18384 : }
18385 : kind = OMP_CLAUSE_BIND_PARALLEL;
18386 : break;
18387 162 : case OMP_CLAUSE_BIND_TEAMS:
18388 162 : if (!flag_openmp) /* flag_openmp_simd */
18389 : {
18390 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18391 0 : break;
18392 : }
18393 162 : if ((octx
18394 128 : && octx->region_type != ORT_IMPLICIT_TARGET
18395 111 : && octx->region_type != ORT_NONE
18396 111 : && (octx->region_type & ORT_TEAMS) == 0)
18397 110 : || in_omp_construct)
18398 : {
18399 64 : error_at (EXPR_LOCATION (for_stmt),
18400 : "%<bind(teams)%> on a %<loop%> region not strictly "
18401 : "nested inside of a %<teams%> region");
18402 64 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18403 64 : break;
18404 : }
18405 : kind = OMP_CLAUSE_BIND_TEAMS;
18406 : break;
18407 0 : default:
18408 0 : gcc_unreachable ();
18409 : }
18410 :
18411 4280 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
18412 3224 : switch (OMP_CLAUSE_CODE (*pc))
18413 : {
18414 343 : case OMP_CLAUSE_REDUCTION:
18415 343 : if (OMP_CLAUSE_REDUCTION_INSCAN (*pc))
18416 : {
18417 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18418 : "%<inscan%> %<reduction%> clause on "
18419 : "%qs construct", "loop");
18420 4 : OMP_CLAUSE_REDUCTION_INSCAN (*pc) = 0;
18421 : }
18422 343 : if (OMP_CLAUSE_REDUCTION_TASK (*pc))
18423 : {
18424 8 : error_at (OMP_CLAUSE_LOCATION (*pc),
18425 : "invalid %<task%> reduction modifier on construct "
18426 : "other than %<parallel%>, %qs or %<sections%>",
18427 4 : lang_GNU_Fortran () ? "do" : "for");
18428 4 : OMP_CLAUSE_REDUCTION_TASK (*pc) = 0;
18429 : }
18430 343 : pc = &OMP_CLAUSE_CHAIN (*pc);
18431 343 : break;
18432 : case OMP_CLAUSE_LASTPRIVATE:
18433 293 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18434 : {
18435 289 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
18436 289 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
18437 289 : if (OMP_CLAUSE_DECL (*pc) == TREE_OPERAND (t, 0))
18438 : break;
18439 26 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18440 25 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18441 : i)) == TREE_LIST
18442 48 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18443 : i)))
18444 : {
18445 22 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18446 22 : if (OMP_CLAUSE_DECL (*pc) == TREE_PURPOSE (orig))
18447 : break;
18448 : }
18449 : }
18450 289 : if (i == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
18451 : {
18452 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18453 : "%<lastprivate%> clause on a %<loop%> construct refers "
18454 : "to a variable %qD which is not the loop iterator",
18455 4 : OMP_CLAUSE_DECL (*pc));
18456 4 : *pc = OMP_CLAUSE_CHAIN (*pc);
18457 4 : break;
18458 : }
18459 285 : pc = &OMP_CLAUSE_CHAIN (*pc);
18460 285 : break;
18461 2592 : default:
18462 2592 : pc = &OMP_CLAUSE_CHAIN (*pc);
18463 2592 : break;
18464 : }
18465 :
18466 1056 : TREE_SET_CODE (for_stmt, OMP_SIMD);
18467 :
18468 1056 : int last;
18469 1056 : switch (kind)
18470 : {
18471 : case OMP_CLAUSE_BIND_THREAD: last = 0; break;
18472 414 : case OMP_CLAUSE_BIND_PARALLEL: last = 1; break;
18473 220 : case OMP_CLAUSE_BIND_TEAMS: last = 2; break;
18474 : }
18475 1910 : for (int pass = 1; pass <= last; pass++)
18476 : {
18477 854 : if (pass == 2)
18478 : {
18479 220 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL,
18480 : make_node (BLOCK));
18481 220 : append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind));
18482 220 : *expr_p = make_node (OMP_PARALLEL);
18483 220 : TREE_TYPE (*expr_p) = void_type_node;
18484 220 : OMP_PARALLEL_BODY (*expr_p) = bind;
18485 220 : OMP_PARALLEL_COMBINED (*expr_p) = 1;
18486 220 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (for_stmt));
18487 220 : tree *pc = &OMP_PARALLEL_CLAUSES (*expr_p);
18488 452 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18489 232 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18490 232 : && (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i))
18491 : == TREE_LIST))
18492 : {
18493 16 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18494 16 : if (TREE_PURPOSE (elt) && TREE_VALUE (elt))
18495 : {
18496 13 : *pc = build_omp_clause (UNKNOWN_LOCATION,
18497 : OMP_CLAUSE_FIRSTPRIVATE);
18498 13 : OMP_CLAUSE_DECL (*pc) = TREE_VALUE (elt);
18499 13 : pc = &OMP_CLAUSE_CHAIN (*pc);
18500 : }
18501 : }
18502 : }
18503 854 : tree t = make_node (pass == 2 ? OMP_DISTRIBUTE : OMP_FOR);
18504 854 : tree *pc = &OMP_FOR_CLAUSES (t);
18505 854 : TREE_TYPE (t) = void_type_node;
18506 854 : OMP_FOR_BODY (t) = *expr_p;
18507 854 : SET_EXPR_LOCATION (t, EXPR_LOCATION (for_stmt));
18508 3968 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
18509 3114 : switch (OMP_CLAUSE_CODE (c))
18510 : {
18511 1992 : case OMP_CLAUSE_BIND:
18512 1992 : case OMP_CLAUSE_ORDER:
18513 1992 : case OMP_CLAUSE_COLLAPSE:
18514 1992 : *pc = copy_node (c);
18515 1992 : pc = &OMP_CLAUSE_CHAIN (*pc);
18516 1992 : break;
18517 : case OMP_CLAUSE_PRIVATE:
18518 : case OMP_CLAUSE_FIRSTPRIVATE:
18519 : /* Only needed on innermost. */
18520 : break;
18521 351 : case OMP_CLAUSE_LASTPRIVATE:
18522 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) && pass != last)
18523 : {
18524 7 : *pc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18525 : OMP_CLAUSE_FIRSTPRIVATE);
18526 7 : OMP_CLAUSE_DECL (*pc) = OMP_CLAUSE_DECL (c);
18527 7 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18528 7 : pc = &OMP_CLAUSE_CHAIN (*pc);
18529 : }
18530 351 : *pc = copy_node (c);
18531 351 : OMP_CLAUSE_LASTPRIVATE_STMT (*pc) = NULL_TREE;
18532 351 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18533 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18534 : {
18535 22 : if (pass != last)
18536 7 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (*pc) = 1;
18537 : else
18538 15 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18539 22 : OMP_CLAUSE_LASTPRIVATE_LOOP_IV (*pc) = 0;
18540 : }
18541 351 : pc = &OMP_CLAUSE_CHAIN (*pc);
18542 351 : break;
18543 463 : case OMP_CLAUSE_REDUCTION:
18544 463 : *pc = copy_node (c);
18545 463 : OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c));
18546 463 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18547 463 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc))
18548 : {
18549 15 : auto_vec<tree> no_context_vars;
18550 15 : int walk_subtrees = 0;
18551 15 : note_no_context_vars (&OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18552 : &walk_subtrees, &no_context_vars);
18553 15 : if (tree p = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c))
18554 0 : note_no_context_vars (&p, &walk_subtrees, &no_context_vars);
18555 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (c),
18556 : note_no_context_vars,
18557 : &no_context_vars);
18558 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (c),
18559 : note_no_context_vars,
18560 : &no_context_vars);
18561 :
18562 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)
18563 15 : = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
18564 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18565 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)
18566 0 : = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c));
18567 :
18568 15 : hash_map<tree, tree> decl_map;
18569 15 : decl_map.put (OMP_CLAUSE_DECL (c), OMP_CLAUSE_DECL (c));
18570 15 : decl_map.put (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18571 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc));
18572 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18573 0 : decl_map.put (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
18574 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc));
18575 :
18576 15 : copy_body_data id;
18577 15 : memset (&id, 0, sizeof (id));
18578 15 : id.src_fn = current_function_decl;
18579 15 : id.dst_fn = current_function_decl;
18580 15 : id.src_cfun = cfun;
18581 15 : id.decl_map = &decl_map;
18582 15 : id.copy_decl = copy_decl_no_change;
18583 15 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
18584 15 : id.transform_new_cfg = true;
18585 15 : id.transform_return_to_modify = false;
18586 15 : id.eh_lp_nr = 0;
18587 15 : walk_tree (&OMP_CLAUSE_REDUCTION_INIT (*pc), copy_tree_body_r,
18588 : &id, NULL);
18589 15 : walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (*pc), copy_tree_body_r,
18590 : &id, NULL);
18591 :
18592 60 : for (tree d : no_context_vars)
18593 : {
18594 15 : DECL_CONTEXT (d) = NULL_TREE;
18595 15 : DECL_CONTEXT (*decl_map.get (d)) = NULL_TREE;
18596 : }
18597 15 : }
18598 : else
18599 : {
18600 448 : OMP_CLAUSE_REDUCTION_INIT (*pc)
18601 448 : = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c));
18602 448 : OMP_CLAUSE_REDUCTION_MERGE (*pc)
18603 896 : = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c));
18604 : }
18605 463 : pc = &OMP_CLAUSE_CHAIN (*pc);
18606 463 : break;
18607 0 : default:
18608 0 : gcc_unreachable ();
18609 : }
18610 854 : *pc = NULL_TREE;
18611 854 : *expr_p = t;
18612 : }
18613 1056 : return gimplify_expr (expr_p, pre_p, NULL, is_gimple_stmt, fb_none);
18614 : }
18615 :
18616 :
18617 : /* Helper function of optimize_target_teams, find OMP_TEAMS inside
18618 : of OMP_TARGET's body. */
18619 :
18620 : static tree
18621 98617 : find_omp_teams (tree *tp, int *walk_subtrees, void *)
18622 : {
18623 98617 : *walk_subtrees = 0;
18624 98617 : switch (TREE_CODE (*tp))
18625 : {
18626 : case OMP_TEAMS:
18627 : return *tp;
18628 27250 : case BIND_EXPR:
18629 27250 : case STATEMENT_LIST:
18630 27250 : *walk_subtrees = 1;
18631 27250 : break;
18632 : default:
18633 : break;
18634 : }
18635 : return NULL_TREE;
18636 : }
18637 :
18638 : /* Helper function of optimize_target_teams, determine if the expression
18639 : can be computed safely before the target construct on the host. */
18640 :
18641 : static tree
18642 1311 : computable_teams_clause (tree *tp, int *walk_subtrees, void *)
18643 : {
18644 1831 : splay_tree_node n;
18645 :
18646 1831 : if (TYPE_P (*tp))
18647 : {
18648 0 : *walk_subtrees = 0;
18649 0 : return NULL_TREE;
18650 : }
18651 1831 : switch (TREE_CODE (*tp))
18652 : {
18653 990 : case VAR_DECL:
18654 990 : case PARM_DECL:
18655 990 : case RESULT_DECL:
18656 990 : *walk_subtrees = 0;
18657 990 : if (error_operand_p (*tp)
18658 990 : || !INTEGRAL_TYPE_P (TREE_TYPE (*tp))
18659 990 : || DECL_HAS_VALUE_EXPR_P (*tp)
18660 990 : || DECL_THREAD_LOCAL_P (*tp)
18661 990 : || TREE_SIDE_EFFECTS (*tp)
18662 1980 : || TREE_THIS_VOLATILE (*tp))
18663 0 : return *tp;
18664 990 : if (is_global_var (*tp)
18665 990 : && (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (*tp))
18666 0 : || lookup_attribute ("omp declare target link",
18667 0 : DECL_ATTRIBUTES (*tp))))
18668 16 : return *tp;
18669 974 : if (VAR_P (*tp)
18670 668 : && !DECL_SEEN_IN_BIND_EXPR_P (*tp)
18671 50 : && !is_global_var (*tp)
18672 1024 : && decl_function_context (*tp) == current_function_decl)
18673 50 : return *tp;
18674 1848 : n = splay_tree_lookup (gimplify_omp_ctxp->variables,
18675 924 : (splay_tree_key) *tp);
18676 924 : if (n == NULL)
18677 : {
18678 292 : if (gimplify_omp_ctxp->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
18679 : return NULL_TREE;
18680 24 : return *tp;
18681 : }
18682 632 : else if (n->value & GOVD_LOCAL)
18683 0 : return *tp;
18684 632 : else if (n->value & GOVD_FIRSTPRIVATE)
18685 : return NULL_TREE;
18686 112 : else if ((n->value & (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18687 : == (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18688 : return NULL_TREE;
18689 96 : return *tp;
18690 76 : case INTEGER_CST:
18691 76 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18692 : return *tp;
18693 : return NULL_TREE;
18694 520 : case TARGET_EXPR:
18695 520 : if (TARGET_EXPR_INITIAL (*tp)
18696 520 : || TREE_CODE (TARGET_EXPR_SLOT (*tp)) != VAR_DECL)
18697 : return *tp;
18698 520 : return computable_teams_clause (&TARGET_EXPR_SLOT (*tp),
18699 520 : walk_subtrees, NULL);
18700 : /* Allow some reasonable subset of integral arithmetics. */
18701 193 : case PLUS_EXPR:
18702 193 : case MINUS_EXPR:
18703 193 : case MULT_EXPR:
18704 193 : case TRUNC_DIV_EXPR:
18705 193 : case CEIL_DIV_EXPR:
18706 193 : case FLOOR_DIV_EXPR:
18707 193 : case ROUND_DIV_EXPR:
18708 193 : case TRUNC_MOD_EXPR:
18709 193 : case CEIL_MOD_EXPR:
18710 193 : case FLOOR_MOD_EXPR:
18711 193 : case ROUND_MOD_EXPR:
18712 193 : case RDIV_EXPR:
18713 193 : case EXACT_DIV_EXPR:
18714 193 : case MIN_EXPR:
18715 193 : case MAX_EXPR:
18716 193 : case LSHIFT_EXPR:
18717 193 : case RSHIFT_EXPR:
18718 193 : case BIT_IOR_EXPR:
18719 193 : case BIT_XOR_EXPR:
18720 193 : case BIT_AND_EXPR:
18721 193 : case NEGATE_EXPR:
18722 193 : case ABS_EXPR:
18723 193 : case BIT_NOT_EXPR:
18724 193 : case NON_LVALUE_EXPR:
18725 193 : CASE_CONVERT:
18726 193 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18727 : return *tp;
18728 : return NULL_TREE;
18729 : /* And disallow anything else, except for comparisons. */
18730 52 : default:
18731 52 : if (COMPARISON_CLASS_P (*tp))
18732 : return NULL_TREE;
18733 : return *tp;
18734 : }
18735 : }
18736 :
18737 : /* Try to determine if the num_teams and/or thread_limit expressions
18738 : can have their values determined already before entering the
18739 : target construct.
18740 : INTEGER_CSTs trivially are,
18741 : integral decls that are firstprivate (explicitly or implicitly)
18742 : or explicitly map(always, to:) or map(always, tofrom:) on the target
18743 : region too, and expressions involving simple arithmetics on those
18744 : too, function calls are not ok, dereferencing something neither etc.
18745 : Add NUM_TEAMS and THREAD_LIMIT clauses to the OMP_CLAUSES of
18746 : EXPR based on what we find:
18747 : 0 stands for clause not specified at all, use implementation default
18748 : -1 stands for value that can't be determined easily before entering
18749 : the target construct.
18750 : -2 means that no explicit teams construct was specified
18751 : If teams construct is not present at all, use 1 for num_teams
18752 : and 0 for thread_limit (only one team is involved, and the thread
18753 : limit is implementation defined. */
18754 :
18755 : static void
18756 13475 : optimize_target_teams (tree target, gimple_seq *pre_p)
18757 : {
18758 13475 : tree body = OMP_BODY (target);
18759 13475 : tree teams = walk_tree (&body, find_omp_teams, NULL, NULL);
18760 13475 : tree num_teams_lower = NULL_TREE;
18761 13475 : tree num_teams_upper = integer_zero_node;
18762 13475 : tree thread_limit = integer_zero_node;
18763 13475 : location_t num_teams_loc = EXPR_LOCATION (target);
18764 13475 : location_t thread_limit_loc = EXPR_LOCATION (target);
18765 13475 : tree c, *p, expr;
18766 13475 : struct gimplify_omp_ctx *target_ctx = gimplify_omp_ctxp;
18767 :
18768 13475 : if (teams == NULL_TREE)
18769 7351 : num_teams_upper = build_int_cst (integer_type_node, -2);
18770 : else
18771 10598 : for (c = OMP_TEAMS_CLAUSES (teams); c; c = OMP_CLAUSE_CHAIN (c))
18772 : {
18773 4474 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS)
18774 : {
18775 620 : p = &num_teams_upper;
18776 620 : num_teams_loc = OMP_CLAUSE_LOCATION (c);
18777 620 : if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c))
18778 : {
18779 148 : expr = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c);
18780 148 : if (TREE_CODE (expr) == INTEGER_CST)
18781 21 : num_teams_lower = expr;
18782 127 : else if (walk_tree (&expr, computable_teams_clause,
18783 : NULL, NULL))
18784 19 : num_teams_lower = integer_minus_one_node;
18785 : else
18786 : {
18787 108 : num_teams_lower = expr;
18788 108 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18789 108 : if (gimplify_expr (&num_teams_lower, pre_p, NULL,
18790 : is_gimple_val, fb_rvalue, false)
18791 : == GS_ERROR)
18792 : {
18793 0 : gimplify_omp_ctxp = target_ctx;
18794 0 : num_teams_lower = integer_minus_one_node;
18795 : }
18796 : else
18797 : {
18798 108 : gimplify_omp_ctxp = target_ctx;
18799 108 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18800 28 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
18801 56 : = num_teams_lower;
18802 : }
18803 : }
18804 : }
18805 : }
18806 3854 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
18807 : {
18808 474 : p = &thread_limit;
18809 474 : thread_limit_loc = OMP_CLAUSE_LOCATION (c);
18810 : }
18811 : else
18812 3380 : continue;
18813 1094 : expr = OMP_CLAUSE_OPERAND (c, 0);
18814 1094 : if (TREE_CODE (expr) == INTEGER_CST)
18815 : {
18816 179 : *p = expr;
18817 179 : continue;
18818 : }
18819 915 : if (walk_tree (&expr, computable_teams_clause, NULL, NULL))
18820 : {
18821 219 : *p = integer_minus_one_node;
18822 219 : continue;
18823 : }
18824 696 : *p = expr;
18825 696 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18826 696 : if (gimplify_expr (p, pre_p, NULL, is_gimple_val, fb_rvalue, false)
18827 : == GS_ERROR)
18828 : {
18829 0 : gimplify_omp_ctxp = target_ctx;
18830 0 : *p = integer_minus_one_node;
18831 0 : continue;
18832 : }
18833 696 : gimplify_omp_ctxp = target_ctx;
18834 696 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18835 48 : OMP_CLAUSE_OPERAND (c, 0) = *p;
18836 : }
18837 13475 : if (!omp_find_clause (OMP_TARGET_CLAUSES (target), OMP_CLAUSE_THREAD_LIMIT))
18838 : {
18839 13204 : c = build_omp_clause (thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
18840 13204 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
18841 13204 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18842 13204 : OMP_TARGET_CLAUSES (target) = c;
18843 : }
18844 13475 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
18845 13475 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
18846 13475 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
18847 13475 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18848 13475 : OMP_TARGET_CLAUSES (target) = c;
18849 13475 : }
18850 :
18851 : /* Gimplify the gross structure of several OMP constructs. */
18852 :
18853 : static void
18854 39860 : gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
18855 : {
18856 39860 : tree expr = *expr_p;
18857 39860 : gimple *stmt;
18858 39860 : gimple_seq body = NULL;
18859 39860 : enum omp_region_type ort;
18860 :
18861 39860 : switch (TREE_CODE (expr))
18862 : {
18863 : case OMP_SECTIONS:
18864 : case OMP_SINGLE:
18865 : ort = ORT_WORKSHARE;
18866 : break;
18867 226 : case OMP_SCOPE:
18868 226 : ort = ORT_TASKGROUP;
18869 226 : break;
18870 13475 : case OMP_TARGET:
18871 13475 : ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET;
18872 : break;
18873 2543 : case OACC_KERNELS:
18874 2543 : ort = ORT_ACC_KERNELS;
18875 2543 : break;
18876 7901 : case OACC_PARALLEL:
18877 7901 : ort = ORT_ACC_PARALLEL;
18878 7901 : break;
18879 1040 : case OACC_SERIAL:
18880 1040 : ort = ORT_ACC_SERIAL;
18881 1040 : break;
18882 1950 : case OACC_DATA:
18883 1950 : ort = ORT_ACC_DATA;
18884 1950 : break;
18885 1872 : case OMP_TARGET_DATA:
18886 1872 : ort = ORT_TARGET_DATA;
18887 1872 : break;
18888 8818 : case OMP_TEAMS:
18889 8818 : ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS;
18890 8818 : if (gimplify_omp_ctxp == NULL
18891 6164 : || gimplify_omp_ctxp->region_type == ORT_IMPLICIT_TARGET)
18892 2654 : ort = (enum omp_region_type) (ort | ORT_HOST_TEAMS);
18893 : break;
18894 118 : case OACC_HOST_DATA:
18895 118 : ort = ORT_ACC_HOST_DATA;
18896 118 : break;
18897 0 : default:
18898 0 : gcc_unreachable ();
18899 : }
18900 :
18901 39860 : gimple_seq iterator_loops_seq = NULL;
18902 39860 : if (TREE_CODE (expr) == OMP_TARGET || TREE_CODE (expr) == OMP_TARGET_DATA)
18903 : {
18904 15347 : remove_unused_omp_iterator_vars (&OMP_CLAUSES (expr));
18905 15347 : build_omp_iterators_loops (&OMP_CLAUSES (expr), &iterator_loops_seq);
18906 : }
18907 :
18908 39860 : bool save_in_omp_construct = in_omp_construct;
18909 39860 : if ((ort & ORT_ACC) == 0)
18910 26308 : in_omp_construct = false;
18911 39860 : gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
18912 39860 : TREE_CODE (expr), &iterator_loops_seq);
18913 39860 : if (TREE_CODE (expr) == OMP_TARGET)
18914 13475 : optimize_target_teams (expr, pre_p);
18915 39860 : if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
18916 10961 : || (ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18917 : {
18918 31553 : push_gimplify_context ();
18919 31553 : gimple *g = gimplify_and_return_first (OMP_BODY (expr), &body);
18920 31553 : if (gimple_code (g) == GIMPLE_BIND)
18921 31553 : pop_gimplify_context (g);
18922 : else
18923 0 : pop_gimplify_context (NULL);
18924 31553 : if ((ort & ORT_TARGET_DATA) != 0)
18925 : {
18926 3940 : enum built_in_function end_ix;
18927 3940 : switch (TREE_CODE (expr))
18928 : {
18929 : case OACC_DATA:
18930 : case OACC_HOST_DATA:
18931 : end_ix = BUILT_IN_GOACC_DATA_END;
18932 : break;
18933 1872 : case OMP_TARGET_DATA:
18934 1872 : end_ix = BUILT_IN_GOMP_TARGET_END_DATA;
18935 1872 : break;
18936 0 : default:
18937 0 : gcc_unreachable ();
18938 : }
18939 3940 : tree fn = builtin_decl_explicit (end_ix);
18940 3940 : g = gimple_build_call (fn, 0);
18941 3940 : gimple_seq cleanup = NULL;
18942 3940 : gimple_seq_add_stmt (&cleanup, g);
18943 3940 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
18944 3940 : body = NULL;
18945 3940 : gimple_seq_add_stmt (&body, g);
18946 : }
18947 : }
18948 : else
18949 8307 : gimplify_and_add (OMP_BODY (expr), &body);
18950 39860 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
18951 39860 : TREE_CODE (expr), &iterator_loops_seq);
18952 39860 : in_omp_construct = save_in_omp_construct;
18953 :
18954 39860 : switch (TREE_CODE (expr))
18955 : {
18956 1950 : case OACC_DATA:
18957 3900 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_DATA,
18958 1950 : OMP_CLAUSES (expr));
18959 1950 : break;
18960 118 : case OACC_HOST_DATA:
18961 118 : if (omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT))
18962 : {
18963 128 : for (tree c = OMP_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18964 95 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
18965 57 : OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c) = 1;
18966 : }
18967 :
18968 236 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_HOST_DATA,
18969 118 : OMP_CLAUSES (expr));
18970 118 : break;
18971 2543 : case OACC_KERNELS:
18972 5086 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS,
18973 2543 : OMP_CLAUSES (expr));
18974 2543 : break;
18975 7901 : case OACC_PARALLEL:
18976 15802 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_PARALLEL,
18977 7901 : OMP_CLAUSES (expr));
18978 7901 : break;
18979 1040 : case OACC_SERIAL:
18980 2080 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_SERIAL,
18981 1040 : OMP_CLAUSES (expr));
18982 1040 : break;
18983 634 : case OMP_SECTIONS:
18984 634 : stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
18985 634 : break;
18986 1283 : case OMP_SINGLE:
18987 1283 : stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
18988 1283 : break;
18989 226 : case OMP_SCOPE:
18990 226 : stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
18991 226 : break;
18992 13475 : case OMP_TARGET:
18993 26950 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
18994 13475 : OMP_CLAUSES (expr), iterator_loops_seq);
18995 13475 : break;
18996 1872 : case OMP_TARGET_DATA:
18997 : /* Put use_device_{ptr,addr} clauses last, as map clauses are supposed
18998 : to be evaluated before the use_device_{ptr,addr} clauses if they
18999 : refer to the same variables. */
19000 1872 : {
19001 1872 : tree use_device_clauses;
19002 1872 : tree *pc, *uc = &use_device_clauses;
19003 9968 : for (pc = &OMP_CLAUSES (expr); *pc; )
19004 8096 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
19005 8096 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
19006 : {
19007 1959 : *uc = *pc;
19008 1959 : *pc = OMP_CLAUSE_CHAIN (*pc);
19009 1959 : uc = &OMP_CLAUSE_CHAIN (*uc);
19010 : }
19011 : else
19012 6137 : pc = &OMP_CLAUSE_CHAIN (*pc);
19013 1872 : *uc = NULL_TREE;
19014 1872 : *pc = use_device_clauses;
19015 1872 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_DATA,
19016 1872 : OMP_CLAUSES (expr), iterator_loops_seq);
19017 : }
19018 1872 : break;
19019 8818 : case OMP_TEAMS:
19020 8818 : stmt = gimple_build_omp_teams (body, OMP_CLAUSES (expr));
19021 8818 : if ((ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
19022 2654 : gimple_omp_teams_set_host (as_a <gomp_teams *> (stmt), true);
19023 : break;
19024 0 : default:
19025 0 : gcc_unreachable ();
19026 : }
19027 :
19028 39860 : gimplify_seq_add_stmt (pre_p, stmt);
19029 39860 : *expr_p = NULL_TREE;
19030 39860 : }
19031 :
19032 : /* Gimplify the gross structure of OpenACC enter/exit data, update, and OpenMP
19033 : target update constructs. */
19034 :
19035 : static void
19036 12299 : gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
19037 : {
19038 12299 : tree expr = *expr_p;
19039 12299 : int kind;
19040 12299 : gomp_target *stmt;
19041 12299 : enum omp_region_type ort = ORT_WORKSHARE;
19042 :
19043 12299 : switch (TREE_CODE (expr))
19044 : {
19045 : case OACC_ENTER_DATA:
19046 : kind = GF_OMP_TARGET_KIND_OACC_ENTER_DATA;
19047 : ort = ORT_ACC;
19048 : break;
19049 : case OACC_EXIT_DATA:
19050 : kind = GF_OMP_TARGET_KIND_OACC_EXIT_DATA;
19051 : ort = ORT_ACC;
19052 : break;
19053 : case OACC_UPDATE:
19054 : kind = GF_OMP_TARGET_KIND_OACC_UPDATE;
19055 : ort = ORT_ACC;
19056 : break;
19057 : case OMP_TARGET_UPDATE:
19058 : kind = GF_OMP_TARGET_KIND_UPDATE;
19059 : break;
19060 : case OMP_TARGET_ENTER_DATA:
19061 : kind = GF_OMP_TARGET_KIND_ENTER_DATA;
19062 : break;
19063 : case OMP_TARGET_EXIT_DATA:
19064 : kind = GF_OMP_TARGET_KIND_EXIT_DATA;
19065 : break;
19066 0 : default:
19067 0 : gcc_unreachable ();
19068 : }
19069 :
19070 12299 : gimple_seq iterator_loops_seq = NULL;
19071 12299 : remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr));
19072 12299 : build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr),
19073 : &iterator_loops_seq);
19074 :
19075 12299 : gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
19076 12299 : ort, TREE_CODE (expr), &iterator_loops_seq);
19077 12299 : gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
19078 12299 : TREE_CODE (expr), &iterator_loops_seq);
19079 12299 : if (TREE_CODE (expr) == OACC_UPDATE
19080 12299 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
19081 : OMP_CLAUSE_IF_PRESENT))
19082 : {
19083 : /* The runtime uses GOMP_MAP_{TO,FROM} to denote the if_present
19084 : clause. */
19085 123 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19086 97 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
19087 47 : switch (OMP_CLAUSE_MAP_KIND (c))
19088 : {
19089 14 : case GOMP_MAP_FORCE_TO:
19090 14 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
19091 14 : break;
19092 24 : case GOMP_MAP_FORCE_FROM:
19093 24 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FROM);
19094 24 : break;
19095 : default:
19096 : break;
19097 : }
19098 : }
19099 12273 : else if (TREE_CODE (expr) == OACC_EXIT_DATA
19100 12273 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
19101 : OMP_CLAUSE_FINALIZE))
19102 : {
19103 : /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote "finalize"
19104 : semantics. */
19105 75 : bool have_clause = false;
19106 275 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19107 200 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
19108 117 : switch (OMP_CLAUSE_MAP_KIND (c))
19109 : {
19110 45 : case GOMP_MAP_FROM:
19111 45 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
19112 45 : have_clause = true;
19113 45 : break;
19114 47 : case GOMP_MAP_RELEASE:
19115 47 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
19116 47 : have_clause = true;
19117 47 : break;
19118 : case GOMP_MAP_TO_PSET:
19119 : /* Fortran arrays with descriptors must map that descriptor when
19120 : doing standalone "attach" operations (in OpenACC). In that
19121 : case GOMP_MAP_TO_PSET appears by itself with no preceding
19122 : clause (see trans-openmp.cc:gfc_trans_omp_clauses). */
19123 : break;
19124 2 : case GOMP_MAP_POINTER:
19125 : /* TODO PR92929: we may see these here, but they'll always follow
19126 : one of the clauses above, and will be handled by libgomp as
19127 : one group, so no handling required here. */
19128 2 : gcc_assert (have_clause);
19129 : break;
19130 22 : case GOMP_MAP_DETACH:
19131 22 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_DETACH);
19132 22 : have_clause = false;
19133 22 : break;
19134 : case GOMP_MAP_STRUCT:
19135 : case GOMP_MAP_STRUCT_UNORD:
19136 22 : have_clause = false;
19137 : break;
19138 0 : default:
19139 0 : gcc_unreachable ();
19140 : }
19141 : }
19142 12299 : stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr),
19143 : iterator_loops_seq);
19144 :
19145 12299 : gimplify_seq_add_stmt (pre_p, stmt);
19146 12299 : *expr_p = NULL_TREE;
19147 12299 : }
19148 :
19149 : /* A subroutine of gimplify_omp_atomic. The front end is supposed to have
19150 : stabilized the lhs of the atomic operation as *ADDR. Return true if
19151 : EXPR is this stabilized form. */
19152 :
19153 : static bool
19154 36630 : goa_lhs_expr_p (tree expr, tree addr)
19155 : {
19156 : /* Also include casts to other type variants. The C front end is fond
19157 : of adding these for e.g. volatile variables. This is like
19158 : STRIP_TYPE_NOPS but includes the main variant lookup. */
19159 36630 : STRIP_USELESS_TYPE_CONVERSION (expr);
19160 :
19161 36630 : if (INDIRECT_REF_P (expr))
19162 : {
19163 5001 : expr = TREE_OPERAND (expr, 0);
19164 5001 : while (expr != addr
19165 91 : && (CONVERT_EXPR_P (expr)
19166 91 : || TREE_CODE (expr) == NON_LVALUE_EXPR)
19167 0 : && TREE_CODE (expr) == TREE_CODE (addr)
19168 5001 : && types_compatible_p (TREE_TYPE (expr), TREE_TYPE (addr)))
19169 : {
19170 0 : expr = TREE_OPERAND (expr, 0);
19171 0 : addr = TREE_OPERAND (addr, 0);
19172 : }
19173 5001 : if (expr == addr)
19174 : return true;
19175 91 : return (TREE_CODE (addr) == ADDR_EXPR
19176 62 : && TREE_CODE (expr) == ADDR_EXPR
19177 91 : && TREE_OPERAND (addr, 0) == TREE_OPERAND (expr, 0));
19178 : }
19179 31629 : if (TREE_CODE (addr) == ADDR_EXPR && expr == TREE_OPERAND (addr, 0))
19180 : return true;
19181 : return false;
19182 : }
19183 :
19184 : /* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR. If an
19185 : expression does not involve the lhs, evaluate it into a temporary.
19186 : Return 1 if the lhs appeared as a subexpression, 0 if it did not,
19187 : or -1 if an error was encountered. */
19188 :
19189 : static int
19190 36630 : goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
19191 : tree lhs_var, tree &target_expr, bool rhs, int depth)
19192 : {
19193 36630 : tree expr = *expr_p;
19194 36630 : int saw_lhs = 0;
19195 :
19196 36630 : if (goa_lhs_expr_p (expr, lhs_addr))
19197 : {
19198 9132 : if (pre_p)
19199 8474 : *expr_p = lhs_var;
19200 9132 : return 1;
19201 : }
19202 27498 : if (is_gimple_val (expr))
19203 : return 0;
19204 :
19205 : /* Maximum depth of lhs in expression is for the
19206 : __builtin_clear_padding (...), __builtin_clear_padding (...),
19207 : __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs; */
19208 17212 : if (++depth > 7)
19209 16 : goto finish;
19210 :
19211 17196 : switch (TREE_CODE_CLASS (TREE_CODE (expr)))
19212 : {
19213 9599 : case tcc_binary:
19214 9599 : case tcc_comparison:
19215 9599 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
19216 : lhs_var, target_expr, true, depth);
19217 : /* FALLTHRU */
19218 11642 : case tcc_unary:
19219 11642 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
19220 : lhs_var, target_expr, true, depth);
19221 11642 : break;
19222 2982 : case tcc_expression:
19223 2982 : switch (TREE_CODE (expr))
19224 : {
19225 836 : case TRUTH_ANDIF_EXPR:
19226 836 : case TRUTH_ORIF_EXPR:
19227 836 : case TRUTH_AND_EXPR:
19228 836 : case TRUTH_OR_EXPR:
19229 836 : case TRUTH_XOR_EXPR:
19230 836 : case BIT_INSERT_EXPR:
19231 836 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19232 : lhs_addr, lhs_var, target_expr, true,
19233 : depth);
19234 : /* FALLTHRU */
19235 888 : case TRUTH_NOT_EXPR:
19236 888 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19237 : lhs_addr, lhs_var, target_expr, true,
19238 : depth);
19239 888 : break;
19240 550 : case MODIFY_EXPR:
19241 550 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19242 : target_expr, true, depth))
19243 : break;
19244 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19245 : lhs_addr, lhs_var, target_expr, true,
19246 : depth);
19247 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19248 : lhs_addr, lhs_var, target_expr, false,
19249 : depth);
19250 544 : break;
19251 : /* FALLTHRU */
19252 164 : case ADDR_EXPR:
19253 164 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19254 : target_expr, true, depth))
19255 : break;
19256 138 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19257 : lhs_addr, lhs_var, target_expr, false,
19258 : depth);
19259 138 : break;
19260 : case COMPOUND_EXPR:
19261 : /* Break out any preevaluations from cp_build_modify_expr. */
19262 76 : for (; TREE_CODE (expr) == COMPOUND_EXPR;
19263 38 : expr = TREE_OPERAND (expr, 1))
19264 : {
19265 : /* Special-case __builtin_clear_padding call before
19266 : __builtin_memcmp. */
19267 38 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
19268 : {
19269 2 : tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
19270 2 : if (fndecl
19271 2 : && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
19272 0 : && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
19273 2 : && (!pre_p
19274 0 : || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
19275 : lhs_addr, lhs_var,
19276 : target_expr, true, depth)))
19277 : {
19278 0 : if (pre_p)
19279 0 : *expr_p = expr;
19280 0 : saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
19281 : pre_p, lhs_addr, lhs_var,
19282 : target_expr, true, depth);
19283 0 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
19284 : pre_p, lhs_addr, lhs_var,
19285 : target_expr, rhs, depth);
19286 0 : return saw_lhs;
19287 : }
19288 : }
19289 :
19290 38 : if (pre_p)
19291 35 : gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
19292 : }
19293 38 : if (!pre_p)
19294 3 : return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
19295 3 : target_expr, rhs, depth);
19296 35 : *expr_p = expr;
19297 35 : return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
19298 35 : target_expr, rhs, depth);
19299 441 : case COND_EXPR:
19300 441 : if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
19301 : lhs_var, target_expr, true, depth))
19302 : break;
19303 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19304 : lhs_addr, lhs_var, target_expr, true,
19305 : depth);
19306 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19307 : lhs_addr, lhs_var, target_expr, true,
19308 : depth);
19309 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
19310 : lhs_addr, lhs_var, target_expr, true,
19311 : depth);
19312 428 : break;
19313 880 : case TARGET_EXPR:
19314 880 : if (TARGET_EXPR_INITIAL (expr))
19315 : {
19316 880 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
19317 : lhs_var, target_expr, true,
19318 : depth))
19319 : break;
19320 702 : if (expr == target_expr)
19321 : saw_lhs = 1;
19322 : else
19323 : {
19324 702 : saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
19325 : pre_p, lhs_addr, lhs_var,
19326 : target_expr, true, depth);
19327 702 : if (saw_lhs && target_expr == NULL_TREE && pre_p)
19328 26 : target_expr = expr;
19329 : }
19330 : }
19331 : break;
19332 : default:
19333 : break;
19334 : }
19335 : break;
19336 555 : case tcc_reference:
19337 555 : if (TREE_CODE (expr) == BIT_FIELD_REF
19338 489 : || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
19339 362 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19340 : lhs_addr, lhs_var, target_expr, true,
19341 : depth);
19342 : break;
19343 58 : case tcc_vl_exp:
19344 58 : if (TREE_CODE (expr) == CALL_EXPR)
19345 : {
19346 58 : if (tree fndecl = get_callee_fndecl (expr))
19347 58 : if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING,
19348 : BUILT_IN_MEMCMP))
19349 : {
19350 56 : int nargs = call_expr_nargs (expr);
19351 224 : for (int i = 0; i < nargs; i++)
19352 168 : saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
19353 : pre_p, lhs_addr, lhs_var,
19354 : target_expr, true, depth);
19355 : }
19356 : }
19357 : break;
19358 : default:
19359 : break;
19360 : }
19361 :
19362 17174 : finish:
19363 17174 : if (saw_lhs == 0 && pre_p)
19364 : {
19365 3476 : enum gimplify_status gs;
19366 3476 : if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
19367 : {
19368 0 : gimplify_stmt (&expr, pre_p);
19369 0 : return saw_lhs;
19370 : }
19371 3476 : else if (rhs)
19372 3298 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
19373 : else
19374 178 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
19375 3476 : if (gs != GS_ALL_DONE)
19376 36630 : saw_lhs = -1;
19377 : }
19378 :
19379 : return saw_lhs;
19380 : }
19381 :
19382 : /* Gimplify an OMP_ATOMIC statement. */
19383 :
19384 : static enum gimplify_status
19385 10185 : gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
19386 : {
19387 10185 : tree addr = TREE_OPERAND (*expr_p, 0);
19388 10185 : tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
19389 10185 : ? NULL : TREE_OPERAND (*expr_p, 1);
19390 10185 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
19391 10185 : tree tmp_load;
19392 10185 : gomp_atomic_load *loadstmt;
19393 10185 : gomp_atomic_store *storestmt;
19394 10185 : tree target_expr = NULL_TREE;
19395 :
19396 10185 : tmp_load = create_tmp_reg (type);
19397 10185 : if (rhs
19398 10185 : && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
19399 : true, 0) < 0)
19400 : return GS_ERROR;
19401 :
19402 10185 : if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
19403 : != GS_ALL_DONE)
19404 : return GS_ERROR;
19405 :
19406 10185 : loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
19407 10185 : OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19408 10185 : gimplify_seq_add_stmt (pre_p, loadstmt);
19409 10185 : if (rhs)
19410 : {
19411 : /* BIT_INSERT_EXPR is not valid for non-integral bitfield
19412 : representatives. Use BIT_FIELD_REF on the lhs instead. */
19413 9004 : tree rhsarg = rhs;
19414 9004 : if (TREE_CODE (rhs) == COND_EXPR)
19415 428 : rhsarg = TREE_OPERAND (rhs, 1);
19416 9004 : if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
19417 9004 : && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
19418 : {
19419 32 : tree bitpos = TREE_OPERAND (rhsarg, 2);
19420 32 : tree op1 = TREE_OPERAND (rhsarg, 1);
19421 32 : tree bitsize;
19422 32 : tree tmp_store = tmp_load;
19423 32 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
19424 12 : tmp_store = get_initialized_tmp_var (tmp_load, pre_p);
19425 32 : if (INTEGRAL_TYPE_P (TREE_TYPE (op1)))
19426 32 : bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
19427 : else
19428 0 : bitsize = TYPE_SIZE (TREE_TYPE (op1));
19429 32 : gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
19430 32 : tree t = build2_loc (EXPR_LOCATION (rhsarg),
19431 : MODIFY_EXPR, void_type_node,
19432 32 : build3_loc (EXPR_LOCATION (rhsarg),
19433 32 : BIT_FIELD_REF, TREE_TYPE (op1),
19434 : tmp_store, bitsize, bitpos), op1);
19435 32 : if (TREE_CODE (rhs) == COND_EXPR)
19436 16 : t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
19437 16 : TREE_OPERAND (rhs, 0), t, void_node);
19438 32 : gimplify_and_add (t, pre_p);
19439 32 : rhs = tmp_store;
19440 : }
19441 9004 : bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
19442 9004 : if (TREE_CODE (rhs) == COND_EXPR)
19443 412 : gimplify_ctxp->allow_rhs_cond_expr = true;
19444 9004 : enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
19445 : is_gimple_val, fb_rvalue);
19446 9004 : gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
19447 9004 : if (gs != GS_ALL_DONE)
19448 : return GS_ERROR;
19449 : }
19450 :
19451 10185 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
19452 1181 : rhs = tmp_load;
19453 10185 : storestmt
19454 10185 : = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19455 10185 : if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
19456 : {
19457 37 : gimple_omp_atomic_set_weak (loadstmt);
19458 37 : gimple_omp_atomic_set_weak (storestmt);
19459 : }
19460 10185 : gimplify_seq_add_stmt (pre_p, storestmt);
19461 10185 : switch (TREE_CODE (*expr_p))
19462 : {
19463 2069 : case OMP_ATOMIC_READ:
19464 2069 : case OMP_ATOMIC_CAPTURE_OLD:
19465 2069 : *expr_p = tmp_load;
19466 2069 : gimple_omp_atomic_set_need_value (loadstmt);
19467 2069 : break;
19468 868 : case OMP_ATOMIC_CAPTURE_NEW:
19469 868 : *expr_p = rhs;
19470 868 : gimple_omp_atomic_set_need_value (storestmt);
19471 868 : break;
19472 7248 : default:
19473 7248 : *expr_p = NULL;
19474 7248 : break;
19475 : }
19476 :
19477 : return GS_ALL_DONE;
19478 : }
19479 :
19480 : /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
19481 : body, and adding some EH bits. */
19482 :
19483 : static enum gimplify_status
19484 478 : gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
19485 : {
19486 478 : tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
19487 478 : gimple *body_stmt;
19488 478 : gtransaction *trans_stmt;
19489 478 : gimple_seq body = NULL;
19490 478 : int subcode = 0;
19491 :
19492 : /* Wrap the transaction body in a BIND_EXPR so we have a context
19493 : where to put decls for OMP. */
19494 478 : if (TREE_CODE (tbody) != BIND_EXPR)
19495 : {
19496 439 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
19497 439 : TREE_SIDE_EFFECTS (bind) = 1;
19498 439 : SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
19499 439 : TRANSACTION_EXPR_BODY (expr) = bind;
19500 : }
19501 :
19502 478 : push_gimplify_context ();
19503 478 : temp = voidify_wrapper_expr (*expr_p, NULL);
19504 :
19505 478 : body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
19506 478 : pop_gimplify_context (body_stmt);
19507 :
19508 478 : trans_stmt = gimple_build_transaction (body);
19509 478 : if (TRANSACTION_EXPR_OUTER (expr))
19510 : subcode = GTMA_IS_OUTER;
19511 447 : else if (TRANSACTION_EXPR_RELAXED (expr))
19512 81 : subcode = GTMA_IS_RELAXED;
19513 478 : gimple_transaction_set_subcode (trans_stmt, subcode);
19514 :
19515 478 : gimplify_seq_add_stmt (pre_p, trans_stmt);
19516 :
19517 478 : if (temp)
19518 : {
19519 76 : *expr_p = temp;
19520 76 : return GS_OK;
19521 : }
19522 :
19523 402 : *expr_p = NULL_TREE;
19524 402 : return GS_ALL_DONE;
19525 : }
19526 :
19527 : /* Gimplify an OMP_ORDERED construct. EXPR is the tree version. BODY
19528 : is the OMP_BODY of the original EXPR (which has already been
19529 : gimplified so it's not present in the EXPR).
19530 :
19531 : Return the gimplified GIMPLE_OMP_ORDERED tuple. */
19532 :
19533 : static gimple *
19534 1950 : gimplify_omp_ordered (tree expr, gimple_seq body)
19535 : {
19536 1950 : tree c, decls;
19537 1950 : int failures = 0;
19538 1950 : unsigned int i;
19539 1950 : tree source_c = NULL_TREE;
19540 1950 : tree sink_c = NULL_TREE;
19541 :
19542 1950 : if (gimplify_omp_ctxp)
19543 : {
19544 3291 : for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19545 1515 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19546 1515 : && gimplify_omp_ctxp->loop_iter_var.is_empty ())
19547 : {
19548 74 : error_at (OMP_CLAUSE_LOCATION (c),
19549 : "%<ordered%> construct with %qs clause must be "
19550 : "closely nested inside a loop with %<ordered%> clause",
19551 74 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
19552 74 : failures++;
19553 : }
19554 1441 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19555 1441 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
19556 : {
19557 642 : bool fail = false;
19558 642 : sink_c = c;
19559 642 : if (OMP_CLAUSE_DECL (c) == NULL_TREE)
19560 72 : continue; /* omp_cur_iteration - 1 */
19561 570 : for (decls = OMP_CLAUSE_DECL (c), i = 0;
19562 3201 : decls && TREE_CODE (decls) == TREE_LIST;
19563 2631 : decls = TREE_CHAIN (decls), ++i)
19564 2631 : if (i >= gimplify_omp_ctxp->loop_iter_var.length () / 2)
19565 4 : continue;
19566 5254 : else if (TREE_VALUE (decls)
19567 2627 : != gimplify_omp_ctxp->loop_iter_var[2 * i])
19568 : {
19569 8 : error_at (OMP_CLAUSE_LOCATION (c),
19570 : "variable %qE is not an iteration "
19571 : "of outermost loop %d, expected %qE",
19572 8 : TREE_VALUE (decls), i + 1,
19573 8 : gimplify_omp_ctxp->loop_iter_var[2 * i]);
19574 8 : fail = true;
19575 8 : failures++;
19576 : }
19577 : else
19578 5238 : TREE_VALUE (decls)
19579 2619 : = gimplify_omp_ctxp->loop_iter_var[2 * i + 1];
19580 1136 : if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
19581 : {
19582 16 : error_at (OMP_CLAUSE_LOCATION (c),
19583 : "number of variables in %qs clause with "
19584 : "%<sink%> modifier does not match number of "
19585 : "iteration variables",
19586 16 : OMP_CLAUSE_DOACROSS_DEPEND (c)
19587 : ? "depend" : "doacross");
19588 16 : failures++;
19589 : }
19590 : }
19591 799 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19592 799 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
19593 : {
19594 475 : if (source_c)
19595 : {
19596 4 : error_at (OMP_CLAUSE_LOCATION (c),
19597 : "more than one %qs clause with %<source%> "
19598 : "modifier on an %<ordered%> construct",
19599 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c)
19600 : ? "depend" : "doacross");
19601 4 : failures++;
19602 : }
19603 : else
19604 : source_c = c;
19605 : }
19606 : }
19607 1950 : if (source_c && sink_c)
19608 : {
19609 4 : error_at (OMP_CLAUSE_LOCATION (source_c),
19610 : "%qs clause with %<source%> modifier specified "
19611 : "together with %qs clauses with %<sink%> modifier "
19612 : "on the same construct",
19613 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
19614 4 : OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
19615 4 : failures++;
19616 : }
19617 :
19618 1950 : if (failures)
19619 102 : return gimple_build_nop ();
19620 1848 : return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
19621 : }
19622 :
19623 : /* Gimplify an OMP_INTEROP statement. */
19624 :
19625 : static enum gimplify_status
19626 612 : gimplify_omp_interop (tree *expr_p, gimple_seq *pre_p)
19627 : {
19628 612 : tree expr = *expr_p;
19629 :
19630 612 : gimplify_scan_omp_clauses (&OMP_INTEROP_CLAUSES (expr), pre_p, ORT_TASK,
19631 : OMP_INTEROP);
19632 612 : gimple *stmt = gimple_build_omp_interop (OMP_INTEROP_CLAUSES (expr));
19633 612 : gimplify_seq_add_stmt (pre_p, stmt);
19634 612 : *expr_p = NULL_TREE;
19635 612 : return GS_ALL_DONE;
19636 : }
19637 :
19638 : /* Callback for walk_tree to find an IFN_GOMP_DISPATCH. */
19639 :
19640 : static tree
19641 3100 : find_ifn_gomp_dispatch (tree *tp, int *, void *modify)
19642 : {
19643 3100 : tree t = *tp;
19644 :
19645 3100 : if (TREE_CODE (t) == CALL_EXPR && CALL_EXPR_IFN (t) == IFN_GOMP_DISPATCH)
19646 1414 : return *(tree *) modify ? *(tree *) modify : *tp;
19647 :
19648 2248 : if (TREE_CODE (t) == MODIFY_EXPR)
19649 513 : *(tree *) modify = *tp;
19650 :
19651 : return NULL_TREE;
19652 : }
19653 :
19654 : /* Gimplify an OMP_DISPATCH construct. */
19655 :
19656 : static enum gimplify_status
19657 852 : gimplify_omp_dispatch (tree *expr_p, gimple_seq *pre_p)
19658 : {
19659 852 : tree expr = *expr_p;
19660 852 : gimple_seq body = NULL;
19661 :
19662 852 : gimplify_scan_omp_clauses (&OMP_DISPATCH_CLAUSES (expr), pre_p, ORT_DISPATCH,
19663 : OMP_DISPATCH);
19664 852 : push_gimplify_context ();
19665 :
19666 : // If device clause, adjust ICV
19667 852 : tree device
19668 852 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_DEVICE);
19669 : // If no device clause exists but an interop clause with a single list
19670 : // item, use it to obtain the device number.
19671 852 : if (device)
19672 272 : device = OMP_CLAUSE_DEVICE_ID (device);
19673 : else
19674 : {
19675 580 : tree first_interop_obj
19676 580 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_INTEROP);
19677 580 : if (first_interop_obj)
19678 96 : for (tree c = TREE_CHAIN (first_interop_obj); c; c = TREE_CHAIN (c))
19679 8 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INTEROP)
19680 : {
19681 : first_interop_obj = NULL_TREE;
19682 : break;
19683 : }
19684 95 : if (first_interop_obj)
19685 : {
19686 88 : device = create_tmp_var (integer_type_node);
19687 88 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (first_interop_obj),
19688 : OMP_CLAUSE_DEVICE);
19689 88 : OMP_CLAUSE_DEVICE_ID (c) = device;
19690 88 : TREE_CHAIN (c) = TREE_CHAIN (first_interop_obj);
19691 88 : TREE_CHAIN (first_interop_obj) = c;
19692 88 : first_interop_obj = OMP_CLAUSE_DECL (first_interop_obj);
19693 : /* device = omp_get_interop_int (obj, omp_ipr_device_num, NULL); */
19694 88 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_INTEROP_INT);
19695 88 : fn = build_call_expr (fn, 3, first_interop_obj,
19696 : build_int_cst (integer_type_node, -5),
19697 : null_pointer_node);
19698 88 : gimplify_assign (device, fold_convert (integer_type_node, fn), &body);
19699 : }
19700 : }
19701 852 : tree saved_device_icv = NULL_TREE;
19702 852 : if (device
19703 852 : && (TREE_CODE (device) != INTEGER_CST
19704 709 : || !wi::eq_p (wi::to_wide (device), -1 /* omp_initial_device */)))
19705 : {
19706 : // Save current default-device-var ICV
19707 360 : saved_device_icv = create_tmp_var (integer_type_node);
19708 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
19709 360 : gcall *call = gimple_build_call (fn, 0);
19710 360 : gimple_call_set_lhs (call, saved_device_icv);
19711 360 : gimplify_seq_add_stmt (&body, call);
19712 :
19713 : // Set default device
19714 360 : fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19715 360 : call = gimple_build_call (fn, 1, device);
19716 360 : gimplify_seq_add_stmt (&body, call);
19717 : }
19718 :
19719 : // If the novariants and nocontext clauses are not compile-time constants,
19720 : // we need to generate code for all possible cases:
19721 : // if (novariants) // implies nocontext
19722 : // base()
19723 : // else if (nocontext)
19724 : // variant1()
19725 : // else
19726 : // variant2()
19727 852 : tree *dispatch_body_p = &OMP_DISPATCH_BODY (expr);
19728 852 : if (TREE_CODE (*dispatch_body_p) == BIND_EXPR)
19729 28 : dispatch_body_p = &BIND_EXPR_BODY (*dispatch_body_p);
19730 852 : tree dispatch_body = *dispatch_body_p;
19731 :
19732 : // Look for IFN_GOMP_DISPATCH and extract the base function call
19733 852 : tree base_call_expr = NULL_TREE;
19734 852 : if (TREE_CODE (dispatch_body) == STATEMENT_LIST)
19735 243 : for (tree_stmt_iterator tsi = tsi_start (dispatch_body); !tsi_end_p (tsi);
19736 187 : tsi_next (&tsi))
19737 : {
19738 243 : tree modify = NULL_TREE;
19739 243 : tree stmt = tsi_stmt (tsi);
19740 243 : base_call_expr
19741 243 : = walk_tree (&stmt, find_ifn_gomp_dispatch, &modify, NULL);
19742 243 : if (base_call_expr != NULL_TREE)
19743 : break;
19744 : }
19745 : else
19746 : {
19747 796 : tree modify = NULL_TREE;
19748 796 : base_call_expr
19749 796 : = walk_tree (dispatch_body_p, find_ifn_gomp_dispatch, &modify, NULL);
19750 : }
19751 852 : gcc_assert (base_call_expr != NULL_TREE);
19752 :
19753 852 : tree dst = NULL_TREE;
19754 852 : if (TREE_CODE (base_call_expr) == MODIFY_EXPR)
19755 : {
19756 290 : dst = TREE_OPERAND (base_call_expr, 0);
19757 290 : base_call_expr = TREE_OPERAND (base_call_expr, 1);
19758 : }
19759 :
19760 880 : while (TREE_CODE (base_call_expr) == FLOAT_EXPR
19761 : || TREE_CODE (base_call_expr) == CONVERT_EXPR
19762 : || TREE_CODE (base_call_expr) == COMPLEX_EXPR
19763 : || TREE_CODE (base_call_expr) == INDIRECT_REF
19764 880 : || TREE_CODE (base_call_expr) == NOP_EXPR)
19765 28 : base_call_expr = TREE_OPERAND (base_call_expr, 0);
19766 :
19767 852 : gcc_assert (CALL_EXPR_IFN (base_call_expr) == IFN_GOMP_DISPATCH);
19768 852 : base_call_expr = CALL_EXPR_ARG (base_call_expr, 0);
19769 :
19770 852 : tree base_fndecl = get_callee_fndecl (base_call_expr);
19771 852 : if (base_fndecl != NULL_TREE)
19772 : {
19773 844 : if (DECL_VIRTUAL_P (base_fndecl))
19774 : {
19775 6 : error_at (
19776 3 : EXPR_LOCATION (base_call_expr),
19777 : "%qD is a virtual function but only a direct call is allowed "
19778 : "in a dispatch construct",
19779 3 : DECL_NAME (base_fndecl));
19780 : }
19781 :
19782 : /* We are not actually going to expand the variant call or use
19783 : the result of omp_get_dynamic candidates here; only check that
19784 : it does not trivially resolve to a call to the base function
19785 : so that we can avoid some extra work in building code that's
19786 : not needed in that case. */
19787 844 : tree construct_context = omp_get_construct_context ();
19788 844 : vec<struct omp_variant> all_candidates
19789 844 : = omp_declare_variant_candidates (base_fndecl, construct_context);
19790 844 : gcc_assert (!all_candidates.is_empty ());
19791 844 : vec<struct omp_variant> candidates
19792 844 : = omp_get_dynamic_candidates (all_candidates, construct_context);
19793 844 : tree variant_fndecl
19794 1676 : = (candidates.length () == 1 ? candidates[0].alternative : NULL_TREE);
19795 :
19796 844 : if (base_fndecl != variant_fndecl
19797 844 : && (omp_has_novariants () == -1 || omp_has_nocontext () == -1))
19798 : {
19799 22 : tree novariants_clause = NULL_TREE, nocontext_clause = NULL_TREE,
19800 22 : novariants_cond = NULL_TREE, nocontext_cond = NULL_TREE;
19801 59 : for (tree c = OMP_DISPATCH_CLAUSES (expr); c; c = TREE_CHAIN (c))
19802 : {
19803 37 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOVARIANTS
19804 37 : && !integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
19805 : {
19806 16 : gcc_assert (novariants_cond == NULL_TREE);
19807 16 : novariants_clause = c;
19808 16 : novariants_cond = OMP_CLAUSE_NOVARIANTS_EXPR (c);
19809 : }
19810 21 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOCONTEXT
19811 21 : && !integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
19812 : {
19813 16 : gcc_assert (nocontext_cond == NULL_TREE);
19814 16 : nocontext_clause = c;
19815 16 : nocontext_cond = OMP_CLAUSE_NOCONTEXT_EXPR (c);
19816 : }
19817 : }
19818 22 : gcc_assert (novariants_cond != NULL_TREE
19819 : || nocontext_cond != NULL_TREE);
19820 :
19821 22 : enum gimplify_status ret
19822 22 : = gimplify_expr (&novariants_cond, &body, NULL, is_gimple_val,
19823 : fb_rvalue);
19824 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19825 0 : return ret;
19826 22 : ret = gimplify_expr (&nocontext_cond, &body, NULL, is_gimple_val,
19827 : fb_rvalue);
19828 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19829 : return ret;
19830 :
19831 22 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19832 :
19833 22 : if (novariants_cond != NULL_TREE)
19834 : {
19835 16 : tree base_label = create_artificial_label (UNKNOWN_LOCATION);
19836 16 : tree cond_label = create_artificial_label (UNKNOWN_LOCATION);
19837 16 : gcond *novariants_cond_stmt
19838 16 : = gimple_build_cond_from_tree (novariants_cond, base_label,
19839 : cond_label);
19840 16 : gimplify_seq_add_stmt (&body, novariants_cond_stmt);
19841 :
19842 16 : gimplify_seq_add_stmt (&body, gimple_build_label (base_label));
19843 16 : tree base_call_expr2 = copy_node (base_call_expr);
19844 16 : base_call_expr2
19845 16 : = build_call_expr_internal_loc (EXPR_LOCATION (base_call_expr2),
19846 : IFN_GOMP_DISPATCH,
19847 16 : TREE_TYPE (base_call_expr2), 1,
19848 : base_call_expr2);
19849 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19850 : {
19851 16 : base_call_expr2 = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19852 : base_call_expr2);
19853 : }
19854 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19855 16 : = boolean_true_node;
19856 16 : gimplify_and_add (base_call_expr2, &body);
19857 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19858 :
19859 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19860 16 : = boolean_false_node;
19861 16 : gimplify_seq_add_stmt (&body, gimple_build_label (cond_label));
19862 : }
19863 :
19864 22 : if (nocontext_cond != NULL_TREE)
19865 : {
19866 16 : tree variant1_label = create_artificial_label (UNKNOWN_LOCATION);
19867 16 : tree variant2_label = create_artificial_label (UNKNOWN_LOCATION);
19868 16 : gcond *nocontext_cond_stmt
19869 16 : = gimple_build_cond_from_tree (nocontext_cond, variant1_label,
19870 : variant2_label);
19871 16 : gimplify_seq_add_stmt (&body, nocontext_cond_stmt);
19872 :
19873 32 : gimplify_seq_add_stmt (&body,
19874 16 : gimple_build_label (variant1_label));
19875 16 : tree variant_call_expr = copy_node (base_call_expr);
19876 32 : variant_call_expr = build_call_expr_internal_loc (
19877 16 : EXPR_LOCATION (variant_call_expr), IFN_GOMP_DISPATCH,
19878 16 : TREE_TYPE (variant_call_expr), 1, variant_call_expr);
19879 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19880 : {
19881 16 : variant_call_expr = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19882 : variant_call_expr);
19883 : }
19884 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_true_node;
19885 16 : gimplify_and_add (variant_call_expr, &body);
19886 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19887 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_false_node;
19888 32 : gimplify_seq_add_stmt (&body,
19889 16 : gimple_build_label (variant2_label));
19890 : }
19891 :
19892 22 : tree variant_call_expr = base_call_expr;
19893 22 : variant_call_expr
19894 22 : = build_call_expr_internal_loc (EXPR_LOCATION (variant_call_expr),
19895 : IFN_GOMP_DISPATCH,
19896 22 : TREE_TYPE (variant_call_expr), 1,
19897 : variant_call_expr);
19898 22 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19899 : {
19900 22 : variant_call_expr
19901 22 : = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, variant_call_expr);
19902 : }
19903 22 : gimplify_and_add (variant_call_expr, &body);
19904 22 : gimplify_seq_add_stmt (&body, gimple_build_label (end_label));
19905 : }
19906 : else
19907 822 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19908 : }
19909 : else
19910 8 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19911 :
19912 : // Restore default-device-var ICV
19913 852 : if (saved_device_icv != NULL_TREE)
19914 : {
19915 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19916 360 : gcall *call = gimple_build_call (fn, 1, saved_device_icv);
19917 360 : gimplify_seq_add_stmt (&body, call);
19918 : }
19919 :
19920 : // Wrap dispatch body into a bind
19921 852 : gimple *bind = gimple_build_bind (NULL_TREE, body, NULL_TREE);
19922 852 : pop_gimplify_context (bind);
19923 :
19924 : // Manually tear down context created by gimplify_scan_omp_clauses to avoid a
19925 : // call to gimplify_adjust_omp_clauses
19926 852 : gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
19927 852 : if (ctx != NULL)
19928 : {
19929 852 : gcc_assert (ctx->code == OMP_DISPATCH);
19930 852 : gimplify_omp_ctxp = ctx->outer_context;
19931 852 : delete_omp_context (ctx);
19932 : }
19933 :
19934 : // Remove nowait as it has no effect on dispatch (OpenMP 5.2), device as it
19935 : // has been handled above, and depend as the front end handled it by inserting
19936 : // taskwait.
19937 852 : tree *dispatch_clauses_ptr = &OMP_DISPATCH_CLAUSES (expr);
19938 1445 : for (tree c = *dispatch_clauses_ptr; c; c = *dispatch_clauses_ptr)
19939 : {
19940 991 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT
19941 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
19942 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE)
19943 : {
19944 398 : *dispatch_clauses_ptr = OMP_CLAUSE_CHAIN (c);
19945 398 : break;
19946 : }
19947 : else
19948 593 : dispatch_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
19949 : }
19950 :
19951 852 : gimple *stmt = gimple_build_omp_dispatch (bind, OMP_DISPATCH_CLAUSES (expr));
19952 852 : gimplify_seq_add_stmt (pre_p, stmt);
19953 852 : *expr_p = NULL_TREE;
19954 852 : return GS_ALL_DONE;
19955 : }
19956 :
19957 : /* Expand a metadirective that has been resolved at gimplification time
19958 : into the candidate directive variants in CANDIDATES. */
19959 :
19960 : static enum gimplify_status
19961 170 : expand_omp_metadirective (vec<struct omp_variant> &candidates,
19962 : gimple_seq *pre_p)
19963 : {
19964 170 : auto_vec<tree> selectors;
19965 170 : auto_vec<tree> directive_labels;
19966 170 : auto_vec<gimple_seq> directive_bodies;
19967 170 : tree body_label = NULL_TREE;
19968 170 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19969 :
19970 : /* Construct bodies for each candidate. */
19971 415 : for (unsigned i = 0; i < candidates.length(); i++)
19972 : {
19973 245 : struct omp_variant &candidate = candidates[i];
19974 245 : gimple_seq body = NULL;
19975 :
19976 245 : selectors.safe_push (omp_dynamic_cond (candidate.selector,
19977 : find_supercontext ()));
19978 245 : directive_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
19979 :
19980 245 : gimplify_seq_add_stmt (&body,
19981 245 : gimple_build_label (directive_labels.last ()));
19982 245 : if (candidate.alternative != NULL_TREE)
19983 245 : gimplify_stmt (&candidate.alternative, &body);
19984 245 : if (candidate.body != NULL_TREE)
19985 : {
19986 35 : if (body_label != NULL_TREE)
19987 0 : gimplify_seq_add_stmt (&body, gimple_build_goto (body_label));
19988 : else
19989 : {
19990 35 : body_label = create_artificial_label (UNKNOWN_LOCATION);
19991 35 : gimplify_seq_add_stmt (&body, gimple_build_label (body_label));
19992 35 : gimplify_stmt (&candidate.body, &body);
19993 : }
19994 : }
19995 :
19996 245 : directive_bodies.safe_push (body);
19997 : }
19998 :
19999 170 : auto_vec<tree> cond_labels;
20000 :
20001 170 : cond_labels.safe_push (NULL_TREE);
20002 376 : for (unsigned i = 1; i < candidates.length () - 1; i++)
20003 18 : cond_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
20004 170 : if (candidates.length () > 1)
20005 57 : cond_labels.safe_push (directive_labels.last ());
20006 :
20007 : /* Generate conditionals to test each dynamic selector in turn, executing
20008 : the directive candidate if successful. */
20009 490 : for (unsigned i = 0; i < candidates.length () - 1; i++)
20010 : {
20011 75 : if (i != 0)
20012 18 : gimplify_seq_add_stmt (pre_p, gimple_build_label (cond_labels [i]));
20013 :
20014 75 : enum gimplify_status ret = gimplify_expr (&selectors[i], pre_p, NULL,
20015 : is_gimple_val, fb_rvalue);
20016 75 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
20017 : return ret;
20018 :
20019 75 : gcond *cond_stmt
20020 75 : = gimple_build_cond_from_tree (selectors[i], directive_labels[i],
20021 75 : cond_labels[i + 1]);
20022 :
20023 75 : gimplify_seq_add_stmt (pre_p, cond_stmt);
20024 75 : gimplify_seq_add_seq (pre_p, directive_bodies[i]);
20025 75 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (end_label));
20026 : }
20027 :
20028 170 : gimplify_seq_add_seq (pre_p, directive_bodies.last ());
20029 170 : gimplify_seq_add_stmt (pre_p, gimple_build_label (end_label));
20030 :
20031 170 : return GS_ALL_DONE;
20032 170 : }
20033 :
20034 : /* Expand a variant construct that requires late resolution in the ompdevlow
20035 : pass. It's a bit easier to do this in tree form and then gimplify that,
20036 : than to emit gimple. The output is going to look something like:
20037 :
20038 : switch_var = OMP_NEXT_VARIANT (0, state);
20039 : loop_label:
20040 : switch (switch_var)
20041 : {
20042 : case 1:
20043 : if (dynamic_selector_predicate_1)
20044 : {
20045 : alternative_1;
20046 : goto end_label;
20047 : }
20048 : else
20049 : {
20050 : switch_var = OMP_NEXT_VARIANT (1, state);
20051 : goto loop_label;
20052 : }
20053 : case 2:
20054 : ...
20055 : }
20056 : end_label:
20057 :
20058 : OMP_NEXT_VARIANT is a magic cookie that is replaced with the switch variable
20059 : index of the next variant to try, after late resolution. */
20060 :
20061 : static tree
20062 16 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
20063 : tree construct_context)
20064 : {
20065 16 : tree body_label = NULL_TREE;
20066 16 : tree standalone_body = NULL_TREE;
20067 16 : tree loop_label = create_artificial_label (UNKNOWN_LOCATION);
20068 16 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
20069 32 : tree selectors = make_tree_vec (all_candidates.length ());
20070 16 : tree switch_body = NULL_TREE;
20071 16 : tree switch_var = create_tmp_var (integer_type_node, "variant");
20072 16 : tree state = tree_cons (NULL_TREE, construct_context, selectors);
20073 :
20074 92 : for (unsigned int i = 0; i < all_candidates.length (); i++)
20075 : {
20076 76 : tree selector = all_candidates[i].selector;
20077 76 : tree alternative = all_candidates[i].alternative;
20078 76 : tree body = all_candidates[i].body;
20079 76 : TREE_VEC_ELT (selectors, i) = selector;
20080 :
20081 : /* Case label. Numbering is 1-based. */
20082 76 : tree case_val = build_int_cst (integer_type_node, i + 1);
20083 76 : tree case_label
20084 76 : = build_case_label (case_val, NULL_TREE,
20085 : create_artificial_label (UNKNOWN_LOCATION));
20086 76 : append_to_statement_list (case_label, &switch_body);
20087 :
20088 : /* The actual body of the variant. */
20089 76 : tree variant_body = NULL_TREE;
20090 76 : append_to_statement_list (alternative, &variant_body);
20091 :
20092 76 : if (body != NULL_TREE)
20093 : {
20094 0 : if (standalone_body == NULL)
20095 : {
20096 0 : standalone_body = body;
20097 0 : body_label = create_artificial_label (UNKNOWN_LOCATION);
20098 : }
20099 0 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20100 : body_label),
20101 : &variant_body);
20102 : }
20103 : else
20104 76 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20105 : end_label),
20106 : &variant_body);
20107 :
20108 : /* If this is a dynamic selector, wrap variant_body with a conditional.
20109 : If the predicate doesn't match, the else clause sets switch_var and
20110 : jumps to loop_var to try again. */
20111 76 : tree dynamic_selector = omp_dynamic_cond (selector, find_supercontext ());
20112 76 : if (dynamic_selector)
20113 : {
20114 20 : tree else_stmt = NULL_TREE;
20115 20 : tree next = build2 (OMP_NEXT_VARIANT, integer_type_node,
20116 : case_val, state);
20117 20 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20118 : switch_var, next),
20119 : &else_stmt);
20120 20 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20121 : loop_label),
20122 : &else_stmt);
20123 20 : variant_body = build3 (COND_EXPR, void_type_node, dynamic_selector,
20124 : variant_body, else_stmt);
20125 : }
20126 76 : append_to_statement_list (variant_body, &switch_body);
20127 : }
20128 :
20129 : /* Put it all together. */
20130 16 : tree result = NULL_TREE;
20131 16 : tree first = build2 (OMP_NEXT_VARIANT, integer_type_node, integer_zero_node,
20132 : state);
20133 16 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20134 : switch_var, first),
20135 : &result);
20136 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, loop_label),
20137 : &result);
20138 16 : append_to_statement_list (build2 (SWITCH_EXPR, integer_type_node,
20139 : switch_var, switch_body),
20140 : &result);
20141 16 : if (standalone_body)
20142 : {
20143 0 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
20144 : body_label),
20145 : &result);
20146 0 : append_to_statement_list (standalone_body, &result);
20147 : }
20148 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, end_label),
20149 : &result);
20150 16 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
20151 16 : return result;
20152 : }
20153 :
20154 :
20155 : /* Gimplify an OMP_METADIRECTIVE construct. EXPR is the tree version.
20156 : The metadirective will be resolved at this point if possible, otherwise
20157 : a GIMPLE_OMP_VARIANT_CONSTRUCT is created. */
20158 :
20159 : static enum gimplify_status
20160 174 : gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *,
20161 : bool (*) (tree), fallback_t)
20162 : {
20163 : /* Try to resolve the metadirective. */
20164 174 : tree construct_context = omp_get_construct_context ();
20165 174 : vec<struct omp_variant> all_candidates
20166 174 : = omp_metadirective_candidates (*expr_p, construct_context);
20167 174 : vec<struct omp_variant> candidates
20168 174 : = omp_get_dynamic_candidates (all_candidates, construct_context);
20169 174 : if (!candidates.is_empty ())
20170 170 : return expand_omp_metadirective (candidates, pre_p);
20171 :
20172 : /* The metadirective cannot be resolved yet. Turn it into a loop with
20173 : a nested switch statement, using OMP_NEXT_VARIANT to set the control
20174 : variable for the switch. */
20175 4 : *expr_p = expand_late_variant_directive (all_candidates, construct_context);
20176 4 : return GS_OK;
20177 : }
20178 :
20179 : /* Gimplify an OMP_DECLARE_MAPPER node (by just removing it). */
20180 :
20181 : static enum gimplify_status
20182 0 : gimplify_omp_declare_mapper (tree *expr_p)
20183 : {
20184 0 : *expr_p = NULL_TREE;
20185 0 : return GS_ALL_DONE;
20186 : }
20187 :
20188 : /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
20189 : expression produces a value to be used as an operand inside a GIMPLE
20190 : statement, the value will be stored back in *EXPR_P. This value will
20191 : be a tree of class tcc_declaration, tcc_constant, tcc_reference or
20192 : an SSA_NAME. The corresponding sequence of GIMPLE statements is
20193 : emitted in PRE_P and POST_P.
20194 :
20195 : Additionally, this process may overwrite parts of the input
20196 : expression during gimplification. Ideally, it should be
20197 : possible to do non-destructive gimplification.
20198 :
20199 : EXPR_P points to the GENERIC expression to convert to GIMPLE. If
20200 : the expression needs to evaluate to a value to be used as
20201 : an operand in a GIMPLE statement, this value will be stored in
20202 : *EXPR_P on exit. This happens when the caller specifies one
20203 : of fb_lvalue or fb_rvalue fallback flags.
20204 :
20205 : PRE_P will contain the sequence of GIMPLE statements corresponding
20206 : to the evaluation of EXPR and all the side-effects that must
20207 : be executed before the main expression. On exit, the last
20208 : statement of PRE_P is the core statement being gimplified. For
20209 : instance, when gimplifying 'if (++a)' the last statement in
20210 : PRE_P will be 'if (t.1)' where t.1 is the result of
20211 : pre-incrementing 'a'.
20212 :
20213 : POST_P will contain the sequence of GIMPLE statements corresponding
20214 : to the evaluation of all the side-effects that must be executed
20215 : after the main expression. If this is NULL, the post
20216 : side-effects are stored at the end of PRE_P.
20217 :
20218 : The reason why the output is split in two is to handle post
20219 : side-effects explicitly. In some cases, an expression may have
20220 : inner and outer post side-effects which need to be emitted in
20221 : an order different from the one given by the recursive
20222 : traversal. For instance, for the expression (*p--)++ the post
20223 : side-effects of '--' must actually occur *after* the post
20224 : side-effects of '++'. However, gimplification will first visit
20225 : the inner expression, so if a separate POST sequence was not
20226 : used, the resulting sequence would be:
20227 :
20228 : 1 t.1 = *p
20229 : 2 p = p - 1
20230 : 3 t.2 = t.1 + 1
20231 : 4 *p = t.2
20232 :
20233 : However, the post-decrement operation in line #2 must not be
20234 : evaluated until after the store to *p at line #4, so the
20235 : correct sequence should be:
20236 :
20237 : 1 t.1 = *p
20238 : 2 t.2 = t.1 + 1
20239 : 3 *p = t.2
20240 : 4 p = p - 1
20241 :
20242 : So, by specifying a separate post queue, it is possible
20243 : to emit the post side-effects in the correct order.
20244 : If POST_P is NULL, an internal queue will be used. Before
20245 : returning to the caller, the sequence POST_P is appended to
20246 : the main output sequence PRE_P.
20247 :
20248 : GIMPLE_TEST_F points to a function that takes a tree T and
20249 : returns nonzero if T is in the GIMPLE form requested by the
20250 : caller. The GIMPLE predicates are in gimple.cc.
20251 :
20252 : FALLBACK tells the function what sort of a temporary we want if
20253 : gimplification cannot produce an expression that complies with
20254 : GIMPLE_TEST_F.
20255 :
20256 : fb_none means that no temporary should be generated
20257 : fb_rvalue means that an rvalue is OK to generate
20258 : fb_lvalue means that an lvalue is OK to generate
20259 : fb_either means that either is OK, but an lvalue is preferable.
20260 : fb_mayfail means that gimplification may fail (in which case
20261 : GS_ERROR will be returned)
20262 :
20263 : The return value is either GS_ERROR or GS_ALL_DONE, since this
20264 : function iterates until EXPR is completely gimplified or an error
20265 : occurs. */
20266 :
20267 : enum gimplify_status
20268 526131958 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
20269 : bool (*gimple_test_f) (tree), fallback_t fallback)
20270 : {
20271 526131958 : tree tmp;
20272 526131958 : gimple_seq internal_pre = NULL;
20273 526131958 : gimple_seq internal_post = NULL;
20274 526131958 : tree save_expr;
20275 526131958 : bool is_statement;
20276 526131958 : location_t saved_location;
20277 526131958 : enum gimplify_status ret;
20278 526131958 : gimple_stmt_iterator pre_last_gsi, post_last_gsi;
20279 526131958 : tree label;
20280 :
20281 526131958 : save_expr = *expr_p;
20282 526131958 : if (save_expr == NULL_TREE)
20283 : return GS_ALL_DONE;
20284 :
20285 : /* If we are gimplifying a top-level statement, PRE_P must be valid. */
20286 473532839 : is_statement = gimple_test_f == is_gimple_stmt;
20287 473532839 : if (is_statement)
20288 102707807 : gcc_assert (pre_p);
20289 :
20290 : /* Consistency checks. */
20291 473532839 : if (gimple_test_f == is_gimple_reg)
20292 6403205 : gcc_assert (fallback & (fb_rvalue | fb_lvalue));
20293 467129634 : else if (gimple_test_f == is_gimple_val
20294 344384768 : || gimple_test_f == is_gimple_call_addr
20295 327692542 : || gimple_test_f == is_gimple_condexpr_for_cond
20296 322029704 : || gimple_test_f == is_gimple_mem_rhs
20297 321885745 : || gimple_test_f == is_gimple_mem_rhs_or_call
20298 310481144 : || gimple_test_f == is_gimple_reg_rhs
20299 309867292 : || gimple_test_f == is_gimple_reg_rhs_or_call
20300 236986484 : || gimple_test_f == is_gimple_asm_val
20301 236946754 : || gimple_test_f == is_gimple_mem_ref_addr)
20302 245809760 : gcc_assert (fallback & fb_rvalue);
20303 221319874 : else if (gimple_test_f == is_gimple_min_lval
20304 190735492 : || gimple_test_f == is_gimple_lvalue)
20305 84907286 : gcc_assert (fallback & fb_lvalue);
20306 136412588 : else if (gimple_test_f == is_gimple_addressable)
20307 33704781 : gcc_assert (fallback & fb_either);
20308 102707807 : else if (gimple_test_f == is_gimple_stmt)
20309 102707807 : gcc_assert (fallback == fb_none);
20310 : else
20311 : {
20312 : /* We should have recognized the GIMPLE_TEST_F predicate to
20313 : know what kind of fallback to use in case a temporary is
20314 : needed to hold the value or address of *EXPR_P. */
20315 0 : gcc_unreachable ();
20316 : }
20317 :
20318 : /* We used to check the predicate here and return immediately if it
20319 : succeeds. This is wrong; the design is for gimplification to be
20320 : idempotent, and for the predicates to only test for valid forms, not
20321 : whether they are fully simplified. */
20322 473532839 : if (pre_p == NULL)
20323 0 : pre_p = &internal_pre;
20324 :
20325 473532839 : if (post_p == NULL)
20326 190791222 : post_p = &internal_post;
20327 :
20328 : /* Remember the last statements added to PRE_P and POST_P. Every
20329 : new statement added by the gimplification helpers needs to be
20330 : annotated with location information. To centralize the
20331 : responsibility, we remember the last statement that had been
20332 : added to both queues before gimplifying *EXPR_P. If
20333 : gimplification produces new statements in PRE_P and POST_P, those
20334 : statements will be annotated with the same location information
20335 : as *EXPR_P. */
20336 473532839 : pre_last_gsi = gsi_last (*pre_p);
20337 473532839 : post_last_gsi = gsi_last (*post_p);
20338 :
20339 473532839 : saved_location = input_location;
20340 473532839 : if (save_expr != error_mark_node
20341 473532839 : && EXPR_HAS_LOCATION (*expr_p))
20342 177197107 : input_location = EXPR_LOCATION (*expr_p);
20343 :
20344 : /* Loop over the specific gimplifiers until the toplevel node
20345 : remains the same. */
20346 492187809 : do
20347 : {
20348 : /* Strip away as many useless type conversions as possible
20349 : at the toplevel. */
20350 492187809 : STRIP_USELESS_TYPE_CONVERSION (*expr_p);
20351 :
20352 : /* Remember the expr. */
20353 492187809 : save_expr = *expr_p;
20354 :
20355 : /* Die, die, die, my darling. */
20356 492187809 : if (error_operand_p (save_expr))
20357 : {
20358 : ret = GS_ERROR;
20359 : break;
20360 : }
20361 :
20362 : /* Do any language-specific gimplification. */
20363 492184141 : ret = ((enum gimplify_status)
20364 492184141 : lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
20365 492184141 : if (ret == GS_OK)
20366 : {
20367 29515379 : if (*expr_p == NULL_TREE)
20368 : break;
20369 29515379 : if (*expr_p != save_expr)
20370 4909161 : continue;
20371 : }
20372 462668762 : else if (ret != GS_UNHANDLED)
20373 : break;
20374 :
20375 : /* Make sure that all the cases set 'ret' appropriately. */
20376 486668756 : ret = GS_UNHANDLED;
20377 486668756 : switch (TREE_CODE (*expr_p))
20378 : {
20379 : /* First deal with the special cases. */
20380 :
20381 1142287 : case POSTINCREMENT_EXPR:
20382 1142287 : case POSTDECREMENT_EXPR:
20383 1142287 : case PREINCREMENT_EXPR:
20384 1142287 : case PREDECREMENT_EXPR:
20385 2284574 : ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
20386 : fallback != fb_none,
20387 1142287 : TREE_TYPE (*expr_p));
20388 1142287 : break;
20389 :
20390 591654 : case VIEW_CONVERT_EXPR:
20391 591654 : if ((fallback & fb_rvalue)
20392 591528 : && is_gimple_reg_type (TREE_TYPE (*expr_p))
20393 1007488 : && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
20394 : {
20395 403992 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20396 : post_p, is_gimple_val, fb_rvalue);
20397 403992 : recalculate_side_effects (*expr_p);
20398 403992 : break;
20399 : }
20400 : /* Fallthru. */
20401 :
20402 30521507 : case ARRAY_REF:
20403 30521507 : case ARRAY_RANGE_REF:
20404 30521507 : case REALPART_EXPR:
20405 30521507 : case IMAGPART_EXPR:
20406 30521507 : case COMPONENT_REF:
20407 30521507 : ret = gimplify_compound_lval (expr_p, pre_p, post_p,
20408 : fallback ? fallback : fb_rvalue);
20409 30521507 : break;
20410 :
20411 6274925 : case COND_EXPR:
20412 6274925 : ret = gimplify_cond_expr (expr_p, pre_p, fallback);
20413 :
20414 : /* C99 code may assign to an array in a structure value of a
20415 : conditional expression, and this has undefined behavior
20416 : only on execution, so create a temporary if an lvalue is
20417 : required. */
20418 6274925 : if (fallback == fb_lvalue)
20419 : {
20420 7 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20421 7 : mark_addressable (*expr_p);
20422 7 : ret = GS_OK;
20423 : }
20424 : break;
20425 :
20426 17252680 : case CALL_EXPR:
20427 17252680 : ret = gimplify_call_expr (expr_p, pre_p, fallback);
20428 :
20429 : /* C99 code may assign to an array in a structure returned
20430 : from a function, and this has undefined behavior only on
20431 : execution, so create a temporary if an lvalue is
20432 : required. */
20433 17252680 : if (fallback == fb_lvalue)
20434 : {
20435 17395 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20436 17395 : mark_addressable (*expr_p);
20437 17395 : ret = GS_OK;
20438 : }
20439 : break;
20440 :
20441 0 : case TREE_LIST:
20442 0 : gcc_unreachable ();
20443 :
20444 0 : case OMP_ARRAY_SECTION:
20445 0 : gcc_unreachable ();
20446 :
20447 493636 : case COMPOUND_EXPR:
20448 493636 : ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
20449 493636 : break;
20450 :
20451 37193 : case COMPOUND_LITERAL_EXPR:
20452 37193 : ret = gimplify_compound_literal_expr (expr_p, pre_p,
20453 : gimple_test_f, fallback);
20454 37193 : break;
20455 :
20456 50908341 : case MODIFY_EXPR:
20457 50908341 : case INIT_EXPR:
20458 50908341 : ret = gimplify_modify_expr (expr_p, pre_p, post_p,
20459 : fallback != fb_none);
20460 50908341 : break;
20461 :
20462 115042 : case TRUTH_ANDIF_EXPR:
20463 115042 : case TRUTH_ORIF_EXPR:
20464 115042 : {
20465 : /* Preserve the original type of the expression and the
20466 : source location of the outer expression. */
20467 115042 : tree org_type = TREE_TYPE (*expr_p);
20468 115042 : *expr_p = gimple_boolify (*expr_p);
20469 115042 : *expr_p = build3_loc (input_location, COND_EXPR,
20470 : org_type, *expr_p,
20471 : fold_convert_loc
20472 : (input_location,
20473 : org_type, boolean_true_node),
20474 : fold_convert_loc
20475 : (input_location,
20476 : org_type, boolean_false_node));
20477 115042 : ret = GS_OK;
20478 115042 : break;
20479 : }
20480 :
20481 235552 : case TRUTH_NOT_EXPR:
20482 235552 : {
20483 235552 : tree type = TREE_TYPE (*expr_p);
20484 : /* The parsers are careful to generate TRUTH_NOT_EXPR
20485 : only with operands that are always zero or one.
20486 : We do not fold here but handle the only interesting case
20487 : manually, as fold may re-introduce the TRUTH_NOT_EXPR. */
20488 235552 : *expr_p = gimple_boolify (*expr_p);
20489 235552 : if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
20490 235552 : *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
20491 235552 : TREE_TYPE (*expr_p),
20492 235552 : TREE_OPERAND (*expr_p, 0));
20493 : else
20494 0 : *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
20495 0 : TREE_TYPE (*expr_p),
20496 0 : TREE_OPERAND (*expr_p, 0),
20497 0 : build_int_cst (TREE_TYPE (*expr_p), 1));
20498 235552 : if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
20499 5630 : *expr_p = fold_convert_loc (input_location, type, *expr_p);
20500 : ret = GS_OK;
20501 : break;
20502 : }
20503 :
20504 33783823 : case ADDR_EXPR:
20505 33783823 : ret = gimplify_addr_expr (expr_p, pre_p, post_p);
20506 33783823 : break;
20507 :
20508 5598 : case ANNOTATE_EXPR:
20509 5598 : {
20510 5598 : tree cond = TREE_OPERAND (*expr_p, 0);
20511 5598 : tree kind = TREE_OPERAND (*expr_p, 1);
20512 5598 : tree data = TREE_OPERAND (*expr_p, 2);
20513 5598 : tree type = TREE_TYPE (cond);
20514 5598 : if (!INTEGRAL_TYPE_P (type))
20515 : {
20516 0 : *expr_p = cond;
20517 0 : ret = GS_OK;
20518 0 : break;
20519 : }
20520 5598 : tree tmp = create_tmp_var (type);
20521 5598 : gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
20522 5598 : gcall *call
20523 5598 : = gimple_build_call_internal (IFN_ANNOTATE, 3, cond, kind, data);
20524 5598 : gimple_call_set_lhs (call, tmp);
20525 5598 : gimplify_seq_add_stmt (pre_p, call);
20526 5598 : *expr_p = tmp;
20527 5598 : ret = GS_ALL_DONE;
20528 5598 : break;
20529 : }
20530 :
20531 51141 : case VA_ARG_EXPR:
20532 51141 : ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
20533 51141 : break;
20534 :
20535 17663253 : CASE_CONVERT:
20536 17663253 : if (IS_EMPTY_STMT (*expr_p))
20537 : {
20538 : ret = GS_ALL_DONE;
20539 : break;
20540 : }
20541 :
20542 15914341 : if (VOID_TYPE_P (TREE_TYPE (*expr_p))
20543 15914341 : || fallback == fb_none)
20544 : {
20545 : /* Just strip a conversion to void (or in void context) and
20546 : try again. */
20547 2696844 : *expr_p = TREE_OPERAND (*expr_p, 0);
20548 2696844 : ret = GS_OK;
20549 2696844 : break;
20550 : }
20551 :
20552 13217497 : ret = gimplify_conversion (expr_p);
20553 13217497 : if (ret == GS_ERROR)
20554 : break;
20555 13217497 : if (*expr_p != save_expr)
20556 : break;
20557 : /* FALLTHRU */
20558 :
20559 13344188 : case FIX_TRUNC_EXPR:
20560 : /* unary_expr: ... | '(' cast ')' val | ... */
20561 13344188 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20562 : is_gimple_val, fb_rvalue);
20563 13344188 : recalculate_side_effects (*expr_p);
20564 13344188 : break;
20565 :
20566 6332009 : case INDIRECT_REF:
20567 6332009 : {
20568 6332009 : bool volatilep = TREE_THIS_VOLATILE (*expr_p);
20569 6332009 : bool notrap = TREE_THIS_NOTRAP (*expr_p);
20570 6332009 : tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
20571 :
20572 6332009 : *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
20573 6332009 : if (*expr_p != save_expr)
20574 : {
20575 : ret = GS_OK;
20576 : break;
20577 : }
20578 :
20579 6313563 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20580 : is_gimple_reg, fb_rvalue);
20581 6313563 : if (ret == GS_ERROR)
20582 : break;
20583 :
20584 6313560 : recalculate_side_effects (*expr_p);
20585 12627120 : *expr_p = fold_build2_loc (input_location, MEM_REF,
20586 6313560 : TREE_TYPE (*expr_p),
20587 6313560 : TREE_OPERAND (*expr_p, 0),
20588 : build_int_cst (saved_ptr_type, 0));
20589 6313560 : TREE_THIS_VOLATILE (*expr_p) = volatilep;
20590 6313560 : TREE_THIS_NOTRAP (*expr_p) = notrap;
20591 6313560 : ret = GS_OK;
20592 6313560 : break;
20593 : }
20594 :
20595 : /* We arrive here through the various re-gimplifcation paths. */
20596 16085254 : case MEM_REF:
20597 : /* First try re-folding the whole thing. */
20598 16085254 : tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
20599 : TREE_OPERAND (*expr_p, 0),
20600 : TREE_OPERAND (*expr_p, 1));
20601 16085254 : if (tmp)
20602 : {
20603 6638 : REF_REVERSE_STORAGE_ORDER (tmp)
20604 3319 : = REF_REVERSE_STORAGE_ORDER (*expr_p);
20605 3319 : *expr_p = tmp;
20606 3319 : recalculate_side_effects (*expr_p);
20607 3319 : ret = GS_OK;
20608 3319 : break;
20609 : }
20610 : /* Avoid re-gimplifying the address operand if it is already
20611 : in suitable form. Re-gimplifying would mark the address
20612 : operand addressable. Always gimplify when not in SSA form
20613 : as we still may have to gimplify decls with value-exprs. */
20614 16081935 : if (!gimplify_ctxp || !gimple_in_ssa_p (cfun)
20615 17099392 : || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
20616 : {
20617 15119599 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20618 : is_gimple_mem_ref_addr, fb_rvalue);
20619 15119599 : if (ret == GS_ERROR)
20620 : break;
20621 : }
20622 16081935 : recalculate_side_effects (*expr_p);
20623 16081935 : ret = GS_ALL_DONE;
20624 16081935 : break;
20625 :
20626 : /* Constants need not be gimplified. */
20627 44693694 : case INTEGER_CST:
20628 44693694 : case REAL_CST:
20629 44693694 : case FIXED_CST:
20630 44693694 : case STRING_CST:
20631 44693694 : case COMPLEX_CST:
20632 44693694 : case VECTOR_CST:
20633 : /* Drop the overflow flag on constants, we do not want
20634 : that in the GIMPLE IL. */
20635 44693694 : if (TREE_OVERFLOW_P (*expr_p))
20636 886 : *expr_p = drop_tree_overflow (*expr_p);
20637 : ret = GS_ALL_DONE;
20638 : break;
20639 :
20640 117330 : case CONST_DECL:
20641 : /* If we require an lvalue, such as for ADDR_EXPR, retain the
20642 : CONST_DECL node. Otherwise the decl is replaceable by its
20643 : value. */
20644 : /* ??? Should be == fb_lvalue, but ADDR_EXPR passes fb_either. */
20645 117330 : if (fallback & fb_lvalue)
20646 : ret = GS_ALL_DONE;
20647 : else
20648 : {
20649 3277 : *expr_p = DECL_INITIAL (*expr_p);
20650 3277 : ret = GS_OK;
20651 : }
20652 : break;
20653 :
20654 6624277 : case DECL_EXPR:
20655 6624277 : ret = gimplify_decl_expr (expr_p, pre_p);
20656 6624277 : break;
20657 :
20658 6030725 : case BIND_EXPR:
20659 6030725 : ret = gimplify_bind_expr (expr_p, pre_p);
20660 6030725 : break;
20661 :
20662 204526 : case LOOP_EXPR:
20663 204526 : ret = gimplify_loop_expr (expr_p, pre_p);
20664 204526 : break;
20665 :
20666 50003 : case SWITCH_EXPR:
20667 50003 : ret = gimplify_switch_expr (expr_p, pre_p);
20668 50003 : break;
20669 :
20670 3153 : case EXIT_EXPR:
20671 3153 : ret = gimplify_exit_expr (expr_p);
20672 3153 : break;
20673 :
20674 1115783 : case GOTO_EXPR:
20675 : /* If the target is not LABEL, then it is a computed jump
20676 : and the target needs to be gimplified. */
20677 1115783 : if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
20678 : {
20679 1118 : ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
20680 : NULL, is_gimple_val, fb_rvalue);
20681 1118 : if (ret == GS_ERROR)
20682 : break;
20683 : }
20684 2231564 : gimplify_seq_add_stmt (pre_p,
20685 1115782 : gimple_build_goto (GOTO_DESTINATION (*expr_p)));
20686 1115782 : ret = GS_ALL_DONE;
20687 1115782 : break;
20688 :
20689 103119 : case PREDICT_EXPR:
20690 412476 : gimplify_seq_add_stmt (pre_p,
20691 103119 : gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
20692 103119 : PREDICT_EXPR_OUTCOME (*expr_p)));
20693 103119 : ret = GS_ALL_DONE;
20694 103119 : break;
20695 :
20696 2592125 : case LABEL_EXPR:
20697 2592125 : ret = gimplify_label_expr (expr_p, pre_p);
20698 2592125 : label = LABEL_EXPR_LABEL (*expr_p);
20699 2592125 : gcc_assert (decl_function_context (label) == current_function_decl);
20700 :
20701 : /* If the label is used in a goto statement, or address of the label
20702 : is taken, we need to unpoison all variables that were seen so far.
20703 : Doing so would prevent us from reporting a false positives. */
20704 2592125 : if (asan_poisoned_variables
20705 4967 : && asan_used_labels != NULL
20706 1325 : && asan_used_labels->contains (label)
20707 2593037 : && !gimplify_omp_ctxp)
20708 904 : asan_poison_variables (asan_poisoned_variables, false, pre_p);
20709 : break;
20710 :
20711 1037861 : case CASE_LABEL_EXPR:
20712 1037861 : ret = gimplify_case_label_expr (expr_p, pre_p);
20713 :
20714 1037861 : if (gimplify_ctxp->live_switch_vars)
20715 1037674 : asan_poison_variables (gimplify_ctxp->live_switch_vars, false,
20716 : pre_p);
20717 : break;
20718 :
20719 2287088 : case RETURN_EXPR:
20720 2287088 : ret = gimplify_return_expr (*expr_p, pre_p);
20721 2287088 : break;
20722 :
20723 978878 : case CONSTRUCTOR:
20724 : /* Don't reduce this in place; let gimplify_init_constructor work its
20725 : magic. Buf if we're just elaborating this for side effects, just
20726 : gimplify any element that has side-effects. */
20727 978878 : if (fallback == fb_none)
20728 : {
20729 371 : unsigned HOST_WIDE_INT ix;
20730 371 : tree val;
20731 371 : tree temp = NULL_TREE;
20732 388 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
20733 17 : if (TREE_SIDE_EFFECTS (val))
20734 4 : append_to_statement_list (val, &temp);
20735 :
20736 371 : *expr_p = temp;
20737 371 : ret = temp ? GS_OK : GS_ALL_DONE;
20738 : }
20739 : /* C99 code may assign to an array in a constructed
20740 : structure or union, and this has undefined behavior only
20741 : on execution, so create a temporary if an lvalue is
20742 : required. */
20743 978507 : else if (fallback == fb_lvalue)
20744 : {
20745 11 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20746 11 : mark_addressable (*expr_p);
20747 11 : ret = GS_OK;
20748 : }
20749 : else
20750 : ret = GS_ALL_DONE;
20751 : break;
20752 :
20753 : /* The following are special cases that are not handled by the
20754 : original GIMPLE grammar. */
20755 :
20756 : /* SAVE_EXPR nodes are converted into a GIMPLE identifier and
20757 : eliminated. */
20758 442398 : case SAVE_EXPR:
20759 442398 : ret = gimplify_save_expr (expr_p, pre_p, post_p);
20760 442398 : break;
20761 :
20762 385083 : case BIT_FIELD_REF:
20763 385083 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20764 : post_p, is_gimple_lvalue, fb_either);
20765 385083 : recalculate_side_effects (*expr_p);
20766 385083 : break;
20767 :
20768 1989 : case TARGET_MEM_REF:
20769 1989 : {
20770 1989 : enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
20771 :
20772 1989 : if (TMR_BASE (*expr_p))
20773 1989 : r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
20774 : post_p, is_gimple_mem_ref_addr, fb_either);
20775 1989 : if (TMR_INDEX (*expr_p))
20776 1251 : r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
20777 : post_p, is_gimple_val, fb_rvalue);
20778 1989 : if (TMR_INDEX2 (*expr_p))
20779 42 : r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
20780 : post_p, is_gimple_val, fb_rvalue);
20781 : /* TMR_STEP and TMR_OFFSET are always integer constants. */
20782 1989 : ret = MIN (r0, r1);
20783 : }
20784 : break;
20785 :
20786 0 : case NON_LVALUE_EXPR:
20787 : /* This should have been stripped above. */
20788 0 : gcc_unreachable ();
20789 :
20790 98062 : case ASM_EXPR:
20791 98062 : ret = gimplify_asm_expr (expr_p, pre_p, post_p);
20792 98062 : break;
20793 :
20794 511415 : case TRY_FINALLY_EXPR:
20795 511415 : case TRY_CATCH_EXPR:
20796 511415 : {
20797 511415 : gimple_seq eval, cleanup;
20798 511415 : gtry *try_;
20799 :
20800 : /* Calls to destructors are generated automatically in FINALLY/CATCH
20801 : block. They should have location as UNKNOWN_LOCATION. However,
20802 : gimplify_call_expr will reset these call stmts to input_location
20803 : if it finds stmt's location is unknown. To prevent resetting for
20804 : destructors, we set the input_location to unknown.
20805 : Note that this only affects the destructor calls in FINALLY/CATCH
20806 : block, and will automatically reset to its original value by the
20807 : end of gimplify_expr. */
20808 511415 : input_location = UNKNOWN_LOCATION;
20809 511415 : eval = cleanup = NULL;
20810 511415 : gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
20811 511415 : bool save_in_handler_expr = gimplify_ctxp->in_handler_expr;
20812 511415 : if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20813 511415 : && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR)
20814 : {
20815 226 : gimple_seq n = NULL, e = NULL;
20816 226 : gimplify_ctxp->in_handler_expr = true;
20817 226 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20818 : 0), &n);
20819 226 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20820 : 1), &e);
20821 226 : if (!gimple_seq_empty_p (n) || !gimple_seq_empty_p (e))
20822 : {
20823 220 : geh_else *stmt = gimple_build_eh_else (n, e);
20824 220 : gimple_seq_add_stmt (&cleanup, stmt);
20825 : }
20826 : }
20827 : else
20828 : {
20829 511189 : gimplify_ctxp->in_handler_expr = true;
20830 511189 : gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
20831 : }
20832 511415 : gimplify_ctxp->in_handler_expr = save_in_handler_expr;
20833 : /* Don't create bogus GIMPLE_TRY with empty cleanup. */
20834 511415 : if (gimple_seq_empty_p (cleanup))
20835 : {
20836 27562 : gimple_seq_add_seq (pre_p, eval);
20837 27562 : ret = GS_ALL_DONE;
20838 27562 : break;
20839 : }
20840 483853 : try_ = gimple_build_try (eval, cleanup,
20841 483853 : TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20842 : ? GIMPLE_TRY_FINALLY
20843 : : GIMPLE_TRY_CATCH);
20844 483853 : if (EXPR_HAS_LOCATION (save_expr))
20845 885614 : gimple_set_location (try_, EXPR_LOCATION (save_expr));
20846 41046 : else if (LOCATION_LOCUS (saved_location) != UNKNOWN_LOCATION)
20847 30487 : gimple_set_location (try_, saved_location);
20848 483853 : if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
20849 172530 : gimple_try_set_catch_is_cleanup (try_,
20850 172530 : TRY_CATCH_IS_CLEANUP (*expr_p));
20851 483853 : gimplify_seq_add_stmt (pre_p, try_);
20852 483853 : ret = GS_ALL_DONE;
20853 483853 : break;
20854 : }
20855 :
20856 5389181 : case CLEANUP_POINT_EXPR:
20857 5389181 : ret = gimplify_cleanup_point_expr (expr_p, pre_p);
20858 5389181 : break;
20859 :
20860 860707 : case TARGET_EXPR:
20861 860707 : ret = gimplify_target_expr (expr_p, pre_p, post_p);
20862 860707 : break;
20863 :
20864 40814 : case CATCH_EXPR:
20865 40814 : {
20866 40814 : gimple *c;
20867 40814 : gimple_seq handler = NULL;
20868 40814 : gimplify_and_add (CATCH_BODY (*expr_p), &handler);
20869 40814 : c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
20870 40814 : gimplify_seq_add_stmt (pre_p, c);
20871 40814 : ret = GS_ALL_DONE;
20872 40814 : break;
20873 : }
20874 :
20875 5832 : case EH_FILTER_EXPR:
20876 5832 : {
20877 5832 : gimple *ehf;
20878 5832 : gimple_seq failure = NULL;
20879 :
20880 5832 : gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
20881 5832 : ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
20882 5832 : copy_warning (ehf, *expr_p);
20883 5832 : gimplify_seq_add_stmt (pre_p, ehf);
20884 5832 : ret = GS_ALL_DONE;
20885 5832 : break;
20886 : }
20887 :
20888 51287 : case OBJ_TYPE_REF:
20889 51287 : {
20890 51287 : enum gimplify_status r0, r1;
20891 51287 : r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p,
20892 : post_p, is_gimple_val, fb_rvalue);
20893 51287 : r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p,
20894 : post_p, is_gimple_val, fb_rvalue);
20895 51287 : TREE_SIDE_EFFECTS (*expr_p) = 0;
20896 51287 : ret = MIN (r0, r1);
20897 : }
20898 : break;
20899 :
20900 40944 : case LABEL_DECL:
20901 : /* We get here when taking the address of a label. We mark
20902 : the label as "forced"; meaning it can never be removed and
20903 : it is a potential target for any computed goto. */
20904 40944 : FORCED_LABEL (*expr_p) = 1;
20905 40944 : ret = GS_ALL_DONE;
20906 40944 : break;
20907 :
20908 8631060 : case STATEMENT_LIST:
20909 8631060 : ret = gimplify_statement_list (expr_p, pre_p);
20910 8631060 : break;
20911 :
20912 1733 : case WITH_SIZE_EXPR:
20913 1733 : {
20914 2015 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20915 : post_p == &internal_post ? NULL : post_p,
20916 : gimple_test_f, fallback);
20917 1733 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
20918 : is_gimple_val, fb_rvalue);
20919 1733 : ret = GS_ALL_DONE;
20920 : }
20921 1733 : break;
20922 :
20923 110647540 : case VAR_DECL:
20924 110647540 : case PARM_DECL:
20925 110647540 : ret = gimplify_var_or_parm_decl (expr_p);
20926 110647540 : break;
20927 :
20928 348572 : case RESULT_DECL:
20929 : /* When within an OMP context, notice uses of variables. */
20930 348572 : if (gimplify_omp_ctxp)
20931 1412 : omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
20932 : /* Handlers can refer to the function result; if that has been
20933 : moved, we need to track it. */
20934 348572 : if (gimplify_ctxp->in_handler_expr && gimplify_ctxp->return_temp)
20935 64 : *expr_p = gimplify_ctxp->return_temp;
20936 : ret = GS_ALL_DONE;
20937 : break;
20938 :
20939 0 : case DEBUG_EXPR_DECL:
20940 0 : gcc_unreachable ();
20941 :
20942 2497979 : case DEBUG_BEGIN_STMT:
20943 4995958 : gimplify_seq_add_stmt (pre_p,
20944 : gimple_build_debug_begin_stmt
20945 2497979 : (TREE_BLOCK (*expr_p),
20946 2497979 : EXPR_LOCATION (*expr_p)));
20947 2497979 : ret = GS_ALL_DONE;
20948 2497979 : *expr_p = NULL;
20949 2497979 : break;
20950 :
20951 : case SSA_NAME:
20952 : /* Allow callbacks into the gimplifier during optimization. */
20953 : ret = GS_ALL_DONE;
20954 : break;
20955 :
20956 18239 : case OMP_PARALLEL:
20957 18239 : gimplify_omp_parallel (expr_p, pre_p);
20958 18239 : ret = GS_ALL_DONE;
20959 18239 : break;
20960 :
20961 3825 : case OMP_TASK:
20962 3825 : gimplify_omp_task (expr_p, pre_p);
20963 3825 : ret = GS_ALL_DONE;
20964 3825 : break;
20965 :
20966 10683 : case OMP_SIMD:
20967 10683 : {
20968 : /* Temporarily disable into_ssa, as scan_omp_simd
20969 : which calls copy_gimple_seq_and_replace_locals can't deal
20970 : with SSA_NAMEs defined outside of the body properly. */
20971 10683 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
20972 10683 : gimplify_ctxp->into_ssa = false;
20973 10683 : ret = gimplify_omp_for (expr_p, pre_p);
20974 10683 : gimplify_ctxp->into_ssa = saved_into_ssa;
20975 10683 : break;
20976 : }
20977 :
20978 47371 : case OMP_FOR:
20979 47371 : case OMP_DISTRIBUTE:
20980 47371 : case OMP_TASKLOOP:
20981 47371 : case OMP_TILE:
20982 47371 : case OMP_UNROLL:
20983 47371 : case OACC_LOOP:
20984 47371 : ret = gimplify_omp_for (expr_p, pre_p);
20985 47371 : break;
20986 :
20987 1056 : case OMP_LOOP:
20988 1056 : ret = gimplify_omp_loop (expr_p, pre_p);
20989 1056 : break;
20990 :
20991 665 : case OACC_CACHE:
20992 665 : gimplify_oacc_cache (expr_p, pre_p);
20993 665 : ret = GS_ALL_DONE;
20994 665 : break;
20995 :
20996 254 : case OACC_DECLARE:
20997 254 : gimplify_oacc_declare (expr_p, pre_p);
20998 254 : ret = GS_ALL_DONE;
20999 254 : break;
21000 :
21001 39860 : case OACC_HOST_DATA:
21002 39860 : case OACC_DATA:
21003 39860 : case OACC_KERNELS:
21004 39860 : case OACC_PARALLEL:
21005 39860 : case OACC_SERIAL:
21006 39860 : case OMP_SCOPE:
21007 39860 : case OMP_SECTIONS:
21008 39860 : case OMP_SINGLE:
21009 39860 : case OMP_TARGET:
21010 39860 : case OMP_TARGET_DATA:
21011 39860 : case OMP_TEAMS:
21012 39860 : gimplify_omp_workshare (expr_p, pre_p);
21013 39860 : ret = GS_ALL_DONE;
21014 39860 : break;
21015 :
21016 12299 : case OACC_ENTER_DATA:
21017 12299 : case OACC_EXIT_DATA:
21018 12299 : case OACC_UPDATE:
21019 12299 : case OMP_TARGET_UPDATE:
21020 12299 : case OMP_TARGET_ENTER_DATA:
21021 12299 : case OMP_TARGET_EXIT_DATA:
21022 12299 : gimplify_omp_target_update (expr_p, pre_p);
21023 12299 : ret = GS_ALL_DONE;
21024 12299 : break;
21025 :
21026 7063 : case OMP_SECTION:
21027 7063 : case OMP_STRUCTURED_BLOCK:
21028 7063 : case OMP_MASTER:
21029 7063 : case OMP_MASKED:
21030 7063 : case OMP_ORDERED:
21031 7063 : case OMP_CRITICAL:
21032 7063 : case OMP_SCAN:
21033 7063 : {
21034 7063 : gimple_seq body = NULL;
21035 7063 : gimple *g;
21036 7063 : bool saved_in_omp_construct = in_omp_construct;
21037 :
21038 7063 : in_omp_construct = true;
21039 7063 : gimplify_and_add (OMP_BODY (*expr_p), &body);
21040 7063 : in_omp_construct = saved_in_omp_construct;
21041 7063 : switch (TREE_CODE (*expr_p))
21042 : {
21043 1279 : case OMP_SECTION:
21044 1279 : g = gimple_build_omp_section (body);
21045 1279 : break;
21046 791 : case OMP_STRUCTURED_BLOCK:
21047 791 : g = gimple_build_omp_structured_block (body);
21048 791 : break;
21049 874 : case OMP_MASTER:
21050 874 : g = gimple_build_omp_master (body);
21051 874 : break;
21052 1950 : case OMP_ORDERED:
21053 1950 : g = gimplify_omp_ordered (*expr_p, body);
21054 1950 : if (OMP_BODY (*expr_p) == NULL_TREE
21055 1950 : && gimple_code (g) == GIMPLE_OMP_ORDERED)
21056 1025 : gimple_omp_ordered_standalone (g);
21057 : break;
21058 497 : case OMP_MASKED:
21059 497 : gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p),
21060 : pre_p, ORT_WORKSHARE, OMP_MASKED);
21061 497 : gimplify_adjust_omp_clauses (pre_p, body,
21062 : &OMP_MASKED_CLAUSES (*expr_p),
21063 : OMP_MASKED);
21064 994 : g = gimple_build_omp_masked (body,
21065 497 : OMP_MASKED_CLAUSES (*expr_p));
21066 497 : break;
21067 546 : case OMP_CRITICAL:
21068 546 : gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
21069 : pre_p, ORT_WORKSHARE, OMP_CRITICAL);
21070 546 : gimplify_adjust_omp_clauses (pre_p, body,
21071 : &OMP_CRITICAL_CLAUSES (*expr_p),
21072 : OMP_CRITICAL);
21073 1638 : g = gimple_build_omp_critical (body,
21074 546 : OMP_CRITICAL_NAME (*expr_p),
21075 546 : OMP_CRITICAL_CLAUSES (*expr_p));
21076 546 : break;
21077 1126 : case OMP_SCAN:
21078 1126 : gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
21079 : pre_p, ORT_WORKSHARE, OMP_SCAN);
21080 1126 : gimplify_adjust_omp_clauses (pre_p, body,
21081 : &OMP_SCAN_CLAUSES (*expr_p),
21082 : OMP_SCAN);
21083 1126 : g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
21084 1126 : break;
21085 0 : default:
21086 0 : gcc_unreachable ();
21087 : }
21088 7063 : gimplify_seq_add_stmt (pre_p, g);
21089 7063 : ret = GS_ALL_DONE;
21090 7063 : break;
21091 : }
21092 :
21093 611 : case OMP_TASKGROUP:
21094 611 : {
21095 611 : gimple_seq body = NULL;
21096 :
21097 611 : tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p);
21098 611 : bool saved_in_omp_construct = in_omp_construct;
21099 611 : gimplify_scan_omp_clauses (pclauses, pre_p, ORT_TASKGROUP,
21100 : OMP_TASKGROUP);
21101 611 : gimplify_adjust_omp_clauses (pre_p, NULL, pclauses, OMP_TASKGROUP);
21102 :
21103 611 : in_omp_construct = true;
21104 611 : gimplify_and_add (OMP_BODY (*expr_p), &body);
21105 611 : in_omp_construct = saved_in_omp_construct;
21106 611 : gimple_seq cleanup = NULL;
21107 611 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END);
21108 611 : gimple *g = gimple_build_call (fn, 0);
21109 611 : gimple_seq_add_stmt (&cleanup, g);
21110 611 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
21111 611 : body = NULL;
21112 611 : gimple_seq_add_stmt (&body, g);
21113 611 : g = gimple_build_omp_taskgroup (body, *pclauses);
21114 611 : gimplify_seq_add_stmt (pre_p, g);
21115 611 : ret = GS_ALL_DONE;
21116 611 : break;
21117 : }
21118 :
21119 612 : case OMP_INTEROP:
21120 612 : ret = gimplify_omp_interop (expr_p, pre_p);
21121 612 : break;
21122 10185 : case OMP_ATOMIC:
21123 10185 : case OMP_ATOMIC_READ:
21124 10185 : case OMP_ATOMIC_CAPTURE_OLD:
21125 10185 : case OMP_ATOMIC_CAPTURE_NEW:
21126 10185 : ret = gimplify_omp_atomic (expr_p, pre_p);
21127 10185 : break;
21128 :
21129 852 : case OMP_DISPATCH:
21130 852 : ret = gimplify_omp_dispatch (expr_p, pre_p);
21131 852 : break;
21132 :
21133 174 : case OMP_METADIRECTIVE:
21134 174 : ret = gimplify_omp_metadirective (expr_p, pre_p, post_p,
21135 : gimple_test_f, fallback);
21136 174 : break;
21137 :
21138 36 : case OMP_NEXT_VARIANT:
21139 36 : case OMP_TARGET_DEVICE_MATCHES:
21140 : /* These are placeholders for constants. There's nothing to do with
21141 : them here but we must mark the containing function as needing
21142 : to run the ompdevlow pass to resolve them. Note that
21143 : OMP_TARGET_DEVICE_MATCHES, in particular, may be inserted by
21144 : the front ends. */
21145 36 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
21146 36 : ret = GS_ALL_DONE;
21147 36 : break;
21148 :
21149 0 : case OMP_DECLARE_MAPPER:
21150 0 : ret = gimplify_omp_declare_mapper (expr_p);
21151 0 : break;
21152 :
21153 478 : case TRANSACTION_EXPR:
21154 478 : ret = gimplify_transaction (expr_p, pre_p);
21155 478 : break;
21156 :
21157 300492 : case TRUTH_AND_EXPR:
21158 300492 : case TRUTH_OR_EXPR:
21159 300492 : case TRUTH_XOR_EXPR:
21160 300492 : {
21161 300492 : tree orig_type = TREE_TYPE (*expr_p);
21162 300492 : tree new_type, xop0, xop1;
21163 300492 : *expr_p = gimple_boolify (*expr_p);
21164 300492 : new_type = TREE_TYPE (*expr_p);
21165 300492 : if (!useless_type_conversion_p (orig_type, new_type))
21166 : {
21167 1148 : *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
21168 1148 : ret = GS_OK;
21169 1148 : break;
21170 : }
21171 :
21172 : /* Boolified binary truth expressions are semantically equivalent
21173 : to bitwise binary expressions. Canonicalize them to the
21174 : bitwise variant. */
21175 299344 : switch (TREE_CODE (*expr_p))
21176 : {
21177 176377 : case TRUTH_AND_EXPR:
21178 176377 : TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
21179 176377 : break;
21180 122359 : case TRUTH_OR_EXPR:
21181 122359 : TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
21182 122359 : break;
21183 608 : case TRUTH_XOR_EXPR:
21184 608 : TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
21185 608 : break;
21186 : default:
21187 : break;
21188 : }
21189 : /* Now make sure that operands have compatible type to
21190 : expression's new_type. */
21191 299344 : xop0 = TREE_OPERAND (*expr_p, 0);
21192 299344 : xop1 = TREE_OPERAND (*expr_p, 1);
21193 299344 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
21194 326 : TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
21195 : new_type,
21196 : xop0);
21197 299344 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
21198 366 : TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
21199 : new_type,
21200 : xop1);
21201 : /* Continue classified as tcc_binary. */
21202 299344 : goto expr_2;
21203 : }
21204 :
21205 11364 : case VEC_COND_EXPR:
21206 11364 : goto expr_3;
21207 :
21208 134286 : case VEC_PERM_EXPR:
21209 : /* Classified as tcc_expression. */
21210 134286 : goto expr_3;
21211 :
21212 48 : case BIT_INSERT_EXPR:
21213 : /* Argument 3 is a constant. */
21214 48 : goto expr_2;
21215 :
21216 3852400 : case POINTER_PLUS_EXPR:
21217 3852400 : {
21218 3852400 : enum gimplify_status r0, r1;
21219 3852400 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21220 : post_p, is_gimple_val, fb_rvalue);
21221 3852400 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21222 : post_p, is_gimple_val, fb_rvalue);
21223 3852400 : recalculate_side_effects (*expr_p);
21224 3852400 : ret = MIN (r0, r1);
21225 : break;
21226 : }
21227 :
21228 45019277 : default:
21229 45019277 : switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
21230 : {
21231 7086977 : case tcc_comparison:
21232 : /* Handle comparison of objects of non scalar mode aggregates
21233 : with a call to memcmp. It would be nice to only have to do
21234 : this for variable-sized objects, but then we'd have to allow
21235 : the same nest of reference nodes we allow for MODIFY_EXPR and
21236 : that's too complex.
21237 :
21238 : Compare scalar mode aggregates as scalar mode values. Using
21239 : memcmp for them would be very inefficient at best, and is
21240 : plain wrong if bitfields are involved. */
21241 7086977 : if (error_operand_p (TREE_OPERAND (*expr_p, 1)))
21242 : ret = GS_ERROR;
21243 : else
21244 : {
21245 7086977 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
21246 :
21247 : /* Vector comparisons need no boolification. */
21248 7086977 : if (TREE_CODE (type) == VECTOR_TYPE)
21249 13371 : goto expr_2;
21250 7073606 : else if (!AGGREGATE_TYPE_P (type))
21251 : {
21252 7073590 : tree org_type = TREE_TYPE (*expr_p);
21253 7073590 : *expr_p = gimple_boolify (*expr_p);
21254 7073590 : if (!useless_type_conversion_p (org_type,
21255 7073590 : TREE_TYPE (*expr_p)))
21256 : {
21257 56781 : *expr_p = fold_convert_loc (input_location,
21258 : org_type, *expr_p);
21259 56781 : ret = GS_OK;
21260 : }
21261 : else
21262 7016809 : goto expr_2;
21263 : }
21264 16 : else if (SCALAR_INT_MODE_P (TYPE_MODE (type)))
21265 16 : ret = gimplify_scalar_mode_aggregate_compare (expr_p);
21266 : else
21267 0 : ret = gimplify_variable_sized_compare (expr_p);
21268 : }
21269 : break;
21270 :
21271 : /* If *EXPR_P does not need to be special-cased, handle it
21272 : according to its class. */
21273 1613178 : case tcc_unary:
21274 1613178 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21275 : post_p, is_gimple_val, fb_rvalue);
21276 1613178 : break;
21277 :
21278 26683964 : case tcc_binary:
21279 26683964 : expr_2:
21280 26683964 : {
21281 26683964 : enum gimplify_status r0, r1;
21282 :
21283 26683964 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21284 : post_p, is_gimple_val, fb_rvalue);
21285 26683964 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21286 : post_p, is_gimple_val, fb_rvalue);
21287 :
21288 26683964 : ret = MIN (r0, r1);
21289 : break;
21290 : }
21291 :
21292 145650 : expr_3:
21293 145650 : {
21294 145650 : enum gimplify_status r0, r1, r2;
21295 :
21296 145650 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21297 : post_p, is_gimple_val, fb_rvalue);
21298 145650 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21299 : post_p, is_gimple_val, fb_rvalue);
21300 145650 : r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
21301 : post_p, is_gimple_val, fb_rvalue);
21302 :
21303 145650 : ret = MIN (MIN (r0, r1), r2);
21304 : break;
21305 : }
21306 :
21307 16964730 : case tcc_declaration:
21308 16964730 : case tcc_constant:
21309 16964730 : ret = GS_ALL_DONE;
21310 16964730 : goto dont_recalculate;
21311 :
21312 0 : default:
21313 0 : gcc_unreachable ();
21314 : }
21315 :
21316 28499589 : recalculate_side_effects (*expr_p);
21317 :
21318 486668756 : dont_recalculate:
21319 : break;
21320 : }
21321 :
21322 486668756 : gcc_assert (*expr_p || ret != GS_OK);
21323 : }
21324 491577917 : while (ret == GS_OK);
21325 :
21326 : /* If we encountered an error_mark somewhere nested inside, either
21327 : stub out the statement or propagate the error back out. */
21328 473532839 : if (ret == GS_ERROR)
21329 : {
21330 5309 : if (is_statement)
21331 4074 : *expr_p = NULL;
21332 5309 : goto out;
21333 : }
21334 :
21335 : /* This was only valid as a return value from the langhook, which
21336 : we handled. Make sure it doesn't escape from any other context. */
21337 473527530 : gcc_assert (ret != GS_UNHANDLED);
21338 :
21339 473527530 : if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
21340 : {
21341 : /* We aren't looking for a value, and we don't have a valid
21342 : statement. If it doesn't have side-effects, throw it away.
21343 : We can also get here with code such as "*&&L;", where L is
21344 : a LABEL_DECL that is marked as FORCED_LABEL. */
21345 1229259 : if (TREE_CODE (*expr_p) == LABEL_DECL
21346 1229259 : || !TREE_SIDE_EFFECTS (*expr_p))
21347 1228243 : *expr_p = NULL;
21348 1016 : else if (!TREE_THIS_VOLATILE (*expr_p))
21349 : {
21350 : /* This is probably a _REF that contains something nested that
21351 : has side effects. Recurse through the operands to find it. */
21352 0 : enum tree_code code = TREE_CODE (*expr_p);
21353 :
21354 0 : switch (code)
21355 : {
21356 0 : case COMPONENT_REF:
21357 0 : case REALPART_EXPR:
21358 0 : case IMAGPART_EXPR:
21359 0 : case VIEW_CONVERT_EXPR:
21360 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21361 : gimple_test_f, fallback);
21362 0 : break;
21363 :
21364 0 : case ARRAY_REF:
21365 0 : case ARRAY_RANGE_REF:
21366 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21367 : gimple_test_f, fallback);
21368 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
21369 : gimple_test_f, fallback);
21370 0 : break;
21371 :
21372 0 : default:
21373 : /* Anything else with side-effects must be converted to
21374 : a valid statement before we get here. */
21375 0 : gcc_unreachable ();
21376 : }
21377 :
21378 0 : *expr_p = NULL;
21379 : }
21380 1016 : else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
21381 966 : && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode
21382 1969 : && !is_empty_type (TREE_TYPE (*expr_p)))
21383 : {
21384 : /* Historically, the compiler has treated a bare reference
21385 : to a non-BLKmode volatile lvalue as forcing a load. */
21386 893 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
21387 :
21388 : /* Normally, we do not want to create a temporary for a
21389 : TREE_ADDRESSABLE type because such a type should not be
21390 : copied by bitwise-assignment. However, we make an
21391 : exception here, as all we are doing here is ensuring that
21392 : we read the bytes that make up the type. We use
21393 : create_tmp_var_raw because create_tmp_var will abort when
21394 : given a TREE_ADDRESSABLE type. */
21395 893 : tree tmp = create_tmp_var_raw (type, "vol");
21396 893 : gimple_add_tmp_var (tmp);
21397 893 : gimplify_assign (tmp, *expr_p, pre_p);
21398 893 : *expr_p = NULL;
21399 : }
21400 : else
21401 : /* We can't do anything useful with a volatile reference to
21402 : an incomplete type, so just throw it away. Likewise for
21403 : a BLKmode type, since any implicit inner load should
21404 : already have been turned into an explicit one by the
21405 : gimplification process. */
21406 123 : *expr_p = NULL;
21407 : }
21408 :
21409 : /* If we are gimplifying at the statement level, we're done. Tack
21410 : everything together and return. */
21411 473527530 : if (fallback == fb_none || is_statement)
21412 : {
21413 : /* Since *EXPR_P has been converted into a GIMPLE tuple, clear
21414 : it out for GC to reclaim it. */
21415 102703733 : *expr_p = NULL_TREE;
21416 :
21417 102703733 : if (!gimple_seq_empty_p (internal_pre)
21418 102703733 : || !gimple_seq_empty_p (internal_post))
21419 : {
21420 19 : gimplify_seq_add_seq (&internal_pre, internal_post);
21421 19 : gimplify_seq_add_seq (pre_p, internal_pre);
21422 : }
21423 :
21424 : /* The result of gimplifying *EXPR_P is going to be the last few
21425 : statements in *PRE_P and *POST_P. Add location information
21426 : to all the statements that were added by the gimplification
21427 : helpers. */
21428 102703733 : if (!gimple_seq_empty_p (*pre_p))
21429 100155377 : annotate_all_with_location_after (*pre_p, pre_last_gsi, input_location);
21430 :
21431 102703733 : if (!gimple_seq_empty_p (*post_p))
21432 19 : annotate_all_with_location_after (*post_p, post_last_gsi,
21433 : input_location);
21434 :
21435 102703733 : goto out;
21436 : }
21437 :
21438 : #ifdef ENABLE_GIMPLE_CHECKING
21439 370823797 : if (*expr_p)
21440 : {
21441 370823797 : enum tree_code code = TREE_CODE (*expr_p);
21442 : /* These expressions should already be in gimple IR form. */
21443 370823797 : gcc_assert (code != MODIFY_EXPR
21444 : && code != ASM_EXPR
21445 : && code != BIND_EXPR
21446 : && code != CATCH_EXPR
21447 : && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
21448 : && code != EH_FILTER_EXPR
21449 : && code != GOTO_EXPR
21450 : && code != LABEL_EXPR
21451 : && code != LOOP_EXPR
21452 : && code != SWITCH_EXPR
21453 : && code != TRY_FINALLY_EXPR
21454 : && code != EH_ELSE_EXPR
21455 : && code != OACC_PARALLEL
21456 : && code != OACC_KERNELS
21457 : && code != OACC_SERIAL
21458 : && code != OACC_DATA
21459 : && code != OACC_HOST_DATA
21460 : && code != OACC_DECLARE
21461 : && code != OACC_UPDATE
21462 : && code != OACC_ENTER_DATA
21463 : && code != OACC_EXIT_DATA
21464 : && code != OACC_CACHE
21465 : && code != OMP_CRITICAL
21466 : && code != OMP_FOR
21467 : && code != OACC_LOOP
21468 : && code != OMP_MASTER
21469 : && code != OMP_MASKED
21470 : && code != OMP_TASKGROUP
21471 : && code != OMP_ORDERED
21472 : && code != OMP_PARALLEL
21473 : && code != OMP_SCAN
21474 : && code != OMP_SECTIONS
21475 : && code != OMP_SECTION
21476 : && code != OMP_STRUCTURED_BLOCK
21477 : && code != OMP_SINGLE
21478 : && code != OMP_SCOPE
21479 : && code != OMP_DISPATCH);
21480 : }
21481 : #endif
21482 :
21483 : /* Otherwise we're gimplifying a subexpression, so the resulting
21484 : value is interesting. If it's a valid operand that matches
21485 : GIMPLE_TEST_F, we're done. Unless we are handling some
21486 : post-effects internally; if that's the case, we need to copy into
21487 : a temporary before adding the post-effects to POST_P. */
21488 370823797 : if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
21489 344438711 : goto out;
21490 :
21491 : /* Otherwise, we need to create a new temporary for the gimplified
21492 : expression. */
21493 :
21494 : /* We can't return an lvalue if we have an internal postqueue. The
21495 : object the lvalue refers to would (probably) be modified by the
21496 : postqueue; we need to copy the value out first, which means an
21497 : rvalue. */
21498 26385086 : if ((fallback & fb_lvalue)
21499 595357 : && gimple_seq_empty_p (internal_post)
21500 26980443 : && is_gimple_addressable (*expr_p))
21501 : {
21502 : /* An lvalue will do. Take the address of the expression, store it
21503 : in a temporary, and replace the expression with an INDIRECT_REF of
21504 : that temporary. */
21505 15 : tree ref_alias_type = reference_alias_ptr_type (*expr_p);
21506 15 : unsigned int ref_align = get_object_alignment (*expr_p);
21507 15 : tree ref_type = TREE_TYPE (*expr_p);
21508 15 : tmp = build_fold_addr_expr_loc (input_location, *expr_p);
21509 15 : gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
21510 15 : if (TYPE_ALIGN (ref_type) != ref_align)
21511 1 : ref_type = build_aligned_type (ref_type, ref_align);
21512 15 : *expr_p = build2 (MEM_REF, ref_type,
21513 : tmp, build_zero_cst (ref_alias_type));
21514 : }
21515 26385071 : else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
21516 : {
21517 : /* An rvalue will do. Assign the gimplified expression into a
21518 : new temporary TMP and replace the original expression with
21519 : TMP. First, make sure that the expression has a type so that
21520 : it can be assigned into a temporary. */
21521 26385063 : gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
21522 26385063 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
21523 : }
21524 : else
21525 : {
21526 : #ifdef ENABLE_GIMPLE_CHECKING
21527 8 : if (!(fallback & fb_mayfail))
21528 : {
21529 0 : fprintf (stderr, "gimplification failed:\n");
21530 0 : print_generic_expr (stderr, *expr_p);
21531 0 : debug_tree (*expr_p);
21532 0 : internal_error ("gimplification failed");
21533 : }
21534 : #endif
21535 8 : gcc_assert (fallback & fb_mayfail);
21536 :
21537 : /* If this is an asm statement, and the user asked for the
21538 : impossible, don't die. Fail and let gimplify_asm_expr
21539 : issue an error. */
21540 8 : ret = GS_ERROR;
21541 8 : goto out;
21542 : }
21543 :
21544 : /* Make sure the temporary matches our predicate. */
21545 26385078 : gcc_assert ((*gimple_test_f) (*expr_p));
21546 :
21547 26385078 : if (!gimple_seq_empty_p (internal_post))
21548 : {
21549 0 : annotate_all_with_location (internal_post, input_location);
21550 0 : gimplify_seq_add_seq (pre_p, internal_post);
21551 : }
21552 :
21553 26385078 : out:
21554 473532839 : input_location = saved_location;
21555 473532839 : return ret;
21556 : }
21557 :
21558 : /* Like gimplify_expr but make sure the gimplified result is not itself
21559 : a SSA name (but a decl if it were). Temporaries required by
21560 : evaluating *EXPR_P may be still SSA names. */
21561 :
21562 : static enum gimplify_status
21563 34762867 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
21564 : bool (*gimple_test_f) (tree), fallback_t fallback,
21565 : bool allow_ssa)
21566 : {
21567 34762867 : enum gimplify_status ret = gimplify_expr (expr_p, pre_p, post_p,
21568 : gimple_test_f, fallback);
21569 34762867 : if (! allow_ssa
21570 266258 : && TREE_CODE (*expr_p) == SSA_NAME)
21571 68827 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false);
21572 34762867 : return ret;
21573 : }
21574 :
21575 : /* Look through TYPE for variable-sized objects and gimplify each such
21576 : size that we find. Add to LIST_P any statements generated. */
21577 :
21578 : void
21579 8409309 : gimplify_type_sizes (tree type, gimple_seq *list_p)
21580 : {
21581 8409309 : if (type == NULL || type == error_mark_node)
21582 : return;
21583 :
21584 8409063 : const bool ignored_p
21585 8409063 : = TYPE_NAME (type)
21586 4175233 : && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
21587 12347113 : && DECL_IGNORED_P (TYPE_NAME (type));
21588 8409063 : tree t;
21589 :
21590 : /* We first do the main variant, then copy into any other variants. */
21591 8409063 : type = TYPE_MAIN_VARIANT (type);
21592 :
21593 : /* Avoid infinite recursion. */
21594 8409063 : if (TYPE_SIZES_GIMPLIFIED (type))
21595 : return;
21596 :
21597 2507305 : TYPE_SIZES_GIMPLIFIED (type) = 1;
21598 :
21599 2507305 : switch (TREE_CODE (type))
21600 : {
21601 496725 : case INTEGER_TYPE:
21602 496725 : case ENUMERAL_TYPE:
21603 496725 : case BOOLEAN_TYPE:
21604 496725 : case REAL_TYPE:
21605 496725 : case FIXED_POINT_TYPE:
21606 496725 : gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
21607 496725 : gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
21608 :
21609 10182533 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21610 : {
21611 9685808 : TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
21612 9685808 : TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
21613 : }
21614 : break;
21615 :
21616 181874 : case ARRAY_TYPE:
21617 : /* These types may not have declarations, so handle them here. */
21618 181874 : gimplify_type_sizes (TREE_TYPE (type), list_p);
21619 181874 : gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
21620 : /* Ensure VLA bounds aren't removed, for -O0 they should be variables
21621 : with assigned stack slots, for -O1+ -g they should be tracked
21622 : by VTA. */
21623 181874 : if (!ignored_p
21624 181874 : && TYPE_DOMAIN (type)
21625 363523 : && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
21626 : {
21627 181649 : t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
21628 181649 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21629 0 : DECL_IGNORED_P (t) = 0;
21630 181649 : t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
21631 181649 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21632 19083 : DECL_IGNORED_P (t) = 0;
21633 : }
21634 : break;
21635 :
21636 507948 : case RECORD_TYPE:
21637 507948 : case UNION_TYPE:
21638 507948 : case QUAL_UNION_TYPE:
21639 11276327 : for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
21640 10768379 : if (TREE_CODE (field) == FIELD_DECL)
21641 : {
21642 1106192 : gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
21643 : /* Likewise, ensure variable offsets aren't removed. */
21644 1106192 : if (!ignored_p
21645 1106192 : && (t = DECL_FIELD_OFFSET (field))
21646 1106180 : && VAR_P (t)
21647 1106354 : && DECL_ARTIFICIAL (t))
21648 162 : DECL_IGNORED_P (t) = 0;
21649 1106192 : gimplify_one_sizepos (&DECL_SIZE (field), list_p);
21650 1106192 : gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
21651 1106192 : gimplify_type_sizes (TREE_TYPE (field), list_p);
21652 : }
21653 : break;
21654 :
21655 : case POINTER_TYPE:
21656 : case REFERENCE_TYPE:
21657 : /* We used to recurse on the pointed-to type here, which turned out to
21658 : be incorrect because its definition might refer to variables not
21659 : yet initialized at this point if a forward declaration is involved.
21660 :
21661 : It was actually useful for anonymous pointed-to types to ensure
21662 : that the sizes evaluation dominates every possible later use of the
21663 : values. Restricting to such types here would be safe since there
21664 : is no possible forward declaration around, but would introduce an
21665 : undesirable middle-end semantic to anonymity. We then defer to
21666 : front-ends the responsibility of ensuring that the sizes are
21667 : evaluated both early and late enough, e.g. by attaching artificial
21668 : type declarations to the tree. */
21669 : break;
21670 :
21671 : default:
21672 : break;
21673 : }
21674 :
21675 2507305 : gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
21676 2507305 : gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
21677 :
21678 16816857 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21679 : {
21680 14309552 : TYPE_SIZE (t) = TYPE_SIZE (type);
21681 14309552 : TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
21682 14309552 : TYPE_SIZES_GIMPLIFIED (t) = 1;
21683 : }
21684 : }
21685 :
21686 : /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
21687 : a size or position, has had all of its SAVE_EXPRs evaluated.
21688 : We add any required statements to *STMT_P. */
21689 :
21690 : void
21691 9344750 : gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
21692 : {
21693 9344750 : tree expr = *expr_p;
21694 :
21695 : /* We don't do anything if the value isn't there, is constant, or contains
21696 : A PLACEHOLDER_EXPR. We also don't want to do anything if it's already
21697 : a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
21698 : will want to replace it with a new variable, but that will cause problems
21699 : if this type is from outside the function. It's OK to have that here. */
21700 9344750 : if (expr == NULL_TREE
21701 9348647 : || is_gimple_constant (expr)
21702 81147 : || VAR_P (expr)
21703 9422000 : || CONTAINS_PLACEHOLDER_P (expr))
21704 9267500 : return;
21705 :
21706 77250 : *expr_p = unshare_expr (expr);
21707 :
21708 : /* SSA names in decl/type fields are a bad idea - they'll get reclaimed
21709 : if the def vanishes. */
21710 77250 : gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false);
21711 :
21712 : /* If expr wasn't already is_gimple_sizepos or is_gimple_constant from the
21713 : FE, ensure that it is a VAR_DECL, otherwise we might handle some decls
21714 : as gimplify_vla_decl even when they would have all sizes INTEGER_CSTs. */
21715 77250 : if (is_gimple_constant (*expr_p))
21716 548 : *expr_p = get_initialized_tmp_var (*expr_p, stmt_p, NULL, false);
21717 : }
21718 :
21719 : /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
21720 : containing the sequence of corresponding GIMPLE statements. If DO_PARMS
21721 : is true, also gimplify the parameters. */
21722 :
21723 : gbind *
21724 3009181 : gimplify_body (tree fndecl, bool do_parms)
21725 : {
21726 3009181 : location_t saved_location = input_location;
21727 3009181 : gimple_seq parm_stmts, parm_cleanup = NULL, seq;
21728 3009181 : gimple *outer_stmt;
21729 3009181 : gbind *outer_bind;
21730 :
21731 3009181 : timevar_push (TV_TREE_GIMPLIFY);
21732 :
21733 3009181 : init_tree_ssa (cfun);
21734 :
21735 : /* Initialize for optimize_insn_for_s{ize,peed}_p possibly called during
21736 : gimplification. */
21737 3009181 : default_rtl_profile ();
21738 :
21739 3009181 : gcc_assert (gimplify_ctxp == NULL);
21740 3009181 : push_gimplify_context (true);
21741 :
21742 3009181 : if (flag_openacc || flag_openmp)
21743 : {
21744 54783 : gcc_assert (gimplify_omp_ctxp == NULL);
21745 54783 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)))
21746 9733 : gimplify_omp_ctxp = new_omp_context (ORT_IMPLICIT_TARGET);
21747 : }
21748 :
21749 : /* Unshare most shared trees in the body and in that of any nested functions.
21750 : It would seem we don't have to do this for nested functions because
21751 : they are supposed to be output and then the outer function gimplified
21752 : first, but the g++ front end doesn't always do it that way. */
21753 3009181 : unshare_body (fndecl);
21754 3009181 : unvisit_body (fndecl);
21755 :
21756 : /* Make sure input_location isn't set to something weird. */
21757 3009181 : input_location = DECL_SOURCE_LOCATION (fndecl);
21758 :
21759 : /* Resolve callee-copies. This has to be done before processing
21760 : the body so that DECL_VALUE_EXPR gets processed correctly. */
21761 3009181 : parm_stmts = do_parms ? gimplify_parameters (&parm_cleanup) : NULL;
21762 :
21763 : /* Gimplify the function's body. */
21764 3009181 : seq = NULL;
21765 3009181 : gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
21766 3009181 : outer_stmt = gimple_seq_first_nondebug_stmt (seq);
21767 3009181 : if (!outer_stmt)
21768 : {
21769 26702 : outer_stmt = gimple_build_nop ();
21770 26702 : gimplify_seq_add_stmt (&seq, outer_stmt);
21771 : }
21772 :
21773 : /* The body must contain exactly one statement, a GIMPLE_BIND. If this is
21774 : not the case, wrap everything in a GIMPLE_BIND to make it so. */
21775 3009181 : if (gimple_code (outer_stmt) == GIMPLE_BIND
21776 3009181 : && (gimple_seq_first_nondebug_stmt (seq)
21777 1725857 : == gimple_seq_last_nondebug_stmt (seq)))
21778 : {
21779 1661815 : outer_bind = as_a <gbind *> (outer_stmt);
21780 1661815 : if (gimple_seq_first_stmt (seq) != outer_stmt
21781 1661815 : || gimple_seq_last_stmt (seq) != outer_stmt)
21782 : {
21783 : /* If there are debug stmts before or after outer_stmt, move them
21784 : inside of outer_bind body. */
21785 1 : gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq);
21786 1 : gimple_seq second_seq = NULL;
21787 1 : if (gimple_seq_first_stmt (seq) != outer_stmt
21788 2 : && gimple_seq_last_stmt (seq) != outer_stmt)
21789 : {
21790 0 : second_seq = gsi_split_seq_after (gsi);
21791 0 : gsi_remove (&gsi, false);
21792 : }
21793 1 : else if (gimple_seq_first_stmt (seq) != outer_stmt)
21794 1 : gsi_remove (&gsi, false);
21795 : else
21796 : {
21797 0 : gsi_remove (&gsi, false);
21798 0 : second_seq = seq;
21799 0 : seq = NULL;
21800 : }
21801 1 : gimple_seq_add_seq_without_update (&seq,
21802 : gimple_bind_body (outer_bind));
21803 1 : gimple_seq_add_seq_without_update (&seq, second_seq);
21804 1 : gimple_bind_set_body (outer_bind, seq);
21805 : }
21806 : }
21807 : else
21808 1347366 : outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
21809 :
21810 3009181 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
21811 :
21812 : /* If we had callee-copies statements, insert them at the beginning
21813 : of the function and clear DECL_HAS_VALUE_EXPR_P on the parameters. */
21814 3009181 : if (!gimple_seq_empty_p (parm_stmts))
21815 : {
21816 41 : tree parm;
21817 :
21818 41 : gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
21819 41 : if (parm_cleanup)
21820 : {
21821 0 : gtry *g = gimple_build_try (parm_stmts, parm_cleanup,
21822 : GIMPLE_TRY_FINALLY);
21823 0 : parm_stmts = NULL;
21824 0 : gimple_seq_add_stmt (&parm_stmts, g);
21825 : }
21826 41 : gimple_bind_set_body (outer_bind, parm_stmts);
21827 :
21828 41 : for (parm = DECL_ARGUMENTS (current_function_decl);
21829 101 : parm; parm = DECL_CHAIN (parm))
21830 60 : if (DECL_HAS_VALUE_EXPR_P (parm))
21831 : {
21832 0 : DECL_HAS_VALUE_EXPR_P (parm) = 0;
21833 0 : DECL_IGNORED_P (parm) = 0;
21834 : }
21835 : }
21836 :
21837 3009181 : if ((flag_openacc || flag_openmp || flag_openmp_simd)
21838 57039 : && gimplify_omp_ctxp)
21839 : {
21840 9786 : delete_omp_context (gimplify_omp_ctxp);
21841 9786 : gimplify_omp_ctxp = NULL;
21842 : }
21843 :
21844 3009181 : pop_gimplify_context (outer_bind);
21845 3009181 : gcc_assert (gimplify_ctxp == NULL);
21846 :
21847 3009181 : if (flag_checking && !seen_error ())
21848 2958726 : verify_gimple_in_seq (gimple_bind_body (outer_bind));
21849 :
21850 3009181 : timevar_pop (TV_TREE_GIMPLIFY);
21851 3009181 : input_location = saved_location;
21852 :
21853 3009181 : return outer_bind;
21854 : }
21855 :
21856 : typedef char *char_p; /* For DEF_VEC_P. */
21857 :
21858 : /* Return whether we should exclude FNDECL from instrumentation. */
21859 :
21860 : static bool
21861 43 : flag_instrument_functions_exclude_p (tree fndecl)
21862 : {
21863 43 : vec<char_p> *v;
21864 :
21865 43 : v = (vec<char_p> *) flag_instrument_functions_exclude_functions;
21866 44 : if (v && v->length () > 0)
21867 : {
21868 1 : const char *name;
21869 1 : int i;
21870 1 : char *s;
21871 :
21872 1 : name = lang_hooks.decl_printable_name (fndecl, 1);
21873 2 : FOR_EACH_VEC_ELT (*v, i, s)
21874 1 : if (strstr (name, s) != NULL)
21875 2 : return true;
21876 : }
21877 :
21878 42 : v = (vec<char_p> *) flag_instrument_functions_exclude_files;
21879 43 : if (v && v->length () > 0)
21880 : {
21881 1 : const char *name;
21882 1 : int i;
21883 1 : char *s;
21884 :
21885 1 : name = DECL_SOURCE_FILE (fndecl);
21886 1 : FOR_EACH_VEC_ELT (*v, i, s)
21887 1 : if (strstr (name, s) != NULL)
21888 2 : return true;
21889 : }
21890 :
21891 : return false;
21892 : }
21893 :
21894 : /* Build a call to the instrumentation function FNCODE and add it to SEQ.
21895 : If COND_VAR is not NULL, it is a boolean variable guarding the call to
21896 : the instrumentation function. IF STMT is not NULL, it is a statement
21897 : to be executed just before the call to the instrumentation function. */
21898 :
21899 : static void
21900 82 : build_instrumentation_call (gimple_seq *seq, enum built_in_function fncode,
21901 : tree cond_var, gimple *stmt)
21902 : {
21903 : /* The instrumentation hooks aren't going to call the instrumented
21904 : function and the address they receive is expected to be matchable
21905 : against symbol addresses. Make sure we don't create a trampoline,
21906 : in case the current function is nested. */
21907 82 : tree this_fn_addr = build_fold_addr_expr (current_function_decl);
21908 82 : TREE_NO_TRAMPOLINE (this_fn_addr) = 1;
21909 :
21910 82 : tree label_true, label_false;
21911 82 : if (cond_var)
21912 : {
21913 20 : label_true = create_artificial_label (UNKNOWN_LOCATION);
21914 20 : label_false = create_artificial_label (UNKNOWN_LOCATION);
21915 20 : gcond *cond = gimple_build_cond (EQ_EXPR, cond_var, boolean_false_node,
21916 : label_true, label_false);
21917 20 : gimplify_seq_add_stmt (seq, cond);
21918 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_true));
21919 20 : gimplify_seq_add_stmt (seq, gimple_build_predict (PRED_COLD_LABEL,
21920 : NOT_TAKEN));
21921 : }
21922 :
21923 82 : if (stmt)
21924 10 : gimplify_seq_add_stmt (seq, stmt);
21925 :
21926 82 : tree x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
21927 82 : gcall *call = gimple_build_call (x, 1, integer_zero_node);
21928 82 : tree tmp_var = create_tmp_var (ptr_type_node, "return_addr");
21929 82 : gimple_call_set_lhs (call, tmp_var);
21930 82 : gimplify_seq_add_stmt (seq, call);
21931 82 : x = builtin_decl_implicit (fncode);
21932 82 : call = gimple_build_call (x, 2, this_fn_addr, tmp_var);
21933 82 : gimplify_seq_add_stmt (seq, call);
21934 :
21935 82 : if (cond_var)
21936 20 : gimplify_seq_add_stmt (seq, gimple_build_label (label_false));
21937 82 : }
21938 :
21939 : /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
21940 : node for the function we want to gimplify.
21941 :
21942 : Return the sequence of GIMPLE statements corresponding to the body
21943 : of FNDECL. */
21944 :
21945 : void
21946 3008701 : gimplify_function_tree (tree fndecl)
21947 : {
21948 3008701 : gimple_seq seq;
21949 3008701 : gbind *bind;
21950 :
21951 3008701 : gcc_assert (!gimple_body (fndecl));
21952 :
21953 3008701 : if (DECL_STRUCT_FUNCTION (fndecl))
21954 3004304 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
21955 : else
21956 4397 : push_struct_function (fndecl);
21957 :
21958 3008701 : reset_cond_uid ();
21959 3008701 : if (cond_uids)
21960 : {
21961 65 : delete cond_uids;
21962 65 : cond_uids = NULL;
21963 : }
21964 :
21965 : /* Tentatively set PROP_gimple_lva here, and reset it in gimplify_va_arg_expr
21966 : if necessary. */
21967 3008701 : cfun->curr_properties |= PROP_gimple_lva;
21968 :
21969 3008701 : if (asan_sanitize_use_after_scope ())
21970 8572 : asan_poisoned_variables = new hash_set<tree> ();
21971 3008701 : if (flag_openmp)
21972 47190 : omp_resolved_variant_calls = new hash_set<tree> ();
21973 :
21974 3008701 : bind = gimplify_body (fndecl, true);
21975 :
21976 3008701 : if (omp_resolved_variant_calls)
21977 : {
21978 47190 : delete omp_resolved_variant_calls;
21979 47190 : omp_resolved_variant_calls = NULL;
21980 : }
21981 3008701 : if (asan_poisoned_variables)
21982 : {
21983 8572 : delete asan_poisoned_variables;
21984 8572 : asan_poisoned_variables = NULL;
21985 : }
21986 :
21987 : /* The tree body of the function is no longer needed, replace it
21988 : with the new GIMPLE body. */
21989 3008701 : seq = NULL;
21990 3008701 : gimple_seq_add_stmt (&seq, bind);
21991 3008701 : gimple_set_body (fndecl, seq);
21992 :
21993 : /* If we're instrumenting function entry/exit, then prepend the call to
21994 : the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
21995 : catch the exit hook. */
21996 : /* ??? Add some way to ignore exceptions for this TFE. */
21997 3008701 : if (flag_instrument_function_entry_exit
21998 97 : && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
21999 : /* Do not instrument extern inline functions. */
22000 44 : && !(DECL_DECLARED_INLINE_P (fndecl)
22001 6 : && DECL_EXTERNAL (fndecl)
22002 1 : && DECL_DISREGARD_INLINE_LIMITS (fndecl))
22003 3008744 : && !flag_instrument_functions_exclude_p (fndecl))
22004 : {
22005 41 : gimple_seq body = NULL, cleanup = NULL;
22006 41 : gassign *assign;
22007 41 : tree cond_var;
22008 :
22009 : /* If -finstrument-functions-once is specified, generate:
22010 :
22011 : static volatile bool C.0 = false;
22012 : bool tmp_called;
22013 :
22014 : tmp_called = C.0;
22015 : if (!tmp_called)
22016 : {
22017 : C.0 = true;
22018 : [call profiling enter function]
22019 : }
22020 :
22021 : without specific protection for data races. */
22022 41 : if (flag_instrument_function_entry_exit > 1)
22023 : {
22024 10 : tree first_var
22025 10 : = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
22026 : VAR_DECL,
22027 : create_tmp_var_name ("C"),
22028 : boolean_type_node);
22029 10 : DECL_ARTIFICIAL (first_var) = 1;
22030 10 : DECL_IGNORED_P (first_var) = 1;
22031 10 : TREE_STATIC (first_var) = 1;
22032 10 : TREE_THIS_VOLATILE (first_var) = 1;
22033 10 : TREE_USED (first_var) = 1;
22034 10 : DECL_INITIAL (first_var) = boolean_false_node;
22035 10 : varpool_node::add (first_var);
22036 :
22037 10 : cond_var = create_tmp_var (boolean_type_node, "tmp_called");
22038 10 : assign = gimple_build_assign (cond_var, first_var);
22039 10 : gimplify_seq_add_stmt (&body, assign);
22040 :
22041 10 : assign = gimple_build_assign (first_var, boolean_true_node);
22042 : }
22043 :
22044 : else
22045 : {
22046 : cond_var = NULL_TREE;
22047 : assign = NULL;
22048 : }
22049 :
22050 41 : build_instrumentation_call (&body, BUILT_IN_PROFILE_FUNC_ENTER,
22051 : cond_var, assign);
22052 :
22053 : /* If -finstrument-functions-once is specified, generate:
22054 :
22055 : if (!tmp_called)
22056 : [call profiling exit function]
22057 :
22058 : without specific protection for data races. */
22059 41 : build_instrumentation_call (&cleanup, BUILT_IN_PROFILE_FUNC_EXIT,
22060 : cond_var, NULL);
22061 :
22062 41 : gimple *tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
22063 41 : gimplify_seq_add_stmt (&body, tf);
22064 41 : gbind *new_bind = gimple_build_bind (NULL, body, NULL);
22065 :
22066 : /* Replace the current function body with the body
22067 : wrapped in the try/finally TF. */
22068 41 : seq = NULL;
22069 41 : gimple_seq_add_stmt (&seq, new_bind);
22070 41 : gimple_set_body (fndecl, seq);
22071 41 : bind = new_bind;
22072 : }
22073 :
22074 3008701 : if (sanitize_flags_p (SANITIZE_THREAD)
22075 3008701 : && param_tsan_instrument_func_entry_exit)
22076 : {
22077 959 : gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
22078 959 : gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
22079 959 : gbind *new_bind = gimple_build_bind (NULL, tf, NULL);
22080 : /* Replace the current function body with the body
22081 : wrapped in the try/finally TF. */
22082 959 : seq = NULL;
22083 959 : gimple_seq_add_stmt (&seq, new_bind);
22084 959 : gimple_set_body (fndecl, seq);
22085 : }
22086 :
22087 3008701 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
22088 3008701 : cfun->curr_properties |= PROP_gimple_any;
22089 :
22090 3008701 : pop_cfun ();
22091 :
22092 3008701 : dump_function (TDI_gimple, fndecl);
22093 3008701 : }
22094 :
22095 : /* Return a dummy expression of type TYPE in order to keep going after an
22096 : error. */
22097 :
22098 : static tree
22099 30 : dummy_object (tree type)
22100 : {
22101 30 : tree t = build_int_cst (build_pointer_type (type), 0);
22102 30 : return build2 (MEM_REF, type, t, t);
22103 : }
22104 :
22105 : /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
22106 : builtin function, but a very special sort of operator. */
22107 :
22108 : enum gimplify_status
22109 51141 : gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
22110 : gimple_seq *post_p ATTRIBUTE_UNUSED)
22111 : {
22112 51141 : tree promoted_type, have_va_type;
22113 51141 : tree valist = TREE_OPERAND (*expr_p, 0);
22114 51141 : tree type = TREE_TYPE (*expr_p);
22115 51141 : tree t, tag, aptag;
22116 51141 : location_t loc = EXPR_LOCATION (*expr_p);
22117 :
22118 : /* Verify that valist is of the proper type. */
22119 51141 : have_va_type = TREE_TYPE (valist);
22120 51141 : if (have_va_type == error_mark_node)
22121 : return GS_ERROR;
22122 51122 : have_va_type = targetm.canonical_va_list_type (have_va_type);
22123 51122 : if (have_va_type == NULL_TREE
22124 51122 : && POINTER_TYPE_P (TREE_TYPE (valist)))
22125 : /* Handle 'Case 1: Not an array type' from c-common.cc/build_va_arg. */
22126 258 : have_va_type
22127 258 : = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
22128 51122 : gcc_assert (have_va_type != NULL_TREE);
22129 :
22130 : /* Generate a diagnostic for requesting data of a type that cannot
22131 : be passed through `...' due to type promotion at the call site. */
22132 51122 : if ((promoted_type = lang_hooks.types.type_promotes_to (type))
22133 : != type)
22134 : {
22135 30 : static bool gave_help;
22136 30 : bool warned;
22137 : /* Use the expansion point to handle cases such as passing bool (defined
22138 : in a system header) through `...'. */
22139 30 : location_t xloc
22140 30 : = expansion_point_location_if_in_system_header (loc);
22141 :
22142 : /* Unfortunately, this is merely undefined, rather than a constraint
22143 : violation, so we cannot make this an error. If this call is never
22144 : executed, the program is still strictly conforming. */
22145 30 : auto_diagnostic_group d;
22146 30 : warned = warning_at (xloc, 0,
22147 : "%qT is promoted to %qT when passed through %<...%>",
22148 : type, promoted_type);
22149 30 : if (!gave_help && warned)
22150 : {
22151 15 : gave_help = true;
22152 15 : inform (xloc, "(so you should pass %qT not %qT to %<va_arg%>)",
22153 : promoted_type, type);
22154 : }
22155 :
22156 : /* We can, however, treat "undefined" any way we please.
22157 : Call abort to encourage the user to fix the program. */
22158 23 : if (warned)
22159 23 : inform (xloc, "if this code is reached, the program will abort");
22160 : /* Before the abort, allow the evaluation of the va_list
22161 : expression to exit or longjmp. */
22162 30 : gimplify_and_add (valist, pre_p);
22163 60 : t = build_call_expr_loc (loc,
22164 : builtin_decl_implicit (BUILT_IN_TRAP), 0);
22165 30 : gimplify_and_add (t, pre_p);
22166 :
22167 : /* This is dead code, but go ahead and finish so that the
22168 : mode of the result comes out right. */
22169 30 : *expr_p = dummy_object (type);
22170 30 : return GS_ALL_DONE;
22171 30 : }
22172 :
22173 51092 : tag = build_int_cst (build_pointer_type (type), 0);
22174 51092 : aptag = build_int_cst (TREE_TYPE (valist), 0);
22175 :
22176 51092 : *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3,
22177 : valist, tag, aptag);
22178 :
22179 : /* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
22180 : needs to be expanded. */
22181 51092 : cfun->curr_properties &= ~PROP_gimple_lva;
22182 :
22183 51092 : return GS_OK;
22184 : }
22185 :
22186 : /* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P.
22187 :
22188 : DST/SRC are the destination and source respectively. You can pass
22189 : ungimplified trees in DST or SRC, in which case they will be
22190 : converted to a gimple operand if necessary.
22191 :
22192 : This function returns the newly created GIMPLE_ASSIGN tuple. */
22193 :
22194 : gimple *
22195 908199 : gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
22196 : {
22197 908199 : tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
22198 908199 : gimplify_and_add (t, seq_p);
22199 908199 : ggc_free (t);
22200 908199 : return gimple_seq_last_stmt (*seq_p);
22201 : }
22202 :
22203 : inline hashval_t
22204 1641610 : gimplify_hasher::hash (const elt_t *p)
22205 : {
22206 1641610 : tree t = p->val;
22207 1641610 : return iterative_hash_expr (t, 0);
22208 : }
22209 :
22210 : inline bool
22211 626823 : gimplify_hasher::equal (const elt_t *p1, const elt_t *p2)
22212 : {
22213 626823 : tree t1 = p1->val;
22214 626823 : tree t2 = p2->val;
22215 626823 : enum tree_code code = TREE_CODE (t1);
22216 :
22217 626823 : if (TREE_CODE (t2) != code
22218 626823 : || TREE_TYPE (t1) != TREE_TYPE (t2))
22219 : return false;
22220 :
22221 368839 : if (!operand_equal_p (t1, t2, 0))
22222 : return false;
22223 :
22224 : return true;
22225 : }
|