Branch data 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-2024 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 : :
74 : : /* Identifier for a basic condition, mapping it to other basic conditions of
75 : : its Boolean expression. Basic conditions given the same uid (in the same
76 : : function) are parts of the same ANDIF/ORIF expression. Used for condition
77 : : coverage. */
78 : : static unsigned nextuid = 1;
79 : : /* Get a fresh identifier for a new condition expression. This is used for
80 : : condition coverage. */
81 : : static unsigned
82 : 4426014 : next_cond_uid ()
83 : : {
84 : 4426014 : return nextuid++;
85 : : }
86 : : /* Reset the condition uid to the value it should have when compiling a new
87 : : function. 0 is already the default/untouched value, so start at non-zero.
88 : : A valid and set id should always be > 0. This is used for condition
89 : : coverage. */
90 : : static void
91 : 2599449 : reset_cond_uid ()
92 : : {
93 : 2599449 : nextuid = 1;
94 : 0 : }
95 : :
96 : : /* Hash set of poisoned variables in a bind expr. */
97 : : static hash_set<tree> *asan_poisoned_variables = NULL;
98 : :
99 : : enum gimplify_omp_var_data
100 : : {
101 : : GOVD_SEEN = 0x000001,
102 : : GOVD_EXPLICIT = 0x000002,
103 : : GOVD_SHARED = 0x000004,
104 : : GOVD_PRIVATE = 0x000008,
105 : : GOVD_FIRSTPRIVATE = 0x000010,
106 : : GOVD_LASTPRIVATE = 0x000020,
107 : : GOVD_REDUCTION = 0x000040,
108 : : GOVD_LOCAL = 0x00080,
109 : : GOVD_MAP = 0x000100,
110 : : GOVD_DEBUG_PRIVATE = 0x000200,
111 : : GOVD_PRIVATE_OUTER_REF = 0x000400,
112 : : GOVD_LINEAR = 0x000800,
113 : : GOVD_ALIGNED = 0x001000,
114 : :
115 : : /* Flag for GOVD_MAP: don't copy back. */
116 : : GOVD_MAP_TO_ONLY = 0x002000,
117 : :
118 : : /* Flag for GOVD_LINEAR or GOVD_LASTPRIVATE: no outer reference. */
119 : : GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 0x004000,
120 : :
121 : : GOVD_MAP_0LEN_ARRAY = 0x008000,
122 : :
123 : : /* Flag for GOVD_MAP, if it is always, to or always, tofrom mapping. */
124 : : GOVD_MAP_ALWAYS_TO = 0x010000,
125 : :
126 : : /* Flag for shared vars that are or might be stored to in the region. */
127 : : GOVD_WRITTEN = 0x020000,
128 : :
129 : : /* Flag for GOVD_MAP, if it is a forced mapping. */
130 : : GOVD_MAP_FORCE = 0x040000,
131 : :
132 : : /* Flag for GOVD_MAP: must be present already. */
133 : : GOVD_MAP_FORCE_PRESENT = 0x080000,
134 : :
135 : : /* Flag for GOVD_MAP: only allocate. */
136 : : GOVD_MAP_ALLOC_ONLY = 0x100000,
137 : :
138 : : /* Flag for GOVD_MAP: only copy back. */
139 : : GOVD_MAP_FROM_ONLY = 0x200000,
140 : :
141 : : GOVD_NONTEMPORAL = 0x400000,
142 : :
143 : : /* Flag for GOVD_LASTPRIVATE: conditional modifier. */
144 : : GOVD_LASTPRIVATE_CONDITIONAL = 0x800000,
145 : :
146 : : GOVD_CONDTEMP = 0x1000000,
147 : :
148 : : /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */
149 : : GOVD_REDUCTION_INSCAN = 0x2000000,
150 : :
151 : : /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. */
152 : : GOVD_FIRSTPRIVATE_IMPLICIT = 0x4000000,
153 : :
154 : : GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
155 : : | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
156 : : | GOVD_LOCAL)
157 : : };
158 : :
159 : :
160 : : enum omp_region_type
161 : : {
162 : : ORT_WORKSHARE = 0x00,
163 : : ORT_TASKGROUP = 0x01,
164 : : ORT_SIMD = 0x04,
165 : :
166 : : ORT_PARALLEL = 0x08,
167 : : ORT_COMBINED_PARALLEL = ORT_PARALLEL | 1,
168 : :
169 : : ORT_TASK = 0x10,
170 : : ORT_UNTIED_TASK = ORT_TASK | 1,
171 : : ORT_TASKLOOP = ORT_TASK | 2,
172 : : ORT_UNTIED_TASKLOOP = ORT_UNTIED_TASK | 2,
173 : :
174 : : ORT_TEAMS = 0x20,
175 : : ORT_COMBINED_TEAMS = ORT_TEAMS | 1,
176 : : ORT_HOST_TEAMS = ORT_TEAMS | 2,
177 : : ORT_COMBINED_HOST_TEAMS = ORT_COMBINED_TEAMS | 2,
178 : :
179 : : /* Data region. */
180 : : ORT_TARGET_DATA = 0x40,
181 : :
182 : : /* Data region with offloading. */
183 : : ORT_TARGET = 0x80,
184 : : ORT_COMBINED_TARGET = ORT_TARGET | 1,
185 : : ORT_IMPLICIT_TARGET = ORT_TARGET | 2,
186 : :
187 : : /* OpenACC variants. */
188 : : ORT_ACC = 0x100, /* A generic OpenACC region. */
189 : : ORT_ACC_DATA = ORT_ACC | ORT_TARGET_DATA, /* Data construct. */
190 : : ORT_ACC_PARALLEL = ORT_ACC | ORT_TARGET, /* Parallel construct */
191 : : ORT_ACC_KERNELS = ORT_ACC | ORT_TARGET | 2, /* Kernels construct. */
192 : : ORT_ACC_SERIAL = ORT_ACC | ORT_TARGET | 4, /* Serial construct. */
193 : : ORT_ACC_HOST_DATA = ORT_ACC | ORT_TARGET_DATA | 2, /* Host data. */
194 : :
195 : : /* Dummy OpenMP region, used to disable expansion of
196 : : DECL_VALUE_EXPRs in taskloop pre body. */
197 : : ORT_NONE = 0x200
198 : : };
199 : :
200 : : /* Gimplify hashtable helper. */
201 : :
202 : : struct gimplify_hasher : free_ptr_hash <elt_t>
203 : : {
204 : : static inline hashval_t hash (const elt_t *);
205 : : static inline bool equal (const elt_t *, const elt_t *);
206 : : };
207 : :
208 : : struct gimplify_ctx
209 : : {
210 : : struct gimplify_ctx *prev_context;
211 : :
212 : : vec<gbind *> bind_expr_stack;
213 : : tree temps;
214 : : gimple_seq conditional_cleanups;
215 : : tree exit_label;
216 : : tree return_temp;
217 : :
218 : : vec<tree> case_labels;
219 : : hash_set<tree> *live_switch_vars;
220 : : /* The formal temporary table. Should this be persistent? */
221 : : hash_table<gimplify_hasher> *temp_htab;
222 : :
223 : : int conditions;
224 : : unsigned into_ssa : 1;
225 : : unsigned allow_rhs_cond_expr : 1;
226 : : unsigned in_cleanup_point_expr : 1;
227 : : unsigned keep_stack : 1;
228 : : unsigned save_stack : 1;
229 : : unsigned in_switch_expr : 1;
230 : : };
231 : :
232 : : enum gimplify_defaultmap_kind
233 : : {
234 : : GDMK_SCALAR,
235 : : GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only. */
236 : : GDMK_AGGREGATE,
237 : : GDMK_ALLOCATABLE,
238 : : GDMK_POINTER
239 : : };
240 : :
241 : : struct gimplify_omp_ctx
242 : : {
243 : : struct gimplify_omp_ctx *outer_context;
244 : : splay_tree variables;
245 : : hash_set<tree> *privatized_types;
246 : : tree clauses;
247 : : /* Iteration variables in an OMP_FOR. */
248 : : vec<tree> loop_iter_var;
249 : : location_t location;
250 : : enum omp_clause_default_kind default_kind;
251 : : enum omp_region_type region_type;
252 : : enum tree_code code;
253 : : bool combined_loop;
254 : : bool distribute;
255 : : bool target_firstprivatize_array_bases;
256 : : bool add_safelen1;
257 : : bool order_concurrent;
258 : : bool has_depend;
259 : : bool in_for_exprs;
260 : : int defaultmap[5];
261 : : };
262 : :
263 : : static struct gimplify_ctx *gimplify_ctxp;
264 : : static struct gimplify_omp_ctx *gimplify_omp_ctxp;
265 : : static bool in_omp_construct;
266 : :
267 : : /* Forward declaration. */
268 : : static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
269 : : static hash_map<tree, tree> *oacc_declare_returns;
270 : : static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
271 : : bool (*) (tree), fallback_t, bool);
272 : : static void prepare_gimple_addressable (tree *, gimple_seq *);
273 : :
274 : : /* Shorter alias name for the above function for use in gimplify.cc
275 : : only. */
276 : :
277 : : static inline void
278 : 84070303 : gimplify_seq_add_stmt (gimple_seq *seq_p, gimple *gs)
279 : : {
280 : 84070303 : gimple_seq_add_stmt_without_update (seq_p, gs);
281 : 5820511 : }
282 : :
283 : : /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
284 : : NULL, a new sequence is allocated. This function is
285 : : similar to gimple_seq_add_seq, but does not scan the operands.
286 : : During gimplification, we need to manipulate statement sequences
287 : : before the def/use vectors have been constructed. */
288 : :
289 : : static void
290 : 8510390 : gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
291 : : {
292 : 8510390 : gimple_stmt_iterator si;
293 : :
294 : 8510390 : if (src == NULL)
295 : 3628822 : return;
296 : :
297 : 4881568 : si = gsi_last (*dst_p);
298 : 4881568 : gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
299 : : }
300 : :
301 : :
302 : : /* Pointer to a list of allocated gimplify_ctx structs to be used for pushing
303 : : and popping gimplify contexts. */
304 : :
305 : : static struct gimplify_ctx *ctx_pool = NULL;
306 : :
307 : : /* Return a gimplify context struct from the pool. */
308 : :
309 : : static inline struct gimplify_ctx *
310 : 7830678 : ctx_alloc (void)
311 : : {
312 : 7830678 : struct gimplify_ctx * c = ctx_pool;
313 : :
314 : 7830678 : if (c)
315 : 7572205 : ctx_pool = c->prev_context;
316 : : else
317 : 258473 : c = XNEW (struct gimplify_ctx);
318 : :
319 : 7830678 : memset (c, '\0', sizeof (*c));
320 : 7830678 : return c;
321 : : }
322 : :
323 : : /* Put gimplify context C back into the pool. */
324 : :
325 : : static inline void
326 : 7830674 : ctx_free (struct gimplify_ctx *c)
327 : : {
328 : 7830674 : c->prev_context = ctx_pool;
329 : 7830674 : ctx_pool = c;
330 : : }
331 : :
332 : : /* Free allocated ctx stack memory. */
333 : :
334 : : void
335 : 224965 : free_gimplify_stack (void)
336 : : {
337 : 224965 : struct gimplify_ctx *c;
338 : :
339 : 452413 : while ((c = ctx_pool))
340 : : {
341 : 227448 : ctx_pool = c->prev_context;
342 : 227448 : free (c);
343 : : }
344 : 224965 : }
345 : :
346 : :
347 : : /* Set up a context for the gimplifier. */
348 : :
349 : : void
350 : 7830678 : push_gimplify_context (bool in_ssa, bool rhs_cond_ok)
351 : : {
352 : 7830678 : struct gimplify_ctx *c = ctx_alloc ();
353 : :
354 : 7830678 : c->prev_context = gimplify_ctxp;
355 : 7830678 : gimplify_ctxp = c;
356 : 7830678 : gimplify_ctxp->into_ssa = in_ssa;
357 : 7830678 : gimplify_ctxp->allow_rhs_cond_expr = rhs_cond_ok;
358 : 7830678 : }
359 : :
360 : : /* Tear down a context for the gimplifier. If BODY is non-null, then
361 : : put the temporaries into the outer BIND_EXPR. Otherwise, put them
362 : : in the local_decls.
363 : :
364 : : BODY is not a sequence, but the first tuple in a sequence. */
365 : :
366 : : void
367 : 7830674 : pop_gimplify_context (gimple *body)
368 : : {
369 : 7830674 : struct gimplify_ctx *c = gimplify_ctxp;
370 : :
371 : 7830674 : gcc_assert (c
372 : : && (!c->bind_expr_stack.exists ()
373 : : || c->bind_expr_stack.is_empty ()));
374 : 7830674 : c->bind_expr_stack.release ();
375 : 7830674 : gimplify_ctxp = c->prev_context;
376 : :
377 : 7830674 : if (body)
378 : 2722677 : declare_vars (c->temps, body, false);
379 : : else
380 : 5107997 : record_vars (c->temps);
381 : :
382 : 7830674 : delete c->temp_htab;
383 : 7830674 : c->temp_htab = NULL;
384 : 7830674 : ctx_free (c);
385 : 7830674 : }
386 : :
387 : : /* Push a GIMPLE_BIND tuple onto the stack of bindings. */
388 : :
389 : : static void
390 : 5536354 : gimple_push_bind_expr (gbind *bind_stmt)
391 : : {
392 : 5536354 : gimplify_ctxp->bind_expr_stack.reserve (8);
393 : 5536354 : gimplify_ctxp->bind_expr_stack.safe_push (bind_stmt);
394 : 5536354 : }
395 : :
396 : : /* Pop the first element off the stack of bindings. */
397 : :
398 : : static void
399 : 5536354 : gimple_pop_bind_expr (void)
400 : : {
401 : 0 : gimplify_ctxp->bind_expr_stack.pop ();
402 : 0 : }
403 : :
404 : : /* Return the first element of the stack of bindings. */
405 : :
406 : : gbind *
407 : 0 : gimple_current_bind_expr (void)
408 : : {
409 : 0 : return gimplify_ctxp->bind_expr_stack.last ();
410 : : }
411 : :
412 : : /* Return the stack of bindings created during gimplification. */
413 : :
414 : : vec<gbind *>
415 : 0 : gimple_bind_expr_stack (void)
416 : : {
417 : 0 : return gimplify_ctxp->bind_expr_stack;
418 : : }
419 : :
420 : : /* Return true iff there is a COND_EXPR between us and the innermost
421 : : CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
422 : :
423 : : static bool
424 : 2448856 : gimple_conditional_context (void)
425 : : {
426 : 2448856 : return gimplify_ctxp->conditions > 0;
427 : : }
428 : :
429 : : /* Note that we've entered a COND_EXPR. */
430 : :
431 : : static void
432 : 5245033 : gimple_push_condition (void)
433 : : {
434 : : #ifdef ENABLE_GIMPLE_CHECKING
435 : 5245033 : if (gimplify_ctxp->conditions == 0)
436 : 3417769 : gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
437 : : #endif
438 : 5245033 : ++(gimplify_ctxp->conditions);
439 : 5245033 : }
440 : :
441 : : /* Note that we've left a COND_EXPR. If we're back at unconditional scope
442 : : now, add any conditional cleanups we've seen to the prequeue. */
443 : :
444 : : static void
445 : 5245033 : gimple_pop_condition (gimple_seq *pre_p)
446 : : {
447 : 5245033 : int conds = --(gimplify_ctxp->conditions);
448 : :
449 : 5245033 : gcc_assert (conds >= 0);
450 : 5245033 : if (conds == 0)
451 : : {
452 : 3417769 : gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
453 : 3417769 : gimplify_ctxp->conditional_cleanups = NULL;
454 : : }
455 : 5245033 : }
456 : :
457 : : /* A stable comparison routine for use with splay trees and DECLs. */
458 : :
459 : : static int
460 : 16924015 : splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
461 : : {
462 : 16924015 : tree a = (tree) xa;
463 : 16924015 : tree b = (tree) xb;
464 : :
465 : 16924015 : return DECL_UID (a) - DECL_UID (b);
466 : : }
467 : :
468 : : /* Create a new omp construct that deals with variable remapping. */
469 : :
470 : : static struct gimplify_omp_ctx *
471 : 133157 : new_omp_context (enum omp_region_type region_type)
472 : : {
473 : 133157 : struct gimplify_omp_ctx *c;
474 : :
475 : 133157 : c = XCNEW (struct gimplify_omp_ctx);
476 : 133157 : c->outer_context = gimplify_omp_ctxp;
477 : 133157 : c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
478 : 133157 : c->privatized_types = new hash_set<tree>;
479 : 133157 : c->location = input_location;
480 : 133157 : c->region_type = region_type;
481 : 133157 : if ((region_type & ORT_TASK) == 0)
482 : 126998 : c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
483 : : else
484 : 6159 : c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
485 : 133157 : c->defaultmap[GDMK_SCALAR] = GOVD_MAP;
486 : 133157 : c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP;
487 : 133157 : c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP;
488 : 133157 : c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP;
489 : 133157 : c->defaultmap[GDMK_POINTER] = GOVD_MAP;
490 : :
491 : 133157 : return c;
492 : : }
493 : :
494 : : /* Destroy an omp construct that deals with variable remapping. */
495 : :
496 : : static void
497 : 133157 : delete_omp_context (struct gimplify_omp_ctx *c)
498 : : {
499 : 133157 : splay_tree_delete (c->variables);
500 : 266314 : delete c->privatized_types;
501 : 133157 : c->loop_iter_var.release ();
502 : 133157 : XDELETE (c);
503 : 133157 : }
504 : :
505 : : static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
506 : : static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
507 : :
508 : : /* Both gimplify the statement T and append it to *SEQ_P. This function
509 : : behaves exactly as gimplify_stmt, but you don't have to pass T as a
510 : : reference. */
511 : :
512 : : void
513 : 34985165 : gimplify_and_add (tree t, gimple_seq *seq_p)
514 : : {
515 : 34985165 : gimplify_stmt (&t, seq_p);
516 : 34985165 : }
517 : :
518 : : /* Gimplify statement T into sequence *SEQ_P, and return the first
519 : : tuple in the sequence of generated tuples for this statement.
520 : : Return NULL if gimplifying T produced no tuples. */
521 : :
522 : : static gimple *
523 : 105695 : gimplify_and_return_first (tree t, gimple_seq *seq_p)
524 : : {
525 : 105695 : gimple_stmt_iterator last = gsi_last (*seq_p);
526 : :
527 : 105695 : gimplify_and_add (t, seq_p);
528 : :
529 : 105695 : if (!gsi_end_p (last))
530 : : {
531 : 5124 : gsi_next (&last);
532 : 5124 : return gsi_stmt (last);
533 : : }
534 : : else
535 : 100571 : return gimple_seq_first_stmt (*seq_p);
536 : : }
537 : :
538 : : /* Returns true iff T is a valid RHS for an assignment to an un-renamed
539 : : LHS, or for a call argument. */
540 : :
541 : : static bool
542 : 233164 : is_gimple_mem_rhs (tree t)
543 : : {
544 : : /* If we're dealing with a renamable type, either source or dest must be
545 : : a renamed variable. */
546 : 233164 : if (is_gimple_reg_type (TREE_TYPE (t)))
547 : 229837 : return is_gimple_val (t);
548 : : else
549 : 3327 : return is_gimple_val (t) || is_gimple_lvalue (t);
550 : : }
551 : :
552 : : /* Return true if T is a CALL_EXPR or an expression that can be
553 : : assigned to a temporary. Note that this predicate should only be
554 : : used during gimplification. See the rationale for this in
555 : : gimplify_modify_expr. */
556 : :
557 : : static bool
558 : 88956730 : is_gimple_reg_rhs_or_call (tree t)
559 : : {
560 : 65221371 : return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
561 : 88956730 : || TREE_CODE (t) == CALL_EXPR);
562 : : }
563 : :
564 : : /* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
565 : : this predicate should only be used during gimplification. See the
566 : : rationale for this in gimplify_modify_expr. */
567 : :
568 : : static bool
569 : 13013033 : is_gimple_mem_rhs_or_call (tree t)
570 : : {
571 : : /* If we're dealing with a renamable type, either source or dest must be
572 : : a renamed variable. */
573 : 13013033 : if (is_gimple_reg_type (TREE_TYPE (t)))
574 : 10057272 : return is_gimple_val (t);
575 : : else
576 : 2955761 : return (is_gimple_val (t)
577 : 1450005 : || is_gimple_lvalue (t)
578 : 966502 : || TREE_CLOBBER_P (t)
579 : 3922183 : || TREE_CODE (t) == CALL_EXPR);
580 : : }
581 : :
582 : : /* Create a temporary with a name derived from VAL. Subroutine of
583 : : lookup_tmp_var; nobody else should call this function. */
584 : :
585 : : static inline tree
586 : 2093958 : create_tmp_from_val (tree val)
587 : : {
588 : : /* Drop all qualifiers and address-space information from the value type. */
589 : 2093958 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
590 : 2093958 : tree var = create_tmp_var (type, get_name (val));
591 : 2093958 : return var;
592 : : }
593 : :
594 : : /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
595 : : an existing expression temporary. If NOT_GIMPLE_REG, mark it as such. */
596 : :
597 : : static tree
598 : 2305504 : lookup_tmp_var (tree val, bool is_formal, bool not_gimple_reg)
599 : : {
600 : 2305504 : tree ret;
601 : :
602 : : /* We cannot mark a formal temporary with DECL_NOT_GIMPLE_REG_P. */
603 : 2305504 : gcc_assert (!is_formal || !not_gimple_reg);
604 : :
605 : : /* If not optimizing, never really reuse a temporary. local-alloc
606 : : won't allocate any variable that is used in more than one basic
607 : : block, which means it will go into memory, causing much extra
608 : : work in reload and final and poorer code generation, outweighing
609 : : the extra memory allocation here. */
610 : 2305504 : if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
611 : : {
612 : 1096063 : ret = create_tmp_from_val (val);
613 : 1096063 : DECL_NOT_GIMPLE_REG_P (ret) = not_gimple_reg;
614 : : }
615 : : else
616 : : {
617 : 1209441 : elt_t elt, *elt_p;
618 : 1209441 : elt_t **slot;
619 : :
620 : 1209441 : elt.val = val;
621 : 1209441 : if (!gimplify_ctxp->temp_htab)
622 : 373679 : gimplify_ctxp->temp_htab = new hash_table<gimplify_hasher> (1000);
623 : 1209441 : slot = gimplify_ctxp->temp_htab->find_slot (&elt, INSERT);
624 : 1209441 : if (*slot == NULL)
625 : : {
626 : 997895 : elt_p = XNEW (elt_t);
627 : 997895 : elt_p->val = val;
628 : 997895 : elt_p->temp = ret = create_tmp_from_val (val);
629 : 997895 : *slot = elt_p;
630 : : }
631 : : else
632 : : {
633 : 211546 : elt_p = *slot;
634 : 211546 : ret = elt_p->temp;
635 : : }
636 : : }
637 : :
638 : 2305504 : return ret;
639 : : }
640 : :
641 : : /* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
642 : :
643 : : static tree
644 : 24287805 : internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
645 : : bool is_formal, bool allow_ssa, bool not_gimple_reg)
646 : : {
647 : 24287805 : tree t, mod;
648 : :
649 : : /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
650 : : can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
651 : 24287805 : gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
652 : : fb_rvalue);
653 : :
654 : 24287805 : if (allow_ssa
655 : 24001627 : && gimplify_ctxp->into_ssa
656 : 46910402 : && is_gimple_reg_type (TREE_TYPE (val)))
657 : : {
658 : 21982302 : t = make_ssa_name (TYPE_MAIN_VARIANT (TREE_TYPE (val)));
659 : 21982302 : if (! gimple_in_ssa_p (cfun))
660 : : {
661 : 19193391 : const char *name = get_name (val);
662 : 19193391 : if (name)
663 : 6516074 : SET_SSA_NAME_VAR_OR_IDENTIFIER (t, create_tmp_var_name (name));
664 : : }
665 : : }
666 : : else
667 : 2305503 : t = lookup_tmp_var (val, is_formal, not_gimple_reg);
668 : :
669 : 24287805 : mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
670 : :
671 : 24287805 : SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location));
672 : :
673 : : /* gimplify_modify_expr might want to reduce this further. */
674 : 24287805 : gimplify_and_add (mod, pre_p);
675 : 24287805 : ggc_free (mod);
676 : :
677 : : /* If we failed to gimplify VAL then we can end up with the temporary
678 : : SSA name not having a definition. In this case return a decl. */
679 : 24287805 : if (TREE_CODE (t) == SSA_NAME && ! SSA_NAME_DEF_STMT (t))
680 : 1 : return lookup_tmp_var (val, is_formal, not_gimple_reg);
681 : :
682 : : return t;
683 : : }
684 : :
685 : : /* Return a formal temporary variable initialized with VAL. PRE_P is as
686 : : in gimplify_expr. Only use this function if:
687 : :
688 : : 1) The value of the unfactored expression represented by VAL will not
689 : : change between the initialization and use of the temporary, and
690 : : 2) The temporary will not be otherwise modified.
691 : :
692 : : For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
693 : : and #2 means it is inappropriate for && temps.
694 : :
695 : : For other cases, use get_initialized_tmp_var instead. */
696 : :
697 : : tree
698 : 23773488 : get_formal_tmp_var (tree val, gimple_seq *pre_p)
699 : : {
700 : 23773488 : return internal_get_tmp_var (val, pre_p, NULL, true, true, false);
701 : : }
702 : :
703 : : /* Return a temporary variable initialized with VAL. PRE_P and POST_P
704 : : are as in gimplify_expr. */
705 : :
706 : : tree
707 : 502599 : get_initialized_tmp_var (tree val, gimple_seq *pre_p,
708 : : gimple_seq *post_p /* = NULL */,
709 : : bool allow_ssa /* = true */)
710 : : {
711 : 502599 : return internal_get_tmp_var (val, pre_p, post_p, false, allow_ssa, false);
712 : : }
713 : :
714 : : /* Declare all the variables in VARS in SCOPE. If DEBUG_INFO is true,
715 : : generate debug info for them; otherwise don't. */
716 : :
717 : : void
718 : 2729880 : declare_vars (tree vars, gimple *gs, bool debug_info)
719 : : {
720 : 2729880 : tree last = vars;
721 : 2729880 : if (last)
722 : : {
723 : 1736798 : tree temps, block;
724 : :
725 : 1736798 : gbind *scope = as_a <gbind *> (gs);
726 : :
727 : 1736798 : temps = nreverse (last);
728 : :
729 : 1736798 : block = gimple_bind_block (scope);
730 : 1736798 : gcc_assert (!block || TREE_CODE (block) == BLOCK);
731 : 1736798 : if (!block || !debug_info)
732 : : {
733 : 1733442 : DECL_CHAIN (last) = gimple_bind_vars (scope);
734 : 1733442 : gimple_bind_set_vars (scope, temps);
735 : : }
736 : : else
737 : : {
738 : : /* We need to attach the nodes both to the BIND_EXPR and to its
739 : : associated BLOCK for debugging purposes. The key point here
740 : : is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
741 : : is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
742 : 3356 : if (BLOCK_VARS (block))
743 : 3175 : BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
744 : : else
745 : : {
746 : 181 : gimple_bind_set_vars (scope,
747 : : chainon (gimple_bind_vars (scope), temps));
748 : 181 : BLOCK_VARS (block) = temps;
749 : : }
750 : : }
751 : : }
752 : 2729880 : }
753 : :
754 : : /* For VAR a VAR_DECL of variable size, try to find a constant upper bound
755 : : for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
756 : : no such upper bound can be obtained. */
757 : :
758 : : static void
759 : 0 : force_constant_size (tree var)
760 : : {
761 : : /* The only attempt we make is by querying the maximum size of objects
762 : : of the variable's type. */
763 : :
764 : 0 : HOST_WIDE_INT max_size;
765 : :
766 : 0 : gcc_assert (VAR_P (var));
767 : :
768 : 0 : max_size = max_int_size_in_bytes (TREE_TYPE (var));
769 : :
770 : 0 : gcc_assert (max_size >= 0);
771 : :
772 : 0 : DECL_SIZE_UNIT (var)
773 : 0 : = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
774 : 0 : DECL_SIZE (var)
775 : 0 : = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
776 : 0 : }
777 : :
778 : : /* Push the temporary variable TMP into the current binding. */
779 : :
780 : : void
781 : 21242 : gimple_add_tmp_var_fn (struct function *fn, tree tmp)
782 : : {
783 : 21242 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
784 : :
785 : : /* Later processing assumes that the object size is constant, which might
786 : : not be true at this point. Force the use of a constant upper bound in
787 : : this case. */
788 : 21242 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
789 : 0 : force_constant_size (tmp);
790 : :
791 : 21242 : DECL_CONTEXT (tmp) = fn->decl;
792 : 21242 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
793 : :
794 : 21242 : record_vars_into (tmp, fn->decl);
795 : 21242 : }
796 : :
797 : : /* Push the temporary variable TMP into the current binding. */
798 : :
799 : : void
800 : 15796799 : gimple_add_tmp_var (tree tmp)
801 : : {
802 : 15796799 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
803 : :
804 : : /* Later processing assumes that the object size is constant, which might
805 : : not be true at this point. Force the use of a constant upper bound in
806 : : this case. */
807 : 15796799 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
808 : 0 : force_constant_size (tmp);
809 : :
810 : 15796799 : DECL_CONTEXT (tmp) = current_function_decl;
811 : 15796799 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
812 : :
813 : 15796799 : if (gimplify_ctxp)
814 : : {
815 : 5247540 : DECL_CHAIN (tmp) = gimplify_ctxp->temps;
816 : 5247540 : gimplify_ctxp->temps = tmp;
817 : :
818 : : /* Mark temporaries local within the nearest enclosing parallel. */
819 : 5247540 : if (gimplify_omp_ctxp)
820 : : {
821 : : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
822 : 520513 : int flag = GOVD_LOCAL | GOVD_SEEN;
823 : : while (ctx
824 : 520513 : && (ctx->region_type == ORT_WORKSHARE
825 : : || ctx->region_type == ORT_TASKGROUP
826 : 378495 : || ctx->region_type == ORT_SIMD
827 : 327256 : || ctx->region_type == ORT_ACC))
828 : : {
829 : 200179 : if (ctx->region_type == ORT_SIMD
830 : : && TREE_ADDRESSABLE (tmp)
831 : 51239 : && !TREE_STATIC (tmp))
832 : : {
833 : 100 : if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST)
834 : 0 : ctx->add_safelen1 = true;
835 : 100 : else if (ctx->in_for_exprs)
836 : : flag = GOVD_PRIVATE;
837 : : else
838 : : flag = GOVD_PRIVATE | GOVD_SEEN;
839 : : break;
840 : : }
841 : 200079 : ctx = ctx->outer_context;
842 : : }
843 : 320334 : if (ctx)
844 : 293171 : omp_add_variable (ctx, tmp, flag);
845 : : }
846 : : }
847 : 10549259 : else if (cfun)
848 : 10549259 : record_vars (tmp);
849 : : else
850 : : {
851 : 0 : gimple_seq body_seq;
852 : :
853 : : /* This case is for nested functions. We need to expose the locals
854 : : they create. */
855 : 0 : body_seq = gimple_body (current_function_decl);
856 : 0 : declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
857 : : }
858 : 15796799 : }
859 : :
860 : :
861 : :
862 : : /* This page contains routines to unshare tree nodes, i.e. to duplicate tree
863 : : nodes that are referenced more than once in GENERIC functions. This is
864 : : necessary because gimplification (translation into GIMPLE) is performed
865 : : by modifying tree nodes in-place, so gimplication of a shared node in a
866 : : first context could generate an invalid GIMPLE form in a second context.
867 : :
868 : : This is achieved with a simple mark/copy/unmark algorithm that walks the
869 : : GENERIC representation top-down, marks nodes with TREE_VISITED the first
870 : : time it encounters them, duplicates them if they already have TREE_VISITED
871 : : set, and finally removes the TREE_VISITED marks it has set.
872 : :
873 : : The algorithm works only at the function level, i.e. it generates a GENERIC
874 : : representation of a function with no nodes shared within the function when
875 : : passed a GENERIC function (except for nodes that are allowed to be shared).
876 : :
877 : : At the global level, it is also necessary to unshare tree nodes that are
878 : : referenced in more than one function, for the same aforementioned reason.
879 : : This requires some cooperation from the front-end. There are 2 strategies:
880 : :
881 : : 1. Manual unsharing. The front-end needs to call unshare_expr on every
882 : : expression that might end up being shared across functions.
883 : :
884 : : 2. Deep unsharing. This is an extension of regular unsharing. Instead
885 : : of calling unshare_expr on expressions that might be shared across
886 : : functions, the front-end pre-marks them with TREE_VISITED. This will
887 : : ensure that they are unshared on the first reference within functions
888 : : when the regular unsharing algorithm runs. The counterpart is that
889 : : this algorithm must look deeper than for manual unsharing, which is
890 : : specified by LANG_HOOKS_DEEP_UNSHARING.
891 : :
892 : : If there are only few specific cases of node sharing across functions, it is
893 : : probably easier for a front-end to unshare the expressions manually. On the
894 : : contrary, if the expressions generated at the global level are as widespread
895 : : as expressions generated within functions, deep unsharing is very likely the
896 : : way to go. */
897 : :
898 : : /* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
899 : : These nodes model computations that must be done once. If we were to
900 : : unshare something like SAVE_EXPR(i++), the gimplification process would
901 : : create wrong code. However, if DATA is non-null, it must hold a pointer
902 : : set that is used to unshare the subtrees of these nodes. */
903 : :
904 : : static tree
905 : 1977297582 : mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
906 : : {
907 : 1977297582 : tree t = *tp;
908 : 1977297582 : enum tree_code code = TREE_CODE (t);
909 : :
910 : : /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
911 : : copy their subtrees if we can make sure to do it only once. */
912 : 1977297582 : if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
913 : : {
914 : 7512767 : if (data && !((hash_set<tree> *)data)->add (t))
915 : : ;
916 : : else
917 : 7512767 : *walk_subtrees = 0;
918 : : }
919 : :
920 : : /* Stop at types, decls, constants like copy_tree_r. */
921 : 1969784815 : else if (TREE_CODE_CLASS (code) == tcc_type
922 : : || TREE_CODE_CLASS (code) == tcc_declaration
923 : 1969784815 : || TREE_CODE_CLASS (code) == tcc_constant)
924 : 1199477331 : *walk_subtrees = 0;
925 : :
926 : : /* Cope with the statement expression extension. */
927 : 770307484 : else if (code == STATEMENT_LIST)
928 : : ;
929 : :
930 : : /* Leave the bulk of the work to copy_tree_r itself. */
931 : : else
932 : 770257850 : copy_tree_r (tp, walk_subtrees, NULL);
933 : :
934 : 1977297582 : return NULL_TREE;
935 : : }
936 : :
937 : : /* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
938 : : If *TP has been visited already, then *TP is deeply copied by calling
939 : : mostly_copy_tree_r. DATA is passed to mostly_copy_tree_r unmodified. */
940 : :
941 : : static tree
942 : 244543792 : copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
943 : : {
944 : 244543792 : tree t = *tp;
945 : 244543792 : enum tree_code code = TREE_CODE (t);
946 : :
947 : : /* Skip types, decls, and constants. But we do want to look at their
948 : : types and the bounds of types. Mark them as visited so we properly
949 : : unmark their subtrees on the unmark pass. If we've already seen them,
950 : : don't look down further. */
951 : 244543792 : if (TREE_CODE_CLASS (code) == tcc_type
952 : : || TREE_CODE_CLASS (code) == tcc_declaration
953 : 244543792 : || TREE_CODE_CLASS (code) == tcc_constant)
954 : : {
955 : 114606453 : if (TREE_VISITED (t))
956 : 69416824 : *walk_subtrees = 0;
957 : : else
958 : 45189629 : TREE_VISITED (t) = 1;
959 : : }
960 : :
961 : : /* If this node has been visited already, unshare it and don't look
962 : : any deeper. */
963 : 129937339 : else if (TREE_VISITED (t))
964 : : {
965 : 1420386 : walk_tree (tp, mostly_copy_tree_r, data, NULL);
966 : 1420386 : *walk_subtrees = 0;
967 : : }
968 : :
969 : : /* Otherwise, mark the node as visited and keep looking. */
970 : : else
971 : 128516953 : TREE_VISITED (t) = 1;
972 : :
973 : 244543792 : return NULL_TREE;
974 : : }
975 : :
976 : : /* Unshare most of the shared trees rooted at *TP. DATA is passed to the
977 : : copy_if_shared_r callback unmodified. */
978 : :
979 : : void
980 : 7857279 : copy_if_shared (tree *tp, void *data)
981 : : {
982 : 7857279 : walk_tree (tp, copy_if_shared_r, data, NULL);
983 : 7857279 : }
984 : :
985 : : /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
986 : : any nested functions. */
987 : :
988 : : static void
989 : 2619093 : unshare_body (tree fndecl)
990 : : {
991 : 2619093 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
992 : : /* If the language requires deep unsharing, we need a pointer set to make
993 : : sure we don't repeatedly unshare subtrees of unshareable nodes. */
994 : 2619093 : hash_set<tree> *visited
995 : 2619093 : = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
996 : :
997 : 2619093 : copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
998 : 2619093 : copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
999 : 2619093 : copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
1000 : :
1001 : 2622284 : delete visited;
1002 : :
1003 : 2619093 : if (cgn)
1004 : 5269902 : for (cgn = first_nested_function (cgn); cgn;
1005 : 19095 : cgn = next_nested_function (cgn))
1006 : 19095 : unshare_body (cgn->decl);
1007 : 2619093 : }
1008 : :
1009 : : /* Callback for walk_tree to unmark the visited trees rooted at *TP.
1010 : : Subtrees are walked until the first unvisited node is encountered. */
1011 : :
1012 : : static tree
1013 : 244543366 : unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1014 : : {
1015 : 244543366 : tree t = *tp;
1016 : :
1017 : : /* If this node has been visited, unmark it and keep looking. */
1018 : 244543366 : if (TREE_VISITED (t))
1019 : 173710771 : TREE_VISITED (t) = 0;
1020 : :
1021 : : /* Otherwise, don't look any deeper. */
1022 : : else
1023 : 70832595 : *walk_subtrees = 0;
1024 : :
1025 : 244543366 : return NULL_TREE;
1026 : : }
1027 : :
1028 : : /* Unmark the visited trees rooted at *TP. */
1029 : :
1030 : : static inline void
1031 : 7857279 : unmark_visited (tree *tp)
1032 : : {
1033 : 7857279 : walk_tree (tp, unmark_visited_r, NULL, NULL);
1034 : 7857279 : }
1035 : :
1036 : : /* Likewise, but mark all trees as not visited. */
1037 : :
1038 : : static void
1039 : 2619093 : unvisit_body (tree fndecl)
1040 : : {
1041 : 2619093 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
1042 : :
1043 : 2619093 : unmark_visited (&DECL_SAVED_TREE (fndecl));
1044 : 2619093 : unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
1045 : 2619093 : unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
1046 : :
1047 : 2619093 : if (cgn)
1048 : 2634951 : for (cgn = first_nested_function (cgn);
1049 : 2634951 : cgn; cgn = next_nested_function (cgn))
1050 : 19095 : unvisit_body (cgn->decl);
1051 : 2619093 : }
1052 : :
1053 : : /* Unconditionally make an unshared copy of EXPR. This is used when using
1054 : : stored expressions which span multiple functions, such as BINFO_VTABLE,
1055 : : as the normal unsharing process can't tell that they're shared. */
1056 : :
1057 : : tree
1058 : 1055188440 : unshare_expr (tree expr)
1059 : : {
1060 : 1055188440 : walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
1061 : 1055188440 : return expr;
1062 : : }
1063 : :
1064 : : /* Worker for unshare_expr_without_location. */
1065 : :
1066 : : static tree
1067 : 6869755 : prune_expr_location (tree *tp, int *walk_subtrees, void *)
1068 : : {
1069 : 6869755 : if (EXPR_P (*tp))
1070 : 3084841 : SET_EXPR_LOCATION (*tp, UNKNOWN_LOCATION);
1071 : : else
1072 : 3784914 : *walk_subtrees = 0;
1073 : 6869755 : return NULL_TREE;
1074 : : }
1075 : :
1076 : : /* Similar to unshare_expr but also prune all expression locations
1077 : : from EXPR. */
1078 : :
1079 : : tree
1080 : 18081034 : unshare_expr_without_location (tree expr)
1081 : : {
1082 : 18081034 : walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
1083 : 18081034 : if (EXPR_P (expr))
1084 : 2309666 : walk_tree (&expr, prune_expr_location, NULL, NULL);
1085 : 18081034 : return expr;
1086 : : }
1087 : :
1088 : : /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
1089 : : one, OR_ELSE otherwise. The location of a STATEMENT_LISTs
1090 : : comprising at least one DEBUG_BEGIN_STMT followed by exactly one
1091 : : EXPR is the location of the EXPR. */
1092 : :
1093 : : static location_t
1094 : 1055932 : rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
1095 : : {
1096 : 1055932 : if (!expr)
1097 : : return or_else;
1098 : :
1099 : 1055932 : if (EXPR_HAS_LOCATION (expr))
1100 : 718315 : return EXPR_LOCATION (expr);
1101 : :
1102 : 337617 : if (TREE_CODE (expr) != STATEMENT_LIST)
1103 : : return or_else;
1104 : :
1105 : 0 : tree_stmt_iterator i = tsi_start (expr);
1106 : :
1107 : 0 : bool found = false;
1108 : 0 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
1109 : : {
1110 : 0 : found = true;
1111 : 0 : tsi_next (&i);
1112 : : }
1113 : :
1114 : 0 : if (!found || !tsi_one_before_end_p (i))
1115 : 0 : return or_else;
1116 : :
1117 : 0 : return rexpr_location (tsi_stmt (i), or_else);
1118 : : }
1119 : :
1120 : : /* Return TRUE iff EXPR (maybe recursively) has a location; see
1121 : : rexpr_location for the potential recursion. */
1122 : :
1123 : : static inline bool
1124 : 463180 : rexpr_has_location (tree expr)
1125 : : {
1126 : 283477 : return rexpr_location (expr) != UNKNOWN_LOCATION;
1127 : : }
1128 : :
1129 : :
1130 : : /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
1131 : : contain statements and have a value. Assign its value to a temporary
1132 : : and give it void_type_node. Return the temporary, or NULL_TREE if
1133 : : WRAPPER was already void. */
1134 : :
1135 : : tree
1136 : 18994096 : voidify_wrapper_expr (tree wrapper, tree temp)
1137 : : {
1138 : 18994096 : tree type = TREE_TYPE (wrapper);
1139 : 18994096 : if (type && !VOID_TYPE_P (type))
1140 : : {
1141 : : tree *p;
1142 : :
1143 : : /* Set p to point to the body of the wrapper. Loop until we find
1144 : : something that isn't a wrapper. */
1145 : 739594 : for (p = &wrapper; p && *p; )
1146 : : {
1147 : 739594 : switch (TREE_CODE (*p))
1148 : : {
1149 : 3598 : case BIND_EXPR:
1150 : 3598 : TREE_SIDE_EFFECTS (*p) = 1;
1151 : 3598 : TREE_TYPE (*p) = void_type_node;
1152 : : /* For a BIND_EXPR, the body is operand 1. */
1153 : 3598 : p = &BIND_EXPR_BODY (*p);
1154 : 3598 : break;
1155 : :
1156 : 343080 : case CLEANUP_POINT_EXPR:
1157 : 343080 : case TRY_FINALLY_EXPR:
1158 : 343080 : case TRY_CATCH_EXPR:
1159 : 343080 : TREE_SIDE_EFFECTS (*p) = 1;
1160 : 343080 : TREE_TYPE (*p) = void_type_node;
1161 : 343080 : p = &TREE_OPERAND (*p, 0);
1162 : 343080 : break;
1163 : :
1164 : 18877 : case STATEMENT_LIST:
1165 : 18877 : {
1166 : 18877 : tree_stmt_iterator i = tsi_last (*p);
1167 : 18877 : TREE_SIDE_EFFECTS (*p) = 1;
1168 : 18877 : TREE_TYPE (*p) = void_type_node;
1169 : 18877 : p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
1170 : : }
1171 : 18877 : break;
1172 : :
1173 : : case COMPOUND_EXPR:
1174 : : /* Advance to the last statement. Set all container types to
1175 : : void. */
1176 : 47712 : for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
1177 : : {
1178 : 23859 : TREE_SIDE_EFFECTS (*p) = 1;
1179 : 23859 : TREE_TYPE (*p) = void_type_node;
1180 : : }
1181 : : break;
1182 : :
1183 : 80 : case TRANSACTION_EXPR:
1184 : 80 : TREE_SIDE_EFFECTS (*p) = 1;
1185 : 80 : TREE_TYPE (*p) = void_type_node;
1186 : 80 : p = &TRANSACTION_EXPR_BODY (*p);
1187 : 80 : break;
1188 : :
1189 : 350106 : default:
1190 : : /* Assume that any tree upon which voidify_wrapper_expr is
1191 : : directly called is a wrapper, and that its body is op0. */
1192 : 350106 : if (p == &wrapper)
1193 : : {
1194 : 33 : TREE_SIDE_EFFECTS (*p) = 1;
1195 : 33 : TREE_TYPE (*p) = void_type_node;
1196 : 33 : p = &TREE_OPERAND (*p, 0);
1197 : 33 : break;
1198 : : }
1199 : 350073 : goto out;
1200 : : }
1201 : : }
1202 : :
1203 : 0 : out:
1204 : 350073 : if (p == NULL || IS_EMPTY_STMT (*p))
1205 : : temp = NULL_TREE;
1206 : 350073 : else if (temp)
1207 : : {
1208 : : /* The wrapper is on the RHS of an assignment that we're pushing
1209 : : down. */
1210 : 1652 : gcc_assert (TREE_CODE (temp) == INIT_EXPR
1211 : : || TREE_CODE (temp) == MODIFY_EXPR);
1212 : 1652 : TREE_OPERAND (temp, 1) = *p;
1213 : 1652 : *p = temp;
1214 : : }
1215 : : else
1216 : : {
1217 : 348421 : temp = create_tmp_var (type, "retval");
1218 : 348421 : *p = build2 (INIT_EXPR, type, temp, *p);
1219 : : }
1220 : :
1221 : 350073 : return temp;
1222 : : }
1223 : :
1224 : : return NULL_TREE;
1225 : : }
1226 : :
1227 : : /* Prepare calls to builtins to SAVE and RESTORE the stack as well as
1228 : : a temporary through which they communicate. */
1229 : :
1230 : : static void
1231 : 7835 : build_stack_save_restore (gcall **save, gcall **restore)
1232 : : {
1233 : 7835 : tree tmp_var;
1234 : :
1235 : 15670 : *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
1236 : 7835 : tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
1237 : 7835 : gimple_call_set_lhs (*save, tmp_var);
1238 : :
1239 : 7835 : *restore
1240 : 7835 : = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1241 : : 1, tmp_var);
1242 : 7835 : }
1243 : :
1244 : : /* Generate IFN_ASAN_MARK call that poisons shadow of a for DECL variable. */
1245 : :
1246 : : static tree
1247 : 435 : build_asan_poison_call_expr (tree decl)
1248 : : {
1249 : : /* Do not poison variables that have size equal to zero. */
1250 : 435 : tree unit_size = DECL_SIZE_UNIT (decl);
1251 : 435 : if (zerop (unit_size))
1252 : : return NULL_TREE;
1253 : :
1254 : 435 : tree base = build_fold_addr_expr (decl);
1255 : :
1256 : 435 : return build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_ASAN_MARK,
1257 : : void_type_node, 3,
1258 : : build_int_cst (integer_type_node,
1259 : 435 : ASAN_MARK_POISON),
1260 : : base, unit_size);
1261 : : }
1262 : :
1263 : : /* Generate IFN_ASAN_MARK call that would poison or unpoison, depending
1264 : : on POISON flag, shadow memory of a DECL variable. The call will be
1265 : : put on location identified by IT iterator, where BEFORE flag drives
1266 : : position where the stmt will be put. */
1267 : :
1268 : : static void
1269 : 3950 : asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
1270 : : bool before)
1271 : : {
1272 : 3950 : tree unit_size = DECL_SIZE_UNIT (decl);
1273 : 3950 : tree base = build_fold_addr_expr (decl);
1274 : :
1275 : : /* Do not poison variables that have size equal to zero. */
1276 : 3950 : if (zerop (unit_size))
1277 : 3950 : return;
1278 : :
1279 : : /* It's necessary to have all stack variables aligned to ASAN granularity
1280 : : bytes. */
1281 : 3936 : gcc_assert (!hwasan_sanitize_p () || hwasan_sanitize_stack_p ());
1282 : 3936 : unsigned shadow_granularity
1283 : 3936 : = hwasan_sanitize_p () ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY;
1284 : 3936 : if (DECL_ALIGN_UNIT (decl) <= shadow_granularity)
1285 : 3734 : SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity);
1286 : :
1287 : 3936 : HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON;
1288 : :
1289 : 3936 : gimple *g
1290 : 3936 : = gimple_build_call_internal (IFN_ASAN_MARK, 3,
1291 : : build_int_cst (integer_type_node, flags),
1292 : : base, unit_size);
1293 : :
1294 : 3936 : if (before)
1295 : 1980 : gsi_insert_before (it, g, GSI_NEW_STMT);
1296 : : else
1297 : 1956 : gsi_insert_after (it, g, GSI_NEW_STMT);
1298 : : }
1299 : :
1300 : : /* Generate IFN_ASAN_MARK internal call that depending on POISON flag
1301 : : either poisons or unpoisons a DECL. Created statement is appended
1302 : : to SEQ_P gimple sequence. */
1303 : :
1304 : : static void
1305 : 3515 : asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
1306 : : {
1307 : 3515 : gimple_stmt_iterator it = gsi_last (*seq_p);
1308 : 3515 : bool before = false;
1309 : :
1310 : 3515 : if (gsi_end_p (it))
1311 : 1765 : before = true;
1312 : :
1313 : 3515 : asan_poison_variable (decl, poison, &it, before);
1314 : 3515 : }
1315 : :
1316 : : /* Sort pair of VAR_DECLs A and B by DECL_UID. */
1317 : :
1318 : : static int
1319 : 135 : sort_by_decl_uid (const void *a, const void *b)
1320 : : {
1321 : 135 : const tree *t1 = (const tree *)a;
1322 : 135 : const tree *t2 = (const tree *)b;
1323 : :
1324 : 135 : int uid1 = DECL_UID (*t1);
1325 : 135 : int uid2 = DECL_UID (*t2);
1326 : :
1327 : 135 : if (uid1 < uid2)
1328 : : return -1;
1329 : 52 : else if (uid1 > uid2)
1330 : : return 1;
1331 : : else
1332 : 0 : return 0;
1333 : : }
1334 : :
1335 : : /* Generate IFN_ASAN_MARK internal call for all VARIABLES
1336 : : depending on POISON flag. Created statement is appended
1337 : : to SEQ_P gimple sequence. */
1338 : :
1339 : : static void
1340 : 1037437 : asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p)
1341 : : {
1342 : 1037437 : unsigned c = variables->elements ();
1343 : 1037437 : if (c == 0)
1344 : 1037261 : return;
1345 : :
1346 : 176 : auto_vec<tree> sorted_variables (c);
1347 : :
1348 : 176 : for (hash_set<tree>::iterator it = variables->begin ();
1349 : 570 : it != variables->end (); ++it)
1350 : 197 : sorted_variables.safe_push (*it);
1351 : :
1352 : 176 : sorted_variables.qsort (sort_by_decl_uid);
1353 : :
1354 : : unsigned i;
1355 : : tree var;
1356 : 549 : FOR_EACH_VEC_ELT (sorted_variables, i, var)
1357 : : {
1358 : 197 : asan_poison_variable (var, poison, seq_p);
1359 : :
1360 : : /* Add use_after_scope_memory attribute for the variable in order
1361 : : to prevent re-written into SSA. */
1362 : 197 : if (!lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
1363 : 197 : DECL_ATTRIBUTES (var)))
1364 : 90 : DECL_ATTRIBUTES (var)
1365 : 180 : = tree_cons (get_identifier (ASAN_USE_AFTER_SCOPE_ATTRIBUTE),
1366 : : integer_one_node,
1367 : 90 : DECL_ATTRIBUTES (var));
1368 : : }
1369 : 176 : }
1370 : :
1371 : : /* Gimplify a BIND_EXPR. Just voidify and recurse. */
1372 : :
1373 : : static enum gimplify_status
1374 : 5536354 : gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
1375 : : {
1376 : 5536354 : tree bind_expr = *expr_p;
1377 : 5536354 : bool old_keep_stack = gimplify_ctxp->keep_stack;
1378 : 5536354 : bool old_save_stack = gimplify_ctxp->save_stack;
1379 : 5536354 : tree t;
1380 : 5536354 : gbind *bind_stmt;
1381 : 5536354 : gimple_seq body, cleanup;
1382 : 5536354 : gcall *stack_save;
1383 : 5536354 : location_t start_locus = 0, end_locus = 0;
1384 : 5536354 : tree ret_clauses = NULL;
1385 : :
1386 : 5536354 : tree temp = voidify_wrapper_expr (bind_expr, NULL);
1387 : :
1388 : : /* Mark variables seen in this bind expr. */
1389 : 11289402 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1390 : : {
1391 : 5753048 : if (VAR_P (t))
1392 : : {
1393 : 5250862 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1394 : 5250862 : tree attr;
1395 : :
1396 : 5250862 : if (flag_openmp
1397 : 210080 : && !is_global_var (t)
1398 : 203433 : && DECL_CONTEXT (t) == current_function_decl
1399 : 203295 : && TREE_USED (t)
1400 : 5452773 : && (attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1401 : : != NULL_TREE)
1402 : : {
1403 : 71 : gcc_assert (!DECL_HAS_VALUE_EXPR_P (t));
1404 : 71 : tree alloc = TREE_PURPOSE (TREE_VALUE (attr));
1405 : 71 : tree align = TREE_VALUE (TREE_VALUE (attr));
1406 : : /* Allocate directives that appear in a target region must specify
1407 : : an allocator clause unless a requires directive with the
1408 : : dynamic_allocators clause is present in the same compilation
1409 : : unit. */
1410 : 71 : bool missing_dyn_alloc = false;
1411 : 71 : if (alloc == NULL_TREE
1412 : 48 : && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS)
1413 : : == 0))
1414 : : {
1415 : : /* This comes too early for omp_discover_declare_target...,
1416 : : but should at least catch the most common cases. */
1417 : 42 : missing_dyn_alloc
1418 : 42 : = cgraph_node::get (current_function_decl)->offloadable;
1419 : 42 : for (struct gimplify_omp_ctx *ctx2 = ctx;
1420 : 48 : ctx2 && !missing_dyn_alloc; ctx2 = ctx2->outer_context)
1421 : 6 : if (ctx2->code == OMP_TARGET)
1422 : 2 : missing_dyn_alloc = true;
1423 : : }
1424 : 42 : if (missing_dyn_alloc)
1425 : 4 : error_at (DECL_SOURCE_LOCATION (t),
1426 : : "%<allocate%> directive for %qD inside a target "
1427 : : "region must specify an %<allocator%> clause", t);
1428 : : /* Skip for omp_default_mem_alloc (= 1),
1429 : : unless align is present. */
1430 : 67 : else if (!errorcount
1431 : 67 : && (align != NULL_TREE
1432 : 52 : || alloc == NULL_TREE
1433 : 10 : || !integer_onep (alloc)))
1434 : : {
1435 : : /* Fortran might already use a pointer type internally;
1436 : : use that pointer except for type(C_ptr) and type(C_funptr);
1437 : : note that normal proc pointers are rejected. */
1438 : 50 : tree type = TREE_TYPE (t);
1439 : 50 : tree tmp, v;
1440 : 50 : if (lang_GNU_Fortran ()
1441 : 28 : && POINTER_TYPE_P (type)
1442 : 8 : && TREE_TYPE (type) != void_type_node
1443 : 56 : && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
1444 : : {
1445 : 6 : type = TREE_TYPE (type);
1446 : 6 : v = t;
1447 : : }
1448 : : else
1449 : : {
1450 : 44 : tmp = build_pointer_type (type);
1451 : 44 : v = create_tmp_var (tmp, get_name (t));
1452 : 44 : DECL_IGNORED_P (v) = 0;
1453 : 44 : DECL_ATTRIBUTES (v)
1454 : 44 : = tree_cons (get_identifier ("omp allocate var"),
1455 : : build_tree_list (NULL_TREE, t),
1456 : : remove_attribute ("omp allocate",
1457 : 44 : DECL_ATTRIBUTES (t)));
1458 : 44 : tmp = build_fold_indirect_ref (v);
1459 : 44 : TREE_THIS_NOTRAP (tmp) = 1;
1460 : 44 : SET_DECL_VALUE_EXPR (t, tmp);
1461 : 44 : DECL_HAS_VALUE_EXPR_P (t) = 1;
1462 : : }
1463 : 50 : tree sz = TYPE_SIZE_UNIT (type);
1464 : : /* The size to use in Fortran might not match TYPE_SIZE_UNIT;
1465 : : hence, for some decls, a size variable is saved in the
1466 : : attributes; use it, if available. */
1467 : 50 : if (TREE_CHAIN (TREE_VALUE (attr))
1468 : 28 : && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))
1469 : 56 : && TREE_PURPOSE (
1470 : : TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))))
1471 : : {
1472 : 6 : sz = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1473 : 6 : sz = TREE_PURPOSE (sz);
1474 : : }
1475 : 50 : if (alloc == NULL_TREE)
1476 : 36 : alloc = build_zero_cst (ptr_type_node);
1477 : 50 : if (align == NULL_TREE)
1478 : 42 : align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (t));
1479 : : else
1480 : 8 : align = build_int_cst (size_type_node,
1481 : 8 : MAX (tree_to_uhwi (align),
1482 : : DECL_ALIGN_UNIT (t)));
1483 : 50 : location_t loc = DECL_SOURCE_LOCATION (t);
1484 : 50 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
1485 : 50 : tmp = build_call_expr_loc (loc, tmp, 3, align, sz, alloc);
1486 : 50 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1487 : 50 : fold_convert (TREE_TYPE (v), tmp));
1488 : 50 : gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE);
1489 : : /* Ensure that either TREE_CHAIN (TREE_VALUE (attr) is set
1490 : : and GOMP_FREE added here or that DECL_HAS_VALUE_EXPR_P (t)
1491 : : is set, using in a condition much further below. */
1492 : 56 : gcc_assert (DECL_HAS_VALUE_EXPR_P (t)
1493 : : || TREE_CHAIN (TREE_VALUE (attr)));
1494 : 50 : if (TREE_CHAIN (TREE_VALUE (attr)))
1495 : : {
1496 : : /* Fortran is special as it does not have properly nest
1497 : : declarations in blocks. And as there is no
1498 : : initializer, there is also no expression to look for.
1499 : : Hence, the FE makes the statement list of the
1500 : : try-finally block available. We can put the GOMP_alloc
1501 : : at the top, unless an allocator or size expression
1502 : : requires to put it afterward; note that the size is
1503 : : always later in generated code; for strings, no
1504 : : size expr but still an expr might be available.
1505 : : As LTO does not handle a statement list, 'sl' has
1506 : : to be removed; done so by removing the attribute. */
1507 : 28 : DECL_ATTRIBUTES (t)
1508 : 28 : = remove_attribute ("omp allocate",
1509 : 28 : DECL_ATTRIBUTES (t));
1510 : 28 : tree sl = TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)));
1511 : 28 : tree_stmt_iterator e = tsi_start (sl);
1512 : 28 : tree needle = NULL_TREE;
1513 : 28 : if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1514 : : {
1515 : 6 : needle = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1516 : 6 : needle = (TREE_VALUE (needle) ? TREE_VALUE (needle)
1517 : : : sz);
1518 : : }
1519 : 22 : else if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1520 : : needle = sz;
1521 : 22 : else if (DECL_P (alloc) && DECL_ARTIFICIAL (alloc))
1522 : : needle = alloc;
1523 : :
1524 : 10 : if (needle != NULL_TREE)
1525 : : {
1526 : 49 : while (!tsi_end_p (e))
1527 : : {
1528 : 49 : if (*e == needle
1529 : 49 : || (TREE_CODE (*e) == MODIFY_EXPR
1530 : 49 : && TREE_OPERAND (*e, 0) == needle))
1531 : : break;
1532 : 39 : ++e;
1533 : : }
1534 : 10 : gcc_assert (!tsi_end_p (e));
1535 : : }
1536 : 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1537 : :
1538 : : /* As the cleanup is in BIND_EXPR_BODY, GOMP_free is added
1539 : : here; for C/C++ it will be added in the 'cleanup'
1540 : : section after gimplification. But Fortran already has
1541 : : a try-finally block. */
1542 : 28 : sl = TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)));
1543 : 28 : e = tsi_last (sl);
1544 : 28 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1545 : 28 : tmp = build_call_expr_loc (EXPR_LOCATION (*e), tmp, 2, v,
1546 : : build_zero_cst (ptr_type_node));
1547 : 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1548 : 28 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1549 : 28 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1550 : 28 : fold_convert (TREE_TYPE (v), tmp));
1551 : 28 : ++e;
1552 : 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1553 : : }
1554 : : else
1555 : : {
1556 : 22 : gcc_assert (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1557 : : == STATEMENT_LIST);
1558 : 22 : tree_stmt_iterator e;
1559 : 22 : e = tsi_start (BIND_EXPR_BODY (bind_expr));
1560 : 105 : while (!tsi_end_p (e))
1561 : : {
1562 : 83 : if ((TREE_CODE (*e) == DECL_EXPR
1563 : 54 : && TREE_OPERAND (*e, 0) == t)
1564 : 115 : || (TREE_CODE (*e) == CLEANUP_POINT_EXPR
1565 : 0 : && (TREE_CODE (TREE_OPERAND (*e, 0))
1566 : : == DECL_EXPR)
1567 : 0 : && (TREE_OPERAND (TREE_OPERAND (*e, 0), 0)
1568 : : == t)))
1569 : : break;
1570 : 61 : ++e;
1571 : : }
1572 : 22 : gcc_assert (!tsi_end_p (e));
1573 : 22 : tsi_link_before (&e, tmp, TSI_SAME_STMT);
1574 : : }
1575 : : }
1576 : : }
1577 : :
1578 : : /* Mark variable as local. */
1579 : 5250862 : if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t))
1580 : : {
1581 : 89000 : if (! DECL_SEEN_IN_BIND_EXPR_P (t)
1582 : 89000 : || splay_tree_lookup (ctx->variables,
1583 : : (splay_tree_key) t) == NULL)
1584 : : {
1585 : 89000 : int flag = GOVD_LOCAL;
1586 : 89000 : if (ctx->region_type == ORT_SIMD
1587 : : && TREE_ADDRESSABLE (t)
1588 : 4404 : && !TREE_STATIC (t))
1589 : : {
1590 : 78 : if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST)
1591 : 2 : ctx->add_safelen1 = true;
1592 : : else
1593 : : flag = GOVD_PRIVATE;
1594 : : }
1595 : 89000 : omp_add_variable (ctx, t, flag | GOVD_SEEN);
1596 : : }
1597 : : /* Static locals inside of target construct or offloaded
1598 : : routines need to be "omp declare target". */
1599 : 89000 : if (TREE_STATIC (t))
1600 : 1003 : for (; ctx; ctx = ctx->outer_context)
1601 : 848 : if ((ctx->region_type & ORT_TARGET) != 0)
1602 : : {
1603 : 634 : if (!lookup_attribute ("omp declare target",
1604 : 634 : DECL_ATTRIBUTES (t)))
1605 : : {
1606 : 621 : tree id = get_identifier ("omp declare target");
1607 : 621 : DECL_ATTRIBUTES (t)
1608 : 621 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
1609 : 621 : varpool_node *node = varpool_node::get (t);
1610 : 621 : if (node)
1611 : : {
1612 : 37 : node->offloadable = 1;
1613 : 37 : if (ENABLE_OFFLOADING && !DECL_EXTERNAL (t))
1614 : : {
1615 : : g->have_offload = true;
1616 : : if (!in_lto_p)
1617 : : vec_safe_push (offload_vars, t);
1618 : : }
1619 : : }
1620 : : }
1621 : : break;
1622 : : }
1623 : : }
1624 : :
1625 : 5250862 : DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
1626 : :
1627 : 5250862 : if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
1628 : 1071 : cfun->has_local_explicit_reg_vars = true;
1629 : : }
1630 : : }
1631 : :
1632 : 11072708 : bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
1633 : 5536354 : BIND_EXPR_BLOCK (bind_expr));
1634 : 5536354 : gimple_push_bind_expr (bind_stmt);
1635 : :
1636 : 5536354 : gimplify_ctxp->keep_stack = false;
1637 : 5536354 : gimplify_ctxp->save_stack = false;
1638 : :
1639 : : /* Gimplify the body into the GIMPLE_BIND tuple's body. */
1640 : 5536354 : body = NULL;
1641 : 5536354 : gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
1642 : 5536354 : gimple_bind_set_body (bind_stmt, body);
1643 : :
1644 : : /* Source location wise, the cleanup code (stack_restore and clobbers)
1645 : : belongs to the end of the block, so propagate what we have. The
1646 : : stack_save operation belongs to the beginning of block, which we can
1647 : : infer from the bind_expr directly if the block has no explicit
1648 : : assignment. */
1649 : 5536354 : if (BIND_EXPR_BLOCK (bind_expr))
1650 : : {
1651 : 5407486 : end_locus = BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1652 : 5407486 : start_locus = BLOCK_SOURCE_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1653 : : }
1654 : 5407486 : if (start_locus == 0)
1655 : 5536354 : start_locus = EXPR_LOCATION (bind_expr);
1656 : :
1657 : 5536354 : cleanup = NULL;
1658 : 5536354 : stack_save = NULL;
1659 : :
1660 : : /* Add clobbers for all variables that go out of scope. */
1661 : 11289402 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1662 : : {
1663 : 5753048 : if (VAR_P (t)
1664 : 5250862 : && !is_global_var (t)
1665 : 10809993 : && DECL_CONTEXT (t) == current_function_decl)
1666 : : {
1667 : 5056546 : if (flag_openmp
1668 : 203295 : && DECL_HAS_VALUE_EXPR_P (t)
1669 : 961 : && TREE_USED (t)
1670 : 5057497 : && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1671 : : {
1672 : : /* For Fortran, TREE_CHAIN (TREE_VALUE (attr)) is set, which
1673 : : causes that the GOMP_free call is already added above;
1674 : : and "omp allocate" is removed from DECL_ATTRIBUTES. */
1675 : 22 : tree v = TREE_OPERAND (DECL_VALUE_EXPR (t), 0);
1676 : 22 : tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1677 : 22 : tmp = build_call_expr_loc (end_locus, tmp, 2, v,
1678 : : build_zero_cst (ptr_type_node));
1679 : 22 : gimplify_and_add (tmp, &cleanup);
1680 : 22 : gimple *clobber_stmt;
1681 : 22 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1682 : 22 : clobber_stmt = gimple_build_assign (v, tmp);
1683 : 22 : gimple_set_location (clobber_stmt, end_locus);
1684 : 22 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1685 : : }
1686 : 5056546 : if (!DECL_HARD_REGISTER (t)
1687 : 5055475 : && !TREE_THIS_VOLATILE (t)
1688 : 5015768 : && !DECL_HAS_VALUE_EXPR_P (t)
1689 : : /* Only care for variables that have to be in memory. Others
1690 : : will be rewritten into SSA names, hence moved to the
1691 : : top-level. */
1692 : 4949339 : && !is_gimple_reg (t)
1693 : 6154557 : && flag_stack_reuse != SR_NONE)
1694 : : {
1695 : 1095668 : tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_STORAGE_END);
1696 : 1095668 : gimple *clobber_stmt;
1697 : 1095668 : clobber_stmt = gimple_build_assign (t, clobber);
1698 : 1095668 : gimple_set_location (clobber_stmt, end_locus);
1699 : 1095668 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1700 : : }
1701 : :
1702 : 5056546 : if (flag_openacc && oacc_declare_returns != NULL)
1703 : : {
1704 : 249 : tree key = t;
1705 : 249 : if (DECL_HAS_VALUE_EXPR_P (key))
1706 : : {
1707 : 9 : key = DECL_VALUE_EXPR (key);
1708 : 9 : if (INDIRECT_REF_P (key))
1709 : 9 : key = TREE_OPERAND (key, 0);
1710 : : }
1711 : 249 : tree *c = oacc_declare_returns->get (key);
1712 : 249 : if (c != NULL)
1713 : : {
1714 : 140 : if (ret_clauses)
1715 : 79 : OMP_CLAUSE_CHAIN (*c) = ret_clauses;
1716 : :
1717 : 140 : ret_clauses = unshare_expr (*c);
1718 : :
1719 : 140 : oacc_declare_returns->remove (key);
1720 : :
1721 : 140 : if (oacc_declare_returns->is_empty ())
1722 : : {
1723 : 46 : delete oacc_declare_returns;
1724 : 46 : oacc_declare_returns = NULL;
1725 : : }
1726 : : }
1727 : : }
1728 : : }
1729 : :
1730 : 5753048 : if (asan_poisoned_variables != NULL
1731 : 5753048 : && asan_poisoned_variables->contains (t))
1732 : : {
1733 : 1659 : asan_poisoned_variables->remove (t);
1734 : 1659 : asan_poison_variable (t, true, &cleanup);
1735 : : }
1736 : :
1737 : 5753048 : if (gimplify_ctxp->live_switch_vars != NULL
1738 : 5753048 : && gimplify_ctxp->live_switch_vars->contains (t))
1739 : 55 : gimplify_ctxp->live_switch_vars->remove (t);
1740 : : }
1741 : :
1742 : : /* If the code both contains VLAs and calls alloca, then we cannot reclaim
1743 : : the stack space allocated to the VLAs. */
1744 : 5536354 : if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack)
1745 : : {
1746 : 7835 : gcall *stack_restore;
1747 : :
1748 : : /* Save stack on entry and restore it on exit. Add a try_finally
1749 : : block to achieve this. */
1750 : 7835 : build_stack_save_restore (&stack_save, &stack_restore);
1751 : :
1752 : 7835 : gimple_set_location (stack_save, start_locus);
1753 : 7835 : gimple_set_location (stack_restore, end_locus);
1754 : :
1755 : 7835 : gimplify_seq_add_stmt (&cleanup, stack_restore);
1756 : : }
1757 : :
1758 : 5536354 : if (ret_clauses)
1759 : : {
1760 : 61 : gomp_target *stmt;
1761 : 61 : gimple_stmt_iterator si = gsi_start (cleanup);
1762 : :
1763 : 61 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
1764 : : ret_clauses);
1765 : 61 : gsi_insert_seq_before_without_update (&si, stmt, GSI_NEW_STMT);
1766 : : }
1767 : :
1768 : 5536354 : if (cleanup)
1769 : : {
1770 : 679534 : gtry *gs;
1771 : 679534 : gimple_seq new_body;
1772 : :
1773 : 679534 : new_body = NULL;
1774 : 679534 : gs = gimple_build_try (gimple_bind_body (bind_stmt), cleanup,
1775 : : GIMPLE_TRY_FINALLY);
1776 : :
1777 : 679534 : if (stack_save)
1778 : 7835 : gimplify_seq_add_stmt (&new_body, stack_save);
1779 : 679534 : gimplify_seq_add_stmt (&new_body, gs);
1780 : 679534 : gimple_bind_set_body (bind_stmt, new_body);
1781 : : }
1782 : :
1783 : : /* keep_stack propagates all the way up to the outermost BIND_EXPR. */
1784 : 5536354 : if (!gimplify_ctxp->keep_stack)
1785 : 5521295 : gimplify_ctxp->keep_stack = old_keep_stack;
1786 : 5536354 : gimplify_ctxp->save_stack = old_save_stack;
1787 : :
1788 : 5536354 : gimple_pop_bind_expr ();
1789 : :
1790 : 5536354 : gimplify_seq_add_stmt (pre_p, bind_stmt);
1791 : :
1792 : 5536354 : if (temp)
1793 : : {
1794 : 2235 : *expr_p = temp;
1795 : 2235 : return GS_OK;
1796 : : }
1797 : :
1798 : 5534119 : *expr_p = NULL_TREE;
1799 : 5534119 : return GS_ALL_DONE;
1800 : : }
1801 : :
1802 : : /* Maybe add early return predict statement to PRE_P sequence. */
1803 : :
1804 : : static void
1805 : 1998678 : maybe_add_early_return_predict_stmt (gimple_seq *pre_p)
1806 : : {
1807 : : /* If we are not in a conditional context, add PREDICT statement. */
1808 : 1998678 : if (gimple_conditional_context ())
1809 : : {
1810 : 420658 : gimple *predict = gimple_build_predict (PRED_TREE_EARLY_RETURN,
1811 : : NOT_TAKEN);
1812 : 420658 : gimplify_seq_add_stmt (pre_p, predict);
1813 : : }
1814 : 1998678 : }
1815 : :
1816 : : /* Gimplify a RETURN_EXPR. If the expression to be returned is not a
1817 : : GIMPLE value, it is assigned to a new temporary and the statement is
1818 : : re-written to return the temporary.
1819 : :
1820 : : PRE_P points to the sequence where side effects that must happen before
1821 : : STMT should be stored. */
1822 : :
1823 : : static enum gimplify_status
1824 : 1998678 : gimplify_return_expr (tree stmt, gimple_seq *pre_p)
1825 : : {
1826 : 1998678 : greturn *ret;
1827 : 1998678 : tree ret_expr = TREE_OPERAND (stmt, 0);
1828 : 1998678 : tree result_decl, result;
1829 : :
1830 : 1998678 : if (ret_expr == error_mark_node)
1831 : : return GS_ERROR;
1832 : :
1833 : 1998678 : if (!ret_expr
1834 : 1924718 : || TREE_CODE (ret_expr) == RESULT_DECL)
1835 : : {
1836 : 84646 : maybe_add_early_return_predict_stmt (pre_p);
1837 : 84646 : greturn *ret = gimple_build_return (ret_expr);
1838 : 84646 : copy_warning (ret, stmt);
1839 : 84646 : gimplify_seq_add_stmt (pre_p, ret);
1840 : 84646 : return GS_ALL_DONE;
1841 : : }
1842 : :
1843 : 1914032 : if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
1844 : : result_decl = NULL_TREE;
1845 : 1913773 : else if (TREE_CODE (ret_expr) == COMPOUND_EXPR)
1846 : : {
1847 : : /* Used in C++ for handling EH cleanup of the return value if a local
1848 : : cleanup throws. Assume the front-end knows what it's doing. */
1849 : 3868 : result_decl = DECL_RESULT (current_function_decl);
1850 : : /* But crash if we end up trying to modify ret_expr below. */
1851 : 3868 : ret_expr = NULL_TREE;
1852 : : }
1853 : : else
1854 : : {
1855 : 1909905 : result_decl = TREE_OPERAND (ret_expr, 0);
1856 : :
1857 : : /* See through a return by reference. */
1858 : 1909905 : if (INDIRECT_REF_P (result_decl))
1859 : 32150 : result_decl = TREE_OPERAND (result_decl, 0);
1860 : :
1861 : 1909905 : gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
1862 : : || TREE_CODE (ret_expr) == INIT_EXPR)
1863 : : && TREE_CODE (result_decl) == RESULT_DECL);
1864 : : }
1865 : :
1866 : : /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
1867 : : Recall that aggregate_value_p is FALSE for any aggregate type that is
1868 : : returned in registers. If we're returning values in registers, then
1869 : : we don't want to extend the lifetime of the RESULT_DECL, particularly
1870 : : across another call. In addition, for those aggregates for which
1871 : : hard_function_value generates a PARALLEL, we'll die during normal
1872 : : expansion of structure assignments; there's special code in expand_return
1873 : : to handle this case that does not exist in expand_expr. */
1874 : 3868 : if (!result_decl)
1875 : : result = NULL_TREE;
1876 : 1913773 : else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
1877 : : {
1878 : 158053 : if (!poly_int_tree_p (DECL_SIZE (result_decl)))
1879 : : {
1880 : 36 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
1881 : 0 : gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
1882 : : /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
1883 : : should be effectively allocated by the caller, i.e. all calls to
1884 : : this function must be subject to the Return Slot Optimization. */
1885 : 36 : gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
1886 : 36 : gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
1887 : : }
1888 : : result = result_decl;
1889 : : }
1890 : 1755720 : else if (gimplify_ctxp->return_temp)
1891 : : result = gimplify_ctxp->return_temp;
1892 : : else
1893 : : {
1894 : 1294357 : result = create_tmp_reg (TREE_TYPE (result_decl));
1895 : :
1896 : : /* ??? With complex control flow (usually involving abnormal edges),
1897 : : we can wind up warning about an uninitialized value for this. Due
1898 : : to how this variable is constructed and initialized, this is never
1899 : : true. Give up and never warn. */
1900 : 1294357 : suppress_warning (result, OPT_Wuninitialized);
1901 : :
1902 : 1294357 : gimplify_ctxp->return_temp = result;
1903 : : }
1904 : :
1905 : : /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
1906 : : Then gimplify the whole thing. */
1907 : 1914032 : if (result != result_decl)
1908 : 1755720 : TREE_OPERAND (ret_expr, 0) = result;
1909 : :
1910 : 1914032 : gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
1911 : :
1912 : 1914032 : maybe_add_early_return_predict_stmt (pre_p);
1913 : 1914032 : ret = gimple_build_return (result);
1914 : 1914032 : copy_warning (ret, stmt);
1915 : 1914032 : gimplify_seq_add_stmt (pre_p, ret);
1916 : :
1917 : 1914032 : return GS_ALL_DONE;
1918 : : }
1919 : :
1920 : : /* Gimplify a variable-length array DECL. */
1921 : :
1922 : : static void
1923 : 8904 : gimplify_vla_decl (tree decl, gimple_seq *seq_p)
1924 : : {
1925 : : /* This is a variable-sized decl. Simplify its size and mark it
1926 : : for deferred expansion. */
1927 : 8904 : tree t, addr, ptr_type;
1928 : :
1929 : 8904 : gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
1930 : 8904 : gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
1931 : :
1932 : : /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */
1933 : 8904 : if (DECL_HAS_VALUE_EXPR_P (decl))
1934 : : return;
1935 : :
1936 : : /* All occurrences of this decl in final gimplified code will be
1937 : : replaced by indirection. Setting DECL_VALUE_EXPR does two
1938 : : things: First, it lets the rest of the gimplifier know what
1939 : : replacement to use. Second, it lets the debug info know
1940 : : where to find the value. */
1941 : 8899 : ptr_type = build_pointer_type (TREE_TYPE (decl));
1942 : 8899 : addr = create_tmp_var (ptr_type, get_name (decl));
1943 : 8899 : DECL_IGNORED_P (addr) = 0;
1944 : 8899 : t = build_fold_indirect_ref (addr);
1945 : 8899 : TREE_THIS_NOTRAP (t) = 1;
1946 : 8899 : SET_DECL_VALUE_EXPR (decl, t);
1947 : 8899 : DECL_HAS_VALUE_EXPR_P (decl) = 1;
1948 : :
1949 : 8899 : t = build_alloca_call_expr (DECL_SIZE_UNIT (decl), DECL_ALIGN (decl),
1950 : 8899 : max_int_size_in_bytes (TREE_TYPE (decl)));
1951 : : /* The call has been built for a variable-sized object. */
1952 : 8899 : CALL_ALLOCA_FOR_VAR_P (t) = 1;
1953 : 8899 : t = fold_convert (ptr_type, t);
1954 : 8899 : t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
1955 : :
1956 : 8899 : gimplify_and_add (t, seq_p);
1957 : :
1958 : : /* Record the dynamic allocation associated with DECL if requested. */
1959 : 8899 : if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
1960 : 0 : record_dynamic_alloc (decl);
1961 : : }
1962 : :
1963 : : /* A helper function to be called via walk_tree. Mark all labels under *TP
1964 : : as being forced. To be called for DECL_INITIAL of static variables. */
1965 : :
1966 : : static tree
1967 : 801337 : force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1968 : : {
1969 : 801337 : if (TYPE_P (*tp))
1970 : 0 : *walk_subtrees = 0;
1971 : 801337 : if (TREE_CODE (*tp) == LABEL_DECL)
1972 : : {
1973 : 934 : FORCED_LABEL (*tp) = 1;
1974 : 934 : cfun->has_forced_label_in_static = 1;
1975 : : }
1976 : :
1977 : 801337 : return NULL_TREE;
1978 : : }
1979 : :
1980 : : /* Generate an initialization to automatic variable DECL based on INIT_TYPE.
1981 : : Build a call to internal const function DEFERRED_INIT:
1982 : : 1st argument: SIZE of the DECL;
1983 : : 2nd argument: INIT_TYPE;
1984 : : 3rd argument: NAME of the DECL;
1985 : :
1986 : : as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL). */
1987 : :
1988 : : static void
1989 : 660 : gimple_add_init_for_auto_var (tree decl,
1990 : : enum auto_init_type init_type,
1991 : : gimple_seq *seq_p)
1992 : : {
1993 : 660 : gcc_assert (auto_var_p (decl));
1994 : 660 : gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
1995 : 660 : location_t loc = EXPR_LOCATION (decl);
1996 : 660 : tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
1997 : :
1998 : 660 : tree init_type_node
1999 : 660 : = build_int_cst (integer_type_node, (int) init_type);
2000 : :
2001 : 660 : tree decl_name = NULL_TREE;
2002 : 660 : if (DECL_NAME (decl))
2003 : :
2004 : 656 : decl_name = build_string_literal (DECL_NAME (decl));
2005 : :
2006 : : else
2007 : : {
2008 : 4 : char decl_name_anonymous[3 + (HOST_BITS_PER_INT + 2) / 3];
2009 : 4 : sprintf (decl_name_anonymous, "D.%u", DECL_UID (decl));
2010 : 4 : decl_name = build_string_literal (decl_name_anonymous);
2011 : : }
2012 : :
2013 : 660 : tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT,
2014 : 660 : TREE_TYPE (decl), 3,
2015 : : decl_size, init_type_node,
2016 : : decl_name);
2017 : :
2018 : 660 : gimplify_assign (decl, call, seq_p);
2019 : 660 : }
2020 : :
2021 : : /* Generate padding initialization for automatic vairable DECL.
2022 : : C guarantees that brace-init with fewer initializers than members
2023 : : aggregate will initialize the rest of the aggregate as-if it were
2024 : : static initialization. In turn static initialization guarantees
2025 : : that padding is initialized to zero. So, we always initialize paddings
2026 : : to zeroes regardless INIT_TYPE.
2027 : : To do the padding initialization, we insert a call to
2028 : : __builtin_clear_padding (&decl, 0, for_auto_init = true).
2029 : : Note, we add an additional dummy argument for __builtin_clear_padding,
2030 : : 'for_auto_init' to distinguish whether this call is for automatic
2031 : : variable initialization or not.
2032 : : */
2033 : : static void
2034 : 131 : gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
2035 : : gimple_seq *seq_p)
2036 : : {
2037 : 131 : tree addr_of_decl = NULL_TREE;
2038 : 131 : tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
2039 : :
2040 : 131 : if (is_vla)
2041 : : {
2042 : : /* The temporary address variable for this vla should be
2043 : : created in gimplify_vla_decl. */
2044 : 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
2045 : 0 : gcc_assert (INDIRECT_REF_P (DECL_VALUE_EXPR (decl)));
2046 : 0 : addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
2047 : : }
2048 : : else
2049 : : {
2050 : 131 : mark_addressable (decl);
2051 : 131 : addr_of_decl = build_fold_addr_expr (decl);
2052 : : }
2053 : :
2054 : 131 : gimple *call = gimple_build_call (fn, 2, addr_of_decl,
2055 : 131 : build_one_cst (TREE_TYPE (addr_of_decl)));
2056 : 131 : gimplify_seq_add_stmt (seq_p, call);
2057 : 131 : }
2058 : :
2059 : : /* Return true if the DECL need to be automaticly initialized by the
2060 : : compiler. */
2061 : : static bool
2062 : 3168734 : is_var_need_auto_init (tree decl)
2063 : : {
2064 : 3168734 : if (auto_var_p (decl)
2065 : 3082463 : && (TREE_CODE (decl) != VAR_DECL
2066 : 3081752 : || !DECL_HARD_REGISTER (decl))
2067 : 3081776 : && (flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
2068 : 719 : && (!lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl)))
2069 : 709 : && !OPAQUE_TYPE_P (TREE_TYPE (decl))
2070 : 3169443 : && !is_empty_type (TREE_TYPE (decl)))
2071 : : return true;
2072 : : return false;
2073 : : }
2074 : :
2075 : : /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
2076 : : and initialization explicit. */
2077 : :
2078 : : static enum gimplify_status
2079 : 6168315 : gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
2080 : : {
2081 : 6168315 : tree stmt = *stmt_p;
2082 : 6168315 : tree decl = DECL_EXPR_DECL (stmt);
2083 : :
2084 : 6168315 : *stmt_p = NULL_TREE;
2085 : :
2086 : 6168315 : if (TREE_TYPE (decl) == error_mark_node)
2087 : : return GS_ERROR;
2088 : :
2089 : 6168247 : if ((TREE_CODE (decl) == TYPE_DECL
2090 : 6129901 : || VAR_P (decl))
2091 : 12295156 : && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
2092 : : {
2093 : 626189 : gimplify_type_sizes (TREE_TYPE (decl), seq_p);
2094 : 626189 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
2095 : 17928 : gimplify_type_sizes (TREE_TYPE (TREE_TYPE (decl)), seq_p);
2096 : : }
2097 : :
2098 : : /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
2099 : : in case its size expressions contain problematic nodes like CALL_EXPR. */
2100 : 6168247 : if (TREE_CODE (decl) == TYPE_DECL
2101 : 38346 : && DECL_ORIGINAL_TYPE (decl)
2102 : 6173550 : && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
2103 : : {
2104 : 0 : gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
2105 : 0 : if (TREE_CODE (DECL_ORIGINAL_TYPE (decl)) == REFERENCE_TYPE)
2106 : 0 : gimplify_type_sizes (TREE_TYPE (DECL_ORIGINAL_TYPE (decl)), seq_p);
2107 : : }
2108 : :
2109 : 6168247 : if (VAR_P (decl) && !DECL_EXTERNAL (decl))
2110 : : {
2111 : 6126909 : tree init = DECL_INITIAL (decl);
2112 : 6126909 : bool is_vla = false;
2113 : : /* Check whether a decl has FE created VALUE_EXPR here BEFORE
2114 : : gimplify_vla_decl creates VALUE_EXPR for a vla decl.
2115 : : If the decl has VALUE_EXPR that was created by FE (usually
2116 : : C++FE), it's a proxy varaible, and FE already initialized
2117 : : the VALUE_EXPR of it, we should not initialize it anymore. */
2118 : 6126909 : bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
2119 : :
2120 : 6126909 : poly_uint64 size;
2121 : 6126909 : if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
2122 : 6126909 : || (!TREE_STATIC (decl)
2123 : 6009458 : && flag_stack_check == GENERIC_STACK_CHECK
2124 : 228 : && maybe_gt (size,
2125 : : (unsigned HOST_WIDE_INT) STACK_CHECK_MAX_VAR_SIZE)))
2126 : : {
2127 : 8786 : gimplify_vla_decl (decl, seq_p);
2128 : 8786 : is_vla = true;
2129 : : }
2130 : :
2131 : 6126909 : if (asan_poisoned_variables
2132 : 4148 : && !is_vla
2133 : : && TREE_ADDRESSABLE (decl)
2134 : 3962 : && !TREE_STATIC (decl)
2135 : 1702 : && !DECL_HAS_VALUE_EXPR_P (decl)
2136 : 1667 : && DECL_ALIGN (decl) <= MAX_SUPPORTED_STACK_ALIGNMENT
2137 : 1667 : && dbg_cnt (asan_use_after_scope)
2138 : 1667 : && !gimplify_omp_ctxp
2139 : : /* GNAT introduces temporaries to hold return values of calls in
2140 : : initializers of variables defined in other units, so the
2141 : : declaration of the variable is discarded completely. We do not
2142 : : want to issue poison calls for such dropped variables. */
2143 : 6128568 : && (DECL_SEEN_IN_BIND_EXPR_P (decl)
2144 : 0 : || (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)))
2145 : : {
2146 : 1659 : asan_poisoned_variables->add (decl);
2147 : 1659 : asan_poison_variable (decl, false, seq_p);
2148 : 1659 : if (!DECL_ARTIFICIAL (decl) && gimplify_ctxp->live_switch_vars)
2149 : 55 : gimplify_ctxp->live_switch_vars->add (decl);
2150 : : }
2151 : :
2152 : : /* Some front ends do not explicitly declare all anonymous
2153 : : artificial variables. We compensate here by declaring the
2154 : : variables, though it would be better if the front ends would
2155 : : explicitly declare them. */
2156 : 6126909 : if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
2157 : 6126909 : && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
2158 : 14277 : gimple_add_tmp_var (decl);
2159 : :
2160 : 6126909 : if (init && init != error_mark_node)
2161 : : {
2162 : 3591037 : if (!TREE_STATIC (decl))
2163 : : {
2164 : 3562333 : DECL_INITIAL (decl) = NULL_TREE;
2165 : 3562333 : init = build2 (INIT_EXPR, void_type_node, decl, init);
2166 : 3562333 : gimplify_and_add (init, seq_p);
2167 : 3562333 : ggc_free (init);
2168 : : /* Clear TREE_READONLY if we really have an initialization. */
2169 : 3562333 : if (!DECL_INITIAL (decl)
2170 : 3562333 : && !omp_privatize_by_reference (decl))
2171 : 3550145 : TREE_READONLY (decl) = 0;
2172 : : }
2173 : : else
2174 : : /* We must still examine initializers for static variables
2175 : : as they may contain a label address. */
2176 : 28704 : walk_tree (&init, force_labels_r, NULL, NULL);
2177 : : }
2178 : : /* When there is no explicit initializer, if the user requested,
2179 : : We should insert an artifical initializer for this automatic
2180 : : variable. */
2181 : 2535872 : else if (is_var_need_auto_init (decl)
2182 : 2535872 : && !decl_had_value_expr_p)
2183 : : {
2184 : 660 : gimple_add_init_for_auto_var (decl,
2185 : : flag_auto_var_init,
2186 : : seq_p);
2187 : : /* The expanding of a call to the above .DEFERRED_INIT will apply
2188 : : block initialization to the whole space covered by this variable.
2189 : : As a result, all the paddings will be initialized to zeroes
2190 : : for zero initialization and 0xFE byte-repeatable patterns for
2191 : : pattern initialization.
2192 : : In order to make the paddings as zeroes for pattern init, We
2193 : : should add a call to __builtin_clear_padding to clear the
2194 : : paddings to zero in compatiple with CLANG.
2195 : : We cannot insert this call if the variable is a gimple register
2196 : : since __builtin_clear_padding will take the address of the
2197 : : variable. As a result, if a long double/_Complex long double
2198 : : variable will spilled into stack later, its padding is 0XFE. */
2199 : 660 : if (flag_auto_var_init == AUTO_INIT_PATTERN
2200 : 216 : && !is_gimple_reg (decl)
2201 : 774 : && clear_padding_type_may_have_padding_p (TREE_TYPE (decl)))
2202 : 87 : gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
2203 : : }
2204 : : }
2205 : :
2206 : : return GS_ALL_DONE;
2207 : : }
2208 : :
2209 : : /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
2210 : : and replacing the LOOP_EXPR with goto, but if the loop contains an
2211 : : EXIT_EXPR, we need to append a label for it to jump to. */
2212 : :
2213 : : static enum gimplify_status
2214 : 156567 : gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
2215 : : {
2216 : 156567 : tree saved_label = gimplify_ctxp->exit_label;
2217 : 156567 : tree start_label = create_artificial_label (UNKNOWN_LOCATION);
2218 : :
2219 : 156567 : gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
2220 : :
2221 : 156567 : gimplify_ctxp->exit_label = NULL_TREE;
2222 : :
2223 : 156567 : gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
2224 : :
2225 : 156567 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
2226 : :
2227 : 156567 : if (gimplify_ctxp->exit_label)
2228 : 6182 : gimplify_seq_add_stmt (pre_p,
2229 : 3091 : gimple_build_label (gimplify_ctxp->exit_label));
2230 : :
2231 : 156567 : gimplify_ctxp->exit_label = saved_label;
2232 : :
2233 : 156567 : *expr_p = NULL;
2234 : 156567 : return GS_ALL_DONE;
2235 : : }
2236 : :
2237 : : /* Gimplify a statement list onto a sequence. These may be created either
2238 : : by an enlightened front-end, or by shortcut_cond_expr. */
2239 : :
2240 : : static enum gimplify_status
2241 : 8105341 : gimplify_statement_list (tree *expr_p, gimple_seq *pre_p)
2242 : : {
2243 : 8105341 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
2244 : :
2245 : 8105341 : tree_stmt_iterator i = tsi_start (*expr_p);
2246 : :
2247 : 51119506 : while (!tsi_end_p (i))
2248 : : {
2249 : 34908824 : gimplify_stmt (tsi_stmt_ptr (i), pre_p);
2250 : 34908824 : tsi_delink (&i);
2251 : : }
2252 : :
2253 : 8105341 : if (temp)
2254 : : {
2255 : 15281 : *expr_p = temp;
2256 : 15281 : return GS_OK;
2257 : : }
2258 : :
2259 : : return GS_ALL_DONE;
2260 : : }
2261 : :
2262 : :
2263 : : /* Emit warning for the unreachable statment STMT if needed.
2264 : : Return the gimple itself when the warning is emitted, otherwise
2265 : : return NULL. */
2266 : : static gimple *
2267 : 227 : emit_warn_switch_unreachable (gimple *stmt)
2268 : : {
2269 : 227 : if (gimple_code (stmt) == GIMPLE_GOTO
2270 : 56 : && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL
2271 : 283 : && DECL_ARTIFICIAL (gimple_goto_dest (stmt)))
2272 : : /* Don't warn for compiler-generated gotos. These occur
2273 : : in Duff's devices, for example. */
2274 : : return NULL;
2275 : 171 : else if ((flag_auto_var_init > AUTO_INIT_UNINITIALIZED)
2276 : 171 : && ((gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2277 : 6 : || (gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
2278 : 2 : && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
2279 : 4 : || (is_gimple_assign (stmt)
2280 : 4 : && gimple_assign_single_p (stmt)
2281 : 4 : && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
2282 : 4 : && gimple_call_internal_p (
2283 : 4 : SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)),
2284 : : IFN_DEFERRED_INIT))))
2285 : : /* Don't warn for compiler-generated initializations for
2286 : : -ftrivial-auto-var-init.
2287 : : There are 3 cases:
2288 : : case 1: a call to .DEFERRED_INIT;
2289 : : case 2: a call to __builtin_clear_padding with the 2nd argument is
2290 : : present and non-zero;
2291 : : case 3: a gimple assign store right after the call to .DEFERRED_INIT
2292 : : that has the LHS of .DEFERRED_INIT as the RHS as following:
2293 : : _1 = .DEFERRED_INIT (4, 2, &"i1"[0]);
2294 : : i1 = _1. */
2295 : 12 : return NULL;
2296 : : else
2297 : 159 : warning_at (gimple_location (stmt), OPT_Wswitch_unreachable,
2298 : : "statement will never be executed");
2299 : 159 : return stmt;
2300 : : }
2301 : :
2302 : : /* Callback for walk_gimple_seq. */
2303 : :
2304 : : static tree
2305 : 47545 : warn_switch_unreachable_and_auto_init_r (gimple_stmt_iterator *gsi_p,
2306 : : bool *handled_ops_p,
2307 : : struct walk_stmt_info *wi)
2308 : : {
2309 : 47545 : gimple *stmt = gsi_stmt (*gsi_p);
2310 : 47545 : bool unreachable_issued = wi->info != NULL;
2311 : :
2312 : 47545 : *handled_ops_p = true;
2313 : 47545 : switch (gimple_code (stmt))
2314 : : {
2315 : 138 : case GIMPLE_TRY:
2316 : : /* A compiler-generated cleanup or a user-written try block.
2317 : : If it's empty, don't dive into it--that would result in
2318 : : worse location info. */
2319 : 138 : if (gimple_try_eval (stmt) == NULL)
2320 : : {
2321 : 4 : if (warn_switch_unreachable && !unreachable_issued)
2322 : 4 : wi->info = emit_warn_switch_unreachable (stmt);
2323 : :
2324 : : /* Stop when auto var init warning is not on. */
2325 : 4 : if (!warn_trivial_auto_var_init)
2326 : 4 : return integer_zero_node;
2327 : : }
2328 : : /* Fall through. */
2329 : 2345 : case GIMPLE_BIND:
2330 : 2345 : case GIMPLE_CATCH:
2331 : 2345 : case GIMPLE_EH_FILTER:
2332 : 2345 : case GIMPLE_TRANSACTION:
2333 : : /* Walk the sub-statements. */
2334 : 2345 : *handled_ops_p = false;
2335 : 2345 : break;
2336 : :
2337 : : case GIMPLE_DEBUG:
2338 : : /* Ignore these. We may generate them before declarations that
2339 : : are never executed. If there's something to warn about,
2340 : : there will be non-debug stmts too, and we'll catch those. */
2341 : : break;
2342 : :
2343 : 44168 : case GIMPLE_LABEL:
2344 : : /* Stop till the first Label. */
2345 : 44168 : return integer_zero_node;
2346 : 47 : case GIMPLE_CALL:
2347 : 47 : if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2348 : : {
2349 : 8 : *handled_ops_p = false;
2350 : 8 : break;
2351 : : }
2352 : 39 : if (warn_trivial_auto_var_init
2353 : 14 : && flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2354 : 53 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2355 : : {
2356 : : /* Get the variable name from the 3rd argument of call. */
2357 : 12 : tree var_name = gimple_call_arg (stmt, 2);
2358 : 12 : var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0);
2359 : 12 : const char *var_name_str = TREE_STRING_POINTER (var_name);
2360 : :
2361 : 12 : warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init,
2362 : : "%qs cannot be initialized with"
2363 : : "%<-ftrivial-auto-var_init%>",
2364 : : var_name_str);
2365 : 12 : break;
2366 : : }
2367 : :
2368 : : /* Fall through. */
2369 : 223 : default:
2370 : : /* check the first "real" statement (not a decl/lexical scope/...), issue
2371 : : warning if needed. */
2372 : 223 : if (warn_switch_unreachable && !unreachable_issued)
2373 : 223 : wi->info = emit_warn_switch_unreachable (stmt);
2374 : : /* Stop when auto var init warning is not on. */
2375 : 223 : if (!warn_trivial_auto_var_init)
2376 : 217 : return integer_zero_node;
2377 : : break;
2378 : : }
2379 : : return NULL_TREE;
2380 : : }
2381 : :
2382 : :
2383 : : /* Possibly warn about unreachable statements between switch's controlling
2384 : : expression and the first case. Also warn about -ftrivial-auto-var-init
2385 : : cannot initialize the auto variable under such situation.
2386 : : SEQ is the body of a switch expression. */
2387 : :
2388 : : static void
2389 : 48049 : maybe_warn_switch_unreachable_and_auto_init (gimple_seq seq)
2390 : : {
2391 : 69 : if ((!warn_switch_unreachable && !warn_trivial_auto_var_init)
2392 : : /* This warning doesn't play well with Fortran when optimizations
2393 : : are on. */
2394 : 47980 : || lang_GNU_Fortran ()
2395 : 92585 : || seq == NULL)
2396 : 3657 : return;
2397 : :
2398 : 44392 : struct walk_stmt_info wi;
2399 : :
2400 : 44392 : memset (&wi, 0, sizeof (wi));
2401 : 44392 : walk_gimple_seq (seq, warn_switch_unreachable_and_auto_init_r, NULL, &wi);
2402 : : }
2403 : :
2404 : :
2405 : : /* A label entry that pairs label and a location. */
2406 : : struct label_entry
2407 : : {
2408 : : tree label;
2409 : : location_t loc;
2410 : : };
2411 : :
2412 : : /* Find LABEL in vector of label entries VEC. */
2413 : :
2414 : : static struct label_entry *
2415 : 12607 : find_label_entry (const auto_vec<struct label_entry> *vec, tree label)
2416 : : {
2417 : 12607 : unsigned int i;
2418 : 12607 : struct label_entry *l;
2419 : :
2420 : 24502 : FOR_EACH_VEC_ELT (*vec, i, l)
2421 : 21022 : if (l->label == label)
2422 : 9127 : return l;
2423 : : return NULL;
2424 : : }
2425 : :
2426 : : /* Return true if LABEL, a LABEL_DECL, represents a case label
2427 : : in a vector of labels CASES. */
2428 : :
2429 : : static bool
2430 : 15661 : case_label_p (const vec<tree> *cases, tree label)
2431 : : {
2432 : 15661 : unsigned int i;
2433 : 15661 : tree l;
2434 : :
2435 : 157316 : FOR_EACH_VEC_ELT (*cases, i, l)
2436 : 156889 : if (CASE_LABEL (l) == label)
2437 : : return true;
2438 : : return false;
2439 : : }
2440 : :
2441 : : /* Find the last nondebug statement in a scope STMT. */
2442 : :
2443 : : static gimple *
2444 : 2302 : last_stmt_in_scope (gimple *stmt)
2445 : : {
2446 : 4320 : if (!stmt)
2447 : : return NULL;
2448 : :
2449 : 4307 : switch (gimple_code (stmt))
2450 : : {
2451 : 1568 : case GIMPLE_BIND:
2452 : 1568 : {
2453 : 1568 : gbind *bind = as_a <gbind *> (stmt);
2454 : 1568 : stmt = gimple_seq_last_nondebug_stmt (gimple_bind_body (bind));
2455 : 1568 : return last_stmt_in_scope (stmt);
2456 : : }
2457 : :
2458 : 633 : case GIMPLE_TRY:
2459 : 633 : {
2460 : 633 : gtry *try_stmt = as_a <gtry *> (stmt);
2461 : 633 : stmt = gimple_seq_last_nondebug_stmt (gimple_try_eval (try_stmt));
2462 : 633 : gimple *last_eval = last_stmt_in_scope (stmt);
2463 : 633 : if (gimple_stmt_may_fallthru (last_eval)
2464 : 469 : && (last_eval == NULL
2465 : 466 : || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH))
2466 : 1095 : && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
2467 : : {
2468 : 450 : stmt = gimple_seq_last_nondebug_stmt (gimple_try_cleanup (try_stmt));
2469 : 450 : return last_stmt_in_scope (stmt);
2470 : : }
2471 : : else
2472 : : return last_eval;
2473 : : }
2474 : :
2475 : 0 : case GIMPLE_DEBUG:
2476 : 0 : gcc_unreachable ();
2477 : :
2478 : : default:
2479 : : return stmt;
2480 : : }
2481 : : }
2482 : :
2483 : : /* Collect labels that may fall through into LABELS and return the statement
2484 : : preceding another case label, or a user-defined label. Store a location
2485 : : useful to give warnings at *PREVLOC (usually the location of the returned
2486 : : statement or of its surrounding scope). */
2487 : :
2488 : : static gimple *
2489 : 20532 : collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
2490 : : auto_vec <struct label_entry> *labels,
2491 : : location_t *prevloc)
2492 : : {
2493 : 20532 : gimple *prev = NULL;
2494 : :
2495 : 20532 : *prevloc = UNKNOWN_LOCATION;
2496 : 103147 : do
2497 : : {
2498 : 103147 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND)
2499 : : {
2500 : : /* Recognize the special GIMPLE_BIND added by gimplify_switch_expr,
2501 : : which starts on a GIMPLE_SWITCH and ends with a break label.
2502 : : Handle that as a single statement that can fall through. */
2503 : 1675 : gbind *bind = as_a <gbind *> (gsi_stmt (*gsi_p));
2504 : 1675 : gimple *first = gimple_seq_first_stmt (gimple_bind_body (bind));
2505 : 1675 : gimple *last = gimple_seq_last_stmt (gimple_bind_body (bind));
2506 : 1665 : if (last
2507 : 1665 : && gimple_code (first) == GIMPLE_SWITCH
2508 : 1816 : && gimple_code (last) == GIMPLE_LABEL)
2509 : : {
2510 : 151 : tree label = gimple_label_label (as_a <glabel *> (last));
2511 : 151 : if (SWITCH_BREAK_LABEL_P (label))
2512 : : {
2513 : 151 : prev = bind;
2514 : 151 : gsi_next (gsi_p);
2515 : 151 : continue;
2516 : : }
2517 : : }
2518 : : }
2519 : 102996 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
2520 : 102996 : || gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
2521 : : {
2522 : : /* Nested scope. Only look at the last statement of
2523 : : the innermost scope. */
2524 : 1669 : location_t bind_loc = gimple_location (gsi_stmt (*gsi_p));
2525 : 1669 : gimple *last = last_stmt_in_scope (gsi_stmt (*gsi_p));
2526 : 1669 : if (last)
2527 : : {
2528 : 1659 : prev = last;
2529 : : /* It might be a label without a location. Use the
2530 : : location of the scope then. */
2531 : 1659 : if (!gimple_has_location (prev))
2532 : 715 : *prevloc = bind_loc;
2533 : : }
2534 : 1669 : gsi_next (gsi_p);
2535 : 1669 : continue;
2536 : 1669 : }
2537 : :
2538 : : /* Ifs are tricky. */
2539 : 101327 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
2540 : : {
2541 : 7370 : gcond *cond_stmt = as_a <gcond *> (gsi_stmt (*gsi_p));
2542 : 7370 : tree false_lab = gimple_cond_false_label (cond_stmt);
2543 : 7370 : location_t if_loc = gimple_location (cond_stmt);
2544 : :
2545 : : /* If we have e.g.
2546 : : if (i > 1) goto <D.2259>; else goto D;
2547 : : we can't do much with the else-branch. */
2548 : 7370 : if (!DECL_ARTIFICIAL (false_lab))
2549 : : break;
2550 : :
2551 : : /* Go on until the false label, then one step back. */
2552 : 59327 : for (; !gsi_end_p (*gsi_p); gsi_next (gsi_p))
2553 : : {
2554 : 59327 : gimple *stmt = gsi_stmt (*gsi_p);
2555 : 59327 : if (gimple_code (stmt) == GIMPLE_LABEL
2556 : 59327 : && gimple_label_label (as_a <glabel *> (stmt)) == false_lab)
2557 : : break;
2558 : : }
2559 : :
2560 : : /* Not found? Oops. */
2561 : 7370 : if (gsi_end_p (*gsi_p))
2562 : : break;
2563 : :
2564 : : /* A dead label can't fall through. */
2565 : 7370 : if (!UNUSED_LABEL_P (false_lab))
2566 : : {
2567 : 7323 : struct label_entry l = { false_lab, if_loc };
2568 : 7323 : labels->safe_push (l);
2569 : : }
2570 : :
2571 : : /* Go to the last statement of the then branch. */
2572 : 7370 : gsi_prev (gsi_p);
2573 : :
2574 : : /* if (i != 0) goto <D.1759>; else goto <D.1760>;
2575 : : <D.1759>:
2576 : : <stmt>;
2577 : : goto <D.1761>;
2578 : : <D.1760>:
2579 : : */
2580 : 7370 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2581 : 7370 : && !gimple_has_location (gsi_stmt (*gsi_p)))
2582 : : {
2583 : : /* Look at the statement before, it might be
2584 : : attribute fallthrough, in which case don't warn. */
2585 : 1627 : gsi_prev (gsi_p);
2586 : 1627 : bool fallthru_before_dest
2587 : 1627 : = gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
2588 : 1627 : gsi_next (gsi_p);
2589 : 1627 : tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
2590 : 1627 : if (!fallthru_before_dest)
2591 : : {
2592 : 1558 : struct label_entry l = { goto_dest, if_loc };
2593 : 1558 : labels->safe_push (l);
2594 : : }
2595 : : }
2596 : : /* This case is about
2597 : : if (1 != 0) goto <D.2022>; else goto <D.2023>;
2598 : : <D.2022>:
2599 : : n = n + 1; // #1
2600 : : <D.2023>: // #2
2601 : : <D.1988>: // #3
2602 : : where #2 is UNUSED_LABEL_P and we want to warn about #1 falling
2603 : : through to #3. So set PREV to #1. */
2604 : 5743 : else if (UNUSED_LABEL_P (false_lab))
2605 : 47 : prev = gsi_stmt (*gsi_p);
2606 : :
2607 : : /* And move back. */
2608 : 7370 : gsi_next (gsi_p);
2609 : : }
2610 : :
2611 : : /* Remember the last statement. Skip labels that are of no interest
2612 : : to us. */
2613 : 101327 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2614 : : {
2615 : 12336 : tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (*gsi_p)));
2616 : 12336 : if (find_label_entry (labels, label))
2617 : 75553 : prev = gsi_stmt (*gsi_p);
2618 : : }
2619 : 88991 : else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
2620 : : ;
2621 : 88991 : else if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_PREDICT)
2622 : : ;
2623 : 87761 : else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
2624 : 75553 : prev = gsi_stmt (*gsi_p);
2625 : 101327 : gsi_next (gsi_p);
2626 : : }
2627 : 103147 : while (!gsi_end_p (*gsi_p)
2628 : : /* Stop if we find a case or a user-defined label. */
2629 : 206294 : && (gimple_code (gsi_stmt (*gsi_p)) != GIMPLE_LABEL
2630 : 21389 : || !gimple_has_location (gsi_stmt (*gsi_p))));
2631 : :
2632 : 20532 : if (prev && gimple_has_location (prev))
2633 : 20019 : *prevloc = gimple_location (prev);
2634 : 20532 : return prev;
2635 : : }
2636 : :
2637 : : /* Return true if the switch fallthough warning should occur. LABEL is
2638 : : the label statement that we're falling through to. */
2639 : :
2640 : : static bool
2641 : 16415 : should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
2642 : : {
2643 : 16415 : gimple_stmt_iterator gsi = *gsi_p;
2644 : :
2645 : : /* Don't warn if the label is marked with a "falls through" comment. */
2646 : 16415 : if (FALLTHROUGH_LABEL_P (label))
2647 : : return false;
2648 : :
2649 : : /* Don't warn for non-case labels followed by a statement:
2650 : : case 0:
2651 : : foo ();
2652 : : label:
2653 : : bar ();
2654 : : as these are likely intentional. */
2655 : 15332 : if (!case_label_p (&gimplify_ctxp->case_labels, label))
2656 : : {
2657 : : tree l;
2658 : 427 : while (!gsi_end_p (gsi)
2659 : 417 : && gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2660 : 329 : && (l = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi))))
2661 : 756 : && !case_label_p (&gimplify_ctxp->case_labels, l))
2662 : 221 : gsi_next_nondebug (&gsi);
2663 : 206 : if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
2664 : 98 : return false;
2665 : : }
2666 : :
2667 : : /* Don't warn for terminated branches, i.e. when the subsequent case labels
2668 : : immediately breaks. */
2669 : 15234 : gsi = *gsi_p;
2670 : :
2671 : : /* Skip all immediately following labels. */
2672 : 33996 : while (!gsi_end_p (gsi)
2673 : 33996 : && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2674 : 15369 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT))
2675 : 18762 : gsi_next_nondebug (&gsi);
2676 : :
2677 : : /* { ... something; default:; } */
2678 : 15234 : if (gsi_end_p (gsi)
2679 : : /* { ... something; default: break; } or
2680 : : { ... something; default: goto L; } */
2681 : 15154 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
2682 : : /* { ... something; default: return; } */
2683 : 29374 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
2684 : 1115 : return false;
2685 : :
2686 : : return true;
2687 : : }
2688 : :
2689 : : /* Callback for walk_gimple_seq. */
2690 : :
2691 : : static tree
2692 : 21407 : warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2693 : : struct walk_stmt_info *)
2694 : : {
2695 : 21407 : gimple *stmt = gsi_stmt (*gsi_p);
2696 : :
2697 : 21407 : *handled_ops_p = true;
2698 : 21407 : switch (gimple_code (stmt))
2699 : : {
2700 : 252 : case GIMPLE_TRY:
2701 : 252 : case GIMPLE_BIND:
2702 : 252 : case GIMPLE_CATCH:
2703 : 252 : case GIMPLE_EH_FILTER:
2704 : 252 : case GIMPLE_TRANSACTION:
2705 : : /* Walk the sub-statements. */
2706 : 252 : *handled_ops_p = false;
2707 : 252 : break;
2708 : :
2709 : : /* Find a sequence of form:
2710 : :
2711 : : GIMPLE_LABEL
2712 : : [...]
2713 : : <may fallthru stmt>
2714 : : GIMPLE_LABEL
2715 : :
2716 : : and possibly warn. */
2717 : : case GIMPLE_LABEL:
2718 : : {
2719 : : /* Found a label. Skip all immediately following labels. */
2720 : 48127 : while (!gsi_end_p (*gsi_p)
2721 : 48127 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2722 : 27384 : gsi_next_nondebug (gsi_p);
2723 : :
2724 : : /* There might be no more statements. */
2725 : 20743 : if (gsi_end_p (*gsi_p))
2726 : 4320 : return integer_zero_node;
2727 : :
2728 : : /* Vector of labels that fall through. */
2729 : 20532 : auto_vec <struct label_entry> labels;
2730 : 20532 : location_t prevloc;
2731 : 20532 : gimple *prev = collect_fallthrough_labels (gsi_p, &labels, &prevloc);
2732 : :
2733 : : /* There might be no more statements. */
2734 : 20532 : if (gsi_end_p (*gsi_p))
2735 : 4109 : return integer_zero_node;
2736 : :
2737 : 16423 : gimple *next = gsi_stmt (*gsi_p);
2738 : 16423 : tree label;
2739 : : /* If what follows is a label, then we may have a fallthrough. */
2740 : 16423 : if (gimple_code (next) == GIMPLE_LABEL
2741 : 16423 : && gimple_has_location (next)
2742 : 16423 : && (label = gimple_label_label (as_a <glabel *> (next)))
2743 : 32846 : && prev != NULL)
2744 : : {
2745 : 16415 : struct label_entry *l;
2746 : 16415 : bool warned_p = false;
2747 : 16415 : auto_diagnostic_group d;
2748 : 16415 : if (!should_warn_for_implicit_fallthrough (gsi_p, label))
2749 : : /* Quiet. */;
2750 : 14390 : else if (gimple_code (prev) == GIMPLE_LABEL
2751 : 271 : && (label = gimple_label_label (as_a <glabel *> (prev)))
2752 : 14390 : && (l = find_label_entry (&labels, label)))
2753 : 246 : warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough_,
2754 : : "this statement may fall through");
2755 : 13873 : else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH)
2756 : : /* Try to be clever and don't warn when the statement
2757 : : can't actually fall through. */
2758 : 13566 : && gimple_stmt_may_fallthru (prev)
2759 : 14236 : && prevloc != UNKNOWN_LOCATION)
2760 : 363 : warned_p = warning_at (prevloc,
2761 : : OPT_Wimplicit_fallthrough_,
2762 : : "this statement may fall through");
2763 : 609 : if (warned_p)
2764 : 609 : inform (gimple_location (next), "here");
2765 : :
2766 : : /* Mark this label as processed so as to prevent multiple
2767 : : warnings in nested switches. */
2768 : 16415 : FALLTHROUGH_LABEL_P (label) = true;
2769 : :
2770 : : /* So that next warn_implicit_fallthrough_r will start looking for
2771 : : a new sequence starting with this label. */
2772 : 16415 : gsi_prev (gsi_p);
2773 : 16415 : }
2774 : 4109 : }
2775 : 16423 : break;
2776 : : default:
2777 : : break;
2778 : : }
2779 : : return NULL_TREE;
2780 : : }
2781 : :
2782 : : /* Warn when a switch case falls through. */
2783 : :
2784 : : static void
2785 : 48049 : maybe_warn_implicit_fallthrough (gimple_seq seq)
2786 : : {
2787 : 48049 : if (!warn_implicit_fallthrough)
2788 : 43829 : return;
2789 : :
2790 : : /* This warning is meant for C/C++/ObjC/ObjC++ only. */
2791 : 4220 : if (!(lang_GNU_C ()
2792 : 1257 : || lang_GNU_CXX ()
2793 : 0 : || lang_GNU_OBJC ()))
2794 : : return;
2795 : :
2796 : 4220 : struct walk_stmt_info wi;
2797 : 4220 : memset (&wi, 0, sizeof (wi));
2798 : 4220 : walk_gimple_seq (seq, warn_implicit_fallthrough_r, NULL, &wi);
2799 : : }
2800 : :
2801 : : /* Callback for walk_gimple_seq. */
2802 : :
2803 : : static tree
2804 : 3261444 : expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2805 : : struct walk_stmt_info *wi)
2806 : : {
2807 : 3261444 : gimple *stmt = gsi_stmt (*gsi_p);
2808 : :
2809 : 3261444 : *handled_ops_p = true;
2810 : 3261444 : switch (gimple_code (stmt))
2811 : : {
2812 : 151911 : case GIMPLE_TRY:
2813 : 151911 : case GIMPLE_BIND:
2814 : 151911 : case GIMPLE_CATCH:
2815 : 151911 : case GIMPLE_EH_FILTER:
2816 : 151911 : case GIMPLE_TRANSACTION:
2817 : : /* Walk the sub-statements. */
2818 : 151911 : *handled_ops_p = false;
2819 : 151911 : break;
2820 : 261808 : case GIMPLE_CALL:
2821 : 261808 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2822 : 261808 : if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
2823 : : {
2824 : 3423 : location_t loc = gimple_location (stmt);
2825 : 3423 : gsi_remove (gsi_p, true);
2826 : 3423 : wi->removed_stmt = true;
2827 : :
2828 : : /* nothrow flag is added by genericize_c_loop to mark fallthrough
2829 : : statement at the end of some loop's body. Those should be
2830 : : always diagnosed, either because they indeed don't precede
2831 : : a case label or default label, or because the next statement
2832 : : is not within the same iteration statement. */
2833 : 3423 : if ((stmt->subcode & GF_CALL_NOTHROW) != 0)
2834 : : {
2835 : 12 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2836 : : "a case label or default label");
2837 : 12 : break;
2838 : : }
2839 : :
2840 : 3411 : if (gsi_end_p (*gsi_p))
2841 : : {
2842 : 37 : static_cast<location_t *>(wi->info)[0] = BUILTINS_LOCATION;
2843 : 37 : static_cast<location_t *>(wi->info)[1] = loc;
2844 : 37 : break;
2845 : : }
2846 : :
2847 : 3374 : bool found = false;
2848 : :
2849 : 3374 : gimple_stmt_iterator gsi2 = *gsi_p;
2850 : 3374 : stmt = gsi_stmt (gsi2);
2851 : 3374 : if (gimple_code (stmt) == GIMPLE_GOTO && !gimple_has_location (stmt))
2852 : : {
2853 : : /* Go on until the artificial label. */
2854 : 69 : tree goto_dest = gimple_goto_dest (stmt);
2855 : 506 : for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
2856 : : {
2857 : 437 : if (gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL
2858 : 437 : && gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)))
2859 : : == goto_dest)
2860 : : break;
2861 : : }
2862 : :
2863 : : /* Not found? Stop. */
2864 : 69 : if (gsi_end_p (gsi2))
2865 : : break;
2866 : :
2867 : : /* Look one past it. */
2868 : 69 : gsi_next (&gsi2);
2869 : : }
2870 : :
2871 : : /* We're looking for a case label or default label here. */
2872 : 3477 : while (!gsi_end_p (gsi2))
2873 : : {
2874 : 3477 : stmt = gsi_stmt (gsi2);
2875 : 3477 : if (gimple_code (stmt) == GIMPLE_LABEL)
2876 : : {
2877 : 3433 : tree label = gimple_label_label (as_a <glabel *> (stmt));
2878 : 3433 : if (gimple_has_location (stmt) && DECL_ARTIFICIAL (label))
2879 : : {
2880 : : found = true;
2881 : : break;
2882 : : }
2883 : : }
2884 : 44 : else if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2885 : : ;
2886 : 44 : else if (!is_gimple_debug (stmt))
2887 : : /* Anything else is not expected. */
2888 : : break;
2889 : 103 : gsi_next (&gsi2);
2890 : : }
2891 : 3374 : if (!found)
2892 : 24 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2893 : : "a case label or default label");
2894 : : }
2895 : : break;
2896 : 2847725 : default:
2897 : 2847725 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2898 : 2847725 : break;
2899 : : }
2900 : 3261444 : return NULL_TREE;
2901 : : }
2902 : :
2903 : : /* Expand all FALLTHROUGH () calls in SEQ. */
2904 : :
2905 : : static void
2906 : 46627 : expand_FALLTHROUGH (gimple_seq *seq_p)
2907 : : {
2908 : 46627 : struct walk_stmt_info wi;
2909 : 46627 : location_t loc[2];
2910 : 46627 : memset (&wi, 0, sizeof (wi));
2911 : 46627 : loc[0] = UNKNOWN_LOCATION;
2912 : 46627 : loc[1] = UNKNOWN_LOCATION;
2913 : 46627 : wi.info = (void *) &loc[0];
2914 : 46627 : walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
2915 : 46627 : if (loc[0] != UNKNOWN_LOCATION)
2916 : : /* We've found [[fallthrough]]; at the end of a switch, which the C++
2917 : : standard says is ill-formed; see [dcl.attr.fallthrough]. */
2918 : 9 : pedwarn (loc[1], 0, "attribute %<fallthrough%> not preceding "
2919 : : "a case label or default label");
2920 : 46627 : }
2921 : :
2922 : :
2923 : : /* Gimplify a SWITCH_EXPR, and collect the vector of labels it can
2924 : : branch to. */
2925 : :
2926 : : static enum gimplify_status
2927 : 48049 : gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
2928 : : {
2929 : 48049 : tree switch_expr = *expr_p;
2930 : 48049 : gimple_seq switch_body_seq = NULL;
2931 : 48049 : enum gimplify_status ret;
2932 : 48049 : tree index_type = TREE_TYPE (switch_expr);
2933 : 48049 : if (index_type == NULL_TREE)
2934 : 11192 : index_type = TREE_TYPE (SWITCH_COND (switch_expr));
2935 : :
2936 : 48049 : ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
2937 : : fb_rvalue);
2938 : 48049 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
2939 : : return ret;
2940 : :
2941 : 48049 : if (SWITCH_BODY (switch_expr))
2942 : : {
2943 : 48049 : vec<tree> labels;
2944 : 48049 : vec<tree> saved_labels;
2945 : 48049 : hash_set<tree> *saved_live_switch_vars = NULL;
2946 : 48049 : tree default_case = NULL_TREE;
2947 : 48049 : gswitch *switch_stmt;
2948 : :
2949 : : /* Save old labels, get new ones from body, then restore the old
2950 : : labels. Save all the things from the switch body to append after. */
2951 : 48049 : saved_labels = gimplify_ctxp->case_labels;
2952 : 48049 : gimplify_ctxp->case_labels.create (8);
2953 : :
2954 : : /* Do not create live_switch_vars if SWITCH_BODY is not a BIND_EXPR. */
2955 : 48049 : saved_live_switch_vars = gimplify_ctxp->live_switch_vars;
2956 : 48049 : tree_code body_type = TREE_CODE (SWITCH_BODY (switch_expr));
2957 : 48049 : if (body_type == BIND_EXPR || body_type == STATEMENT_LIST)
2958 : 47733 : gimplify_ctxp->live_switch_vars = new hash_set<tree> (4);
2959 : : else
2960 : 316 : gimplify_ctxp->live_switch_vars = NULL;
2961 : :
2962 : 48049 : bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
2963 : 48049 : gimplify_ctxp->in_switch_expr = true;
2964 : :
2965 : 48049 : gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
2966 : :
2967 : 48049 : gimplify_ctxp->in_switch_expr = old_in_switch_expr;
2968 : 48049 : maybe_warn_switch_unreachable_and_auto_init (switch_body_seq);
2969 : 48049 : maybe_warn_implicit_fallthrough (switch_body_seq);
2970 : : /* Only do this for the outermost GIMPLE_SWITCH. */
2971 : 48049 : if (!gimplify_ctxp->in_switch_expr)
2972 : 46627 : expand_FALLTHROUGH (&switch_body_seq);
2973 : :
2974 : 48049 : labels = gimplify_ctxp->case_labels;
2975 : 48049 : gimplify_ctxp->case_labels = saved_labels;
2976 : :
2977 : 48049 : if (gimplify_ctxp->live_switch_vars)
2978 : : {
2979 : 47733 : gcc_assert (gimplify_ctxp->live_switch_vars->is_empty ());
2980 : 47733 : delete gimplify_ctxp->live_switch_vars;
2981 : : }
2982 : 48049 : gimplify_ctxp->live_switch_vars = saved_live_switch_vars;
2983 : :
2984 : 48049 : preprocess_case_label_vec_for_gimple (labels, index_type,
2985 : : &default_case);
2986 : :
2987 : 48049 : bool add_bind = false;
2988 : 48049 : if (!default_case)
2989 : : {
2990 : 14457 : glabel *new_default;
2991 : :
2992 : 14457 : default_case
2993 : 14457 : = build_case_label (NULL_TREE, NULL_TREE,
2994 : : create_artificial_label (UNKNOWN_LOCATION));
2995 : 14457 : if (old_in_switch_expr)
2996 : : {
2997 : 778 : SWITCH_BREAK_LABEL_P (CASE_LABEL (default_case)) = 1;
2998 : 778 : add_bind = true;
2999 : : }
3000 : 14457 : new_default = gimple_build_label (CASE_LABEL (default_case));
3001 : 14457 : gimplify_seq_add_stmt (&switch_body_seq, new_default);
3002 : : }
3003 : 33592 : else if (old_in_switch_expr)
3004 : : {
3005 : 644 : gimple *last = gimple_seq_last_stmt (switch_body_seq);
3006 : 644 : if (last && gimple_code (last) == GIMPLE_LABEL)
3007 : : {
3008 : 364 : tree label = gimple_label_label (as_a <glabel *> (last));
3009 : 364 : if (SWITCH_BREAK_LABEL_P (label))
3010 : 48049 : add_bind = true;
3011 : : }
3012 : : }
3013 : :
3014 : 48049 : switch_stmt = gimple_build_switch (SWITCH_COND (switch_expr),
3015 : : default_case, labels);
3016 : : /* For the benefit of -Wimplicit-fallthrough, if switch_body_seq
3017 : : ends with a GIMPLE_LABEL holding SWITCH_BREAK_LABEL_P LABEL_DECL,
3018 : : wrap the GIMPLE_SWITCH up to that GIMPLE_LABEL into a GIMPLE_BIND,
3019 : : so that we can easily find the start and end of the switch
3020 : : statement. */
3021 : 48049 : if (add_bind)
3022 : : {
3023 : 1141 : gimple_seq bind_body = NULL;
3024 : 1141 : gimplify_seq_add_stmt (&bind_body, switch_stmt);
3025 : 1141 : gimple_seq_add_seq (&bind_body, switch_body_seq);
3026 : 1141 : gbind *bind = gimple_build_bind (NULL_TREE, bind_body, NULL_TREE);
3027 : 1141 : gimple_set_location (bind, EXPR_LOCATION (switch_expr));
3028 : 1141 : gimplify_seq_add_stmt (pre_p, bind);
3029 : : }
3030 : : else
3031 : : {
3032 : 46908 : gimplify_seq_add_stmt (pre_p, switch_stmt);
3033 : 46908 : gimplify_seq_add_seq (pre_p, switch_body_seq);
3034 : : }
3035 : 48049 : labels.release ();
3036 : : }
3037 : : else
3038 : 0 : gcc_unreachable ();
3039 : :
3040 : 48049 : return GS_ALL_DONE;
3041 : : }
3042 : :
3043 : : /* Gimplify the LABEL_EXPR pointed to by EXPR_P. */
3044 : :
3045 : : static enum gimplify_status
3046 : 2224384 : gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
3047 : : {
3048 : 2224384 : gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
3049 : : == current_function_decl);
3050 : :
3051 : 2224384 : tree label = LABEL_EXPR_LABEL (*expr_p);
3052 : 2224384 : glabel *label_stmt = gimple_build_label (label);
3053 : 2224384 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3054 : 2224384 : gimplify_seq_add_stmt (pre_p, label_stmt);
3055 : :
3056 : 2224384 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3057 : 10 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3058 : : NOT_TAKEN));
3059 : 2224374 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3060 : 4 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3061 : : TAKEN));
3062 : :
3063 : 2224384 : return GS_ALL_DONE;
3064 : : }
3065 : :
3066 : : /* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
3067 : :
3068 : : static enum gimplify_status
3069 : 1037493 : gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
3070 : : {
3071 : 1037493 : struct gimplify_ctx *ctxp;
3072 : 1037493 : glabel *label_stmt;
3073 : :
3074 : : /* Invalid programs can play Duff's Device type games with, for example,
3075 : : #pragma omp parallel. At least in the C front end, we don't
3076 : : detect such invalid branches until after gimplification, in the
3077 : : diagnose_omp_blocks pass. */
3078 : 1037502 : for (ctxp = gimplify_ctxp; ; ctxp = ctxp->prev_context)
3079 : 1037502 : if (ctxp->case_labels.exists ())
3080 : : break;
3081 : :
3082 : 1037493 : tree label = CASE_LABEL (*expr_p);
3083 : 1037493 : label_stmt = gimple_build_label (label);
3084 : 1037493 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3085 : 1037493 : ctxp->case_labels.safe_push (*expr_p);
3086 : 1037493 : gimplify_seq_add_stmt (pre_p, label_stmt);
3087 : :
3088 : 1037493 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3089 : 6 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3090 : : NOT_TAKEN));
3091 : 1037487 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3092 : 6 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3093 : : TAKEN));
3094 : :
3095 : 1037493 : return GS_ALL_DONE;
3096 : : }
3097 : :
3098 : : /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first
3099 : : if necessary. */
3100 : :
3101 : : tree
3102 : 1626916 : build_and_jump (tree *label_p)
3103 : : {
3104 : 1626916 : if (label_p == NULL)
3105 : : /* If there's nowhere to jump, just fall through. */
3106 : : return NULL_TREE;
3107 : :
3108 : 1105194 : if (*label_p == NULL_TREE)
3109 : : {
3110 : 629787 : tree label = create_artificial_label (UNKNOWN_LOCATION);
3111 : 629787 : *label_p = label;
3112 : : }
3113 : :
3114 : 1105194 : return build1 (GOTO_EXPR, void_type_node, *label_p);
3115 : : }
3116 : :
3117 : : /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
3118 : : This also involves building a label to jump to and communicating it to
3119 : : gimplify_loop_expr through gimplify_ctxp->exit_label. */
3120 : :
3121 : : static enum gimplify_status
3122 : 3091 : gimplify_exit_expr (tree *expr_p)
3123 : : {
3124 : 3091 : tree cond = TREE_OPERAND (*expr_p, 0);
3125 : 3091 : tree expr;
3126 : :
3127 : 3091 : expr = build_and_jump (&gimplify_ctxp->exit_label);
3128 : 3091 : expr = build3 (COND_EXPR, void_type_node, cond, expr, NULL_TREE);
3129 : 3091 : *expr_p = expr;
3130 : :
3131 : 3091 : return GS_OK;
3132 : : }
3133 : :
3134 : : /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is
3135 : : different from its canonical type, wrap the whole thing inside a
3136 : : NOP_EXPR and force the type of the COMPONENT_REF to be the canonical
3137 : : type.
3138 : :
3139 : : The canonical type of a COMPONENT_REF is the type of the field being
3140 : : referenced--unless the field is a bit-field which can be read directly
3141 : : in a smaller mode, in which case the canonical type is the
3142 : : sign-appropriate type corresponding to that mode. */
3143 : :
3144 : : static void
3145 : 16856863 : canonicalize_component_ref (tree *expr_p)
3146 : : {
3147 : 16856863 : tree expr = *expr_p;
3148 : 16856863 : tree type;
3149 : :
3150 : 16856863 : gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
3151 : :
3152 : 16856863 : if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
3153 : 6830211 : type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
3154 : : else
3155 : 10026652 : type = TREE_TYPE (TREE_OPERAND (expr, 1));
3156 : :
3157 : : /* One could argue that all the stuff below is not necessary for
3158 : : the non-bitfield case and declare it a FE error if type
3159 : : adjustment would be needed. */
3160 : 16856863 : if (TREE_TYPE (expr) != type)
3161 : : {
3162 : : #ifdef ENABLE_TYPES_CHECKING
3163 : 648841 : tree old_type = TREE_TYPE (expr);
3164 : : #endif
3165 : 648841 : int type_quals;
3166 : :
3167 : : /* We need to preserve qualifiers and propagate them from
3168 : : operand 0. */
3169 : 648841 : type_quals = TYPE_QUALS (type)
3170 : 648841 : | TYPE_QUALS (TREE_TYPE (TREE_OPERAND (expr, 0)));
3171 : 648841 : if (TYPE_QUALS (type) != type_quals)
3172 : 648788 : type = build_qualified_type (TYPE_MAIN_VARIANT (type), type_quals);
3173 : :
3174 : : /* Set the type of the COMPONENT_REF to the underlying type. */
3175 : 648841 : TREE_TYPE (expr) = type;
3176 : :
3177 : : #ifdef ENABLE_TYPES_CHECKING
3178 : : /* It is now a FE error, if the conversion from the canonical
3179 : : type to the original expression type is not useless. */
3180 : 648841 : gcc_assert (useless_type_conversion_p (old_type, type));
3181 : : #endif
3182 : : }
3183 : 16856863 : }
3184 : :
3185 : : /* If a NOP conversion is changing a pointer to array of foo to a pointer
3186 : : to foo, embed that change in the ADDR_EXPR by converting
3187 : : T array[U];
3188 : : (T *)&array
3189 : : ==>
3190 : : &array[L]
3191 : : where L is the lower bound. For simplicity, only do this for constant
3192 : : lower bound.
3193 : : The constraint is that the type of &array[L] is trivially convertible
3194 : : to T *. */
3195 : :
3196 : : static void
3197 : 411089 : canonicalize_addr_expr (tree *expr_p)
3198 : : {
3199 : 411089 : tree expr = *expr_p;
3200 : 411089 : tree addr_expr = TREE_OPERAND (expr, 0);
3201 : 411089 : tree datype, ddatype, pddatype;
3202 : :
3203 : : /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
3204 : 821850 : if (!POINTER_TYPE_P (TREE_TYPE (expr))
3205 : 411089 : || TREE_CODE (addr_expr) != ADDR_EXPR)
3206 : : return;
3207 : :
3208 : : /* The addr_expr type should be a pointer to an array. */
3209 : 328 : datype = TREE_TYPE (TREE_TYPE (addr_expr));
3210 : 328 : if (TREE_CODE (datype) != ARRAY_TYPE)
3211 : : return;
3212 : :
3213 : : /* The pointer to element type shall be trivially convertible to
3214 : : the expression pointer type. */
3215 : 28 : ddatype = TREE_TYPE (datype);
3216 : 28 : pddatype = build_pointer_type (ddatype);
3217 : 28 : if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
3218 : : pddatype))
3219 : : return;
3220 : :
3221 : : /* The lower bound and element sizes must be constant. */
3222 : 0 : if (!TYPE_SIZE_UNIT (ddatype)
3223 : 0 : || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
3224 : 0 : || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
3225 : 0 : || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
3226 : : return;
3227 : :
3228 : : /* All checks succeeded. Build a new node to merge the cast. */
3229 : 0 : *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
3230 : 0 : TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
3231 : : NULL_TREE, NULL_TREE);
3232 : 0 : *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
3233 : :
3234 : : /* We can have stripped a required restrict qualifier above. */
3235 : 0 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
3236 : 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
3237 : : }
3238 : :
3239 : : /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
3240 : : underneath as appropriate. */
3241 : :
3242 : : static enum gimplify_status
3243 : 11800080 : gimplify_conversion (tree *expr_p)
3244 : : {
3245 : 11800080 : location_t loc = EXPR_LOCATION (*expr_p);
3246 : 11800080 : gcc_assert (CONVERT_EXPR_P (*expr_p));
3247 : :
3248 : : /* Then strip away all but the outermost conversion. */
3249 : 11800080 : STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
3250 : :
3251 : : /* And remove the outermost conversion if it's useless. */
3252 : 11800080 : if (tree_ssa_useless_type_conversion (*expr_p))
3253 : 0 : *expr_p = TREE_OPERAND (*expr_p, 0);
3254 : :
3255 : : /* If we still have a conversion at the toplevel,
3256 : : then canonicalize some constructs. */
3257 : 11800080 : if (CONVERT_EXPR_P (*expr_p))
3258 : : {
3259 : 11800080 : tree sub = TREE_OPERAND (*expr_p, 0);
3260 : :
3261 : : /* If a NOP conversion is changing the type of a COMPONENT_REF
3262 : : expression, then canonicalize its type now in order to expose more
3263 : : redundant conversions. */
3264 : 11800080 : if (TREE_CODE (sub) == COMPONENT_REF)
3265 : 272826 : canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0));
3266 : :
3267 : : /* If a NOP conversion is changing a pointer to array of foo
3268 : : to a pointer to foo, embed that change in the ADDR_EXPR. */
3269 : 11527254 : else if (TREE_CODE (sub) == ADDR_EXPR)
3270 : 411089 : canonicalize_addr_expr (expr_p);
3271 : : }
3272 : :
3273 : : /* If we have a conversion to a non-register type force the
3274 : : use of a VIEW_CONVERT_EXPR instead. */
3275 : 11800080 : if (CONVERT_EXPR_P (*expr_p) && !is_gimple_reg_type (TREE_TYPE (*expr_p)))
3276 : 110 : *expr_p = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p),
3277 : 110 : TREE_OPERAND (*expr_p, 0));
3278 : :
3279 : : /* Canonicalize CONVERT_EXPR to NOP_EXPR. */
3280 : 11800080 : if (TREE_CODE (*expr_p) == CONVERT_EXPR)
3281 : 227150 : TREE_SET_CODE (*expr_p, NOP_EXPR);
3282 : :
3283 : 11800080 : return GS_OK;
3284 : : }
3285 : :
3286 : : /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
3287 : : DECL_VALUE_EXPR, and it's worth re-examining things. */
3288 : :
3289 : : static enum gimplify_status
3290 : 114755049 : gimplify_var_or_parm_decl (tree *expr_p)
3291 : : {
3292 : 114755049 : tree decl = *expr_p;
3293 : :
3294 : : /* ??? If this is a local variable, and it has not been seen in any
3295 : : outer BIND_EXPR, then it's probably the result of a duplicate
3296 : : declaration, for which we've already issued an error. It would
3297 : : be really nice if the front end wouldn't leak these at all.
3298 : : Currently the only known culprit is C++ destructors, as seen
3299 : : in g++.old-deja/g++.jason/binding.C.
3300 : : Another possible culpit are size expressions for variably modified
3301 : : types which are lost in the FE or not gimplified correctly. */
3302 : 114755049 : if (VAR_P (decl)
3303 : 89444469 : && !DECL_SEEN_IN_BIND_EXPR_P (decl)
3304 : 16613266 : && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
3305 : 114804410 : && decl_function_context (decl) == current_function_decl)
3306 : : {
3307 : 0 : gcc_assert (seen_error ());
3308 : : return GS_ERROR;
3309 : : }
3310 : :
3311 : : /* When within an OMP context, notice uses of variables. */
3312 : 114755049 : if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
3313 : : return GS_ALL_DONE;
3314 : :
3315 : : /* If the decl is an alias for another expression, substitute it now. */
3316 : 114749025 : if (DECL_HAS_VALUE_EXPR_P (decl))
3317 : : {
3318 : 342541 : *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
3319 : 342541 : return GS_OK;
3320 : : }
3321 : :
3322 : : return GS_ALL_DONE;
3323 : : }
3324 : :
3325 : : /* Recalculate the value of the TREE_SIDE_EFFECTS flag for T. */
3326 : :
3327 : : static void
3328 : 100034239 : recalculate_side_effects (tree t)
3329 : : {
3330 : 100034239 : enum tree_code code = TREE_CODE (t);
3331 : 100034239 : int len = TREE_OPERAND_LENGTH (t);
3332 : 100034239 : int i;
3333 : :
3334 : 100034239 : switch (TREE_CODE_CLASS (code))
3335 : : {
3336 : 601708 : case tcc_expression:
3337 : 601708 : switch (code)
3338 : : {
3339 : : case INIT_EXPR:
3340 : : case MODIFY_EXPR:
3341 : : case VA_ARG_EXPR:
3342 : : case PREDECREMENT_EXPR:
3343 : : case PREINCREMENT_EXPR:
3344 : : case POSTDECREMENT_EXPR:
3345 : : case POSTINCREMENT_EXPR:
3346 : : /* All of these have side-effects, no matter what their
3347 : : operands are. */
3348 : : return;
3349 : :
3350 : : default:
3351 : : break;
3352 : : }
3353 : : /* Fall through. */
3354 : :
3355 : 100034237 : case tcc_comparison: /* a comparison expression */
3356 : 100034237 : case tcc_unary: /* a unary arithmetic expression */
3357 : 100034237 : case tcc_binary: /* a binary arithmetic expression */
3358 : 100034237 : case tcc_reference: /* a reference */
3359 : 100034237 : case tcc_vl_exp: /* a function call */
3360 : 100034237 : TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
3361 : 324631249 : for (i = 0; i < len; ++i)
3362 : : {
3363 : 224597012 : tree op = TREE_OPERAND (t, i);
3364 : 224597012 : if (op && TREE_SIDE_EFFECTS (op))
3365 : 1162370 : TREE_SIDE_EFFECTS (t) = 1;
3366 : : }
3367 : : break;
3368 : :
3369 : : case tcc_constant:
3370 : : /* No side-effects. */
3371 : : return;
3372 : :
3373 : 2 : default:
3374 : 2 : if (code == SSA_NAME)
3375 : : /* No side-effects. */
3376 : : return;
3377 : 0 : gcc_unreachable ();
3378 : : }
3379 : : }
3380 : :
3381 : : /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
3382 : : node *EXPR_P.
3383 : :
3384 : : compound_lval
3385 : : : min_lval '[' val ']'
3386 : : | min_lval '.' ID
3387 : : | compound_lval '[' val ']'
3388 : : | compound_lval '.' ID
3389 : :
3390 : : This is not part of the original SIMPLE definition, which separates
3391 : : array and member references, but it seems reasonable to handle them
3392 : : together. Also, this way we don't run into problems with union
3393 : : aliasing; gcc requires that for accesses through a union to alias, the
3394 : : union reference must be explicit, which was not always the case when we
3395 : : were splitting up array and member refs.
3396 : :
3397 : : PRE_P points to the sequence where side effects that must happen before
3398 : : *EXPR_P should be stored.
3399 : :
3400 : : POST_P points to the sequence where side effects that must happen after
3401 : : *EXPR_P should be stored. */
3402 : :
3403 : : static enum gimplify_status
3404 : 27246333 : gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3405 : : fallback_t fallback)
3406 : : {
3407 : 27246333 : tree *p;
3408 : 27246333 : enum gimplify_status ret = GS_ALL_DONE, tret;
3409 : 27246333 : int i;
3410 : 27246333 : location_t loc = EXPR_LOCATION (*expr_p);
3411 : 27246333 : tree expr = *expr_p;
3412 : :
3413 : : /* Create a stack of the subexpressions so later we can walk them in
3414 : : order from inner to outer. */
3415 : 27246333 : auto_vec<tree, 10> expr_stack;
3416 : :
3417 : : /* We can handle anything that get_inner_reference can deal with. */
3418 : 65082633 : for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
3419 : : {
3420 : 37836300 : restart:
3421 : : /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
3422 : 65140501 : if (TREE_CODE (*p) == INDIRECT_REF)
3423 : 3501210 : *p = fold_indirect_ref_loc (loc, *p);
3424 : :
3425 : 65140501 : if (handled_component_p (*p))
3426 : : ;
3427 : : /* Expand DECL_VALUE_EXPR now. In some cases that may expose
3428 : : additional COMPONENT_REFs. */
3429 : 11894242 : else if ((VAR_P (*p) || TREE_CODE (*p) == PARM_DECL)
3430 : 28692060 : && gimplify_var_or_parm_decl (p) == GS_OK)
3431 : 57868 : goto restart;
3432 : : else
3433 : : break;
3434 : :
3435 : 37836300 : expr_stack.safe_push (*p);
3436 : : }
3437 : :
3438 : 27246333 : gcc_assert (expr_stack.length ());
3439 : :
3440 : : /* Now EXPR_STACK is a stack of pointers to all the refs we've
3441 : : walked through and P points to the innermost expression.
3442 : :
3443 : : Java requires that we elaborated nodes in source order. That
3444 : : means we must gimplify the inner expression followed by each of
3445 : : the indices, in order. But we can't gimplify the inner
3446 : : expression until we deal with any variable bounds, sizes, or
3447 : : positions in order to deal with PLACEHOLDER_EXPRs.
3448 : :
3449 : : The base expression may contain a statement expression that
3450 : : has declarations used in size expressions, so has to be
3451 : : gimplified before gimplifying the size expressions.
3452 : :
3453 : : So we do this in three steps. First we deal with variable
3454 : : bounds, sizes, and positions, then we gimplify the base and
3455 : : ensure it is memory if needed, then we deal with the annotations
3456 : : for any variables in the components and any indices, from left
3457 : : to right. */
3458 : :
3459 : 27246333 : bool need_non_reg = false;
3460 : 65082630 : for (i = expr_stack.length () - 1; i >= 0; i--)
3461 : : {
3462 : 37836300 : tree t = expr_stack[i];
3463 : :
3464 : 37836300 : if (error_operand_p (TREE_OPERAND (t, 0)))
3465 : : return GS_ERROR;
3466 : :
3467 : 37836297 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3468 : : {
3469 : : /* Deal with the low bound and element type size and put them into
3470 : : the ARRAY_REF. If these values are set, they have already been
3471 : : gimplified. */
3472 : 7890948 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3473 : : {
3474 : 7846152 : tree low = unshare_expr (array_ref_low_bound (t));
3475 : 7846152 : if (!is_gimple_min_invariant (low))
3476 : : {
3477 : 0 : TREE_OPERAND (t, 2) = low;
3478 : : }
3479 : : }
3480 : :
3481 : 7890948 : if (TREE_OPERAND (t, 3) == NULL_TREE)
3482 : : {
3483 : 7870952 : tree elmt_size = array_ref_element_size (t);
3484 : 7870952 : if (!is_gimple_min_invariant (elmt_size))
3485 : : {
3486 : 9425 : elmt_size = unshare_expr (elmt_size);
3487 : 9425 : tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
3488 : 9425 : tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
3489 : :
3490 : : /* Divide the element size by the alignment of the element
3491 : : type (above). */
3492 : 9425 : elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR,
3493 : : elmt_size, factor);
3494 : :
3495 : 9425 : TREE_OPERAND (t, 3) = elmt_size;
3496 : : }
3497 : : }
3498 : : need_non_reg = true;
3499 : : }
3500 : 29945349 : else if (TREE_CODE (t) == COMPONENT_REF)
3501 : : {
3502 : : /* Set the field offset into T and gimplify it. */
3503 : 28676582 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3504 : : {
3505 : 28676215 : tree offset = component_ref_field_offset (t);
3506 : 28676215 : if (!is_gimple_min_invariant (offset))
3507 : : {
3508 : 281 : offset = unshare_expr (offset);
3509 : 281 : tree field = TREE_OPERAND (t, 1);
3510 : 281 : tree factor
3511 : 281 : = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
3512 : :
3513 : : /* Divide the offset by its alignment. */
3514 : 281 : offset = size_binop_loc (loc, EXACT_DIV_EXPR,
3515 : : offset, factor);
3516 : :
3517 : 281 : TREE_OPERAND (t, 2) = offset;
3518 : : }
3519 : : }
3520 : : need_non_reg = true;
3521 : : }
3522 : 1268767 : else if (!is_gimple_reg_type (TREE_TYPE (t)))
3523 : : /* When the result of an operation, in particular a VIEW_CONVERT_EXPR
3524 : : is a non-register type then require the base object to be a
3525 : : non-register as well. */
3526 : 36834587 : need_non_reg = true;
3527 : : }
3528 : :
3529 : : /* Step 2 is to gimplify the base expression. Make sure lvalue is set
3530 : : so as to match the min_lval predicate. Failure to do so may result
3531 : : in the creation of large aggregate temporaries. */
3532 : 27246330 : tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
3533 : : fallback | fb_lvalue);
3534 : 27246330 : ret = MIN (ret, tret);
3535 : 27246330 : if (ret == GS_ERROR)
3536 : : return GS_ERROR;
3537 : :
3538 : : /* Step 2a: if we have component references we do not support on
3539 : : registers then make sure the base isn't a register. Of course
3540 : : we can only do so if an rvalue is OK. */
3541 : 27246330 : if (need_non_reg && (fallback & fb_rvalue))
3542 : 20349704 : prepare_gimple_addressable (p, pre_p);
3543 : :
3544 : :
3545 : : /* Step 3: gimplify size expressions and the indices and operands of
3546 : : ARRAY_REF. During this loop we also remove any useless conversions.
3547 : : If we operate on a register also make sure to properly gimplify
3548 : : to individual operations. */
3549 : :
3550 : 27246330 : bool reg_operations = is_gimple_reg (*p);
3551 : 65082627 : for (; expr_stack.length () > 0; )
3552 : : {
3553 : 37836297 : tree t = expr_stack.pop ();
3554 : :
3555 : 37836297 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3556 : : {
3557 : 7890948 : gcc_assert (!reg_operations);
3558 : :
3559 : : /* Gimplify the low bound and element type size. */
3560 : 7890948 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3561 : : is_gimple_reg, fb_rvalue);
3562 : 7890948 : ret = MIN (ret, tret);
3563 : :
3564 : 7890948 : tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
3565 : : is_gimple_reg, fb_rvalue);
3566 : 7890948 : ret = MIN (ret, tret);
3567 : :
3568 : : /* Gimplify the dimension. */
3569 : 7890948 : tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
3570 : : is_gimple_val, fb_rvalue);
3571 : 7890948 : ret = MIN (ret, tret);
3572 : : }
3573 : 29945349 : else if (TREE_CODE (t) == COMPONENT_REF)
3574 : : {
3575 : 28676582 : gcc_assert (!reg_operations);
3576 : :
3577 : 28676582 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3578 : : is_gimple_reg, fb_rvalue);
3579 : 28676582 : ret = MIN (ret, tret);
3580 : : }
3581 : 1268767 : else if (reg_operations)
3582 : : {
3583 : 758586 : tret = gimplify_expr (&TREE_OPERAND (t, 0), pre_p, post_p,
3584 : : is_gimple_val, fb_rvalue);
3585 : 758586 : ret = MIN (ret, tret);
3586 : : }
3587 : :
3588 : 37836297 : STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
3589 : :
3590 : : /* The innermost expression P may have originally had
3591 : : TREE_SIDE_EFFECTS set which would have caused all the outer
3592 : : expressions in *EXPR_P leading to P to also have had
3593 : : TREE_SIDE_EFFECTS set. */
3594 : 37836297 : recalculate_side_effects (t);
3595 : : }
3596 : :
3597 : : /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */
3598 : 27246330 : if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
3599 : : {
3600 : 16584037 : canonicalize_component_ref (expr_p);
3601 : : }
3602 : :
3603 : 27246330 : expr_stack.release ();
3604 : :
3605 : 27246330 : gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
3606 : :
3607 : : return ret;
3608 : 27246333 : }
3609 : :
3610 : : /* Gimplify the self modifying expression pointed to by EXPR_P
3611 : : (++, --, +=, -=).
3612 : :
3613 : : PRE_P points to the list where side effects that must happen before
3614 : : *EXPR_P should be stored.
3615 : :
3616 : : POST_P points to the list where side effects that must happen after
3617 : : *EXPR_P should be stored.
3618 : :
3619 : : WANT_VALUE is nonzero iff we want to use the value of this expression
3620 : : in another expression.
3621 : :
3622 : : ARITH_TYPE is the type the computation should be performed in. */
3623 : :
3624 : : enum gimplify_status
3625 : 1100366 : gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3626 : : bool want_value, tree arith_type)
3627 : : {
3628 : 1100366 : enum tree_code code;
3629 : 1100366 : tree lhs, lvalue, rhs, t1;
3630 : 1100366 : gimple_seq post = NULL, *orig_post_p = post_p;
3631 : 1100366 : bool postfix;
3632 : 1100366 : enum tree_code arith_code;
3633 : 1100366 : enum gimplify_status ret;
3634 : 1100366 : location_t loc = EXPR_LOCATION (*expr_p);
3635 : :
3636 : 1100366 : code = TREE_CODE (*expr_p);
3637 : :
3638 : 1100366 : gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
3639 : : || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
3640 : :
3641 : : /* Prefix or postfix? */
3642 : 1100366 : if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
3643 : : /* Faster to treat as prefix if result is not used. */
3644 : : postfix = want_value;
3645 : : else
3646 : : postfix = false;
3647 : :
3648 : : /* For postfix, make sure the inner expression's post side effects
3649 : : are executed after side effects from this expression. */
3650 : 379888 : if (postfix)
3651 : 1100366 : post_p = &post;
3652 : :
3653 : : /* Add or subtract? */
3654 : 1100366 : if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
3655 : : arith_code = PLUS_EXPR;
3656 : : else
3657 : 42586 : arith_code = MINUS_EXPR;
3658 : :
3659 : : /* Gimplify the LHS into a GIMPLE lvalue. */
3660 : 1100366 : lvalue = TREE_OPERAND (*expr_p, 0);
3661 : 1100366 : ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
3662 : 1100366 : if (ret == GS_ERROR)
3663 : : return ret;
3664 : :
3665 : : /* Extract the operands to the arithmetic operation. */
3666 : 1100365 : lhs = lvalue;
3667 : 1100365 : rhs = TREE_OPERAND (*expr_p, 1);
3668 : :
3669 : : /* For postfix operator, we evaluate the LHS to an rvalue and then use
3670 : : that as the result value and in the postqueue operation. */
3671 : 1100365 : if (postfix)
3672 : : {
3673 : 187004 : ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
3674 : 187004 : if (ret == GS_ERROR)
3675 : : return ret;
3676 : :
3677 : 187004 : lhs = get_initialized_tmp_var (lhs, pre_p);
3678 : : }
3679 : :
3680 : : /* For POINTERs increment, use POINTER_PLUS_EXPR. */
3681 : 1100365 : if (POINTER_TYPE_P (TREE_TYPE (lhs)))
3682 : : {
3683 : 224877 : rhs = convert_to_ptrofftype_loc (loc, rhs);
3684 : 224877 : if (arith_code == MINUS_EXPR)
3685 : 7235 : rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
3686 : 224877 : t1 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
3687 : : }
3688 : : else
3689 : 875488 : t1 = fold_convert (TREE_TYPE (*expr_p),
3690 : : fold_build2 (arith_code, arith_type,
3691 : : fold_convert (arith_type, lhs),
3692 : : fold_convert (arith_type, rhs)));
3693 : :
3694 : 1100365 : if (postfix)
3695 : : {
3696 : 187004 : gimplify_assign (lvalue, t1, pre_p);
3697 : 187004 : gimplify_seq_add_seq (orig_post_p, post);
3698 : 187004 : *expr_p = lhs;
3699 : 187004 : return GS_ALL_DONE;
3700 : : }
3701 : : else
3702 : : {
3703 : 913361 : *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
3704 : 913361 : return GS_OK;
3705 : : }
3706 : : }
3707 : :
3708 : : /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
3709 : :
3710 : : static void
3711 : 72288640 : maybe_with_size_expr (tree *expr_p)
3712 : : {
3713 : 72288640 : tree expr = *expr_p;
3714 : 72288640 : tree type = TREE_TYPE (expr);
3715 : 72288640 : tree size;
3716 : :
3717 : : /* If we've already wrapped this or the type is error_mark_node, we can't do
3718 : : anything. */
3719 : 72288640 : if (TREE_CODE (expr) == WITH_SIZE_EXPR
3720 : 72288519 : || type == error_mark_node)
3721 : : return;
3722 : :
3723 : : /* If the size isn't known or is a constant, we have nothing to do. */
3724 : 72288477 : size = TYPE_SIZE_UNIT (type);
3725 : 72288477 : if (!size || poly_int_tree_p (size))
3726 : : return;
3727 : :
3728 : : /* Otherwise, make a WITH_SIZE_EXPR. */
3729 : 1467 : size = unshare_expr (size);
3730 : 1467 : size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
3731 : 1467 : *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
3732 : : }
3733 : :
3734 : : /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P
3735 : : Store any side-effects in PRE_P. CALL_LOCATION is the location of
3736 : : the CALL_EXPR. If ALLOW_SSA is set the actual parameter may be
3737 : : gimplified to an SSA name. */
3738 : :
3739 : : enum gimplify_status
3740 : 29211166 : gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
3741 : : bool allow_ssa)
3742 : : {
3743 : 29211166 : bool (*test) (tree);
3744 : 29211166 : fallback_t fb;
3745 : :
3746 : : /* In general, we allow lvalues for function arguments to avoid
3747 : : extra overhead of copying large aggregates out of even larger
3748 : : aggregates into temporaries only to copy the temporaries to
3749 : : the argument list. Make optimizers happy by pulling out to
3750 : : temporaries those types that fit in registers. */
3751 : 29211166 : if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
3752 : : test = is_gimple_val, fb = fb_rvalue;
3753 : : else
3754 : : {
3755 : 1382338 : test = is_gimple_lvalue, fb = fb_either;
3756 : : /* Also strip a TARGET_EXPR that would force an extra copy. */
3757 : 1382338 : if (TREE_CODE (*arg_p) == TARGET_EXPR)
3758 : : {
3759 : 237291 : tree init = TARGET_EXPR_INITIAL (*arg_p);
3760 : 237291 : if (init
3761 : 237291 : && !VOID_TYPE_P (TREE_TYPE (init)))
3762 : 218176 : *arg_p = init;
3763 : : }
3764 : : }
3765 : :
3766 : : /* If this is a variable sized type, we must remember the size. */
3767 : 29211166 : maybe_with_size_expr (arg_p);
3768 : :
3769 : : /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */
3770 : : /* Make sure arguments have the same location as the function call
3771 : : itself. */
3772 : 29211166 : protected_set_expr_location (*arg_p, call_location);
3773 : :
3774 : : /* There is a sequence point before a function call. Side effects in
3775 : : the argument list must occur before the actual call. So, when
3776 : : gimplifying arguments, force gimplify_expr to use an internal
3777 : : post queue which is then appended to the end of PRE_P. */
3778 : 29211166 : return gimplify_expr (arg_p, pre_p, NULL, test, fb, allow_ssa);
3779 : : }
3780 : :
3781 : : /* Don't fold inside offloading or taskreg regions: it can break code by
3782 : : adding decl references that weren't in the source. We'll do it during
3783 : : omplower pass instead. */
3784 : :
3785 : : static bool
3786 : 53471250 : maybe_fold_stmt (gimple_stmt_iterator *gsi)
3787 : : {
3788 : 53471250 : struct gimplify_omp_ctx *ctx;
3789 : 53984239 : for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
3790 : 1094026 : if ((ctx->region_type & (ORT_TARGET | ORT_PARALLEL | ORT_TASK)) != 0)
3791 : : return false;
3792 : 518057 : else if ((ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
3793 : : return false;
3794 : : /* Delay folding of builtins until the IL is in consistent state
3795 : : so the diagnostic machinery can do a better job. */
3796 : 52890213 : if (gimple_call_builtin_p (gsi_stmt (*gsi)))
3797 : : return false;
3798 : 50741549 : return fold_stmt (gsi);
3799 : : }
3800 : :
3801 : : /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
3802 : : WANT_VALUE is true if the result of the call is desired. */
3803 : :
3804 : : static enum gimplify_status
3805 : 14909024 : gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
3806 : : {
3807 : 14909024 : tree fndecl, parms, p, fnptrtype;
3808 : 14909024 : enum gimplify_status ret;
3809 : 14909024 : int i, nargs;
3810 : 14909024 : gcall *call;
3811 : 14909024 : bool builtin_va_start_p = false;
3812 : 14909024 : location_t loc = EXPR_LOCATION (*expr_p);
3813 : :
3814 : 14909024 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
3815 : :
3816 : : /* For reliable diagnostics during inlining, it is necessary that
3817 : : every call_expr be annotated with file and line. */
3818 : 14909024 : if (! EXPR_HAS_LOCATION (*expr_p))
3819 : 523188 : SET_EXPR_LOCATION (*expr_p, input_location);
3820 : :
3821 : : /* Gimplify internal functions created in the FEs. */
3822 : 14909024 : if (CALL_EXPR_FN (*expr_p) == NULL_TREE)
3823 : : {
3824 : 370402 : if (want_value)
3825 : : return GS_ALL_DONE;
3826 : :
3827 : 17695 : nargs = call_expr_nargs (*expr_p);
3828 : 17695 : enum internal_fn ifn = CALL_EXPR_IFN (*expr_p);
3829 : 17695 : auto_vec<tree> vargs (nargs);
3830 : :
3831 : 17695 : if (ifn == IFN_ASSUME)
3832 : : {
3833 : 465 : if (simple_condition_p (CALL_EXPR_ARG (*expr_p, 0)))
3834 : : {
3835 : : /* If the [[assume (cond)]]; condition is simple
3836 : : enough and can be evaluated unconditionally
3837 : : without side-effects, expand it as
3838 : : if (!cond) __builtin_unreachable (); */
3839 : 265 : tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
3840 : 530 : *expr_p = build3 (COND_EXPR, void_type_node,
3841 : 265 : CALL_EXPR_ARG (*expr_p, 0), void_node,
3842 : 265 : build_call_expr_loc (EXPR_LOCATION (*expr_p),
3843 : : fndecl, 0));
3844 : 265 : return GS_OK;
3845 : : }
3846 : : /* If not optimizing, ignore the assumptions. */
3847 : 200 : if (!optimize || seen_error ())
3848 : : {
3849 : 99 : *expr_p = NULL_TREE;
3850 : 99 : return GS_ALL_DONE;
3851 : : }
3852 : : /* Temporarily, until gimple lowering, transform
3853 : : .ASSUME (cond);
3854 : : into:
3855 : : [[assume (guard)]]
3856 : : {
3857 : : guard = cond;
3858 : : }
3859 : : such that gimple lowering can outline the condition into
3860 : : a separate function easily. */
3861 : 101 : tree guard = create_tmp_var (boolean_type_node);
3862 : 101 : *expr_p = build2 (MODIFY_EXPR, void_type_node, guard,
3863 : 101 : gimple_boolify (CALL_EXPR_ARG (*expr_p, 0)));
3864 : 101 : *expr_p = build3 (BIND_EXPR, void_type_node, NULL, *expr_p, NULL);
3865 : 101 : push_gimplify_context ();
3866 : 101 : gimple_seq body = NULL;
3867 : 101 : gimple *g = gimplify_and_return_first (*expr_p, &body);
3868 : 101 : pop_gimplify_context (g);
3869 : 101 : g = gimple_build_assume (guard, body);
3870 : 101 : gimple_set_location (g, loc);
3871 : 101 : gimplify_seq_add_stmt (pre_p, g);
3872 : 101 : *expr_p = NULL_TREE;
3873 : 101 : return GS_ALL_DONE;
3874 : : }
3875 : :
3876 : 40522 : for (i = 0; i < nargs; i++)
3877 : : {
3878 : 23292 : gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
3879 : 23292 : EXPR_LOCATION (*expr_p));
3880 : 23292 : vargs.quick_push (CALL_EXPR_ARG (*expr_p, i));
3881 : : }
3882 : :
3883 : 17230 : gcall *call = gimple_build_call_internal_vec (ifn, vargs);
3884 : 17230 : gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p));
3885 : 17230 : gimplify_seq_add_stmt (pre_p, call);
3886 : 17230 : return GS_ALL_DONE;
3887 : 17695 : }
3888 : :
3889 : : /* This may be a call to a builtin function.
3890 : :
3891 : : Builtin function calls may be transformed into different
3892 : : (and more efficient) builtin function calls under certain
3893 : : circumstances. Unfortunately, gimplification can muck things
3894 : : up enough that the builtin expanders are not aware that certain
3895 : : transformations are still valid.
3896 : :
3897 : : So we attempt transformation/gimplification of the call before
3898 : : we gimplify the CALL_EXPR. At this time we do not manage to
3899 : : transform all calls in the same manner as the expanders do, but
3900 : : we do transform most of them. */
3901 : 14538622 : fndecl = get_callee_fndecl (*expr_p);
3902 : 14538622 : if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
3903 : 3644494 : switch (DECL_FUNCTION_CODE (fndecl))
3904 : : {
3905 : 78759 : CASE_BUILT_IN_ALLOCA:
3906 : : /* If the call has been built for a variable-sized object, then we
3907 : : want to restore the stack level when the enclosing BIND_EXPR is
3908 : : exited to reclaim the allocated space; otherwise, we precisely
3909 : : need to do the opposite and preserve the latest stack level. */
3910 : 78759 : if (CALL_ALLOCA_FOR_VAR_P (*expr_p))
3911 : 8899 : gimplify_ctxp->save_stack = true;
3912 : : else
3913 : 69860 : gimplify_ctxp->keep_stack = true;
3914 : : break;
3915 : :
3916 : 20603 : case BUILT_IN_VA_START:
3917 : 20603 : {
3918 : 20603 : builtin_va_start_p = true;
3919 : 20603 : if (call_expr_nargs (*expr_p) < 2)
3920 : : {
3921 : 1 : error ("too few arguments to function %<va_start%>");
3922 : 1 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
3923 : 1 : return GS_OK;
3924 : : }
3925 : :
3926 : 20602 : if (fold_builtin_next_arg (*expr_p, true))
3927 : : {
3928 : 10 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
3929 : 10 : return GS_OK;
3930 : : }
3931 : : break;
3932 : : }
3933 : :
3934 : 29 : case BUILT_IN_EH_RETURN:
3935 : 29 : cfun->calls_eh_return = true;
3936 : 29 : break;
3937 : :
3938 : 1064 : case BUILT_IN_CLEAR_PADDING:
3939 : 1064 : if (call_expr_nargs (*expr_p) == 1)
3940 : : {
3941 : : /* Remember the original type of the argument in an internal
3942 : : dummy second argument, as in GIMPLE pointer conversions are
3943 : : useless. Also mark this call as not for automatic
3944 : : initialization in the internal dummy third argument. */
3945 : 532 : p = CALL_EXPR_ARG (*expr_p, 0);
3946 : 532 : *expr_p
3947 : 532 : = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
3948 : 532 : build_zero_cst (TREE_TYPE (p)));
3949 : 532 : return GS_OK;
3950 : : }
3951 : : break;
3952 : :
3953 : : default:
3954 : : ;
3955 : : }
3956 : 14538079 : if (fndecl && fndecl_built_in_p (fndecl))
3957 : : {
3958 : 3859385 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
3959 : 3859385 : if (new_tree && new_tree != *expr_p)
3960 : : {
3961 : : /* There was a transformation of this call which computes the
3962 : : same value, but in a more efficient way. Return and try
3963 : : again. */
3964 : 667 : *expr_p = new_tree;
3965 : 667 : return GS_OK;
3966 : : }
3967 : : }
3968 : :
3969 : : /* Remember the original function pointer type. */
3970 : 14537412 : fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
3971 : :
3972 : 14537412 : if (flag_openmp
3973 : 377702 : && fndecl
3974 : 377067 : && cfun
3975 : 377067 : && (cfun->curr_properties & PROP_gimple_any) == 0)
3976 : : {
3977 : 181363 : tree variant = omp_resolve_declare_variant (fndecl);
3978 : 181363 : if (variant != fndecl)
3979 : 254 : CALL_EXPR_FN (*expr_p) = build1 (ADDR_EXPR, fnptrtype, variant);
3980 : : }
3981 : :
3982 : : /* There is a sequence point before the call, so any side effects in
3983 : : the calling expression must occur before the actual call. Force
3984 : : gimplify_expr to use an internal post queue. */
3985 : 14537412 : ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
3986 : : is_gimple_call_addr, fb_rvalue);
3987 : :
3988 : 14537412 : if (ret == GS_ERROR)
3989 : : return GS_ERROR;
3990 : :
3991 : 14537410 : nargs = call_expr_nargs (*expr_p);
3992 : :
3993 : : /* Get argument types for verification. */
3994 : 14537410 : fndecl = get_callee_fndecl (*expr_p);
3995 : 14537410 : parms = NULL_TREE;
3996 : 14537410 : if (fndecl)
3997 : 14319206 : parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
3998 : : else
3999 : 218204 : parms = TYPE_ARG_TYPES (TREE_TYPE (fnptrtype));
4000 : :
4001 : 28856616 : if (fndecl && DECL_ARGUMENTS (fndecl))
4002 : : p = DECL_ARGUMENTS (fndecl);
4003 : 6824492 : else if (parms)
4004 : : p = parms;
4005 : : else
4006 : : p = NULL_TREE;
4007 : 38567922 : for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
4008 : : ;
4009 : :
4010 : : /* If the last argument is __builtin_va_arg_pack () and it is not
4011 : : passed as a named argument, decrease the number of CALL_EXPR
4012 : : arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */
4013 : 14537410 : if (!p
4014 : 14537410 : && i < nargs
4015 : 14537410 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR)
4016 : : {
4017 : 6069 : tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1);
4018 : 6069 : tree last_arg_fndecl = get_callee_fndecl (last_arg);
4019 : :
4020 : 6069 : if (last_arg_fndecl
4021 : 6069 : && fndecl_built_in_p (last_arg_fndecl, BUILT_IN_VA_ARG_PACK))
4022 : : {
4023 : 125 : tree call = *expr_p;
4024 : :
4025 : 125 : --nargs;
4026 : 250 : *expr_p = build_call_array_loc (loc, TREE_TYPE (call),
4027 : 125 : CALL_EXPR_FN (call),
4028 : 125 : nargs, CALL_EXPR_ARGP (call));
4029 : :
4030 : : /* Copy all CALL_EXPR flags, location and block, except
4031 : : CALL_EXPR_VA_ARG_PACK flag. */
4032 : 125 : CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call);
4033 : 125 : CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call);
4034 : 125 : CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
4035 : 125 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4036 : 125 : CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
4037 : 125 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
4038 : :
4039 : : /* Set CALL_EXPR_VA_ARG_PACK. */
4040 : 125 : CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
4041 : : }
4042 : : }
4043 : :
4044 : : /* If the call returns twice then after building the CFG the call
4045 : : argument computations will no longer dominate the call because
4046 : : we add an abnormal incoming edge to the call. So do not use SSA
4047 : : vars there. */
4048 : 14537410 : bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE;
4049 : :
4050 : : /* Gimplify the function arguments. */
4051 : 14537410 : if (nargs > 0)
4052 : : {
4053 : 12536255 : for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
4054 : 37857824 : PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
4055 : 25321569 : PUSH_ARGS_REVERSED ? i-- : i++)
4056 : : {
4057 : 25321569 : enum gimplify_status t;
4058 : :
4059 : : /* Avoid gimplifying the second argument to va_start, which needs to
4060 : : be the plain PARM_DECL. */
4061 : 25321569 : if ((i != 1) || !builtin_va_start_p)
4062 : : {
4063 : 25300977 : t = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
4064 : 25300977 : EXPR_LOCATION (*expr_p), ! returns_twice);
4065 : :
4066 : 25300977 : if (t == GS_ERROR)
4067 : 25321569 : ret = GS_ERROR;
4068 : : }
4069 : : }
4070 : : }
4071 : :
4072 : : /* Gimplify the static chain. */
4073 : 14537410 : if (CALL_EXPR_STATIC_CHAIN (*expr_p))
4074 : : {
4075 : 28838 : if (fndecl && !DECL_STATIC_CHAIN (fndecl))
4076 : 3 : CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL;
4077 : : else
4078 : : {
4079 : 28159 : enum gimplify_status t;
4080 : 28159 : t = gimplify_arg (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p,
4081 : 28159 : EXPR_LOCATION (*expr_p), ! returns_twice);
4082 : 28159 : if (t == GS_ERROR)
4083 : 14537410 : ret = GS_ERROR;
4084 : : }
4085 : : }
4086 : :
4087 : : /* Verify the function result. */
4088 : 14537410 : if (want_value && fndecl
4089 : 14537410 : && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
4090 : : {
4091 : 0 : error_at (loc, "using result of function returning %<void%>");
4092 : 0 : ret = GS_ERROR;
4093 : : }
4094 : :
4095 : : /* Try this again in case gimplification exposed something. */
4096 : 14537410 : if (ret != GS_ERROR)
4097 : : {
4098 : 14537368 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4099 : :
4100 : 14537368 : if (new_tree && new_tree != *expr_p)
4101 : : {
4102 : : /* There was a transformation of this call which computes the
4103 : : same value, but in a more efficient way. Return and try
4104 : : again. */
4105 : 11609 : *expr_p = new_tree;
4106 : 11609 : return GS_OK;
4107 : : }
4108 : : }
4109 : : else
4110 : : {
4111 : 42 : *expr_p = error_mark_node;
4112 : 42 : return GS_ERROR;
4113 : : }
4114 : :
4115 : : /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
4116 : : decl. This allows us to eliminate redundant or useless
4117 : : calls to "const" functions. */
4118 : 14525759 : if (TREE_CODE (*expr_p) == CALL_EXPR)
4119 : : {
4120 : 14525759 : int flags = call_expr_flags (*expr_p);
4121 : 14525759 : if (flags & (ECF_CONST | ECF_PURE)
4122 : : /* An infinite loop is considered a side effect. */
4123 : 2250749 : && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
4124 : 1943293 : TREE_SIDE_EFFECTS (*expr_p) = 0;
4125 : : }
4126 : :
4127 : : /* If the value is not needed by the caller, emit a new GIMPLE_CALL
4128 : : and clear *EXPR_P. Otherwise, leave *EXPR_P in its gimplified
4129 : : form and delegate the creation of a GIMPLE_CALL to
4130 : : gimplify_modify_expr. This is always possible because when
4131 : : WANT_VALUE is true, the caller wants the result of this call into
4132 : : a temporary, which means that we will emit an INIT_EXPR in
4133 : : internal_get_tmp_var which will then be handled by
4134 : : gimplify_modify_expr. */
4135 : 14525759 : if (!want_value)
4136 : : {
4137 : : /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
4138 : : have to do is replicate it as a GIMPLE_CALL tuple. */
4139 : 5605287 : gimple_stmt_iterator gsi;
4140 : 5605287 : call = gimple_build_call_from_tree (*expr_p, fnptrtype);
4141 : 5605287 : notice_special_calls (call);
4142 : 5605287 : gimplify_seq_add_stmt (pre_p, call);
4143 : 5605287 : gsi = gsi_last (*pre_p);
4144 : 5605287 : maybe_fold_stmt (&gsi);
4145 : 5605287 : *expr_p = NULL_TREE;
4146 : : }
4147 : : else
4148 : : /* Remember the original function type. */
4149 : 8920472 : CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
4150 : 8920472 : CALL_EXPR_FN (*expr_p));
4151 : :
4152 : : return ret;
4153 : : }
4154 : :
4155 : : /* Handle shortcut semantics in the predicate operand of a COND_EXPR by
4156 : : rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs.
4157 : :
4158 : : TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the
4159 : : condition is true or false, respectively. If null, we should generate
4160 : : our own to skip over the evaluation of this specific expression.
4161 : :
4162 : : LOCUS is the source location of the COND_EXPR.
4163 : :
4164 : : The condition_uid is a discriminator tag for condition coverage used to map
4165 : : conditions to its corresponding full Boolean function.
4166 : :
4167 : : This function is the tree equivalent of do_jump.
4168 : :
4169 : : shortcut_cond_r should only be called by shortcut_cond_expr. */
4170 : :
4171 : : static tree
4172 : 1206778 : shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
4173 : : location_t locus, unsigned condition_uid)
4174 : : {
4175 : 1206778 : tree local_label = NULL_TREE;
4176 : 1206778 : tree t, expr = NULL;
4177 : :
4178 : : /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
4179 : : retain the shortcut semantics. Just insert the gotos here;
4180 : : shortcut_cond_expr will append the real blocks later. */
4181 : 1206778 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
4182 : : {
4183 : 106138 : location_t new_locus;
4184 : :
4185 : : /* Turn if (a && b) into
4186 : :
4187 : : if (a); else goto no;
4188 : : if (b) goto yes; else goto no;
4189 : : (no:) */
4190 : :
4191 : 106138 : if (false_label_p == NULL)
4192 : 3844 : false_label_p = &local_label;
4193 : :
4194 : : /* Keep the original source location on the first 'if'. */
4195 : 106138 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus,
4196 : : condition_uid);
4197 : 106138 : append_to_statement_list (t, &expr);
4198 : :
4199 : : /* Set the source location of the && on the second 'if'. */
4200 : 106138 : new_locus = rexpr_location (pred, locus);
4201 : 106138 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4202 : : new_locus, condition_uid);
4203 : 106138 : append_to_statement_list (t, &expr);
4204 : : }
4205 : 1100640 : else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
4206 : : {
4207 : 357994 : location_t new_locus;
4208 : :
4209 : : /* Turn if (a || b) into
4210 : :
4211 : : if (a) goto yes;
4212 : : if (b) goto yes; else goto no;
4213 : : (yes:) */
4214 : :
4215 : 357994 : if (true_label_p == NULL)
4216 : 212042 : true_label_p = &local_label;
4217 : :
4218 : : /* Keep the original source location on the first 'if'. */
4219 : 357994 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus,
4220 : : condition_uid);
4221 : 357994 : append_to_statement_list (t, &expr);
4222 : :
4223 : : /* Set the source location of the || on the second 'if'. */
4224 : 357994 : new_locus = rexpr_location (pred, locus);
4225 : 357994 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
4226 : : new_locus, condition_uid);
4227 : 357994 : append_to_statement_list (t, &expr);
4228 : : }
4229 : 742646 : else if (TREE_CODE (pred) == COND_EXPR
4230 : 754 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
4231 : 743400 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
4232 : : {
4233 : 746 : location_t new_locus;
4234 : :
4235 : : /* As long as we're messing with gotos, turn if (a ? b : c) into
4236 : : if (a)
4237 : : if (b) goto yes; else goto no;
4238 : : else
4239 : : if (c) goto yes; else goto no;
4240 : :
4241 : : Don't do this if one of the arms has void type, which can happen
4242 : : in C++ when the arm is throw. */
4243 : :
4244 : : /* Keep the original source location on the first 'if'. Set the source
4245 : : location of the ? on the second 'if'. */
4246 : 746 : new_locus = rexpr_location (pred, locus);
4247 : 1492 : expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
4248 : 746 : shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
4249 : : false_label_p, locus, condition_uid),
4250 : 746 : shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
4251 : : false_label_p, new_locus,
4252 : : condition_uid));
4253 : 746 : SET_EXPR_UID (expr, condition_uid);
4254 : : }
4255 : : else
4256 : : {
4257 : 741900 : expr = build3 (COND_EXPR, void_type_node, pred,
4258 : : build_and_jump (true_label_p),
4259 : : build_and_jump (false_label_p));
4260 : 741900 : SET_EXPR_LOCATION (expr, locus);
4261 : 741900 : SET_EXPR_UID (expr, condition_uid);
4262 : : }
4263 : :
4264 : 1206778 : if (local_label)
4265 : : {
4266 : 215886 : t = build1 (LABEL_EXPR, void_type_node, local_label);
4267 : 215886 : append_to_statement_list (t, &expr);
4268 : : }
4269 : :
4270 : 1206778 : return expr;
4271 : : }
4272 : :
4273 : : /* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip
4274 : : any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
4275 : : statement, if it is the last one. Otherwise, return NULL. */
4276 : :
4277 : : static tree
4278 : 10422252 : find_goto (tree expr)
4279 : : {
4280 : 10716353 : if (!expr)
4281 : : return NULL_TREE;
4282 : :
4283 : 8865843 : if (TREE_CODE (expr) == GOTO_EXPR)
4284 : : return expr;
4285 : :
4286 : 7105221 : if (TREE_CODE (expr) != STATEMENT_LIST)
4287 : : return NULL_TREE;
4288 : :
4289 : 952222 : tree_stmt_iterator i = tsi_start (expr);
4290 : :
4291 : 1330929 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
4292 : 378707 : tsi_next (&i);
4293 : :
4294 : 9527560 : if (!tsi_one_before_end_p (i))
4295 : : return NULL_TREE;
4296 : :
4297 : 294101 : return find_goto (tsi_stmt (i));
4298 : : }
4299 : :
4300 : : /* Same as find_goto, except that it returns NULL if the destination
4301 : : is not a LABEL_DECL. */
4302 : :
4303 : : static inline tree
4304 : 10422252 : find_goto_label (tree expr)
4305 : : {
4306 : 10422252 : tree dest = find_goto (expr);
4307 : 12182874 : if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
4308 : 1760513 : return dest;
4309 : : return NULL_TREE;
4310 : : }
4311 : :
4312 : :
4313 : : /* Given a multi-term condition (ANDIF, ORIF), walk the predicate PRED and tag
4314 : : every basic condition with CONDITION_UID. Two basic conditions share the
4315 : : CONDITION_UID discriminator when they belong to the same predicate, which is
4316 : : used by the condition coverage. Doing this as an explicit step makes for a
4317 : : simpler implementation than weaving it into the splitting code as the
4318 : : splitting code eventually calls the entry point gimplfiy_expr which makes
4319 : : bookkeeping complicated. */
4320 : : static void
4321 : 514540 : tag_shortcut_cond (tree pred, unsigned condition_uid)
4322 : : {
4323 : 549525 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR
4324 : 549525 : || TREE_CODE (pred) == TRUTH_ORIF_EXPR)
4325 : : {
4326 : 508584 : tree fst = TREE_OPERAND (pred, 0);
4327 : 508584 : tree lst = TREE_OPERAND (pred, 1);
4328 : :
4329 : 508584 : if (TREE_CODE (fst) == TRUTH_ANDIF_EXPR
4330 : 508584 : || TREE_CODE (fst) == TRUTH_ORIF_EXPR)
4331 : 161244 : tag_shortcut_cond (fst, condition_uid);
4332 : 347340 : else if (TREE_CODE (fst) == COND_EXPR)
4333 : 212 : SET_EXPR_UID (fst, condition_uid);
4334 : :
4335 : 508584 : if (TREE_CODE (lst) == TRUTH_ANDIF_EXPR
4336 : 508584 : || TREE_CODE (lst) == TRUTH_ORIF_EXPR)
4337 : : tag_shortcut_cond (lst, condition_uid);
4338 : 473599 : else if (TREE_CODE (lst) == COND_EXPR)
4339 : 418 : SET_EXPR_UID (lst, condition_uid);
4340 : : }
4341 : 514540 : }
4342 : :
4343 : : /* Given a conditional expression EXPR with short-circuit boolean
4344 : : predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
4345 : : predicate apart into the equivalent sequence of conditionals. CONDITION_UID
4346 : : is a the tag/discriminator for this EXPR - all basic conditions in the
4347 : : expression will be given the same CONDITION_UID. */
4348 : : static tree
4349 : 353296 : shortcut_cond_expr (tree expr, unsigned condition_uid)
4350 : : {
4351 : 353296 : tree pred = TREE_OPERAND (expr, 0);
4352 : 353296 : tree then_ = TREE_OPERAND (expr, 1);
4353 : 353296 : tree else_ = TREE_OPERAND (expr, 2);
4354 : 353296 : tree true_label, false_label, end_label, t;
4355 : 353296 : tree *true_label_p;
4356 : 353296 : tree *false_label_p;
4357 : 353296 : bool emit_end, emit_false, jump_over_else;
4358 : 353296 : bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
4359 : 353296 : bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
4360 : :
4361 : 353296 : tag_shortcut_cond (pred, condition_uid);
4362 : :
4363 : : /* First do simple transformations. */
4364 : 353296 : if (!else_se)
4365 : : {
4366 : : /* If there is no 'else', turn
4367 : : if (a && b) then c
4368 : : into
4369 : : if (a) if (b) then c. */
4370 : 250651 : while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
4371 : : {
4372 : : /* Keep the original source location on the first 'if'. */
4373 : 41658 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
4374 : 41658 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
4375 : : /* Set the source location of the && on the second 'if'. */
4376 : 41658 : if (rexpr_has_location (pred))
4377 : 40772 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
4378 : 41658 : then_ = shortcut_cond_expr (expr, condition_uid);
4379 : 41658 : then_se = then_ && TREE_SIDE_EFFECTS (then_);
4380 : 41658 : pred = TREE_OPERAND (pred, 0);
4381 : 41658 : expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
4382 : 41658 : SET_EXPR_LOCATION (expr, locus);
4383 : : }
4384 : : }
4385 : :
4386 : 353296 : if (!then_se)
4387 : : {
4388 : : /* If there is no 'then', turn
4389 : : if (a || b); else d
4390 : : into
4391 : : if (a); else if (b); else d. */
4392 : 18798 : while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
4393 : : {
4394 : : /* Keep the original source location on the first 'if'. */
4395 : 709 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
4396 : 709 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
4397 : : /* Set the source location of the || on the second 'if'. */
4398 : 709 : if (rexpr_has_location (pred))
4399 : 708 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
4400 : 709 : else_ = shortcut_cond_expr (expr, condition_uid);
4401 : 709 : else_se = else_ && TREE_SIDE_EFFECTS (else_);
4402 : 709 : pred = TREE_OPERAND (pred, 0);
4403 : 709 : expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
4404 : 709 : SET_EXPR_LOCATION (expr, locus);
4405 : : }
4406 : : }
4407 : :
4408 : : /* The expr tree should also have the expression id set. */
4409 : 353296 : SET_EXPR_UID (expr, condition_uid);
4410 : :
4411 : : /* If we're done, great. */
4412 : 353296 : if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR
4413 : 353296 : && TREE_CODE (pred) != TRUTH_ORIF_EXPR)
4414 : : return expr;
4415 : :
4416 : : /* Otherwise we need to mess with gotos. Change
4417 : : if (a) c; else d;
4418 : : to
4419 : : if (a); else goto no;
4420 : : c; goto end;
4421 : : no: d; end:
4422 : : and recursively gimplify the condition. */
4423 : :
4424 : 277022 : true_label = false_label = end_label = NULL_TREE;
4425 : :
4426 : : /* If our arms just jump somewhere, hijack those labels so we don't
4427 : : generate jumps to jumps. */
4428 : :
4429 : 277022 : if (tree then_goto = find_goto_label (then_))
4430 : : {
4431 : 4221 : true_label = GOTO_DESTINATION (then_goto);
4432 : 4221 : then_ = NULL;
4433 : 4221 : then_se = false;
4434 : : }
4435 : :
4436 : 277022 : if (tree else_goto = find_goto_label (else_))
4437 : : {
4438 : 3851 : false_label = GOTO_DESTINATION (else_goto);
4439 : 3851 : else_ = NULL;
4440 : 3851 : else_se = false;
4441 : : }
4442 : :
4443 : : /* If we aren't hijacking a label for the 'then' branch, it falls through. */
4444 : 277022 : if (true_label)
4445 : : true_label_p = &true_label;
4446 : : else
4447 : 272801 : true_label_p = NULL;
4448 : :
4449 : : /* The 'else' branch also needs a label if it contains interesting code. */
4450 : 277022 : if (false_label || else_se)
4451 : : false_label_p = &false_label;
4452 : : else
4453 : 277022 : false_label_p = NULL;
4454 : :
4455 : : /* If there was nothing else in our arms, just forward the label(s). */
4456 : 277022 : if (!then_se && !else_se)
4457 : 7778 : return shortcut_cond_r (pred, true_label_p, false_label_p,
4458 : 11667 : EXPR_LOC_OR_LOC (expr, input_location), condition_uid);
4459 : :
4460 : : /* If our last subexpression already has a terminal label, reuse it. */
4461 : 273133 : if (else_se)
4462 : 139671 : t = expr_last (else_);
4463 : 133462 : else if (then_se)
4464 : 133462 : t = expr_last (then_);
4465 : : else
4466 : : t = NULL;
4467 : 273133 : if (t && TREE_CODE (t) == LABEL_EXPR)
4468 : 905 : end_label = LABEL_EXPR_LABEL (t);
4469 : :
4470 : : /* If we don't care about jumping to the 'else' branch, jump to the end
4471 : : if the condition is false. */
4472 : 273133 : if (!false_label_p)
4473 : 133219 : false_label_p = &end_label;
4474 : :
4475 : : /* We only want to emit these labels if we aren't hijacking them. */
4476 : 273133 : emit_end = (end_label == NULL_TREE);
4477 : 273133 : emit_false = (false_label == NULL_TREE);
4478 : :
4479 : : /* We only emit the jump over the else clause if we have to--if the
4480 : : then clause may fall through. Otherwise we can wind up with a
4481 : : useless jump and a useless label at the end of gimplified code,
4482 : : which will cause us to think that this conditional as a whole
4483 : : falls through even if it doesn't. If we then inline a function
4484 : : which ends with such a condition, that can cause us to issue an
4485 : : inappropriate warning about control reaching the end of a
4486 : : non-void function. */
4487 : 273133 : jump_over_else = block_may_fallthru (then_);
4488 : :
4489 : 545671 : pred = shortcut_cond_r (pred, true_label_p, false_label_p,
4490 : 545671 : EXPR_LOC_OR_LOC (expr, input_location),
4491 : : condition_uid);
4492 : :
4493 : 273133 : expr = NULL;
4494 : 273133 : append_to_statement_list (pred, &expr);
4495 : :
4496 : 273133 : append_to_statement_list (then_, &expr);
4497 : 273133 : if (else_se)
4498 : : {
4499 : 139671 : if (jump_over_else)
4500 : : {
4501 : 137336 : tree last = expr_last (expr);
4502 : 137336 : t = build_and_jump (&end_label);
4503 : 137336 : if (rexpr_has_location (last))
4504 : 27640 : SET_EXPR_LOCATION (t, rexpr_location (last));
4505 : 137336 : append_to_statement_list (t, &expr);
4506 : : }
4507 : 139671 : if (emit_false)
4508 : : {
4509 : 139671 : t = build1 (LABEL_EXPR, void_type_node, false_label);
4510 : 139671 : append_to_statement_list (t, &expr);
4511 : : }
4512 : 139671 : append_to_statement_list (else_, &expr);
4513 : : }
4514 : 273133 : if (emit_end && end_label)
4515 : : {
4516 : 269655 : t = build1 (LABEL_EXPR, void_type_node, end_label);
4517 : 269655 : append_to_statement_list (t, &expr);
4518 : : }
4519 : :
4520 : 273133 : return expr;
4521 : : }
4522 : :
4523 : : /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */
4524 : :
4525 : : tree
4526 : 14713764 : gimple_boolify (tree expr)
4527 : : {
4528 : 14713764 : tree type = TREE_TYPE (expr);
4529 : 14713764 : location_t loc = EXPR_LOCATION (expr);
4530 : :
4531 : 14713764 : if (TREE_CODE (expr) == NE_EXPR
4532 : 5087137 : && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
4533 : 15635536 : && integer_zerop (TREE_OPERAND (expr, 1)))
4534 : : {
4535 : 467759 : tree call = TREE_OPERAND (expr, 0);
4536 : 467759 : tree fn = get_callee_fndecl (call);
4537 : :
4538 : : /* For __builtin_expect ((long) (x), y) recurse into x as well
4539 : : if x is truth_value_p. */
4540 : 467759 : if (fn
4541 : 467181 : && fndecl_built_in_p (fn, BUILT_IN_EXPECT)
4542 : 595575 : && call_expr_nargs (call) == 2)
4543 : : {
4544 : 127816 : tree arg = CALL_EXPR_ARG (call, 0);
4545 : 127816 : if (arg)
4546 : : {
4547 : 127816 : if (TREE_CODE (arg) == NOP_EXPR
4548 : 127816 : && TREE_TYPE (arg) == TREE_TYPE (call))
4549 : 56810 : arg = TREE_OPERAND (arg, 0);
4550 : 127816 : if (truth_value_p (TREE_CODE (arg)))
4551 : : {
4552 : 101681 : arg = gimple_boolify (arg);
4553 : 101681 : CALL_EXPR_ARG (call, 0)
4554 : 203362 : = fold_convert_loc (loc, TREE_TYPE (call), arg);
4555 : : }
4556 : : }
4557 : : }
4558 : : }
4559 : :
4560 : 14713764 : switch (TREE_CODE (expr))
4561 : : {
4562 : 1073033 : case TRUTH_AND_EXPR:
4563 : 1073033 : case TRUTH_OR_EXPR:
4564 : 1073033 : case TRUTH_XOR_EXPR:
4565 : 1073033 : case TRUTH_ANDIF_EXPR:
4566 : 1073033 : case TRUTH_ORIF_EXPR:
4567 : : /* Also boolify the arguments of truth exprs. */
4568 : 1073033 : TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
4569 : : /* FALLTHRU */
4570 : :
4571 : 1449108 : case TRUTH_NOT_EXPR:
4572 : 1449108 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
4573 : :
4574 : : /* These expressions always produce boolean results. */
4575 : 1449108 : if (TREE_CODE (type) != BOOLEAN_TYPE)
4576 : 299135 : TREE_TYPE (expr) = boolean_type_node;
4577 : : return expr;
4578 : :
4579 : 3327 : case ANNOTATE_EXPR:
4580 : 3327 : switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)))
4581 : : {
4582 : 3327 : case annot_expr_ivdep_kind:
4583 : 3327 : case annot_expr_unroll_kind:
4584 : 3327 : case annot_expr_no_vector_kind:
4585 : 3327 : case annot_expr_vector_kind:
4586 : 3327 : case annot_expr_parallel_kind:
4587 : 3327 : case annot_expr_maybe_infinite_kind:
4588 : 3327 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
4589 : 3327 : if (TREE_CODE (type) != BOOLEAN_TYPE)
4590 : 2700 : TREE_TYPE (expr) = boolean_type_node;
4591 : : return expr;
4592 : 0 : default:
4593 : 0 : gcc_unreachable ();
4594 : : }
4595 : :
4596 : 13261329 : default:
4597 : 13261329 : if (COMPARISON_CLASS_P (expr))
4598 : : {
4599 : : /* These expressions always produce boolean results. */
4600 : 11660183 : if (TREE_CODE (type) != BOOLEAN_TYPE)
4601 : 1524421 : TREE_TYPE (expr) = boolean_type_node;
4602 : 11660183 : return expr;
4603 : : }
4604 : : /* Other expressions that get here must have boolean values, but
4605 : : might need to be converted to the appropriate mode. */
4606 : 1601146 : if (TREE_CODE (type) == BOOLEAN_TYPE)
4607 : : return expr;
4608 : 178909 : return fold_convert_loc (loc, boolean_type_node, expr);
4609 : : }
4610 : : }
4611 : :
4612 : : /* Given a conditional expression *EXPR_P without side effects, gimplify
4613 : : its operands. New statements are inserted to PRE_P. */
4614 : :
4615 : : static enum gimplify_status
4616 : 30607 : gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
4617 : : {
4618 : 30607 : tree expr = *expr_p, cond;
4619 : 30607 : enum gimplify_status ret, tret;
4620 : 30607 : enum tree_code code;
4621 : :
4622 : 30607 : cond = gimple_boolify (COND_EXPR_COND (expr));
4623 : :
4624 : : /* We need to handle && and || specially, as their gimplification
4625 : : creates pure cond_expr, thus leading to an infinite cycle otherwise. */
4626 : 30607 : code = TREE_CODE (cond);
4627 : 30607 : if (code == TRUTH_ANDIF_EXPR)
4628 : 18 : TREE_SET_CODE (cond, TRUTH_AND_EXPR);
4629 : 30589 : else if (code == TRUTH_ORIF_EXPR)
4630 : 656 : TREE_SET_CODE (cond, TRUTH_OR_EXPR);
4631 : 30607 : ret = gimplify_expr (&cond, pre_p, NULL, is_gimple_val, fb_rvalue);
4632 : 30607 : COND_EXPR_COND (*expr_p) = cond;
4633 : :
4634 : 30607 : tret = gimplify_expr (&COND_EXPR_THEN (expr), pre_p, NULL,
4635 : : is_gimple_val, fb_rvalue);
4636 : 30607 : ret = MIN (ret, tret);
4637 : 30607 : tret = gimplify_expr (&COND_EXPR_ELSE (expr), pre_p, NULL,
4638 : : is_gimple_val, fb_rvalue);
4639 : :
4640 : 30607 : return MIN (ret, tret);
4641 : : }
4642 : :
4643 : : /* Return true if evaluating EXPR could trap.
4644 : : EXPR is GENERIC, while tree_could_trap_p can be called
4645 : : only on GIMPLE. */
4646 : :
4647 : : bool
4648 : 11575318 : generic_expr_could_trap_p (tree expr)
4649 : : {
4650 : 11575318 : unsigned i, n;
4651 : :
4652 : 11575318 : if (!expr || is_gimple_val (expr))
4653 : 4744517 : return false;
4654 : :
4655 : 6830801 : if (!EXPR_P (expr) || tree_could_trap_p (expr))
4656 : 2173441 : return true;
4657 : :
4658 : 4657360 : n = TREE_OPERAND_LENGTH (expr);
4659 : 10522645 : for (i = 0; i < n; i++)
4660 : 7870671 : if (generic_expr_could_trap_p (TREE_OPERAND (expr, i)))
4661 : : return true;
4662 : :
4663 : : return false;
4664 : : }
4665 : :
4666 : : /* Associate the condition STMT with the discriminator UID. STMTs that are
4667 : : broken down with ANDIF/ORIF from the same Boolean expression should be given
4668 : : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
4669 : : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
4670 : : for condition coverage. */
4671 : : static void
4672 : 4934104 : gimple_associate_condition_with_expr (struct function *fn, gcond *stmt,
4673 : : unsigned uid)
4674 : : {
4675 : 4934104 : if (!condition_coverage_flag)
4676 : : return;
4677 : :
4678 : 635 : if (!fn->cond_uids)
4679 : 134 : fn->cond_uids = new hash_map <gcond*, unsigned> ();
4680 : :
4681 : 635 : fn->cond_uids->put (stmt, uid);
4682 : : }
4683 : :
4684 : : /* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
4685 : : into
4686 : :
4687 : : if (p) if (p)
4688 : : t1 = a; a;
4689 : : else or else
4690 : : t1 = b; b;
4691 : : t1;
4692 : :
4693 : : The second form is used when *EXPR_P is of type void.
4694 : :
4695 : : PRE_P points to the list where side effects that must happen before
4696 : : *EXPR_P should be stored. */
4697 : :
4698 : : static enum gimplify_status
4699 : 5722987 : gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
4700 : : {
4701 : 5722987 : tree expr = *expr_p;
4702 : 5722987 : tree type = TREE_TYPE (expr);
4703 : 5722987 : location_t loc = EXPR_LOCATION (expr);
4704 : 5722987 : tree tmp, arm1, arm2;
4705 : 5722987 : enum gimplify_status ret;
4706 : 5722987 : tree label_true, label_false, label_cont;
4707 : 5722987 : bool have_then_clause_p, have_else_clause_p;
4708 : 5722987 : gcond *cond_stmt;
4709 : 5722987 : enum tree_code pred_code;
4710 : 5722987 : gimple_seq seq = NULL;
4711 : :
4712 : : /* If this COND_EXPR has a value, copy the values into a temporary within
4713 : : the arms. */
4714 : 5722987 : if (!VOID_TYPE_P (type))
4715 : : {
4716 : 477229 : tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
4717 : 477229 : tree result;
4718 : :
4719 : : /* If either an rvalue is ok or we do not require an lvalue, create the
4720 : : temporary. But we cannot do that if the type is addressable. */
4721 : 477229 : if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
4722 : 477222 : && !TREE_ADDRESSABLE (type))
4723 : : {
4724 : 477222 : if (gimplify_ctxp->allow_rhs_cond_expr
4725 : : /* If either branch has side effects or could trap, it can't be
4726 : : evaluated unconditionally. */
4727 : 30607 : && !TREE_SIDE_EFFECTS (then_)
4728 : 30607 : && !generic_expr_could_trap_p (then_)
4729 : 30607 : && !TREE_SIDE_EFFECTS (else_)
4730 : 507829 : && !generic_expr_could_trap_p (else_))
4731 : 30607 : return gimplify_pure_cond_expr (expr_p, pre_p);
4732 : :
4733 : 446615 : tmp = create_tmp_var (type, "iftmp");
4734 : 446615 : result = tmp;
4735 : : }
4736 : :
4737 : : /* Otherwise, only create and copy references to the values. */
4738 : : else
4739 : : {
4740 : 7 : type = build_pointer_type (type);
4741 : :
4742 : 7 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
4743 : 7 : then_ = build_fold_addr_expr_loc (loc, then_);
4744 : :
4745 : 7 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
4746 : 7 : else_ = build_fold_addr_expr_loc (loc, else_);
4747 : :
4748 : 7 : expr
4749 : 7 : = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
4750 : :
4751 : 7 : tmp = create_tmp_var (type, "iftmp");
4752 : 7 : result = build_simple_mem_ref_loc (loc, tmp);
4753 : : }
4754 : :
4755 : : /* Build the new then clause, `tmp = then_;'. But don't build the
4756 : : assignment if the value is void; in C++ it can be if it's a throw. */
4757 : 446622 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
4758 : 361672 : TREE_OPERAND (expr, 1) = build2 (INIT_EXPR, type, tmp, then_);
4759 : :
4760 : : /* Similarly, build the new else clause, `tmp = else_;'. */
4761 : 446622 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
4762 : 442462 : TREE_OPERAND (expr, 2) = build2 (INIT_EXPR, type, tmp, else_);
4763 : :
4764 : 446622 : TREE_TYPE (expr) = void_type_node;
4765 : 446622 : recalculate_side_effects (expr);
4766 : :
4767 : : /* Move the COND_EXPR to the prequeue. */
4768 : 446622 : gimplify_stmt (&expr, pre_p);
4769 : :
4770 : 446622 : *expr_p = result;
4771 : 446622 : return GS_ALL_DONE;
4772 : : }
4773 : :
4774 : : /* Remove any COMPOUND_EXPR so the following cases will be caught. */
4775 : 5259666 : STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
4776 : 5245758 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
4777 : 79865 : gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
4778 : :
4779 : : /* Make sure the condition has BOOLEAN_TYPE. */
4780 : 5245758 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
4781 : :
4782 : : /* Break apart && and || conditions. */
4783 : 5245758 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
4784 : 5245758 : || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
4785 : : {
4786 : 310929 : expr = shortcut_cond_expr (expr, next_cond_uid ());
4787 : :
4788 : 310929 : if (expr != *expr_p)
4789 : : {
4790 : 310929 : *expr_p = expr;
4791 : :
4792 : : /* We can't rely on gimplify_expr to re-gimplify the expanded
4793 : : form properly, as cleanups might cause the target labels to be
4794 : : wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to
4795 : : set up a conditional context. */
4796 : 310929 : gimple_push_condition ();
4797 : 310929 : gimplify_stmt (expr_p, &seq);
4798 : 310929 : gimple_pop_condition (pre_p);
4799 : 310929 : gimple_seq_add_seq (pre_p, seq);
4800 : :
4801 : 310929 : return GS_ALL_DONE;
4802 : : }
4803 : : }
4804 : :
4805 : : /* Now do the normal gimplification. */
4806 : :
4807 : : /* Gimplify condition. */
4808 : 4934829 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
4809 : : is_gimple_condexpr_for_cond, fb_rvalue);
4810 : 4934829 : if (ret == GS_ERROR)
4811 : : return GS_ERROR;
4812 : 4934104 : gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
4813 : :
4814 : 4934104 : gimple_push_condition ();
4815 : :
4816 : 4934104 : have_then_clause_p = have_else_clause_p = false;
4817 : 4934104 : label_true = find_goto_label (TREE_OPERAND (expr, 1));
4818 : 4934104 : if (label_true
4819 : 1118855 : && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
4820 : : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
4821 : : have different locations, otherwise we end up with incorrect
4822 : : location information on the branches. */
4823 : 6052959 : && (optimize
4824 : 211488 : || !EXPR_HAS_LOCATION (expr)
4825 : 185443 : || !rexpr_has_location (label_true)
4826 : 58576 : || EXPR_LOCATION (expr) == rexpr_location (label_true)))
4827 : : {
4828 : 1118100 : have_then_clause_p = true;
4829 : 1118100 : label_true = GOTO_DESTINATION (label_true);
4830 : : }
4831 : : else
4832 : 3816004 : label_true = create_artificial_label (UNKNOWN_LOCATION);
4833 : 4934104 : label_false = find_goto_label (TREE_OPERAND (expr, 2));
4834 : 4934104 : if (label_false
4835 : 633586 : && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
4836 : : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
4837 : : have different locations, otherwise we end up with incorrect
4838 : : location information on the branches. */
4839 : 5567690 : && (optimize
4840 : 99010 : || !EXPR_HAS_LOCATION (expr)
4841 : 98034 : || !rexpr_has_location (label_false)
4842 : 178 : || EXPR_LOCATION (expr) == rexpr_location (label_false)))
4843 : : {
4844 : 633420 : have_else_clause_p = true;
4845 : 633420 : label_false = GOTO_DESTINATION (label_false);
4846 : : }
4847 : : else
4848 : 4300684 : label_false = create_artificial_label (UNKNOWN_LOCATION);
4849 : :
4850 : 4934104 : unsigned cond_uid = EXPR_COND_UID (expr);
4851 : 4934104 : if (cond_uid == 0)
4852 : 4115085 : cond_uid = next_cond_uid ();
4853 : :
4854 : 4934104 : gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
4855 : : &arm2);
4856 : 4934104 : cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
4857 : : label_false);
4858 : 4934104 : gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
4859 : 4934104 : gimple_associate_condition_with_expr (cfun, cond_stmt, cond_uid);
4860 : 4934104 : copy_warning (cond_stmt, COND_EXPR_COND (expr));
4861 : 4934104 : gimplify_seq_add_stmt (&seq, cond_stmt);
4862 : 4934104 : gimple_stmt_iterator gsi = gsi_last (seq);
4863 : 4934104 : maybe_fold_stmt (&gsi);
4864 : :
4865 : 4934104 : label_cont = NULL_TREE;
4866 : 4934104 : if (!have_then_clause_p)
4867 : : {
4868 : : /* For if (...) {} else { code; } put label_true after
4869 : : the else block. */
4870 : 3816004 : if (TREE_OPERAND (expr, 1) == NULL_TREE
4871 : 168954 : && !have_else_clause_p
4872 : 3816703 : && TREE_OPERAND (expr, 2) != NULL_TREE)
4873 : : {
4874 : : /* For if (0) {} else { code; } tell -Wimplicit-fallthrough
4875 : : handling that label_cont == label_true can be only reached
4876 : : through fallthrough from { code; }. */
4877 : 699 : if (integer_zerop (COND_EXPR_COND (expr)))
4878 : 0 : UNUSED_LABEL_P (label_true) = 1;
4879 : : label_cont = label_true;
4880 : : }
4881 : : else
4882 : : {
4883 : 3815305 : bool then_side_effects
4884 : 3815305 : = (TREE_OPERAND (expr, 1)
4885 : 3815305 : && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)));
4886 : 3815305 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
4887 : 3815305 : have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
4888 : : /* For if (...) { code; } else {} or
4889 : : if (...) { code; } else goto label; or
4890 : : if (...) { code; return; } else { ... }
4891 : : label_cont isn't needed. */
4892 : 3815305 : if (!have_else_clause_p
4893 : 3646002 : && TREE_OPERAND (expr, 2) != NULL_TREE
4894 : 6282327 : && gimple_seq_may_fallthru (seq))
4895 : : {
4896 : 1677223 : gimple *g;
4897 : 1677223 : label_cont = create_artificial_label (UNKNOWN_LOCATION);
4898 : :
4899 : : /* For if (0) { non-side-effect-code } else { code }
4900 : : tell -Wimplicit-fallthrough handling that label_cont can
4901 : : be only reached through fallthrough from { code }. */
4902 : 1677223 : if (integer_zerop (COND_EXPR_COND (expr)))
4903 : : {
4904 : 50220 : UNUSED_LABEL_P (label_true) = 1;
4905 : 50220 : if (!then_side_effects)
4906 : 11162 : UNUSED_LABEL_P (label_cont) = 1;
4907 : : }
4908 : :
4909 : 1677223 : g = gimple_build_goto (label_cont);
4910 : :
4911 : : /* GIMPLE_COND's are very low level; they have embedded
4912 : : gotos. This particular embedded goto should not be marked
4913 : : with the location of the original COND_EXPR, as it would
4914 : : correspond to the COND_EXPR's condition, not the ELSE or the
4915 : : THEN arms. To avoid marking it with the wrong location, flag
4916 : : it as "no location". */
4917 : 1677223 : gimple_set_do_not_emit_location (g);
4918 : :
4919 : 1677223 : gimplify_seq_add_stmt (&seq, g);
4920 : : }
4921 : : }
4922 : : }
4923 : 4934104 : if (!have_else_clause_p)
4924 : : {
4925 : : /* For if (1) { code } or if (1) { code } else { non-side-effect-code }
4926 : : tell -Wimplicit-fallthrough handling that label_false can be only
4927 : : reached through fallthrough from { code }. */
4928 : 4300684 : if (integer_nonzerop (COND_EXPR_COND (expr))
4929 : 4300684 : && (TREE_OPERAND (expr, 2) == NULL_TREE
4930 : 55303 : || !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2))))
4931 : 6396 : UNUSED_LABEL_P (label_false) = 1;
4932 : 4300684 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_false));
4933 : 4300684 : have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq);
4934 : : }
4935 : 4934104 : if (label_cont)
4936 : 1677922 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_cont));
4937 : :
4938 : 4934104 : gimple_pop_condition (pre_p);
4939 : 4934104 : gimple_seq_add_seq (pre_p, seq);
4940 : :
4941 : 4934104 : if (ret == GS_ERROR)
4942 : : ; /* Do nothing. */
4943 : 4934104 : else if (have_then_clause_p || have_else_clause_p)
4944 : : ret = GS_ALL_DONE;
4945 : : else
4946 : : {
4947 : : /* Both arms are empty; replace the COND_EXPR with its predicate. */
4948 : 2795 : expr = TREE_OPERAND (expr, 0);
4949 : 2795 : gimplify_stmt (&expr, pre_p);
4950 : : }
4951 : :
4952 : 4934104 : *expr_p = NULL;
4953 : 4934104 : return ret;
4954 : : }
4955 : :
4956 : : /* Prepare the node pointed to by EXPR_P, an is_gimple_addressable expression,
4957 : : to be marked addressable.
4958 : :
4959 : : We cannot rely on such an expression being directly markable if a temporary
4960 : : has been created by the gimplification. In this case, we create another
4961 : : temporary and initialize it with a copy, which will become a store after we
4962 : : mark it addressable. This can happen if the front-end passed us something
4963 : : that it could not mark addressable yet, like a Fortran pass-by-reference
4964 : : parameter (int) floatvar. */
4965 : :
4966 : : static void
4967 : 49396184 : prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
4968 : : {
4969 : 54074136 : while (handled_component_p (*expr_p))
4970 : 4677952 : expr_p = &TREE_OPERAND (*expr_p, 0);
4971 : :
4972 : : /* Do not allow an SSA name as the temporary. */
4973 : 49396184 : if (is_gimple_reg (*expr_p))
4974 : 11718 : *expr_p = internal_get_tmp_var (*expr_p, seq_p, NULL, false, false, true);
4975 : 49396184 : }
4976 : :
4977 : : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
4978 : : a call to __builtin_memcpy. */
4979 : :
4980 : : static enum gimplify_status
4981 : 1067 : gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
4982 : : gimple_seq *seq_p)
4983 : : {
4984 : 1067 : tree t, to, to_ptr, from, from_ptr;
4985 : 1067 : gcall *gs;
4986 : 1067 : location_t loc = EXPR_LOCATION (*expr_p);
4987 : :
4988 : 1067 : to = TREE_OPERAND (*expr_p, 0);
4989 : 1067 : from = TREE_OPERAND (*expr_p, 1);
4990 : 1067 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to)))
4991 : : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))));
4992 : :
4993 : : /* Mark the RHS addressable. Beware that it may not be possible to do so
4994 : : directly if a temporary has been created by the gimplification. */
4995 : 1067 : prepare_gimple_addressable (&from, seq_p);
4996 : :
4997 : 1067 : mark_addressable (from);
4998 : 1067 : from_ptr = build_fold_addr_expr_loc (loc, from);
4999 : 1067 : gimplify_arg (&from_ptr, seq_p, loc);
5000 : :
5001 : 1067 : mark_addressable (to);
5002 : 1067 : to_ptr = build_fold_addr_expr_loc (loc, to);
5003 : 1067 : gimplify_arg (&to_ptr, seq_p, loc);
5004 : :
5005 : 1067 : t = builtin_decl_implicit (BUILT_IN_MEMCPY);
5006 : :
5007 : 1067 : gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
5008 : 1067 : gimple_call_set_alloca_for_var (gs, true);
5009 : :
5010 : 1067 : if (want_value)
5011 : : {
5012 : : /* tmp = memcpy() */
5013 : 8 : t = create_tmp_var (TREE_TYPE (to_ptr));
5014 : 8 : gimple_call_set_lhs (gs, t);
5015 : 8 : gimplify_seq_add_stmt (seq_p, gs);
5016 : :
5017 : 8 : *expr_p = build_simple_mem_ref (t);
5018 : 8 : return GS_ALL_DONE;
5019 : : }
5020 : :
5021 : 1059 : gimplify_seq_add_stmt (seq_p, gs);
5022 : 1059 : *expr_p = NULL;
5023 : 1059 : return GS_ALL_DONE;
5024 : : }
5025 : :
5026 : : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5027 : : a call to __builtin_memset. In this case we know that the RHS is
5028 : : a CONSTRUCTOR with an empty element list. */
5029 : :
5030 : : static enum gimplify_status
5031 : 57 : gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
5032 : : gimple_seq *seq_p)
5033 : : {
5034 : 57 : tree t, from, to, to_ptr;
5035 : 57 : gcall *gs;
5036 : 57 : location_t loc = EXPR_LOCATION (*expr_p);
5037 : :
5038 : : /* Assert our assumptions, to abort instead of producing wrong code
5039 : : silently if they are not met. Beware that the RHS CONSTRUCTOR might
5040 : : not be immediately exposed. */
5041 : 57 : from = TREE_OPERAND (*expr_p, 1);
5042 : 57 : if (TREE_CODE (from) == WITH_SIZE_EXPR)
5043 : 57 : from = TREE_OPERAND (from, 0);
5044 : :
5045 : 57 : gcc_assert (TREE_CODE (from) == CONSTRUCTOR
5046 : : && vec_safe_is_empty (CONSTRUCTOR_ELTS (from)));
5047 : :
5048 : : /* Now proceed. */
5049 : 57 : to = TREE_OPERAND (*expr_p, 0);
5050 : 57 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to))));
5051 : :
5052 : 57 : to_ptr = build_fold_addr_expr_loc (loc, to);
5053 : 57 : gimplify_arg (&to_ptr, seq_p, loc);
5054 : 57 : t = builtin_decl_implicit (BUILT_IN_MEMSET);
5055 : :
5056 : 57 : gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
5057 : :
5058 : 57 : if (want_value)
5059 : : {
5060 : : /* tmp = memset() */
5061 : 0 : t = create_tmp_var (TREE_TYPE (to_ptr));
5062 : 0 : gimple_call_set_lhs (gs, t);
5063 : 0 : gimplify_seq_add_stmt (seq_p, gs);
5064 : :
5065 : 0 : *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
5066 : 0 : return GS_ALL_DONE;
5067 : : }
5068 : :
5069 : 57 : gimplify_seq_add_stmt (seq_p, gs);
5070 : 57 : *expr_p = NULL;
5071 : 57 : return GS_ALL_DONE;
5072 : : }
5073 : :
5074 : : /* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
5075 : : determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
5076 : : assignment. Return non-null if we detect a potential overlap. */
5077 : :
5078 : : struct gimplify_init_ctor_preeval_data
5079 : : {
5080 : : /* The base decl of the lhs object. May be NULL, in which case we
5081 : : have to assume the lhs is indirect. */
5082 : : tree lhs_base_decl;
5083 : :
5084 : : /* The alias set of the lhs object. */
5085 : : alias_set_type lhs_alias_set;
5086 : : };
5087 : :
5088 : : static tree
5089 : 114196 : gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
5090 : : {
5091 : 114196 : struct gimplify_init_ctor_preeval_data *data
5092 : : = (struct gimplify_init_ctor_preeval_data *) xdata;
5093 : 114196 : tree t = *tp;
5094 : :
5095 : : /* If we find the base object, obviously we have overlap. */
5096 : 114196 : if (data->lhs_base_decl == t)
5097 : : return t;
5098 : :
5099 : : /* If the constructor component is indirect, determine if we have a
5100 : : potential overlap with the lhs. The only bits of information we
5101 : : have to go on at this point are addressability and alias sets. */
5102 : 114195 : if ((INDIRECT_REF_P (t)
5103 : 114195 : || TREE_CODE (t) == MEM_REF)
5104 : 643 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5105 : 114707 : && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
5106 : : return t;
5107 : :
5108 : : /* If the constructor component is a call, determine if it can hide a
5109 : : potential overlap with the lhs through an INDIRECT_REF like above.
5110 : : ??? Ugh - this is completely broken. In fact this whole analysis
5111 : : doesn't look conservative. */
5112 : 113683 : if (TREE_CODE (t) == CALL_EXPR)
5113 : : {
5114 : 0 : tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
5115 : :
5116 : 0 : for (type = TYPE_ARG_TYPES (fntype); type; type = TREE_CHAIN (type))
5117 : 0 : if (POINTER_TYPE_P (TREE_VALUE (type))
5118 : 0 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5119 : 0 : && alias_sets_conflict_p (data->lhs_alias_set,
5120 : : get_alias_set
5121 : 0 : (TREE_TYPE (TREE_VALUE (type)))))
5122 : : return t;
5123 : : }
5124 : :
5125 : 113683 : if (IS_TYPE_OR_DECL_P (t))
5126 : 10978 : *walk_subtrees = 0;
5127 : : return NULL;
5128 : : }
5129 : :
5130 : : /* A subroutine of gimplify_init_constructor. Pre-evaluate EXPR,
5131 : : force values that overlap with the lhs (as described by *DATA)
5132 : : into temporaries. */
5133 : :
5134 : : static void
5135 : 381409 : gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
5136 : : struct gimplify_init_ctor_preeval_data *data)
5137 : : {
5138 : 381409 : enum gimplify_status one;
5139 : :
5140 : : /* If the value is constant, then there's nothing to pre-evaluate. */
5141 : 381409 : if (TREE_CONSTANT (*expr_p))
5142 : : {
5143 : : /* Ensure it does not have side effects, it might contain a reference to
5144 : : the object we're initializing. */
5145 : 168382 : gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
5146 : : return;
5147 : : }
5148 : :
5149 : : /* If the type has non-trivial constructors, we can't pre-evaluate. */
5150 : 213027 : if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
5151 : : return;
5152 : :
5153 : : /* Recurse for nested constructors. */
5154 : 213027 : if (TREE_CODE (*expr_p) == CONSTRUCTOR)
5155 : : {
5156 : 71570 : unsigned HOST_WIDE_INT ix;
5157 : 71570 : constructor_elt *ce;
5158 : 71570 : vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (*expr_p);
5159 : :
5160 : 263509 : FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
5161 : 191939 : gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
5162 : :
5163 : : return;
5164 : : }
5165 : :
5166 : : /* If this is a variable sized type, we must remember the size. */
5167 : 141457 : maybe_with_size_expr (expr_p);
5168 : :
5169 : : /* Gimplify the constructor element to something appropriate for the rhs
5170 : : of a MODIFY_EXPR. Given that we know the LHS is an aggregate, we know
5171 : : the gimplifier will consider this a store to memory. Doing this
5172 : : gimplification now means that we won't have to deal with complicated
5173 : : language-specific trees, nor trees like SAVE_EXPR that can induce
5174 : : exponential search behavior. */
5175 : 141457 : one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
5176 : 141457 : if (one == GS_ERROR)
5177 : : {
5178 : 0 : *expr_p = NULL;
5179 : 0 : return;
5180 : : }
5181 : :
5182 : : /* If we gimplified to a bare decl, we can be sure that it doesn't overlap
5183 : : with the lhs, since "a = { .x=a }" doesn't make sense. This will
5184 : : always be true for all scalars, since is_gimple_mem_rhs insists on a
5185 : : temporary variable for them. */
5186 : 141457 : if (DECL_P (*expr_p))
5187 : : return;
5188 : :
5189 : : /* If this is of variable size, we have no choice but to assume it doesn't
5190 : : overlap since we can't make a temporary for it. */
5191 : 102638 : if (TREE_CODE (TYPE_SIZE (TREE_TYPE (*expr_p))) != INTEGER_CST)
5192 : : return;
5193 : :
5194 : : /* Otherwise, we must search for overlap ... */
5195 : 102638 : if (!walk_tree (expr_p, gimplify_init_ctor_preeval_1, data, NULL))
5196 : : return;
5197 : :
5198 : : /* ... and if found, force the value into a temporary. */
5199 : 513 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
5200 : : }
5201 : :
5202 : : /* A subroutine of gimplify_init_ctor_eval. Create a loop for
5203 : : a RANGE_EXPR in a CONSTRUCTOR for an array.
5204 : :
5205 : : var = lower;
5206 : : loop_entry:
5207 : : object[var] = value;
5208 : : if (var == upper)
5209 : : goto loop_exit;
5210 : : var = var + 1;
5211 : : goto loop_entry;
5212 : : loop_exit:
5213 : :
5214 : : We increment var _after_ the loop exit check because we might otherwise
5215 : : fail if upper == TYPE_MAX_VALUE (type for upper).
5216 : :
5217 : : Note that we never have to deal with SAVE_EXPRs here, because this has
5218 : : already been taken care of for us, in gimplify_init_ctor_preeval(). */
5219 : :
5220 : : static void gimplify_init_ctor_eval (tree, vec<constructor_elt, va_gc> *,
5221 : : gimple_seq *, bool);
5222 : :
5223 : : static void
5224 : 385 : gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
5225 : : tree value, tree array_elt_type,
5226 : : gimple_seq *pre_p, bool cleared)
5227 : : {
5228 : 385 : tree loop_entry_label, loop_exit_label, fall_thru_label;
5229 : 385 : tree var, var_type, cref, tmp;
5230 : :
5231 : 385 : loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
5232 : 385 : loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
5233 : 385 : fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
5234 : :
5235 : : /* Create and initialize the index variable. */
5236 : 385 : var_type = TREE_TYPE (upper);
5237 : 385 : var = create_tmp_var (var_type);
5238 : 385 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
5239 : :
5240 : : /* Add the loop entry label. */
5241 : 385 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
5242 : :
5243 : : /* Build the reference. */
5244 : 385 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
5245 : : var, NULL_TREE, NULL_TREE);
5246 : :
5247 : : /* If we are a constructor, just call gimplify_init_ctor_eval to do
5248 : : the store. Otherwise just assign value to the reference. */
5249 : :
5250 : 385 : if (TREE_CODE (value) == CONSTRUCTOR)
5251 : : /* NB we might have to call ourself recursively through
5252 : : gimplify_init_ctor_eval if the value is a constructor. */
5253 : 98 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
5254 : : pre_p, cleared);
5255 : : else
5256 : : {
5257 : 287 : if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue)
5258 : : != GS_ERROR)
5259 : 287 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
5260 : : }
5261 : :
5262 : : /* We exit the loop when the index var is equal to the upper bound. */
5263 : 770 : gimplify_seq_add_stmt (pre_p,
5264 : 385 : gimple_build_cond (EQ_EXPR, var, upper,
5265 : : loop_exit_label, fall_thru_label));
5266 : :
5267 : 385 : gimplify_seq_add_stmt (pre_p, gimple_build_label (fall_thru_label));
5268 : :
5269 : : /* Otherwise, increment the index var... */
5270 : 385 : tmp = build2 (PLUS_EXPR, var_type, var,
5271 : : fold_convert (var_type, integer_one_node));
5272 : 385 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
5273 : :
5274 : : /* ...and jump back to the loop entry. */
5275 : 385 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
5276 : :
5277 : : /* Add the loop exit label. */
5278 : 385 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
5279 : 385 : }
5280 : :
5281 : : /* A subroutine of gimplify_init_constructor. Generate individual
5282 : : MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the
5283 : : assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the
5284 : : CONSTRUCTOR. CLEARED is true if the entire LHS object has been
5285 : : zeroed first. */
5286 : :
5287 : : static void
5288 : 1132325 : gimplify_init_ctor_eval (tree object, vec<constructor_elt, va_gc> *elts,
5289 : : gimple_seq *pre_p, bool cleared)
5290 : : {
5291 : 1132325 : tree array_elt_type = NULL;
5292 : 1132325 : unsigned HOST_WIDE_INT ix;
5293 : 1132325 : tree purpose, value;
5294 : :
5295 : 1132325 : if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
5296 : 131484 : array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
5297 : :
5298 : 4150435 : FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
5299 : : {
5300 : 3018110 : tree cref;
5301 : :
5302 : : /* NULL values are created above for gimplification errors. */
5303 : 3018110 : if (value == NULL)
5304 : 0 : continue;
5305 : :
5306 : 3018110 : if (cleared && initializer_zerop (value))
5307 : 259473 : continue;
5308 : :
5309 : : /* ??? Here's to hoping the front end fills in all of the indices,
5310 : : so we don't have to figure out what's missing ourselves. */
5311 : 2758637 : gcc_assert (purpose);
5312 : :
5313 : : /* Skip zero-sized fields, unless value has side-effects. This can
5314 : : happen with calls to functions returning a empty type, which
5315 : : we shouldn't discard. As a number of downstream passes don't
5316 : : expect sets of empty type fields, we rely on the gimplification of
5317 : : the MODIFY_EXPR we make below to drop the assignment statement. */
5318 : 2758637 : if (!TREE_SIDE_EFFECTS (value)
5319 : 2471532 : && TREE_CODE (purpose) == FIELD_DECL
5320 : 4861155 : && is_empty_type (TREE_TYPE (purpose)))
5321 : 8924 : continue;
5322 : :
5323 : : /* If we have a RANGE_EXPR, we have to build a loop to assign the
5324 : : whole range. */
5325 : 2749713 : if (TREE_CODE (purpose) == RANGE_EXPR)
5326 : : {
5327 : 395 : tree lower = TREE_OPERAND (purpose, 0);
5328 : 395 : tree upper = TREE_OPERAND (purpose, 1);
5329 : :
5330 : : /* If the lower bound is equal to upper, just treat it as if
5331 : : upper was the index. */
5332 : 395 : if (simple_cst_equal (lower, upper))
5333 : : purpose = upper;
5334 : : else
5335 : : {
5336 : 385 : gimplify_init_ctor_eval_range (object, lower, upper, value,
5337 : : array_elt_type, pre_p, cleared);
5338 : 385 : continue;
5339 : : }
5340 : : }
5341 : :
5342 : 2749328 : if (array_elt_type)
5343 : : {
5344 : : /* Do not use bitsizetype for ARRAY_REF indices. */
5345 : 456965 : if (TYPE_DOMAIN (TREE_TYPE (object)))
5346 : 456965 : purpose
5347 : 456965 : = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
5348 : : purpose);
5349 : 456965 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
5350 : : purpose, NULL_TREE, NULL_TREE);
5351 : : }
5352 : : else
5353 : : {
5354 : 2292363 : gcc_assert (TREE_CODE (purpose) == FIELD_DECL);
5355 : 2292363 : cref = build3 (COMPONENT_REF, TREE_TYPE (purpose),
5356 : : unshare_expr (object), purpose, NULL_TREE);
5357 : : }
5358 : :
5359 : 2749328 : if (TREE_CODE (value) == CONSTRUCTOR
5360 : 2749328 : && TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE)
5361 : 252677 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
5362 : : pre_p, cleared);
5363 : : else
5364 : : {
5365 : 2496651 : tree init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
5366 : 2496651 : gimplify_and_add (init, pre_p);
5367 : 2496651 : ggc_free (init);
5368 : : }
5369 : : }
5370 : 1132325 : }
5371 : :
5372 : : /* Return the appropriate RHS predicate for this LHS. */
5373 : :
5374 : : gimple_predicate
5375 : 43839181 : rhs_predicate_for (tree lhs)
5376 : : {
5377 : 43839181 : if (is_gimple_reg (lhs))
5378 : : return is_gimple_reg_rhs_or_call;
5379 : : else
5380 : 10290756 : return is_gimple_mem_rhs_or_call;
5381 : : }
5382 : :
5383 : : /* Return the initial guess for an appropriate RHS predicate for this LHS,
5384 : : before the LHS has been gimplified. */
5385 : :
5386 : : static gimple_predicate
5387 : 42935960 : initial_rhs_predicate_for (tree lhs)
5388 : : {
5389 : 42935960 : if (is_gimple_reg_type (TREE_TYPE (lhs)))
5390 : : return is_gimple_reg_rhs_or_call;
5391 : : else
5392 : 2138605 : return is_gimple_mem_rhs_or_call;
5393 : : }
5394 : :
5395 : : /* Gimplify a C99 compound literal expression. This just means adding
5396 : : the DECL_EXPR before the current statement and using its anonymous
5397 : : decl instead. */
5398 : :
5399 : : static enum gimplify_status
5400 : 36374 : gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
5401 : : bool (*gimple_test_f) (tree),
5402 : : fallback_t fallback)
5403 : : {
5404 : 36374 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
5405 : 36374 : tree decl = DECL_EXPR_DECL (decl_s);
5406 : 36374 : tree init = DECL_INITIAL (decl);
5407 : : /* Mark the decl as addressable if the compound literal
5408 : : expression is addressable now, otherwise it is marked too late
5409 : : after we gimplify the initialization expression. */
5410 : 36374 : if (TREE_ADDRESSABLE (*expr_p))
5411 : 487 : TREE_ADDRESSABLE (decl) = 1;
5412 : : /* Otherwise, if we don't need an lvalue and have a literal directly
5413 : : substitute it. Check if it matches the gimple predicate, as
5414 : : otherwise we'd generate a new temporary, and we can as well just
5415 : : use the decl we already have. */
5416 : 35887 : else if (!TREE_ADDRESSABLE (decl)
5417 : 35887 : && !TREE_THIS_VOLATILE (decl)
5418 : 35882 : && init
5419 : 35875 : && (fallback & fb_lvalue) == 0
5420 : 71660 : && gimple_test_f (init))
5421 : : {
5422 : 34757 : *expr_p = init;
5423 : 34757 : return GS_OK;
5424 : : }
5425 : :
5426 : : /* If the decl is not addressable, then it is being used in some
5427 : : expression or on the right hand side of a statement, and it can
5428 : : be put into a readonly data section. */
5429 : 1617 : if (!TREE_ADDRESSABLE (decl) && (fallback & fb_lvalue) == 0)
5430 : 1021 : TREE_READONLY (decl) = 1;
5431 : :
5432 : : /* This decl isn't mentioned in the enclosing block, so add it to the
5433 : : list of temps. FIXME it seems a bit of a kludge to say that
5434 : : anonymous artificial vars aren't pushed, but everything else is. */
5435 : 1617 : if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
5436 : 2 : gimple_add_tmp_var (decl);
5437 : :
5438 : 1617 : gimplify_and_add (decl_s, pre_p);
5439 : 1617 : *expr_p = decl;
5440 : 1617 : return GS_OK;
5441 : : }
5442 : :
5443 : : /* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
5444 : : return a new CONSTRUCTOR if something changed. */
5445 : :
5446 : : static tree
5447 : 1656507 : optimize_compound_literals_in_ctor (tree orig_ctor)
5448 : : {
5449 : 1656507 : tree ctor = orig_ctor;
5450 : 1656507 : vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
5451 : 1656507 : unsigned int idx, num = vec_safe_length (elts);
5452 : :
5453 : 5515950 : for (idx = 0; idx < num; idx++)
5454 : : {
5455 : 3859443 : tree value = (*elts)[idx].value;
5456 : 3859443 : tree newval = value;
5457 : 3859443 : if (TREE_CODE (value) == CONSTRUCTOR)
5458 : 464522 : newval = optimize_compound_literals_in_ctor (value);
5459 : 3394921 : else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
5460 : : {
5461 : 79 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
5462 : 79 : tree decl = DECL_EXPR_DECL (decl_s);
5463 : 79 : tree init = DECL_INITIAL (decl);
5464 : :
5465 : 79 : if (!TREE_ADDRESSABLE (value)
5466 : 79 : && !TREE_ADDRESSABLE (decl)
5467 : 79 : && init
5468 : 79 : && TREE_CODE (init) == CONSTRUCTOR)
5469 : 48 : newval = optimize_compound_literals_in_ctor (init);
5470 : : }
5471 : 3859443 : if (newval == value)
5472 : 3859387 : continue;
5473 : :
5474 : 56 : if (ctor == orig_ctor)
5475 : : {
5476 : 45 : ctor = copy_node (orig_ctor);
5477 : 90 : CONSTRUCTOR_ELTS (ctor) = vec_safe_copy (elts);
5478 : 45 : elts = CONSTRUCTOR_ELTS (ctor);
5479 : : }
5480 : 56 : (*elts)[idx].value = newval;
5481 : : }
5482 : 1656507 : return ctor;
5483 : : }
5484 : :
5485 : : /* A subroutine of gimplify_modify_expr. Break out elements of a
5486 : : CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
5487 : :
5488 : : Note that we still need to clear any elements that don't have explicit
5489 : : initializers, so if not all elements are initialized we keep the
5490 : : original MODIFY_EXPR, we just remove all of the constructor elements.
5491 : :
5492 : : If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
5493 : : GS_ERROR if we would have to create a temporary when gimplifying
5494 : : this constructor. Otherwise, return GS_OK.
5495 : :
5496 : : If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
5497 : :
5498 : : static enum gimplify_status
5499 : 1191937 : gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
5500 : : bool want_value, bool notify_temp_creation)
5501 : : {
5502 : 1191937 : tree object, ctor, type;
5503 : 1191937 : enum gimplify_status ret;
5504 : 1191937 : vec<constructor_elt, va_gc> *elts;
5505 : 1191937 : bool cleared = false;
5506 : 1191937 : bool is_empty_ctor = false;
5507 : 1191937 : bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR);
5508 : :
5509 : 1191937 : gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
5510 : :
5511 : 1191937 : if (!notify_temp_creation)
5512 : : {
5513 : 1187328 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
5514 : : is_gimple_lvalue, fb_lvalue);
5515 : 1187328 : if (ret == GS_ERROR)
5516 : : return ret;
5517 : : }
5518 : :
5519 : 1191937 : object = TREE_OPERAND (*expr_p, 0);
5520 : 1191937 : ctor = TREE_OPERAND (*expr_p, 1)
5521 : 1191937 : = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
5522 : 1191937 : type = TREE_TYPE (ctor);
5523 : 1191937 : elts = CONSTRUCTOR_ELTS (ctor);
5524 : 1191937 : ret = GS_ALL_DONE;
5525 : :
5526 : 1191937 : switch (TREE_CODE (type))
5527 : : {
5528 : 1185645 : case RECORD_TYPE:
5529 : 1185645 : case UNION_TYPE:
5530 : 1185645 : case QUAL_UNION_TYPE:
5531 : 1185645 : case ARRAY_TYPE:
5532 : 1185645 : {
5533 : : /* Use readonly data for initializers of this or smaller size
5534 : : regardless of the num_nonzero_elements / num_unique_nonzero_elements
5535 : : ratio. */
5536 : 1185645 : const HOST_WIDE_INT min_unique_size = 64;
5537 : : /* If num_nonzero_elements / num_unique_nonzero_elements ratio
5538 : : is smaller than this, use readonly data. */
5539 : 1185645 : const int unique_nonzero_ratio = 8;
5540 : : /* True if a single access of the object must be ensured. This is the
5541 : : case if the target is volatile, the type is non-addressable and more
5542 : : than one field need to be assigned. */
5543 : 1185645 : const bool ensure_single_access
5544 : 1185645 : = TREE_THIS_VOLATILE (object)
5545 : 220 : && !TREE_ADDRESSABLE (type)
5546 : 1185829 : && vec_safe_length (elts) > 1;
5547 : 1185645 : struct gimplify_init_ctor_preeval_data preeval_data;
5548 : 1185645 : HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
5549 : 1185645 : HOST_WIDE_INT num_unique_nonzero_elements;
5550 : 1185645 : bool complete_p, valid_const_initializer;
5551 : :
5552 : : /* Aggregate types must lower constructors to initialization of
5553 : : individual elements. The exception is that a CONSTRUCTOR node
5554 : : with no elements indicates zero-initialization of the whole. */
5555 : 1185645 : if (vec_safe_is_empty (elts))
5556 : : {
5557 : 287941 : if (notify_temp_creation)
5558 : 6071 : return GS_OK;
5559 : :
5560 : : /* The var will be initialized and so appear on lhs of
5561 : : assignment, it can't be TREE_READONLY anymore. */
5562 : 287929 : if (VAR_P (object))
5563 : 168606 : TREE_READONLY (object) = 0;
5564 : :
5565 : : is_empty_ctor = true;
5566 : 289314 : break;
5567 : : }
5568 : :
5569 : : /* Fetch information about the constructor to direct later processing.
5570 : : We might want to make static versions of it in various cases, and
5571 : : can only do so if it known to be a valid constant initializer. */
5572 : 897704 : valid_const_initializer
5573 : 897704 : = categorize_ctor_elements (ctor, &num_nonzero_elements,
5574 : : &num_unique_nonzero_elements,
5575 : : &num_ctor_elements, &complete_p);
5576 : :
5577 : : /* If a const aggregate variable is being initialized, then it
5578 : : should never be a lose to promote the variable to be static. */
5579 : 897704 : if (valid_const_initializer
5580 : 530867 : && num_nonzero_elements > 1
5581 : 399808 : && TREE_READONLY (object)
5582 : 3567 : && VAR_P (object)
5583 : 3193 : && !DECL_REGISTER (object)
5584 : 3186 : && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)
5585 : 3005 : || DECL_MERGEABLE (object))
5586 : : /* For ctors that have many repeated nonzero elements
5587 : : represented through RANGE_EXPRs, prefer initializing
5588 : : those through runtime loops over copies of large amounts
5589 : : of data from readonly data section. */
5590 : 897704 : && (num_unique_nonzero_elements
5591 : 1385 : > num_nonzero_elements / unique_nonzero_ratio
5592 : 0 : || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
5593 : : <= (unsigned HOST_WIDE_INT) min_unique_size)))
5594 : : {
5595 : 1385 : if (notify_temp_creation)
5596 : : return GS_ERROR;
5597 : :
5598 : 1385 : DECL_INITIAL (object) = ctor;
5599 : 1385 : TREE_STATIC (object) = 1;
5600 : 1385 : if (!DECL_NAME (object))
5601 : 1219 : DECL_NAME (object) = create_tmp_var_name ("C");
5602 : 1385 : walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL);
5603 : :
5604 : : /* ??? C++ doesn't automatically append a .<number> to the
5605 : : assembler name, and even when it does, it looks at FE private
5606 : : data structures to figure out what that number should be,
5607 : : which are not set for this variable. I suppose this is
5608 : : important for local statics for inline functions, which aren't
5609 : : "local" in the object file sense. So in order to get a unique
5610 : : TU-local symbol, we must invoke the lhd version now. */
5611 : 1385 : lhd_set_decl_assembler_name (object);
5612 : :
5613 : 1385 : *expr_p = NULL_TREE;
5614 : 1385 : break;
5615 : : }
5616 : :
5617 : : /* The var will be initialized and so appear on lhs of
5618 : : assignment, it can't be TREE_READONLY anymore. */
5619 : 896319 : if (VAR_P (object) && !notify_temp_creation)
5620 : 725886 : TREE_READONLY (object) = 0;
5621 : :
5622 : : /* If there are "lots" of initialized elements, even discounting
5623 : : those that are not address constants (and thus *must* be
5624 : : computed at runtime), then partition the constructor into
5625 : : constant and non-constant parts. Block copy the constant
5626 : : parts in, then generate code for the non-constant parts. */
5627 : : /* TODO. There's code in cp/typeck.cc to do this. */
5628 : :
5629 : 896319 : if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
5630 : : /* store_constructor will ignore the clearing of variable-sized
5631 : : objects. Initializers for such objects must explicitly set
5632 : : every field that needs to be set. */
5633 : : cleared = false;
5634 : 896297 : else if (!complete_p)
5635 : : /* If the constructor isn't complete, clear the whole object
5636 : : beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
5637 : :
5638 : : ??? This ought not to be needed. For any element not present
5639 : : in the initializer, we should simply set them to zero. Except
5640 : : we'd need to *find* the elements that are not present, and that
5641 : : requires trickery to avoid quadratic compile-time behavior in
5642 : : large cases or excessive memory use in small cases. */
5643 : 143031 : cleared = !CONSTRUCTOR_NO_CLEARING (ctor);
5644 : 753266 : else if (num_ctor_elements - num_nonzero_elements
5645 : 753266 : > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
5646 : 753266 : && num_nonzero_elements < num_ctor_elements / 4)
5647 : : /* If there are "lots" of zeros, it's more efficient to clear
5648 : : the memory and then set the nonzero elements. */
5649 : : cleared = true;
5650 : 748117 : else if (ensure_single_access && num_nonzero_elements == 0)
5651 : : /* If a single access to the target must be ensured and all elements
5652 : : are zero, then it's optimal to clear whatever their number. */
5653 : : cleared = true;
5654 : : else
5655 : 748134 : cleared = false;
5656 : :
5657 : : /* If there are "lots" of initialized elements, and all of them
5658 : : are valid address constants, then the entire initializer can
5659 : : be dropped to memory, and then memcpy'd out. Don't do this
5660 : : for sparse arrays, though, as it's more efficient to follow
5661 : : the standard CONSTRUCTOR behavior of memset followed by
5662 : : individual element initialization. Also don't do this for small
5663 : : all-zero initializers (which aren't big enough to merit
5664 : : clearing), and don't try to make bitwise copies of
5665 : : TREE_ADDRESSABLE types. */
5666 : 896319 : if (valid_const_initializer
5667 : 529482 : && complete_p
5668 : 400411 : && !(cleared || num_nonzero_elements == 0)
5669 : 304686 : && !TREE_ADDRESSABLE (type))
5670 : : {
5671 : 303871 : HOST_WIDE_INT size = int_size_in_bytes (type);
5672 : 303871 : unsigned int align;
5673 : :
5674 : : /* ??? We can still get unbounded array types, at least
5675 : : from the C++ front end. This seems wrong, but attempt
5676 : : to work around it for now. */
5677 : 303871 : if (size < 0)
5678 : : {
5679 : 10 : size = int_size_in_bytes (TREE_TYPE (object));
5680 : 10 : if (size >= 0)
5681 : 0 : TREE_TYPE (ctor) = type = TREE_TYPE (object);
5682 : : }
5683 : :
5684 : : /* Find the maximum alignment we can assume for the object. */
5685 : : /* ??? Make use of DECL_OFFSET_ALIGN. */
5686 : 303871 : if (DECL_P (object))
5687 : 290548 : align = DECL_ALIGN (object);
5688 : : else
5689 : 13323 : align = TYPE_ALIGN (type);
5690 : :
5691 : : /* Do a block move either if the size is so small as to make
5692 : : each individual move a sub-unit move on average, or if it
5693 : : is so large as to make individual moves inefficient. */
5694 : 303871 : if (size > 0
5695 : 303861 : && num_nonzero_elements > 1
5696 : : /* For ctors that have many repeated nonzero elements
5697 : : represented through RANGE_EXPRs, prefer initializing
5698 : : those through runtime loops over copies of large amounts
5699 : : of data from readonly data section. */
5700 : 284171 : && (num_unique_nonzero_elements
5701 : 284171 : > num_nonzero_elements / unique_nonzero_ratio
5702 : 43 : || size <= min_unique_size)
5703 : 587999 : && (size < num_nonzero_elements
5704 : 284048 : || !can_move_by_pieces (size, align)))
5705 : : {
5706 : 2622 : if (notify_temp_creation)
5707 : : return GS_ERROR;
5708 : :
5709 : 1311 : walk_tree (&ctor, force_labels_r, NULL, NULL);
5710 : 1311 : ctor = tree_output_constant_def (ctor);
5711 : 1311 : if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
5712 : 0 : ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
5713 : 1311 : TREE_OPERAND (*expr_p, 1) = ctor;
5714 : :
5715 : : /* This is no longer an assignment of a CONSTRUCTOR, but
5716 : : we still may have processing to do on the LHS. So
5717 : : pretend we didn't do anything here to let that happen. */
5718 : 1311 : return GS_UNHANDLED;
5719 : : }
5720 : : }
5721 : :
5722 : : /* If a single access to the target must be ensured and there are
5723 : : nonzero elements or the zero elements are not assigned en masse,
5724 : : initialize the target from a temporary. */
5725 : 893697 : if (ensure_single_access && (num_nonzero_elements > 0 || !cleared))
5726 : : {
5727 : 157 : if (notify_temp_creation)
5728 : : return GS_ERROR;
5729 : :
5730 : 151 : tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type));
5731 : 151 : TREE_OPERAND (*expr_p, 0) = temp;
5732 : 151 : *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
5733 : : *expr_p,
5734 : : build2 (MODIFY_EXPR, void_type_node,
5735 : : object, temp));
5736 : 151 : return GS_OK;
5737 : : }
5738 : :
5739 : 893540 : if (notify_temp_creation)
5740 : : return GS_OK;
5741 : :
5742 : : /* If there are nonzero elements and if needed, pre-evaluate to capture
5743 : : elements overlapping with the lhs into temporaries. We must do this
5744 : : before clearing to fetch the values before they are zeroed-out. */
5745 : 890260 : if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
5746 : : {
5747 : 189470 : preeval_data.lhs_base_decl = get_base_address (object);
5748 : 189470 : if (!DECL_P (preeval_data.lhs_base_decl))
5749 : 39942 : preeval_data.lhs_base_decl = NULL;
5750 : 189470 : preeval_data.lhs_alias_set = get_alias_set (object);
5751 : :
5752 : 189470 : gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
5753 : : pre_p, post_p, &preeval_data);
5754 : : }
5755 : :
5756 : 890260 : bool ctor_has_side_effects_p
5757 : 890260 : = TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1));
5758 : :
5759 : 890260 : if (cleared)
5760 : : {
5761 : : /* Zap the CONSTRUCTOR element list, which simplifies this case.
5762 : : Note that we still have to gimplify, in order to handle the
5763 : : case of variable sized types. Avoid shared tree structures. */
5764 : 148031 : CONSTRUCTOR_ELTS (ctor) = NULL;
5765 : 148031 : TREE_SIDE_EFFECTS (ctor) = 0;
5766 : 148031 : object = unshare_expr (object);
5767 : 148031 : gimplify_stmt (expr_p, pre_p);
5768 : : }
5769 : :
5770 : : /* If we have not block cleared the object, or if there are nonzero
5771 : : elements in the constructor, or if the constructor has side effects,
5772 : : add assignments to the individual scalar fields of the object. */
5773 : 890260 : if (!cleared
5774 : 148031 : || num_nonzero_elements > 0
5775 : 10726 : || ctor_has_side_effects_p)
5776 : 879550 : gimplify_init_ctor_eval (object, elts, pre_p, cleared);
5777 : :
5778 : 890260 : *expr_p = NULL_TREE;
5779 : : }
5780 : 890260 : break;
5781 : :
5782 : 0 : case COMPLEX_TYPE:
5783 : 0 : {
5784 : 0 : tree r, i;
5785 : :
5786 : 0 : if (notify_temp_creation)
5787 : : return GS_OK;
5788 : :
5789 : : /* Extract the real and imaginary parts out of the ctor. */
5790 : 0 : gcc_assert (elts->length () == 2);
5791 : 0 : r = (*elts)[0].value;
5792 : 0 : i = (*elts)[1].value;
5793 : 0 : if (r == NULL || i == NULL)
5794 : : {
5795 : 0 : tree zero = build_zero_cst (TREE_TYPE (type));
5796 : 0 : if (r == NULL)
5797 : 0 : r = zero;
5798 : 0 : if (i == NULL)
5799 : 0 : i = zero;
5800 : : }
5801 : :
5802 : : /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to
5803 : : represent creation of a complex value. */
5804 : 0 : if (TREE_CONSTANT (r) && TREE_CONSTANT (i))
5805 : : {
5806 : 0 : ctor = build_complex (type, r, i);
5807 : 0 : TREE_OPERAND (*expr_p, 1) = ctor;
5808 : : }
5809 : : else
5810 : : {
5811 : 0 : ctor = build2 (COMPLEX_EXPR, type, r, i);
5812 : 0 : TREE_OPERAND (*expr_p, 1) = ctor;
5813 : 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1),
5814 : : pre_p,
5815 : : post_p,
5816 : 0 : rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
5817 : : fb_rvalue);
5818 : : }
5819 : : }
5820 : : break;
5821 : :
5822 : 6292 : case VECTOR_TYPE:
5823 : 6292 : {
5824 : 6292 : unsigned HOST_WIDE_INT ix;
5825 : 6292 : constructor_elt *ce;
5826 : :
5827 : 6292 : if (notify_temp_creation)
5828 : 1191937 : return GS_OK;
5829 : :
5830 : : /* Vector types use CONSTRUCTOR all the way through gimple
5831 : : compilation as a general initializer. */
5832 : 58674 : FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
5833 : : {
5834 : 52382 : enum gimplify_status tret;
5835 : 52382 : tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
5836 : : fb_rvalue);
5837 : 52382 : if (tret == GS_ERROR)
5838 : : ret = GS_ERROR;
5839 : 52381 : else if (TREE_STATIC (ctor)
5840 : 52411 : && !initializer_constant_valid_p (ce->value,
5841 : 30 : TREE_TYPE (ce->value)))
5842 : 30 : TREE_STATIC (ctor) = 0;
5843 : : }
5844 : 6292 : recompute_constructor_flags (ctor);
5845 : :
5846 : : /* Go ahead and simplify constant constructors to VECTOR_CST. */
5847 : 6292 : if (TREE_CONSTANT (ctor))
5848 : : {
5849 : 395 : bool constant_p = true;
5850 : : tree value;
5851 : :
5852 : : /* Even when ctor is constant, it might contain non-*_CST
5853 : : elements, such as addresses or trapping values like
5854 : : 1.0/0.0 - 1.0/0.0. Such expressions don't belong
5855 : : in VECTOR_CST nodes. */
5856 : 395 : FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
5857 : 238 : if (!CONSTANT_CLASS_P (value))
5858 : : {
5859 : : constant_p = false;
5860 : : break;
5861 : : }
5862 : :
5863 : 157 : if (constant_p)
5864 : : {
5865 : 157 : TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts);
5866 : 157 : break;
5867 : : }
5868 : : }
5869 : :
5870 : 6135 : if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
5871 : 892 : TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
5872 : : }
5873 : : break;
5874 : :
5875 : 0 : default:
5876 : : /* So how did we get a CONSTRUCTOR for a scalar type? */
5877 : 0 : gcc_unreachable ();
5878 : : }
5879 : :
5880 : 1185866 : if (ret == GS_ERROR)
5881 : : return GS_ERROR;
5882 : : /* If we have gimplified both sides of the initializer but have
5883 : : not emitted an assignment, do so now. */
5884 : 1185865 : if (*expr_p
5885 : : /* If the type is an empty type, we don't need to emit the
5886 : : assignment. */
5887 : 1185865 : && !is_empty_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
5888 : : {
5889 : 290992 : tree lhs = TREE_OPERAND (*expr_p, 0);
5890 : 290992 : tree rhs = TREE_OPERAND (*expr_p, 1);
5891 : 290992 : if (want_value && object == lhs)
5892 : 12 : lhs = unshare_expr (lhs);
5893 : 290992 : gassign *init = gimple_build_assign (lhs, rhs);
5894 : 290992 : gimplify_seq_add_stmt (pre_p, init);
5895 : : }
5896 : 1185865 : if (want_value)
5897 : : {
5898 : 19 : *expr_p = object;
5899 : 19 : ret = GS_OK;
5900 : : }
5901 : : else
5902 : : {
5903 : 1185846 : *expr_p = NULL;
5904 : 1185846 : ret = GS_ALL_DONE;
5905 : : }
5906 : :
5907 : : /* If the user requests to initialize automatic variables, we
5908 : : should initialize paddings inside the variable. Add a call to
5909 : : __builtin_clear_pading (&object, 0, for_auto_init = true) to
5910 : : initialize paddings of object always to zero regardless of
5911 : : INIT_TYPE. Note, we will not insert this call if the aggregate
5912 : : variable has be completely cleared already or it's initialized
5913 : : with an empty constructor. We cannot insert this call if the
5914 : : variable is a gimple register since __builtin_clear_padding will take
5915 : : the address of the variable. As a result, if a long double/_Complex long
5916 : : double variable will be spilled into stack later, its padding cannot
5917 : : be cleared with __builtin_clear_padding. We should clear its padding
5918 : : when it is spilled into memory. */
5919 : 1185865 : if (is_init_expr
5920 : 861930 : && !is_gimple_reg (object)
5921 : 858091 : && clear_padding_type_may_have_padding_p (type)
5922 : 822757 : && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
5923 : 189895 : || !AGGREGATE_TYPE_P (type))
5924 : 1818727 : && is_var_need_auto_init (object))
5925 : 44 : gimple_add_padding_init_for_auto_var (object, false, pre_p);
5926 : :
5927 : : return ret;
5928 : : }
5929 : :
5930 : : /* Given a pointer value OP0, return a simplified version of an
5931 : : indirection through OP0, or NULL_TREE if no simplification is
5932 : : possible. This may only be applied to a rhs of an expression.
5933 : : Note that the resulting type may be different from the type pointed
5934 : : to in the sense that it is still compatible from the langhooks
5935 : : point of view. */
5936 : :
5937 : : static tree
5938 : 494541 : gimple_fold_indirect_ref_rhs (tree t)
5939 : : {
5940 : 0 : return gimple_fold_indirect_ref (t);
5941 : : }
5942 : :
5943 : : /* Subroutine of gimplify_modify_expr to do simplifications of
5944 : : MODIFY_EXPRs based on the code of the RHS. We loop for as long as
5945 : : something changes. */
5946 : :
5947 : : static enum gimplify_status
5948 : 87584891 : gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
5949 : : gimple_seq *pre_p, gimple_seq *post_p,
5950 : : bool want_value)
5951 : : {
5952 : 87584891 : enum gimplify_status ret = GS_UNHANDLED;
5953 : 88156810 : bool changed;
5954 : :
5955 : 86956686 : do
5956 : : {
5957 : 88156810 : changed = false;
5958 : 88156810 : switch (TREE_CODE (*from_p))
5959 : : {
5960 : 11359483 : case VAR_DECL:
5961 : : /* If we're assigning from a read-only variable initialized with
5962 : : a constructor and not volatile, do the direct assignment from
5963 : : the constructor, but only if the target is not volatile either
5964 : : since this latter assignment might end up being done on a per
5965 : : field basis. However, if the target is volatile and the type
5966 : : is aggregate and non-addressable, gimplify_init_constructor
5967 : : knows that it needs to ensure a single access to the target
5968 : : and it will return GS_OK only in this case. */
5969 : 11359483 : if (TREE_READONLY (*from_p)
5970 : 91874 : && DECL_INITIAL (*from_p)
5971 : 61909 : && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR
5972 : 4609 : && !TREE_THIS_VOLATILE (*from_p)
5973 : 11364092 : && (!TREE_THIS_VOLATILE (*to_p)
5974 : 6 : || (AGGREGATE_TYPE_P (TREE_TYPE (*to_p))
5975 : 6 : && !TREE_ADDRESSABLE (TREE_TYPE (*to_p)))))
5976 : : {
5977 : 4609 : tree old_from = *from_p;
5978 : 4609 : enum gimplify_status subret;
5979 : :
5980 : : /* Move the constructor into the RHS. */
5981 : 4609 : *from_p = unshare_expr (DECL_INITIAL (*from_p));
5982 : :
5983 : : /* Let's see if gimplify_init_constructor will need to put
5984 : : it in memory. */
5985 : 4609 : subret = gimplify_init_constructor (expr_p, NULL, NULL,
5986 : : false, true);
5987 : 4609 : if (subret == GS_ERROR)
5988 : : {
5989 : : /* If so, revert the change. */
5990 : 1317 : *from_p = old_from;
5991 : : }
5992 : : else
5993 : : {
5994 : : ret = GS_OK;
5995 : : changed = true;
5996 : : }
5997 : : }
5998 : : break;
5999 : 496259 : case INDIRECT_REF:
6000 : 496259 : if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
6001 : : /* If we have code like
6002 : :
6003 : : *(const A*)(A*)&x
6004 : :
6005 : : where the type of "x" is a (possibly cv-qualified variant
6006 : : of "A"), treat the entire expression as identical to "x".
6007 : : This kind of code arises in C++ when an object is bound
6008 : : to a const reference, and if "x" is a TARGET_EXPR we want
6009 : : to take advantage of the optimization below. But not if
6010 : : the type is TREE_ADDRESSABLE; then C++17 says that the
6011 : : TARGET_EXPR needs to be a temporary. */
6012 : 989082 : if (tree t
6013 : 494541 : = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)))
6014 : : {
6015 : 116269 : bool volatile_p = TREE_THIS_VOLATILE (*from_p);
6016 : 116269 : if (TREE_THIS_VOLATILE (t) != volatile_p)
6017 : : {
6018 : 5 : if (DECL_P (t))
6019 : 0 : t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
6020 : : build_fold_addr_expr (t));
6021 : 5 : if (REFERENCE_CLASS_P (t))
6022 : 5 : TREE_THIS_VOLATILE (t) = volatile_p;
6023 : : }
6024 : 116269 : *from_p = t;
6025 : 116269 : ret = GS_OK;
6026 : 116269 : changed = true;
6027 : : }
6028 : : break;
6029 : :
6030 : 157518 : case TARGET_EXPR:
6031 : 157518 : {
6032 : : /* If we are initializing something from a TARGET_EXPR, strip the
6033 : : TARGET_EXPR and initialize it directly, if possible. This can't
6034 : : be done if the initializer is void, since that implies that the
6035 : : temporary is set in some non-trivial way.
6036 : :
6037 : : ??? What about code that pulls out the temp and uses it
6038 : : elsewhere? I think that such code never uses the TARGET_EXPR as
6039 : : an initializer. If I'm wrong, we'll die because the temp won't
6040 : : have any RTL. In that case, I guess we'll need to replace
6041 : : references somehow. */
6042 : 157518 : tree init = TARGET_EXPR_INITIAL (*from_p);
6043 : :
6044 : 157518 : if (init
6045 : 156815 : && (TREE_CODE (*expr_p) != MODIFY_EXPR
6046 : 51241 : || !TARGET_EXPR_NO_ELIDE (*from_p))
6047 : 314039 : && !VOID_TYPE_P (TREE_TYPE (init)))
6048 : : {
6049 : 136811 : *from_p = init;
6050 : 136811 : ret = GS_OK;
6051 : 136811 : changed = true;
6052 : : }
6053 : : }
6054 : : break;
6055 : :
6056 : 315361 : case COMPOUND_EXPR:
6057 : : /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
6058 : : caught. */
6059 : 315361 : gimplify_compound_expr (from_p, pre_p, true);
6060 : 315361 : ret = GS_OK;
6061 : 315361 : changed = true;
6062 : 315361 : break;
6063 : :
6064 : 1198577 : case CONSTRUCTOR:
6065 : : /* If we already made some changes, let the front end have a
6066 : : crack at this before we break it down. */
6067 : 1198577 : if (ret != GS_UNHANDLED)
6068 : : break;
6069 : :
6070 : : /* If we're initializing from a CONSTRUCTOR, break this into
6071 : : individual MODIFY_EXPRs. */
6072 : 1187328 : ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
6073 : : false);
6074 : 1187328 : return ret;
6075 : :
6076 : 171193 : case COND_EXPR:
6077 : : /* If we're assigning to a non-register type, push the assignment
6078 : : down into the branches. This is mandatory for ADDRESSABLE types,
6079 : : since we cannot generate temporaries for such, but it saves a
6080 : : copy in other cases as well. */
6081 : 171193 : if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
6082 : : {
6083 : : /* This code should mirror the code in gimplify_cond_expr. */
6084 : 7298 : enum tree_code code = TREE_CODE (*expr_p);
6085 : 7298 : tree cond = *from_p;
6086 : 7298 : tree result = *to_p;
6087 : :
6088 : 7298 : ret = gimplify_expr (&result, pre_p, post_p,
6089 : : is_gimple_lvalue, fb_lvalue);
6090 : 7298 : if (ret != GS_ERROR)
6091 : 7298 : ret = GS_OK;
6092 : :
6093 : : /* If we are going to write RESULT more than once, clear
6094 : : TREE_READONLY flag, otherwise we might incorrectly promote
6095 : : the variable to static const and initialize it at compile
6096 : : time in one of the branches. */
6097 : 7298 : if (VAR_P (result)
6098 : 7013 : && TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node
6099 : 14295 : && TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6100 : 6965 : TREE_READONLY (result) = 0;
6101 : 7298 : if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
6102 : 7282 : TREE_OPERAND (cond, 1)
6103 : 14564 : = build2 (code, void_type_node, result,
6104 : 7282 : TREE_OPERAND (cond, 1));
6105 : 7298 : if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
6106 : 7266 : TREE_OPERAND (cond, 2)
6107 : 14532 : = build2 (code, void_type_node, unshare_expr (result),
6108 : 7266 : TREE_OPERAND (cond, 2));
6109 : :
6110 : 7298 : TREE_TYPE (cond) = void_type_node;
6111 : 7298 : recalculate_side_effects (cond);
6112 : :
6113 : 7298 : if (want_value)
6114 : : {
6115 : 0 : gimplify_and_add (cond, pre_p);
6116 : 0 : *expr_p = unshare_expr (result);
6117 : : }
6118 : : else
6119 : 7298 : *expr_p = cond;
6120 : 7298 : return ret;
6121 : : }
6122 : : break;
6123 : :
6124 : 8511758 : case CALL_EXPR:
6125 : : /* For calls that return in memory, give *to_p as the CALL_EXPR's
6126 : : return slot so that we don't generate a temporary. */
6127 : 8511758 : if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
6128 : 8511758 : && aggregate_value_p (*from_p, *from_p))
6129 : : {
6130 : 233610 : bool use_target;
6131 : :
6132 : 233610 : if (!(rhs_predicate_for (*to_p))(*from_p))
6133 : : /* If we need a temporary, *to_p isn't accurate. */
6134 : : use_target = false;
6135 : : /* It's OK to use the return slot directly unless it's an NRV. */
6136 : 232875 : else if (TREE_CODE (*to_p) == RESULT_DECL
6137 : 2661 : && DECL_NAME (*to_p) == NULL_TREE
6138 : 235435 : && needs_to_live_in_memory (*to_p))
6139 : : use_target = true;
6140 : 230315 : else if (is_gimple_reg_type (TREE_TYPE (*to_p))
6141 : 230315 : || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
6142 : : /* Don't force regs into memory. */
6143 : : use_target = false;
6144 : 216357 : else if (TREE_CODE (*expr_p) == INIT_EXPR)
6145 : : /* It's OK to use the target directly if it's being
6146 : : initialized. */
6147 : : use_target = true;
6148 : 13088 : else if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p)))
6149 : : != INTEGER_CST)
6150 : : /* Always use the target and thus RSO for variable-sized types.
6151 : : GIMPLE cannot deal with a variable-sized assignment
6152 : : embedded in a call statement. */
6153 : : use_target = true;
6154 : 13062 : else if (TREE_CODE (*to_p) != SSA_NAME
6155 : 13062 : && (!is_gimple_variable (*to_p)
6156 : 9908 : || needs_to_live_in_memory (*to_p)))
6157 : : /* Don't use the original target if it's already addressable;
6158 : : if its address escapes, and the called function uses the
6159 : : NRV optimization, a conforming program could see *to_p
6160 : : change before the called function returns; see c++/19317.
6161 : : When optimizing, the return_slot pass marks more functions
6162 : : as safe after we have escape info. */
6163 : : use_target = false;
6164 : : else
6165 : : use_target = true;
6166 : :
6167 : : if (use_target)
6168 : : {
6169 : 207830 : CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
6170 : 207830 : mark_addressable (*to_p);
6171 : : }
6172 : : }
6173 : : break;
6174 : :
6175 : 1348 : case WITH_SIZE_EXPR:
6176 : : /* Likewise for calls that return an aggregate of non-constant size,
6177 : : since we would not be able to generate a temporary at all. */
6178 : 1348 : if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
6179 : : {
6180 : 181 : *from_p = TREE_OPERAND (*from_p, 0);
6181 : : /* We don't change ret in this case because the
6182 : : WITH_SIZE_EXPR might have been added in
6183 : : gimplify_modify_expr, so returning GS_OK would lead to an
6184 : : infinite loop. */
6185 : 181 : changed = true;
6186 : : }
6187 : : break;
6188 : :
6189 : : /* If we're initializing from a container, push the initialization
6190 : : inside it. */
6191 : 1652 : case CLEANUP_POINT_EXPR:
6192 : 1652 : case BIND_EXPR:
6193 : 1652 : case STATEMENT_LIST:
6194 : 1652 : {
6195 : 1652 : tree wrap = *from_p;
6196 : 1652 : tree t;
6197 : :
6198 : 1652 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
6199 : : fb_lvalue);
6200 : 1652 : if (ret != GS_ERROR)
6201 : 1652 : ret = GS_OK;
6202 : :
6203 : 1652 : t = voidify_wrapper_expr (wrap, *expr_p);
6204 : 1652 : gcc_assert (t == *expr_p);
6205 : :
6206 : 1652 : if (want_value)
6207 : : {
6208 : 8 : gimplify_and_add (wrap, pre_p);
6209 : 8 : *expr_p = unshare_expr (*to_p);
6210 : : }
6211 : : else
6212 : 1644 : *expr_p = wrap;
6213 : : return GS_OK;
6214 : : }
6215 : :
6216 : 8676817 : case NOP_EXPR:
6217 : : /* Pull out compound literal expressions from a NOP_EXPR.
6218 : : Those are created in the C FE to drop qualifiers during
6219 : : lvalue conversion. */
6220 : 8676817 : if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR)
6221 : 8676817 : && tree_ssa_useless_type_conversion (*from_p))
6222 : : {
6223 : 5 : *from_p = TREE_OPERAND (*from_p, 0);
6224 : 5 : ret = GS_OK;
6225 : 5 : changed = true;
6226 : : }
6227 : : break;
6228 : :
6229 : 3846 : case COMPOUND_LITERAL_EXPR:
6230 : 3846 : {
6231 : 3846 : tree complit = TREE_OPERAND (*expr_p, 1);
6232 : 3846 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
6233 : 3846 : tree decl = DECL_EXPR_DECL (decl_s);
6234 : 3846 : tree init = DECL_INITIAL (decl);
6235 : :
6236 : : /* struct T x = (struct T) { 0, 1, 2 } can be optimized
6237 : : into struct T x = { 0, 1, 2 } if the address of the
6238 : : compound literal has never been taken. */
6239 : 3846 : if (!TREE_ADDRESSABLE (complit)
6240 : 3846 : && !TREE_ADDRESSABLE (decl)
6241 : 3846 : && init)
6242 : : {
6243 : 3846 : *expr_p = copy_node (*expr_p);
6244 : 3846 : TREE_OPERAND (*expr_p, 1) = init;
6245 : 3846 : return GS_OK;
6246 : : }
6247 : : }
6248 : :
6249 : : default:
6250 : : break;
6251 : : }
6252 : : }
6253 : : while (changed);
6254 : :
6255 : : return ret;
6256 : : }
6257 : :
6258 : :
6259 : : /* Return true if T looks like a valid GIMPLE statement. */
6260 : :
6261 : : static bool
6262 : 17670047 : is_gimple_stmt (tree t)
6263 : : {
6264 : 17670047 : const enum tree_code code = TREE_CODE (t);
6265 : :
6266 : 17670047 : switch (code)
6267 : : {
6268 : 1542470 : case NOP_EXPR:
6269 : : /* The only valid NOP_EXPR is the empty statement. */
6270 : 1542470 : return IS_EMPTY_STMT (t);
6271 : :
6272 : 0 : case BIND_EXPR:
6273 : 0 : case COND_EXPR:
6274 : : /* These are only valid if they're void. */
6275 : 0 : return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
6276 : :
6277 : : case SWITCH_EXPR:
6278 : : case GOTO_EXPR:
6279 : : case RETURN_EXPR:
6280 : : case LABEL_EXPR:
6281 : : case CASE_LABEL_EXPR:
6282 : : case TRY_CATCH_EXPR:
6283 : : case TRY_FINALLY_EXPR:
6284 : : case EH_FILTER_EXPR:
6285 : : case CATCH_EXPR:
6286 : : case ASM_EXPR:
6287 : : case STATEMENT_LIST:
6288 : : case OACC_PARALLEL:
6289 : : case OACC_KERNELS:
6290 : : case OACC_SERIAL:
6291 : : case OACC_DATA:
6292 : : case OACC_HOST_DATA:
6293 : : case OACC_DECLARE:
6294 : : case OACC_UPDATE:
6295 : : case OACC_ENTER_DATA:
6296 : : case OACC_EXIT_DATA:
6297 : : case OACC_CACHE:
6298 : : case OMP_PARALLEL:
6299 : : case OMP_FOR:
6300 : : case OMP_SIMD:
6301 : : case OMP_DISTRIBUTE:
6302 : : case OMP_LOOP:
6303 : : case OACC_LOOP:
6304 : : case OMP_SCAN:
6305 : : case OMP_SCOPE:
6306 : : case OMP_SECTIONS:
6307 : : case OMP_SECTION:
6308 : : case OMP_STRUCTURED_BLOCK:
6309 : : case OMP_SINGLE:
6310 : : case OMP_MASTER:
6311 : : case OMP_MASKED:
6312 : : case OMP_TASKGROUP:
6313 : : case OMP_ORDERED:
6314 : : case OMP_CRITICAL:
6315 : : case OMP_TASK:
6316 : : case OMP_TARGET:
6317 : : case OMP_TARGET_DATA:
6318 : : case OMP_TARGET_UPDATE:
6319 : : case OMP_TARGET_ENTER_DATA:
6320 : : case OMP_TARGET_EXIT_DATA:
6321 : : case OMP_TASKLOOP:
6322 : : case OMP_TEAMS:
6323 : : /* These are always void. */
6324 : : return true;
6325 : :
6326 : : case CALL_EXPR:
6327 : : case MODIFY_EXPR:
6328 : : case PREDICT_EXPR:
6329 : : /* These are valid regardless of their type. */
6330 : : return true;
6331 : :
6332 : : default:
6333 : : return false;
6334 : : }
6335 : : }
6336 : :
6337 : :
6338 : : /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
6339 : : a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
6340 : :
6341 : : IMPORTANT NOTE: This promotion is performed by introducing a load of the
6342 : : other, unmodified part of the complex object just before the total store.
6343 : : As a consequence, if the object is still uninitialized, an undefined value
6344 : : will be loaded into a register, which may result in a spurious exception
6345 : : if the register is floating-point and the value happens to be a signaling
6346 : : NaN for example. Then the fully-fledged complex operations lowering pass
6347 : : followed by a DCE pass are necessary in order to fix things up. */
6348 : :
6349 : : static enum gimplify_status
6350 : 2183 : gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
6351 : : bool want_value)
6352 : : {
6353 : 2183 : enum tree_code code, ocode;
6354 : 2183 : tree lhs, rhs, new_rhs, other, realpart, imagpart;
6355 : :
6356 : 2183 : lhs = TREE_OPERAND (*expr_p, 0);
6357 : 2183 : rhs = TREE_OPERAND (*expr_p, 1);
6358 : 2183 : code = TREE_CODE (lhs);
6359 : 2183 : lhs = TREE_OPERAND (lhs, 0);
6360 : :
6361 : 2183 : ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
6362 : 2183 : other = build1 (ocode, TREE_TYPE (rhs), lhs);
6363 : 2183 : suppress_warning (other);
6364 : 2183 : other = get_formal_tmp_var (other, pre_p);
6365 : :
6366 : 2183 : realpart = code == REALPART_EXPR ? rhs : other;
6367 : 1076 : imagpart = code == REALPART_EXPR ? other : rhs;
6368 : :
6369 : 2183 : if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
6370 : 0 : new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
6371 : : else
6372 : 2183 : new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
6373 : :
6374 : 2183 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
6375 : 2183 : *expr_p = (want_value) ? rhs : NULL_TREE;
6376 : :
6377 : 2183 : return GS_ALL_DONE;
6378 : : }
6379 : :
6380 : : /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
6381 : :
6382 : : modify_expr
6383 : : : varname '=' rhs
6384 : : | '*' ID '=' rhs
6385 : :
6386 : : PRE_P points to the list where side effects that must happen before
6387 : : *EXPR_P should be stored.
6388 : :
6389 : : POST_P points to the list where side effects that must happen after
6390 : : *EXPR_P should be stored.
6391 : :
6392 : : WANT_VALUE is nonzero iff we want to use the value of this expression
6393 : : in another expression. */
6394 : :
6395 : : static enum gimplify_status
6396 : 45233233 : gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
6397 : : bool want_value)
6398 : : {
6399 : 45233233 : tree *from_p = &TREE_OPERAND (*expr_p, 1);
6400 : 45233233 : tree *to_p = &TREE_OPERAND (*expr_p, 0);
6401 : 45233233 : enum gimplify_status ret = GS_UNHANDLED;
6402 : 45233233 : gimple *assign;
6403 : 45233233 : location_t loc = EXPR_LOCATION (*expr_p);
6404 : 45233233 : gimple_stmt_iterator gsi;
6405 : :
6406 : 45233233 : if (error_operand_p (*from_p) || error_operand_p (*to_p))
6407 : : return GS_ERROR;
6408 : :
6409 : 45233203 : gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
6410 : : || TREE_CODE (*expr_p) == INIT_EXPR);
6411 : :
6412 : : /* Trying to simplify a clobber using normal logic doesn't work,
6413 : : so handle it here. */
6414 : 45233203 : if (TREE_CLOBBER_P (*from_p))
6415 : : {
6416 : 584184 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
6417 : 584184 : if (ret == GS_ERROR)
6418 : : return ret;
6419 : 584184 : gcc_assert (!want_value);
6420 : 584184 : if (!VAR_P (*to_p) && TREE_CODE (*to_p) != MEM_REF)
6421 : : {
6422 : 197 : tree addr = get_initialized_tmp_var (build_fold_addr_expr (*to_p),
6423 : : pre_p, post_p);
6424 : 197 : *to_p = build_simple_mem_ref_loc (EXPR_LOCATION (*to_p), addr);
6425 : : }
6426 : 584184 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
6427 : 584184 : *expr_p = NULL;
6428 : 584184 : return GS_ALL_DONE;
6429 : : }
6430 : :
6431 : : /* Convert initialization from an empty variable-size CONSTRUCTOR to
6432 : : memset. */
6433 : 44649019 : if (TREE_TYPE (*from_p) != error_mark_node
6434 : 44649019 : && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
6435 : 44649019 : && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
6436 : 1379 : && TREE_CODE (*from_p) == CONSTRUCTOR
6437 : 44649098 : && CONSTRUCTOR_NELTS (*from_p) == 0)
6438 : : {
6439 : 57 : maybe_with_size_expr (from_p);
6440 : 57 : gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
6441 : 57 : return gimplify_modify_expr_to_memset (expr_p,
6442 : 57 : TREE_OPERAND (*from_p, 1),
6443 : 57 : want_value, pre_p);
6444 : : }
6445 : :
6446 : : /* Insert pointer conversions required by the middle-end that are not
6447 : : required by the frontend. This fixes middle-end type checking for
6448 : : for example gcc.dg/redecl-6.c. */
6449 : 44648962 : if (POINTER_TYPE_P (TREE_TYPE (*to_p)))
6450 : : {
6451 : 12181949 : STRIP_USELESS_TYPE_CONVERSION (*from_p);
6452 : 12181949 : if (!useless_type_conversion_p (TREE_TYPE (*to_p), TREE_TYPE (*from_p)))
6453 : 309 : *from_p = fold_convert_loc (loc, TREE_TYPE (*to_p), *from_p);
6454 : : }
6455 : :
6456 : : /* See if any simplifications can be done based on what the RHS is. */
6457 : 44648962 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
6458 : : want_value);
6459 : 44648962 : if (ret != GS_UNHANDLED)
6460 : : return ret;
6461 : :
6462 : : /* For empty types only gimplify the left hand side and right hand
6463 : : side as statements and throw away the assignment. Do this after
6464 : : gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable
6465 : : types properly. */
6466 : 42937934 : if (is_empty_type (TREE_TYPE (*from_p))
6467 : 11584 : && !want_value
6468 : : /* Don't do this for calls that return addressable types, expand_call
6469 : : relies on those having a lhs. */
6470 : 42949511 : && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
6471 : 9603 : && TREE_CODE (*from_p) == CALL_EXPR))
6472 : : {
6473 : 1974 : gimplify_stmt (from_p, pre_p);
6474 : 1974 : gimplify_stmt (to_p, pre_p);
6475 : 1974 : *expr_p = NULL_TREE;
6476 : 1974 : return GS_ALL_DONE;
6477 : : }
6478 : :
6479 : : /* If the value being copied is of variable width, compute the length
6480 : : of the copy into a WITH_SIZE_EXPR. Note that we need to do this
6481 : : before gimplifying any of the operands so that we can resolve any
6482 : : PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
6483 : : the size of the expression to be copied, not of the destination, so
6484 : : that is what we must do here. */
6485 : 42935960 : maybe_with_size_expr (from_p);
6486 : :
6487 : : /* As a special case, we have to temporarily allow for assignments
6488 : : with a CALL_EXPR on the RHS. Since in GIMPLE a function call is
6489 : : a toplevel statement, when gimplifying the GENERIC expression
6490 : : MODIFY_EXPR <a, CALL_EXPR <foo>>, we cannot create the tuple
6491 : : GIMPLE_ASSIGN <a, GIMPLE_CALL <foo>>.
6492 : :
6493 : : Instead, we need to create the tuple GIMPLE_CALL <a, foo>. To
6494 : : prevent gimplify_expr from trying to create a new temporary for
6495 : : foo's LHS, we tell it that it should only gimplify until it
6496 : : reaches the CALL_EXPR. On return from gimplify_expr, the newly
6497 : : created GIMPLE_CALL <foo> will be the last statement in *PRE_P
6498 : : and all we need to do here is set 'a' to be its LHS. */
6499 : :
6500 : : /* Gimplify the RHS first for C++17 and bug 71104. */
6501 : 42935960 : gimple_predicate initial_pred = initial_rhs_predicate_for (*to_p);
6502 : 42935960 : ret = gimplify_expr (from_p, pre_p, post_p, initial_pred, fb_rvalue);
6503 : 42935960 : if (ret == GS_ERROR)
6504 : : return ret;
6505 : :
6506 : : /* Then gimplify the LHS. */
6507 : : /* If we gimplified the RHS to a CALL_EXPR and that call may return
6508 : : twice we have to make sure to gimplify into non-SSA as otherwise
6509 : : the abnormal edge added later will make those defs not dominate
6510 : : their uses.
6511 : : ??? Technically this applies only to the registers used in the
6512 : : resulting non-register *TO_P. */
6513 : 42935929 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
6514 : 42935929 : if (saved_into_ssa
6515 : 40701219 : && TREE_CODE (*from_p) == CALL_EXPR
6516 : 47268211 : && call_expr_flags (*from_p) & ECF_RETURNS_TWICE)
6517 : 1385 : gimplify_ctxp->into_ssa = false;
6518 : 42935929 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
6519 : 42935929 : gimplify_ctxp->into_ssa = saved_into_ssa;
6520 : 42935929 : if (ret == GS_ERROR)
6521 : : return ret;
6522 : :
6523 : : /* Now that the LHS is gimplified, re-gimplify the RHS if our initial
6524 : : guess for the predicate was wrong. */
6525 : 42935929 : gimple_predicate final_pred = rhs_predicate_for (*to_p);
6526 : 42935929 : if (final_pred != initial_pred)
6527 : : {
6528 : 7383161 : ret = gimplify_expr (from_p, pre_p, post_p, final_pred, fb_rvalue);
6529 : 7383161 : if (ret == GS_ERROR)
6530 : : return ret;
6531 : : }
6532 : :
6533 : : /* In case of va_arg internal fn wrappped in a WITH_SIZE_EXPR, add the type
6534 : : size as argument to the call. */
6535 : 42935929 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
6536 : : {
6537 : 1249 : tree call = TREE_OPERAND (*from_p, 0);
6538 : 1249 : tree vlasize = TREE_OPERAND (*from_p, 1);
6539 : :
6540 : 1249 : if (TREE_CODE (call) == CALL_EXPR
6541 : 1249 : && CALL_EXPR_IFN (call) == IFN_VA_ARG)
6542 : : {
6543 : 95 : int nargs = call_expr_nargs (call);
6544 : 95 : tree type = TREE_TYPE (call);
6545 : 95 : tree ap = CALL_EXPR_ARG (call, 0);
6546 : 95 : tree tag = CALL_EXPR_ARG (call, 1);
6547 : 95 : tree aptag = CALL_EXPR_ARG (call, 2);
6548 : 95 : tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
6549 : : IFN_VA_ARG, type,
6550 : : nargs + 1, ap, tag,
6551 : : aptag, vlasize);
6552 : 95 : TREE_OPERAND (*from_p, 0) = newcall;
6553 : : }
6554 : : }
6555 : :
6556 : : /* Now see if the above changed *from_p to something we handle specially. */
6557 : 42935929 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
6558 : : want_value);
6559 : 42935929 : if (ret != GS_UNHANDLED)
6560 : : return ret;
6561 : :
6562 : : /* If we've got a variable sized assignment between two lvalues (i.e. does
6563 : : not involve a call), then we can make things a bit more straightforward
6564 : : by converting the assignment to memcpy or memset. */
6565 : 42935109 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
6566 : : {
6567 : 1068 : tree from = TREE_OPERAND (*from_p, 0);
6568 : 1068 : tree size = TREE_OPERAND (*from_p, 1);
6569 : :
6570 : 1068 : if (TREE_CODE (from) == CONSTRUCTOR)
6571 : 0 : return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
6572 : 1068 : else if (is_gimple_addressable (from)
6573 : 1068 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (*to_p)))
6574 : 2135 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))))
6575 : : {
6576 : 1067 : *from_p = from;
6577 : 1067 : return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
6578 : 1067 : pre_p);
6579 : : }
6580 : : }
6581 : :
6582 : : /* Transform partial stores to non-addressable complex variables into
6583 : : total stores. This allows us to use real instead of virtual operands
6584 : : for these variables, which improves optimization. */
6585 : 42934042 : if ((TREE_CODE (*to_p) == REALPART_EXPR
6586 : 42934042 : || TREE_CODE (*to_p) == IMAGPART_EXPR)
6587 : 42934042 : && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
6588 : 2183 : return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
6589 : :
6590 : : /* Try to alleviate the effects of the gimplification creating artificial
6591 : : temporaries (see for example is_gimple_reg_rhs) on the debug info, but
6592 : : make sure not to create DECL_DEBUG_EXPR links across functions. */
6593 : 42931859 : if (!gimplify_ctxp->into_ssa
6594 : 2233815 : && VAR_P (*from_p)
6595 : 446127 : && DECL_IGNORED_P (*from_p)
6596 : 325774 : && DECL_P (*to_p)
6597 : 119550 : && !DECL_IGNORED_P (*to_p)
6598 : 29090 : && decl_function_context (*to_p) == current_function_decl
6599 : 42954941 : && decl_function_context (*from_p) == current_function_decl)
6600 : : {
6601 : 23077 : if (!DECL_NAME (*from_p) && DECL_NAME (*to_p))
6602 : 17637 : DECL_NAME (*from_p)
6603 : 35274 : = create_tmp_var_name (IDENTIFIER_POINTER (DECL_NAME (*to_p)));
6604 : 23077 : DECL_HAS_DEBUG_EXPR_P (*from_p) = 1;
6605 : 23077 : SET_DECL_DEBUG_EXPR (*from_p, *to_p);
6606 : : }
6607 : :
6608 : 42931859 : if (want_value && TREE_THIS_VOLATILE (*to_p))
6609 : 628 : *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
6610 : :
6611 : 42931859 : if (TREE_CODE (*from_p) == CALL_EXPR)
6612 : : {
6613 : : /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
6614 : : instead of a GIMPLE_ASSIGN. */
6615 : 4065368 : gcall *call_stmt;
6616 : 4065368 : if (CALL_EXPR_FN (*from_p) == NULL_TREE)
6617 : : {
6618 : : /* Gimplify internal functions created in the FEs. */
6619 : 170477 : int nargs = call_expr_nargs (*from_p), i;
6620 : 170477 : enum internal_fn ifn = CALL_EXPR_IFN (*from_p);
6621 : 170477 : auto_vec<tree> vargs (nargs);
6622 : :
6623 : 854548 : for (i = 0; i < nargs; i++)
6624 : : {
6625 : 513594 : gimplify_arg (&CALL_EXPR_ARG (*from_p, i), pre_p,
6626 : 513594 : EXPR_LOCATION (*from_p));
6627 : 513594 : vargs.quick_push (CALL_EXPR_ARG (*from_p, i));
6628 : : }
6629 : 170477 : call_stmt = gimple_build_call_internal_vec (ifn, vargs);
6630 : 170477 : gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p));
6631 : 340954 : gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p));
6632 : 170477 : }
6633 : : else
6634 : : {
6635 : 3894891 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
6636 : 3894891 : CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
6637 : 3894891 : STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
6638 : 3894891 : tree fndecl = get_callee_fndecl (*from_p);
6639 : 3894891 : if (fndecl
6640 : 3779856 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
6641 : 4010458 : && call_expr_nargs (*from_p) == 3)
6642 : 49991 : call_stmt = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3,
6643 : 49991 : CALL_EXPR_ARG (*from_p, 0),
6644 : 49991 : CALL_EXPR_ARG (*from_p, 1),
6645 : 49991 : CALL_EXPR_ARG (*from_p, 2));
6646 : : else
6647 : : {
6648 : 3844900 : call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
6649 : : }
6650 : : }
6651 : 4065368 : notice_special_calls (call_stmt);
6652 : 4065368 : if (!gimple_call_noreturn_p (call_stmt) || !should_remove_lhs_p (*to_p))
6653 : 4064565 : gimple_call_set_lhs (call_stmt, *to_p);
6654 : 803 : else if (TREE_CODE (*to_p) == SSA_NAME)
6655 : : /* The above is somewhat premature, avoid ICEing later for a
6656 : : SSA name w/o a definition. We may have uses in the GIMPLE IL.
6657 : : ??? This doesn't make it a default-def. */
6658 : 10 : SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop ();
6659 : :
6660 : : assign = call_stmt;
6661 : : }
6662 : : else
6663 : : {
6664 : 38866491 : assign = gimple_build_assign (*to_p, *from_p);
6665 : 38866491 : gimple_set_location (assign, EXPR_LOCATION (*expr_p));
6666 : 38866491 : if (COMPARISON_CLASS_P (*from_p))
6667 : 1062291 : copy_warning (assign, *from_p);
6668 : : }
6669 : :
6670 : 42931859 : if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
6671 : : {
6672 : : /* We should have got an SSA name from the start. */
6673 : 31634224 : gcc_assert (TREE_CODE (*to_p) == SSA_NAME
6674 : : || ! gimple_in_ssa_p (cfun));
6675 : : }
6676 : :
6677 : 42931859 : gimplify_seq_add_stmt (pre_p, assign);
6678 : 42931859 : gsi = gsi_last (*pre_p);
6679 : 42931859 : maybe_fold_stmt (&gsi);
6680 : :
6681 : 42931859 : if (want_value)
6682 : : {
6683 : 525969 : *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
6684 : 525969 : return GS_OK;
6685 : : }
6686 : : else
6687 : 42405890 : *expr_p = NULL;
6688 : :
6689 : 42405890 : return GS_ALL_DONE;
6690 : : }
6691 : :
6692 : : /* Gimplify a comparison between two variable-sized objects. Do this
6693 : : with a call to BUILT_IN_MEMCMP. */
6694 : :
6695 : : static enum gimplify_status
6696 : 0 : gimplify_variable_sized_compare (tree *expr_p)
6697 : : {
6698 : 0 : location_t loc = EXPR_LOCATION (*expr_p);
6699 : 0 : tree op0 = TREE_OPERAND (*expr_p, 0);
6700 : 0 : tree op1 = TREE_OPERAND (*expr_p, 1);
6701 : 0 : tree t, arg, dest, src, expr;
6702 : :
6703 : 0 : arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
6704 : 0 : arg = unshare_expr (arg);
6705 : 0 : arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
6706 : 0 : src = build_fold_addr_expr_loc (loc, op1);
6707 : 0 : dest = build_fold_addr_expr_loc (loc, op0);
6708 : 0 : t = builtin_decl_implicit (BUILT_IN_MEMCMP);
6709 : 0 : t = build_call_expr_loc (loc, t, 3, dest, src, arg);
6710 : :
6711 : 0 : expr
6712 : 0 : = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
6713 : 0 : SET_EXPR_LOCATION (expr, loc);
6714 : 0 : *expr_p = expr;
6715 : :
6716 : 0 : return GS_OK;
6717 : : }
6718 : :
6719 : : /* Gimplify a comparison between two aggregate objects of integral scalar
6720 : : mode as a comparison between the bitwise equivalent scalar values. */
6721 : :
6722 : : static enum gimplify_status
6723 : 14 : gimplify_scalar_mode_aggregate_compare (tree *expr_p)
6724 : : {
6725 : 14 : location_t loc = EXPR_LOCATION (*expr_p);
6726 : 14 : tree op0 = TREE_OPERAND (*expr_p, 0);
6727 : 14 : tree op1 = TREE_OPERAND (*expr_p, 1);
6728 : :
6729 : 14 : tree type = TREE_TYPE (op0);
6730 : 14 : tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
6731 : :
6732 : 14 : op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
6733 : 14 : op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
6734 : :
6735 : 14 : *expr_p
6736 : 14 : = fold_build2_loc (loc, TREE_CODE (*expr_p), TREE_TYPE (*expr_p), op0, op1);
6737 : :
6738 : 14 : return GS_OK;
6739 : : }
6740 : :
6741 : : /* Gimplify an expression sequence. This function gimplifies each
6742 : : expression and rewrites the original expression with the last
6743 : : expression of the sequence in GIMPLE form.
6744 : :
6745 : : PRE_P points to the list where the side effects for all the
6746 : : expressions in the sequence will be emitted.
6747 : :
6748 : : WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
6749 : :
6750 : : static enum gimplify_status
6751 : 933066 : gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
6752 : : {
6753 : 933066 : tree t = *expr_p;
6754 : :
6755 : 991203 : do
6756 : : {
6757 : 991203 : tree *sub_p = &TREE_OPERAND (t, 0);
6758 : :
6759 : 991203 : if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
6760 : 178340 : gimplify_compound_expr (sub_p, pre_p, false);
6761 : : else
6762 : 812863 : gimplify_stmt (sub_p, pre_p);
6763 : :
6764 : 991203 : t = TREE_OPERAND (t, 1);
6765 : : }
6766 : 991203 : while (TREE_CODE (t) == COMPOUND_EXPR);
6767 : :
6768 : 933066 : *expr_p = t;
6769 : 933066 : if (want_value)
6770 : : return GS_OK;
6771 : : else
6772 : : {
6773 : 459438 : gimplify_stmt (expr_p, pre_p);
6774 : 459438 : return GS_ALL_DONE;
6775 : : }
6776 : : }
6777 : :
6778 : : /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
6779 : : gimplify. After gimplification, EXPR_P will point to a new temporary
6780 : : that holds the original value of the SAVE_EXPR node.
6781 : :
6782 : : PRE_P points to the list where side effects that must happen before
6783 : : *EXPR_P should be stored. */
6784 : :
6785 : : static enum gimplify_status
6786 : 456217 : gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
6787 : : {
6788 : 456217 : enum gimplify_status ret = GS_ALL_DONE;
6789 : 456217 : tree val;
6790 : :
6791 : 456217 : gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
6792 : 456217 : val = TREE_OPERAND (*expr_p, 0);
6793 : :
6794 : 456217 : if (val && TREE_TYPE (val) == error_mark_node)
6795 : : return GS_ERROR;
6796 : :
6797 : : /* If the SAVE_EXPR has not been resolved, then evaluate it once. */
6798 : 456215 : if (!SAVE_EXPR_RESOLVED_P (*expr_p))
6799 : : {
6800 : : /* The operand may be a void-valued expression. It is
6801 : : being executed only for its side-effects. */
6802 : 191054 : if (TREE_TYPE (val) == void_type_node)
6803 : : {
6804 : 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
6805 : : is_gimple_stmt, fb_none);
6806 : 0 : val = NULL;
6807 : : }
6808 : : else
6809 : : /* The temporary may not be an SSA name as later abnormal and EH
6810 : : control flow may invalidate use/def domination. When in SSA
6811 : : form then assume there are no such issues and SAVE_EXPRs only
6812 : : appear via GENERIC foldings. */
6813 : 382108 : val = get_initialized_tmp_var (val, pre_p, post_p,
6814 : 382108 : gimple_in_ssa_p (cfun));
6815 : :
6816 : 191054 : TREE_OPERAND (*expr_p, 0) = val;
6817 : 191054 : SAVE_EXPR_RESOLVED_P (*expr_p) = 1;
6818 : : }
6819 : :
6820 : 456215 : *expr_p = val;
6821 : :
6822 : 456215 : return ret;
6823 : : }
6824 : :
6825 : : /* Rewrite the ADDR_EXPR node pointed to by EXPR_P
6826 : :
6827 : : unary_expr
6828 : : : ...
6829 : : | '&' varname
6830 : : ...
6831 : :
6832 : : PRE_P points to the list where side effects that must happen before
6833 : : *EXPR_P should be stored.
6834 : :
6835 : : POST_P points to the list where side effects that must happen after
6836 : : *EXPR_P should be stored. */
6837 : :
6838 : : static enum gimplify_status
6839 : 29119903 : gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
6840 : : {
6841 : 29119903 : tree expr = *expr_p;
6842 : 29119903 : tree op0 = TREE_OPERAND (expr, 0);
6843 : 29119903 : enum gimplify_status ret;
6844 : 29119903 : location_t loc = EXPR_LOCATION (*expr_p);
6845 : :
6846 : 29119903 : switch (TREE_CODE (op0))
6847 : : {
6848 : 89886 : case INDIRECT_REF:
6849 : 89886 : do_indirect_ref:
6850 : : /* Check if we are dealing with an expression of the form '&*ptr'.
6851 : : While the front end folds away '&*ptr' into 'ptr', these
6852 : : expressions may be generated internally by the compiler (e.g.,
6853 : : builtins like __builtin_va_end). */
6854 : : /* Caution: the silent array decomposition semantics we allow for
6855 : : ADDR_EXPR means we can't always discard the pair. */
6856 : : /* Gimplification of the ADDR_EXPR operand may drop
6857 : : cv-qualification conversions, so make sure we add them if
6858 : : needed. */
6859 : 89886 : {
6860 : 89886 : tree op00 = TREE_OPERAND (op0, 0);
6861 : 89886 : tree t_expr = TREE_TYPE (expr);
6862 : 89886 : tree t_op00 = TREE_TYPE (op00);
6863 : :
6864 : 89886 : if (!useless_type_conversion_p (t_expr, t_op00))
6865 : 0 : op00 = fold_convert_loc (loc, TREE_TYPE (expr), op00);
6866 : 89886 : *expr_p = op00;
6867 : 89886 : ret = GS_OK;
6868 : : }
6869 : 89886 : break;
6870 : :
6871 : 0 : case VIEW_CONVERT_EXPR:
6872 : : /* Take the address of our operand and then convert it to the type of
6873 : : this ADDR_EXPR.
6874 : :
6875 : : ??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
6876 : : all clear. The impact of this transformation is even less clear. */
6877 : :
6878 : : /* If the operand is a useless conversion, look through it. Doing so
6879 : : guarantees that the ADDR_EXPR and its operand will remain of the
6880 : : same type. */
6881 : 0 : if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
6882 : 0 : op0 = TREE_OPERAND (op0, 0);
6883 : :
6884 : 0 : *expr_p = fold_convert_loc (loc, TREE_TYPE (expr),
6885 : : build_fold_addr_expr_loc (loc,
6886 : 0 : TREE_OPERAND (op0, 0)));
6887 : 0 : ret = GS_OK;
6888 : 0 : break;
6889 : :
6890 : 53563 : case MEM_REF:
6891 : 53563 : if (integer_zerop (TREE_OPERAND (op0, 1)))
6892 : 37806 : goto do_indirect_ref;
6893 : :
6894 : : /* fall through */
6895 : :
6896 : 29045397 : default:
6897 : : /* If we see a call to a declared builtin or see its address
6898 : : being taken (we can unify those cases here) then we can mark
6899 : : the builtin for implicit generation by GCC. */
6900 : 29045397 : if (TREE_CODE (op0) == FUNCTION_DECL
6901 : 14630526 : && fndecl_built_in_p (op0, BUILT_IN_NORMAL)
6902 : 32689452 : && builtin_decl_declared_p (DECL_FUNCTION_CODE (op0)))
6903 : 1217164 : set_builtin_decl_implicit_p (DECL_FUNCTION_CODE (op0), true);
6904 : :
6905 : : /* We use fb_either here because the C frontend sometimes takes
6906 : : the address of a call that returns a struct; see
6907 : : gcc.dg/c99-array-lval-1.c. The gimplifier will correctly make
6908 : : the implied temporary explicit. */
6909 : :
6910 : : /* Make the operand addressable. */
6911 : 29045397 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
6912 : : is_gimple_addressable, fb_either);
6913 : 29045397 : if (ret == GS_ERROR)
6914 : : break;
6915 : :
6916 : : /* Then mark it. Beware that it may not be possible to do so directly
6917 : : if a temporary has been created by the gimplification. */
6918 : 29045395 : prepare_gimple_addressable (&TREE_OPERAND (expr, 0), pre_p);
6919 : :
6920 : 29045395 : op0 = TREE_OPERAND (expr, 0);
6921 : :
6922 : : /* For various reasons, the gimplification of the expression
6923 : : may have made a new INDIRECT_REF. */
6924 : 29045395 : if (INDIRECT_REF_P (op0)
6925 : 29045395 : || (TREE_CODE (op0) == MEM_REF
6926 : 31137 : && integer_zerop (TREE_OPERAND (op0, 1))))
6927 : 15380 : goto do_indirect_ref;
6928 : :
6929 : 29030015 : mark_addressable (TREE_OPERAND (expr, 0));
6930 : :
6931 : : /* The FEs may end up building ADDR_EXPRs early on a decl with
6932 : : an incomplete type. Re-build ADDR_EXPRs in canonical form
6933 : : here. */
6934 : 29030015 : if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
6935 : 149243 : *expr_p = build_fold_addr_expr (op0);
6936 : :
6937 : : /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */
6938 : 29030015 : recompute_tree_invariant_for_addr_expr (*expr_p);
6939 : :
6940 : : /* If we re-built the ADDR_EXPR add a conversion to the original type
6941 : : if required. */
6942 : 29030015 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
6943 : 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
6944 : :
6945 : : break;
6946 : : }
6947 : :
6948 : 29119903 : return ret;
6949 : : }
6950 : :
6951 : : /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple
6952 : : value; output operands should be a gimple lvalue. */
6953 : :
6954 : : static enum gimplify_status
6955 : 103710 : gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
6956 : : {
6957 : 103710 : tree expr;
6958 : 103710 : int noutputs;
6959 : 103710 : const char **oconstraints;
6960 : 103710 : int i;
6961 : 103710 : tree link;
6962 : 103710 : const char *constraint;
6963 : 103710 : bool allows_mem, allows_reg, is_inout;
6964 : 103710 : enum gimplify_status ret, tret;
6965 : 103710 : gasm *stmt;
6966 : 103710 : vec<tree, va_gc> *inputs;
6967 : 103710 : vec<tree, va_gc> *outputs;
6968 : 103710 : vec<tree, va_gc> *clobbers;
6969 : 103710 : vec<tree, va_gc> *labels;
6970 : 103710 : tree link_next;
6971 : :
6972 : 103710 : expr = *expr_p;
6973 : 103710 : noutputs = list_length (ASM_OUTPUTS (expr));
6974 : 103710 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
6975 : :
6976 : 103710 : inputs = NULL;
6977 : 103710 : outputs = NULL;
6978 : 103710 : clobbers = NULL;
6979 : 103710 : labels = NULL;
6980 : :
6981 : 103710 : ret = GS_ALL_DONE;
6982 : 103710 : link_next = NULL_TREE;
6983 : 181317 : for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
6984 : : {
6985 : 77622 : bool ok;
6986 : 77622 : size_t constraint_len;
6987 : :
6988 : 77622 : link_next = TREE_CHAIN (link);
6989 : :
6990 : 155244 : oconstraints[i]
6991 : 77622 : = constraint
6992 : 77622 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
6993 : 77622 : constraint_len = strlen (constraint);
6994 : 77622 : if (constraint_len == 0)
6995 : 6 : continue;
6996 : :
6997 : 77616 : ok = parse_output_constraint (&constraint, i, 0, 0,
6998 : : &allows_mem, &allows_reg, &is_inout);
6999 : 77616 : if (!ok)
7000 : : {
7001 : 4 : ret = GS_ERROR;
7002 : 4 : is_inout = false;
7003 : : }
7004 : :
7005 : : /* If we can't make copies, we can only accept memory.
7006 : : Similarly for VLAs. */
7007 : 77616 : tree outtype = TREE_TYPE (TREE_VALUE (link));
7008 : 77616 : if (outtype != error_mark_node
7009 : 77616 : && (TREE_ADDRESSABLE (outtype)
7010 : 77584 : || !COMPLETE_TYPE_P (outtype)
7011 : 77559 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (outtype))))
7012 : : {
7013 : 253 : if (allows_mem)
7014 : 238 : allows_reg = 0;
7015 : : else
7016 : : {
7017 : 15 : error ("impossible constraint in %<asm%>");
7018 : 15 : error ("non-memory output %d must stay in memory", i);
7019 : 15 : return GS_ERROR;
7020 : : }
7021 : : }
7022 : :
7023 : 77601 : if (!allows_reg && allows_mem)
7024 : 1881 : mark_addressable (TREE_VALUE (link));
7025 : :
7026 : 77601 : tree orig = TREE_VALUE (link);
7027 : 146051 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
7028 : : is_inout ? is_gimple_min_lval : is_gimple_lvalue,
7029 : : fb_lvalue | fb_mayfail);
7030 : 77601 : if (tret == GS_ERROR)
7031 : : {
7032 : 12 : if (orig != error_mark_node)
7033 : 0 : error ("invalid lvalue in %<asm%> output %d", i);
7034 : : ret = tret;
7035 : : }
7036 : :
7037 : : /* If the constraint does not allow memory make sure we gimplify
7038 : : it to a register if it is not already but its base is. This
7039 : : happens for complex and vector components. */
7040 : 77601 : if (!allows_mem)
7041 : : {
7042 : 69534 : tree op = TREE_VALUE (link);
7043 : 69534 : if (! is_gimple_val (op)
7044 : 25913 : && is_gimple_reg_type (TREE_TYPE (op))
7045 : 95446 : && is_gimple_reg (get_base_address (op)))
7046 : : {
7047 : 19 : tree tem = create_tmp_reg (TREE_TYPE (op));
7048 : 19 : tree ass;
7049 : 19 : if (is_inout)
7050 : : {
7051 : 7 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem),
7052 : : tem, unshare_expr (op));
7053 : 7 : gimplify_and_add (ass, pre_p);
7054 : : }
7055 : 19 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem), op, tem);
7056 : 19 : gimplify_and_add (ass, post_p);
7057 : :
7058 : 19 : TREE_VALUE (link) = tem;
7059 : 19 : tret = GS_OK;
7060 : : }
7061 : : }
7062 : :
7063 : 77601 : vec_safe_push (outputs, link);
7064 : 77601 : TREE_CHAIN (link) = NULL_TREE;
7065 : :
7066 : 77601 : if (is_inout)
7067 : : {
7068 : : /* An input/output operand. To give the optimizers more
7069 : : flexibility, split it into separate input and output
7070 : : operands. */
7071 : 9151 : tree input;
7072 : : /* Buffer big enough to format a 32-bit UINT_MAX into. */
7073 : 9151 : char buf[11];
7074 : :
7075 : : /* Turn the in/out constraint into an output constraint. */
7076 : 9151 : char *p = xstrdup (constraint);
7077 : 9151 : p[0] = '=';
7078 : 9151 : TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
7079 : :
7080 : : /* And add a matching input constraint. */
7081 : 9151 : if (allows_reg)
7082 : : {
7083 : 8644 : sprintf (buf, "%u", i);
7084 : :
7085 : : /* If there are multiple alternatives in the constraint,
7086 : : handle each of them individually. Those that allow register
7087 : : will be replaced with operand number, the others will stay
7088 : : unchanged. */
7089 : 8644 : if (strchr (p, ',') != NULL)
7090 : : {
7091 : 100 : size_t len = 0, buflen = strlen (buf);
7092 : 100 : char *beg, *end, *str, *dst;
7093 : :
7094 : 100 : for (beg = p + 1;;)
7095 : : {
7096 : 200 : end = strchr (beg, ',');
7097 : 200 : if (end == NULL)
7098 : 100 : end = strchr (beg, '\0');
7099 : 200 : if ((size_t) (end - beg) < buflen)
7100 : 28 : len += buflen + 1;
7101 : : else
7102 : 172 : len += end - beg + 1;
7103 : 200 : if (*end)
7104 : 100 : beg = end + 1;
7105 : : else
7106 : : break;
7107 : : }
7108 : :
7109 : 100 : str = (char *) alloca (len);
7110 : 100 : for (beg = p + 1, dst = str;;)
7111 : : {
7112 : 200 : const char *tem;
7113 : 200 : bool mem_p, reg_p, inout_p;
7114 : :
7115 : 200 : end = strchr (beg, ',');
7116 : 200 : if (end)
7117 : 100 : *end = '\0';
7118 : 200 : beg[-1] = '=';
7119 : 200 : tem = beg - 1;
7120 : 200 : parse_output_constraint (&tem, i, 0, 0,
7121 : : &mem_p, ®_p, &inout_p);
7122 : 200 : if (dst != str)
7123 : 100 : *dst++ = ',';
7124 : 200 : if (reg_p)
7125 : : {
7126 : 115 : memcpy (dst, buf, buflen);
7127 : 115 : dst += buflen;
7128 : : }
7129 : : else
7130 : : {
7131 : 85 : if (end)
7132 : 0 : len = end - beg;
7133 : : else
7134 : 85 : len = strlen (beg);
7135 : 85 : memcpy (dst, beg, len);
7136 : 85 : dst += len;
7137 : : }
7138 : 200 : if (end)
7139 : 100 : beg = end + 1;
7140 : : else
7141 : : break;
7142 : 100 : }
7143 : 100 : *dst = '\0';
7144 : 100 : input = build_string (dst - str, str);
7145 : : }
7146 : : else
7147 : 8544 : input = build_string (strlen (buf), buf);
7148 : : }
7149 : : else
7150 : 507 : input = build_string (constraint_len - 1, constraint + 1);
7151 : :
7152 : 9151 : free (p);
7153 : :
7154 : 9151 : input = build_tree_list (build_tree_list (NULL_TREE, input),
7155 : 9151 : unshare_expr (TREE_VALUE (link)));
7156 : 9151 : ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
7157 : : }
7158 : : }
7159 : :
7160 : 103695 : link_next = NULL_TREE;
7161 : 151141 : for (link = ASM_INPUTS (expr); link; ++i, link = link_next)
7162 : : {
7163 : 47458 : link_next = TREE_CHAIN (link);
7164 : 47458 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7165 : 47458 : parse_input_constraint (&constraint, 0, 0, noutputs, 0,
7166 : : oconstraints, &allows_mem, &allows_reg);
7167 : :
7168 : : /* If we can't make copies, we can only accept memory. */
7169 : 47458 : tree intype = TREE_TYPE (TREE_VALUE (link));
7170 : 47458 : if (intype != error_mark_node
7171 : 47458 : && (TREE_ADDRESSABLE (intype)
7172 : 47415 : || !COMPLETE_TYPE_P (intype)
7173 : 47391 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (intype))))
7174 : : {
7175 : 247 : if (allows_mem)
7176 : 235 : allows_reg = 0;
7177 : : else
7178 : : {
7179 : 12 : error ("impossible constraint in %<asm%>");
7180 : 12 : error ("non-memory input %d must stay in memory", i);
7181 : 12 : return GS_ERROR;
7182 : : }
7183 : : }
7184 : :
7185 : : /* If the operand is a memory input, it should be an lvalue. */
7186 : 47446 : if (!allows_reg && allows_mem)
7187 : : {
7188 : 2265 : tree inputv = TREE_VALUE (link);
7189 : 2265 : STRIP_NOPS (inputv);
7190 : 2265 : if (TREE_CODE (inputv) == PREDECREMENT_EXPR
7191 : : || TREE_CODE (inputv) == PREINCREMENT_EXPR
7192 : : || TREE_CODE (inputv) == POSTDECREMENT_EXPR
7193 : 2265 : || TREE_CODE (inputv) == POSTINCREMENT_EXPR
7194 : 2251 : || TREE_CODE (inputv) == MODIFY_EXPR)
7195 : 16 : TREE_VALUE (link) = error_mark_node;
7196 : 2265 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
7197 : : is_gimple_lvalue, fb_lvalue | fb_mayfail);
7198 : 2265 : if (tret != GS_ERROR)
7199 : : {
7200 : : /* Unlike output operands, memory inputs are not guaranteed
7201 : : to be lvalues by the FE, and while the expressions are
7202 : : marked addressable there, if it is e.g. a statement
7203 : : expression, temporaries in it might not end up being
7204 : : addressable. They might be already used in the IL and thus
7205 : : it is too late to make them addressable now though. */
7206 : 2233 : tree x = TREE_VALUE (link);
7207 : 2755 : while (handled_component_p (x))
7208 : 522 : x = TREE_OPERAND (x, 0);
7209 : 2233 : if (TREE_CODE (x) == MEM_REF
7210 : 2233 : && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
7211 : 0 : x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
7212 : 2233 : if ((VAR_P (x)
7213 : : || TREE_CODE (x) == PARM_DECL
7214 : : || TREE_CODE (x) == RESULT_DECL)
7215 : 1453 : && !TREE_ADDRESSABLE (x)
7216 : 24 : && is_gimple_reg (x))
7217 : : {
7218 : 18 : warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link),
7219 : : input_location), 0,
7220 : : "memory input %d is not directly addressable",
7221 : : i);
7222 : 18 : prepare_gimple_addressable (&TREE_VALUE (link), pre_p);
7223 : : }
7224 : : }
7225 : 2265 : mark_addressable (TREE_VALUE (link));
7226 : 2265 : if (tret == GS_ERROR)
7227 : : {
7228 : 32 : if (inputv != error_mark_node)
7229 : 25 : error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
7230 : : "memory input %d is not directly addressable", i);
7231 : : ret = tret;
7232 : : }
7233 : : }
7234 : : else
7235 : : {
7236 : 45181 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
7237 : : is_gimple_asm_val, fb_rvalue);
7238 : 45181 : if (tret == GS_ERROR)
7239 : 44 : ret = tret;
7240 : : }
7241 : :
7242 : 47446 : TREE_CHAIN (link) = NULL_TREE;
7243 : 47446 : vec_safe_push (inputs, link);
7244 : : }
7245 : :
7246 : 103683 : link_next = NULL_TREE;
7247 : 206061 : for (link = ASM_CLOBBERS (expr); link; ++i, link = link_next)
7248 : : {
7249 : 102378 : link_next = TREE_CHAIN (link);
7250 : 102378 : TREE_CHAIN (link) = NULL_TREE;
7251 : 102378 : vec_safe_push (clobbers, link);
7252 : : }
7253 : :
7254 : 103683 : link_next = NULL_TREE;
7255 : 104474 : for (link = ASM_LABELS (expr); link; ++i, link = link_next)
7256 : : {
7257 : 791 : link_next = TREE_CHAIN (link);
7258 : 791 : TREE_CHAIN (link) = NULL_TREE;
7259 : 791 : vec_safe_push (labels, link);
7260 : : }
7261 : :
7262 : : /* Do not add ASMs with errors to the gimple IL stream. */
7263 : 103683 : if (ret != GS_ERROR)
7264 : : {
7265 : 103628 : stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
7266 : : inputs, outputs, clobbers, labels);
7267 : :
7268 : : /* asm is volatile if it was marked by the user as volatile or
7269 : : there are no outputs or this is an asm goto. */
7270 : 207256 : gimple_asm_set_volatile (stmt,
7271 : 103628 : ASM_VOLATILE_P (expr)
7272 : 8895 : || noutputs == 0
7273 : 112517 : || labels);
7274 : 103628 : gimple_asm_set_input (stmt, ASM_INPUT_P (expr));
7275 : 103628 : gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
7276 : :
7277 : 103628 : gimplify_seq_add_stmt (pre_p, stmt);
7278 : : }
7279 : :
7280 : : return ret;
7281 : : }
7282 : :
7283 : : /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding
7284 : : GIMPLE_WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
7285 : : gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we
7286 : : return to this function.
7287 : :
7288 : : FIXME should we complexify the prequeue handling instead? Or use flags
7289 : : for all the cleanups and let the optimizer tighten them up? The current
7290 : : code seems pretty fragile; it will break on a cleanup within any
7291 : : non-conditional nesting. But any such nesting would be broken, anyway;
7292 : : we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
7293 : : and continues out of it. We can do that at the RTL level, though, so
7294 : : having an optimizer to tighten up try/finally regions would be a Good
7295 : : Thing. */
7296 : :
7297 : : static enum gimplify_status
7298 : 4857410 : gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
7299 : : {
7300 : 4857410 : gimple_stmt_iterator iter;
7301 : 4857410 : gimple_seq body_sequence = NULL;
7302 : :
7303 : 4857410 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
7304 : :
7305 : : /* We only care about the number of conditions between the innermost
7306 : : CLEANUP_POINT_EXPR and the cleanup. So save and reset the count and
7307 : : any cleanups collected outside the CLEANUP_POINT_EXPR. */
7308 : 4857410 : int old_conds = gimplify_ctxp->conditions;
7309 : 4857410 : gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
7310 : 4857410 : bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
7311 : 4857410 : gimplify_ctxp->conditions = 0;
7312 : 4857410 : gimplify_ctxp->conditional_cleanups = NULL;
7313 : 4857410 : gimplify_ctxp->in_cleanup_point_expr = true;
7314 : :
7315 : 4857410 : gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
7316 : :
7317 : 4857410 : gimplify_ctxp->conditions = old_conds;
7318 : 4857410 : gimplify_ctxp->conditional_cleanups = old_cleanups;
7319 : 4857410 : gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
7320 : :
7321 : 24221149 : for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
7322 : : {
7323 : 14538704 : gimple *wce = gsi_stmt (iter);
7324 : :
7325 : 14538704 : if (gimple_code (wce) == GIMPLE_WITH_CLEANUP_EXPR)
7326 : : {
7327 : 450178 : if (gsi_one_before_end_p (iter))
7328 : : {
7329 : : /* Note that gsi_insert_seq_before and gsi_remove do not
7330 : : scan operands, unlike some other sequence mutators. */
7331 : 3430 : if (!gimple_wce_cleanup_eh_only (wce))
7332 : 3046 : gsi_insert_seq_before_without_update (&iter,
7333 : : gimple_wce_cleanup (wce),
7334 : : GSI_SAME_STMT);
7335 : 3430 : gsi_remove (&iter, true);
7336 : 3430 : break;
7337 : : }
7338 : : else
7339 : : {
7340 : 446748 : gtry *gtry;
7341 : 446748 : gimple_seq seq;
7342 : 446748 : enum gimple_try_flags kind;
7343 : :
7344 : 446748 : if (gimple_wce_cleanup_eh_only (wce))
7345 : : kind = GIMPLE_TRY_CATCH;
7346 : : else
7347 : 413296 : kind = GIMPLE_TRY_FINALLY;
7348 : 446748 : seq = gsi_split_seq_after (iter);
7349 : :
7350 : 446748 : gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
7351 : : /* Do not use gsi_replace here, as it may scan operands.
7352 : : We want to do a simple structural modification only. */
7353 : 446748 : gsi_set_stmt (&iter, gtry);
7354 : 893496 : iter = gsi_start (gtry->eval);
7355 : : }
7356 : : }
7357 : : else
7358 : 14088526 : gsi_next (&iter);
7359 : : }
7360 : :
7361 : 4857410 : gimplify_seq_add_seq (pre_p, body_sequence);
7362 : 4857410 : if (temp)
7363 : : {
7364 : 330792 : *expr_p = temp;
7365 : 330792 : return GS_OK;
7366 : : }
7367 : : else
7368 : : {
7369 : 4526618 : *expr_p = NULL;
7370 : 4526618 : return GS_ALL_DONE;
7371 : : }
7372 : : }
7373 : :
7374 : : /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
7375 : : is the cleanup action required. EH_ONLY is true if the cleanup should
7376 : : only be executed if an exception is thrown, not on normal exit.
7377 : : If FORCE_UNCOND is true perform the cleanup unconditionally; this is
7378 : : only valid for clobbers. */
7379 : :
7380 : : static void
7381 : 454135 : gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
7382 : : bool force_uncond = false)
7383 : : {
7384 : 454135 : gimple *wce;
7385 : 454135 : gimple_seq cleanup_stmts = NULL;
7386 : :
7387 : : /* Errors can result in improperly nested cleanups. Which results in
7388 : : confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
7389 : 454135 : if (seen_error ())
7390 : 3957 : return;
7391 : :
7392 : 450178 : if (gimple_conditional_context ())
7393 : : {
7394 : : /* If we're in a conditional context, this is more complex. We only
7395 : : want to run the cleanup if we actually ran the initialization that
7396 : : necessitates it, but we want to run it after the end of the
7397 : : conditional context. So we wrap the try/finally around the
7398 : : condition and use a flag to determine whether or not to actually
7399 : : run the destructor. Thus
7400 : :
7401 : : test ? f(A()) : 0
7402 : :
7403 : : becomes (approximately)
7404 : :
7405 : : flag = 0;
7406 : : try {
7407 : : if (test) { A::A(temp); flag = 1; val = f(temp); }
7408 : : else { val = 0; }
7409 : : } finally {
7410 : : if (flag) A::~A(temp);
7411 : : }
7412 : : val
7413 : : */
7414 : 10477 : if (force_uncond)
7415 : : {
7416 : 9791 : gimplify_stmt (&cleanup, &cleanup_stmts);
7417 : 9791 : wce = gimple_build_wce (cleanup_stmts);
7418 : 9791 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
7419 : : }
7420 : : else
7421 : : {
7422 : 686 : tree flag = create_tmp_var (boolean_type_node, "cleanup");
7423 : 686 : gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
7424 : 686 : gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
7425 : :
7426 : 686 : cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
7427 : 686 : gimplify_stmt (&cleanup, &cleanup_stmts);
7428 : 686 : wce = gimple_build_wce (cleanup_stmts);
7429 : 686 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
7430 : :
7431 : 686 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
7432 : 686 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
7433 : 686 : gimplify_seq_add_stmt (pre_p, ftrue);
7434 : :
7435 : : /* Because of this manipulation, and the EH edges that jump
7436 : : threading cannot redirect, the temporary (VAR) will appear
7437 : : to be used uninitialized. Don't warn. */
7438 : 686 : suppress_warning (var, OPT_Wuninitialized);
7439 : : }
7440 : : }
7441 : : else
7442 : : {
7443 : 439701 : gimplify_stmt (&cleanup, &cleanup_stmts);
7444 : 439701 : wce = gimple_build_wce (cleanup_stmts);
7445 : 439701 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
7446 : 439701 : gimplify_seq_add_stmt (pre_p, wce);
7447 : : }
7448 : : }
7449 : :
7450 : : /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
7451 : :
7452 : : static enum gimplify_status
7453 : 610878 : gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7454 : : {
7455 : 610878 : tree targ = *expr_p;
7456 : 610878 : tree temp = TARGET_EXPR_SLOT (targ);
7457 : 610878 : tree init = TARGET_EXPR_INITIAL (targ);
7458 : 610878 : enum gimplify_status ret;
7459 : :
7460 : 610878 : bool unpoison_empty_seq = false;
7461 : 610878 : gimple_stmt_iterator unpoison_it;
7462 : :
7463 : 610878 : if (init)
7464 : : {
7465 : 585118 : gimple_seq init_pre_p = NULL;
7466 : :
7467 : : /* TARGET_EXPR temps aren't part of the enclosing block, so add it
7468 : : to the temps list. Handle also variable length TARGET_EXPRs. */
7469 : 585118 : if (!poly_int_tree_p (DECL_SIZE (temp)))
7470 : : {
7471 : 26 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
7472 : 1 : gimplify_type_sizes (TREE_TYPE (temp), &init_pre_p);
7473 : : /* FIXME: this is correct only when the size of the type does
7474 : : not depend on expressions evaluated in init. */
7475 : 26 : gimplify_vla_decl (temp, &init_pre_p);
7476 : : }
7477 : : else
7478 : : {
7479 : : /* Save location where we need to place unpoisoning. It's possible
7480 : : that a variable will be converted to needs_to_live_in_memory. */
7481 : 585092 : unpoison_it = gsi_last (*pre_p);
7482 : 585092 : unpoison_empty_seq = gsi_end_p (unpoison_it);
7483 : :
7484 : 585092 : gimple_add_tmp_var (temp);
7485 : : }
7486 : :
7487 : : /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
7488 : : expression is supposed to initialize the slot. */
7489 : 585118 : if (VOID_TYPE_P (TREE_TYPE (init)))
7490 : 259126 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
7491 : : fb_none);
7492 : : else
7493 : : {
7494 : 325992 : tree init_expr = build2 (INIT_EXPR, void_type_node, temp, init);
7495 : 325992 : init = init_expr;
7496 : 325992 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
7497 : : fb_none);
7498 : 325992 : init = NULL;
7499 : 325992 : ggc_free (init_expr);
7500 : : }
7501 : 585118 : if (ret == GS_ERROR)
7502 : : {
7503 : : /* PR c++/28266 Make sure this is expanded only once. */
7504 : 11 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
7505 : 11 : return GS_ERROR;
7506 : : }
7507 : :
7508 : 585107 : if (init)
7509 : 0 : gimplify_and_add (init, &init_pre_p);
7510 : :
7511 : : /* Add a clobber for the temporary going out of scope, like
7512 : : gimplify_bind_expr. But only if we did not promote the
7513 : : temporary to static storage. */
7514 : 585107 : if (gimplify_ctxp->in_cleanup_point_expr
7515 : 440946 : && !TREE_STATIC (temp)
7516 : 1024980 : && needs_to_live_in_memory (temp))
7517 : : {
7518 : 337281 : if (flag_stack_reuse == SR_ALL)
7519 : : {
7520 : 336838 : tree clobber = build_clobber (TREE_TYPE (temp),
7521 : : CLOBBER_STORAGE_END);
7522 : 336838 : clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
7523 : 336838 : gimple_push_cleanup (temp, clobber, false, pre_p, true);
7524 : : }
7525 : 337281 : if (asan_poisoned_variables
7526 : 443 : && DECL_ALIGN (temp) <= MAX_SUPPORTED_STACK_ALIGNMENT
7527 : 443 : && !TREE_STATIC (temp)
7528 : 443 : && dbg_cnt (asan_use_after_scope)
7529 : 337724 : && !gimplify_omp_ctxp)
7530 : : {
7531 : 435 : tree asan_cleanup = build_asan_poison_call_expr (temp);
7532 : 435 : if (asan_cleanup)
7533 : : {
7534 : 435 : if (unpoison_empty_seq)
7535 : 223 : unpoison_it = gsi_start (*pre_p);
7536 : :
7537 : 435 : asan_poison_variable (temp, false, &unpoison_it,
7538 : : unpoison_empty_seq);
7539 : 435 : gimple_push_cleanup (temp, asan_cleanup, false, pre_p);
7540 : : }
7541 : : }
7542 : : }
7543 : :
7544 : 585107 : gimple_seq_add_seq (pre_p, init_pre_p);
7545 : :
7546 : : /* If needed, push the cleanup for the temp. */
7547 : 585107 : if (TARGET_EXPR_CLEANUP (targ))
7548 : 116862 : gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
7549 : 116862 : CLEANUP_EH_ONLY (targ), pre_p);
7550 : :
7551 : : /* Only expand this once. */
7552 : 585107 : TREE_OPERAND (targ, 3) = init;
7553 : 585107 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
7554 : : }
7555 : : else
7556 : : /* We should have expanded this before. */
7557 : 25760 : gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
7558 : :
7559 : 610867 : *expr_p = temp;
7560 : 610867 : return GS_OK;
7561 : : }
7562 : :
7563 : : /* Gimplification of expression trees. */
7564 : :
7565 : : /* Gimplify an expression which appears at statement context. The
7566 : : corresponding GIMPLE statements are added to *SEQ_P. If *SEQ_P is
7567 : : NULL, a new sequence is allocated.
7568 : :
7569 : : Return true if we actually added a statement to the queue. */
7570 : :
7571 : : bool
7572 : 93686804 : gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
7573 : : {
7574 : 93686804 : gimple_seq_node last;
7575 : :
7576 : 93686804 : last = gimple_seq_last (*seq_p);
7577 : 93686804 : gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
7578 : 93686804 : return last != gimple_seq_last (*seq_p);
7579 : : }
7580 : :
7581 : : /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
7582 : : to CTX. If entries already exist, force them to be some flavor of private.
7583 : : If there is no enclosing parallel, do nothing. */
7584 : :
7585 : : void
7586 : 118718 : omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
7587 : : {
7588 : 118718 : splay_tree_node n;
7589 : :
7590 : 118718 : if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE)
7591 : : return;
7592 : :
7593 : 35760 : do
7594 : : {
7595 : 35760 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
7596 : 35760 : if (n != NULL)
7597 : : {
7598 : 4454 : if (n->value & GOVD_SHARED)
7599 : 179 : n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
7600 : 4275 : else if (n->value & GOVD_MAP)
7601 : 59 : n->value |= GOVD_MAP_TO_ONLY;
7602 : : else
7603 : : return;
7604 : : }
7605 : 31306 : else if ((ctx->region_type & ORT_TARGET) != 0)
7606 : : {
7607 : 6880 : if (ctx->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
7608 : 4125 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
7609 : : else
7610 : 2755 : omp_add_variable (ctx, decl, GOVD_MAP | GOVD_MAP_TO_ONLY);
7611 : : }
7612 : 24426 : else if (ctx->region_type != ORT_WORKSHARE
7613 : : && ctx->region_type != ORT_TASKGROUP
7614 : 22525 : && ctx->region_type != ORT_SIMD
7615 : 21901 : && ctx->region_type != ORT_ACC
7616 : 21791 : && !(ctx->region_type & ORT_TARGET_DATA))
7617 : 13065 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
7618 : :
7619 : 31544 : ctx = ctx->outer_context;
7620 : : }
7621 : 31544 : while (ctx);
7622 : : }
7623 : :
7624 : : /* Similarly for each of the type sizes of TYPE. */
7625 : :
7626 : : static void
7627 : 38959 : omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
7628 : : {
7629 : 38959 : if (type == NULL || type == error_mark_node)
7630 : : return;
7631 : 38955 : type = TYPE_MAIN_VARIANT (type);
7632 : :
7633 : 38955 : if (ctx->privatized_types->add (type))
7634 : : return;
7635 : :
7636 : 29712 : switch (TREE_CODE (type))
7637 : : {
7638 : 12679 : case INTEGER_TYPE:
7639 : 12679 : case ENUMERAL_TYPE:
7640 : 12679 : case BOOLEAN_TYPE:
7641 : 12679 : case REAL_TYPE:
7642 : 12679 : case FIXED_POINT_TYPE:
7643 : 12679 : omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
7644 : 12679 : omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
7645 : 12679 : break;
7646 : :
7647 : 5075 : case ARRAY_TYPE:
7648 : 5075 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
7649 : 5075 : omp_firstprivatize_type_sizes (ctx, TYPE_DOMAIN (type));
7650 : 5075 : break;
7651 : :
7652 : 2483 : case RECORD_TYPE:
7653 : 2483 : case UNION_TYPE:
7654 : 2483 : case QUAL_UNION_TYPE:
7655 : 2483 : {
7656 : 2483 : tree field;
7657 : 26006 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
7658 : 23523 : if (TREE_CODE (field) == FIELD_DECL)
7659 : : {
7660 : 8825 : omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
7661 : 8825 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (field));
7662 : : }
7663 : : }
7664 : : break;
7665 : :
7666 : 8826 : case POINTER_TYPE:
7667 : 8826 : case REFERENCE_TYPE:
7668 : 8826 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
7669 : 8826 : break;
7670 : :
7671 : : default:
7672 : : break;
7673 : : }
7674 : :
7675 : 29712 : omp_firstprivatize_variable (ctx, TYPE_SIZE (type));
7676 : 29712 : omp_firstprivatize_variable (ctx, TYPE_SIZE_UNIT (type));
7677 : 29712 : lang_hooks.types.omp_firstprivatize_type_sizes (ctx, type);
7678 : : }
7679 : :
7680 : : /* Add an entry for DECL in the OMP context CTX with FLAGS. */
7681 : :
7682 : : static void
7683 : 660447 : omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
7684 : : {
7685 : 660447 : splay_tree_node n;
7686 : 660447 : unsigned int nflags;
7687 : 660447 : tree t;
7688 : :
7689 : 660447 : if (error_operand_p (decl) || ctx->region_type == ORT_NONE)
7690 : : return;
7691 : :
7692 : : /* Never elide decls whose type has TREE_ADDRESSABLE set. This means
7693 : : there are constructors involved somewhere. Exception is a shared clause,
7694 : : there is nothing privatized in that case. */
7695 : 660424 : if ((flags & GOVD_SHARED) == 0
7696 : 660424 : && (TREE_ADDRESSABLE (TREE_TYPE (decl))
7697 : 603789 : || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
7698 : 3627 : flags |= GOVD_SEEN;
7699 : :
7700 : 660424 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
7701 : 660424 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
7702 : : {
7703 : : /* We shouldn't be re-adding the decl with the same data
7704 : : sharing class. */
7705 : 901 : gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
7706 : 901 : nflags = n->value | flags;
7707 : : /* The only combination of data sharing classes we should see is
7708 : : FIRSTPRIVATE and LASTPRIVATE. However, OpenACC permits
7709 : : reduction variables to be used in data sharing clauses. */
7710 : 901 : gcc_assert ((ctx->region_type & ORT_ACC) != 0
7711 : : || ((nflags & GOVD_DATA_SHARE_CLASS)
7712 : : == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE))
7713 : : || (flags & GOVD_DATA_SHARE_CLASS) == 0);
7714 : 901 : n->value = nflags;
7715 : 901 : return;
7716 : : }
7717 : :
7718 : : /* When adding a variable-sized variable, we have to handle all sorts
7719 : : of additional bits of data: the pointer replacement variable, and
7720 : : the parameters of the type. */
7721 : 659523 : if (DECL_SIZE (decl) && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
7722 : : {
7723 : : /* Add the pointer replacement variable as PRIVATE if the variable
7724 : : replacement is private, else FIRSTPRIVATE since we'll need the
7725 : : address of the original variable either for SHARED, or for the
7726 : : copy into or out of the context. */
7727 : 1395 : if (!(flags & GOVD_LOCAL) && ctx->region_type != ORT_TASKGROUP)
7728 : : {
7729 : 1301 : if (flags & GOVD_MAP)
7730 : : nflags = GOVD_MAP | GOVD_MAP_TO_ONLY | GOVD_EXPLICIT;
7731 : 563 : else if (flags & GOVD_PRIVATE)
7732 : : nflags = GOVD_PRIVATE;
7733 : 479 : else if (((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
7734 : 48 : && (flags & GOVD_FIRSTPRIVATE))
7735 : 471 : || (ctx->region_type == ORT_TARGET_DATA
7736 : 6 : && (flags & GOVD_DATA_SHARE_CLASS) == 0))
7737 : : nflags = GOVD_PRIVATE | GOVD_EXPLICIT;
7738 : : else
7739 : 1301 : nflags = GOVD_FIRSTPRIVATE;
7740 : 1301 : nflags |= flags & GOVD_SEEN;
7741 : 1301 : t = DECL_VALUE_EXPR (decl);
7742 : 1301 : gcc_assert (INDIRECT_REF_P (t));
7743 : 1301 : t = TREE_OPERAND (t, 0);
7744 : 1301 : gcc_assert (DECL_P (t));
7745 : 1301 : omp_add_variable (ctx, t, nflags);
7746 : : }
7747 : :
7748 : : /* Add all of the variable and type parameters (which should have
7749 : : been gimplified to a formal temporary) as FIRSTPRIVATE. */
7750 : 1395 : omp_firstprivatize_variable (ctx, DECL_SIZE_UNIT (decl));
7751 : 1395 : omp_firstprivatize_variable (ctx, DECL_SIZE (decl));
7752 : 1395 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
7753 : :
7754 : : /* The variable-sized variable itself is never SHARED, only some form
7755 : : of PRIVATE. The sharing would take place via the pointer variable
7756 : : which we remapped above. */
7757 : 1395 : if (flags & GOVD_SHARED)
7758 : 322 : flags = GOVD_SHARED | GOVD_DEBUG_PRIVATE
7759 : 322 : | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
7760 : :
7761 : : /* We're going to make use of the TYPE_SIZE_UNIT at least in the
7762 : : alloca statement we generate for the variable, so make sure it
7763 : : is available. This isn't automatically needed for the SHARED
7764 : : case, since we won't be allocating local storage then.
7765 : : For local variables TYPE_SIZE_UNIT might not be gimplified yet,
7766 : : in this case omp_notice_variable will be called later
7767 : : on when it is gimplified. */
7768 : 1073 : else if (! (flags & (GOVD_LOCAL | GOVD_MAP))
7769 : 1073 : && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
7770 : 269 : omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
7771 : : }
7772 : 658128 : else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
7773 : 658128 : && omp_privatize_by_reference (decl))
7774 : : {
7775 : 9763 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
7776 : :
7777 : : /* Similar to the direct variable sized case above, we'll need the
7778 : : size of references being privatized. */
7779 : 9763 : if ((flags & GOVD_SHARED) == 0)
7780 : : {
7781 : 6626 : t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
7782 : 6626 : if (t && DECL_P (t))
7783 : 1337 : omp_notice_variable (ctx, t, true);
7784 : : }
7785 : : }
7786 : :
7787 : 659523 : if (n != NULL)
7788 : 1765 : n->value |= flags;
7789 : : else
7790 : 657758 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
7791 : :
7792 : : /* For reductions clauses in OpenACC loop directives, by default create a
7793 : : copy clause on the enclosing parallel construct for carrying back the
7794 : : results. */
7795 : 659523 : if (ctx->region_type == ORT_ACC && (flags & GOVD_REDUCTION))
7796 : : {
7797 : 4282 : struct gimplify_omp_ctx *outer_ctx = ctx->outer_context;
7798 : 5662 : while (outer_ctx)
7799 : : {
7800 : 5139 : n = splay_tree_lookup (outer_ctx->variables, (splay_tree_key)decl);
7801 : 5139 : if (n != NULL)
7802 : : {
7803 : : /* Ignore local variables and explicitly declared clauses. */
7804 : 3565 : if (n->value & (GOVD_LOCAL | GOVD_EXPLICIT))
7805 : : break;
7806 : 353 : else if (outer_ctx->region_type == ORT_ACC_KERNELS)
7807 : : {
7808 : : /* According to the OpenACC spec, such a reduction variable
7809 : : should already have a copy map on a kernels construct,
7810 : : verify that here. */
7811 : 173 : gcc_assert (!(n->value & GOVD_FIRSTPRIVATE)
7812 : : && (n->value & GOVD_MAP));
7813 : : }
7814 : 180 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
7815 : : {
7816 : : /* Remove firstprivate and make it a copy map. */
7817 : 180 : n->value &= ~GOVD_FIRSTPRIVATE;
7818 : 180 : n->value |= GOVD_MAP;
7819 : : }
7820 : : }
7821 : 1574 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
7822 : : {
7823 : 547 : splay_tree_insert (outer_ctx->variables, (splay_tree_key)decl,
7824 : : GOVD_MAP | GOVD_SEEN);
7825 : 547 : break;
7826 : : }
7827 : 1380 : outer_ctx = outer_ctx->outer_context;
7828 : : }
7829 : : }
7830 : : }
7831 : :
7832 : : /* Notice a threadprivate variable DECL used in OMP context CTX.
7833 : : This just prints out diagnostics about threadprivate variable uses
7834 : : in untied tasks. If DECL2 is non-NULL, prevent this warning
7835 : : on that variable. */
7836 : :
7837 : : static bool
7838 : 13598 : omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
7839 : : tree decl2)
7840 : : {
7841 : 13598 : splay_tree_node n;
7842 : 13598 : struct gimplify_omp_ctx *octx;
7843 : :
7844 : 27389 : for (octx = ctx; octx; octx = octx->outer_context)
7845 : 13791 : if ((octx->region_type & ORT_TARGET) != 0
7846 : 13791 : || octx->order_concurrent)
7847 : : {
7848 : 136 : n = splay_tree_lookup (octx->variables, (splay_tree_key)decl);
7849 : 136 : if (n == NULL)
7850 : : {
7851 : 24 : if (octx->order_concurrent)
7852 : : {
7853 : 24 : error ("threadprivate variable %qE used in a region with"
7854 : 24 : " %<order(concurrent)%> clause", DECL_NAME (decl));
7855 : 24 : inform (octx->location, "enclosing region");
7856 : : }
7857 : : else
7858 : : {
7859 : 0 : error ("threadprivate variable %qE used in target region",
7860 : 0 : DECL_NAME (decl));
7861 : 0 : inform (octx->location, "enclosing target region");
7862 : : }
7863 : 24 : splay_tree_insert (octx->variables, (splay_tree_key)decl, 0);
7864 : : }
7865 : 136 : if (decl2)
7866 : 0 : splay_tree_insert (octx->variables, (splay_tree_key)decl2, 0);
7867 : : }
7868 : :
7869 : 13598 : if (ctx->region_type != ORT_UNTIED_TASK)
7870 : : return false;
7871 : 37 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
7872 : 37 : if (n == NULL)
7873 : : {
7874 : 6 : error ("threadprivate variable %qE used in untied task",
7875 : 6 : DECL_NAME (decl));
7876 : 6 : inform (ctx->location, "enclosing task");
7877 : 6 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
7878 : : }
7879 : 37 : if (decl2)
7880 : 4 : splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
7881 : : return false;
7882 : : }
7883 : :
7884 : : /* Return true if global var DECL is device resident. */
7885 : :
7886 : : static bool
7887 : 618 : device_resident_p (tree decl)
7888 : : {
7889 : 618 : tree attr = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (decl));
7890 : :
7891 : 618 : if (!attr)
7892 : : return false;
7893 : :
7894 : 0 : for (tree t = TREE_VALUE (attr); t; t = TREE_PURPOSE (t))
7895 : : {
7896 : 0 : tree c = TREE_VALUE (t);
7897 : 0 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DEVICE_RESIDENT)
7898 : : return true;
7899 : : }
7900 : :
7901 : : return false;
7902 : : }
7903 : :
7904 : : /* Return true if DECL has an ACC DECLARE attribute. */
7905 : :
7906 : : static bool
7907 : 8795 : is_oacc_declared (tree decl)
7908 : : {
7909 : 8795 : tree t = TREE_CODE (decl) == MEM_REF ? TREE_OPERAND (decl, 0) : decl;
7910 : 8795 : tree declared = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (t));
7911 : 8795 : return declared != NULL_TREE;
7912 : : }
7913 : :
7914 : : /* Determine outer default flags for DECL mentioned in an OMP region
7915 : : but not declared in an enclosing clause.
7916 : :
7917 : : ??? Some compiler-generated variables (like SAVE_EXPRs) could be
7918 : : remapped firstprivate instead of shared. To some extent this is
7919 : : addressed in omp_firstprivatize_type_sizes, but not
7920 : : effectively. */
7921 : :
7922 : : static unsigned
7923 : 43936 : omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
7924 : : bool in_code, unsigned flags)
7925 : : {
7926 : 43936 : enum omp_clause_default_kind default_kind = ctx->default_kind;
7927 : 43936 : enum omp_clause_default_kind kind;
7928 : :
7929 : 43936 : kind = lang_hooks.decls.omp_predetermined_sharing (decl);
7930 : 43936 : if (ctx->region_type & ORT_TASK)
7931 : : {
7932 : 2996 : tree detach_clause = omp_find_clause (ctx->clauses, OMP_CLAUSE_DETACH);
7933 : :
7934 : : /* The event-handle specified by a detach clause should always be firstprivate,
7935 : : regardless of the current default. */
7936 : 3208 : if (detach_clause && OMP_CLAUSE_DECL (detach_clause) == decl)
7937 : : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
7938 : : }
7939 : 43936 : if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
7940 : : default_kind = kind;
7941 : 56063 : else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
7942 : : default_kind = OMP_CLAUSE_DEFAULT_SHARED;
7943 : : /* For C/C++ default({,first}private), variables with static storage duration
7944 : : declared in a namespace or global scope and referenced in construct
7945 : : must be explicitly specified, i.e. acts as default(none). */
7946 : 41385 : else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
7947 : 41385 : || default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
7948 : 434 : && VAR_P (decl)
7949 : 393 : && is_global_var (decl)
7950 : 240 : && (DECL_FILE_SCOPE_P (decl)
7951 : 136 : || (DECL_CONTEXT (decl)
7952 : 136 : && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
7953 : 41553 : && !lang_GNU_Fortran ())
7954 : : default_kind = OMP_CLAUSE_DEFAULT_NONE;
7955 : :
7956 : 43767 : switch (default_kind)
7957 : : {
7958 : 335 : case OMP_CLAUSE_DEFAULT_NONE:
7959 : 335 : {
7960 : 335 : const char *rtype;
7961 : :
7962 : 335 : if (ctx->region_type & ORT_PARALLEL)
7963 : : rtype = "parallel";
7964 : 141 : else if ((ctx->region_type & ORT_TASKLOOP) == ORT_TASKLOOP)
7965 : : rtype = "taskloop";
7966 : 94 : else if (ctx->region_type & ORT_TASK)
7967 : : rtype = "task";
7968 : 47 : else if (ctx->region_type & ORT_TEAMS)
7969 : : rtype = "teams";
7970 : : else
7971 : 0 : gcc_unreachable ();
7972 : :
7973 : 335 : error ("%qE not specified in enclosing %qs",
7974 : 335 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)), rtype);
7975 : 335 : inform (ctx->location, "enclosing %qs", rtype);
7976 : : }
7977 : : /* FALLTHRU */
7978 : 41168 : case OMP_CLAUSE_DEFAULT_SHARED:
7979 : 41168 : flags |= GOVD_SHARED;
7980 : 41168 : break;
7981 : 171 : case OMP_CLAUSE_DEFAULT_PRIVATE:
7982 : 171 : flags |= GOVD_PRIVATE;
7983 : 171 : break;
7984 : 303 : case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
7985 : 303 : flags |= GOVD_FIRSTPRIVATE;
7986 : 303 : break;
7987 : 2294 : case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
7988 : : /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */
7989 : 2294 : gcc_assert ((ctx->region_type & ORT_TASK) != 0);
7990 : 2294 : if (struct gimplify_omp_ctx *octx = ctx->outer_context)
7991 : : {
7992 : 1386 : omp_notice_variable (octx, decl, in_code);
7993 : 2221 : for (; octx; octx = octx->outer_context)
7994 : : {
7995 : 2158 : splay_tree_node n2;
7996 : :
7997 : 2158 : n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
7998 : 2158 : if ((octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)) != 0
7999 : 6 : && (n2 == NULL || (n2->value & GOVD_DATA_SHARE_CLASS) == 0))
8000 : 6 : continue;
8001 : 2152 : if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
8002 : : {
8003 : 363 : flags |= GOVD_FIRSTPRIVATE;
8004 : 363 : goto found_outer;
8005 : : }
8006 : 1789 : if ((octx->region_type & (ORT_PARALLEL | ORT_TEAMS)) != 0)
8007 : : {
8008 : 960 : flags |= GOVD_SHARED;
8009 : 960 : goto found_outer;
8010 : : }
8011 : : }
8012 : : }
8013 : :
8014 : 971 : if (TREE_CODE (decl) == PARM_DECL
8015 : 971 : || (!is_global_var (decl)
8016 : 195 : && DECL_CONTEXT (decl) == current_function_decl))
8017 : 534 : flags |= GOVD_FIRSTPRIVATE;
8018 : : else
8019 : 437 : flags |= GOVD_SHARED;
8020 : 43936 : found_outer:
8021 : : break;
8022 : :
8023 : 0 : default:
8024 : 0 : gcc_unreachable ();
8025 : : }
8026 : :
8027 : 43936 : return flags;
8028 : : }
8029 : :
8030 : : /* Return string name for types of OpenACC constructs from ORT_* values. */
8031 : :
8032 : : static const char *
8033 : 288 : oacc_region_type_name (enum omp_region_type region_type)
8034 : : {
8035 : 288 : switch (region_type)
8036 : : {
8037 : : case ORT_ACC_DATA:
8038 : : return "data";
8039 : 168 : case ORT_ACC_PARALLEL:
8040 : 168 : return "parallel";
8041 : 48 : case ORT_ACC_KERNELS:
8042 : 48 : return "kernels";
8043 : 0 : case ORT_ACC_SERIAL:
8044 : 0 : return "serial";
8045 : 0 : default:
8046 : 0 : gcc_unreachable ();
8047 : : }
8048 : : }
8049 : :
8050 : : /* Determine outer default flags for DECL mentioned in an OACC region
8051 : : but not declared in an enclosing clause. */
8052 : :
8053 : : static unsigned
8054 : 8473 : oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
8055 : : {
8056 : 8473 : struct gimplify_omp_ctx *ctx_default = ctx;
8057 : : /* If no 'default' clause appears on this compute construct... */
8058 : 8473 : if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED)
8059 : : {
8060 : : /* ..., see if one appears on a lexically containing 'data'
8061 : : construct. */
8062 : 9233 : while ((ctx_default = ctx_default->outer_context))
8063 : : {
8064 : 1392 : if (ctx_default->region_type == ORT_ACC_DATA
8065 : 1392 : && ctx_default->default_kind != OMP_CLAUSE_DEFAULT_SHARED)
8066 : : break;
8067 : : }
8068 : : /* If not, reset. */
8069 : 7935 : if (!ctx_default)
8070 : 8379 : ctx_default = ctx;
8071 : : }
8072 : :
8073 : 8473 : bool on_device = false;
8074 : 8473 : bool is_private = false;
8075 : 8473 : bool declared = is_oacc_declared (decl);
8076 : 8473 : tree type = TREE_TYPE (decl);
8077 : :
8078 : 8473 : if (omp_privatize_by_reference (decl))
8079 : 337 : type = TREE_TYPE (type);
8080 : :
8081 : : /* For Fortran COMMON blocks, only used variables in those blocks are
8082 : : transfered and remapped. The block itself will have a private clause to
8083 : : avoid transfering the data twice.
8084 : : The hook evaluates to false by default. For a variable in Fortran's COMMON
8085 : : or EQUIVALENCE block, returns 'true' (as we have shared=false) - as only
8086 : : the variables in such a COMMON/EQUIVALENCE block shall be privatized not
8087 : : the whole block. For C++ and Fortran, it can also be true under certain
8088 : : other conditions, if DECL_HAS_VALUE_EXPR. */
8089 : 8473 : if (RECORD_OR_UNION_TYPE_P (type))
8090 : 954 : is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false);
8091 : :
8092 : 8473 : if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0
8093 : 8473 : && is_global_var (decl)
8094 : 618 : && device_resident_p (decl)
8095 : 8473 : && !is_private)
8096 : : {
8097 : 0 : on_device = true;
8098 : 0 : flags |= GOVD_MAP_TO_ONLY;
8099 : : }
8100 : :
8101 : 8473 : switch (ctx->region_type)
8102 : : {
8103 : 1553 : case ORT_ACC_KERNELS:
8104 : 1553 : if (is_private)
8105 : 0 : flags |= GOVD_FIRSTPRIVATE;
8106 : 1553 : else if (AGGREGATE_TYPE_P (type))
8107 : : {
8108 : : /* Aggregates default to 'present_or_copy', or 'present'. */
8109 : 424 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
8110 : 404 : flags |= GOVD_MAP;
8111 : : else
8112 : 20 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
8113 : : }
8114 : : else
8115 : : /* Scalars default to 'copy'. */
8116 : 1129 : flags |= GOVD_MAP | GOVD_MAP_FORCE;
8117 : :
8118 : : break;
8119 : :
8120 : 6920 : case ORT_ACC_PARALLEL:
8121 : 6920 : case ORT_ACC_SERIAL:
8122 : 6920 : if (is_private)
8123 : 0 : flags |= GOVD_FIRSTPRIVATE;
8124 : 6920 : else if (on_device || declared)
8125 : 17 : flags |= GOVD_MAP;
8126 : 6903 : else if (AGGREGATE_TYPE_P (type))
8127 : : {
8128 : : /* Aggregates default to 'present_or_copy', or 'present'. */
8129 : 3428 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
8130 : 3173 : flags |= GOVD_MAP;
8131 : : else
8132 : 255 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
8133 : : }
8134 : : else
8135 : : /* Scalars default to 'firstprivate'. */
8136 : 3475 : flags |= GOVD_FIRSTPRIVATE;
8137 : :
8138 : : break;
8139 : :
8140 : 0 : default:
8141 : 0 : gcc_unreachable ();
8142 : : }
8143 : :
8144 : 8473 : if (DECL_ARTIFICIAL (decl))
8145 : : ; /* We can get compiler-generated decls, and should not complain
8146 : : about them. */
8147 : 8187 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_NONE)
8148 : : {
8149 : 216 : error ("%qE not specified in enclosing OpenACC %qs construct",
8150 : 108 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)),
8151 : : oacc_region_type_name (ctx->region_type));
8152 : 108 : if (ctx_default != ctx)
8153 : 72 : inform (ctx->location, "enclosing OpenACC %qs construct and",
8154 : : oacc_region_type_name (ctx->region_type));
8155 : 108 : inform (ctx_default->location,
8156 : : "enclosing OpenACC %qs construct with %qs clause",
8157 : : oacc_region_type_name (ctx_default->region_type),
8158 : : "default(none)");
8159 : : }
8160 : 8079 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_PRESENT)
8161 : : ; /* Handled above. */
8162 : : else
8163 : 7558 : gcc_checking_assert (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED);
8164 : :
8165 : 8473 : return flags;
8166 : : }
8167 : :
8168 : : /* Record the fact that DECL was used within the OMP context CTX.
8169 : : IN_CODE is true when real code uses DECL, and false when we should
8170 : : merely emit default(none) errors. Return true if DECL is going to
8171 : : be remapped and thus DECL shouldn't be gimplified into its
8172 : : DECL_VALUE_EXPR (if any). */
8173 : :
8174 : : static bool
8175 : 3591277 : omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
8176 : : {
8177 : 3591277 : splay_tree_node n;
8178 : 3591277 : unsigned flags = in_code ? GOVD_SEEN : 0;
8179 : 3591277 : bool ret = false, shared;
8180 : :
8181 : 3591277 : if (error_operand_p (decl))
8182 : : return false;
8183 : :
8184 : 3591277 : if (DECL_ARTIFICIAL (decl))
8185 : : {
8186 : 2042068 : tree attr = lookup_attribute ("omp allocate var", DECL_ATTRIBUTES (decl));
8187 : 2042068 : if (attr)
8188 : 531 : decl = TREE_VALUE (TREE_VALUE (attr));
8189 : : }
8190 : :
8191 : 3591277 : if (ctx->region_type == ORT_NONE)
8192 : 156 : return lang_hooks.decls.omp_disregard_value_expr (decl, false);
8193 : :
8194 : 3591121 : if (is_global_var (decl))
8195 : : {
8196 : : /* Threadprivate variables are predetermined. */
8197 : 471322 : if (DECL_THREAD_LOCAL_P (decl))
8198 : 12980 : return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
8199 : :
8200 : 458342 : if (DECL_HAS_VALUE_EXPR_P (decl))
8201 : : {
8202 : 4340 : if (ctx->region_type & ORT_ACC)
8203 : : /* For OpenACC, defer expansion of value to avoid transfering
8204 : : privatized common block data instead of im-/explicitly transfered
8205 : : variables which are in common blocks. */
8206 : : ;
8207 : : else
8208 : : {
8209 : 2086 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
8210 : :
8211 : 2086 : if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
8212 : 618 : return omp_notice_threadprivate_variable (ctx, decl, value);
8213 : : }
8214 : : }
8215 : :
8216 : 457724 : if (gimplify_omp_ctxp->outer_context == NULL
8217 : 81331 : && VAR_P (decl)
8218 : 539055 : && oacc_get_fn_attrib (current_function_decl))
8219 : : {
8220 : 824 : location_t loc = DECL_SOURCE_LOCATION (decl);
8221 : :
8222 : 824 : if (lookup_attribute ("omp declare target link",
8223 : 824 : DECL_ATTRIBUTES (decl)))
8224 : : {
8225 : 60 : error_at (loc,
8226 : : "%qE with %<link%> clause used in %<routine%> function",
8227 : 30 : DECL_NAME (decl));
8228 : 30 : return false;
8229 : : }
8230 : 794 : else if (!lookup_attribute ("omp declare target",
8231 : 794 : DECL_ATTRIBUTES (decl)))
8232 : : {
8233 : 160 : error_at (loc,
8234 : : "%qE requires a %<declare%> directive for use "
8235 : 80 : "in a %<routine%> function", DECL_NAME (decl));
8236 : 80 : return false;
8237 : : }
8238 : : }
8239 : : }
8240 : :
8241 : 3577413 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8242 : 3577413 : if ((ctx->region_type & ORT_TARGET) != 0)
8243 : : {
8244 : 623070 : if (n == NULL)
8245 : : {
8246 : 32869 : unsigned nflags = flags;
8247 : 32869 : if ((ctx->region_type & ORT_ACC) == 0)
8248 : : {
8249 : 22304 : bool is_declare_target = false;
8250 : 22304 : if (is_global_var (decl)
8251 : 22304 : && varpool_node::get_create (decl)->offloadable)
8252 : : {
8253 : 7034 : struct gimplify_omp_ctx *octx;
8254 : 7034 : for (octx = ctx->outer_context;
8255 : 7044 : octx; octx = octx->outer_context)
8256 : : {
8257 : 11 : n = splay_tree_lookup (octx->variables,
8258 : : (splay_tree_key)decl);
8259 : 11 : if (n
8260 : 11 : && (n->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED
8261 : 11 : && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
8262 : : break;
8263 : : }
8264 : 7034 : is_declare_target = octx == NULL;
8265 : : }
8266 : 7034 : if (!is_declare_target)
8267 : : {
8268 : 15271 : int gdmk;
8269 : 15271 : enum omp_clause_defaultmap_kind kind;
8270 : 15271 : if (lang_hooks.decls.omp_allocatable_p (decl))
8271 : : gdmk = GDMK_ALLOCATABLE;
8272 : 14961 : else if (lang_hooks.decls.omp_scalar_target_p (decl))
8273 : : gdmk = GDMK_SCALAR_TARGET;
8274 : 14886 : else if (lang_hooks.decls.omp_scalar_p (decl, false))
8275 : : gdmk = GDMK_SCALAR;
8276 : 2072 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
8277 : 2072 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
8278 : 273 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
8279 : : == POINTER_TYPE)))
8280 : : gdmk = GDMK_POINTER;
8281 : : else
8282 : : gdmk = GDMK_AGGREGATE;
8283 : 15271 : kind = lang_hooks.decls.omp_predetermined_mapping (decl);
8284 : 15271 : if (kind != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
8285 : : {
8286 : 891 : if (kind == OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE)
8287 : 114 : nflags |= GOVD_FIRSTPRIVATE;
8288 : 777 : else if (kind == OMP_CLAUSE_DEFAULTMAP_TO)
8289 : 777 : nflags |= GOVD_MAP | GOVD_MAP_TO_ONLY;
8290 : : else
8291 : 0 : gcc_unreachable ();
8292 : : }
8293 : 14380 : else if (ctx->defaultmap[gdmk] == 0)
8294 : : {
8295 : 76 : tree d = lang_hooks.decls.omp_report_decl (decl);
8296 : 76 : error ("%qE not specified in enclosing %<target%>",
8297 : 76 : DECL_NAME (d));
8298 : 76 : inform (ctx->location, "enclosing %<target%>");
8299 : : }
8300 : 14304 : else if (ctx->defaultmap[gdmk]
8301 : 14304 : & (GOVD_MAP_0LEN_ARRAY | GOVD_FIRSTPRIVATE))
8302 : 8845 : nflags |= ctx->defaultmap[gdmk];
8303 : 5459 : else if (ctx->defaultmap[gdmk] & GOVD_MAP_FORCE_PRESENT)
8304 : : {
8305 : 44 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
8306 : 44 : nflags |= ctx->defaultmap[gdmk] | GOVD_MAP_ALLOC_ONLY;
8307 : : }
8308 : : else
8309 : : {
8310 : 5415 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
8311 : 5415 : nflags |= ctx->defaultmap[gdmk] & ~GOVD_MAP;
8312 : : }
8313 : : }
8314 : : }
8315 : :
8316 : 32869 : struct gimplify_omp_ctx *octx = ctx->outer_context;
8317 : 32869 : if ((ctx->region_type & ORT_ACC) && octx)
8318 : : {
8319 : : /* Look in outer OpenACC contexts, to see if there's a
8320 : : data attribute for this variable. */
8321 : 3405 : omp_notice_variable (octx, decl, in_code);
8322 : :
8323 : 4905 : for (; octx; octx = octx->outer_context)
8324 : : {
8325 : 3587 : if (!(octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)))
8326 : : break;
8327 : 3587 : splay_tree_node n2
8328 : 3587 : = splay_tree_lookup (octx->variables,
8329 : : (splay_tree_key) decl);
8330 : 3587 : if (n2)
8331 : : {
8332 : 2087 : if (octx->region_type == ORT_ACC_HOST_DATA)
8333 : 5 : error ("variable %qE declared in enclosing "
8334 : 5 : "%<host_data%> region", DECL_NAME (decl));
8335 : 2087 : nflags |= GOVD_MAP;
8336 : 2087 : if (octx->region_type == ORT_ACC_DATA
8337 : 2082 : && (n2->value & GOVD_MAP_0LEN_ARRAY))
8338 : 291 : nflags |= GOVD_MAP_0LEN_ARRAY;
8339 : 2087 : goto found_outer;
8340 : : }
8341 : : }
8342 : : }
8343 : :
8344 : 30782 : if ((nflags & ~(GOVD_MAP_TO_ONLY | GOVD_MAP_FROM_ONLY
8345 : : | GOVD_MAP_ALLOC_ONLY)) == flags)
8346 : : {
8347 : 21002 : tree type = TREE_TYPE (decl);
8348 : :
8349 : 21002 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases
8350 : 21002 : && omp_privatize_by_reference (decl))
8351 : 28 : type = TREE_TYPE (type);
8352 : 21002 : if (!omp_mappable_type (type))
8353 : : {
8354 : 10 : error ("%qD referenced in target region does not have "
8355 : : "a mappable type", decl);
8356 : 10 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
8357 : : }
8358 : : else
8359 : : {
8360 : 20992 : if ((ctx->region_type & ORT_ACC) != 0)
8361 : 8473 : nflags = oacc_default_clause (ctx, decl, flags);
8362 : : else
8363 : 12519 : nflags |= GOVD_MAP;
8364 : : }
8365 : : }
8366 : 9780 : found_outer:
8367 : 32869 : omp_add_variable (ctx, decl, nflags);
8368 : 32869 : if (ctx->region_type & ORT_ACC)
8369 : : /* For OpenACC, as remarked above, defer expansion. */
8370 : : shared = false;
8371 : : else
8372 : 22304 : shared = (nflags & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
8373 : 32869 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
8374 : : }
8375 : : else
8376 : : {
8377 : 590201 : if (ctx->region_type & ORT_ACC)
8378 : : /* For OpenACC, as remarked above, defer expansion. */
8379 : : shared = false;
8380 : : else
8381 : 296471 : shared = ((n->value | flags)
8382 : 296471 : & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
8383 : 590201 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
8384 : : /* If nothing changed, there's nothing left to do. */
8385 : 590201 : if ((n->value & flags) == flags)
8386 : : return ret;
8387 : 15657 : flags |= n->value;
8388 : 15657 : n->value = flags;
8389 : : }
8390 : 48526 : goto do_outer;
8391 : : }
8392 : :
8393 : 2954343 : if (n == NULL)
8394 : : {
8395 : 1144574 : if (ctx->region_type == ORT_WORKSHARE
8396 : : || ctx->region_type == ORT_TASKGROUP
8397 : 557689 : || ctx->region_type == ORT_SIMD
8398 : 283837 : || ctx->region_type == ORT_ACC
8399 : 88027 : || (ctx->region_type & ORT_TARGET_DATA) != 0)
8400 : 1100638 : goto do_outer;
8401 : :
8402 : 43936 : flags = omp_default_clause (ctx, decl, in_code, flags);
8403 : :
8404 : 43936 : if ((flags & GOVD_PRIVATE)
8405 : 43936 : && lang_hooks.decls.omp_private_outer_ref (decl))
8406 : 6 : flags |= GOVD_PRIVATE_OUTER_REF;
8407 : :
8408 : 43936 : omp_add_variable (ctx, decl, flags);
8409 : :
8410 : 43936 : shared = (flags & GOVD_SHARED) != 0;
8411 : 43936 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
8412 : 43936 : goto do_outer;
8413 : : }
8414 : :
8415 : : /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd
8416 : : lb, b or incr expressions, those shouldn't be turned into simd arrays. */
8417 : 1809769 : if (ctx->region_type == ORT_SIMD
8418 : 155051 : && ctx->in_for_exprs
8419 : 79 : && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT))
8420 : : == GOVD_PRIVATE))
8421 : 1809769 : flags &= ~GOVD_SEEN;
8422 : :
8423 : 1809769 : if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
8424 : 30901 : && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
8425 : 1840622 : && DECL_SIZE (decl))
8426 : : {
8427 : 30852 : if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
8428 : : {
8429 : 140 : splay_tree_node n2;
8430 : 140 : tree t = DECL_VALUE_EXPR (decl);
8431 : 140 : gcc_assert (INDIRECT_REF_P (t));
8432 : 140 : t = TREE_OPERAND (t, 0);
8433 : 140 : gcc_assert (DECL_P (t));
8434 : 140 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
8435 : 140 : n2->value |= GOVD_SEEN;
8436 : : }
8437 : 30712 : else if (omp_privatize_by_reference (decl)
8438 : 4232 : && TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)))
8439 : 34907 : && (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
8440 : : != INTEGER_CST))
8441 : : {
8442 : 1312 : splay_tree_node n2;
8443 : 1312 : tree t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
8444 : 1312 : gcc_assert (DECL_P (t));
8445 : 1312 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
8446 : 1312 : if (n2)
8447 : 605 : omp_notice_variable (ctx, t, true);
8448 : : }
8449 : : }
8450 : :
8451 : 1809769 : if (ctx->region_type & ORT_ACC)
8452 : : /* For OpenACC, as remarked above, defer expansion. */
8453 : : shared = false;
8454 : : else
8455 : 1629663 : shared = ((flags | n->value) & GOVD_SHARED) != 0;
8456 : 1809769 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
8457 : :
8458 : : /* If nothing changed, there's nothing left to do. */
8459 : 1809769 : if ((n->value & flags) == flags)
8460 : : return ret;
8461 : 30853 : flags |= n->value;
8462 : 30853 : n->value = flags;
8463 : :
8464 : 1223953 : do_outer:
8465 : : /* If the variable is private in the current context, then we don't
8466 : : need to propagate anything to an outer context. */
8467 : 1223953 : if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF))
8468 : : return ret;
8469 : 1214405 : if ((flags & (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
8470 : : == (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
8471 : : return ret;
8472 : 1214345 : if ((flags & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
8473 : : | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
8474 : : == (GOVD_LASTPRIVATE | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
8475 : : return ret;
8476 : 1214345 : if (ctx->outer_context
8477 : 1214345 : && omp_notice_variable (ctx->outer_context, decl, in_code))
8478 : : return true;
8479 : : return ret;
8480 : : }
8481 : :
8482 : : /* Verify that DECL is private within CTX. If there's specific information
8483 : : to the contrary in the innermost scope, generate an error. */
8484 : :
8485 : : static bool
8486 : 50208 : omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd)
8487 : : {
8488 : 95338 : splay_tree_node n;
8489 : :
8490 : 95338 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8491 : 95338 : if (n != NULL)
8492 : : {
8493 : 17224 : if (n->value & GOVD_SHARED)
8494 : : {
8495 : 436 : if (ctx == gimplify_omp_ctxp)
8496 : : {
8497 : 0 : if (simd)
8498 : 0 : error ("iteration variable %qE is predetermined linear",
8499 : 0 : DECL_NAME (decl));
8500 : : else
8501 : 0 : error ("iteration variable %qE should be private",
8502 : 0 : DECL_NAME (decl));
8503 : 0 : n->value = GOVD_PRIVATE;
8504 : 0 : return true;
8505 : : }
8506 : : else
8507 : : return false;
8508 : : }
8509 : 16788 : else if ((n->value & GOVD_EXPLICIT) != 0
8510 : 9246 : && (ctx == gimplify_omp_ctxp
8511 : 219 : || (ctx->region_type == ORT_COMBINED_PARALLEL
8512 : 121 : && gimplify_omp_ctxp->outer_context == ctx)))
8513 : : {
8514 : 9148 : if ((n->value & GOVD_FIRSTPRIVATE) != 0)
8515 : 5 : error ("iteration variable %qE should not be firstprivate",
8516 : 5 : DECL_NAME (decl));
8517 : 9143 : else if ((n->value & GOVD_REDUCTION) != 0)
8518 : 10 : error ("iteration variable %qE should not be reduction",
8519 : 10 : DECL_NAME (decl));
8520 : 9133 : else if (simd != 1 && (n->value & GOVD_LINEAR) != 0)
8521 : 74 : error ("iteration variable %qE should not be linear",
8522 : 74 : DECL_NAME (decl));
8523 : : }
8524 : 16788 : return (ctx == gimplify_omp_ctxp
8525 : 16788 : || (ctx->region_type == ORT_COMBINED_PARALLEL
8526 : 18100 : && gimplify_omp_ctxp->outer_context == ctx));
8527 : : }
8528 : :
8529 : 78114 : if (ctx->region_type != ORT_WORKSHARE
8530 : : && ctx->region_type != ORT_TASKGROUP
8531 : 49510 : && ctx->region_type != ORT_SIMD
8532 : 35522 : && ctx->region_type != ORT_ACC)
8533 : : return false;
8534 : 54034 : else if (ctx->outer_context)
8535 : : return omp_is_private (ctx->outer_context, decl, simd);
8536 : : return false;
8537 : : }
8538 : :
8539 : : /* Return true if DECL is private within a parallel region
8540 : : that binds to the current construct's context or in parallel
8541 : : region's REDUCTION clause. */
8542 : :
8543 : : static bool
8544 : 12124 : omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
8545 : : {
8546 : 12208 : splay_tree_node n;
8547 : :
8548 : 12208 : do
8549 : : {
8550 : 12208 : ctx = ctx->outer_context;
8551 : 12208 : if (ctx == NULL)
8552 : : {
8553 : 2990 : if (is_global_var (decl))
8554 : : return false;
8555 : :
8556 : : /* References might be private, but might be shared too,
8557 : : when checking for copyprivate, assume they might be
8558 : : private, otherwise assume they might be shared. */
8559 : 1415 : if (copyprivate)
8560 : : return true;
8561 : :
8562 : 1363 : if (omp_privatize_by_reference (decl))
8563 : : return false;
8564 : :
8565 : : /* Treat C++ privatized non-static data members outside
8566 : : of the privatization the same. */
8567 : 1313 : if (omp_member_access_dummy_var (decl))
8568 : : return false;
8569 : :
8570 : : return true;
8571 : : }
8572 : :
8573 : 9218 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
8574 : :
8575 : 9218 : if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
8576 : 1343 : && (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0))
8577 : : {
8578 : 285 : if ((ctx->region_type & ORT_TARGET_DATA) != 0
8579 : 280 : || n == NULL
8580 : 270 : || (n->value & GOVD_MAP) == 0)
8581 : 15 : continue;
8582 : : return false;
8583 : : }
8584 : :
8585 : 7875 : if (n != NULL)
8586 : : {
8587 : 5592 : if ((n->value & GOVD_LOCAL) != 0
8588 : 5592 : && omp_member_access_dummy_var (decl))
8589 : : return false;
8590 : 5540 : return (n->value & GOVD_SHARED) == 0;
8591 : : }
8592 : :
8593 : 3341 : if (ctx->region_type == ORT_WORKSHARE
8594 : : || ctx->region_type == ORT_TASKGROUP
8595 : 3277 : || ctx->region_type == ORT_SIMD
8596 : 3272 : || ctx->region_type == ORT_ACC)
8597 : 69 : continue;
8598 : :
8599 : : break;
8600 : : }
8601 : : while (1);
8602 : : return false;
8603 : : }
8604 : :
8605 : : /* Callback for walk_tree to find a DECL_EXPR for the given DECL. */
8606 : :
8607 : : static tree
8608 : 3148 : find_decl_expr (tree *tp, int *walk_subtrees, void *data)
8609 : : {
8610 : 3148 : tree t = *tp;
8611 : :
8612 : : /* If this node has been visited, unmark it and keep looking. */
8613 : 3148 : if (TREE_CODE (t) == DECL_EXPR && DECL_EXPR_DECL (t) == (tree) data)
8614 : : return t;
8615 : :
8616 : 2724 : if (IS_TYPE_OR_DECL_P (t))
8617 : 452 : *walk_subtrees = 0;
8618 : : return NULL_TREE;
8619 : : }
8620 : :
8621 : :
8622 : : /* Gimplify the affinity clause but effectively ignore it.
8623 : : Generate:
8624 : : var = begin;
8625 : : if ((step > 1) ? var <= end : var > end)
8626 : : locatator_var_expr; */
8627 : :
8628 : : static void
8629 : 582 : gimplify_omp_affinity (tree *list_p, gimple_seq *pre_p)
8630 : : {
8631 : 582 : tree last_iter = NULL_TREE;
8632 : 582 : tree last_bind = NULL_TREE;
8633 : 582 : tree label = NULL_TREE;
8634 : 582 : tree *last_body = NULL;
8635 : 1494 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
8636 : 912 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
8637 : : {
8638 : 912 : tree t = OMP_CLAUSE_DECL (c);
8639 : 912 : if (TREE_CODE (t) == TREE_LIST
8640 : 479 : && TREE_PURPOSE (t)
8641 : 1391 : && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
8642 : : {
8643 : 479 : if (TREE_VALUE (t) == null_pointer_node)
8644 : 248 : continue;
8645 : 231 : if (TREE_PURPOSE (t) != last_iter)
8646 : : {
8647 : 157 : if (last_bind)
8648 : : {
8649 : 11 : append_to_statement_list (label, last_body);
8650 : 11 : gimplify_and_add (last_bind, pre_p);
8651 : 11 : last_bind = NULL_TREE;
8652 : : }
8653 : 338 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
8654 : : {
8655 : 181 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
8656 : : is_gimple_val, fb_rvalue) == GS_ERROR
8657 : 181 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
8658 : : is_gimple_val, fb_rvalue) == GS_ERROR
8659 : 181 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
8660 : : is_gimple_val, fb_rvalue) == GS_ERROR
8661 : 362 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
8662 : : is_gimple_val, fb_rvalue)
8663 : : == GS_ERROR))
8664 : 0 : return;
8665 : : }
8666 : 157 : last_iter = TREE_PURPOSE (t);
8667 : 157 : tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 5);
8668 : 157 : last_bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
8669 : : NULL, block);
8670 : 157 : last_body = &BIND_EXPR_BODY (last_bind);
8671 : 157 : tree cond = NULL_TREE;
8672 : 157 : location_t loc = OMP_CLAUSE_LOCATION (c);
8673 : 338 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
8674 : : {
8675 : 181 : tree var = TREE_VEC_ELT (it, 0);
8676 : 181 : tree begin = TREE_VEC_ELT (it, 1);
8677 : 181 : tree end = TREE_VEC_ELT (it, 2);
8678 : 181 : tree step = TREE_VEC_ELT (it, 3);
8679 : 181 : loc = DECL_SOURCE_LOCATION (var);
8680 : 181 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
8681 : : var, begin);
8682 : 181 : append_to_statement_list_force (tem, last_body);
8683 : :
8684 : 181 : tree cond1 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
8685 : 181 : step, build_zero_cst (TREE_TYPE (step)));
8686 : 181 : tree cond2 = fold_build2_loc (loc, LE_EXPR, boolean_type_node,
8687 : : var, end);
8688 : 181 : tree cond3 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
8689 : : var, end);
8690 : 181 : cond1 = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
8691 : : cond1, cond2, cond3);
8692 : 181 : if (cond)
8693 : 24 : cond = fold_build2_loc (loc, TRUTH_AND_EXPR,
8694 : : boolean_type_node, cond, cond1);
8695 : : else
8696 : : cond = cond1;
8697 : : }
8698 : 157 : tree cont_label = create_artificial_label (loc);
8699 : 157 : label = build1 (LABEL_EXPR, void_type_node, cont_label);
8700 : 157 : tree tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
8701 : : void_node,
8702 : : build_and_jump (&cont_label));
8703 : 157 : append_to_statement_list_force (tem, last_body);
8704 : : }
8705 : 231 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
8706 : : {
8707 : 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t), 0),
8708 : : last_body);
8709 : 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
8710 : : }
8711 : 231 : if (error_operand_p (TREE_VALUE (t)))
8712 : : return;
8713 : 231 : append_to_statement_list_force (TREE_VALUE (t), last_body);
8714 : 231 : TREE_VALUE (t) = null_pointer_node;
8715 : : }
8716 : : else
8717 : : {
8718 : 433 : if (last_bind)
8719 : : {
8720 : 11 : append_to_statement_list (label, last_body);
8721 : 11 : gimplify_and_add (last_bind, pre_p);
8722 : 11 : last_bind = NULL_TREE;
8723 : : }
8724 : 433 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
8725 : : {
8726 : 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
8727 : : NULL, is_gimple_val, fb_rvalue);
8728 : 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
8729 : : }
8730 : 433 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
8731 : : return;
8732 : 433 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
8733 : : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
8734 : : return;
8735 : 433 : gimplify_and_add (OMP_CLAUSE_DECL (c), pre_p);
8736 : : }
8737 : : }
8738 : 582 : if (last_bind)
8739 : : {
8740 : 135 : append_to_statement_list (label, last_body);
8741 : 135 : gimplify_and_add (last_bind, pre_p);
8742 : : }
8743 : : return;
8744 : : }
8745 : :
8746 : : /* If *LIST_P contains any OpenMP depend clauses with iterators,
8747 : : lower all the depend clauses by populating corresponding depend
8748 : : array. Returns 0 if there are no such depend clauses, or
8749 : : 2 if all depend clauses should be removed, 1 otherwise. */
8750 : :
8751 : : static int
8752 : 1915 : gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
8753 : : {
8754 : 1915 : tree c;
8755 : 1915 : gimple *g;
8756 : 1915 : size_t n[5] = { 0, 0, 0, 0, 0 };
8757 : 1915 : bool unused[5];
8758 : 1915 : tree counts[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
8759 : 1915 : tree last_iter = NULL_TREE, last_count = NULL_TREE;
8760 : 1915 : size_t i, j;
8761 : 1915 : location_t first_loc = UNKNOWN_LOCATION;
8762 : :
8763 : 6245 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
8764 : 4330 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
8765 : : {
8766 : 2243 : switch (OMP_CLAUSE_DEPEND_KIND (c))
8767 : : {
8768 : : case OMP_CLAUSE_DEPEND_IN:
8769 : : i = 2;
8770 : : break;
8771 : : case OMP_CLAUSE_DEPEND_OUT:
8772 : : case OMP_CLAUSE_DEPEND_INOUT:
8773 : : i = 0;
8774 : : break;
8775 : : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
8776 : : i = 1;
8777 : : break;
8778 : : case OMP_CLAUSE_DEPEND_DEPOBJ:
8779 : : i = 3;
8780 : : break;
8781 : : case OMP_CLAUSE_DEPEND_INOUTSET:
8782 : : i = 4;
8783 : : break;
8784 : 0 : default:
8785 : 0 : gcc_unreachable ();
8786 : : }
8787 : 2243 : tree t = OMP_CLAUSE_DECL (c);
8788 : 2243 : if (first_loc == UNKNOWN_LOCATION)
8789 : 1915 : first_loc = OMP_CLAUSE_LOCATION (c);
8790 : 2243 : if (TREE_CODE (t) == TREE_LIST
8791 : 351 : && TREE_PURPOSE (t)
8792 : 2594 : && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
8793 : : {
8794 : 351 : if (TREE_PURPOSE (t) != last_iter)
8795 : : {
8796 : 292 : tree tcnt = size_one_node;
8797 : 624 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
8798 : : {
8799 : 332 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
8800 : : is_gimple_val, fb_rvalue) == GS_ERROR
8801 : 332 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
8802 : : is_gimple_val, fb_rvalue) == GS_ERROR
8803 : 332 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
8804 : : is_gimple_val, fb_rvalue) == GS_ERROR
8805 : 664 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
8806 : : is_gimple_val, fb_rvalue)
8807 : : == GS_ERROR))
8808 : 0 : return 2;
8809 : 332 : tree var = TREE_VEC_ELT (it, 0);
8810 : 332 : tree begin = TREE_VEC_ELT (it, 1);
8811 : 332 : tree end = TREE_VEC_ELT (it, 2);
8812 : 332 : tree step = TREE_VEC_ELT (it, 3);
8813 : 332 : tree orig_step = TREE_VEC_ELT (it, 4);
8814 : 332 : tree type = TREE_TYPE (var);
8815 : 332 : tree stype = TREE_TYPE (step);
8816 : 332 : location_t loc = DECL_SOURCE_LOCATION (var);
8817 : 332 : tree endmbegin;
8818 : : /* Compute count for this iterator as
8819 : : orig_step > 0
8820 : : ? (begin < end ? (end - begin + (step - 1)) / step : 0)
8821 : : : (begin > end ? (end - begin + (step + 1)) / step : 0)
8822 : : and compute product of those for the entire depend
8823 : : clause. */
8824 : 332 : if (POINTER_TYPE_P (type))
8825 : 53 : endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR,
8826 : : stype, end, begin);
8827 : : else
8828 : 279 : endmbegin = fold_build2_loc (loc, MINUS_EXPR, type,
8829 : : end, begin);
8830 : 332 : tree stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype,
8831 : : step,
8832 : 332 : build_int_cst (stype, 1));
8833 : 332 : tree stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
8834 : 332 : build_int_cst (stype, 1));
8835 : 332 : tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
8836 : : unshare_expr (endmbegin),
8837 : : stepm1);
8838 : 332 : pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype,
8839 : : pos, step);
8840 : 332 : tree neg = fold_build2_loc (loc, PLUS_EXPR, stype,
8841 : : endmbegin, stepp1);
8842 : 332 : if (TYPE_UNSIGNED (stype))
8843 : : {
8844 : 35 : neg = fold_build1_loc (loc, NEGATE_EXPR, stype, neg);
8845 : 35 : step = fold_build1_loc (loc, NEGATE_EXPR, stype, step);
8846 : : }
8847 : 332 : neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype,
8848 : : neg, step);
8849 : 332 : step = NULL_TREE;
8850 : 332 : tree cond = fold_build2_loc (loc, LT_EXPR,
8851 : : boolean_type_node,
8852 : : begin, end);
8853 : 332 : pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
8854 : 332 : build_int_cst (stype, 0));
8855 : 332 : cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node,
8856 : : end, begin);
8857 : 332 : neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
8858 : 332 : build_int_cst (stype, 0));
8859 : 332 : tree osteptype = TREE_TYPE (orig_step);
8860 : 332 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
8861 : : orig_step,
8862 : 332 : build_int_cst (osteptype, 0));
8863 : 332 : tree cnt = fold_build3_loc (loc, COND_EXPR, stype,
8864 : 332 : cond, pos, neg);
8865 : 332 : cnt = fold_convert_loc (loc, sizetype, cnt);
8866 : 332 : if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
8867 : : fb_rvalue) == GS_ERROR)
8868 : : return 2;
8869 : 332 : tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
8870 : : }
8871 : 292 : if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val,
8872 : : fb_rvalue) == GS_ERROR)
8873 : : return 2;
8874 : 292 : last_iter = TREE_PURPOSE (t);
8875 : 292 : last_count = tcnt;
8876 : : }
8877 : 351 : if (counts[i] == NULL_TREE)
8878 : 283 : counts[i] = last_count;
8879 : : else
8880 : 68 : counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
8881 : : PLUS_EXPR, counts[i], last_count);
8882 : : }
8883 : : else
8884 : 1892 : n[i]++;
8885 : : }
8886 : 10580 : for (i = 0; i < 5; i++)
8887 : 8906 : if (counts[i])
8888 : : break;
8889 : 1915 : if (i == 5)
8890 : : return 0;
8891 : :
8892 : 241 : tree total = size_zero_node;
8893 : 1446 : for (i = 0; i < 5; i++)
8894 : : {
8895 : 1205 : unused[i] = counts[i] == NULL_TREE && n[i] == 0;
8896 : 1205 : if (counts[i] == NULL_TREE)
8897 : 922 : counts[i] = size_zero_node;
8898 : 1205 : if (n[i])
8899 : 54 : counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
8900 : 1205 : if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
8901 : : fb_rvalue) == GS_ERROR)
8902 : : return 2;
8903 : 1205 : total = size_binop (PLUS_EXPR, total, counts[i]);
8904 : : }
8905 : :
8906 : 241 : if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
8907 : : == GS_ERROR)
8908 : : return 2;
8909 : 241 : bool is_old = unused[1] && unused[3] && unused[4];
8910 : 241 : tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
8911 : : size_int (is_old ? 1 : 4));
8912 : 241 : if (!unused[4])
8913 : 3 : totalpx = size_binop (PLUS_EXPR, totalpx,
8914 : : size_binop (MULT_EXPR, counts[4], size_int (2)));
8915 : 241 : tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
8916 : 241 : tree array = create_tmp_var_raw (type);
8917 : 241 : TREE_ADDRESSABLE (array) = 1;
8918 : 241 : if (!poly_int_tree_p (totalpx))
8919 : : {
8920 : 92 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
8921 : 92 : gimplify_type_sizes (TREE_TYPE (array), pre_p);
8922 : 92 : if (gimplify_omp_ctxp)
8923 : : {
8924 : : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
8925 : : while (ctx
8926 : 20 : && (ctx->region_type == ORT_WORKSHARE
8927 : : || ctx->region_type == ORT_TASKGROUP
8928 : 20 : || ctx->region_type == ORT_SIMD
8929 : 20 : || ctx->region_type == ORT_ACC))
8930 : 0 : ctx = ctx->outer_context;
8931 : 20 : if (ctx)
8932 : 20 : omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
8933 : : }
8934 : 92 : gimplify_vla_decl (array, pre_p);
8935 : : }
8936 : : else
8937 : 149 : gimple_add_tmp_var (array);
8938 : 241 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
8939 : : NULL_TREE);
8940 : 241 : tree tem;
8941 : 241 : if (!is_old)
8942 : : {
8943 : 34 : tem = build2 (MODIFY_EXPR, void_type_node, r,
8944 : 34 : build_int_cst (ptr_type_node, 0));
8945 : 34 : gimplify_and_add (tem, pre_p);
8946 : 34 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
8947 : : NULL_TREE);
8948 : : }
8949 : 241 : tem = build2 (MODIFY_EXPR, void_type_node, r,
8950 : : fold_convert (ptr_type_node, total));
8951 : 241 : gimplify_and_add (tem, pre_p);
8952 : 927 : for (i = 1; i < (is_old ? 2 : 4); i++)
8953 : : {
8954 : 309 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
8955 : : NULL_TREE, NULL_TREE);
8956 : 309 : tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
8957 : 309 : gimplify_and_add (tem, pre_p);
8958 : : }
8959 : :
8960 : : tree cnts[6];
8961 : 832 : for (j = 5; j; j--)
8962 : 832 : if (!unused[j - 1])
8963 : : break;
8964 : 1446 : for (i = 0; i < 5; i++)
8965 : : {
8966 : 1205 : if (i && (i >= j || unused[i - 1]))
8967 : : {
8968 : 908 : cnts[i] = cnts[i - 1];
8969 : 908 : continue;
8970 : : }
8971 : 297 : cnts[i] = create_tmp_var (sizetype);
8972 : 297 : if (i == 0)
8973 : 275 : g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
8974 : : else
8975 : : {
8976 : 56 : tree t;
8977 : 56 : if (is_old)
8978 : 44 : t = size_binop (PLUS_EXPR, counts[0], size_int (2));
8979 : : else
8980 : 12 : t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
8981 : 56 : if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
8982 : : == GS_ERROR)
8983 : 0 : return 2;
8984 : 56 : g = gimple_build_assign (cnts[i], t);
8985 : : }
8986 : 297 : gimple_seq_add_stmt (pre_p, g);
8987 : : }
8988 : 241 : if (unused[4])
8989 : 238 : cnts[5] = NULL_TREE;
8990 : : else
8991 : : {
8992 : 3 : tree t = size_binop (PLUS_EXPR, total, size_int (5));
8993 : 3 : cnts[5] = create_tmp_var (sizetype);
8994 : 3 : g = gimple_build_assign (cnts[i], t);
8995 : 3 : gimple_seq_add_stmt (pre_p, g);
8996 : : }
8997 : :
8998 : 241 : last_iter = NULL_TREE;
8999 : 241 : tree last_bind = NULL_TREE;
9000 : 241 : tree *last_body = NULL;
9001 : 664 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9002 : 423 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
9003 : : {
9004 : 407 : switch (OMP_CLAUSE_DEPEND_KIND (c))
9005 : : {
9006 : : case OMP_CLAUSE_DEPEND_IN:
9007 : : i = 2;
9008 : : break;
9009 : : case OMP_CLAUSE_DEPEND_OUT:
9010 : : case OMP_CLAUSE_DEPEND_INOUT:
9011 : : i = 0;
9012 : : break;
9013 : : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
9014 : : i = 1;
9015 : : break;
9016 : : case OMP_CLAUSE_DEPEND_DEPOBJ:
9017 : : i = 3;
9018 : : break;
9019 : : case OMP_CLAUSE_DEPEND_INOUTSET:
9020 : : i = 4;
9021 : : break;
9022 : 0 : default:
9023 : 0 : gcc_unreachable ();
9024 : : }
9025 : 407 : tree t = OMP_CLAUSE_DECL (c);
9026 : 407 : if (TREE_CODE (t) == TREE_LIST
9027 : 351 : && TREE_PURPOSE (t)
9028 : 758 : && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
9029 : : {
9030 : 351 : if (TREE_PURPOSE (t) != last_iter)
9031 : : {
9032 : 292 : if (last_bind)
9033 : 33 : gimplify_and_add (last_bind, pre_p);
9034 : 292 : tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 5);
9035 : 292 : last_bind = build3 (BIND_EXPR, void_type_node,
9036 : 292 : BLOCK_VARS (block), NULL, block);
9037 : 292 : TREE_SIDE_EFFECTS (last_bind) = 1;
9038 : 292 : SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
9039 : 292 : tree *p = &BIND_EXPR_BODY (last_bind);
9040 : 624 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9041 : : {
9042 : 332 : tree var = TREE_VEC_ELT (it, 0);
9043 : 332 : tree begin = TREE_VEC_ELT (it, 1);
9044 : 332 : tree end = TREE_VEC_ELT (it, 2);
9045 : 332 : tree step = TREE_VEC_ELT (it, 3);
9046 : 332 : tree orig_step = TREE_VEC_ELT (it, 4);
9047 : 332 : tree type = TREE_TYPE (var);
9048 : 332 : location_t loc = DECL_SOURCE_LOCATION (var);
9049 : : /* Emit:
9050 : : var = begin;
9051 : : goto cond_label;
9052 : : beg_label:
9053 : : ...
9054 : : var = var + step;
9055 : : cond_label:
9056 : : if (orig_step > 0) {
9057 : : if (var < end) goto beg_label;
9058 : : } else {
9059 : : if (var > end) goto beg_label;
9060 : : }
9061 : : for each iterator, with inner iterators added to
9062 : : the ... above. */
9063 : 332 : tree beg_label = create_artificial_label (loc);
9064 : 332 : tree cond_label = NULL_TREE;
9065 : 332 : tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
9066 : : var, begin);
9067 : 332 : append_to_statement_list_force (tem, p);
9068 : 332 : tem = build_and_jump (&cond_label);
9069 : 332 : append_to_statement_list_force (tem, p);
9070 : 332 : tem = build1 (LABEL_EXPR, void_type_node, beg_label);
9071 : 332 : append_to_statement_list (tem, p);
9072 : 332 : tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
9073 : : NULL_TREE, NULL_TREE);
9074 : 332 : TREE_SIDE_EFFECTS (bind) = 1;
9075 : 332 : SET_EXPR_LOCATION (bind, loc);
9076 : 332 : append_to_statement_list_force (bind, p);
9077 : 332 : if (POINTER_TYPE_P (type))
9078 : 53 : tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
9079 : : var, fold_convert_loc (loc, sizetype,
9080 : : step));
9081 : : else
9082 : 279 : tem = build2_loc (loc, PLUS_EXPR, type, var, step);
9083 : 332 : tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
9084 : : var, tem);
9085 : 332 : append_to_statement_list_force (tem, p);
9086 : 332 : tem = build1 (LABEL_EXPR, void_type_node, cond_label);
9087 : 332 : append_to_statement_list (tem, p);
9088 : 332 : tree cond = fold_build2_loc (loc, LT_EXPR,
9089 : : boolean_type_node,
9090 : : var, end);
9091 : 332 : tree pos
9092 : 332 : = fold_build3_loc (loc, COND_EXPR, void_type_node,
9093 : : cond, build_and_jump (&beg_label),
9094 : : void_node);
9095 : 332 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9096 : : var, end);
9097 : 332 : tree neg
9098 : 332 : = fold_build3_loc (loc, COND_EXPR, void_type_node,
9099 : : cond, build_and_jump (&beg_label),
9100 : : void_node);
9101 : 332 : tree osteptype = TREE_TYPE (orig_step);
9102 : 332 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9103 : : orig_step,
9104 : 332 : build_int_cst (osteptype, 0));
9105 : 332 : tem = fold_build3_loc (loc, COND_EXPR, void_type_node,
9106 : : cond, pos, neg);
9107 : 332 : append_to_statement_list_force (tem, p);
9108 : 332 : p = &BIND_EXPR_BODY (bind);
9109 : : }
9110 : : last_body = p;
9111 : : }
9112 : 351 : last_iter = TREE_PURPOSE (t);
9113 : 351 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
9114 : : {
9115 : 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
9116 : : 0), last_body);
9117 : 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
9118 : : }
9119 : 351 : if (error_operand_p (TREE_VALUE (t)))
9120 : : return 2;
9121 : 351 : if (TREE_VALUE (t) != null_pointer_node)
9122 : 345 : TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
9123 : 351 : if (i == 4)
9124 : : {
9125 : 3 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
9126 : : NULL_TREE, NULL_TREE);
9127 : 3 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
9128 : : NULL_TREE, NULL_TREE);
9129 : 3 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
9130 : 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
9131 : : void_type_node, r, r2);
9132 : 3 : append_to_statement_list_force (tem, last_body);
9133 : 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
9134 : : void_type_node, cnts[i],
9135 : 3 : size_binop (PLUS_EXPR, cnts[i],
9136 : : size_int (1)));
9137 : 3 : append_to_statement_list_force (tem, last_body);
9138 : 3 : i = 5;
9139 : : }
9140 : 351 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
9141 : : NULL_TREE, NULL_TREE);
9142 : 702 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
9143 : 351 : void_type_node, r, TREE_VALUE (t));
9144 : 351 : append_to_statement_list_force (tem, last_body);
9145 : 351 : if (i == 5)
9146 : : {
9147 : 3 : r = build4 (ARRAY_REF, ptr_type_node, array,
9148 : 3 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
9149 : : NULL_TREE, NULL_TREE);
9150 : 3 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
9151 : 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
9152 : : void_type_node, r, tem);
9153 : 3 : append_to_statement_list_force (tem, last_body);
9154 : : }
9155 : 351 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
9156 : : void_type_node, cnts[i],
9157 : 351 : size_binop (PLUS_EXPR, cnts[i],
9158 : : size_int (1 + (i == 5))));
9159 : 351 : append_to_statement_list_force (tem, last_body);
9160 : 351 : TREE_VALUE (t) = null_pointer_node;
9161 : : }
9162 : : else
9163 : : {
9164 : 56 : if (last_bind)
9165 : : {
9166 : 22 : gimplify_and_add (last_bind, pre_p);
9167 : 22 : last_bind = NULL_TREE;
9168 : : }
9169 : 56 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
9170 : : {
9171 : 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
9172 : : NULL, is_gimple_val, fb_rvalue);
9173 : 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
9174 : : }
9175 : 56 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
9176 : : return 2;
9177 : 56 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
9178 : 56 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
9179 : 56 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
9180 : : is_gimple_val, fb_rvalue) == GS_ERROR)
9181 : : return 2;
9182 : 56 : if (i == 4)
9183 : : {
9184 : 0 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
9185 : : NULL_TREE, NULL_TREE);
9186 : 0 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
9187 : : NULL_TREE, NULL_TREE);
9188 : 0 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
9189 : 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, r2);
9190 : 0 : gimplify_and_add (tem, pre_p);
9191 : 0 : g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR,
9192 : : cnts[i],
9193 : : size_int (1)));
9194 : 0 : gimple_seq_add_stmt (pre_p, g);
9195 : 0 : i = 5;
9196 : : }
9197 : 56 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
9198 : : NULL_TREE, NULL_TREE);
9199 : 56 : tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
9200 : 56 : gimplify_and_add (tem, pre_p);
9201 : 56 : if (i == 5)
9202 : : {
9203 : 0 : r = build4 (ARRAY_REF, ptr_type_node, array,
9204 : 0 : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
9205 : : NULL_TREE, NULL_TREE);
9206 : 0 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
9207 : 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, tem);
9208 : 0 : append_to_statement_list_force (tem, last_body);
9209 : 0 : gimplify_and_add (tem, pre_p);
9210 : : }
9211 : 56 : g = gimple_build_assign (cnts[i],
9212 : 56 : size_binop (PLUS_EXPR, cnts[i],
9213 : : size_int (1 + (i == 5))));
9214 : 56 : gimple_seq_add_stmt (pre_p, g);
9215 : : }
9216 : : }
9217 : 241 : if (last_bind)
9218 : 237 : gimplify_and_add (last_bind, pre_p);
9219 : 241 : tree cond = boolean_false_node;
9220 : 241 : if (is_old)
9221 : : {
9222 : 207 : if (!unused[0])
9223 : 99 : cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
9224 : : size_binop_loc (first_loc, PLUS_EXPR, counts[0],
9225 : 99 : size_int (2)));
9226 : 207 : if (!unused[2])
9227 : 152 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
9228 : : build2_loc (first_loc, NE_EXPR, boolean_type_node,
9229 : : cnts[2],
9230 : : size_binop_loc (first_loc, PLUS_EXPR,
9231 : : totalpx,
9232 : 152 : size_int (1))));
9233 : : }
9234 : : else
9235 : : {
9236 : 34 : tree prev = size_int (5);
9237 : 204 : for (i = 0; i < 5; i++)
9238 : : {
9239 : 170 : if (unused[i])
9240 : 124 : continue;
9241 : 46 : prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
9242 : 46 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
9243 : : build2_loc (first_loc, NE_EXPR, boolean_type_node,
9244 : : cnts[i], unshare_expr (prev)));
9245 : : }
9246 : : }
9247 : 241 : tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
9248 : : build_call_expr_loc (first_loc,
9249 : : builtin_decl_explicit (BUILT_IN_TRAP),
9250 : : 0), void_node);
9251 : 241 : gimplify_and_add (tem, pre_p);
9252 : 241 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
9253 : 241 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
9254 : 241 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
9255 : 241 : OMP_CLAUSE_CHAIN (c) = *list_p;
9256 : 241 : *list_p = c;
9257 : 241 : return 1;
9258 : : }
9259 : :
9260 : : /* True if mapping node C maps, or unmaps, a (Fortran) array descriptor. */
9261 : :
9262 : : static bool
9263 : 110635 : omp_map_clause_descriptor_p (tree c)
9264 : : {
9265 : 110635 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
9266 : : return false;
9267 : :
9268 : 110633 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)
9269 : : return true;
9270 : :
9271 : 72682 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
9272 : 67271 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE)
9273 : 73154 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (c))
9274 : 4002 : return true;
9275 : :
9276 : : return false;
9277 : : }
9278 : :
9279 : : /* For a set of mappings describing an array section pointed to by a struct
9280 : : (or derived type, etc.) component, create an "alloc" or "release" node to
9281 : : insert into a list following a GOMP_MAP_STRUCT node. For some types of
9282 : : mapping (e.g. Fortran arrays with descriptors), an additional mapping may
9283 : : be created that is inserted into the list of mapping nodes attached to the
9284 : : directive being processed -- not part of the sorted list of nodes after
9285 : : GOMP_MAP_STRUCT.
9286 : :
9287 : : CODE is the code of the directive being processed. GRP_START and GRP_END
9288 : : are the first and last of two or three nodes representing this array section
9289 : : mapping (e.g. a data movement node like GOMP_MAP_{TO,FROM}, optionally a
9290 : : GOMP_MAP_TO_PSET, and finally a GOMP_MAP_ALWAYS_POINTER). EXTRA_NODE is
9291 : : filled with the additional node described above, if needed.
9292 : :
9293 : : This function does not add the new nodes to any lists itself. It is the
9294 : : responsibility of the caller to do that. */
9295 : :
9296 : : static tree
9297 : 1616 : build_omp_struct_comp_nodes (enum tree_code code, tree grp_start, tree grp_end,
9298 : : tree *extra_node)
9299 : : {
9300 : 3232 : enum gomp_map_kind mkind
9301 : 1616 : = (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
9302 : 1616 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
9303 : :
9304 : 1616 : gcc_assert (grp_start != grp_end);
9305 : :
9306 : 1616 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
9307 : 1616 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
9308 : 1616 : OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (grp_end));
9309 : 1616 : OMP_CLAUSE_CHAIN (c2) = NULL_TREE;
9310 : 1616 : tree grp_mid = NULL_TREE;
9311 : 1616 : if (OMP_CLAUSE_CHAIN (grp_start) != grp_end)
9312 : 185 : grp_mid = OMP_CLAUSE_CHAIN (grp_start);
9313 : :
9314 : 185 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
9315 : 0 : OMP_CLAUSE_SIZE (c2) = OMP_CLAUSE_SIZE (grp_mid);
9316 : : else
9317 : 1616 : OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node);
9318 : :
9319 : 1616 : if (grp_mid
9320 : 185 : && OMP_CLAUSE_CODE (grp_mid) == OMP_CLAUSE_MAP
9321 : 1801 : && OMP_CLAUSE_MAP_KIND (grp_mid) == GOMP_MAP_ALWAYS_POINTER)
9322 : : {
9323 : 0 : tree c3
9324 : 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
9325 : 0 : OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
9326 : 0 : OMP_CLAUSE_DECL (c3) = unshare_expr (OMP_CLAUSE_DECL (grp_mid));
9327 : 0 : OMP_CLAUSE_SIZE (c3) = TYPE_SIZE_UNIT (ptr_type_node);
9328 : 0 : OMP_CLAUSE_CHAIN (c3) = NULL_TREE;
9329 : :
9330 : 0 : *extra_node = c3;
9331 : : }
9332 : : else
9333 : 1616 : *extra_node = NULL_TREE;
9334 : :
9335 : 1616 : return c2;
9336 : : }
9337 : :
9338 : : /* Strip ARRAY_REFS or an indirect ref off BASE, find the containing object,
9339 : : and set *BITPOSP and *POFFSETP to the bit offset of the access.
9340 : : If BASE_REF is non-NULL and the containing object is a reference, set
9341 : : *BASE_REF to that reference before dereferencing the object.
9342 : : If BASE_REF is NULL, check that the containing object is a COMPONENT_REF or
9343 : : has array type, else return NULL. */
9344 : :
9345 : : static tree
9346 : 6207 : extract_base_bit_offset (tree base, poly_int64 *bitposp,
9347 : : poly_offset_int *poffsetp,
9348 : : bool *variable_offset)
9349 : : {
9350 : 6207 : tree offset;
9351 : 6207 : poly_int64 bitsize, bitpos;
9352 : 6207 : machine_mode mode;
9353 : 6207 : int unsignedp, reversep, volatilep = 0;
9354 : 6207 : poly_offset_int poffset;
9355 : :
9356 : 6207 : STRIP_NOPS (base);
9357 : :
9358 : 6207 : base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
9359 : : &unsignedp, &reversep, &volatilep);
9360 : :
9361 : 6207 : STRIP_NOPS (base);
9362 : :
9363 : 6207 : if (offset && poly_int_tree_p (offset))
9364 : : {
9365 : 0 : poffset = wi::to_poly_offset (offset);
9366 : 0 : *variable_offset = false;
9367 : : }
9368 : : else
9369 : : {
9370 : 6207 : poffset = 0;
9371 : 6207 : *variable_offset = (offset != NULL_TREE);
9372 : : }
9373 : :
9374 : 6207 : if (maybe_ne (bitpos, 0))
9375 : 4758 : poffset += bits_to_bytes_round_down (bitpos);
9376 : :
9377 : 6207 : *bitposp = bitpos;
9378 : 6207 : *poffsetp = poffset;
9379 : :
9380 : 6207 : return base;
9381 : : }
9382 : :
9383 : : /* Used for topological sorting of mapping groups. UNVISITED means we haven't
9384 : : started processing the group yet. The TEMPORARY mark is used when we first
9385 : : encounter a group on a depth-first traversal, and the PERMANENT mark is used
9386 : : when we have processed all the group's children (i.e. all the base pointers
9387 : : referred to by the group's mapping nodes, recursively). */
9388 : :
9389 : : enum omp_tsort_mark {
9390 : : UNVISITED,
9391 : : TEMPORARY,
9392 : : PERMANENT
9393 : : };
9394 : :
9395 : : /* Hash for trees based on operand_equal_p. Like tree_operand_hash
9396 : : but ignores side effects in the equality comparisons. */
9397 : :
9398 : : struct tree_operand_hash_no_se : tree_operand_hash
9399 : : {
9400 : : static inline bool equal (const value_type &,
9401 : : const compare_type &);
9402 : : };
9403 : :
9404 : : inline bool
9405 : 334461 : tree_operand_hash_no_se::equal (const value_type &t1,
9406 : : const compare_type &t2)
9407 : : {
9408 : 334461 : return operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS);
9409 : : }
9410 : :
9411 : : /* A group of OMP_CLAUSE_MAP nodes that correspond to a single "map"
9412 : : clause. */
9413 : :
9414 : : struct omp_mapping_group {
9415 : : tree *grp_start;
9416 : : tree grp_end;
9417 : : omp_tsort_mark mark;
9418 : : /* If we've removed the group but need to reindex, mark the group as
9419 : : deleted. */
9420 : : bool deleted;
9421 : : /* The group points to an already-created "GOMP_MAP_STRUCT
9422 : : GOMP_MAP_ATTACH_DETACH" pair. */
9423 : : bool reprocess_struct;
9424 : : /* The group should use "zero-length" allocations for pointers that are not
9425 : : mapped "to" on the same directive. */
9426 : : bool fragile;
9427 : : struct omp_mapping_group *sibling;
9428 : : struct omp_mapping_group *next;
9429 : : };
9430 : :
9431 : : DEBUG_FUNCTION void
9432 : 0 : debug_mapping_group (omp_mapping_group *grp)
9433 : : {
9434 : 0 : tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end);
9435 : 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = NULL;
9436 : 0 : debug_generic_expr (*grp->grp_start);
9437 : 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = tmp;
9438 : 0 : }
9439 : :
9440 : : /* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there
9441 : : isn't one. */
9442 : :
9443 : : static tree
9444 : 31278 : omp_get_base_pointer (tree expr)
9445 : : {
9446 : 31278 : while (TREE_CODE (expr) == ARRAY_REF
9447 : 36334 : || TREE_CODE (expr) == COMPONENT_REF)
9448 : 5056 : expr = TREE_OPERAND (expr, 0);
9449 : :
9450 : 31278 : if (INDIRECT_REF_P (expr)
9451 : 31278 : || (TREE_CODE (expr) == MEM_REF
9452 : 0 : && integer_zerop (TREE_OPERAND (expr, 1))))
9453 : : {
9454 : 9095 : expr = TREE_OPERAND (expr, 0);
9455 : 9132 : while (TREE_CODE (expr) == COMPOUND_EXPR)
9456 : 37 : expr = TREE_OPERAND (expr, 1);
9457 : 9095 : if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
9458 : 738 : expr = TREE_OPERAND (expr, 0);
9459 : 9095 : if (TREE_CODE (expr) == SAVE_EXPR)
9460 : 31 : expr = TREE_OPERAND (expr, 0);
9461 : 9095 : STRIP_NOPS (expr);
9462 : 9095 : return expr;
9463 : : }
9464 : :
9465 : : return NULL_TREE;
9466 : : }
9467 : :
9468 : : /* An attach or detach operation depends directly on the address being
9469 : : attached/detached. Return that address, or none if there are no
9470 : : attachments/detachments. */
9471 : :
9472 : : static tree
9473 : 14263 : omp_get_attachment (omp_mapping_group *grp)
9474 : : {
9475 : 14263 : tree node = *grp->grp_start;
9476 : :
9477 : 14263 : switch (OMP_CLAUSE_MAP_KIND (node))
9478 : : {
9479 : 11930 : case GOMP_MAP_TO:
9480 : 11930 : case GOMP_MAP_FROM:
9481 : 11930 : case GOMP_MAP_TOFROM:
9482 : 11930 : case GOMP_MAP_ALWAYS_FROM:
9483 : 11930 : case GOMP_MAP_ALWAYS_TO:
9484 : 11930 : case GOMP_MAP_ALWAYS_TOFROM:
9485 : 11930 : case GOMP_MAP_FORCE_FROM:
9486 : 11930 : case GOMP_MAP_FORCE_TO:
9487 : 11930 : case GOMP_MAP_FORCE_TOFROM:
9488 : 11930 : case GOMP_MAP_FORCE_PRESENT:
9489 : 11930 : case GOMP_MAP_PRESENT_ALLOC:
9490 : 11930 : case GOMP_MAP_PRESENT_FROM:
9491 : 11930 : case GOMP_MAP_PRESENT_TO:
9492 : 11930 : case GOMP_MAP_PRESENT_TOFROM:
9493 : 11930 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
9494 : 11930 : case GOMP_MAP_ALWAYS_PRESENT_TO:
9495 : 11930 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
9496 : 11930 : case GOMP_MAP_ALLOC:
9497 : 11930 : case GOMP_MAP_RELEASE:
9498 : 11930 : case GOMP_MAP_DELETE:
9499 : 11930 : case GOMP_MAP_FORCE_ALLOC:
9500 : 11930 : if (node == grp->grp_end)
9501 : : return NULL_TREE;
9502 : :
9503 : 5653 : node = OMP_CLAUSE_CHAIN (node);
9504 : 5653 : if (node && omp_map_clause_descriptor_p (node))
9505 : : {
9506 : 982 : gcc_assert (node != grp->grp_end);
9507 : 982 : node = OMP_CLAUSE_CHAIN (node);
9508 : : }
9509 : 5653 : if (node)
9510 : 5653 : switch (OMP_CLAUSE_MAP_KIND (node))
9511 : : {
9512 : : case GOMP_MAP_POINTER:
9513 : : case GOMP_MAP_ALWAYS_POINTER:
9514 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
9515 : : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
9516 : : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
9517 : : return NULL_TREE;
9518 : :
9519 : 1917 : case GOMP_MAP_ATTACH_DETACH:
9520 : 1917 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
9521 : 1917 : case GOMP_MAP_DETACH:
9522 : 1917 : return OMP_CLAUSE_DECL (node);
9523 : :
9524 : 0 : default:
9525 : 0 : internal_error ("unexpected mapping node");
9526 : : }
9527 : 0 : return error_mark_node;
9528 : :
9529 : 0 : case GOMP_MAP_TO_PSET:
9530 : 0 : gcc_assert (node != grp->grp_end);
9531 : 0 : node = OMP_CLAUSE_CHAIN (node);
9532 : 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
9533 : 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
9534 : 0 : return OMP_CLAUSE_DECL (node);
9535 : : else
9536 : 0 : internal_error ("unexpected mapping node");
9537 : : return error_mark_node;
9538 : :
9539 : 396 : case GOMP_MAP_ATTACH:
9540 : 396 : case GOMP_MAP_DETACH:
9541 : 396 : node = OMP_CLAUSE_CHAIN (node);
9542 : 396 : if (!node || *grp->grp_start == grp->grp_end)
9543 : 396 : return OMP_CLAUSE_DECL (*grp->grp_start);
9544 : 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
9545 : 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
9546 : 0 : return OMP_CLAUSE_DECL (*grp->grp_start);
9547 : : else
9548 : 0 : internal_error ("unexpected mapping node");
9549 : : return error_mark_node;
9550 : :
9551 : : case GOMP_MAP_STRUCT:
9552 : : case GOMP_MAP_STRUCT_UNORD:
9553 : : case GOMP_MAP_FORCE_DEVICEPTR:
9554 : : case GOMP_MAP_DEVICE_RESIDENT:
9555 : : case GOMP_MAP_LINK:
9556 : : case GOMP_MAP_IF_PRESENT:
9557 : : case GOMP_MAP_FIRSTPRIVATE:
9558 : : case GOMP_MAP_FIRSTPRIVATE_INT:
9559 : : case GOMP_MAP_USE_DEVICE_PTR:
9560 : : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
9561 : : return NULL_TREE;
9562 : :
9563 : 0 : default:
9564 : 0 : internal_error ("unexpected mapping node");
9565 : : }
9566 : :
9567 : : return error_mark_node;
9568 : : }
9569 : :
9570 : : /* Given a pointer START_P to the start of a group of related (e.g. pointer)
9571 : : mappings, return the chain pointer to the end of that group in the list. */
9572 : :
9573 : : static tree *
9574 : 102688 : omp_group_last (tree *start_p)
9575 : : {
9576 : 102688 : tree c = *start_p, nc, *grp_last_p = start_p;
9577 : :
9578 : 102688 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
9579 : :
9580 : 102688 : nc = OMP_CLAUSE_CHAIN (c);
9581 : :
9582 : 180035 : if (!nc || OMP_CLAUSE_CODE (nc) != OMP_CLAUSE_MAP)
9583 : : return grp_last_p;
9584 : :
9585 : 64820 : switch (OMP_CLAUSE_MAP_KIND (c))
9586 : : {
9587 : : default:
9588 : : while (nc
9589 : 105024 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
9590 : 220396 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
9591 : 97886 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
9592 : 87142 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH
9593 : 77002 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
9594 : 51718 : || (OMP_CLAUSE_MAP_KIND (nc)
9595 : : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
9596 : 51698 : || (OMP_CLAUSE_MAP_KIND (nc)
9597 : : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)
9598 : 51327 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH
9599 : 51286 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER
9600 : 49406 : || omp_map_clause_descriptor_p (nc)))
9601 : : {
9602 : 62069 : tree nc2 = OMP_CLAUSE_CHAIN (nc);
9603 : 62069 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH)
9604 : : {
9605 : : /* In the specific case we're doing "exit data" on an array
9606 : : slice of a reference-to-pointer struct component, we will see
9607 : : DETACH followed by ATTACH_DETACH here. We want to treat that
9608 : : as a single group. In other cases DETACH might represent a
9609 : : stand-alone "detach" clause, so we don't want to consider
9610 : : that part of the group. */
9611 : 41 : if (nc2
9612 : 12 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
9613 : 53 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH)
9614 : 0 : goto consume_two_nodes;
9615 : : else
9616 : : break;
9617 : : }
9618 : 62028 : if (nc2
9619 : 45122 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
9620 : 38559 : && (OMP_CLAUSE_MAP_KIND (nc)
9621 : : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
9622 : 62048 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH)
9623 : : {
9624 : 20 : consume_two_nodes:
9625 : 20 : grp_last_p = &OMP_CLAUSE_CHAIN (nc);
9626 : 20 : c = nc2;
9627 : 20 : nc = OMP_CLAUSE_CHAIN (nc2);
9628 : : }
9629 : : else
9630 : : {
9631 : 62008 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
9632 : 62008 : c = nc;
9633 : 62008 : nc = nc2;
9634 : : }
9635 : : }
9636 : : break;
9637 : :
9638 : 120 : case GOMP_MAP_ATTACH:
9639 : 120 : case GOMP_MAP_DETACH:
9640 : : /* This is a weird artifact of how directives are parsed: bare attach or
9641 : : detach clauses get a subsequent (meaningless) FIRSTPRIVATE_POINTER or
9642 : : FIRSTPRIVATE_REFERENCE node. FIXME. */
9643 : 120 : if (nc
9644 : 120 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
9645 : 120 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
9646 : 120 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER))
9647 : 0 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
9648 : : break;
9649 : :
9650 : 27 : case GOMP_MAP_TO_PSET:
9651 : 27 : if (OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
9652 : 27 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH
9653 : 6 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH))
9654 : 27 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
9655 : : break;
9656 : :
9657 : 4766 : case GOMP_MAP_STRUCT:
9658 : 4766 : case GOMP_MAP_STRUCT_UNORD:
9659 : 4766 : {
9660 : 4766 : unsigned HOST_WIDE_INT num_mappings
9661 : 4766 : = tree_to_uhwi (OMP_CLAUSE_SIZE (c));
9662 : 4766 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
9663 : 4426 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
9664 : 8714 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH)
9665 : 1118 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
9666 : 11567 : for (unsigned i = 0; i < num_mappings; i++)
9667 : 6801 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
9668 : : }
9669 : : break;
9670 : : }
9671 : :
9672 : : return grp_last_p;
9673 : : }
9674 : :
9675 : : /* Walk through LIST_P, and return a list of groups of mappings found (e.g.
9676 : : OMP_CLAUSE_MAP with GOMP_MAP_{TO/FROM/TOFROM} followed by one or two
9677 : : associated GOMP_MAP_POINTER mappings). Return a vector of omp_mapping_group
9678 : : if we have more than one such group, else return NULL. */
9679 : :
9680 : : static void
9681 : 84979 : omp_gather_mapping_groups_1 (tree *list_p, vec<omp_mapping_group> *groups,
9682 : : tree gather_sentinel)
9683 : : {
9684 : 84979 : for (tree *cp = list_p;
9685 : 252147 : *cp && *cp != gather_sentinel;
9686 : 167168 : cp = &OMP_CLAUSE_CHAIN (*cp))
9687 : : {
9688 : 167168 : if (OMP_CLAUSE_CODE (*cp) != OMP_CLAUSE_MAP)
9689 : 94111 : continue;
9690 : :
9691 : 73057 : tree *grp_last_p = omp_group_last (cp);
9692 : 73057 : omp_mapping_group grp;
9693 : :
9694 : 73057 : grp.grp_start = cp;
9695 : 73057 : grp.grp_end = *grp_last_p;
9696 : 73057 : grp.mark = UNVISITED;
9697 : 73057 : grp.sibling = NULL;
9698 : 73057 : grp.deleted = false;
9699 : 73057 : grp.reprocess_struct = false;
9700 : 73057 : grp.fragile = false;
9701 : 73057 : grp.next = NULL;
9702 : 73057 : groups->safe_push (grp);
9703 : :
9704 : 73057 : cp = grp_last_p;
9705 : : }
9706 : 84979 : }
9707 : :
9708 : : static vec<omp_mapping_group> *
9709 : 84675 : omp_gather_mapping_groups (tree *list_p)
9710 : : {
9711 : 84675 : vec<omp_mapping_group> *groups = new vec<omp_mapping_group> ();
9712 : :
9713 : 84675 : omp_gather_mapping_groups_1 (list_p, groups, NULL_TREE);
9714 : :
9715 : 84675 : if (groups->length () > 0)
9716 : : return groups;
9717 : : else
9718 : : {
9719 : 43161 : delete groups;
9720 : 43161 : return NULL;
9721 : : }
9722 : : }
9723 : :
9724 : : /* A pointer mapping group GRP may define a block of memory starting at some
9725 : : base address, and maybe also define a firstprivate pointer or firstprivate
9726 : : reference that points to that block. The return value is a node containing
9727 : : the former, and the *FIRSTPRIVATE pointer is set if we have the latter.
9728 : : If we define several base pointers, i.e. for a GOMP_MAP_STRUCT mapping,
9729 : : return the number of consecutive chained nodes in CHAINED. */
9730 : :
9731 : : static tree
9732 : 73393 : omp_group_base (omp_mapping_group *grp, unsigned int *chained,
9733 : : tree *firstprivate)
9734 : : {
9735 : 73393 : tree node = *grp->grp_start;
9736 : :
9737 : 73393 : *firstprivate = NULL_TREE;
9738 : 73393 : *chained = 1;
9739 : :
9740 : 73393 : switch (OMP_CLAUSE_MAP_KIND (node))
9741 : : {
9742 : 69858 : case GOMP_MAP_TO:
9743 : 69858 : case GOMP_MAP_FROM:
9744 : 69858 : case GOMP_MAP_TOFROM:
9745 : 69858 : case GOMP_MAP_ALWAYS_FROM:
9746 : 69858 : case GOMP_MAP_ALWAYS_TO:
9747 : 69858 : case GOMP_MAP_ALWAYS_TOFROM:
9748 : 69858 : case GOMP_MAP_FORCE_FROM:
9749 : 69858 : case GOMP_MAP_FORCE_TO:
9750 : 69858 : case GOMP_MAP_FORCE_TOFROM:
9751 : 69858 : case GOMP_MAP_FORCE_PRESENT:
9752 : 69858 : case GOMP_MAP_PRESENT_ALLOC:
9753 : 69858 : case GOMP_MAP_PRESENT_FROM:
9754 : 69858 : case GOMP_MAP_PRESENT_TO:
9755 : 69858 : case GOMP_MAP_PRESENT_TOFROM:
9756 : 69858 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
9757 : 69858 : case GOMP_MAP_ALWAYS_PRESENT_TO:
9758 : 69858 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
9759 : 69858 : case GOMP_MAP_ALLOC:
9760 : 69858 : case GOMP_MAP_RELEASE:
9761 : 69858 : case GOMP_MAP_DELETE:
9762 : 69858 : case GOMP_MAP_FORCE_ALLOC:
9763 : 69858 : case GOMP_MAP_IF_PRESENT:
9764 : 69858 : if (node == grp->grp_end)
9765 : : return node;
9766 : :
9767 : 32108 : node = OMP_CLAUSE_CHAIN (node);
9768 : 32108 : if (!node)
9769 : 0 : internal_error ("unexpected mapping node");
9770 : 32108 : if (omp_map_clause_descriptor_p (node))
9771 : : {
9772 : 9532 : if (node == grp->grp_end)
9773 : 0 : return *grp->grp_start;
9774 : 9532 : node = OMP_CLAUSE_CHAIN (node);
9775 : : }
9776 : 32108 : switch (OMP_CLAUSE_MAP_KIND (node))
9777 : : {
9778 : 22897 : case GOMP_MAP_POINTER:
9779 : 22897 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
9780 : 22897 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
9781 : 22897 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
9782 : 22897 : *firstprivate = OMP_CLAUSE_DECL (node);
9783 : 22897 : return *grp->grp_start;
9784 : :
9785 : 9211 : case GOMP_MAP_ALWAYS_POINTER:
9786 : 9211 : case GOMP_MAP_ATTACH_DETACH:
9787 : 9211 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
9788 : 9211 : case GOMP_MAP_DETACH:
9789 : 9211 : return *grp->grp_start;
9790 : :
9791 : 0 : default:
9792 : 0 : internal_error ("unexpected mapping node");
9793 : : }
9794 : : return error_mark_node;
9795 : :
9796 : 18 : case GOMP_MAP_TO_PSET:
9797 : 18 : gcc_assert (node != grp->grp_end);
9798 : 18 : node = OMP_CLAUSE_CHAIN (node);
9799 : 18 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
9800 : 18 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
9801 : : return NULL_TREE;
9802 : : else
9803 : 0 : internal_error ("unexpected mapping node");
9804 : : return error_mark_node;
9805 : :
9806 : 950 : case GOMP_MAP_ATTACH:
9807 : 950 : case GOMP_MAP_DETACH:
9808 : 950 : node = OMP_CLAUSE_CHAIN (node);
9809 : 950 : if (!node || *grp->grp_start == grp->grp_end)
9810 : : return NULL_TREE;
9811 : 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
9812 : 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
9813 : : {
9814 : : /* We're mapping the base pointer itself in a bare attach or detach
9815 : : node. This is a side effect of how parsing works, and the mapping
9816 : : will be removed anyway (at least for enter/exit data directives).
9817 : : We should ignore the mapping here. FIXME. */
9818 : : return NULL_TREE;
9819 : : }
9820 : : else
9821 : 0 : internal_error ("unexpected mapping node");
9822 : : return error_mark_node;
9823 : :
9824 : 2277 : case GOMP_MAP_STRUCT:
9825 : 2277 : case GOMP_MAP_STRUCT_UNORD:
9826 : 2277 : {
9827 : 2277 : unsigned HOST_WIDE_INT num_mappings
9828 : 2277 : = tree_to_uhwi (OMP_CLAUSE_SIZE (node));
9829 : 2277 : node = OMP_CLAUSE_CHAIN (node);
9830 : 2277 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
9831 : 2277 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
9832 : : {
9833 : 393 : *firstprivate = OMP_CLAUSE_DECL (node);
9834 : 393 : node = OMP_CLAUSE_CHAIN (node);
9835 : : }
9836 : 1884 : else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH_DETACH)
9837 : 300 : node = OMP_CLAUSE_CHAIN (node);
9838 : 2277 : *chained = num_mappings;
9839 : 2277 : return node;
9840 : : }
9841 : :
9842 : : case GOMP_MAP_FORCE_DEVICEPTR:
9843 : : case GOMP_MAP_DEVICE_RESIDENT:
9844 : : case GOMP_MAP_LINK:
9845 : : case GOMP_MAP_FIRSTPRIVATE:
9846 : : case GOMP_MAP_FIRSTPRIVATE_INT:
9847 : : case GOMP_MAP_USE_DEVICE_PTR:
9848 : : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
9849 : : return NULL_TREE;
9850 : :
9851 : 0 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
9852 : 0 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
9853 : 0 : case GOMP_MAP_POINTER:
9854 : 0 : case GOMP_MAP_ALWAYS_POINTER:
9855 : 0 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
9856 : : /* These shouldn't appear by themselves. */
9857 : 0 : if (!seen_error ())
9858 : 0 : internal_error ("unexpected pointer mapping node");
9859 : 0 : return error_mark_node;
9860 : :
9861 : 0 : default:
9862 : 0 : gcc_unreachable ();
9863 : : }
9864 : :
9865 : : return error_mark_node;
9866 : : }
9867 : :
9868 : : /* Given a vector of omp_mapping_groups, build a hash table so we can look up
9869 : : nodes by tree_operand_hash_no_se. */
9870 : :
9871 : : static void
9872 : 41969 : omp_index_mapping_groups_1 (hash_map<tree_operand_hash_no_se,
9873 : : omp_mapping_group *> *grpmap,
9874 : : vec<omp_mapping_group> *groups,
9875 : : tree reindex_sentinel)
9876 : : {
9877 : 41969 : omp_mapping_group *grp;
9878 : 41969 : unsigned int i;
9879 : 41969 : bool reindexing = reindex_sentinel != NULL_TREE, above_hwm = false;
9880 : :
9881 : 115770 : FOR_EACH_VEC_ELT (*groups, i, grp)
9882 : : {
9883 : 73801 : if (reindexing && *grp->grp_start == reindex_sentinel)
9884 : 73801 : above_hwm = true;
9885 : :
9886 : 73801 : if (reindexing && !above_hwm)
9887 : 50511 : continue;
9888 : :
9889 : 73532 : if (grp->reprocess_struct)
9890 : 139 : continue;
9891 : :
9892 : 73393 : tree fpp;
9893 : 73393 : unsigned int chained;
9894 : 73393 : tree node = omp_group_base (grp, &chained, &fpp);
9895 : :
9896 : 73393 : if (node == error_mark_node || (!node && !fpp))
9897 : 1258 : continue;
9898 : :
9899 : : for (unsigned j = 0;
9900 : 145245 : node && j < chained;
9901 : 73110 : node = OMP_CLAUSE_CHAIN (node), j++)
9902 : : {
9903 : 73110 : tree decl = OMP_CLAUSE_DECL (node);
9904 : : /* Sometimes we see zero-offset MEM_REF instead of INDIRECT_REF,
9905 : : meaning node-hash lookups don't work. This is a workaround for
9906 : : that, but ideally we should just create the INDIRECT_REF at
9907 : : source instead. FIXME. */
9908 : 73110 : if (TREE_CODE (decl) == MEM_REF
9909 : 73110 : && integer_zerop (TREE_OPERAND (decl, 1)))
9910 : 0 : decl = build_fold_indirect_ref (TREE_OPERAND (decl, 0));
9911 : :
9912 : 73110 : omp_mapping_group **prev = grpmap->get (decl);
9913 : :
9914 : 73110 : if (prev && *prev == grp)
9915 : : /* Empty. */;
9916 : 73110 : else if (prev)
9917 : : {
9918 : : /* Mapping the same thing twice is normally diagnosed as an error,
9919 : : but can happen under some circumstances, e.g. in pr99928-16.c,
9920 : : the directive:
9921 : :
9922 : : #pragma omp target simd reduction(+:a[:3]) \
9923 : : map(always, tofrom: a[:6])
9924 : : ...
9925 : :
9926 : : will result in two "a[0]" mappings (of different sizes). */
9927 : :
9928 : 129 : grp->sibling = (*prev)->sibling;
9929 : 129 : (*prev)->sibling = grp;
9930 : : }
9931 : : else
9932 : 72981 : grpmap->put (decl, grp);
9933 : : }
9934 : :
9935 : 72135 : if (!fpp)
9936 : 48845 : continue;
9937 : :
9938 : 23290 : omp_mapping_group **prev = grpmap->get (fpp);
9939 : 23290 : if (prev && *prev != grp)
9940 : : {
9941 : 14 : grp->sibling = (*prev)->sibling;
9942 : 14 : (*prev)->sibling = grp;
9943 : : }
9944 : : else
9945 : 23276 : grpmap->put (fpp, grp);
9946 : : }
9947 : 41969 : }
9948 : :
9949 : : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
9950 : 41514 : omp_index_mapping_groups (vec<omp_mapping_group> *groups)
9951 : : {
9952 : 41514 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
9953 : 41514 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
9954 : :
9955 : 41514 : omp_index_mapping_groups_1 (grpmap, groups, NULL_TREE);
9956 : :
9957 : 41514 : return grpmap;
9958 : : }
9959 : :
9960 : : /* Rebuild group map from partially-processed clause list (during
9961 : : omp_build_struct_sibling_lists). We have already processed nodes up until
9962 : : a high-water mark (HWM). This is a bit tricky because the list is being
9963 : : reordered as it is scanned, but we know:
9964 : :
9965 : : 1. The list after HWM has not been touched yet, so we can reindex it safely.
9966 : :
9967 : : 2. The list before and including HWM has been altered, but remains
9968 : : well-formed throughout the sibling-list building operation.
9969 : :
9970 : : so, we can do the reindex operation in two parts, on the processed and
9971 : : then the unprocessed halves of the list. */
9972 : :
9973 : : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
9974 : 304 : omp_reindex_mapping_groups (tree *list_p,
9975 : : vec<omp_mapping_group> *groups,
9976 : : vec<omp_mapping_group> *processed_groups,
9977 : : tree sentinel)
9978 : : {
9979 : 304 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
9980 : 304 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
9981 : :
9982 : 304 : processed_groups->truncate (0);
9983 : :
9984 : 304 : omp_gather_mapping_groups_1 (list_p, processed_groups, sentinel);
9985 : 304 : omp_index_mapping_groups_1 (grpmap, processed_groups, NULL_TREE);
9986 : 304 : if (sentinel)
9987 : 151 : omp_index_mapping_groups_1 (grpmap, groups, sentinel);
9988 : :
9989 : 304 : return grpmap;
9990 : : }
9991 : :
9992 : : /* Find the immediately-containing struct for a component ref (etc.)
9993 : : expression EXPR. */
9994 : :
9995 : : static tree
9996 : 35609 : omp_containing_struct (tree expr)
9997 : : {
9998 : 35609 : tree expr0 = expr;
9999 : :
10000 : 35609 : STRIP_NOPS (expr);
10001 : :
10002 : : /* Note: don't strip NOPs unless we're also stripping off array refs or a
10003 : : component ref. */
10004 : 35609 : if (TREE_CODE (expr) != ARRAY_REF && TREE_CODE (expr) != COMPONENT_REF)
10005 : : return expr0;
10006 : :
10007 : 17708 : while (TREE_CODE (expr) == ARRAY_REF)
10008 : 2086 : expr = TREE_OPERAND (expr, 0);
10009 : :
10010 : 15622 : if (TREE_CODE (expr) == COMPONENT_REF)
10011 : 14715 : expr = TREE_OPERAND (expr, 0);
10012 : :
10013 : : return expr;
10014 : : }
10015 : :
10016 : : /* Return TRUE if DECL describes a component that is part of a whole structure
10017 : : that is mapped elsewhere in GRPMAP. *MAPPED_BY_GROUP is set to the group
10018 : : that maps that structure, if present. */
10019 : :
10020 : : static bool
10021 : 20956 : omp_mapped_by_containing_struct (hash_map<tree_operand_hash_no_se,
10022 : : omp_mapping_group *> *grpmap,
10023 : : tree decl,
10024 : : omp_mapping_group **mapped_by_group)
10025 : : {
10026 : 20956 : tree wsdecl = NULL_TREE;
10027 : :
10028 : 20956 : *mapped_by_group = NULL;
10029 : :
10030 : 35609 : while (true)
10031 : : {
10032 : 35609 : wsdecl = omp_containing_struct (decl);
10033 : 35609 : if (wsdecl == decl)
10034 : : break;
10035 : 15622 : omp_mapping_group **wholestruct = grpmap->get (wsdecl);
10036 : 15622 : if (!wholestruct
10037 : 14653 : && TREE_CODE (wsdecl) == MEM_REF
10038 : 15622 : && integer_zerop (TREE_OPERAND (wsdecl, 1)))
10039 : : {
10040 : 0 : tree deref = TREE_OPERAND (wsdecl, 0);
10041 : 0 : deref = build_fold_indirect_ref (deref);
10042 : 0 : wholestruct = grpmap->get (deref);
10043 : : }
10044 : 15622 : if (wholestruct)
10045 : : {
10046 : 969 : *mapped_by_group = *wholestruct;
10047 : 969 : return true;
10048 : : }
10049 : : decl = wsdecl;
10050 : : }
10051 : :
10052 : : return false;
10053 : : }
10054 : :
10055 : : /* Helper function for omp_tsort_mapping_groups. Returns TRUE on success, or
10056 : : FALSE on error. */
10057 : :
10058 : : static bool
10059 : 17137 : omp_tsort_mapping_groups_1 (omp_mapping_group ***outlist,
10060 : : vec<omp_mapping_group> *groups,
10061 : : hash_map<tree_operand_hash_no_se,
10062 : : omp_mapping_group *> *grpmap,
10063 : : omp_mapping_group *grp)
10064 : : {
10065 : 17137 : if (grp->mark == PERMANENT)
10066 : : return true;
10067 : 14263 : if (grp->mark == TEMPORARY)
10068 : : {
10069 : 0 : fprintf (stderr, "when processing group:\n");
10070 : 0 : debug_mapping_group (grp);
10071 : 0 : internal_error ("base pointer cycle detected");
10072 : : return false;
10073 : : }
10074 : 14263 : grp->mark = TEMPORARY;
10075 : :
10076 : 14263 : tree attaches_to = omp_get_attachment (grp);
10077 : :
10078 : 14263 : if (attaches_to)
10079 : : {
10080 : 2313 : omp_mapping_group **basep = grpmap->get (attaches_to);
10081 : :
10082 : 2313 : if (basep && *basep != grp)
10083 : : {
10084 : 2640 : for (omp_mapping_group *w = *basep; w; w = w->sibling)
10085 : 1320 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
10086 : : return false;
10087 : : }
10088 : : }
10089 : :
10090 : 14263 : tree decl = OMP_CLAUSE_DECL (*grp->grp_start);
10091 : :
10092 : 19495 : while (decl)
10093 : : {
10094 : 19495 : tree base = omp_get_base_pointer (decl);
10095 : :
10096 : 19495 : if (!base)
10097 : : break;
10098 : :
10099 : 7570 : omp_mapping_group **innerp = grpmap->get (base);
10100 : 7570 : omp_mapping_group *wholestruct;
10101 : :
10102 : : /* We should treat whole-structure mappings as if all (pointer, in this
10103 : : case) members are mapped as individual list items. Check if we have
10104 : : such a whole-structure mapping, if we don't have an explicit reference
10105 : : to the pointer member itself. */
10106 : 7570 : if (!innerp
10107 : 3199 : && TREE_CODE (base) == COMPONENT_REF
10108 : 8895 : && omp_mapped_by_containing_struct (grpmap, base, &wholestruct))
10109 : : innerp = &wholestruct;
10110 : :
10111 : 7570 : if (innerp && *innerp != grp)
10112 : : {
10113 : 4676 : for (omp_mapping_group *w = *innerp; w; w = w->sibling)
10114 : 2338 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
10115 : 0 : return false;
10116 : : break;
10117 : : }
10118 : :
10119 : 5232 : decl = base;
10120 : : }
10121 : :
10122 : 14263 : grp->mark = PERMANENT;
10123 : :
10124 : : /* Emit grp to output list. */
10125 : :
10126 : 14263 : **outlist = grp;
10127 : 14263 : *outlist = &grp->next;
10128 : :
10129 : 14263 : return true;
10130 : : }
10131 : :
10132 : : /* Topologically sort GROUPS, so that OMP 5.0-defined base pointers come
10133 : : before mappings that use those pointers. This is an implementation of the
10134 : : depth-first search algorithm, described e.g. at:
10135 : :
10136 : : https://en.wikipedia.org/wiki/Topological_sorting
10137 : : */
10138 : :
10139 : : static omp_mapping_group *
10140 : 7288 : omp_tsort_mapping_groups (vec<omp_mapping_group> *groups,
10141 : : hash_map<tree_operand_hash_no_se, omp_mapping_group *>
10142 : : *grpmap,
10143 : : bool enter_exit_data)
10144 : : {
10145 : 7288 : omp_mapping_group *grp, *outlist = NULL, **cursor;
10146 : 7288 : unsigned int i;
10147 : 7288 : bool saw_runtime_implicit = false;
10148 : :
10149 : 7288 : cursor = &outlist;
10150 : :
10151 : 21551 : FOR_EACH_VEC_ELT (*groups, i, grp)
10152 : : {
10153 : 14263 : if (grp->mark != PERMANENT)
10154 : : {
10155 : 13479 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
10156 : : {
10157 : 205 : saw_runtime_implicit = true;
10158 : 205 : continue;
10159 : : }
10160 : 13274 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
10161 : : return NULL;
10162 : : }
10163 : : }
10164 : :
10165 : 7288 : if (!saw_runtime_implicit)
10166 : 7157 : return outlist;
10167 : :
10168 : 536 : FOR_EACH_VEC_ELT (*groups, i, grp)
10169 : : {
10170 : 405 : if (grp->mark != PERMANENT
10171 : 405 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
10172 : : {
10173 : : /* Clear the flag for enter/exit data because it is currently
10174 : : meaningless for those operations in libgomp. */
10175 : 205 : if (enter_exit_data)
10176 : 35 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start) = 0;
10177 : :
10178 : 205 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
10179 : : return NULL;
10180 : : }
10181 : : }
10182 : :
10183 : 131 : return outlist;
10184 : : }
10185 : :
10186 : : /* Split INLIST into three parts:
10187 : :
10188 : : - "present" alloc/to/from groups
10189 : : - other to/from groups
10190 : : - other alloc/release/delete groups
10191 : :
10192 : : These sub-lists are then concatenated together to form the final list.
10193 : : Each sub-list retains the order of the original list.
10194 : : Note that ATTACH nodes are later moved to the end of the list in
10195 : : gimplify_adjust_omp_clauses, for target regions. */
10196 : :
10197 : : static omp_mapping_group *
10198 : 7288 : omp_segregate_mapping_groups (omp_mapping_group *inlist)
10199 : : {
10200 : 7288 : omp_mapping_group *ard_groups = NULL, *tf_groups = NULL;
10201 : 7288 : omp_mapping_group *p_groups = NULL;
10202 : 7288 : omp_mapping_group **ard_tail = &ard_groups, **tf_tail = &tf_groups;
10203 : 7288 : omp_mapping_group **p_tail = &p_groups;
10204 : :
10205 : 21551 : for (omp_mapping_group *w = inlist; w;)
10206 : : {
10207 : 14263 : tree c = *w->grp_start;
10208 : 14263 : omp_mapping_group *next = w->next;
10209 : :
10210 : 14263 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
10211 : :
10212 : 14263 : switch (OMP_CLAUSE_MAP_KIND (c))
10213 : : {
10214 : 1617 : case GOMP_MAP_ALLOC:
10215 : 1617 : case GOMP_MAP_RELEASE:
10216 : 1617 : case GOMP_MAP_DELETE:
10217 : 1617 : *ard_tail = w;
10218 : 1617 : w->next = NULL;
10219 : 1617 : ard_tail = &w->next;
10220 : 1617 : break;
10221 : :
10222 : : /* These map types are all semantically identical, so are moved into a
10223 : : single group. They will each be changed into GOMP_MAP_FORCE_PRESENT
10224 : : in gimplify_adjust_omp_clauses. */
10225 : 145 : case GOMP_MAP_PRESENT_ALLOC:
10226 : 145 : case GOMP_MAP_PRESENT_FROM:
10227 : 145 : case GOMP_MAP_PRESENT_TO:
10228 : 145 : case GOMP_MAP_PRESENT_TOFROM:
10229 : 145 : *p_tail = w;
10230 : 145 : w->next = NULL;
10231 : 145 : p_tail = &w->next;
10232 : 145 : break;
10233 : :
10234 : 12501 : default:
10235 : 12501 : *tf_tail = w;
10236 : 12501 : w->next = NULL;
10237 : 12501 : tf_tail = &w->next;
10238 : : }
10239 : :
10240 : : w = next;
10241 : : }
10242 : :
10243 : : /* Now splice the lists together... */
10244 : 7288 : *tf_tail = ard_groups;
10245 : 7288 : *p_tail = tf_groups;
10246 : :
10247 : 7288 : return p_groups;
10248 : : }
10249 : :
10250 : : /* Given a list LIST_P containing groups of mappings given by GROUPS, reorder
10251 : : those groups based on the output list of omp_tsort_mapping_groups --
10252 : : singly-linked, threaded through each element's NEXT pointer starting at
10253 : : HEAD. Each list element appears exactly once in that linked list.
10254 : :
10255 : : Each element of GROUPS may correspond to one or several mapping nodes.
10256 : : Node groups are kept together, and in the reordered list, the positions of
10257 : : the original groups are reused for the positions of the reordered list.
10258 : : Hence if we have e.g.
10259 : :
10260 : : {to ptr ptr} firstprivate {tofrom ptr} ...
10261 : : ^ ^ ^
10262 : : first group non-"map" second group
10263 : :
10264 : : and say the second group contains a base pointer for the first so must be
10265 : : moved before it, the resulting list will contain:
10266 : :
10267 : : {tofrom ptr} firstprivate {to ptr ptr} ...
10268 : : ^ prev. second group ^ prev. first group
10269 : : */
10270 : :
10271 : : static tree *
10272 : 7288 : omp_reorder_mapping_groups (vec<omp_mapping_group> *groups,
10273 : : omp_mapping_group *head,
10274 : : tree *list_p)
10275 : : {
10276 : 7288 : omp_mapping_group *grp;
10277 : 7288 : unsigned int i;
10278 : 7288 : unsigned numgroups = groups->length ();
10279 : 7288 : auto_vec<tree> old_heads (numgroups);
10280 : 7288 : auto_vec<tree *> old_headps (numgroups);
10281 : 7288 : auto_vec<tree> new_heads (numgroups);
10282 : 7288 : auto_vec<tree> old_succs (numgroups);
10283 : 7288 : bool map_at_start = (list_p == (*groups)[0].grp_start);
10284 : :
10285 : 7288 : tree *new_grp_tail = NULL;
10286 : :
10287 : : /* Stash the start & end nodes of each mapping group before we start
10288 : : modifying the list. */
10289 : 21551 : FOR_EACH_VEC_ELT (*groups, i, grp)
10290 : : {
10291 : 14263 : old_headps.quick_push (grp->grp_start);
10292 : 14263 : old_heads.quick_push (*grp->grp_start);
10293 : 14263 : old_succs.quick_push (OMP_CLAUSE_CHAIN (grp->grp_end));
10294 : : }
10295 : :
10296 : : /* And similarly, the heads of the groups in the order we want to rearrange
10297 : : the list to. */
10298 : 21551 : for (omp_mapping_group *w = head; w; w = w->next)
10299 : 14263 : new_heads.quick_push (*w->grp_start);
10300 : :
10301 : 21551 : FOR_EACH_VEC_ELT (*groups, i, grp)
10302 : : {
10303 : 14263 : gcc_assert (head);
10304 : :
10305 : 14263 : if (new_grp_tail && old_succs[i - 1] == old_heads[i])
10306 : : {
10307 : : /* a {b c d} {e f g} h i j (original)
10308 : : -->
10309 : : a {k l m} {e f g} h i j (inserted new group on last iter)
10310 : : -->
10311 : : a {k l m} {n o p} h i j (this time, chain last group to new one)
10312 : : ^new_grp_tail
10313 : : */
10314 : 6285 : *new_grp_tail = new_heads[i];
10315 : : }
10316 : 7978 : else if (new_grp_tail)
10317 : : {
10318 : : /* a {b c d} e {f g h} i j k (original)
10319 : : -->
10320 : : a {l m n} e {f g h} i j k (gap after last iter's group)
10321 : : -->
10322 : : a {l m n} e {o p q} h i j (chain last group to old successor)
10323 : : ^new_grp_tail
10324 : : */
10325 : 690 : *new_grp_tail = old_succs[i - 1];
10326 : 690 : *old_headps[i] = new_heads[i];
10327 : : }
10328 : : else
10329 : : {
10330 : : /* The first inserted group -- point to new group, and leave end
10331 : : open.
10332 : : a {b c d} e f
10333 : : -->
10334 : : a {g h i...
10335 : : */
10336 : 7288 : *grp->grp_start = new_heads[i];
10337 : : }
10338 : :
10339 : 14263 : new_grp_tail = &OMP_CLAUSE_CHAIN (head->grp_end);
10340 : :
10341 : 14263 : head = head->next;
10342 : : }
10343 : :
10344 : 7288 : if (new_grp_tail)
10345 : 7288 : *new_grp_tail = old_succs[numgroups - 1];
10346 : :
10347 : 7288 : gcc_assert (!head);
10348 : :
10349 : 10320 : return map_at_start ? (*groups)[0].grp_start : list_p;
10350 : 7288 : }
10351 : :
10352 : : /* DECL is supposed to have lastprivate semantics in the outer contexts
10353 : : of combined/composite constructs, starting with OCTX.
10354 : : Add needed lastprivate, shared or map clause if no data sharing or
10355 : : mapping clause are present. IMPLICIT_P is true if it is an implicit
10356 : : clause (IV on simd), in which case the lastprivate will not be
10357 : : copied to some constructs. */
10358 : :
10359 : : static void
10360 : 15462 : omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx,
10361 : : tree decl, bool implicit_p)
10362 : : {
10363 : 15462 : struct gimplify_omp_ctx *orig_octx = octx;
10364 : 28147 : for (; octx; octx = octx->outer_context)
10365 : : {
10366 : 27022 : if ((octx->region_type == ORT_COMBINED_PARALLEL
10367 : 21741 : || (octx->region_type & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS)
10368 : 26378 : && splay_tree_lookup (octx->variables,
10369 : : (splay_tree_key) decl) == NULL)
10370 : : {
10371 : 4061 : omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN);
10372 : 4061 : continue;
10373 : : }
10374 : 19178 : if ((octx->region_type & ORT_TASK) != 0
10375 : 653 : && octx->combined_loop
10376 : 19498 : && splay_tree_lookup (octx->variables,
10377 : : (splay_tree_key) decl) == NULL)
10378 : : {
10379 : 278 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
10380 : 278 : continue;
10381 : : }
10382 : 23518 : if (implicit_p
10383 : 14024 : && octx->region_type == ORT_WORKSHARE
10384 : 10694 : && octx->combined_loop
10385 : 10564 : && splay_tree_lookup (octx->variables,
10386 : : (splay_tree_key) decl) == NULL
10387 : 10564 : && octx->outer_context
10388 : 9065 : && octx->outer_context->region_type == ORT_COMBINED_PARALLEL
10389 : 23525 : && splay_tree_lookup (octx->outer_context->variables,
10390 : : (splay_tree_key) decl) == NULL)
10391 : : {
10392 : 4896 : octx = octx->outer_context;
10393 : 4896 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
10394 : 4896 : continue;
10395 : : }
10396 : 5834 : if ((octx->region_type == ORT_WORKSHARE || octx->region_type == ORT_ACC)
10397 : 7892 : && octx->combined_loop
10398 : 7678 : && splay_tree_lookup (octx->variables,
10399 : : (splay_tree_key) decl) == NULL
10400 : 19991 : && !omp_check_private (octx, decl, false))
10401 : : {
10402 : 3450 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
10403 : 3450 : continue;
10404 : : }
10405 : 10276 : if (octx->region_type == ORT_COMBINED_TARGET)
10406 : : {
10407 : 2091 : splay_tree_node n = splay_tree_lookup (octx->variables,
10408 : : (splay_tree_key) decl);
10409 : 2091 : if (n == NULL)
10410 : : {
10411 : 2066 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
10412 : 2066 : octx = octx->outer_context;
10413 : : }
10414 : 25 : else if (!implicit_p
10415 : 25 : && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT))
10416 : : {
10417 : 15 : n->value &= ~(GOVD_FIRSTPRIVATE
10418 : : | GOVD_FIRSTPRIVATE_IMPLICIT
10419 : : | GOVD_EXPLICIT);
10420 : 15 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
10421 : 15 : octx = octx->outer_context;
10422 : : }
10423 : : }
10424 : : break;
10425 : : }
10426 : 15462 : if (octx && (implicit_p || octx != orig_octx))
10427 : 4300 : omp_notice_variable (octx, decl, true);
10428 : 15462 : }
10429 : :
10430 : : /* We might have indexed several groups for DECL, e.g. a "TO" mapping and also
10431 : : a "FIRSTPRIVATE" mapping. Return the one that isn't firstprivate, etc. */
10432 : :
10433 : : static omp_mapping_group *
10434 : 5020 : omp_get_nonfirstprivate_group (hash_map<tree_operand_hash_no_se,
10435 : : omp_mapping_group *> *grpmap,
10436 : : tree decl, bool allow_deleted = false)
10437 : : {
10438 : 5020 : omp_mapping_group **to_group_p = grpmap->get (decl);
10439 : :
10440 : 5020 : if (!to_group_p)
10441 : : return NULL;
10442 : :
10443 : 2155 : omp_mapping_group *to_group = *to_group_p;
10444 : :
10445 : 3368 : for (; to_group; to_group = to_group->sibling)
10446 : : {
10447 : 2195 : tree grp_end = to_group->grp_end;
10448 : 2195 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
10449 : : {
10450 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
10451 : : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
10452 : : break;
10453 : :
10454 : 984 : default:
10455 : 984 : if (allow_deleted || !to_group->deleted)
10456 : 982 : return to_group;
10457 : : }
10458 : : }
10459 : :
10460 : : return NULL;
10461 : : }
10462 : :
10463 : : /* Return TRUE if the directive (whose clauses are described by the hash table
10464 : : of mapping groups, GRPMAP) maps DECL explicitly. If TO_SPECIFICALLY is
10465 : : true, only count TO mappings. If ALLOW_DELETED is true, ignore the
10466 : : "deleted" flag for groups. If CONTAINED_IN_STRUCT is true, also return
10467 : : TRUE if DECL is mapped as a member of a whole-struct mapping. */
10468 : :
10469 : : static bool
10470 : 3640 : omp_directive_maps_explicitly (hash_map<tree_operand_hash_no_se,
10471 : : omp_mapping_group *> *grpmap,
10472 : : tree decl, omp_mapping_group **base_group,
10473 : : bool to_specifically, bool allow_deleted,
10474 : : bool contained_in_struct)
10475 : : {
10476 : 3640 : omp_mapping_group *decl_group
10477 : 3640 : = omp_get_nonfirstprivate_group (grpmap, decl, allow_deleted);
10478 : :
10479 : 3640 : *base_group = NULL;
10480 : :
10481 : 3640 : if (decl_group)
10482 : : {
10483 : 876 : tree grp_first = *decl_group->grp_start;
10484 : : /* We might be called during omp_build_struct_sibling_lists, when
10485 : : GOMP_MAP_STRUCT might have been inserted at the start of the group.
10486 : : Skip over that, and also possibly the node after it. */
10487 : 876 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT
10488 : 876 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT_UNORD)
10489 : : {
10490 : 6 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
10491 : 6 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_FIRSTPRIVATE_POINTER
10492 : 6 : || (OMP_CLAUSE_MAP_KIND (grp_first)
10493 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
10494 : 12 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_ATTACH_DETACH)
10495 : 0 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
10496 : : }
10497 : 876 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
10498 : 876 : if (!to_specifically
10499 : 495 : || GOMP_MAP_COPY_TO_P (first_kind)
10500 : 307 : || first_kind == GOMP_MAP_ALLOC)
10501 : : {
10502 : 836 : *base_group = decl_group;
10503 : 836 : return true;
10504 : : }
10505 : : }
10506 : :
10507 : 2804 : if (contained_in_struct
10508 : 2804 : && omp_mapped_by_containing_struct (grpmap, decl, base_group))
10509 : : return true;
10510 : :
10511 : : return false;
10512 : : }
10513 : :
10514 : : /* If we have mappings INNER and OUTER, where INNER is a component access and
10515 : : OUTER is a mapping of the whole containing struct, check that the mappings
10516 : : are compatible. We'll be deleting the inner mapping, so we need to make
10517 : : sure the outer mapping does (at least) the same transfers to/from the device
10518 : : as the inner mapping. */
10519 : :
10520 : : bool
10521 : 195 : omp_check_mapping_compatibility (location_t loc,
10522 : : omp_mapping_group *outer,
10523 : : omp_mapping_group *inner)
10524 : : {
10525 : 195 : tree first_outer = *outer->grp_start, first_inner = *inner->grp_start;
10526 : :
10527 : 195 : gcc_assert (OMP_CLAUSE_CODE (first_outer) == OMP_CLAUSE_MAP);
10528 : 195 : gcc_assert (OMP_CLAUSE_CODE (first_inner) == OMP_CLAUSE_MAP);
10529 : :
10530 : 195 : enum gomp_map_kind outer_kind = OMP_CLAUSE_MAP_KIND (first_outer);
10531 : 195 : enum gomp_map_kind inner_kind = OMP_CLAUSE_MAP_KIND (first_inner);
10532 : :
10533 : 195 : if (outer_kind == inner_kind)
10534 : : return true;
10535 : :
10536 : 79 : switch (outer_kind)
10537 : : {
10538 : 0 : case GOMP_MAP_ALWAYS_TO:
10539 : 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
10540 : 0 : || inner_kind == GOMP_MAP_ALLOC
10541 : 0 : || inner_kind == GOMP_MAP_TO)
10542 : : return true;
10543 : : break;
10544 : :
10545 : 0 : case GOMP_MAP_ALWAYS_FROM:
10546 : 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
10547 : 0 : || inner_kind == GOMP_MAP_RELEASE
10548 : : || inner_kind == GOMP_MAP_FROM)
10549 : : return true;
10550 : : break;
10551 : :
10552 : 12 : case GOMP_MAP_TO:
10553 : 12 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
10554 : 12 : || inner_kind == GOMP_MAP_ALLOC)
10555 : : return true;
10556 : : break;
10557 : :
10558 : 10 : case GOMP_MAP_FROM:
10559 : 10 : if (inner_kind == GOMP_MAP_RELEASE
10560 : 10 : || inner_kind == GOMP_MAP_FORCE_PRESENT)
10561 : : return true;
10562 : : break;
10563 : :
10564 : 32 : case GOMP_MAP_ALWAYS_TOFROM:
10565 : 32 : case GOMP_MAP_TOFROM:
10566 : 32 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
10567 : 32 : || inner_kind == GOMP_MAP_ALLOC
10568 : : || inner_kind == GOMP_MAP_TO
10569 : 23 : || inner_kind == GOMP_MAP_FROM
10570 : 12 : || inner_kind == GOMP_MAP_TOFROM)
10571 : : return true;
10572 : : break;
10573 : :
10574 : 35 : default:
10575 : 35 : ;
10576 : : }
10577 : :
10578 : 105 : error_at (loc, "data movement for component %qE is not compatible with "
10579 : 35 : "movement for struct %qE", OMP_CLAUSE_DECL (first_inner),
10580 : 35 : OMP_CLAUSE_DECL (first_outer));
10581 : :
10582 : 35 : return false;
10583 : : }
10584 : :
10585 : : /* This function handles several cases where clauses on a mapping directive
10586 : : can interact with each other.
10587 : :
10588 : : If we have a FIRSTPRIVATE_POINTER node and we're also mapping the pointer
10589 : : on the same directive, change the mapping of the first node to
10590 : : ATTACH_DETACH. We should have detected that this will happen already in
10591 : : c-omp.cc:c_omp_adjust_map_clauses and marked the appropriate decl
10592 : : as addressable. (If we didn't, bail out.)
10593 : :
10594 : : If we have a FIRSTPRIVATE_REFERENCE (for a reference to pointer) and we're
10595 : : mapping the base pointer also, we may need to change the mapping type to
10596 : : ATTACH_DETACH and synthesize an alloc node for the reference itself.
10597 : :
10598 : : If we have an ATTACH_DETACH node, this is an array section with a pointer
10599 : : base. If we're mapping the base on the same directive too, we can drop its
10600 : : mapping. However, if we have a reference to pointer, make other appropriate
10601 : : adjustments to the mapping nodes instead.
10602 : :
10603 : : If we have an ATTACH_DETACH node with a Fortran pointer-set (array
10604 : : descriptor) mapping for a derived-type component, and we're also mapping the
10605 : : whole of the derived-type variable on another clause, the pointer-set
10606 : : mapping is removed.
10607 : :
10608 : : If we have a component access but we're also mapping the whole of the
10609 : : containing struct, drop the former access.
10610 : :
10611 : : If the expression is a component access, and we're also mapping a base
10612 : : pointer used in that component access in the same expression, change the
10613 : : mapping type of the latter to ALLOC (ready for processing by
10614 : : omp_build_struct_sibling_lists). */
10615 : :
10616 : : void
10617 : 7288 : omp_resolve_clause_dependencies (enum tree_code code,
10618 : : vec<omp_mapping_group> *groups,
10619 : : hash_map<tree_operand_hash_no_se,
10620 : : omp_mapping_group *> *grpmap)
10621 : : {
10622 : 7288 : int i;
10623 : 7288 : omp_mapping_group *grp;
10624 : 7288 : bool repair_chain = false;
10625 : :
10626 : 20711 : FOR_EACH_VEC_ELT (*groups, i, grp)
10627 : : {
10628 : 13423 : tree grp_end = grp->grp_end;
10629 : 13423 : tree decl = OMP_CLAUSE_DECL (grp_end);
10630 : :
10631 : 13423 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
10632 : :
10633 : 13423 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
10634 : : {
10635 : 1102 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
10636 : 1102 : {
10637 : 1102 : omp_mapping_group *to_group
10638 : 1102 : = omp_get_nonfirstprivate_group (grpmap, decl);
10639 : :
10640 : 1102 : if (!to_group || to_group == grp)
10641 : 1073 : continue;
10642 : :
10643 : 29 : tree grp_first = *to_group->grp_start;
10644 : 29 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
10645 : :
10646 : 29 : if ((GOMP_MAP_COPY_TO_P (first_kind)
10647 : 7 : || first_kind == GOMP_MAP_ALLOC)
10648 : 58 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
10649 : : != GOMP_MAP_FIRSTPRIVATE_POINTER))
10650 : : {
10651 : 29 : gcc_assert (TREE_ADDRESSABLE (OMP_CLAUSE_DECL (grp_end)));
10652 : 29 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
10653 : : }
10654 : : }
10655 : : break;
10656 : :
10657 : 136 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
10658 : 136 : {
10659 : 136 : tree ptr = build_fold_indirect_ref (decl);
10660 : :
10661 : 136 : omp_mapping_group *to_group
10662 : 136 : = omp_get_nonfirstprivate_group (grpmap, ptr);
10663 : :
10664 : 136 : if (!to_group || to_group == grp)
10665 : 132 : continue;
10666 : :
10667 : 4 : tree grp_first = *to_group->grp_start;
10668 : 4 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
10669 : :
10670 : 4 : if (GOMP_MAP_COPY_TO_P (first_kind)
10671 : 4 : || first_kind == GOMP_MAP_ALLOC)
10672 : : {
10673 : 4 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
10674 : 4 : OMP_CLAUSE_DECL (grp_end) = ptr;
10675 : 4 : if ((OMP_CLAUSE_CHAIN (*to_group->grp_start)
10676 : 4 : == to_group->grp_end)
10677 : 4 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
10678 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
10679 : : {
10680 : 0 : gcc_assert (TREE_ADDRESSABLE
10681 : : (OMP_CLAUSE_DECL (to_group->grp_end)));
10682 : 0 : OMP_CLAUSE_SET_MAP_KIND (to_group->grp_end,
10683 : : GOMP_MAP_ATTACH_DETACH);
10684 : :
10685 : 0 : location_t loc = OMP_CLAUSE_LOCATION (to_group->grp_end);
10686 : 0 : tree alloc
10687 : 0 : = build_omp_clause (loc, OMP_CLAUSE_MAP);
10688 : 0 : OMP_CLAUSE_SET_MAP_KIND (alloc, GOMP_MAP_ALLOC);
10689 : 0 : tree tmp = build_fold_addr_expr (OMP_CLAUSE_DECL
10690 : : (to_group->grp_end));
10691 : 0 : tree char_ptr_type = build_pointer_type (char_type_node);
10692 : 0 : OMP_CLAUSE_DECL (alloc)
10693 : 0 : = build2 (MEM_REF, char_type_node,
10694 : : tmp,
10695 : 0 : build_int_cst (char_ptr_type, 0));
10696 : 0 : OMP_CLAUSE_SIZE (alloc) = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
10697 : :
10698 : 0 : OMP_CLAUSE_CHAIN (alloc)
10699 : 0 : = OMP_CLAUSE_CHAIN (*to_group->grp_start);
10700 : 0 : OMP_CLAUSE_CHAIN (*to_group->grp_start) = alloc;
10701 : : }
10702 : : }
10703 : : }
10704 : : break;
10705 : :
10706 : : case GOMP_MAP_ATTACH_DETACH:
10707 : : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10708 : : {
10709 : 1890 : tree base_ptr, referenced_ptr_node = NULL_TREE;
10710 : :
10711 : 1890 : while (TREE_CODE (decl) == ARRAY_REF)
10712 : 0 : decl = TREE_OPERAND (decl, 0);
10713 : :
10714 : 1890 : if (TREE_CODE (decl) == INDIRECT_REF)
10715 : 13 : decl = TREE_OPERAND (decl, 0);
10716 : :
10717 : : /* Only component accesses. */
10718 : 1890 : if (DECL_P (decl))
10719 : 195 : continue;
10720 : :
10721 : : /* We want the pointer itself when checking if the base pointer is
10722 : : mapped elsewhere in the same directive -- if we have a
10723 : : reference to the pointer, don't use that. */
10724 : :
10725 : 1695 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
10726 : 1695 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
10727 : : {
10728 : 394 : referenced_ptr_node = OMP_CLAUSE_CHAIN (*grp->grp_start);
10729 : 394 : base_ptr = OMP_CLAUSE_DECL (referenced_ptr_node);
10730 : : }
10731 : : else
10732 : : base_ptr = decl;
10733 : :
10734 : 3390 : gomp_map_kind zlas_kind
10735 : 1695 : = (code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
10736 : 1695 : ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION;
10737 : :
10738 : 1695 : if (TREE_CODE (TREE_TYPE (base_ptr)) == POINTER_TYPE)
10739 : : {
10740 : : /* If we map the base TO, and we're doing an attachment, we can
10741 : : skip the TO mapping altogether and create an ALLOC mapping
10742 : : instead, since the attachment will overwrite the device
10743 : : pointer in that location immediately anyway. Otherwise,
10744 : : change our mapping to
10745 : : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION in case the
10746 : : attachment target has not been copied to the device already
10747 : : by some earlier directive. */
10748 : :
10749 : 1271 : bool base_mapped_to = false;
10750 : :
10751 : 1271 : omp_mapping_group *base_group;
10752 : :
10753 : 1271 : if (omp_directive_maps_explicitly (grpmap, base_ptr,
10754 : : &base_group, false, true,
10755 : : false))
10756 : : {
10757 : 381 : if (referenced_ptr_node)
10758 : : {
10759 : 129 : base_mapped_to = true;
10760 : 129 : if ((OMP_CLAUSE_MAP_KIND (base_group->grp_end)
10761 : : == GOMP_MAP_ATTACH_DETACH)
10762 : 129 : && (OMP_CLAUSE_CHAIN (*base_group->grp_start)
10763 : : == base_group->grp_end))
10764 : : {
10765 : 258 : OMP_CLAUSE_CHAIN (*base_group->grp_start)
10766 : 129 : = OMP_CLAUSE_CHAIN (base_group->grp_end);
10767 : 129 : base_group->grp_end = *base_group->grp_start;
10768 : 129 : repair_chain = true;
10769 : : }
10770 : : }
10771 : : else
10772 : : {
10773 : 252 : base_group->deleted = true;
10774 : 252 : OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end) = 1;
10775 : : }
10776 : : }
10777 : :
10778 : : /* We're dealing with a reference to a pointer, and we are
10779 : : attaching both the reference and the pointer. We know the
10780 : : reference itself is on the target, because we are going to
10781 : : create an ALLOC node for it in accumulate_sibling_list. The
10782 : : pointer might be on the target already or it might not, but
10783 : : if it isn't then it's not an error, so use
10784 : : GOMP_MAP_ATTACH_ZLAS for it. */
10785 : 1271 : if (!base_mapped_to && referenced_ptr_node)
10786 : 56 : OMP_CLAUSE_SET_MAP_KIND (referenced_ptr_node, zlas_kind);
10787 : :
10788 : 1271 : omp_mapping_group *struct_group;
10789 : 1271 : tree desc;
10790 : 1271 : if ((desc = OMP_CLAUSE_CHAIN (*grp->grp_start))
10791 : 1271 : && omp_map_clause_descriptor_p (desc)
10792 : 1830 : && omp_mapped_by_containing_struct (grpmap, decl,
10793 : : &struct_group))
10794 : : /* If we have a pointer set but we're mapping (or unmapping)
10795 : : the whole of the containing struct, we can remove the
10796 : : pointer set mapping. */
10797 : 15 : OMP_CLAUSE_CHAIN (*grp->grp_start) = OMP_CLAUSE_CHAIN (desc);
10798 : : }
10799 : 424 : else if (TREE_CODE (TREE_TYPE (base_ptr)) == REFERENCE_TYPE
10800 : 424 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (base_ptr)))
10801 : : == ARRAY_TYPE)
10802 : 562 : && OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION
10803 : : (*grp->grp_start))
10804 : 92 : OMP_CLAUSE_SET_MAP_KIND (grp->grp_end, zlas_kind);
10805 : : }
10806 : : break;
10807 : :
10808 : : case GOMP_MAP_ATTACH:
10809 : : /* Ignore standalone attach here. */
10810 : : break;
10811 : :
10812 : 10258 : default:
10813 : 10258 : {
10814 : 10258 : omp_mapping_group *struct_group;
10815 : 10258 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
10816 : 10258 : && *grp->grp_start == grp_end)
10817 : : {
10818 : 98 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
10819 : : struct_group, grp);
10820 : : /* Remove the whole of this mapping -- redundant. */
10821 : 98 : grp->deleted = true;
10822 : : }
10823 : :
10824 : : tree base = decl;
10825 : 11783 : while ((base = omp_get_base_pointer (base)))
10826 : : {
10827 : 1525 : omp_mapping_group *base_group;
10828 : :
10829 : 1525 : if (omp_directive_maps_explicitly (grpmap, base, &base_group,
10830 : : true, true, false))
10831 : : {
10832 : 309 : tree grp_first = *base_group->grp_start;
10833 : 309 : OMP_CLAUSE_SET_MAP_KIND (grp_first, GOMP_MAP_ALLOC);
10834 : : }
10835 : : }
10836 : : }
10837 : : }
10838 : : }
10839 : :
10840 : 7288 : if (repair_chain)
10841 : : {
10842 : : /* Group start pointers may have become detached from the
10843 : : OMP_CLAUSE_CHAIN of previous groups if elements were removed from the
10844 : : end of those groups. Fix that now. */
10845 : : tree *new_next = NULL;
10846 : 716 : FOR_EACH_VEC_ELT (*groups, i, grp)
10847 : : {
10848 : 587 : if (new_next)
10849 : 458 : grp->grp_start = new_next;
10850 : :
10851 : 587 : new_next = &OMP_CLAUSE_CHAIN (grp->grp_end);
10852 : : }
10853 : : }
10854 : 7288 : }
10855 : :
10856 : : /* Similar to omp_resolve_clause_dependencies, but for OpenACC. The only
10857 : : clause dependencies we handle for now are struct element mappings and
10858 : : whole-struct mappings on the same directive, and duplicate clause
10859 : : detection. */
10860 : :
10861 : : void
10862 : 9669 : oacc_resolve_clause_dependencies (vec<omp_mapping_group> *groups,
10863 : : hash_map<tree_operand_hash_no_se,
10864 : : omp_mapping_group *> *grpmap)
10865 : : {
10866 : 9669 : int i;
10867 : 9669 : omp_mapping_group *grp;
10868 : 9669 : hash_set<tree_operand_hash> *seen_components = NULL;
10869 : 9669 : hash_set<tree_operand_hash> *shown_error = NULL;
10870 : :
10871 : 25160 : FOR_EACH_VEC_ELT (*groups, i, grp)
10872 : : {
10873 : 15491 : tree grp_end = grp->grp_end;
10874 : 15491 : tree decl = OMP_CLAUSE_DECL (grp_end);
10875 : :
10876 : 15491 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
10877 : :
10878 : 15491 : if (DECL_P (grp_end))
10879 : 14935 : continue;
10880 : :
10881 : 15491 : tree c = OMP_CLAUSE_DECL (*grp->grp_start);
10882 : 17205 : while (TREE_CODE (c) == ARRAY_REF)
10883 : 1714 : c = TREE_OPERAND (c, 0);
10884 : 15491 : if (TREE_CODE (c) != COMPONENT_REF)
10885 : 14935 : continue;
10886 : 556 : if (!seen_components)
10887 : 512 : seen_components = new hash_set<tree_operand_hash> ();
10888 : 556 : if (!shown_error)
10889 : 512 : shown_error = new hash_set<tree_operand_hash> ();
10890 : 556 : if (seen_components->contains (c)
10891 : 556 : && !shown_error->contains (c))
10892 : : {
10893 : 10 : error_at (OMP_CLAUSE_LOCATION (grp_end),
10894 : : "%qE appears more than once in map clauses",
10895 : 5 : OMP_CLAUSE_DECL (grp_end));
10896 : 5 : shown_error->add (c);
10897 : : }
10898 : : else
10899 : 551 : seen_components->add (c);
10900 : :
10901 : 556 : omp_mapping_group *struct_group;
10902 : 556 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
10903 : 556 : && *grp->grp_start == grp_end)
10904 : : {
10905 : 97 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
10906 : : struct_group, grp);
10907 : : /* Remove the whole of this mapping -- redundant. */
10908 : 97 : grp->deleted = true;
10909 : : }
10910 : : }
10911 : :
10912 : 9669 : if (seen_components)
10913 : 512 : delete seen_components;
10914 : 9669 : if (shown_error)
10915 : 512 : delete shown_error;
10916 : 9669 : }
10917 : :
10918 : : /* Link node NEWNODE so it is pointed to by chain INSERT_AT. NEWNODE's chain
10919 : : is linked to the previous node pointed to by INSERT_AT. */
10920 : :
10921 : : static tree *
10922 : 1032 : omp_siblist_insert_node_after (tree newnode, tree *insert_at)
10923 : : {
10924 : 1032 : OMP_CLAUSE_CHAIN (newnode) = *insert_at;
10925 : 1032 : *insert_at = newnode;
10926 : 1032 : return &OMP_CLAUSE_CHAIN (newnode);
10927 : : }
10928 : :
10929 : : /* Move NODE (which is currently pointed to by the chain OLD_POS) so it is
10930 : : pointed to by chain MOVE_AFTER instead. */
10931 : :
10932 : : static void
10933 : 795 : omp_siblist_move_node_after (tree node, tree *old_pos, tree *move_after)
10934 : : {
10935 : 795 : gcc_assert (node == *old_pos);
10936 : 795 : *old_pos = OMP_CLAUSE_CHAIN (node);
10937 : 795 : OMP_CLAUSE_CHAIN (node) = *move_after;
10938 : 795 : *move_after = node;
10939 : 795 : }
10940 : :
10941 : : /* Move nodes from FIRST_PTR (pointed to by previous node's chain) to
10942 : : LAST_NODE to after MOVE_AFTER chain. Similar to below function, but no
10943 : : new nodes are prepended to the list before splicing into the new position.
10944 : : Return the position we should continue scanning the list at, or NULL to
10945 : : stay where we were. */
10946 : :
10947 : : static tree *
10948 : 241 : omp_siblist_move_nodes_after (tree *first_ptr, tree last_node,
10949 : : tree *move_after)
10950 : : {
10951 : 241 : if (first_ptr == move_after)
10952 : : return NULL;
10953 : :
10954 : 228 : tree tmp = *first_ptr;
10955 : 228 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
10956 : 228 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
10957 : 228 : *move_after = tmp;
10958 : :
10959 : 228 : return first_ptr;
10960 : : }
10961 : :
10962 : : /* Concatenate two lists described by [FIRST_NEW, LAST_NEW_TAIL] and
10963 : : [FIRST_PTR, LAST_NODE], and insert them in the OMP clause list after chain
10964 : : pointer MOVE_AFTER.
10965 : :
10966 : : The latter list was previously part of the OMP clause list, and the former
10967 : : (prepended) part is comprised of new nodes.
10968 : :
10969 : : We start with a list of nodes starting with a struct mapping node. We
10970 : : rearrange the list so that new nodes starting from FIRST_NEW and whose last
10971 : : node's chain is LAST_NEW_TAIL comes directly after MOVE_AFTER, followed by
10972 : : the group of mapping nodes we are currently processing (from the chain
10973 : : FIRST_PTR to LAST_NODE). The return value is the pointer to the next chain
10974 : : we should continue processing from, or NULL to stay where we were.
10975 : :
10976 : : The transformation (in the case where MOVE_AFTER and FIRST_PTR are
10977 : : different) is worked through below. Here we are processing LAST_NODE, and
10978 : : FIRST_PTR points at the preceding mapping clause:
10979 : :
10980 : : #. mapping node chain
10981 : : ---------------------------------------------------
10982 : : A. struct_node [->B]
10983 : : B. comp_1 [->C]
10984 : : C. comp_2 [->D (move_after)]
10985 : : D. map_to_3 [->E]
10986 : : E. attach_3 [->F (first_ptr)]
10987 : : F. map_to_4 [->G (continue_at)]
10988 : : G. attach_4 (last_node) [->H]
10989 : : H. ...
10990 : :
10991 : : *last_new_tail = *first_ptr;
10992 : :
10993 : : I. new_node (first_new) [->F (last_new_tail)]
10994 : :
10995 : : *first_ptr = OMP_CLAUSE_CHAIN (last_node)
10996 : :
10997 : : #. mapping node chain
10998 : : ----------------------------------------------------
10999 : : A. struct_node [->B]
11000 : : B. comp_1 [->C]
11001 : : C. comp_2 [->D (move_after)]
11002 : : D. map_to_3 [->E]
11003 : : E. attach_3 [->H (first_ptr)]
11004 : : F. map_to_4 [->G (continue_at)]
11005 : : G. attach_4 (last_node) [->H]
11006 : : H. ...
11007 : :
11008 : : I. new_node (first_new) [->F (last_new_tail)]
11009 : :
11010 : : OMP_CLAUSE_CHAIN (last_node) = *move_after;
11011 : :
11012 : : #. mapping node chain
11013 : : ---------------------------------------------------
11014 : : A. struct_node [->B]
11015 : : B. comp_1 [->C]
11016 : : C. comp_2 [->D (move_after)]
11017 : : D. map_to_3 [->E]
11018 : : E. attach_3 [->H (continue_at)]
11019 : : F. map_to_4 [->G]
11020 : : G. attach_4 (last_node) [->D]
11021 : : H. ...
11022 : :
11023 : : I. new_node (first_new) [->F (last_new_tail)]
11024 : :
11025 : : *move_after = first_new;
11026 : :
11027 : : #. mapping node chain
11028 : : ---------------------------------------------------
11029 : : A. struct_node [->B]
11030 : : B. comp_1 [->C]
11031 : : C. comp_2 [->I (move_after)]
11032 : : D. map_to_3 [->E]
11033 : : E. attach_3 [->H (continue_at)]
11034 : : F. map_to_4 [->G]
11035 : : G. attach_4 (last_node) [->D]
11036 : : H. ...
11037 : : I. new_node (first_new) [->F (last_new_tail)]
11038 : :
11039 : : or, in order:
11040 : :
11041 : : #. mapping node chain
11042 : : ---------------------------------------------------
11043 : : A. struct_node [->B]
11044 : : B. comp_1 [->C]
11045 : : C. comp_2 [->I (move_after)]
11046 : : I. new_node (first_new) [->F (last_new_tail)]
11047 : : F. map_to_4 [->G]
11048 : : G. attach_4 (last_node) [->D]
11049 : : D. map_to_3 [->E]
11050 : : E. attach_3 [->H (continue_at)]
11051 : : H. ...
11052 : : */
11053 : :
11054 : : static tree *
11055 : 60 : omp_siblist_move_concat_nodes_after (tree first_new, tree *last_new_tail,
11056 : : tree *first_ptr, tree last_node,
11057 : : tree *move_after)
11058 : : {
11059 : 60 : tree *continue_at = NULL;
11060 : 60 : *last_new_tail = *first_ptr;
11061 : 60 : if (first_ptr == move_after)
11062 : 13 : *move_after = first_new;
11063 : : else
11064 : : {
11065 : 47 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
11066 : 47 : continue_at = first_ptr;
11067 : 47 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
11068 : 47 : *move_after = first_new;
11069 : : }
11070 : 60 : return continue_at;
11071 : : }
11072 : :
11073 : : static omp_addr_token *
11074 : 9599 : omp_first_chained_access_token (vec<omp_addr_token *> &addr_tokens)
11075 : : {
11076 : 9599 : using namespace omp_addr_tokenizer;
11077 : 9599 : int idx = addr_tokens.length () - 1;
11078 : 9599 : gcc_assert (idx >= 0);
11079 : 9599 : if (addr_tokens[idx]->type != ACCESS_METHOD)
11080 : : return addr_tokens[idx];
11081 : 9616 : while (idx > 0 && addr_tokens[idx - 1]->type == ACCESS_METHOD)
11082 : : idx--;
11083 : 9599 : return addr_tokens[idx];
11084 : : }
11085 : :
11086 : : /* Mapping struct members causes an additional set of nodes to be created,
11087 : : starting with GOMP_MAP_STRUCT followed by a number of mappings equal to the
11088 : : number of members being mapped, in order of ascending position (address or
11089 : : bitwise).
11090 : :
11091 : : We scan through the list of mapping clauses, calling this function for each
11092 : : struct member mapping we find, and build up the list of mappings after the
11093 : : initial GOMP_MAP_STRUCT node. For pointer members, these will be
11094 : : newly-created ALLOC nodes. For non-pointer members, the existing mapping is
11095 : : moved into place in the sorted list.
11096 : :
11097 : : struct {
11098 : : int *a;
11099 : : int *b;
11100 : : int c;
11101 : : int *d;
11102 : : };
11103 : :
11104 : : #pragma (acc|omp directive) copy(struct.a[0:n], struct.b[0:n], struct.c,
11105 : : struct.d[0:n])
11106 : :
11107 : : GOMP_MAP_STRUCT (4)
11108 : : [GOMP_MAP_FIRSTPRIVATE_REFERENCE -- for refs to structs]
11109 : : GOMP_MAP_ALLOC (struct.a)
11110 : : GOMP_MAP_ALLOC (struct.b)
11111 : : GOMP_MAP_TO (struct.c)
11112 : : GOMP_MAP_ALLOC (struct.d)
11113 : : ...
11114 : :
11115 : : In the case where we are mapping references to pointers, or in Fortran if
11116 : : we are mapping an array with a descriptor, additional nodes may be created
11117 : : after the struct node list also.
11118 : :
11119 : : The return code is either a pointer to the next node to process (if the
11120 : : list has been rearranged), else NULL to continue with the next node in the
11121 : : original list. */
11122 : :
11123 : : static tree *
11124 : 3827 : omp_accumulate_sibling_list (enum omp_region_type region_type,
11125 : : enum tree_code code,
11126 : : hash_map<tree_operand_hash, tree>
11127 : : *&struct_map_to_clause,
11128 : : hash_map<tree_operand_hash_no_se,
11129 : : omp_mapping_group *> *group_map,
11130 : : tree *grp_start_p, tree grp_end,
11131 : : vec<omp_addr_token *> &addr_tokens, tree **inner,
11132 : : bool *fragile_p, bool reprocessing_struct,
11133 : : tree **added_tail)
11134 : : {
11135 : 3827 : using namespace omp_addr_tokenizer;
11136 : 3827 : poly_offset_int coffset;
11137 : 3827 : poly_int64 cbitpos;
11138 : 3827 : tree ocd = OMP_CLAUSE_DECL (grp_end);
11139 : 3827 : bool openmp = !(region_type & ORT_ACC);
11140 : 3827 : bool target = (region_type & ORT_TARGET) != 0;
11141 : 3827 : tree *continue_at = NULL;
11142 : :
11143 : 4132 : while (TREE_CODE (ocd) == ARRAY_REF)
11144 : 305 : ocd = TREE_OPERAND (ocd, 0);
11145 : :
11146 : 3827 : if (*fragile_p)
11147 : : {
11148 : 142 : omp_mapping_group *to_group
11149 : 142 : = omp_get_nonfirstprivate_group (group_map, ocd, true);
11150 : :
11151 : 142 : if (to_group)
11152 : : return NULL;
11153 : : }
11154 : :
11155 : 3754 : omp_addr_token *last_token = omp_first_chained_access_token (addr_tokens);
11156 : 3754 : if (last_token->type == ACCESS_METHOD)
11157 : : {
11158 : 3754 : switch (last_token->u.access_kind)
11159 : : {
11160 : 735 : case ACCESS_REF:
11161 : 735 : case ACCESS_REF_TO_POINTER:
11162 : 735 : case ACCESS_REF_TO_POINTER_OFFSET:
11163 : 735 : case ACCESS_INDEXED_REF_TO_ARRAY:
11164 : : /* We may see either a bare reference or a dereferenced
11165 : : "convert_from_reference"-like one here. Handle either way. */
11166 : 735 : if (TREE_CODE (ocd) == INDIRECT_REF)
11167 : 64 : ocd = TREE_OPERAND (ocd, 0);
11168 : 735 : gcc_assert (TREE_CODE (TREE_TYPE (ocd)) == REFERENCE_TYPE);
11169 : : break;
11170 : :
11171 : : default:
11172 : : ;
11173 : : }
11174 : : }
11175 : :
11176 : 3754 : bool variable_offset;
11177 : 3754 : tree base
11178 : 3754 : = extract_base_bit_offset (ocd, &cbitpos, &coffset, &variable_offset);
11179 : :
11180 : 3754 : int base_token;
11181 : 18942 : for (base_token = addr_tokens.length () - 1; base_token >= 0; base_token--)
11182 : : {
11183 : 15188 : if (addr_tokens[base_token]->type == ARRAY_BASE
11184 : 15188 : || addr_tokens[base_token]->type == STRUCTURE_BASE)
11185 : : break;
11186 : : }
11187 : :
11188 : : /* The two expressions in the assertion below aren't quite the same: if we
11189 : : have 'struct_base_decl access_indexed_array' for something like
11190 : : "myvar[2].x" then base will be "myvar" and addr_tokens[base_token]->expr
11191 : : will be "myvar[2]" -- the actual base of the structure.
11192 : : The former interpretation leads to a strange situation where we get
11193 : : struct(myvar) alloc(myvar[2].ptr1)
11194 : : That is, the array of structures is kind of treated as one big structure
11195 : : for the purposes of gathering sibling lists, etc. */
11196 : : /* gcc_assert (base == addr_tokens[base_token]->expr); */
11197 : :
11198 : 3754 : bool attach_detach = ((OMP_CLAUSE_MAP_KIND (grp_end)
11199 : : == GOMP_MAP_ATTACH_DETACH)
11200 : 3754 : || (OMP_CLAUSE_MAP_KIND (grp_end)
11201 : 3754 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
11202 : 3754 : bool has_descriptor = false;
11203 : 3754 : if (OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
11204 : : {
11205 : 2314 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
11206 : 2314 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
11207 : : has_descriptor = true;
11208 : : }
11209 : :
11210 : 3754 : if (!struct_map_to_clause || struct_map_to_clause->get (base) == NULL)
11211 : : {
11212 : 2585 : enum gomp_map_kind str_kind = GOMP_MAP_STRUCT;
11213 : :
11214 : 2585 : if (struct_map_to_clause == NULL)
11215 : 2188 : struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
11216 : :
11217 : 2585 : if (variable_offset)
11218 : 108 : str_kind = GOMP_MAP_STRUCT_UNORD;
11219 : :
11220 : 2585 : tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
11221 : :
11222 : 2585 : OMP_CLAUSE_SET_MAP_KIND (l, str_kind);
11223 : 2585 : OMP_CLAUSE_DECL (l) = unshare_expr (base);
11224 : 2585 : OMP_CLAUSE_SIZE (l) = size_int (1);
11225 : :
11226 : 2585 : struct_map_to_clause->put (base, l);
11227 : :
11228 : : /* On first iterating through the clause list, we insert the struct node
11229 : : just before the component access node that triggers the initial
11230 : : omp_accumulate_sibling_list call for a particular sibling list (and
11231 : : it then forms the first entry in that list). When reprocessing
11232 : : struct bases that are themselves component accesses, we insert the
11233 : : struct node on an off-side list to avoid inserting the new
11234 : : GOMP_MAP_STRUCT into the middle of the old one. */
11235 : 2585 : tree *insert_node_pos = reprocessing_struct ? *added_tail : grp_start_p;
11236 : :
11237 : 2585 : if (has_descriptor)
11238 : : {
11239 : 463 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
11240 : 463 : if (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
11241 : 93 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
11242 : 463 : tree sc = *insert_node_pos;
11243 : 463 : OMP_CLAUSE_CHAIN (l) = desc;
11244 : 463 : OMP_CLAUSE_CHAIN (*grp_start_p) = OMP_CLAUSE_CHAIN (desc);
11245 : 463 : OMP_CLAUSE_CHAIN (desc) = sc;
11246 : 463 : *insert_node_pos = l;
11247 : : }
11248 : 2122 : else if (attach_detach)
11249 : : {
11250 : 1307 : tree extra_node;
11251 : 1307 : tree alloc_node
11252 : 1307 : = build_omp_struct_comp_nodes (code, *grp_start_p, grp_end,
11253 : : &extra_node);
11254 : 1307 : tree *tail;
11255 : 1307 : OMP_CLAUSE_CHAIN (l) = alloc_node;
11256 : :
11257 : 1307 : if (extra_node)
11258 : : {
11259 : 0 : OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos;
11260 : 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
11261 : 0 : tail = &OMP_CLAUSE_CHAIN (extra_node);
11262 : : }
11263 : : else
11264 : : {
11265 : 1307 : OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
11266 : 1307 : tail = &OMP_CLAUSE_CHAIN (alloc_node);
11267 : : }
11268 : :
11269 : : /* For OpenMP semantics, we don't want to implicitly allocate
11270 : : space for the pointer here for non-compute regions (e.g. "enter
11271 : : data"). A FRAGILE_P node is only being created so that
11272 : : omp-low.cc is able to rewrite the struct properly.
11273 : : For references (to pointers), we want to actually allocate the
11274 : : space for the reference itself in the sorted list following the
11275 : : struct node.
11276 : : For pointers, we want to allocate space if we had an explicit
11277 : : mapping of the attachment point, but not otherwise. */
11278 : 1307 : if (*fragile_p
11279 : 1307 : || (openmp
11280 : : && !target
11281 : : && attach_detach
11282 : 212 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
11283 : 66 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
11284 : : {
11285 : 110 : if (!lang_GNU_Fortran ())
11286 : : /* In Fortran, pointers are dereferenced automatically, but may
11287 : : be unassociated. So we still want to allocate space for the
11288 : : pointer (as the base for an attach operation that should be
11289 : : present in the same directive's clause list also). */
11290 : 98 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
11291 : 110 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
11292 : : }
11293 : :
11294 : 1307 : *insert_node_pos = l;
11295 : :
11296 : 1307 : if (reprocessing_struct)
11297 : : {
11298 : : /* When reprocessing a struct node group used as the base of a
11299 : : subcomponent access, if we have a reference-to-pointer base,
11300 : : we will see:
11301 : : struct(**ptr) attach(*ptr)
11302 : : whereas for a non-reprocess-struct group, we see, e.g.:
11303 : : tofrom(**ptr) attach(*ptr) attach(ptr)
11304 : : and we create the "alloc" for the second "attach", i.e.
11305 : : for the reference itself. When reprocessing a struct group we
11306 : : thus change the pointer attachment into a reference attachment
11307 : : by stripping the indirection. (The attachment of the
11308 : : referenced pointer must happen elsewhere, either on the same
11309 : : directive, or otherwise.) */
11310 : 181 : tree adecl = OMP_CLAUSE_DECL (alloc_node);
11311 : :
11312 : 181 : if ((TREE_CODE (adecl) == INDIRECT_REF
11313 : 149 : || (TREE_CODE (adecl) == MEM_REF
11314 : 0 : && integer_zerop (TREE_OPERAND (adecl, 1))))
11315 : 32 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (adecl, 0)))
11316 : : == REFERENCE_TYPE)
11317 : 213 : && (TREE_CODE (TREE_TYPE (TREE_TYPE
11318 : : (TREE_OPERAND (adecl, 0)))) == POINTER_TYPE))
11319 : 32 : OMP_CLAUSE_DECL (alloc_node) = TREE_OPERAND (adecl, 0);
11320 : :
11321 : 181 : *added_tail = tail;
11322 : : }
11323 : : }
11324 : : else
11325 : : {
11326 : 815 : gcc_assert (*grp_start_p == grp_end);
11327 : 815 : if (reprocessing_struct)
11328 : : {
11329 : : /* If we don't have an attach/detach node, this is a
11330 : : "target data" directive or similar, not an offload region.
11331 : : Synthesize an "alloc" node using just the initiating
11332 : : GOMP_MAP_STRUCT decl. */
11333 : 64 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
11334 : 32 : || code == OACC_EXIT_DATA)
11335 : 32 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
11336 : 32 : tree alloc_node
11337 : 32 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
11338 : : OMP_CLAUSE_MAP);
11339 : 32 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
11340 : 32 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
11341 : 64 : OMP_CLAUSE_SIZE (alloc_node)
11342 : 32 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
11343 : :
11344 : 32 : OMP_CLAUSE_CHAIN (alloc_node) = OMP_CLAUSE_CHAIN (l);
11345 : 32 : OMP_CLAUSE_CHAIN (l) = alloc_node;
11346 : 32 : *insert_node_pos = l;
11347 : 32 : *added_tail = &OMP_CLAUSE_CHAIN (alloc_node);
11348 : : }
11349 : : else
11350 : 783 : grp_start_p = omp_siblist_insert_node_after (l, insert_node_pos);
11351 : : }
11352 : :
11353 : 2585 : unsigned last_access = base_token + 1;
11354 : :
11355 : 2585 : while (last_access + 1 < addr_tokens.length ()
11356 : 2753 : && addr_tokens[last_access + 1]->type == ACCESS_METHOD)
11357 : : last_access++;
11358 : :
11359 : 2585 : if ((region_type & ORT_TARGET)
11360 : 2585 : && addr_tokens[base_token + 1]->type == ACCESS_METHOD)
11361 : : {
11362 : 1550 : bool base_ref = false;
11363 : 1550 : access_method_kinds access_kind
11364 : 1550 : = addr_tokens[last_access]->u.access_kind;
11365 : :
11366 : 1550 : switch (access_kind)
11367 : : {
11368 : : case ACCESS_DIRECT:
11369 : : case ACCESS_INDEXED_ARRAY:
11370 : 910 : return NULL;
11371 : :
11372 : 401 : case ACCESS_REF:
11373 : 401 : case ACCESS_REF_TO_POINTER:
11374 : 401 : case ACCESS_REF_TO_POINTER_OFFSET:
11375 : 401 : case ACCESS_INDEXED_REF_TO_ARRAY:
11376 : 401 : base_ref = true;
11377 : 401 : break;
11378 : :
11379 : 844 : default:
11380 : 844 : ;
11381 : : }
11382 : 844 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
11383 : : OMP_CLAUSE_MAP);
11384 : 844 : enum gomp_map_kind mkind;
11385 : 844 : omp_mapping_group *decl_group;
11386 : 844 : tree use_base;
11387 : 844 : switch (access_kind)
11388 : : {
11389 : 443 : case ACCESS_POINTER:
11390 : 443 : case ACCESS_POINTER_OFFSET:
11391 : 443 : use_base = addr_tokens[last_access]->expr;
11392 : 443 : break;
11393 : 198 : case ACCESS_REF_TO_POINTER:
11394 : 198 : case ACCESS_REF_TO_POINTER_OFFSET:
11395 : 198 : use_base
11396 : 198 : = build_fold_indirect_ref (addr_tokens[last_access]->expr);
11397 : 198 : break;
11398 : 203 : default:
11399 : 203 : use_base = addr_tokens[base_token]->expr;
11400 : : }
11401 : 844 : bool mapped_to_p
11402 : 844 : = omp_directive_maps_explicitly (group_map, use_base, &decl_group,
11403 : : true, false, true);
11404 : 844 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
11405 : 844 : && DECL_P (addr_tokens[last_access]->expr)
11406 : 1342 : && !mapped_to_p)
11407 : 442 : mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
11408 : : : GOMP_MAP_FIRSTPRIVATE_POINTER;
11409 : : else
11410 : : mkind = GOMP_MAP_ATTACH_DETACH;
11411 : :
11412 : 844 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
11413 : : /* If we have a reference to pointer base, we want to attach the
11414 : : pointer here, not the reference. The reference attachment happens
11415 : : elsewhere. */
11416 : 844 : bool ref_to_ptr
11417 : 844 : = (access_kind == ACCESS_REF_TO_POINTER
11418 : 844 : || access_kind == ACCESS_REF_TO_POINTER_OFFSET);
11419 : 844 : tree sdecl = addr_tokens[last_access]->expr;
11420 : 844 : tree sdecl_ptr = ref_to_ptr ? build_fold_indirect_ref (sdecl)
11421 : 844 : : sdecl;
11422 : : /* For the FIRSTPRIVATE_REFERENCE after the struct node, we
11423 : : want to use the reference itself for the decl, but we
11424 : : still want to use the pointer to calculate the bias. */
11425 : 844 : OMP_CLAUSE_DECL (c2) = (mkind == GOMP_MAP_ATTACH_DETACH)
11426 : 844 : ? sdecl_ptr : sdecl;
11427 : 844 : sdecl = sdecl_ptr;
11428 : 844 : tree baddr = build_fold_addr_expr (base);
11429 : 844 : baddr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
11430 : : ptrdiff_type_node, baddr);
11431 : 844 : tree decladdr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
11432 : : ptrdiff_type_node, sdecl);
11433 : 844 : OMP_CLAUSE_SIZE (c2)
11434 : 844 : = fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR,
11435 : : ptrdiff_type_node, baddr, decladdr);
11436 : : /* Insert after struct node. */
11437 : 844 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
11438 : 844 : OMP_CLAUSE_CHAIN (l) = c2;
11439 : :
11440 : 844 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
11441 : 844 : && (addr_tokens[base_token]->u.structure_base_kind
11442 : : == BASE_COMPONENT_EXPR)
11443 : 272 : && mkind == GOMP_MAP_ATTACH_DETACH
11444 : 1116 : && addr_tokens[last_access]->u.access_kind != ACCESS_REF)
11445 : : {
11446 : 204 : *inner = insert_node_pos;
11447 : 204 : if (openmp)
11448 : 152 : *fragile_p = true;
11449 : 204 : return NULL;
11450 : : }
11451 : : }
11452 : :
11453 : 1675 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
11454 : 1675 : && (addr_tokens[base_token]->u.structure_base_kind
11455 : : == BASE_COMPONENT_EXPR)
11456 : 1992 : && addr_tokens[last_access]->u.access_kind == ACCESS_REF)
11457 : 100 : *inner = insert_node_pos;
11458 : :
11459 : 1675 : return NULL;
11460 : : }
11461 : 1169 : else if (struct_map_to_clause)
11462 : : {
11463 : 1169 : tree *osc = struct_map_to_clause->get (base);
11464 : 1169 : tree *sc = NULL, *scp = NULL;
11465 : 1169 : bool unordered = false;
11466 : :
11467 : 1169 : if (osc && OMP_CLAUSE_MAP_KIND (*osc) == GOMP_MAP_STRUCT_UNORD)
11468 : : unordered = true;
11469 : :
11470 : 1169 : unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
11471 : 1169 : sc = &OMP_CLAUSE_CHAIN (*osc);
11472 : : /* The struct mapping might be immediately followed by a
11473 : : FIRSTPRIVATE_POINTER, FIRSTPRIVATE_REFERENCE or an ATTACH_DETACH --
11474 : : if it's an indirect access or a reference, or if the structure base
11475 : : is not a decl. The FIRSTPRIVATE_* nodes are removed in omp-low.cc
11476 : : after they have been processed there, and ATTACH_DETACH nodes are
11477 : : recomputed and moved out of the GOMP_MAP_STRUCT construct once
11478 : : sibling list building is complete. */
11479 : 1169 : if (OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_POINTER
11480 : 1123 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11481 : 2247 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_ATTACH_DETACH)
11482 : 190 : sc = &OMP_CLAUSE_CHAIN (*sc);
11483 : 3224 : for (i = 0; i < elems; i++, sc = &OMP_CLAUSE_CHAIN (*sc))
11484 : 2453 : if (attach_detach && sc == grp_start_p)
11485 : : break;
11486 : 2453 : else if (TREE_CODE (OMP_CLAUSE_DECL (*sc)) != COMPONENT_REF
11487 : 182 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != INDIRECT_REF
11488 : 2635 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != ARRAY_REF)
11489 : : break;
11490 : : else
11491 : : {
11492 : 2453 : tree sc_decl = OMP_CLAUSE_DECL (*sc);
11493 : 2453 : poly_offset_int offset;
11494 : 2453 : poly_int64 bitpos;
11495 : :
11496 : 2453 : if (TREE_CODE (sc_decl) == ARRAY_REF)
11497 : : {
11498 : 364 : while (TREE_CODE (sc_decl) == ARRAY_REF)
11499 : 182 : sc_decl = TREE_OPERAND (sc_decl, 0);
11500 : 182 : if (TREE_CODE (sc_decl) != COMPONENT_REF
11501 : 182 : || TREE_CODE (TREE_TYPE (sc_decl)) != ARRAY_TYPE)
11502 : : break;
11503 : : }
11504 : 2271 : else if (INDIRECT_REF_P (sc_decl)
11505 : 0 : && TREE_CODE (TREE_OPERAND (sc_decl, 0)) == COMPONENT_REF
11506 : 2271 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (sc_decl, 0)))
11507 : : == REFERENCE_TYPE))
11508 : 0 : sc_decl = TREE_OPERAND (sc_decl, 0);
11509 : :
11510 : 2453 : bool variable_offset2;
11511 : 2453 : tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset,
11512 : : &variable_offset2);
11513 : 2453 : if (!base2 || !operand_equal_p (base2, base, 0))
11514 : : break;
11515 : 2453 : if (scp)
11516 : 218 : continue;
11517 : 2235 : if (variable_offset2)
11518 : : {
11519 : 48 : OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
11520 : 48 : unordered = true;
11521 : 48 : break;
11522 : : }
11523 : 2187 : else if ((region_type & ORT_ACC) != 0)
11524 : : {
11525 : : /* For OpenACC, allow (ignore) duplicate struct accesses in
11526 : : the middle of a mapping clause, e.g. "mystruct->foo" in:
11527 : : copy(mystruct->foo->bar) copy(mystruct->foo->qux). */
11528 : 229 : if (reprocessing_struct
11529 : 8 : && known_eq (coffset, offset)
11530 : 229 : && known_eq (cbitpos, bitpos))
11531 : 25 : return NULL;
11532 : : }
11533 : 1958 : else if (known_eq (coffset, offset)
11534 : 1958 : && known_eq (cbitpos, bitpos))
11535 : : {
11536 : : /* Having two struct members at the same offset doesn't work,
11537 : : so make sure we don't. (We're allowed to ignore this.
11538 : : Should we report the error?) */
11539 : : /*error_at (OMP_CLAUSE_LOCATION (grp_end),
11540 : : "duplicate struct member %qE in map clauses",
11541 : : OMP_CLAUSE_DECL (grp_end));*/
11542 : : return NULL;
11543 : : }
11544 : 2162 : if (maybe_lt (coffset, offset)
11545 : 3746 : || (known_eq (coffset, offset)
11546 : 2 : && maybe_lt (cbitpos, bitpos)))
11547 : : {
11548 : 578 : if (attach_detach)
11549 : : scp = sc;
11550 : : else
11551 : : break;
11552 : : }
11553 : : }
11554 : :
11555 : : /* If this is an unordered struct, just insert the new element at the
11556 : : end of the list. */
11557 : 1144 : if (unordered)
11558 : : {
11559 : 102 : for (; i < elems; i++)
11560 : 54 : sc = &OMP_CLAUSE_CHAIN (*sc);
11561 : : scp = NULL;
11562 : : }
11563 : :
11564 : 1144 : OMP_CLAUSE_SIZE (*osc)
11565 : 1144 : = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
11566 : :
11567 : 1144 : if (reprocessing_struct)
11568 : : {
11569 : : /* If we're reprocessing a struct node, we don't want to do most of
11570 : : the list manipulation below. We only need to handle the (pointer
11571 : : or reference) attach/detach case. */
11572 : 8 : tree extra_node, alloc_node;
11573 : 8 : if (has_descriptor)
11574 : 0 : gcc_unreachable ();
11575 : 8 : else if (attach_detach)
11576 : 8 : alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
11577 : : grp_end, &extra_node);
11578 : : else
11579 : : {
11580 : : /* If we don't have an attach/detach node, this is a
11581 : : "target data" directive or similar, not an offload region.
11582 : : Synthesize an "alloc" node using just the initiating
11583 : : GOMP_MAP_STRUCT decl. */
11584 : 0 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
11585 : 0 : || code == OACC_EXIT_DATA)
11586 : 0 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
11587 : 0 : alloc_node
11588 : 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
11589 : : OMP_CLAUSE_MAP);
11590 : 0 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
11591 : 0 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
11592 : 0 : OMP_CLAUSE_SIZE (alloc_node)
11593 : 0 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
11594 : : }
11595 : :
11596 : 8 : if (scp)
11597 : 0 : omp_siblist_insert_node_after (alloc_node, scp);
11598 : : else
11599 : : {
11600 : 8 : tree *new_end = omp_siblist_insert_node_after (alloc_node, sc);
11601 : 8 : if (sc == *added_tail)
11602 : 8 : *added_tail = new_end;
11603 : : }
11604 : :
11605 : 8 : return NULL;
11606 : : }
11607 : :
11608 : 1136 : if (has_descriptor)
11609 : : {
11610 : 315 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
11611 : 315 : if (code == OMP_TARGET_EXIT_DATA
11612 : 315 : || code == OACC_EXIT_DATA)
11613 : 19 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
11614 : 630 : omp_siblist_move_node_after (desc,
11615 : 315 : &OMP_CLAUSE_CHAIN (*grp_start_p),
11616 : : scp ? scp : sc);
11617 : : }
11618 : 821 : else if (attach_detach)
11619 : : {
11620 : 301 : tree cl = NULL_TREE, extra_node;
11621 : 301 : tree alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
11622 : : grp_end, &extra_node);
11623 : 301 : tree *tail_chain = NULL;
11624 : :
11625 : 301 : if (*fragile_p
11626 : 301 : || (openmp
11627 : : && !target
11628 : : && attach_detach
11629 : 56 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
11630 : 17 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
11631 : : {
11632 : 0 : if (!lang_GNU_Fortran ())
11633 : 0 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
11634 : 0 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
11635 : : }
11636 : :
11637 : : /* Here, we have:
11638 : :
11639 : : grp_end : the last (or only) node in this group.
11640 : : grp_start_p : pointer to the first node in a pointer mapping group
11641 : : up to and including GRP_END.
11642 : : sc : pointer to the chain for the end of the struct component
11643 : : list.
11644 : : scp : pointer to the chain for the sorted position at which we
11645 : : should insert in the middle of the struct component list
11646 : : (else NULL to insert at end).
11647 : : alloc_node : the "alloc" node for the structure (pointer-type)
11648 : : component. We insert at SCP (if present), else SC
11649 : : (the end of the struct component list).
11650 : : extra_node : a newly-synthesized node for an additional indirect
11651 : : pointer mapping or a Fortran pointer set, if needed.
11652 : : cl : first node to prepend before grp_start_p.
11653 : : tail_chain : pointer to chain of last prepended node.
11654 : :
11655 : : The general idea is we move the nodes for this struct mapping
11656 : : together: the alloc node goes into the sorted list directly after
11657 : : the struct mapping, and any extra nodes (together with the nodes
11658 : : mapping arrays pointed to by struct components) get moved after
11659 : : that list. When SCP is NULL, we insert the nodes at SC, i.e. at
11660 : : the end of the struct component mapping list. It's important that
11661 : : the alloc_node comes first in that case because it's part of the
11662 : : sorted component mapping list (but subsequent nodes are not!). */
11663 : :
11664 : 301 : if (scp)
11665 : 241 : omp_siblist_insert_node_after (alloc_node, scp);
11666 : :
11667 : : /* Make [cl,tail_chain] a list of the alloc node (if we haven't
11668 : : already inserted it) and the extra_node (if it is present). The
11669 : : list can be empty if we added alloc_node above and there is no
11670 : : extra node. */
11671 : 241 : if (scp && extra_node)
11672 : : {
11673 : 0 : cl = extra_node;
11674 : 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
11675 : : }
11676 : 301 : else if (extra_node)
11677 : : {
11678 : 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
11679 : 0 : cl = alloc_node;
11680 : 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
11681 : : }
11682 : 301 : else if (!scp)
11683 : : {
11684 : 60 : cl = alloc_node;
11685 : 60 : tail_chain = &OMP_CLAUSE_CHAIN (alloc_node);
11686 : : }
11687 : :
11688 : 301 : continue_at
11689 : 301 : = cl ? omp_siblist_move_concat_nodes_after (cl, tail_chain,
11690 : : grp_start_p, grp_end,
11691 : : sc)
11692 : 241 : : omp_siblist_move_nodes_after (grp_start_p, grp_end, sc);
11693 : : }
11694 : 520 : else if (*sc != grp_end)
11695 : : {
11696 : 480 : gcc_assert (*grp_start_p == grp_end);
11697 : :
11698 : : /* We are moving the current node back to a previous struct node:
11699 : : the node that used to point to the current node will now point to
11700 : : the next node. */
11701 : 480 : continue_at = grp_start_p;
11702 : : /* In the non-pointer case, the mapping clause itself is moved into
11703 : : the correct position in the struct component list, which in this
11704 : : case is just SC. */
11705 : 480 : omp_siblist_move_node_after (*grp_start_p, grp_start_p, sc);
11706 : : }
11707 : : }
11708 : : return continue_at;
11709 : : }
11710 : :
11711 : : /* Scan through GROUPS, and create sorted structure sibling lists without
11712 : : gimplifying. */
11713 : :
11714 : : static bool
11715 : 16957 : omp_build_struct_sibling_lists (enum tree_code code,
11716 : : enum omp_region_type region_type,
11717 : : vec<omp_mapping_group> *groups,
11718 : : hash_map<tree_operand_hash_no_se,
11719 : : omp_mapping_group *> **grpmap,
11720 : : tree *list_p)
11721 : : {
11722 : 16957 : using namespace omp_addr_tokenizer;
11723 : 16957 : unsigned i;
11724 : 16957 : omp_mapping_group *grp;
11725 : 16957 : hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
11726 : 16957 : bool success = true;
11727 : 16957 : tree *new_next = NULL;
11728 : 33914 : tree *tail = &OMP_CLAUSE_CHAIN ((*groups)[groups->length () - 1].grp_end);
11729 : 16957 : tree added_nodes = NULL_TREE;
11730 : 16957 : tree *added_tail = &added_nodes;
11731 : 16957 : auto_vec<omp_mapping_group> pre_hwm_groups;
11732 : :
11733 : 63132 : FOR_EACH_VEC_ELT (*groups, i, grp)
11734 : : {
11735 : 29218 : tree c = grp->grp_end;
11736 : 29218 : tree decl = OMP_CLAUSE_DECL (c);
11737 : 29218 : tree grp_end = grp->grp_end;
11738 : 29218 : auto_vec<omp_addr_token *> addr_tokens;
11739 : 29218 : tree sentinel = OMP_CLAUSE_CHAIN (grp_end);
11740 : :
11741 : 29218 : if (new_next && !grp->reprocess_struct)
11742 : 472 : grp->grp_start = new_next;
11743 : :
11744 : 29218 : new_next = NULL;
11745 : :
11746 : 29218 : tree *grp_start_p = grp->grp_start;
11747 : :
11748 : 29218 : if (DECL_P (decl))
11749 : 20207 : continue;
11750 : :
11751 : : /* Skip groups we marked for deletion in
11752 : : {omp,oacc}_resolve_clause_dependencies. */
11753 : 9011 : if (grp->deleted)
11754 : 417 : continue;
11755 : :
11756 : 8594 : if (OMP_CLAUSE_CHAIN (*grp_start_p)
11757 : 8594 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
11758 : : {
11759 : : /* Don't process an array descriptor that isn't inside a derived type
11760 : : as a struct (the GOMP_MAP_POINTER following will have the form
11761 : : "var.data", but such mappings are handled specially). */
11762 : 5264 : tree grpmid = OMP_CLAUSE_CHAIN (*grp_start_p);
11763 : 5264 : if (omp_map_clause_descriptor_p (grpmid)
11764 : 8838 : && DECL_P (OMP_CLAUSE_DECL (grpmid)))
11765 : 2749 : continue;
11766 : : }
11767 : :
11768 : : tree expr = decl;
11769 : :
11770 : 6881 : while (TREE_CODE (expr) == ARRAY_REF)
11771 : 1036 : expr = TREE_OPERAND (expr, 0);
11772 : :
11773 : 5845 : if (!omp_parse_expr (addr_tokens, expr))
11774 : 0 : continue;
11775 : :
11776 : 5845 : omp_addr_token *last_token
11777 : 5845 : = omp_first_chained_access_token (addr_tokens);
11778 : :
11779 : : /* A mapping of a reference to a pointer member that doesn't specify an
11780 : : array section, etc., like this:
11781 : : *mystruct.ref_to_ptr
11782 : : should not be processed by the struct sibling-list handling code --
11783 : : it just transfers the referenced pointer.
11784 : :
11785 : : In contrast, the quite similar-looking construct:
11786 : : *mystruct.ptr
11787 : : which is equivalent to e.g.
11788 : : mystruct.ptr[0]
11789 : : *does* trigger sibling-list processing.
11790 : :
11791 : : An exception for the former case is for "fragile" groups where the
11792 : : reference itself is not handled otherwise; this is subject to special
11793 : : handling in omp_accumulate_sibling_list also. */
11794 : :
11795 : 5845 : if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
11796 : 2672 : && last_token->type == ACCESS_METHOD
11797 : 2672 : && last_token->u.access_kind == ACCESS_REF
11798 : 6131 : && !grp->fragile)
11799 : 221 : continue;
11800 : :
11801 : 5624 : tree d = decl;
11802 : 5624 : if (TREE_CODE (d) == ARRAY_REF)
11803 : : {
11804 : 2017 : while (TREE_CODE (d) == ARRAY_REF)
11805 : 1019 : d = TREE_OPERAND (d, 0);
11806 : 998 : if (TREE_CODE (d) == COMPONENT_REF
11807 : 998 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
11808 : : decl = d;
11809 : : }
11810 : 5624 : if (d == decl
11811 : 4933 : && INDIRECT_REF_P (decl)
11812 : 670 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
11813 : 105 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
11814 : : == REFERENCE_TYPE)
11815 : 5721 : && (OMP_CLAUSE_MAP_KIND (c)
11816 : : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
11817 : 97 : decl = TREE_OPERAND (decl, 0);
11818 : :
11819 : 5624 : STRIP_NOPS (decl);
11820 : :
11821 : 5624 : if (TREE_CODE (decl) != COMPONENT_REF)
11822 : 1300 : continue;
11823 : :
11824 : : /* If we're mapping the whole struct in another node, skip adding this
11825 : : node to a sibling list. */
11826 : 4324 : omp_mapping_group *wholestruct;
11827 : 4324 : if (omp_mapped_by_containing_struct (*grpmap, OMP_CLAUSE_DECL (c),
11828 : : &wholestruct))
11829 : 122 : continue;
11830 : :
11831 : 4202 : if (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
11832 : 4202 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
11833 : 4089 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
11834 : : && code != OACC_UPDATE
11835 : 8220 : && code != OMP_TARGET_UPDATE)
11836 : : {
11837 : 3827 : if (error_operand_p (decl))
11838 : : {
11839 : 0 : success = false;
11840 : 0 : goto error_out;
11841 : : }
11842 : :
11843 : 3827 : tree stype = TREE_TYPE (decl);
11844 : 3827 : if (TREE_CODE (stype) == REFERENCE_TYPE)
11845 : 768 : stype = TREE_TYPE (stype);
11846 : 3827 : if (TYPE_SIZE_UNIT (stype) == NULL
11847 : 3827 : || TREE_CODE (TYPE_SIZE_UNIT (stype)) != INTEGER_CST)
11848 : : {
11849 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
11850 : : "mapping field %qE of variable length "
11851 : 0 : "structure", OMP_CLAUSE_DECL (c));
11852 : 0 : success = false;
11853 : 0 : goto error_out;
11854 : : }
11855 : :
11856 : 3827 : tree *inner = NULL;
11857 : 3827 : bool fragile_p = grp->fragile;
11858 : :
11859 : 3827 : new_next
11860 : 7654 : = omp_accumulate_sibling_list (region_type, code,
11861 : : struct_map_to_clause, *grpmap,
11862 : : grp_start_p, grp_end, addr_tokens,
11863 : : &inner, &fragile_p,
11864 : 3827 : grp->reprocess_struct, &added_tail);
11865 : :
11866 : 3827 : if (inner)
11867 : : {
11868 : 304 : omp_mapping_group newgrp;
11869 : 304 : newgrp.grp_start = inner;
11870 : 304 : if (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (*inner))
11871 : : == GOMP_MAP_ATTACH_DETACH)
11872 : 272 : newgrp.grp_end = OMP_CLAUSE_CHAIN (*inner);
11873 : : else
11874 : 32 : newgrp.grp_end = *inner;
11875 : 304 : newgrp.mark = UNVISITED;
11876 : 304 : newgrp.sibling = NULL;
11877 : 304 : newgrp.deleted = false;
11878 : 304 : newgrp.reprocess_struct = true;
11879 : 304 : newgrp.fragile = fragile_p;
11880 : 304 : newgrp.next = NULL;
11881 : 304 : groups->safe_push (newgrp);
11882 : :
11883 : : /* !!! Growing GROUPS might invalidate the pointers in the group
11884 : : map. Rebuild it here. This is a bit inefficient, but
11885 : : shouldn't happen very often. */
11886 : 608 : delete (*grpmap);
11887 : 304 : *grpmap
11888 : 304 : = omp_reindex_mapping_groups (list_p, groups, &pre_hwm_groups,
11889 : : sentinel);
11890 : : }
11891 : : }
11892 : 29218 : }
11893 : :
11894 : : /* Delete groups marked for deletion above. At this point the order of the
11895 : : groups may no longer correspond to the order of the underlying list,
11896 : : which complicates this a little. First clear out OMP_CLAUSE_DECL for
11897 : : deleted nodes... */
11898 : :
11899 : 46175 : FOR_EACH_VEC_ELT (*groups, i, grp)
11900 : 29218 : if (grp->deleted)
11901 : 417 : for (tree d = *grp->grp_start;
11902 : 834 : d != OMP_CLAUSE_CHAIN (grp->grp_end);
11903 : 417 : d = OMP_CLAUSE_CHAIN (d))
11904 : 417 : OMP_CLAUSE_DECL (d) = NULL_TREE;
11905 : :
11906 : : /* ...then sweep through the list removing the now-empty nodes. */
11907 : :
11908 : : tail = list_p;
11909 : 89411 : while (*tail)
11910 : : {
11911 : 72454 : if (OMP_CLAUSE_CODE (*tail) == OMP_CLAUSE_MAP
11912 : 72454 : && OMP_CLAUSE_DECL (*tail) == NULL_TREE)
11913 : 417 : *tail = OMP_CLAUSE_CHAIN (*tail);
11914 : : else
11915 : 72037 : tail = &OMP_CLAUSE_CHAIN (*tail);
11916 : : }
11917 : :
11918 : : /* Tack on the struct nodes added during nested struct reprocessing. */
11919 : 16957 : if (added_nodes)
11920 : : {
11921 : 193 : *tail = added_nodes;
11922 : 193 : tail = added_tail;
11923 : : }
11924 : :
11925 : : /* Now we have finished building the struct sibling lists, reprocess
11926 : : newly-added "attach" nodes: we need the address of the first
11927 : : mapped element of each struct sibling list for the bias of the attach
11928 : : operation -- not necessarily the base address of the whole struct. */
11929 : 16957 : if (struct_map_to_clause)
11930 : 4773 : for (hash_map<tree_operand_hash, tree>::iterator iter
11931 : 2188 : = struct_map_to_clause->begin ();
11932 : 6961 : iter != struct_map_to_clause->end ();
11933 : 2585 : ++iter)
11934 : : {
11935 : 2585 : tree struct_node = (*iter).second;
11936 : 2585 : gcc_assert (OMP_CLAUSE_CODE (struct_node) == OMP_CLAUSE_MAP);
11937 : 2585 : tree attach = OMP_CLAUSE_CHAIN (struct_node);
11938 : :
11939 : 2585 : if (OMP_CLAUSE_CODE (attach) != OMP_CLAUSE_MAP
11940 : 2585 : || OMP_CLAUSE_MAP_KIND (attach) != GOMP_MAP_ATTACH_DETACH)
11941 : 2183 : continue;
11942 : :
11943 : 402 : OMP_CLAUSE_SET_MAP_KIND (attach, GOMP_MAP_ATTACH);
11944 : :
11945 : : /* Sanity check: the standalone attach node will not work if we have
11946 : : an "enter data" operation (because for those, variables need to be
11947 : : mapped separately and attach nodes must be grouped together with the
11948 : : base they attach to). We should only have created the
11949 : : ATTACH_DETACH node after GOMP_MAP_STRUCT for a target region, so
11950 : : this should never be true. */
11951 : 402 : gcc_assert ((region_type & ORT_TARGET) != 0);
11952 : :
11953 : : /* This is the first sorted node in the struct sibling list. Use it
11954 : : to recalculate the correct bias to use.
11955 : : (&first_node - attach_decl).
11956 : : For GOMP_MAP_STRUCT_UNORD, we need e.g. the
11957 : : min(min(min(first,second),third),fourth) element, because the
11958 : : elements aren't in any particular order. */
11959 : 402 : tree lowest_addr;
11960 : 402 : if (OMP_CLAUSE_MAP_KIND (struct_node) == GOMP_MAP_STRUCT_UNORD)
11961 : : {
11962 : 4 : tree first_node = OMP_CLAUSE_CHAIN (attach);
11963 : 4 : unsigned HOST_WIDE_INT num_mappings
11964 : 4 : = tree_to_uhwi (OMP_CLAUSE_SIZE (struct_node));
11965 : 4 : lowest_addr = OMP_CLAUSE_DECL (first_node);
11966 : 4 : lowest_addr = build_fold_addr_expr (lowest_addr);
11967 : 4 : lowest_addr = fold_convert (pointer_sized_int_node, lowest_addr);
11968 : 4 : tree next_node = OMP_CLAUSE_CHAIN (first_node);
11969 : 8 : while (num_mappings > 1)
11970 : : {
11971 : 4 : tree tmp = OMP_CLAUSE_DECL (next_node);
11972 : 4 : tmp = build_fold_addr_expr (tmp);
11973 : 4 : tmp = fold_convert (pointer_sized_int_node, tmp);
11974 : 4 : lowest_addr = fold_build2 (MIN_EXPR, pointer_sized_int_node,
11975 : : lowest_addr, tmp);
11976 : 4 : next_node = OMP_CLAUSE_CHAIN (next_node);
11977 : 4 : num_mappings--;
11978 : : }
11979 : 4 : lowest_addr = fold_convert (ptrdiff_type_node, lowest_addr);
11980 : : }
11981 : : else
11982 : : {
11983 : 398 : tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
11984 : 398 : first_node = build_fold_addr_expr (first_node);
11985 : 398 : lowest_addr = fold_convert (ptrdiff_type_node, first_node);
11986 : : }
11987 : 402 : tree attach_decl = OMP_CLAUSE_DECL (attach);
11988 : 402 : attach_decl = fold_convert (ptrdiff_type_node, attach_decl);
11989 : 402 : OMP_CLAUSE_SIZE (attach)
11990 : 402 : = fold_build2 (MINUS_EXPR, ptrdiff_type_node, lowest_addr,
11991 : : attach_decl);
11992 : :
11993 : : /* Remove GOMP_MAP_ATTACH node from after struct node. */
11994 : 402 : OMP_CLAUSE_CHAIN (struct_node) = OMP_CLAUSE_CHAIN (attach);
11995 : : /* ...and re-insert it at the end of our clause list. */
11996 : 402 : *tail = attach;
11997 : 402 : OMP_CLAUSE_CHAIN (attach) = NULL_TREE;
11998 : 402 : tail = &OMP_CLAUSE_CHAIN (attach);
11999 : : }
12000 : :
12001 : 14769 : error_out:
12002 : 16957 : if (struct_map_to_clause)
12003 : 2188 : delete struct_map_to_clause;
12004 : :
12005 : 16957 : return success;
12006 : 16957 : }
12007 : :
12008 : : /* Scan the OMP clauses in *LIST_P, installing mappings into a new
12009 : : and previous omp contexts. */
12010 : :
12011 : : static void
12012 : 129715 : gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
12013 : : enum omp_region_type region_type,
12014 : : enum tree_code code)
12015 : : {
12016 : 129715 : using namespace omp_addr_tokenizer;
12017 : 129715 : struct gimplify_omp_ctx *ctx, *outer_ctx;
12018 : 129715 : tree c;
12019 : 129715 : tree *orig_list_p = list_p;
12020 : 129715 : int handled_depend_iterators = -1;
12021 : 129715 : int nowait = -1;
12022 : :
12023 : 129715 : ctx = new_omp_context (region_type);
12024 : 129715 : ctx->code = code;
12025 : 129715 : outer_ctx = ctx->outer_context;
12026 : 129715 : if (code == OMP_TARGET)
12027 : : {
12028 : 12437 : if (!lang_GNU_Fortran ())
12029 : 10654 : ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
12030 : 12437 : ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE;
12031 : 24874 : ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran ()
12032 : 12437 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
12033 : : }
12034 : 129715 : if (!lang_GNU_Fortran ())
12035 : 101203 : switch (code)
12036 : : {
12037 : 18913 : case OMP_TARGET:
12038 : 18913 : case OMP_TARGET_DATA:
12039 : 18913 : case OMP_TARGET_ENTER_DATA:
12040 : 18913 : case OMP_TARGET_EXIT_DATA:
12041 : 18913 : case OACC_DECLARE:
12042 : 18913 : case OACC_HOST_DATA:
12043 : 18913 : case OACC_PARALLEL:
12044 : 18913 : case OACC_KERNELS:
12045 : 18913 : ctx->target_firstprivatize_array_bases = true;
12046 : : default:
12047 : : break;
12048 : : }
12049 : :
12050 : 129715 : vec<omp_mapping_group> *groups = NULL;
12051 : 129715 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
12052 : 129715 : unsigned grpnum = 0;
12053 : 129715 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
12054 : :
12055 : 129715 : if (code == OMP_TARGET
12056 : 129715 : || code == OMP_TARGET_DATA
12057 : 129715 : || code == OMP_TARGET_ENTER_DATA
12058 : : || code == OMP_TARGET_EXIT_DATA
12059 : : || code == OACC_DATA
12060 : : || code == OACC_KERNELS
12061 : : || code == OACC_PARALLEL
12062 : : || code == OACC_SERIAL
12063 : : || code == OACC_ENTER_DATA
12064 : : || code == OACC_EXIT_DATA
12065 : : || code == OACC_UPDATE
12066 : : || code == OACC_DECLARE)
12067 : : {
12068 : 32358 : groups = omp_gather_mapping_groups (list_p);
12069 : :
12070 : 32358 : if (groups)
12071 : 17269 : grpmap = omp_index_mapping_groups (groups);
12072 : : }
12073 : :
12074 : 334147 : while ((c = *list_p) != NULL)
12075 : : {
12076 : 204432 : bool remove = false;
12077 : 204432 : bool notice_outer = true;
12078 : 204432 : bool map_descriptor;
12079 : 204432 : const char *check_non_private = NULL;
12080 : 204432 : unsigned int flags;
12081 : 204432 : tree decl;
12082 : 204432 : auto_vec<omp_addr_token *, 10> addr_tokens;
12083 : :
12084 : 239595 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
12085 : : {
12086 : : grp_start_p = NULL;
12087 : : grp_end = NULL_TREE;
12088 : : }
12089 : :
12090 : 204432 : switch (OMP_CLAUSE_CODE (c))
12091 : : {
12092 : 11598 : case OMP_CLAUSE_PRIVATE:
12093 : 11598 : flags = GOVD_PRIVATE | GOVD_EXPLICIT;
12094 : 11598 : if (lang_hooks.decls.omp_private_outer_ref (OMP_CLAUSE_DECL (c)))
12095 : : {
12096 : 165 : flags |= GOVD_PRIVATE_OUTER_REF;
12097 : 165 : OMP_CLAUSE_PRIVATE_OUTER_REF (c) = 1;
12098 : : }
12099 : : else
12100 : : notice_outer = false;
12101 : 11598 : goto do_add;
12102 : 5759 : case OMP_CLAUSE_SHARED:
12103 : 5759 : flags = GOVD_SHARED | GOVD_EXPLICIT;
12104 : 5759 : goto do_add;
12105 : 8313 : case OMP_CLAUSE_FIRSTPRIVATE:
12106 : 8313 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
12107 : 8313 : check_non_private = "firstprivate";
12108 : 8313 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
12109 : : {
12110 : 433 : gcc_assert (code == OMP_TARGET);
12111 : : flags |= GOVD_FIRSTPRIVATE_IMPLICIT;
12112 : : }
12113 : 8313 : goto do_add;
12114 : 7816 : case OMP_CLAUSE_LASTPRIVATE:
12115 : 7816 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
12116 : 534 : switch (code)
12117 : : {
12118 : 30 : case OMP_DISTRIBUTE:
12119 : 30 : error_at (OMP_CLAUSE_LOCATION (c),
12120 : : "conditional %<lastprivate%> clause on "
12121 : : "%qs construct", "distribute");
12122 : 30 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
12123 : 30 : break;
12124 : 16 : case OMP_TASKLOOP:
12125 : 16 : error_at (OMP_CLAUSE_LOCATION (c),
12126 : : "conditional %<lastprivate%> clause on "
12127 : : "%qs construct", "taskloop");
12128 : 16 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
12129 : 16 : break;
12130 : : default:
12131 : : break;
12132 : : }
12133 : 7816 : flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
12134 : 7816 : if (code != OMP_LOOP)
12135 : 7422 : check_non_private = "lastprivate";
12136 : 7816 : decl = OMP_CLAUSE_DECL (c);
12137 : 7816 : if (error_operand_p (decl))
12138 : 0 : goto do_add;
12139 : 7816 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
12140 : 7816 : && !lang_hooks.decls.omp_scalar_p (decl, true))
12141 : : {
12142 : 6 : error_at (OMP_CLAUSE_LOCATION (c),
12143 : : "non-scalar variable %qD in conditional "
12144 : : "%<lastprivate%> clause", decl);
12145 : 6 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
12146 : : }
12147 : 7816 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
12148 : 482 : flags |= GOVD_LASTPRIVATE_CONDITIONAL;
12149 : 7816 : omp_lastprivate_for_combined_outer_constructs (outer_ctx, decl,
12150 : : false);
12151 : 7816 : goto do_add;
12152 : 15285 : case OMP_CLAUSE_REDUCTION:
12153 : 15285 : if (OMP_CLAUSE_REDUCTION_TASK (c))
12154 : : {
12155 : 618 : if (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
12156 : : {
12157 : 423 : if (nowait == -1)
12158 : 303 : nowait = omp_find_clause (*list_p,
12159 : 303 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
12160 : 423 : if (nowait
12161 : 18 : && (outer_ctx == NULL
12162 : 0 : || outer_ctx->region_type != ORT_COMBINED_PARALLEL))
12163 : : {
12164 : 18 : error_at (OMP_CLAUSE_LOCATION (c),
12165 : : "%<task%> reduction modifier on a construct "
12166 : : "with a %<nowait%> clause");
12167 : 18 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
12168 : : }
12169 : : }
12170 : 195 : else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL)
12171 : : {
12172 : 46 : error_at (OMP_CLAUSE_LOCATION (c),
12173 : : "invalid %<task%> reduction modifier on construct "
12174 : : "other than %<parallel%>, %qs, %<sections%> or "
12175 : 23 : "%<scope%>", lang_GNU_Fortran () ? "do" : "for");
12176 : 23 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
12177 : : }
12178 : : }
12179 : 15285 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
12180 : 885 : switch (code)
12181 : : {
12182 : 5 : case OMP_SECTIONS:
12183 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
12184 : : "%<inscan%> %<reduction%> clause on "
12185 : : "%qs construct", "sections");
12186 : 5 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
12187 : 5 : break;
12188 : 5 : case OMP_PARALLEL:
12189 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
12190 : : "%<inscan%> %<reduction%> clause on "
12191 : : "%qs construct", "parallel");
12192 : 5 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
12193 : 5 : break;
12194 : 5 : case OMP_TEAMS:
12195 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
12196 : : "%<inscan%> %<reduction%> clause on "
12197 : : "%qs construct", "teams");
12198 : 5 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
12199 : 5 : break;
12200 : 5 : case OMP_TASKLOOP:
12201 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
12202 : : "%<inscan%> %<reduction%> clause on "
12203 : : "%qs construct", "taskloop");
12204 : 5 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
12205 : 5 : break;
12206 : 5 : case OMP_SCOPE:
12207 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
12208 : : "%<inscan%> %<reduction%> clause on "
12209 : : "%qs construct", "scope");
12210 : 5 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
12211 : 5 : break;
12212 : : default:
12213 : : break;
12214 : : }
12215 : : /* FALLTHRU */
12216 : 17976 : case OMP_CLAUSE_IN_REDUCTION:
12217 : 17976 : case OMP_CLAUSE_TASK_REDUCTION:
12218 : 17976 : flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
12219 : : /* OpenACC permits reductions on private variables. */
12220 : 17976 : if (!(region_type & ORT_ACC)
12221 : : /* taskgroup is actually not a worksharing region. */
12222 : 13145 : && code != OMP_TASKGROUP)
12223 : 12585 : check_non_private = omp_clause_code_name[OMP_CLAUSE_CODE (c)];
12224 : 17976 : decl = OMP_CLAUSE_DECL (c);
12225 : 17976 : if (TREE_CODE (decl) == MEM_REF)
12226 : : {
12227 : 2849 : tree type = TREE_TYPE (decl);
12228 : 2849 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
12229 : 2849 : gimplify_ctxp->into_ssa = false;
12230 : 2849 : if (gimplify_expr (&TYPE_MAX_VALUE (TYPE_DOMAIN (type)), pre_p,
12231 : : NULL, is_gimple_val, fb_rvalue, false)
12232 : : == GS_ERROR)
12233 : : {
12234 : 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
12235 : 0 : remove = true;
12236 : 0 : break;
12237 : : }
12238 : 2849 : gimplify_ctxp->into_ssa = saved_into_ssa;
12239 : 2849 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
12240 : 2849 : if (DECL_P (v))
12241 : : {
12242 : 576 : omp_firstprivatize_variable (ctx, v);
12243 : 576 : omp_notice_variable (ctx, v, true);
12244 : : }
12245 : 2849 : decl = TREE_OPERAND (decl, 0);
12246 : 2849 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
12247 : : {
12248 : 484 : gimplify_ctxp->into_ssa = false;
12249 : 484 : if (gimplify_expr (&TREE_OPERAND (decl, 1), pre_p,
12250 : : NULL, is_gimple_val, fb_rvalue, false)
12251 : : == GS_ERROR)
12252 : : {
12253 : 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
12254 : 0 : remove = true;
12255 : 0 : break;
12256 : : }
12257 : 484 : gimplify_ctxp->into_ssa = saved_into_ssa;
12258 : 484 : v = TREE_OPERAND (decl, 1);
12259 : 484 : if (DECL_P (v))
12260 : : {
12261 : 484 : omp_firstprivatize_variable (ctx, v);
12262 : 484 : omp_notice_variable (ctx, v, true);
12263 : : }
12264 : 484 : decl = TREE_OPERAND (decl, 0);
12265 : : }
12266 : 2849 : if (TREE_CODE (decl) == ADDR_EXPR
12267 : 1541 : || TREE_CODE (decl) == INDIRECT_REF)
12268 : 1496 : decl = TREE_OPERAND (decl, 0);
12269 : : }
12270 : 17976 : goto do_add_decl;
12271 : 2843 : case OMP_CLAUSE_LINEAR:
12272 : 2843 : if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
12273 : : is_gimple_val, fb_rvalue) == GS_ERROR)
12274 : : {
12275 : : remove = true;
12276 : : break;
12277 : : }
12278 : : else
12279 : : {
12280 : 2843 : if (code == OMP_SIMD
12281 : 2843 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
12282 : : {
12283 : 1250 : struct gimplify_omp_ctx *octx = outer_ctx;
12284 : 1250 : if (octx
12285 : 805 : && octx->region_type == ORT_WORKSHARE
12286 : 536 : && octx->combined_loop
12287 : 536 : && !octx->distribute)
12288 : : {
12289 : 526 : if (octx->outer_context
12290 : 449 : && (octx->outer_context->region_type
12291 : : == ORT_COMBINED_PARALLEL))
12292 : 412 : octx = octx->outer_context->outer_context;
12293 : : else
12294 : : octx = octx->outer_context;
12295 : : }
12296 : 971 : if (octx
12297 : 351 : && octx->region_type == ORT_WORKSHARE
12298 : 20 : && octx->combined_loop
12299 : 20 : && octx->distribute)
12300 : : {
12301 : 20 : error_at (OMP_CLAUSE_LOCATION (c),
12302 : : "%<linear%> clause for variable other than "
12303 : : "loop iterator specified on construct "
12304 : : "combined with %<distribute%>");
12305 : 20 : remove = true;
12306 : 20 : break;
12307 : : }
12308 : : }
12309 : : /* For combined #pragma omp parallel for simd, need to put
12310 : : lastprivate and perhaps firstprivate too on the
12311 : : parallel. Similarly for #pragma omp for simd. */
12312 : : struct gimplify_omp_ctx *octx = outer_ctx;
12313 : : bool taskloop_seen = false;
12314 : : decl = NULL_TREE;
12315 : 3678 : do
12316 : : {
12317 : 3678 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
12318 : 3678 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
12319 : : break;
12320 : 3618 : decl = OMP_CLAUSE_DECL (c);
12321 : 3618 : if (error_operand_p (decl))
12322 : : {
12323 : : decl = NULL_TREE;
12324 : : break;
12325 : : }
12326 : 3618 : flags = GOVD_SEEN;
12327 : 3618 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
12328 : 1832 : flags |= GOVD_FIRSTPRIVATE;
12329 : 3618 : if (!OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
12330 : 3618 : flags |= GOVD_LASTPRIVATE;
12331 : 3618 : if (octx
12332 : 2697 : && octx->region_type == ORT_WORKSHARE
12333 : 1289 : && octx->combined_loop)
12334 : : {
12335 : 1278 : if (octx->outer_context
12336 : 1088 : && (octx->outer_context->region_type
12337 : : == ORT_COMBINED_PARALLEL))
12338 : : octx = octx->outer_context;
12339 : 514 : else if (omp_check_private (octx, decl, false))
12340 : : break;
12341 : : }
12342 : : else if (octx
12343 : 1419 : && (octx->region_type & ORT_TASK) != 0
12344 : 334 : && octx->combined_loop)
12345 : : taskloop_seen = true;
12346 : : else if (octx
12347 : 1089 : && octx->region_type == ORT_COMBINED_PARALLEL
12348 : 334 : && ((ctx->region_type == ORT_WORKSHARE
12349 : 225 : && octx == outer_ctx)
12350 : 109 : || taskloop_seen))
12351 : : flags = GOVD_SEEN | GOVD_SHARED;
12352 : : else if (octx
12353 : 755 : && ((octx->region_type & ORT_COMBINED_TEAMS)
12354 : : == ORT_COMBINED_TEAMS))
12355 : : flags = GOVD_SEEN | GOVD_SHARED;
12356 : 588 : else if (octx
12357 : 588 : && octx->region_type == ORT_COMBINED_TARGET)
12358 : : {
12359 : 213 : if (flags & GOVD_LASTPRIVATE)
12360 : 213 : flags = GOVD_SEEN | GOVD_MAP;
12361 : : }
12362 : : else
12363 : : break;
12364 : 2230 : splay_tree_node on
12365 : 2230 : = splay_tree_lookup (octx->variables,
12366 : : (splay_tree_key) decl);
12367 : 2230 : if (on && (on->value & GOVD_DATA_SHARE_CLASS) != 0)
12368 : : {
12369 : : octx = NULL;
12370 : : break;
12371 : : }
12372 : 2225 : omp_add_variable (octx, decl, flags);
12373 : 2225 : if (octx->outer_context == NULL)
12374 : : break;
12375 : : octx = octx->outer_context;
12376 : : }
12377 : : while (1);
12378 : 2823 : if (octx
12379 : 2823 : && decl
12380 : 2823 : && (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
12381 : 765 : || !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
12382 : 1837 : omp_notice_variable (octx, decl, true);
12383 : : }
12384 : 2823 : flags = GOVD_LINEAR | GOVD_EXPLICIT;
12385 : 2823 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
12386 : 2823 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
12387 : : {
12388 : : notice_outer = false;
12389 : : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
12390 : : }
12391 : 2823 : goto do_add;
12392 : :
12393 : 47977 : case OMP_CLAUSE_MAP:
12394 : 47977 : if (!grp_start_p)
12395 : : {
12396 : 29236 : grp_start_p = list_p;
12397 : 29236 : grp_end = (*groups)[grpnum].grp_end;
12398 : 29236 : grpnum++;
12399 : : }
12400 : 47977 : decl = OMP_CLAUSE_DECL (c);
12401 : :
12402 : 47977 : if (error_operand_p (decl))
12403 : : {
12404 : : remove = true;
12405 : : break;
12406 : : }
12407 : :
12408 : 47977 : if (!omp_parse_expr (addr_tokens, decl))
12409 : : {
12410 : : remove = true;
12411 : : break;
12412 : : }
12413 : :
12414 : 47977 : if (remove)
12415 : : break;
12416 : 47977 : if (DECL_P (decl) && outer_ctx && (region_type & ORT_ACC))
12417 : : {
12418 : : struct gimplify_omp_ctx *octx;
12419 : 1203 : for (octx = outer_ctx; octx; octx = octx->outer_context)
12420 : : {
12421 : 1203 : if (octx->region_type != ORT_ACC_HOST_DATA)
12422 : : break;
12423 : 15 : splay_tree_node n2
12424 : 15 : = splay_tree_lookup (octx->variables,
12425 : : (splay_tree_key) decl);
12426 : 15 : if (n2)
12427 : 5 : error_at (OMP_CLAUSE_LOCATION (c), "variable %qE "
12428 : : "declared in enclosing %<host_data%> region",
12429 : 5 : DECL_NAME (decl));
12430 : : }
12431 : : }
12432 : :
12433 : 47977 : map_descriptor = false;
12434 : :
12435 : : /* This condition checks if we're mapping an array descriptor that
12436 : : isn't inside a derived type -- these have special handling, and
12437 : : are not handled as structs in omp_build_struct_sibling_lists.
12438 : : See that function for further details. */
12439 : 47977 : if (*grp_start_p != grp_end
12440 : 31930 : && OMP_CLAUSE_CHAIN (*grp_start_p)
12441 : 79907 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
12442 : : {
12443 : 15278 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
12444 : 15278 : if (omp_map_clause_descriptor_p (grp_mid)
12445 : 28792 : && DECL_P (OMP_CLAUSE_DECL (grp_mid)))
12446 : : map_descriptor = true;
12447 : : }
12448 : 32699 : else if (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP
12449 : 32699 : && (OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_RELEASE
12450 : 32107 : || OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_DELETE)
12451 : 33442 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (grp_end))
12452 : : map_descriptor = true;
12453 : :
12454 : : /* Adding the decl for a struct access: we haven't created
12455 : : GOMP_MAP_STRUCT nodes yet, so this statement needs to predict
12456 : : whether they will be created in gimplify_adjust_omp_clauses.
12457 : : NOTE: Technically we should probably look through DECL_VALUE_EXPR
12458 : : here because something that looks like a DECL_P may actually be a
12459 : : struct access, e.g. variables in a lambda closure
12460 : : (__closure->__foo) or class members (this->foo). Currently in both
12461 : : those cases we map the whole of the containing object (directly in
12462 : : the C++ FE) though, so struct nodes are not created. */
12463 : 47977 : if (c == grp_end
12464 : 29236 : && addr_tokens[0]->type == STRUCTURE_BASE
12465 : 7458 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
12466 : 55435 : && !map_descriptor)
12467 : : {
12468 : 4712 : gcc_assert (addr_tokens[1]->type == ACCESS_METHOD);
12469 : : /* If we got to this struct via a chain of pointers, maybe we
12470 : : want to map it implicitly instead. */
12471 : 4712 : if (omp_access_chain_p (addr_tokens, 1))
12472 : : break;
12473 : 4552 : omp_mapping_group *wholestruct;
12474 : 4552 : if (!(region_type & ORT_ACC)
12475 : 7788 : && omp_mapped_by_containing_struct (grpmap,
12476 : 3236 : OMP_CLAUSE_DECL (c),
12477 : : &wholestruct))
12478 : : break;
12479 : 4368 : decl = addr_tokens[1]->expr;
12480 : 4368 : if (splay_tree_lookup (ctx->variables, (splay_tree_key) decl))
12481 : : break;
12482 : : /* Standalone attach or detach clauses for a struct element
12483 : : should not inhibit implicit mapping of the whole struct. */
12484 : 2728 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
12485 : 2728 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
12486 : : break;
12487 : 2560 : flags = GOVD_MAP | GOVD_EXPLICIT;
12488 : :
12489 : 2560 : gcc_assert (addr_tokens[1]->u.access_kind != ACCESS_DIRECT
12490 : : || TREE_ADDRESSABLE (decl));
12491 : 2560 : goto do_add_decl;
12492 : : }
12493 : :
12494 : 43265 : if (!DECL_P (decl))
12495 : : {
12496 : 19620 : tree d = decl, *pd;
12497 : 19620 : if (TREE_CODE (d) == ARRAY_REF)
12498 : : {
12499 : 5033 : while (TREE_CODE (d) == ARRAY_REF)
12500 : 2584 : d = TREE_OPERAND (d, 0);
12501 : 2449 : if (TREE_CODE (d) == COMPONENT_REF
12502 : 2449 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
12503 : : decl = d;
12504 : : }
12505 : 19620 : pd = &OMP_CLAUSE_DECL (c);
12506 : 19620 : if (d == decl
12507 : 17217 : && TREE_CODE (decl) == INDIRECT_REF
12508 : 13168 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
12509 : 1013 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
12510 : : == REFERENCE_TYPE)
12511 : 20272 : && (OMP_CLAUSE_MAP_KIND (c)
12512 : : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
12513 : : {
12514 : 647 : pd = &TREE_OPERAND (decl, 0);
12515 : 647 : decl = TREE_OPERAND (decl, 0);
12516 : : }
12517 : :
12518 : 19620 : if (addr_tokens[0]->type == STRUCTURE_BASE
12519 : 10068 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
12520 : 10068 : && addr_tokens[1]->type == ACCESS_METHOD
12521 : 10068 : && (addr_tokens[1]->u.access_kind == ACCESS_POINTER
12522 : 9584 : || (addr_tokens[1]->u.access_kind
12523 : : == ACCESS_POINTER_OFFSET))
12524 : 20180 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)))
12525 : : {
12526 : 0 : tree base = addr_tokens[1]->expr;
12527 : 0 : splay_tree_node n
12528 : 0 : = splay_tree_lookup (ctx->variables,
12529 : : (splay_tree_key) base);
12530 : 0 : n->value |= GOVD_SEEN;
12531 : : }
12532 : :
12533 : 19620 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
12534 : : {
12535 : : /* Don't gimplify *pd fully at this point, as the base
12536 : : will need to be adjusted during omp lowering. */
12537 : 88 : auto_vec<tree, 10> expr_stack;
12538 : 88 : tree *p = pd;
12539 : 88 : while (handled_component_p (*p)
12540 : : || TREE_CODE (*p) == INDIRECT_REF
12541 : : || TREE_CODE (*p) == ADDR_EXPR
12542 : : || TREE_CODE (*p) == MEM_REF
12543 : 224 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
12544 : : {
12545 : 136 : expr_stack.safe_push (*p);
12546 : 136 : p = &TREE_OPERAND (*p, 0);
12547 : : }
12548 : 312 : for (int i = expr_stack.length () - 1; i >= 0; i--)
12549 : : {
12550 : 136 : tree t = expr_stack[i];
12551 : 136 : if (TREE_CODE (t) == ARRAY_REF
12552 : 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
12553 : : {
12554 : 56 : if (TREE_OPERAND (t, 2) == NULL_TREE)
12555 : : {
12556 : 56 : tree low = unshare_expr (array_ref_low_bound (t));
12557 : 56 : if (!is_gimple_min_invariant (low))
12558 : : {
12559 : 0 : TREE_OPERAND (t, 2) = low;
12560 : 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
12561 : : pre_p, NULL,
12562 : : is_gimple_reg,
12563 : : fb_rvalue) == GS_ERROR)
12564 : 0 : remove = true;
12565 : : }
12566 : : }
12567 : 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
12568 : : NULL, is_gimple_reg,
12569 : : fb_rvalue) == GS_ERROR)
12570 : 0 : remove = true;
12571 : 56 : if (TREE_OPERAND (t, 3) == NULL_TREE)
12572 : : {
12573 : 56 : tree elmt_size = array_ref_element_size (t);
12574 : 56 : if (!is_gimple_min_invariant (elmt_size))
12575 : : {
12576 : 0 : elmt_size = unshare_expr (elmt_size);
12577 : 0 : tree elmt_type
12578 : 0 : = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t,
12579 : : 0)));
12580 : 0 : tree factor
12581 : 0 : = size_int (TYPE_ALIGN_UNIT (elmt_type));
12582 : 0 : elmt_size
12583 : 0 : = size_binop (EXACT_DIV_EXPR, elmt_size,
12584 : : factor);
12585 : 0 : TREE_OPERAND (t, 3) = elmt_size;
12586 : 0 : if (gimplify_expr (&TREE_OPERAND (t, 3),
12587 : : pre_p, NULL,
12588 : : is_gimple_reg,
12589 : : fb_rvalue) == GS_ERROR)
12590 : 0 : remove = true;
12591 : : }
12592 : : }
12593 : 0 : else if (gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
12594 : : NULL, is_gimple_reg,
12595 : : fb_rvalue) == GS_ERROR)
12596 : 0 : remove = true;
12597 : : }
12598 : 80 : else if (TREE_CODE (t) == COMPONENT_REF)
12599 : : {
12600 : 0 : if (TREE_OPERAND (t, 2) == NULL_TREE)
12601 : : {
12602 : 0 : tree offset = component_ref_field_offset (t);
12603 : 0 : if (!is_gimple_min_invariant (offset))
12604 : : {
12605 : 0 : offset = unshare_expr (offset);
12606 : 0 : tree field = TREE_OPERAND (t, 1);
12607 : 0 : tree factor
12608 : 0 : = size_int (DECL_OFFSET_ALIGN (field)
12609 : : / BITS_PER_UNIT);
12610 : 0 : offset = size_binop (EXACT_DIV_EXPR, offset,
12611 : : factor);
12612 : 0 : TREE_OPERAND (t, 2) = offset;
12613 : 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
12614 : : pre_p, NULL,
12615 : : is_gimple_reg,
12616 : : fb_rvalue) == GS_ERROR)
12617 : 0 : remove = true;
12618 : : }
12619 : : }
12620 : 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
12621 : : NULL, is_gimple_reg,
12622 : : fb_rvalue) == GS_ERROR)
12623 : 0 : remove = true;
12624 : : }
12625 : : }
12626 : 224 : for (; expr_stack.length () > 0; )
12627 : : {
12628 : 136 : tree t = expr_stack.pop ();
12629 : :
12630 : 136 : if (TREE_CODE (t) == ARRAY_REF
12631 : 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
12632 : : {
12633 : 56 : if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))
12634 : 56 : && gimplify_expr (&TREE_OPERAND (t, 1), pre_p,
12635 : : NULL, is_gimple_val,
12636 : : fb_rvalue) == GS_ERROR)
12637 : 144 : remove = true;
12638 : : }
12639 : : }
12640 : 88 : }
12641 : : break;
12642 : : }
12643 : :
12644 : 23645 : if ((code == OMP_TARGET
12645 : : || code == OMP_TARGET_DATA
12646 : : || code == OMP_TARGET_ENTER_DATA
12647 : 14406 : || code == OMP_TARGET_EXIT_DATA)
12648 : 24178 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
12649 : : {
12650 : : /* If we have attach/detach but the decl we have is a pointer to
12651 : : pointer, we're probably mapping the "base level" array
12652 : : implicitly. Make sure we don't add the decl as if we mapped
12653 : : it explicitly. That is,
12654 : :
12655 : : int **arr;
12656 : : [...]
12657 : : #pragma omp target map(arr[a][b:c])
12658 : :
12659 : : should *not* map "arr" explicitly. That way we get a
12660 : : zero-length "alloc" mapping for it, and assuming it's been
12661 : : mapped by some previous directive, etc., things work as they
12662 : : should. */
12663 : :
12664 : 182 : tree basetype = TREE_TYPE (addr_tokens[0]->expr);
12665 : :
12666 : 182 : if (TREE_CODE (basetype) == REFERENCE_TYPE)
12667 : 34 : basetype = TREE_TYPE (basetype);
12668 : :
12669 : 182 : if (code == OMP_TARGET
12670 : 42 : && addr_tokens[0]->type == ARRAY_BASE
12671 : 42 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
12672 : 42 : && TREE_CODE (basetype) == POINTER_TYPE
12673 : 224 : && TREE_CODE (TREE_TYPE (basetype)) == POINTER_TYPE)
12674 : : break;
12675 : : }
12676 : :
12677 : 23635 : flags = GOVD_MAP | GOVD_EXPLICIT;
12678 : 23635 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
12679 : 23505 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM
12680 : 22999 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TO
12681 : 46604 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TOFROM)
12682 : : flags |= GOVD_MAP_ALWAYS_TO;
12683 : :
12684 : 23635 : goto do_add;
12685 : :
12686 : 582 : case OMP_CLAUSE_AFFINITY:
12687 : 582 : gimplify_omp_affinity (list_p, pre_p);
12688 : 582 : remove = true;
12689 : 582 : break;
12690 : 10 : case OMP_CLAUSE_DOACROSS:
12691 : 10 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
12692 : : {
12693 : 5 : tree deps = OMP_CLAUSE_DECL (c);
12694 : 10 : while (deps && TREE_CODE (deps) == TREE_LIST)
12695 : : {
12696 : 5 : if (TREE_CODE (TREE_PURPOSE (deps)) == TRUNC_DIV_EXPR
12697 : 5 : && DECL_P (TREE_OPERAND (TREE_PURPOSE (deps), 1)))
12698 : 0 : gimplify_expr (&TREE_OPERAND (TREE_PURPOSE (deps), 1),
12699 : : pre_p, NULL, is_gimple_val, fb_rvalue);
12700 : 5 : deps = TREE_CHAIN (deps);
12701 : : }
12702 : : }
12703 : : else
12704 : 5 : gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
12705 : : == OMP_CLAUSE_DOACROSS_SOURCE);
12706 : : break;
12707 : 2243 : case OMP_CLAUSE_DEPEND:
12708 : 2243 : if (handled_depend_iterators == -1)
12709 : 1915 : handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
12710 : 2243 : if (handled_depend_iterators)
12711 : : {
12712 : 407 : if (handled_depend_iterators == 2)
12713 : 0 : remove = true;
12714 : : break;
12715 : : }
12716 : 1836 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
12717 : : {
12718 : 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
12719 : : NULL, is_gimple_val, fb_rvalue);
12720 : 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
12721 : : }
12722 : 1836 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
12723 : : {
12724 : : remove = true;
12725 : : break;
12726 : : }
12727 : 1836 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
12728 : : {
12729 : 1800 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
12730 : 1800 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
12731 : : is_gimple_val, fb_rvalue) == GS_ERROR)
12732 : : {
12733 : : remove = true;
12734 : : break;
12735 : : }
12736 : : }
12737 : 1836 : if (code == OMP_TASK)
12738 : 1465 : ctx->has_depend = true;
12739 : : break;
12740 : :
12741 : 8341 : case OMP_CLAUSE_TO:
12742 : 8341 : case OMP_CLAUSE_FROM:
12743 : 8341 : case OMP_CLAUSE__CACHE_:
12744 : 8341 : decl = OMP_CLAUSE_DECL (c);
12745 : 8341 : if (error_operand_p (decl))
12746 : : {
12747 : : remove = true;
12748 : : break;
12749 : : }
12750 : 8341 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
12751 : 7466 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
12752 : 684 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
12753 : 8341 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
12754 : : NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
12755 : : {
12756 : : remove = true;
12757 : : break;
12758 : : }
12759 : 8341 : if (!DECL_P (decl))
12760 : : {
12761 : 2123 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p,
12762 : : NULL, is_gimple_lvalue, fb_lvalue)
12763 : : == GS_ERROR)
12764 : : {
12765 : 0 : remove = true;
12766 : : break;
12767 : : }
12768 : : break;
12769 : : }
12770 : 6218 : goto do_notice;
12771 : :
12772 : 2146 : case OMP_CLAUSE_USE_DEVICE_PTR:
12773 : 2146 : case OMP_CLAUSE_USE_DEVICE_ADDR:
12774 : 2146 : flags = GOVD_EXPLICIT;
12775 : 2146 : goto do_add;
12776 : :
12777 : 581 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
12778 : 581 : decl = OMP_CLAUSE_DECL (c);
12779 : 581 : while (TREE_CODE (decl) == INDIRECT_REF
12780 : 638 : || TREE_CODE (decl) == ARRAY_REF)
12781 : 57 : decl = TREE_OPERAND (decl, 0);
12782 : 581 : flags = GOVD_EXPLICIT;
12783 : 581 : goto do_add_decl;
12784 : :
12785 : 386 : case OMP_CLAUSE_IS_DEVICE_PTR:
12786 : 386 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
12787 : 386 : goto do_add;
12788 : :
12789 : 62674 : do_add:
12790 : 62674 : decl = OMP_CLAUSE_DECL (c);
12791 : 83791 : do_add_decl:
12792 : 83791 : if (error_operand_p (decl))
12793 : : {
12794 : : remove = true;
12795 : : break;
12796 : : }
12797 : 83781 : if (DECL_NAME (decl) == NULL_TREE && (flags & GOVD_SHARED) == 0)
12798 : : {
12799 : 2024 : tree t = omp_member_access_dummy_var (decl);
12800 : 2024 : if (t)
12801 : : {
12802 : 783 : tree v = DECL_VALUE_EXPR (decl);
12803 : 783 : DECL_NAME (decl) = DECL_NAME (TREE_OPERAND (v, 1));
12804 : 783 : if (outer_ctx)
12805 : 155 : omp_notice_variable (outer_ctx, t, true);
12806 : : }
12807 : : }
12808 : 83781 : if (code == OACC_DATA
12809 : 2446 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
12810 : 86227 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
12811 : 323 : flags |= GOVD_MAP_0LEN_ARRAY;
12812 : 83781 : omp_add_variable (ctx, decl, flags);
12813 : 83781 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
12814 : 68496 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
12815 : 66365 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
12816 : 86472 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
12817 : : {
12818 : 4416 : struct gimplify_omp_ctx *pctx
12819 : 2208 : = code == OMP_TARGET ? outer_ctx : ctx;
12820 : 2208 : if (pctx)
12821 : 2178 : omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
12822 : : GOVD_LOCAL | GOVD_SEEN);
12823 : 2178 : if (pctx
12824 : 2178 : && OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
12825 : 634 : && walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
12826 : : find_decl_expr,
12827 : : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
12828 : : NULL) == NULL_TREE)
12829 : 210 : omp_add_variable (pctx,
12830 : 210 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
12831 : : GOVD_LOCAL | GOVD_SEEN);
12832 : 2208 : gimplify_omp_ctxp = pctx;
12833 : 2208 : push_gimplify_context ();
12834 : :
12835 : 2208 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
12836 : 2208 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
12837 : :
12838 : 2208 : gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
12839 : 2208 : &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
12840 : 2208 : pop_gimplify_context
12841 : 2208 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)));
12842 : 2208 : push_gimplify_context ();
12843 : 4416 : gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
12844 : 2208 : &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
12845 : 2208 : pop_gimplify_context
12846 : 2208 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
12847 : 2208 : OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
12848 : 2208 : OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
12849 : :
12850 : 2208 : gimplify_omp_ctxp = outer_ctx;
12851 : : }
12852 : 81573 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
12853 : 81573 : && OMP_CLAUSE_LASTPRIVATE_STMT (c))
12854 : : {
12855 : 297 : gimplify_omp_ctxp = ctx;
12856 : 297 : push_gimplify_context ();
12857 : 297 : if (TREE_CODE (OMP_CLAUSE_LASTPRIVATE_STMT (c)) != BIND_EXPR)
12858 : : {
12859 : 297 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
12860 : : NULL, NULL);
12861 : 297 : TREE_SIDE_EFFECTS (bind) = 1;
12862 : 297 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LASTPRIVATE_STMT (c);
12863 : 297 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = bind;
12864 : : }
12865 : 594 : gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c),
12866 : 297 : &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
12867 : 297 : pop_gimplify_context
12868 : 297 : (gimple_seq_first_stmt (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)));
12869 : 297 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL_TREE;
12870 : :
12871 : 297 : gimplify_omp_ctxp = outer_ctx;
12872 : : }
12873 : 81276 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
12874 : 81276 : && OMP_CLAUSE_LINEAR_STMT (c))
12875 : : {
12876 : 60 : gimplify_omp_ctxp = ctx;
12877 : 60 : push_gimplify_context ();
12878 : 60 : if (TREE_CODE (OMP_CLAUSE_LINEAR_STMT (c)) != BIND_EXPR)
12879 : : {
12880 : 60 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
12881 : : NULL, NULL);
12882 : 60 : TREE_SIDE_EFFECTS (bind) = 1;
12883 : 60 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LINEAR_STMT (c);
12884 : 60 : OMP_CLAUSE_LINEAR_STMT (c) = bind;
12885 : : }
12886 : 120 : gimplify_and_add (OMP_CLAUSE_LINEAR_STMT (c),
12887 : 60 : &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
12888 : 60 : pop_gimplify_context
12889 : 60 : (gimple_seq_first_stmt (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)));
12890 : 60 : OMP_CLAUSE_LINEAR_STMT (c) = NULL_TREE;
12891 : :
12892 : 60 : gimplify_omp_ctxp = outer_ctx;
12893 : : }
12894 : 83781 : if (notice_outer)
12895 : 72288 : goto do_notice;
12896 : : break;
12897 : :
12898 : 963 : case OMP_CLAUSE_COPYIN:
12899 : 963 : case OMP_CLAUSE_COPYPRIVATE:
12900 : 963 : decl = OMP_CLAUSE_DECL (c);
12901 : 963 : if (error_operand_p (decl))
12902 : : {
12903 : : remove = true;
12904 : : break;
12905 : : }
12906 : 963 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
12907 : : && !remove
12908 : 963 : && !omp_check_private (ctx, decl, true))
12909 : : {
12910 : 38 : remove = true;
12911 : 38 : if (is_global_var (decl))
12912 : : {
12913 : 32 : if (DECL_THREAD_LOCAL_P (decl))
12914 : : remove = false;
12915 : 12 : else if (DECL_HAS_VALUE_EXPR_P (decl))
12916 : : {
12917 : 2 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
12918 : :
12919 : 2 : if (value
12920 : 2 : && DECL_P (value)
12921 : 4 : && DECL_THREAD_LOCAL_P (value))
12922 : : remove = false;
12923 : : }
12924 : : }
12925 : : if (remove)
12926 : 16 : error_at (OMP_CLAUSE_LOCATION (c),
12927 : : "copyprivate variable %qE is not threadprivate"
12928 : 16 : " or private in outer context", DECL_NAME (decl));
12929 : : }
12930 : 79469 : do_notice:
12931 : 79469 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
12932 : 64184 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
12933 : 55871 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
12934 : 31414 : && outer_ctx
12935 : 18137 : && ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
12936 : 16780 : || (region_type == ORT_WORKSHARE
12937 : 4140 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
12938 : 1166 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
12939 : 988 : || code == OMP_LOOP)))
12940 : 81501 : && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
12941 : 893 : || (code == OMP_LOOP
12942 : 160 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
12943 : 160 : && ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
12944 : : == ORT_COMBINED_TEAMS))))
12945 : : {
12946 : 1280 : splay_tree_node on
12947 : 1280 : = splay_tree_lookup (outer_ctx->variables,
12948 : : (splay_tree_key)decl);
12949 : 1280 : if (on == NULL || (on->value & GOVD_DATA_SHARE_CLASS) == 0)
12950 : : {
12951 : 1011 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
12952 : 800 : && TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
12953 : 1151 : && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
12954 : 70 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12955 : 0 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
12956 : : == POINTER_TYPE))))
12957 : 70 : omp_firstprivatize_variable (outer_ctx, decl);
12958 : : else
12959 : : {
12960 : 941 : omp_add_variable (outer_ctx, decl,
12961 : : GOVD_SEEN | GOVD_SHARED);
12962 : 941 : if (outer_ctx->outer_context)
12963 : 271 : omp_notice_variable (outer_ctx->outer_context, decl,
12964 : : true);
12965 : : }
12966 : : }
12967 : : }
12968 : 78799 : if (outer_ctx)
12969 : 30623 : omp_notice_variable (outer_ctx, decl, true);
12970 : 79469 : if (check_non_private
12971 : 28320 : && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
12972 : 5058 : && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
12973 : 1756 : || decl == OMP_CLAUSE_DECL (c)
12974 : 252 : || (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
12975 : 252 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
12976 : : == ADDR_EXPR
12977 : 126 : || (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
12978 : : == POINTER_PLUS_EXPR
12979 : 22 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND
12980 : : (OMP_CLAUSE_DECL (c), 0), 0))
12981 : : == ADDR_EXPR)))))
12982 : 84412 : && omp_check_private (ctx, decl, false))
12983 : : {
12984 : 70 : error ("%s variable %qE is private in outer context",
12985 : 35 : check_non_private, DECL_NAME (decl));
12986 : 35 : remove = true;
12987 : : }
12988 : : break;
12989 : :
12990 : 198 : case OMP_CLAUSE_DETACH:
12991 : 198 : flags = GOVD_FIRSTPRIVATE | GOVD_SEEN;
12992 : 198 : goto do_add;
12993 : :
12994 : 4456 : case OMP_CLAUSE_IF:
12995 : 4456 : if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK
12996 : 4456 : && OMP_CLAUSE_IF_MODIFIER (c) != code)
12997 : : {
12998 : : const char *p[2];
12999 : 210 : for (int i = 0; i < 2; i++)
13000 : 140 : switch (i ? OMP_CLAUSE_IF_MODIFIER (c) : code)
13001 : : {
13002 : 10 : case VOID_CST: p[i] = "cancel"; break;
13003 : 30 : case OMP_PARALLEL: p[i] = "parallel"; break;
13004 : 5 : case OMP_SIMD: p[i] = "simd"; break;
13005 : 15 : case OMP_TASK: p[i] = "task"; break;
13006 : 15 : case OMP_TASKLOOP: p[i] = "taskloop"; break;
13007 : 10 : case OMP_TARGET_DATA: p[i] = "target data"; break;
13008 : 15 : case OMP_TARGET: p[i] = "target"; break;
13009 : 15 : case OMP_TARGET_UPDATE: p[i] = "target update"; break;
13010 : 10 : case OMP_TARGET_ENTER_DATA:
13011 : 10 : p[i] = "target enter data"; break;
13012 : 15 : case OMP_TARGET_EXIT_DATA: p[i] = "target exit data"; break;
13013 : 0 : default: gcc_unreachable ();
13014 : : }
13015 : 70 : error_at (OMP_CLAUSE_LOCATION (c),
13016 : : "expected %qs %<if%> clause modifier rather than %qs",
13017 : : p[0], p[1]);
13018 : 70 : remove = true;
13019 : : }
13020 : : /* Fall through. */
13021 : :
13022 : 5223 : case OMP_CLAUSE_SELF:
13023 : 5223 : case OMP_CLAUSE_FINAL:
13024 : 5223 : OMP_CLAUSE_OPERAND (c, 0)
13025 : 10446 : = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
13026 : : /* Fall through. */
13027 : :
13028 : 6275 : case OMP_CLAUSE_NUM_TEAMS:
13029 : 6275 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
13030 : 1052 : && OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
13031 : 6559 : && !is_gimple_min_invariant (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
13032 : : {
13033 : 241 : if (error_operand_p (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
13034 : : {
13035 : : remove = true;
13036 : : break;
13037 : : }
13038 : 241 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
13039 : 482 : = get_initialized_tmp_var (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c),
13040 : : pre_p, NULL, true);
13041 : : }
13042 : : /* Fall through. */
13043 : :
13044 : 22501 : case OMP_CLAUSE_SCHEDULE:
13045 : 22501 : case OMP_CLAUSE_NUM_THREADS:
13046 : 22501 : case OMP_CLAUSE_THREAD_LIMIT:
13047 : 22501 : case OMP_CLAUSE_DIST_SCHEDULE:
13048 : 22501 : case OMP_CLAUSE_DEVICE:
13049 : 22501 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
13050 : 22501 : && OMP_CLAUSE_DEVICE_ANCESTOR (c))
13051 : : {
13052 : 145 : if (code != OMP_TARGET)
13053 : : {
13054 : 24 : error_at (OMP_CLAUSE_LOCATION (c),
13055 : : "%<device%> clause with %<ancestor%> is only "
13056 : : "allowed on %<target%> construct");
13057 : 24 : remove = true;
13058 : 24 : break;
13059 : : }
13060 : :
13061 : 121 : tree clauses = *orig_list_p;
13062 : 368 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
13063 : 260 : if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE
13064 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE
13065 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE
13066 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP
13067 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP
13068 : : )
13069 : : {
13070 : 13 : error_at (OMP_CLAUSE_LOCATION (c),
13071 : : "with %<ancestor%>, only the %<device%>, "
13072 : : "%<firstprivate%>, %<private%>, %<defaultmap%>, "
13073 : : "and %<map%> clauses may appear on the "
13074 : : "construct");
13075 : 13 : remove = true;
13076 : 13 : break;
13077 : : }
13078 : : }
13079 : : /* Fall through. */
13080 : :
13081 : 32504 : case OMP_CLAUSE_PRIORITY:
13082 : 32504 : case OMP_CLAUSE_GRAINSIZE:
13083 : 32504 : case OMP_CLAUSE_NUM_TASKS:
13084 : 32504 : case OMP_CLAUSE_FILTER:
13085 : 32504 : case OMP_CLAUSE_HINT:
13086 : 32504 : case OMP_CLAUSE_ASYNC:
13087 : 32504 : case OMP_CLAUSE_WAIT:
13088 : 32504 : case OMP_CLAUSE_NUM_GANGS:
13089 : 32504 : case OMP_CLAUSE_NUM_WORKERS:
13090 : 32504 : case OMP_CLAUSE_VECTOR_LENGTH:
13091 : 32504 : case OMP_CLAUSE_WORKER:
13092 : 32504 : case OMP_CLAUSE_VECTOR:
13093 : 32504 : if (OMP_CLAUSE_OPERAND (c, 0)
13094 : 32504 : && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0)))
13095 : : {
13096 : 8560 : if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0)))
13097 : : {
13098 : : remove = true;
13099 : : break;
13100 : : }
13101 : : /* All these clauses care about value, not a particular decl,
13102 : : so try to force it into a SSA_NAME or fresh temporary. */
13103 : 8553 : OMP_CLAUSE_OPERAND (c, 0)
13104 : 17106 : = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0),
13105 : : pre_p, NULL, true);
13106 : : }
13107 : : break;
13108 : :
13109 : 2321 : case OMP_CLAUSE_GANG:
13110 : 2321 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
13111 : : is_gimple_val, fb_rvalue) == GS_ERROR)
13112 : 0 : remove = true;
13113 : 2321 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL,
13114 : : is_gimple_val, fb_rvalue) == GS_ERROR)
13115 : 0 : remove = true;
13116 : : break;
13117 : :
13118 : : case OMP_CLAUSE_NOWAIT:
13119 : 204432 : nowait = 1;
13120 : : break;
13121 : :
13122 : : case OMP_CLAUSE_ORDERED:
13123 : : case OMP_CLAUSE_UNTIED:
13124 : : case OMP_CLAUSE_COLLAPSE:
13125 : : case OMP_CLAUSE_TILE:
13126 : : case OMP_CLAUSE_AUTO:
13127 : : case OMP_CLAUSE_SEQ:
13128 : : case OMP_CLAUSE_INDEPENDENT:
13129 : : case OMP_CLAUSE_MERGEABLE:
13130 : : case OMP_CLAUSE_PROC_BIND:
13131 : : case OMP_CLAUSE_SAFELEN:
13132 : : case OMP_CLAUSE_SIMDLEN:
13133 : : case OMP_CLAUSE_NOGROUP:
13134 : : case OMP_CLAUSE_THREADS:
13135 : : case OMP_CLAUSE_SIMD:
13136 : : case OMP_CLAUSE_BIND:
13137 : : case OMP_CLAUSE_IF_PRESENT:
13138 : : case OMP_CLAUSE_FINALIZE:
13139 : : break;
13140 : :
13141 : 4555 : case OMP_CLAUSE_ORDER:
13142 : 4555 : ctx->order_concurrent = true;
13143 : 4555 : break;
13144 : :
13145 : 1157 : case OMP_CLAUSE_DEFAULTMAP:
13146 : 1157 : enum gimplify_defaultmap_kind gdmkmin, gdmkmax;
13147 : 1157 : switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c))
13148 : : {
13149 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
13150 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
13151 : : gdmkmin = GDMK_SCALAR;
13152 : : gdmkmax = GDMK_POINTER;
13153 : : break;
13154 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
13155 : : gdmkmin = GDMK_SCALAR;
13156 : : gdmkmax = GDMK_SCALAR_TARGET;
13157 : : break;
13158 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
13159 : : gdmkmin = gdmkmax = GDMK_AGGREGATE;
13160 : : break;
13161 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE:
13162 : : gdmkmin = gdmkmax = GDMK_ALLOCATABLE;
13163 : : break;
13164 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
13165 : : gdmkmin = gdmkmax = GDMK_POINTER;
13166 : : break;
13167 : 0 : default:
13168 : 0 : gcc_unreachable ();
13169 : : }
13170 : 5139 : for (int gdmk = gdmkmin; gdmk <= gdmkmax; gdmk++)
13171 : 3982 : switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (c))
13172 : : {
13173 : 87 : case OMP_CLAUSE_DEFAULTMAP_ALLOC:
13174 : 87 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_ALLOC_ONLY;
13175 : 87 : break;
13176 : 68 : case OMP_CLAUSE_DEFAULTMAP_TO:
13177 : 68 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_TO_ONLY;
13178 : 68 : break;
13179 : 35 : case OMP_CLAUSE_DEFAULTMAP_FROM:
13180 : 35 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FROM_ONLY;
13181 : 35 : break;
13182 : 748 : case OMP_CLAUSE_DEFAULTMAP_TOFROM:
13183 : 748 : ctx->defaultmap[gdmk] = GOVD_MAP;
13184 : 748 : break;
13185 : 457 : case OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE:
13186 : 457 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
13187 : 457 : break;
13188 : 2483 : case OMP_CLAUSE_DEFAULTMAP_NONE:
13189 : 2483 : ctx->defaultmap[gdmk] = 0;
13190 : 2483 : break;
13191 : 42 : case OMP_CLAUSE_DEFAULTMAP_PRESENT:
13192 : 42 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
13193 : 42 : break;
13194 : 62 : case OMP_CLAUSE_DEFAULTMAP_DEFAULT:
13195 : 62 : switch (gdmk)
13196 : : {
13197 : 12 : case GDMK_SCALAR:
13198 : 12 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
13199 : 12 : break;
13200 : 12 : case GDMK_SCALAR_TARGET:
13201 : 12 : ctx->defaultmap[gdmk] = (lang_GNU_Fortran ()
13202 : 12 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
13203 : 12 : break;
13204 : 14 : case GDMK_AGGREGATE:
13205 : 14 : case GDMK_ALLOCATABLE:
13206 : 14 : ctx->defaultmap[gdmk] = GOVD_MAP;
13207 : 14 : break;
13208 : 24 : case GDMK_POINTER:
13209 : 24 : ctx->defaultmap[gdmk] = GOVD_MAP;
13210 : 24 : if (!lang_GNU_Fortran ())
13211 : 16 : ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY;
13212 : : break;
13213 : : default:
13214 : : gcc_unreachable ();
13215 : : }
13216 : : break;
13217 : 0 : default:
13218 : 0 : gcc_unreachable ();
13219 : : }
13220 : : break;
13221 : :
13222 : 911 : case OMP_CLAUSE_ALIGNED:
13223 : 911 : decl = OMP_CLAUSE_DECL (c);
13224 : 911 : if (error_operand_p (decl))
13225 : : {
13226 : : remove = true;
13227 : : break;
13228 : : }
13229 : 911 : if (gimplify_expr (&OMP_CLAUSE_ALIGNED_ALIGNMENT (c), pre_p, NULL,
13230 : : is_gimple_val, fb_rvalue) == GS_ERROR)
13231 : : {
13232 : : remove = true;
13233 : : break;
13234 : : }
13235 : 911 : if (!is_global_var (decl)
13236 : 911 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
13237 : 671 : omp_add_variable (ctx, decl, GOVD_ALIGNED);
13238 : : break;
13239 : :
13240 : 552 : case OMP_CLAUSE_NONTEMPORAL:
13241 : 552 : decl = OMP_CLAUSE_DECL (c);
13242 : 552 : if (error_operand_p (decl))
13243 : : {
13244 : : remove = true;
13245 : : break;
13246 : : }
13247 : 552 : omp_add_variable (ctx, decl, GOVD_NONTEMPORAL);
13248 : 552 : break;
13249 : :
13250 : 3975 : case OMP_CLAUSE_ALLOCATE:
13251 : 3975 : decl = OMP_CLAUSE_DECL (c);
13252 : 3975 : if (error_operand_p (decl))
13253 : : {
13254 : : remove = true;
13255 : : break;
13256 : : }
13257 : 3975 : if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL,
13258 : : is_gimple_val, fb_rvalue) == GS_ERROR)
13259 : : {
13260 : : remove = true;
13261 : : break;
13262 : : }
13263 : 3975 : else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
13264 : 3975 : || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
13265 : : == INTEGER_CST))
13266 : : ;
13267 : 512 : else if (code == OMP_TASKLOOP
13268 : 512 : || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
13269 : 82 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
13270 : 164 : = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
13271 : : pre_p, NULL, false);
13272 : : break;
13273 : :
13274 : 4753 : case OMP_CLAUSE_DEFAULT:
13275 : 4753 : ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
13276 : 4753 : break;
13277 : :
13278 : 695 : case OMP_CLAUSE_INCLUSIVE:
13279 : 695 : case OMP_CLAUSE_EXCLUSIVE:
13280 : 695 : decl = OMP_CLAUSE_DECL (c);
13281 : 695 : {
13282 : 695 : splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
13283 : : (splay_tree_key) decl);
13284 : 695 : if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
13285 : : {
13286 : 6 : error_at (OMP_CLAUSE_LOCATION (c),
13287 : : "%qD specified in %qs clause but not in %<inscan%> "
13288 : : "%<reduction%> clause on the containing construct",
13289 : 6 : decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
13290 : 6 : remove = true;
13291 : : }
13292 : : else
13293 : : {
13294 : 689 : n->value |= GOVD_REDUCTION_INSCAN;
13295 : 689 : if (outer_ctx->region_type == ORT_SIMD
13296 : 570 : && outer_ctx->outer_context
13297 : 110 : && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
13298 : : {
13299 : 110 : n = splay_tree_lookup (outer_ctx->outer_context->variables,
13300 : : (splay_tree_key) decl);
13301 : 110 : if (n && (n->value & GOVD_REDUCTION) != 0)
13302 : 110 : n->value |= GOVD_REDUCTION_INSCAN;
13303 : : }
13304 : : }
13305 : : }
13306 : : break;
13307 : :
13308 : 0 : case OMP_CLAUSE_NOHOST:
13309 : 0 : default:
13310 : 0 : gcc_unreachable ();
13311 : : }
13312 : :
13313 : 204432 : if (code == OACC_DATA
13314 : 5144 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
13315 : 209328 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
13316 : 4573 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
13317 : : remove = true;
13318 : 204109 : if (remove)
13319 : 1106 : *list_p = OMP_CLAUSE_CHAIN (c);
13320 : : else
13321 : 203326 : list_p = &OMP_CLAUSE_CHAIN (c);
13322 : 204432 : }
13323 : :
13324 : 129715 : if (groups)
13325 : : {
13326 : 34538 : delete grpmap;
13327 : 17269 : delete groups;
13328 : : }
13329 : :
13330 : 129715 : ctx->clauses = *orig_list_p;
13331 : 129715 : gimplify_omp_ctxp = ctx;
13332 : 129715 : }
13333 : :
13334 : : /* Return true if DECL is a candidate for shared to firstprivate
13335 : : optimization. We only consider non-addressable scalars, not
13336 : : too big, and not references. */
13337 : :
13338 : : static bool
13339 : 392400 : omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
13340 : : {
13341 : 392400 : if (TREE_ADDRESSABLE (decl))
13342 : : return false;
13343 : 343635 : tree type = TREE_TYPE (decl);
13344 : 343635 : if (!is_gimple_reg_type (type)
13345 : 319076 : || TREE_CODE (type) == REFERENCE_TYPE
13346 : 657302 : || TREE_ADDRESSABLE (type))
13347 : : return false;
13348 : : /* Don't optimize too large decls, as each thread/task will have
13349 : : its own. */
13350 : 313667 : HOST_WIDE_INT len = int_size_in_bytes (type);
13351 : 313667 : if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
13352 : : return false;
13353 : 313650 : if (omp_privatize_by_reference (decl))
13354 : : return false;
13355 : : return true;
13356 : : }
13357 : :
13358 : : /* Helper function of omp_find_stores_op and gimplify_adjust_omp_clauses*.
13359 : : For omp_shared_to_firstprivate_optimizable_decl_p decl mark it as
13360 : : GOVD_WRITTEN in outer contexts. */
13361 : :
13362 : : static void
13363 : 292334 : omp_mark_stores (struct gimplify_omp_ctx *ctx, tree decl)
13364 : : {
13365 : 446392 : for (; ctx; ctx = ctx->outer_context)
13366 : : {
13367 : 428747 : splay_tree_node n = splay_tree_lookup (ctx->variables,
13368 : : (splay_tree_key) decl);
13369 : 428747 : if (n == NULL)
13370 : 150204 : continue;
13371 : 278543 : else if (n->value & GOVD_SHARED)
13372 : : {
13373 : 9150 : n->value |= GOVD_WRITTEN;
13374 : 9150 : return;
13375 : : }
13376 : 269393 : else if (n->value & GOVD_DATA_SHARE_CLASS)
13377 : : return;
13378 : : }
13379 : : }
13380 : :
13381 : : /* Helper callback for walk_gimple_seq to discover possible stores
13382 : : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
13383 : : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
13384 : : for those. */
13385 : :
13386 : : static tree
13387 : 1080447 : omp_find_stores_op (tree *tp, int *walk_subtrees, void *data)
13388 : : {
13389 : 1080447 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13390 : :
13391 : 1080447 : *walk_subtrees = 0;
13392 : 1080447 : if (!wi->is_lhs)
13393 : : return NULL_TREE;
13394 : :
13395 : 309350 : tree op = *tp;
13396 : 387468 : do
13397 : : {
13398 : 387468 : if (handled_component_p (op))
13399 : 78118 : op = TREE_OPERAND (op, 0);
13400 : 309350 : else if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
13401 : 309350 : && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
13402 : 0 : op = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
13403 : : else
13404 : : break;
13405 : : }
13406 : : while (1);
13407 : 309350 : if (!DECL_P (op) || !omp_shared_to_firstprivate_optimizable_decl_p (op))
13408 : 58221 : return NULL_TREE;
13409 : :
13410 : 251129 : omp_mark_stores (gimplify_omp_ctxp, op);
13411 : 251129 : return NULL_TREE;
13412 : : }
13413 : :
13414 : : /* Helper callback for walk_gimple_seq to discover possible stores
13415 : : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
13416 : : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
13417 : : for those. */
13418 : :
13419 : : static tree
13420 : 605883 : omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
13421 : : bool *handled_ops_p,
13422 : : struct walk_stmt_info *wi)
13423 : : {
13424 : 605883 : gimple *stmt = gsi_stmt (*gsi_p);
13425 : 605883 : switch (gimple_code (stmt))
13426 : : {
13427 : : /* Don't recurse on OpenMP constructs for which
13428 : : gimplify_adjust_omp_clauses already handled the bodies,
13429 : : except handle gimple_omp_for_pre_body. */
13430 : 26911 : case GIMPLE_OMP_FOR:
13431 : 26911 : *handled_ops_p = true;
13432 : 26911 : if (gimple_omp_for_pre_body (stmt))
13433 : 1246 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
13434 : : omp_find_stores_stmt, omp_find_stores_op, wi);
13435 : : break;
13436 : 8800 : case GIMPLE_OMP_PARALLEL:
13437 : 8800 : case GIMPLE_OMP_TASK:
13438 : 8800 : case GIMPLE_OMP_SECTIONS:
13439 : 8800 : case GIMPLE_OMP_SINGLE:
13440 : 8800 : case GIMPLE_OMP_SCOPE:
13441 : 8800 : case GIMPLE_OMP_TARGET:
13442 : 8800 : case GIMPLE_OMP_TEAMS:
13443 : 8800 : case GIMPLE_OMP_CRITICAL:
13444 : 8800 : *handled_ops_p = true;
13445 : 8800 : break;
13446 : : default:
13447 : : break;
13448 : : }
13449 : 605883 : return NULL_TREE;
13450 : : }
13451 : :
13452 : : struct gimplify_adjust_omp_clauses_data
13453 : : {
13454 : : tree *list_p;
13455 : : gimple_seq *pre_p;
13456 : : };
13457 : :
13458 : : /* For all variables that were not actually used within the context,
13459 : : remove PRIVATE, SHARED, and FIRSTPRIVATE clauses. */
13460 : :
13461 : : static int
13462 : 646884 : gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
13463 : : {
13464 : 646884 : tree *list_p = ((struct gimplify_adjust_omp_clauses_data *) data)->list_p;
13465 : 646884 : gimple_seq *pre_p
13466 : : = ((struct gimplify_adjust_omp_clauses_data *) data)->pre_p;
13467 : 646884 : tree decl = (tree) n->key;
13468 : 646884 : unsigned flags = n->value;
13469 : 646884 : enum omp_clause_code code;
13470 : 646884 : tree clause;
13471 : 646884 : bool private_debug;
13472 : :
13473 : 646884 : if (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
13474 : 123795 : && (flags & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
13475 : 646884 : flags = GOVD_SHARED | GOVD_SEEN | GOVD_WRITTEN;
13476 : 646884 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
13477 : : return 0;
13478 : 176610 : if ((flags & GOVD_SEEN) == 0)
13479 : : return 0;
13480 : 156036 : if (flags & GOVD_DEBUG_PRIVATE)
13481 : : {
13482 : 301 : gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_SHARED);
13483 : : private_debug = true;
13484 : : }
13485 : 155735 : else if (flags & GOVD_MAP)
13486 : : private_debug = false;
13487 : : else
13488 : 137903 : private_debug
13489 : 137903 : = lang_hooks.decls.omp_private_debug_clause (decl,
13490 : 137903 : !!(flags & GOVD_SHARED));
13491 : 137903 : if (private_debug)
13492 : : code = OMP_CLAUSE_PRIVATE;
13493 : 155613 : else if (flags & GOVD_MAP)
13494 : : {
13495 : 17832 : code = OMP_CLAUSE_MAP;
13496 : 17832 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0
13497 : 17832 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
13498 : : {
13499 : 2 : error ("%<_Atomic%> %qD in implicit %<map%> clause", decl);
13500 : 2 : return 0;
13501 : : }
13502 : 17830 : if (VAR_P (decl)
13503 : 15837 : && DECL_IN_CONSTANT_POOL (decl)
13504 : 17831 : && !lookup_attribute ("omp declare target",
13505 : 1 : DECL_ATTRIBUTES (decl)))
13506 : : {
13507 : 1 : tree id = get_identifier ("omp declare target");
13508 : 1 : DECL_ATTRIBUTES (decl)
13509 : 1 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
13510 : 1 : varpool_node *node = varpool_node::get (decl);
13511 : 1 : if (node)
13512 : : {
13513 : 1 : node->offloadable = 1;
13514 : 1 : if (ENABLE_OFFLOADING)
13515 : : g->have_offload = true;
13516 : : }
13517 : : }
13518 : : }
13519 : 137781 : else if (flags & GOVD_SHARED)
13520 : : {
13521 : 47636 : if (is_global_var (decl))
13522 : : {
13523 : 16597 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
13524 : 25878 : while (ctx != NULL)
13525 : : {
13526 : 17854 : splay_tree_node on
13527 : 17854 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
13528 : 17854 : if (on && (on->value & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
13529 : : | GOVD_PRIVATE | GOVD_REDUCTION
13530 : : | GOVD_LINEAR | GOVD_MAP)) != 0)
13531 : : break;
13532 : 9281 : ctx = ctx->outer_context;
13533 : : }
13534 : 16597 : if (ctx == NULL)
13535 : : return 0;
13536 : : }
13537 : 39612 : code = OMP_CLAUSE_SHARED;
13538 : : /* Don't optimize shared into firstprivate for read-only vars
13539 : : on tasks with depend clause, we shouldn't try to copy them
13540 : : until the dependencies are satisfied. */
13541 : 39612 : if (gimplify_omp_ctxp->has_depend)
13542 : 350 : flags |= GOVD_WRITTEN;
13543 : : }
13544 : 90145 : else if (flags & GOVD_PRIVATE)
13545 : : code = OMP_CLAUSE_PRIVATE;
13546 : 30630 : else if (flags & GOVD_FIRSTPRIVATE)
13547 : : {
13548 : 20969 : code = OMP_CLAUSE_FIRSTPRIVATE;
13549 : 20969 : if ((gimplify_omp_ctxp->region_type & ORT_TARGET)
13550 : 20969 : && (gimplify_omp_ctxp->region_type & ORT_ACC) == 0
13551 : 20969 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
13552 : : {
13553 : 1 : error ("%<_Atomic%> %qD in implicit %<firstprivate%> clause on "
13554 : : "%<target%> construct", decl);
13555 : 1 : return 0;
13556 : : }
13557 : : }
13558 : 9661 : else if (flags & GOVD_LASTPRIVATE)
13559 : : code = OMP_CLAUSE_LASTPRIVATE;
13560 : 270 : else if (flags & (GOVD_ALIGNED | GOVD_NONTEMPORAL))
13561 : : return 0;
13562 : 126 : else if (flags & GOVD_CONDTEMP)
13563 : : {
13564 : 126 : code = OMP_CLAUSE__CONDTEMP_;
13565 : 126 : gimple_add_tmp_var (decl);
13566 : : }
13567 : : else
13568 : 0 : gcc_unreachable ();
13569 : :
13570 : 147865 : if (((flags & GOVD_LASTPRIVATE)
13571 : 137730 : || (code == OMP_CLAUSE_SHARED && (flags & GOVD_WRITTEN)))
13572 : 154015 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
13573 : 15554 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
13574 : :
13575 : 147865 : tree chain = *list_p;
13576 : 147865 : clause = build_omp_clause (input_location, code);
13577 : 147865 : OMP_CLAUSE_DECL (clause) = decl;
13578 : 147865 : OMP_CLAUSE_CHAIN (clause) = chain;
13579 : 147865 : if (private_debug)
13580 : 423 : OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
13581 : 147442 : else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
13582 : 6 : OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
13583 : 147436 : else if (code == OMP_CLAUSE_SHARED
13584 : 39612 : && (flags & GOVD_WRITTEN) == 0
13585 : 180898 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
13586 : 19749 : OMP_CLAUSE_SHARED_READONLY (clause) = 1;
13587 : 127687 : else if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_EXPLICIT) == 0)
13588 : 20968 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clause) = 1;
13589 : 106719 : else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
13590 : : {
13591 : 620 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
13592 : 620 : OMP_CLAUSE_DECL (nc) = decl;
13593 : 620 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
13594 : 620 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
13595 : 15 : OMP_CLAUSE_DECL (clause)
13596 : 30 : = build_fold_indirect_ref_loc (input_location, decl);
13597 : 620 : OMP_CLAUSE_DECL (clause)
13598 : 620 : = build2 (MEM_REF, char_type_node, OMP_CLAUSE_DECL (clause),
13599 : 620 : build_int_cst (build_pointer_type (char_type_node), 0));
13600 : 620 : OMP_CLAUSE_SIZE (clause) = size_zero_node;
13601 : 620 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
13602 : 620 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
13603 : 620 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
13604 : 620 : tree dtype = TREE_TYPE (decl);
13605 : 620 : if (TREE_CODE (dtype) == REFERENCE_TYPE)
13606 : 15 : dtype = TREE_TYPE (dtype);
13607 : : /* FIRSTPRIVATE_POINTER doesn't work well if we have a
13608 : : multiply-indirected pointer. If we have a reference to a pointer to
13609 : : a pointer, it's possible that this should really be
13610 : : GOMP_MAP_FIRSTPRIVATE_REFERENCE -- but that also doesn't work at the
13611 : : moment, so stick with this. (See PR113279 and testcases
13612 : : baseptrs-{4,6}.C:ref2ptrptr_offset_decl_member_slice). */
13613 : 620 : if (TREE_CODE (dtype) == POINTER_TYPE
13614 : 620 : && TREE_CODE (TREE_TYPE (dtype)) == POINTER_TYPE)
13615 : 19 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
13616 : : else
13617 : 601 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
13618 : 620 : OMP_CLAUSE_CHAIN (nc) = chain;
13619 : 620 : OMP_CLAUSE_CHAIN (clause) = nc;
13620 : 620 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
13621 : 620 : gimplify_omp_ctxp = ctx->outer_context;
13622 : 620 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0),
13623 : : pre_p, NULL, is_gimple_val, fb_rvalue);
13624 : 620 : gimplify_omp_ctxp = ctx;
13625 : 620 : }
13626 : 17210 : else if (code == OMP_CLAUSE_MAP)
13627 : : {
13628 : 17210 : int kind;
13629 : : /* Not all combinations of these GOVD_MAP flags are actually valid. */
13630 : 17210 : switch (flags & (GOVD_MAP_TO_ONLY
13631 : : | GOVD_MAP_FORCE
13632 : : | GOVD_MAP_FORCE_PRESENT
13633 : : | GOVD_MAP_ALLOC_ONLY
13634 : : | GOVD_MAP_FROM_ONLY))
13635 : : {
13636 : : case 0:
13637 : : kind = GOMP_MAP_TOFROM;
13638 : : break;
13639 : 1129 : case GOVD_MAP_FORCE:
13640 : 1129 : kind = GOMP_MAP_TOFROM | GOMP_MAP_FLAG_FORCE;
13641 : 1129 : break;
13642 : 798 : case GOVD_MAP_TO_ONLY:
13643 : 798 : kind = GOMP_MAP_TO;
13644 : 798 : break;
13645 : 20 : case GOVD_MAP_FROM_ONLY:
13646 : 20 : kind = GOMP_MAP_FROM;
13647 : 20 : break;
13648 : 39 : case GOVD_MAP_ALLOC_ONLY:
13649 : 39 : kind = GOMP_MAP_ALLOC;
13650 : 39 : break;
13651 : 0 : case GOVD_MAP_TO_ONLY | GOVD_MAP_FORCE:
13652 : 0 : kind = GOMP_MAP_TO | GOMP_MAP_FLAG_FORCE;
13653 : 0 : break;
13654 : : case GOVD_MAP_FORCE_PRESENT:
13655 : 319 : kind = GOMP_MAP_FORCE_PRESENT;
13656 : : break;
13657 : : case GOVD_MAP_FORCE_PRESENT | GOVD_MAP_ALLOC_ONLY:
13658 : 319 : kind = GOMP_MAP_FORCE_PRESENT;
13659 : : break;
13660 : 0 : default:
13661 : 0 : gcc_unreachable ();
13662 : : }
13663 : 17210 : OMP_CLAUSE_SET_MAP_KIND (clause, kind);
13664 : : /* Setting of the implicit flag for the runtime is currently disabled for
13665 : : OpenACC. */
13666 : 17210 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
13667 : 9836 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1;
13668 : 17210 : if (DECL_SIZE (decl)
13669 : 17210 : && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
13670 : : {
13671 : 535 : tree decl2 = DECL_VALUE_EXPR (decl);
13672 : 535 : gcc_assert (INDIRECT_REF_P (decl2));
13673 : 535 : decl2 = TREE_OPERAND (decl2, 0);
13674 : 535 : gcc_assert (DECL_P (decl2));
13675 : 535 : tree mem = build_simple_mem_ref (decl2);
13676 : 535 : OMP_CLAUSE_DECL (clause) = mem;
13677 : 535 : OMP_CLAUSE_SIZE (clause) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
13678 : 535 : if (gimplify_omp_ctxp->outer_context)
13679 : : {
13680 : 446 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
13681 : 446 : omp_notice_variable (ctx, decl2, true);
13682 : 446 : omp_notice_variable (ctx, OMP_CLAUSE_SIZE (clause), true);
13683 : : }
13684 : 535 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
13685 : : OMP_CLAUSE_MAP);
13686 : 535 : OMP_CLAUSE_DECL (nc) = decl;
13687 : 535 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
13688 : 535 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases)
13689 : 535 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
13690 : : else
13691 : 0 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
13692 : 535 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
13693 : 535 : OMP_CLAUSE_CHAIN (clause) = nc;
13694 : : }
13695 : 16675 : else if (gimplify_omp_ctxp->target_firstprivatize_array_bases
13696 : 16675 : && omp_privatize_by_reference (decl))
13697 : : {
13698 : 26 : OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl);
13699 : 26 : OMP_CLAUSE_SIZE (clause)
13700 : 26 : = unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))));
13701 : 26 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
13702 : 26 : gimplify_omp_ctxp = ctx->outer_context;
13703 : 26 : gimplify_expr (&OMP_CLAUSE_SIZE (clause),
13704 : : pre_p, NULL, is_gimple_val, fb_rvalue);
13705 : 26 : gimplify_omp_ctxp = ctx;
13706 : 26 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
13707 : : OMP_CLAUSE_MAP);
13708 : 26 : OMP_CLAUSE_DECL (nc) = decl;
13709 : 26 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
13710 : 26 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
13711 : 26 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
13712 : 26 : OMP_CLAUSE_CHAIN (clause) = nc;
13713 : : }
13714 : : else
13715 : 16649 : OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
13716 : : }
13717 : 147865 : if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
13718 : : {
13719 : 744 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
13720 : 744 : OMP_CLAUSE_DECL (nc) = decl;
13721 : 744 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
13722 : 744 : OMP_CLAUSE_CHAIN (nc) = chain;
13723 : 744 : OMP_CLAUSE_CHAIN (clause) = nc;
13724 : 744 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
13725 : 744 : gimplify_omp_ctxp = ctx->outer_context;
13726 : 744 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
13727 : 744 : (ctx->region_type & ORT_ACC) != 0);
13728 : 744 : gimplify_omp_ctxp = ctx;
13729 : : }
13730 : 147865 : *list_p = clause;
13731 : 147865 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
13732 : 147865 : gimplify_omp_ctxp = ctx->outer_context;
13733 : : /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
13734 : : in simd. Those are only added for the local vars inside of simd body
13735 : : and they don't need to be e.g. default constructible. */
13736 : 147865 : if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
13737 : 139741 : lang_hooks.decls.omp_finish_clause (clause, pre_p,
13738 : 139741 : (ctx->region_type & ORT_ACC) != 0);
13739 : 147865 : if (gimplify_omp_ctxp)
13740 : 183793 : for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
13741 : 93317 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
13742 : 93317 : && DECL_P (OMP_CLAUSE_SIZE (clause)))
13743 : 1241 : omp_notice_variable (gimplify_omp_ctxp, OMP_CLAUSE_SIZE (clause),
13744 : : true);
13745 : 147865 : gimplify_omp_ctxp = ctx;
13746 : 147865 : return 0;
13747 : : }
13748 : :
13749 : : static void
13750 : 129715 : gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
13751 : : enum tree_code code)
13752 : : {
13753 : 129715 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
13754 : 129715 : tree *orig_list_p = list_p;
13755 : 129715 : tree c, decl;
13756 : 129715 : bool has_inscan_reductions = false;
13757 : :
13758 : 129715 : if (body)
13759 : : {
13760 : : struct gimplify_omp_ctx *octx;
13761 : 223179 : for (octx = ctx; octx; octx = octx->outer_context)
13762 : 172807 : if ((octx->region_type & (ORT_PARALLEL | ORT_TASK | ORT_TEAMS)) != 0)
13763 : : break;
13764 : 111754 : if (octx)
13765 : : {
13766 : 61382 : struct walk_stmt_info wi;
13767 : 61382 : memset (&wi, 0, sizeof (wi));
13768 : 61382 : walk_gimple_seq (body, omp_find_stores_stmt,
13769 : : omp_find_stores_op, &wi);
13770 : : }
13771 : : }
13772 : :
13773 : 129715 : if (ctx->add_safelen1)
13774 : : {
13775 : : /* If there are VLAs in the body of simd loop, prevent
13776 : : vectorization. */
13777 : 2 : gcc_assert (ctx->region_type == ORT_SIMD);
13778 : 2 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
13779 : 2 : OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node;
13780 : 2 : OMP_CLAUSE_CHAIN (c) = *list_p;
13781 : 2 : *list_p = c;
13782 : 2 : list_p = &OMP_CLAUSE_CHAIN (c);
13783 : : }
13784 : :
13785 : 129715 : if (ctx->region_type == ORT_WORKSHARE
13786 : 39880 : && ctx->outer_context
13787 : 27988 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
13788 : : {
13789 : 25246 : for (c = ctx->outer_context->clauses; c; c = OMP_CLAUSE_CHAIN (c))
13790 : 13151 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
13791 : 13151 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13792 : : {
13793 : 134 : decl = OMP_CLAUSE_DECL (c);
13794 : 134 : splay_tree_node n
13795 : 134 : = splay_tree_lookup (ctx->outer_context->variables,
13796 : : (splay_tree_key) decl);
13797 : 134 : gcc_checking_assert (!splay_tree_lookup (ctx->variables,
13798 : : (splay_tree_key) decl));
13799 : 134 : omp_add_variable (ctx, decl, n->value);
13800 : 134 : tree c2 = copy_node (c);
13801 : 134 : OMP_CLAUSE_CHAIN (c2) = *list_p;
13802 : 134 : *list_p = c2;
13803 : 134 : if ((n->value & GOVD_FIRSTPRIVATE) == 0)
13804 : 108 : continue;
13805 : 26 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
13806 : : OMP_CLAUSE_FIRSTPRIVATE);
13807 : 26 : OMP_CLAUSE_DECL (c2) = decl;
13808 : 26 : OMP_CLAUSE_CHAIN (c2) = *list_p;
13809 : 26 : *list_p = c2;
13810 : : }
13811 : : }
13812 : :
13813 : 129715 : if (code == OMP_TARGET
13814 : 129715 : || code == OMP_TARGET_DATA
13815 : 129715 : || code == OMP_TARGET_ENTER_DATA
13816 : 114654 : || code == OMP_TARGET_EXIT_DATA)
13817 : : {
13818 : 15662 : vec<omp_mapping_group> *groups;
13819 : 15662 : groups = omp_gather_mapping_groups (list_p);
13820 : 15662 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
13821 : :
13822 : 15662 : if (groups)
13823 : : {
13824 : 7288 : grpmap = omp_index_mapping_groups (groups);
13825 : :
13826 : 7288 : omp_resolve_clause_dependencies (code, groups, grpmap);
13827 : 7288 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
13828 : : &grpmap, list_p);
13829 : :
13830 : 7288 : omp_mapping_group *outlist = NULL;
13831 : :
13832 : 14576 : delete grpmap;
13833 : 7288 : delete groups;
13834 : :
13835 : : /* Rebuild now we have struct sibling lists. */
13836 : 7288 : groups = omp_gather_mapping_groups (list_p);
13837 : 7288 : grpmap = omp_index_mapping_groups (groups);
13838 : :
13839 : 7288 : bool enter_exit = (code == OMP_TARGET_ENTER_DATA
13840 : 7288 : || code == OMP_TARGET_EXIT_DATA);
13841 : :
13842 : 7288 : outlist = omp_tsort_mapping_groups (groups, grpmap, enter_exit);
13843 : 7288 : outlist = omp_segregate_mapping_groups (outlist);
13844 : 7288 : list_p = omp_reorder_mapping_groups (groups, outlist, list_p);
13845 : :
13846 : 14576 : delete grpmap;
13847 : 7288 : delete groups;
13848 : : }
13849 : 15662 : }
13850 : 114053 : else if (ctx->region_type & ORT_ACC)
13851 : : {
13852 : 29367 : vec<omp_mapping_group> *groups;
13853 : 29367 : groups = omp_gather_mapping_groups (list_p);
13854 : 29367 : if (groups)
13855 : : {
13856 : 9669 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap;
13857 : 9669 : grpmap = omp_index_mapping_groups (groups);
13858 : :
13859 : 9669 : oacc_resolve_clause_dependencies (groups, grpmap);
13860 : 9669 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
13861 : : &grpmap, list_p);
13862 : :
13863 : 9669 : delete groups;
13864 : 19338 : delete grpmap;
13865 : : }
13866 : : }
13867 : :
13868 : 129715 : tree attach_list = NULL_TREE;
13869 : 129715 : tree *attach_tail = &attach_list;
13870 : :
13871 : 129715 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
13872 : :
13873 : 377589 : while ((c = *list_p) != NULL)
13874 : : {
13875 : 247874 : splay_tree_node n;
13876 : 247874 : bool remove = false;
13877 : 247874 : bool move_attach = false;
13878 : :
13879 : 287344 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
13880 : : grp_end = NULL_TREE;
13881 : :
13882 : 247874 : switch (OMP_CLAUSE_CODE (c))
13883 : : {
13884 : 8332 : case OMP_CLAUSE_FIRSTPRIVATE:
13885 : 8332 : if ((ctx->region_type & ORT_TARGET)
13886 : 8332 : && (ctx->region_type & ORT_ACC) == 0
13887 : 8332 : && TYPE_ATOMIC (strip_array_types
13888 : : (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
13889 : : {
13890 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
13891 : : "%<_Atomic%> %qD in %<firstprivate%> clause on "
13892 : 2 : "%<target%> construct", OMP_CLAUSE_DECL (c));
13893 : 2 : remove = true;
13894 : 2 : break;
13895 : : }
13896 : 8330 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13897 : : {
13898 : 433 : decl = OMP_CLAUSE_DECL (c);
13899 : 433 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
13900 : 433 : if ((n->value & GOVD_MAP) != 0)
13901 : : {
13902 : : remove = true;
13903 : : break;
13904 : : }
13905 : 418 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0;
13906 : 418 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0;
13907 : : }
13908 : : /* FALLTHRU */
13909 : 37514 : case OMP_CLAUSE_PRIVATE:
13910 : 37514 : case OMP_CLAUSE_SHARED:
13911 : 37514 : case OMP_CLAUSE_LINEAR:
13912 : 37514 : decl = OMP_CLAUSE_DECL (c);
13913 : 37514 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
13914 : 37514 : remove = !(n->value & GOVD_SEEN);
13915 : 37514 : if ((n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0
13916 : 56 : && code == OMP_PARALLEL
13917 : 37540 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13918 : : remove = true;
13919 : 37488 : if (! remove)
13920 : : {
13921 : 32482 : bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
13922 : 32482 : if ((n->value & GOVD_DEBUG_PRIVATE)
13923 : 32482 : || lang_hooks.decls.omp_private_debug_clause (decl, shared))
13924 : : {
13925 : 83 : gcc_assert ((n->value & GOVD_DEBUG_PRIVATE) == 0
13926 : : || ((n->value & GOVD_DATA_SHARE_CLASS)
13927 : : == GOVD_SHARED));
13928 : 83 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
13929 : 83 : OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
13930 : : }
13931 : 32482 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
13932 : 4222 : && ctx->has_depend
13933 : 33040 : && DECL_P (decl))
13934 : 558 : n->value |= GOVD_WRITTEN;
13935 : 32482 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
13936 : 4222 : && (n->value & GOVD_WRITTEN) == 0
13937 : 3109 : && DECL_P (decl)
13938 : 35591 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
13939 : 583 : OMP_CLAUSE_SHARED_READONLY (c) = 1;
13940 : 31899 : else if (DECL_P (decl)
13941 : 31899 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
13942 : 3639 : && (n->value & GOVD_WRITTEN) != 0)
13943 : 30786 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
13944 : 9846 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
13945 : 39448 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
13946 : 6197 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
13947 : : }
13948 : : else
13949 : 5032 : n->value &= ~GOVD_EXPLICIT;
13950 : : break;
13951 : :
13952 : 13675 : case OMP_CLAUSE_LASTPRIVATE:
13953 : : /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
13954 : : accurately reflect the presence of a FIRSTPRIVATE clause. */
13955 : 13675 : decl = OMP_CLAUSE_DECL (c);
13956 : 13675 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
13957 : 13675 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
13958 : 13675 : = (n->value & GOVD_FIRSTPRIVATE) != 0;
13959 : 13675 : if (code == OMP_DISTRIBUTE
13960 : 13675 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
13961 : : {
13962 : 5 : remove = true;
13963 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
13964 : : "same variable used in %<firstprivate%> and "
13965 : : "%<lastprivate%> clauses on %<distribute%> "
13966 : : "construct");
13967 : : }
13968 : 13675 : if (!remove
13969 : 13670 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
13970 : 13670 : && DECL_P (decl)
13971 : 13670 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
13972 : 12045 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
13973 : 13675 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && code == OMP_PARALLEL)
13974 : 5183 : remove = true;
13975 : : break;
13976 : :
13977 : 911 : case OMP_CLAUSE_ALIGNED:
13978 : 911 : decl = OMP_CLAUSE_DECL (c);
13979 : 911 : if (!is_global_var (decl))
13980 : : {
13981 : 812 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
13982 : 812 : remove = n == NULL || !(n->value & GOVD_SEEN);
13983 : 101 : if (!remove && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
13984 : : {
13985 : 101 : struct gimplify_omp_ctx *octx;
13986 : 101 : if (n != NULL
13987 : 101 : && (n->value & (GOVD_DATA_SHARE_CLASS
13988 : : & ~GOVD_FIRSTPRIVATE)))
13989 : : remove = true;
13990 : : else
13991 : 115 : for (octx = ctx->outer_context; octx;
13992 : 14 : octx = octx->outer_context)
13993 : : {
13994 : 28 : n = splay_tree_lookup (octx->variables,
13995 : : (splay_tree_key) decl);
13996 : 28 : if (n == NULL)
13997 : 14 : continue;
13998 : 14 : if (n->value & GOVD_LOCAL)
13999 : : break;
14000 : : /* We have to avoid assigning a shared variable
14001 : : to itself when trying to add
14002 : : __builtin_assume_aligned. */
14003 : 14 : if (n->value & GOVD_SHARED)
14004 : : {
14005 : : remove = true;
14006 : : break;
14007 : : }
14008 : : }
14009 : : }
14010 : : }
14011 : 99 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
14012 : : {
14013 : 95 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
14014 : 95 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
14015 : 247874 : remove = true;
14016 : : }
14017 : : break;
14018 : :
14019 : 581 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14020 : 581 : decl = OMP_CLAUSE_DECL (c);
14021 : 581 : while (INDIRECT_REF_P (decl)
14022 : 638 : || TREE_CODE (decl) == ARRAY_REF)
14023 : 57 : decl = TREE_OPERAND (decl, 0);
14024 : 581 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
14025 : 581 : remove = n == NULL || !(n->value & GOVD_SEEN);
14026 : : break;
14027 : :
14028 : 938 : case OMP_CLAUSE_IS_DEVICE_PTR:
14029 : 938 : case OMP_CLAUSE_NONTEMPORAL:
14030 : 938 : decl = OMP_CLAUSE_DECL (c);
14031 : 938 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
14032 : 938 : remove = n == NULL || !(n->value & GOVD_SEEN);
14033 : : break;
14034 : :
14035 : 52462 : case OMP_CLAUSE_MAP:
14036 : 52462 : decl = OMP_CLAUSE_DECL (c);
14037 : 52462 : if (!grp_end)
14038 : : {
14039 : 29631 : grp_start_p = list_p;
14040 : 29631 : grp_end = *omp_group_last (grp_start_p);
14041 : : }
14042 : 52462 : switch (OMP_CLAUSE_MAP_KIND (c))
14043 : : {
14044 : 145 : case GOMP_MAP_PRESENT_ALLOC:
14045 : 145 : case GOMP_MAP_PRESENT_TO:
14046 : 145 : case GOMP_MAP_PRESENT_FROM:
14047 : 145 : case GOMP_MAP_PRESENT_TOFROM:
14048 : 145 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_PRESENT);
14049 : 145 : break;
14050 : : default:
14051 : : break;
14052 : : }
14053 : 52462 : switch (code)
14054 : : {
14055 : 4641 : case OACC_DATA:
14056 : 4641 : if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
14057 : : break;
14058 : : /* Fallthrough. */
14059 : 16891 : case OACC_HOST_DATA:
14060 : 16891 : case OACC_ENTER_DATA:
14061 : 16891 : case OACC_EXIT_DATA:
14062 : 16891 : case OMP_TARGET_DATA:
14063 : 16891 : case OMP_TARGET_ENTER_DATA:
14064 : 16891 : case OMP_TARGET_EXIT_DATA:
14065 : 16891 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
14066 : 16891 : || (OMP_CLAUSE_MAP_KIND (c)
14067 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
14068 : : /* For target {,enter ,exit }data only the array slice is
14069 : : mapped, but not the pointer to it. */
14070 : : remove = true;
14071 : 16891 : if (code == OMP_TARGET_EXIT_DATA
14072 : 16891 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
14073 : 1651 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER))
14074 : : remove = true;
14075 : : break;
14076 : : case OMP_TARGET:
14077 : : break;
14078 : : default:
14079 : : break;
14080 : : }
14081 : 16889 : if (remove)
14082 : : break;
14083 : 52105 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14084 : : {
14085 : : /* Sanity check: attach/detach map kinds use the size as a bias,
14086 : : and it's never right to use the decl size for such
14087 : : mappings. */
14088 : 16594 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
14089 : : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
14090 : : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DETACH
14091 : : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
14092 : : && (OMP_CLAUSE_MAP_KIND (c)
14093 : : != GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
14094 : 20230 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
14095 : 3636 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
14096 : : }
14097 : 52105 : gimplify_omp_ctxp = ctx->outer_context;
14098 : 52105 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p, NULL,
14099 : : is_gimple_val, fb_rvalue) == GS_ERROR)
14100 : : {
14101 : 0 : gimplify_omp_ctxp = ctx;
14102 : 0 : remove = true;
14103 : 0 : break;
14104 : : }
14105 : 52105 : else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
14106 : 49148 : || (OMP_CLAUSE_MAP_KIND (c)
14107 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
14108 : 48759 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14109 : 58112 : && TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
14110 : : {
14111 : 776 : OMP_CLAUSE_SIZE (c)
14112 : 776 : = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), pre_p, NULL,
14113 : : false);
14114 : 776 : if ((ctx->region_type & ORT_TARGET) != 0)
14115 : 600 : omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
14116 : : GOVD_FIRSTPRIVATE | GOVD_SEEN);
14117 : : }
14118 : 52105 : gimplify_omp_ctxp = ctx;
14119 : : /* Data clauses associated with reductions must be
14120 : : compatible with present_or_copy. Warn and adjust the clause
14121 : : if that is not the case. */
14122 : 52105 : if (ctx->region_type == ORT_ACC_PARALLEL
14123 : 42872 : || ctx->region_type == ORT_ACC_SERIAL)
14124 : : {
14125 : 9485 : tree t = DECL_P (decl) ? decl : TREE_OPERAND (decl, 0);
14126 : 9485 : n = NULL;
14127 : :
14128 : 9485 : if (DECL_P (t))
14129 : 7650 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
14130 : :
14131 : 7650 : if (n && (n->value & GOVD_REDUCTION))
14132 : : {
14133 : 555 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
14134 : :
14135 : 555 : OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1;
14136 : 555 : if ((kind & GOMP_MAP_TOFROM) != GOMP_MAP_TOFROM
14137 : 103 : && kind != GOMP_MAP_FORCE_PRESENT
14138 : 103 : && kind != GOMP_MAP_POINTER)
14139 : : {
14140 : 72 : warning_at (OMP_CLAUSE_LOCATION (c), 0,
14141 : : "incompatible data clause with reduction "
14142 : : "on %qE; promoting to %<present_or_copy%>",
14143 : 72 : DECL_NAME (t));
14144 : 72 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
14145 : : }
14146 : : }
14147 : : }
14148 : 52105 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
14149 : 49628 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
14150 : 52213 : && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
14151 : : {
14152 : : remove = true;
14153 : : break;
14154 : : }
14155 : : /* If we have a DECL_VALUE_EXPR (e.g. this is a class member and/or
14156 : : a variable captured in a lambda closure), look through that now
14157 : : before the DECL_P check below. (A code other than COMPONENT_REF,
14158 : : i.e. INDIRECT_REF, will be a VLA/variable-length array
14159 : : section. A global var may be a variable in a common block. We
14160 : : don't want to do this here for either of those.) */
14161 : 51707 : if ((ctx->region_type & ORT_ACC) == 0
14162 : 25226 : && DECL_P (decl)
14163 : 11249 : && !is_global_var (decl)
14164 : 9883 : && DECL_HAS_VALUE_EXPR_P (decl)
14165 : 51928 : && TREE_CODE (DECL_VALUE_EXPR (decl)) == COMPONENT_REF)
14166 : 0 : decl = OMP_CLAUSE_DECL (c) = DECL_VALUE_EXPR (decl);
14167 : 51707 : if (TREE_CODE (decl) == TARGET_EXPR)
14168 : : {
14169 : 0 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
14170 : : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
14171 : 24815 : remove = true;
14172 : : }
14173 : 51707 : else if (!DECL_P (decl))
14174 : : {
14175 : 26892 : if ((ctx->region_type & ORT_TARGET) != 0
14176 : 26892 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14177 : : {
14178 : 27 : if (INDIRECT_REF_P (decl)
14179 : 0 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
14180 : 27 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
14181 : : == REFERENCE_TYPE))
14182 : 0 : decl = TREE_OPERAND (decl, 0);
14183 : 27 : if (TREE_CODE (decl) == COMPONENT_REF)
14184 : : {
14185 : 0 : while (TREE_CODE (decl) == COMPONENT_REF)
14186 : 0 : decl = TREE_OPERAND (decl, 0);
14187 : 0 : if (DECL_P (decl))
14188 : : {
14189 : 0 : n = splay_tree_lookup (ctx->variables,
14190 : : (splay_tree_key) decl);
14191 : 0 : if (!(n->value & GOVD_SEEN))
14192 : 26892 : remove = true;
14193 : : }
14194 : : }
14195 : : }
14196 : :
14197 : 26892 : tree d = decl, *pd;
14198 : 26892 : if (TREE_CODE (d) == ARRAY_REF)
14199 : : {
14200 : 5725 : while (TREE_CODE (d) == ARRAY_REF)
14201 : 2931 : d = TREE_OPERAND (d, 0);
14202 : 2794 : if (TREE_CODE (d) == COMPONENT_REF
14203 : 2794 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
14204 : : decl = d;
14205 : : }
14206 : 26892 : pd = &OMP_CLAUSE_DECL (c);
14207 : 26892 : if (d == decl
14208 : 24451 : && TREE_CODE (decl) == INDIRECT_REF
14209 : 14601 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
14210 : 1386 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
14211 : : == REFERENCE_TYPE)
14212 : 27693 : && (OMP_CLAUSE_MAP_KIND (c)
14213 : : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
14214 : : {
14215 : 796 : pd = &TREE_OPERAND (decl, 0);
14216 : 796 : decl = TREE_OPERAND (decl, 0);
14217 : : }
14218 : :
14219 : 26892 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14220 : 2450 : switch (code)
14221 : : {
14222 : 430 : case OACC_ENTER_DATA:
14223 : 430 : case OACC_EXIT_DATA:
14224 : 430 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
14225 : : == ARRAY_TYPE)
14226 : : remove = true;
14227 : 420 : else if (code == OACC_ENTER_DATA)
14228 : 264 : goto change_to_attach;
14229 : : /* Fallthrough. */
14230 : 331 : case OMP_TARGET_EXIT_DATA:
14231 : 331 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DETACH);
14232 : 331 : break;
14233 : 71 : case OACC_UPDATE:
14234 : : /* An "attach/detach" operation on an update directive
14235 : : should behave as a GOMP_MAP_ALWAYS_POINTER. Note that
14236 : : both GOMP_MAP_ATTACH_DETACH and GOMP_MAP_ALWAYS_POINTER
14237 : : kinds depend on the previous mapping (for non-TARGET
14238 : : regions). */
14239 : 71 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
14240 : 71 : break;
14241 : 2048 : default:
14242 : 2048 : change_to_attach:
14243 : 2048 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH);
14244 : 2048 : if ((ctx->region_type & ORT_TARGET) != 0)
14245 : 1652 : move_attach = true;
14246 : : }
14247 : 24442 : else if ((ctx->region_type & ORT_TARGET) != 0
14248 : 24442 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
14249 : 11162 : || (OMP_CLAUSE_MAP_KIND (c)
14250 : : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
14251 : : move_attach = true;
14252 : :
14253 : : /* If we have e.g. map(struct: *var), don't gimplify the
14254 : : argument since omp-low.cc wants to see the decl itself. */
14255 : 26892 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
14256 : : break;
14257 : :
14258 : : /* We've already partly gimplified this in
14259 : : gimplify_scan_omp_clauses. Don't do any more. */
14260 : 25776 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
14261 : : break;
14262 : :
14263 : 25688 : gimplify_omp_ctxp = ctx->outer_context;
14264 : 25688 : if (gimplify_expr (pd, pre_p, NULL, is_gimple_lvalue,
14265 : : fb_lvalue) == GS_ERROR)
14266 : 0 : remove = true;
14267 : 25688 : gimplify_omp_ctxp = ctx;
14268 : 25688 : break;
14269 : : }
14270 : :
14271 : 24815 : if ((code == OMP_TARGET
14272 : : || code == OMP_TARGET_DATA
14273 : : || code == OMP_TARGET_ENTER_DATA
14274 : 14412 : || code == OMP_TARGET_EXIT_DATA)
14275 : 25339 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14276 : : {
14277 : 211 : bool firstprivatize = false;
14278 : :
14279 : 216 : for (struct gimplify_omp_ctx *octx = ctx->outer_context; octx;
14280 : 5 : octx = octx->outer_context)
14281 : : {
14282 : 6 : splay_tree_node n
14283 : 12 : = splay_tree_lookup (octx->variables,
14284 : 6 : (splay_tree_key) OMP_CLAUSE_DECL (c));
14285 : : /* If this is contained in an outer OpenMP region as a
14286 : : firstprivate value, remove the attach/detach. */
14287 : 6 : if (n && (n->value & GOVD_FIRSTPRIVATE))
14288 : : {
14289 : : firstprivatize = true;
14290 : : break;
14291 : : }
14292 : : }
14293 : :
14294 : 211 : enum gomp_map_kind map_kind;
14295 : 211 : if (firstprivatize)
14296 : : map_kind = GOMP_MAP_FIRSTPRIVATE_POINTER;
14297 : 210 : else if (code == OMP_TARGET_EXIT_DATA)
14298 : : map_kind = GOMP_MAP_DETACH;
14299 : : else
14300 : 166 : map_kind = GOMP_MAP_ATTACH;
14301 : 211 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
14302 : : }
14303 : 24604 : else if ((ctx->region_type & ORT_ACC) != 0
14304 : 24604 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14305 : : {
14306 : 0 : enum gomp_map_kind map_kind = (code == OACC_EXIT_DATA
14307 : 0 : ? GOMP_MAP_DETACH
14308 : : : GOMP_MAP_ATTACH);
14309 : 0 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
14310 : : }
14311 : :
14312 : 24815 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
14313 : 24815 : if ((ctx->region_type & ORT_TARGET) != 0
14314 : 15136 : && !(n->value & GOVD_SEEN)
14315 : 1476 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) == 0
14316 : 26065 : && (!is_global_var (decl)
14317 : 80 : || !lookup_attribute ("omp declare target link",
14318 : 80 : DECL_ATTRIBUTES (decl))))
14319 : : {
14320 : 1239 : remove = true;
14321 : : /* For struct element mapping, if struct is never referenced
14322 : : in target block and none of the mapping has always modifier,
14323 : : remove all the struct element mappings, which immediately
14324 : : follow the GOMP_MAP_STRUCT map clause. */
14325 : 1239 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
14326 : 1239 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
14327 : : {
14328 : 35 : HOST_WIDE_INT cnt = tree_to_shwi (OMP_CLAUSE_SIZE (c));
14329 : 95 : while (cnt--)
14330 : 60 : OMP_CLAUSE_CHAIN (c)
14331 : 60 : = OMP_CLAUSE_CHAIN (OMP_CLAUSE_CHAIN (c));
14332 : : }
14333 : : }
14334 : 23576 : else if (DECL_SIZE (decl)
14335 : 23546 : && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST
14336 : 229 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER
14337 : 229 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
14338 : 23629 : && (OMP_CLAUSE_MAP_KIND (c)
14339 : : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
14340 : : {
14341 : : /* For GOMP_MAP_FORCE_DEVICEPTR, we'll never enter here, because
14342 : : for these, TREE_CODE (DECL_SIZE (decl)) will always be
14343 : : INTEGER_CST. */
14344 : 53 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
14345 : :
14346 : 53 : tree decl2 = DECL_VALUE_EXPR (decl);
14347 : 53 : gcc_assert (INDIRECT_REF_P (decl2));
14348 : 53 : decl2 = TREE_OPERAND (decl2, 0);
14349 : 53 : gcc_assert (DECL_P (decl2));
14350 : 53 : tree mem = build_simple_mem_ref (decl2);
14351 : 53 : OMP_CLAUSE_DECL (c) = mem;
14352 : 53 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
14353 : 53 : if (ctx->outer_context)
14354 : : {
14355 : 15 : omp_notice_variable (ctx->outer_context, decl2, true);
14356 : 30 : omp_notice_variable (ctx->outer_context,
14357 : 15 : OMP_CLAUSE_SIZE (c), true);
14358 : : }
14359 : 53 : if (((ctx->region_type & ORT_TARGET) != 0
14360 : 25 : || !ctx->target_firstprivatize_array_bases)
14361 : 35 : && ((n->value & GOVD_SEEN) == 0
14362 : 31 : || (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0))
14363 : : {
14364 : 35 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
14365 : : OMP_CLAUSE_MAP);
14366 : 35 : OMP_CLAUSE_DECL (nc) = decl;
14367 : 35 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
14368 : 35 : if (ctx->target_firstprivatize_array_bases)
14369 : 28 : OMP_CLAUSE_SET_MAP_KIND (nc,
14370 : : GOMP_MAP_FIRSTPRIVATE_POINTER);
14371 : : else
14372 : 7 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
14373 : 35 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
14374 : 35 : OMP_CLAUSE_CHAIN (c) = nc;
14375 : 35 : c = nc;
14376 : : }
14377 : : }
14378 : : else
14379 : : {
14380 : 23523 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14381 : 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
14382 : 23523 : gcc_assert ((n->value & GOVD_SEEN) == 0
14383 : : || ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
14384 : : == 0));
14385 : : }
14386 : :
14387 : : /* If we have a target region, we can push all the attaches to the
14388 : : end of the list (we may have standalone "attach" operations
14389 : : synthesized for GOMP_MAP_STRUCT nodes that must be processed after
14390 : : the attachment point AND the pointed-to block have been mapped).
14391 : : If we have something else, e.g. "enter data", we need to keep
14392 : : "attach" nodes together with the previous node they attach to so
14393 : : that separate "exit data" operations work properly (see
14394 : : libgomp/target.c). */
14395 : 24815 : if ((ctx->region_type & ORT_TARGET) != 0
14396 : 24815 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
14397 : 15034 : || (OMP_CLAUSE_MAP_KIND (c)
14398 : : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
14399 : : move_attach = true;
14400 : :
14401 : : break;
14402 : :
14403 : 8341 : case OMP_CLAUSE_TO:
14404 : 8341 : case OMP_CLAUSE_FROM:
14405 : 8341 : case OMP_CLAUSE__CACHE_:
14406 : 8341 : decl = OMP_CLAUSE_DECL (c);
14407 : 8341 : if (!DECL_P (decl))
14408 : : break;
14409 : 6218 : if (DECL_SIZE (decl)
14410 : 6218 : && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
14411 : : {
14412 : 4 : tree decl2 = DECL_VALUE_EXPR (decl);
14413 : 4 : gcc_assert (INDIRECT_REF_P (decl2));
14414 : 4 : decl2 = TREE_OPERAND (decl2, 0);
14415 : 4 : gcc_assert (DECL_P (decl2));
14416 : 4 : tree mem = build_simple_mem_ref (decl2);
14417 : 4 : OMP_CLAUSE_DECL (c) = mem;
14418 : 4 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
14419 : 4 : if (ctx->outer_context)
14420 : : {
14421 : 4 : omp_notice_variable (ctx->outer_context, decl2, true);
14422 : 8 : omp_notice_variable (ctx->outer_context,
14423 : 4 : OMP_CLAUSE_SIZE (c), true);
14424 : : }
14425 : : }
14426 : 6214 : else if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14427 : 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
14428 : : break;
14429 : :
14430 : 15279 : case OMP_CLAUSE_REDUCTION:
14431 : 15279 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
14432 : : {
14433 : 860 : decl = OMP_CLAUSE_DECL (c);
14434 : 860 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
14435 : 860 : if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
14436 : : {
14437 : 61 : remove = true;
14438 : 61 : error_at (OMP_CLAUSE_LOCATION (c),
14439 : : "%qD specified in %<inscan%> %<reduction%> clause "
14440 : : "but not in %<scan%> directive clause", decl);
14441 : 61 : break;
14442 : : }
14443 : : has_inscan_reductions = true;
14444 : : }
14445 : : /* FALLTHRU */
14446 : 17909 : case OMP_CLAUSE_IN_REDUCTION:
14447 : 17909 : case OMP_CLAUSE_TASK_REDUCTION:
14448 : 17909 : decl = OMP_CLAUSE_DECL (c);
14449 : : /* OpenACC reductions need a present_or_copy data clause.
14450 : : Add one if necessary. Emit error when the reduction is private. */
14451 : 17909 : if (ctx->region_type == ORT_ACC_PARALLEL
14452 : 17419 : || ctx->region_type == ORT_ACC_SERIAL)
14453 : : {
14454 : 549 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
14455 : 549 : if (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
14456 : : {
14457 : 13 : remove = true;
14458 : 13 : error_at (OMP_CLAUSE_LOCATION (c), "invalid private "
14459 : 13 : "reduction on %qE", DECL_NAME (decl));
14460 : : }
14461 : 536 : else if ((n->value & GOVD_MAP) == 0)
14462 : : {
14463 : 339 : tree next = OMP_CLAUSE_CHAIN (c);
14464 : 339 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP);
14465 : 339 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM);
14466 : 339 : OMP_CLAUSE_DECL (nc) = decl;
14467 : 339 : OMP_CLAUSE_CHAIN (c) = nc;
14468 : 339 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
14469 : 339 : (ctx->region_type
14470 : : & ORT_ACC) != 0);
14471 : 365 : while (1)
14472 : : {
14473 : 352 : OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1;
14474 : 352 : if (OMP_CLAUSE_CHAIN (nc) == NULL)
14475 : : break;
14476 : 13 : nc = OMP_CLAUSE_CHAIN (nc);
14477 : : }
14478 : 339 : OMP_CLAUSE_CHAIN (nc) = next;
14479 : 339 : n->value |= GOVD_MAP;
14480 : : }
14481 : : }
14482 : 17909 : if (DECL_P (decl)
14483 : 17909 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
14484 : 7409 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
14485 : : break;
14486 : :
14487 : 3975 : case OMP_CLAUSE_ALLOCATE:
14488 : 3975 : decl = OMP_CLAUSE_DECL (c);
14489 : 3975 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
14490 : 3975 : if (n != NULL && !(n->value & GOVD_SEEN))
14491 : : {
14492 : 1306 : if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
14493 : : != 0
14494 : 1306 : && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
14495 : : remove = true;
14496 : : }
14497 : : if (!remove
14498 : 2669 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
14499 : 1240 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
14500 : 488 : && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
14501 : 362 : || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
14502 : 302 : || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
14503 : : {
14504 : 208 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
14505 : 208 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
14506 : 208 : if (n == NULL)
14507 : : {
14508 : 88 : enum omp_clause_default_kind default_kind
14509 : : = ctx->default_kind;
14510 : 88 : ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
14511 : 88 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
14512 : : true);
14513 : 88 : ctx->default_kind = default_kind;
14514 : : }
14515 : : else
14516 : 120 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
14517 : : true);
14518 : : }
14519 : : break;
14520 : :
14521 : : case OMP_CLAUSE_COPYIN:
14522 : : case OMP_CLAUSE_COPYPRIVATE:
14523 : : case OMP_CLAUSE_IF:
14524 : : case OMP_CLAUSE_SELF:
14525 : : case OMP_CLAUSE_NUM_THREADS:
14526 : : case OMP_CLAUSE_NUM_TEAMS:
14527 : : case OMP_CLAUSE_THREAD_LIMIT:
14528 : : case OMP_CLAUSE_DIST_SCHEDULE:
14529 : : case OMP_CLAUSE_DEVICE:
14530 : : case OMP_CLAUSE_SCHEDULE:
14531 : : case OMP_CLAUSE_NOWAIT:
14532 : : case OMP_CLAUSE_ORDERED:
14533 : : case OMP_CLAUSE_DEFAULT:
14534 : : case OMP_CLAUSE_UNTIED:
14535 : : case OMP_CLAUSE_COLLAPSE:
14536 : : case OMP_CLAUSE_FINAL:
14537 : : case OMP_CLAUSE_MERGEABLE:
14538 : : case OMP_CLAUSE_PROC_BIND:
14539 : : case OMP_CLAUSE_SAFELEN:
14540 : : case OMP_CLAUSE_SIMDLEN:
14541 : : case OMP_CLAUSE_DEPEND:
14542 : : case OMP_CLAUSE_DOACROSS:
14543 : : case OMP_CLAUSE_PRIORITY:
14544 : : case OMP_CLAUSE_GRAINSIZE:
14545 : : case OMP_CLAUSE_NUM_TASKS:
14546 : : case OMP_CLAUSE_NOGROUP:
14547 : : case OMP_CLAUSE_THREADS:
14548 : : case OMP_CLAUSE_SIMD:
14549 : : case OMP_CLAUSE_FILTER:
14550 : : case OMP_CLAUSE_HINT:
14551 : : case OMP_CLAUSE_DEFAULTMAP:
14552 : : case OMP_CLAUSE_ORDER:
14553 : : case OMP_CLAUSE_BIND:
14554 : : case OMP_CLAUSE_DETACH:
14555 : : case OMP_CLAUSE_USE_DEVICE_PTR:
14556 : : case OMP_CLAUSE_USE_DEVICE_ADDR:
14557 : : case OMP_CLAUSE_ASYNC:
14558 : : case OMP_CLAUSE_WAIT:
14559 : : case OMP_CLAUSE_INDEPENDENT:
14560 : : case OMP_CLAUSE_NUM_GANGS:
14561 : : case OMP_CLAUSE_NUM_WORKERS:
14562 : : case OMP_CLAUSE_VECTOR_LENGTH:
14563 : : case OMP_CLAUSE_GANG:
14564 : : case OMP_CLAUSE_WORKER:
14565 : : case OMP_CLAUSE_VECTOR:
14566 : : case OMP_CLAUSE_AUTO:
14567 : : case OMP_CLAUSE_SEQ:
14568 : : case OMP_CLAUSE_TILE:
14569 : : case OMP_CLAUSE_IF_PRESENT:
14570 : : case OMP_CLAUSE_FINALIZE:
14571 : : case OMP_CLAUSE_INCLUSIVE:
14572 : : case OMP_CLAUSE_EXCLUSIVE:
14573 : : break;
14574 : :
14575 : 0 : case OMP_CLAUSE_NOHOST:
14576 : 0 : default:
14577 : 0 : gcc_unreachable ();
14578 : : }
14579 : :
14580 : 247874 : if (remove)
14581 : 10455 : *list_p = OMP_CLAUSE_CHAIN (c);
14582 : 237419 : else if (move_attach)
14583 : : {
14584 : : /* Remove attach node from here, separate out into its own list. */
14585 : 2162 : *attach_tail = c;
14586 : 2162 : *list_p = OMP_CLAUSE_CHAIN (c);
14587 : 2162 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
14588 : 2162 : attach_tail = &OMP_CLAUSE_CHAIN (c);
14589 : : }
14590 : : else
14591 : 235257 : list_p = &OMP_CLAUSE_CHAIN (c);
14592 : : }
14593 : :
14594 : : /* Splice attach nodes at the end of the list. */
14595 : 129715 : if (attach_list)
14596 : : {
14597 : 1046 : *list_p = attach_list;
14598 : 1046 : list_p = attach_tail;
14599 : : }
14600 : :
14601 : : /* Add in any implicit data sharing. */
14602 : 129715 : struct gimplify_adjust_omp_clauses_data data;
14603 : 129715 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
14604 : : {
14605 : : /* OpenMP. Implicit clauses are added at the start of the clause list,
14606 : : but after any non-map clauses. */
14607 : : tree *implicit_add_list_p = orig_list_p;
14608 : 257066 : while (*implicit_add_list_p
14609 : 257066 : && OMP_CLAUSE_CODE (*implicit_add_list_p) != OMP_CLAUSE_MAP)
14610 : 156718 : implicit_add_list_p = &OMP_CLAUSE_CHAIN (*implicit_add_list_p);
14611 : 100348 : data.list_p = implicit_add_list_p;
14612 : : }
14613 : : else
14614 : : /* OpenACC. */
14615 : 29367 : data.list_p = list_p;
14616 : 129715 : data.pre_p = pre_p;
14617 : 129715 : splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
14618 : :
14619 : 129715 : if (has_inscan_reductions)
14620 : 2658 : for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
14621 : 1993 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14622 : 1993 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14623 : : {
14624 : 6 : error_at (OMP_CLAUSE_LOCATION (c),
14625 : : "%<inscan%> %<reduction%> clause used together with "
14626 : : "%<linear%> clause for a variable other than loop "
14627 : : "iterator");
14628 : 6 : break;
14629 : : }
14630 : :
14631 : 129715 : gimplify_omp_ctxp = ctx->outer_context;
14632 : 129715 : delete_omp_context (ctx);
14633 : 129715 : }
14634 : :
14635 : : /* Return 0 if CONSTRUCTS selectors don't match the OpenMP context,
14636 : : -1 if unknown yet (simd is involved, won't be known until vectorization)
14637 : : and 1 if they do. If SCORES is non-NULL, it should point to an array
14638 : : of at least 2*NCONSTRUCTS+2 ints, and will be filled with the positions
14639 : : of the CONSTRUCTS (position -1 if it will never match) followed by
14640 : : number of constructs in the OpenMP context construct trait. If the
14641 : : score depends on whether it will be in a declare simd clone or not,
14642 : : the function returns 2 and there will be two sets of the scores, the first
14643 : : one for the case that it is not in a declare simd clone, the other
14644 : : that it is in a declare simd clone. */
14645 : :
14646 : : int
14647 : 499 : omp_construct_selector_matches (enum tree_code *constructs, int nconstructs,
14648 : : int *scores)
14649 : : {
14650 : 499 : int matched = 0, cnt = 0;
14651 : 499 : bool simd_seen = false;
14652 : 499 : bool target_seen = false;
14653 : 499 : int declare_simd_cnt = -1;
14654 : 499 : auto_vec<enum tree_code, 16> codes;
14655 : 1371 : for (struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; ctx;)
14656 : : {
14657 : 882 : if (((ctx->region_type & ORT_PARALLEL) && ctx->code == OMP_PARALLEL)
14658 : 552 : || ((ctx->region_type & (ORT_TARGET | ORT_IMPLICIT_TARGET | ORT_ACC))
14659 : 552 : == ORT_TARGET && ctx->code == OMP_TARGET)
14660 : 542 : || ((ctx->region_type & ORT_TEAMS) && ctx->code == OMP_TEAMS)
14661 : 452 : || (ctx->region_type == ORT_WORKSHARE && ctx->code == OMP_FOR)
14662 : 983 : || (ctx->region_type == ORT_SIMD
14663 : : && ctx->code == OMP_SIMD
14664 : 72 : && !omp_find_clause (ctx->clauses, OMP_CLAUSE_BIND)))
14665 : : {
14666 : 853 : ++cnt;
14667 : 853 : if (scores)
14668 : 310 : codes.safe_push (ctx->code);
14669 : 543 : else if (matched < nconstructs && ctx->code == constructs[matched])
14670 : : {
14671 : 366 : if (ctx->code == OMP_SIMD)
14672 : : {
14673 : 52 : if (matched)
14674 : : return 0;
14675 : : simd_seen = true;
14676 : : }
14677 : 366 : ++matched;
14678 : : }
14679 : 853 : if (ctx->code == OMP_TARGET)
14680 : : {
14681 : 10 : if (scores == NULL)
14682 : 6 : return matched < nconstructs ? 0 : simd_seen ? -1 : 1;
14683 : : target_seen = true;
14684 : : break;
14685 : : }
14686 : : }
14687 : 29 : else if (ctx->region_type == ORT_WORKSHARE
14688 : 29 : && ctx->code == OMP_LOOP
14689 : 0 : && ctx->outer_context
14690 : 0 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL
14691 : 0 : && ctx->outer_context->outer_context
14692 : 0 : && ctx->outer_context->outer_context->code == OMP_LOOP
14693 : 0 : && ctx->outer_context->outer_context->distribute)
14694 : 872 : ctx = ctx->outer_context->outer_context;
14695 : 872 : ctx = ctx->outer_context;
14696 : : }
14697 : 495 : if (!target_seen
14698 : 984 : && lookup_attribute ("omp declare simd",
14699 : 489 : DECL_ATTRIBUTES (current_function_decl)))
14700 : : {
14701 : : /* Declare simd is a maybe case, it is supposed to be added only to the
14702 : : omp-simd-clone.cc added clones and not to the base function. */
14703 : 120 : declare_simd_cnt = cnt++;
14704 : 120 : if (scores)
14705 : 120 : codes.safe_push (OMP_SIMD);
14706 : 0 : else if (cnt == 0
14707 : 0 : && constructs[0] == OMP_SIMD)
14708 : : {
14709 : 0 : gcc_assert (matched == 0);
14710 : 0 : simd_seen = true;
14711 : 0 : if (++matched == nconstructs)
14712 : : return -1;
14713 : : }
14714 : : }
14715 : 495 : if (tree attr = lookup_attribute ("omp declare variant variant",
14716 : 495 : DECL_ATTRIBUTES (current_function_decl)))
14717 : : {
14718 : 4 : tree selectors = TREE_VALUE (attr);
14719 : 4 : int variant_nconstructs = list_length (selectors);
14720 : 4 : enum tree_code *variant_constructs = NULL;
14721 : 4 : if (!target_seen && variant_nconstructs)
14722 : : {
14723 : 2 : variant_constructs
14724 : 2 : = (enum tree_code *) alloca (variant_nconstructs
14725 : : * sizeof (enum tree_code));
14726 : 2 : omp_construct_traits_to_codes (selectors, variant_nconstructs,
14727 : : variant_constructs);
14728 : : }
14729 : 8 : for (int i = 0; i < variant_nconstructs; i++)
14730 : : {
14731 : 4 : ++cnt;
14732 : 4 : if (scores)
14733 : 0 : codes.safe_push (variant_constructs[i]);
14734 : 4 : else if (matched < nconstructs
14735 : 4 : && variant_constructs[i] == constructs[matched])
14736 : : {
14737 : 4 : if (variant_constructs[i] == OMP_SIMD)
14738 : : {
14739 : 0 : if (matched)
14740 : : return 0;
14741 : : simd_seen = true;
14742 : : }
14743 : 4 : ++matched;
14744 : : }
14745 : : }
14746 : : }
14747 : 495 : if (!target_seen
14748 : 984 : && lookup_attribute ("omp declare target block",
14749 : 489 : DECL_ATTRIBUTES (current_function_decl)))
14750 : : {
14751 : 1 : if (scores)
14752 : 0 : codes.safe_push (OMP_TARGET);
14753 : 1 : else if (matched < nconstructs && constructs[matched] == OMP_TARGET)
14754 : 1 : ++matched;
14755 : : }
14756 : 495 : if (scores)
14757 : : {
14758 : 892 : for (int pass = 0; pass < (declare_simd_cnt == -1 ? 1 : 2); pass++)
14759 : : {
14760 : 326 : int j = codes.length () - 1;
14761 : 448 : for (int i = nconstructs - 1; i >= 0; i--)
14762 : : {
14763 : : while (j >= 0
14764 : 220 : && (pass != 0 || declare_simd_cnt != j)
14765 : 440 : && constructs[i] != codes[j])
14766 : 98 : --j;
14767 : 122 : if (pass == 0 && declare_simd_cnt != -1 && j > declare_simd_cnt)
14768 : 0 : *scores++ = j - 1;
14769 : : else
14770 : 122 : *scores++ = j;
14771 : : }
14772 : 326 : *scores++ = ((pass == 0 && declare_simd_cnt != -1)
14773 : 652 : ? codes.length () - 1 : codes.length ());
14774 : : }
14775 : 206 : return declare_simd_cnt == -1 ? 1 : 2;
14776 : : }
14777 : 289 : if (matched == nconstructs)
14778 : 318 : return simd_seen ? -1 : 1;
14779 : : return 0;
14780 : 499 : }
14781 : :
14782 : : /* Gimplify OACC_CACHE. */
14783 : :
14784 : : static void
14785 : 855 : gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
14786 : : {
14787 : 855 : tree expr = *expr_p;
14788 : :
14789 : 855 : gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_ACC,
14790 : : OACC_CACHE);
14791 : 855 : gimplify_adjust_omp_clauses (pre_p, NULL, &OACC_CACHE_CLAUSES (expr),
14792 : : OACC_CACHE);
14793 : :
14794 : : /* TODO: Do something sensible with this information. */
14795 : :
14796 : 855 : *expr_p = NULL_TREE;
14797 : 855 : }
14798 : :
14799 : : /* Helper function of gimplify_oacc_declare. The helper's purpose is to,
14800 : : if required, translate 'kind' in CLAUSE into an 'entry' kind and 'exit'
14801 : : kind. The entry kind will replace the one in CLAUSE, while the exit
14802 : : kind will be used in a new omp_clause and returned to the caller. */
14803 : :
14804 : : static tree
14805 : 232 : gimplify_oacc_declare_1 (tree clause)
14806 : : {
14807 : 232 : HOST_WIDE_INT kind, new_op;
14808 : 232 : bool ret = false;
14809 : 232 : tree c = NULL;
14810 : :
14811 : 232 : kind = OMP_CLAUSE_MAP_KIND (clause);
14812 : :
14813 : 232 : switch (kind)
14814 : : {
14815 : : case GOMP_MAP_ALLOC:
14816 : : new_op = GOMP_MAP_RELEASE;
14817 : : ret = true;
14818 : : break;
14819 : :
14820 : 35 : case GOMP_MAP_FROM:
14821 : 35 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_ALLOC);
14822 : 35 : new_op = GOMP_MAP_FROM;
14823 : 35 : ret = true;
14824 : 35 : break;
14825 : :
14826 : 48 : case GOMP_MAP_TOFROM:
14827 : 48 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_TO);
14828 : 48 : new_op = GOMP_MAP_FROM;
14829 : 48 : ret = true;
14830 : 48 : break;
14831 : :
14832 : : case GOMP_MAP_DEVICE_RESIDENT:
14833 : : case GOMP_MAP_FORCE_DEVICEPTR:
14834 : : case GOMP_MAP_FORCE_PRESENT:
14835 : : case GOMP_MAP_LINK:
14836 : : case GOMP_MAP_POINTER:
14837 : : case GOMP_MAP_TO:
14838 : : break;
14839 : :
14840 : 0 : default:
14841 : 0 : gcc_unreachable ();
14842 : 83 : break;
14843 : : }
14844 : :
14845 : 83 : if (ret)
14846 : : {
14847 : 140 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clause), OMP_CLAUSE_MAP);
14848 : 140 : OMP_CLAUSE_SET_MAP_KIND (c, new_op);
14849 : 140 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clause);
14850 : : }
14851 : :
14852 : 232 : return c;
14853 : : }
14854 : :
14855 : : /* Gimplify OACC_DECLARE. */
14856 : :
14857 : : static void
14858 : 312 : gimplify_oacc_declare (tree *expr_p, gimple_seq *pre_p)
14859 : : {
14860 : 312 : tree expr = *expr_p;
14861 : 312 : gomp_target *stmt;
14862 : 312 : tree clauses, t, decl;
14863 : :
14864 : 312 : clauses = OACC_DECLARE_CLAUSES (expr);
14865 : :
14866 : 312 : gimplify_scan_omp_clauses (&clauses, pre_p, ORT_TARGET_DATA, OACC_DECLARE);
14867 : 312 : gimplify_adjust_omp_clauses (pre_p, NULL, &clauses, OACC_DECLARE);
14868 : :
14869 : 634 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
14870 : : {
14871 : 322 : decl = OMP_CLAUSE_DECL (t);
14872 : :
14873 : 322 : if (TREE_CODE (decl) == MEM_REF)
14874 : 9 : decl = TREE_OPERAND (decl, 0);
14875 : :
14876 : 322 : if (VAR_P (decl) && !is_oacc_declared (decl))
14877 : : {
14878 : 322 : tree attr = get_identifier ("oacc declare target");
14879 : 322 : DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE,
14880 : 322 : DECL_ATTRIBUTES (decl));
14881 : : }
14882 : :
14883 : 322 : if (VAR_P (decl)
14884 : 322 : && !is_global_var (decl)
14885 : 554 : && DECL_CONTEXT (decl) == current_function_decl)
14886 : : {
14887 : 232 : tree c = gimplify_oacc_declare_1 (t);
14888 : 232 : if (c)
14889 : : {
14890 : 140 : if (oacc_declare_returns == NULL)
14891 : 46 : oacc_declare_returns = new hash_map<tree, tree>;
14892 : :
14893 : 140 : oacc_declare_returns->put (decl, c);
14894 : : }
14895 : : }
14896 : :
14897 : 322 : if (gimplify_omp_ctxp)
14898 : 89 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_SEEN);
14899 : : }
14900 : :
14901 : 312 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
14902 : : clauses);
14903 : :
14904 : 312 : gimplify_seq_add_stmt (pre_p, stmt);
14905 : :
14906 : 312 : *expr_p = NULL_TREE;
14907 : 312 : }
14908 : :
14909 : : /* Gimplify the contents of an OMP_PARALLEL statement. This involves
14910 : : gimplification of the body, as well as scanning the body for used
14911 : : variables. We need to do this scan now, because variable-sized
14912 : : decls will be decomposed during gimplification. */
14913 : :
14914 : : static void
14915 : 18253 : gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
14916 : : {
14917 : 18253 : tree expr = *expr_p;
14918 : 18253 : gimple *g;
14919 : 18253 : gimple_seq body = NULL;
14920 : :
14921 : 36506 : gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
14922 : 18253 : OMP_PARALLEL_COMBINED (expr)
14923 : : ? ORT_COMBINED_PARALLEL
14924 : : : ORT_PARALLEL, OMP_PARALLEL);
14925 : :
14926 : 18253 : push_gimplify_context ();
14927 : :
14928 : 18253 : g = gimplify_and_return_first (OMP_PARALLEL_BODY (expr), &body);
14929 : 18253 : if (gimple_code (g) == GIMPLE_BIND)
14930 : 18253 : pop_gimplify_context (g);
14931 : : else
14932 : 0 : pop_gimplify_context (NULL);
14933 : :
14934 : 18253 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_PARALLEL_CLAUSES (expr),
14935 : : OMP_PARALLEL);
14936 : :
14937 : 36506 : g = gimple_build_omp_parallel (body,
14938 : 18253 : OMP_PARALLEL_CLAUSES (expr),
14939 : : NULL_TREE, NULL_TREE);
14940 : 18253 : if (OMP_PARALLEL_COMBINED (expr))
14941 : 12295 : gimple_omp_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
14942 : 18253 : gimplify_seq_add_stmt (pre_p, g);
14943 : 18253 : *expr_p = NULL_TREE;
14944 : 18253 : }
14945 : :
14946 : : /* Gimplify the contents of an OMP_TASK statement. This involves
14947 : : gimplification of the body, as well as scanning the body for used
14948 : : variables. We need to do this scan now, because variable-sized
14949 : : decls will be decomposed during gimplification. */
14950 : :
14951 : : static void
14952 : 4465 : gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
14953 : : {
14954 : 4465 : tree expr = *expr_p;
14955 : 4465 : gimple *g;
14956 : 4465 : gimple_seq body = NULL;
14957 : 4465 : bool nowait = false;
14958 : 4465 : bool has_depend = false;
14959 : :
14960 : 4465 : if (OMP_TASK_BODY (expr) == NULL_TREE)
14961 : : {
14962 : 190 : for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
14963 : 127 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14964 : : {
14965 : 84 : has_depend = true;
14966 : 84 : if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
14967 : : {
14968 : 11 : error_at (OMP_CLAUSE_LOCATION (c),
14969 : : "%<mutexinoutset%> kind in %<depend%> clause on a "
14970 : : "%<taskwait%> construct");
14971 : 11 : break;
14972 : : }
14973 : : }
14974 : 43 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT)
14975 : 43 : nowait = true;
14976 : 74 : if (nowait && !has_depend)
14977 : : {
14978 : 6 : error_at (EXPR_LOCATION (expr),
14979 : : "%<taskwait%> construct with %<nowait%> clause but no "
14980 : : "%<depend%> clauses");
14981 : 6 : *expr_p = NULL_TREE;
14982 : 6 : return;
14983 : : }
14984 : : }
14985 : :
14986 : 13377 : gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
14987 : 4459 : omp_find_clause (OMP_TASK_CLAUSES (expr),
14988 : : OMP_CLAUSE_UNTIED)
14989 : : ? ORT_UNTIED_TASK : ORT_TASK, OMP_TASK);
14990 : :
14991 : 4459 : if (OMP_TASK_BODY (expr))
14992 : : {
14993 : 4391 : push_gimplify_context ();
14994 : :
14995 : 4391 : g = gimplify_and_return_first (OMP_TASK_BODY (expr), &body);
14996 : 4391 : if (gimple_code (g) == GIMPLE_BIND)
14997 : 4391 : pop_gimplify_context (g);
14998 : : else
14999 : 0 : pop_gimplify_context (NULL);
15000 : : }
15001 : :
15002 : 4459 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_TASK_CLAUSES (expr),
15003 : : OMP_TASK);
15004 : :
15005 : 8918 : g = gimple_build_omp_task (body,
15006 : 4459 : OMP_TASK_CLAUSES (expr),
15007 : : NULL_TREE, NULL_TREE,
15008 : : NULL_TREE, NULL_TREE, NULL_TREE);
15009 : 4459 : if (OMP_TASK_BODY (expr) == NULL_TREE)
15010 : 68 : gimple_omp_task_set_taskwait_p (g, true);
15011 : 4459 : gimplify_seq_add_stmt (pre_p, g);
15012 : 4459 : *expr_p = NULL_TREE;
15013 : : }
15014 : :
15015 : : /* Helper function for gimplify_omp_for. If *TP is not a gimple constant,
15016 : : force it into a temporary initialized in PRE_P and add firstprivate clause
15017 : : to ORIG_FOR_STMT. */
15018 : :
15019 : : static void
15020 : 4458 : gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p,
15021 : : tree orig_for_stmt)
15022 : : {
15023 : 4458 : if (*tp == NULL || is_gimple_constant (*tp))
15024 : : return;
15025 : :
15026 : 662 : *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false);
15027 : : /* Reference to pointer conversion is considered useless,
15028 : : but is significant for firstprivate clause. Force it
15029 : : here. */
15030 : 662 : if (type
15031 : 578 : && TREE_CODE (type) == POINTER_TYPE
15032 : 752 : && TREE_CODE (TREE_TYPE (*tp)) == REFERENCE_TYPE)
15033 : : {
15034 : 12 : tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
15035 : 12 : tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, *tp);
15036 : 12 : gimplify_and_add (m, pre_p);
15037 : 12 : *tp = v;
15038 : : }
15039 : :
15040 : 662 : tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
15041 : 662 : OMP_CLAUSE_DECL (c) = *tp;
15042 : 662 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (orig_for_stmt);
15043 : 662 : OMP_FOR_CLAUSES (orig_for_stmt) = c;
15044 : : }
15045 : :
15046 : : /* Helper function of gimplify_omp_for, find OMP_ORDERED with
15047 : : null OMP_ORDERED_BODY inside of OMP_FOR's body. */
15048 : :
15049 : : static tree
15050 : 17321 : find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
15051 : : {
15052 : 17321 : switch (TREE_CODE (*tp))
15053 : : {
15054 : 1000 : case OMP_ORDERED:
15055 : 1000 : if (OMP_ORDERED_BODY (*tp) == NULL_TREE)
15056 : : return *tp;
15057 : : break;
15058 : 28 : case OMP_SIMD:
15059 : 28 : case OMP_PARALLEL:
15060 : 28 : case OMP_TARGET:
15061 : 28 : *walk_subtrees = 0;
15062 : 28 : break;
15063 : : default:
15064 : : break;
15065 : : }
15066 : : return NULL_TREE;
15067 : : }
15068 : :
15069 : : /* Gimplify the gross structure of an OMP_FOR statement. */
15070 : :
15071 : : static enum gimplify_status
15072 : 55732 : gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
15073 : : {
15074 : 55732 : tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t;
15075 : 55732 : enum gimplify_status ret = GS_ALL_DONE;
15076 : 55732 : enum gimplify_status tret;
15077 : 55732 : gomp_for *gfor;
15078 : 55732 : gimple_seq for_body, for_pre_body;
15079 : 55732 : int i;
15080 : 55732 : bitmap has_decl_expr = NULL;
15081 : 55732 : enum omp_region_type ort = ORT_WORKSHARE;
15082 : 55732 : bool openacc = TREE_CODE (*expr_p) == OACC_LOOP;
15083 : :
15084 : 55732 : orig_for_stmt = for_stmt = *expr_p;
15085 : :
15086 : 55732 : bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND)
15087 : 55732 : != NULL_TREE);
15088 : 55732 : if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
15089 : : {
15090 : 18341 : tree *data[4] = { NULL, NULL, NULL, NULL };
15091 : 18341 : gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
15092 : 18341 : inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt),
15093 : : find_combined_omp_for, data, NULL);
15094 : 18341 : if (inner_for_stmt == NULL_TREE)
15095 : : {
15096 : 16 : gcc_assert (seen_error ());
15097 : 16 : *expr_p = NULL_TREE;
15098 : 3832 : return GS_ERROR;
15099 : : }
15100 : 18325 : if (data[2] && OMP_FOR_PRE_BODY (*data[2]))
15101 : : {
15102 : 2 : append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]),
15103 : : &OMP_FOR_PRE_BODY (for_stmt));
15104 : 2 : OMP_FOR_PRE_BODY (*data[2]) = NULL_TREE;
15105 : : }
15106 : 18325 : if (OMP_FOR_PRE_BODY (inner_for_stmt))
15107 : : {
15108 : 7719 : append_to_statement_list_force (OMP_FOR_PRE_BODY (inner_for_stmt),
15109 : : &OMP_FOR_PRE_BODY (for_stmt));
15110 : 7719 : OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
15111 : : }
15112 : :
15113 : 18325 : if (data[0])
15114 : : {
15115 : : /* We have some statements or variable declarations in between
15116 : : the composite construct directives. Move them around the
15117 : : inner_for_stmt. */
15118 : 3816 : data[0] = expr_p;
15119 : 15264 : for (i = 0; i < 3; i++)
15120 : 11448 : if (data[i])
15121 : : {
15122 : 7182 : tree t = *data[i];
15123 : 7182 : if (i < 2 && data[i + 1] == &OMP_BODY (t))
15124 : 983 : data[i + 1] = data[i];
15125 : 7182 : *data[i] = OMP_BODY (t);
15126 : 7182 : tree body = build3 (BIND_EXPR, void_type_node, NULL_TREE,
15127 : : NULL_TREE, make_node (BLOCK));
15128 : 7182 : OMP_BODY (t) = body;
15129 : 7182 : append_to_statement_list_force (inner_for_stmt,
15130 : : &BIND_EXPR_BODY (body));
15131 : 7182 : *data[3] = t;
15132 : 7182 : data[3] = tsi_stmt_ptr (tsi_start (BIND_EXPR_BODY (body)));
15133 : 7182 : gcc_assert (*data[3] == inner_for_stmt);
15134 : : }
15135 : : return GS_OK;
15136 : : }
15137 : :
15138 : 37928 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
15139 : 23419 : if (!loop_p
15140 : 22467 : && OMP_FOR_ORIG_DECLS (inner_for_stmt)
15141 : 11681 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
15142 : : i)) == TREE_LIST
15143 : 23484 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
15144 : : i)))
15145 : : {
15146 : 37 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
15147 : : /* Class iterators aren't allowed on OMP_SIMD, so the only
15148 : : case we need to solve is distribute parallel for. They are
15149 : : allowed on the loop construct, but that is already handled
15150 : : in gimplify_omp_loop. */
15151 : 37 : gcc_assert (TREE_CODE (inner_for_stmt) == OMP_FOR
15152 : : && TREE_CODE (for_stmt) == OMP_DISTRIBUTE
15153 : : && data[1]);
15154 : 37 : tree orig_decl = TREE_PURPOSE (orig);
15155 : 37 : tree last = TREE_VALUE (orig);
15156 : 37 : tree *pc;
15157 : 37 : for (pc = &OMP_FOR_CLAUSES (inner_for_stmt);
15158 : 68 : *pc; pc = &OMP_CLAUSE_CHAIN (*pc))
15159 : 39 : if ((OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE
15160 : 32 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE)
15161 : 40 : && OMP_CLAUSE_DECL (*pc) == orig_decl)
15162 : : break;
15163 : 37 : if (*pc == NULL_TREE)
15164 : : {
15165 : 29 : tree *spc;
15166 : 29 : for (spc = &OMP_PARALLEL_CLAUSES (*data[1]);
15167 : 95 : *spc; spc = &OMP_CLAUSE_CHAIN (*spc))
15168 : 67 : if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE
15169 : 67 : && OMP_CLAUSE_DECL (*spc) == orig_decl)
15170 : : break;
15171 : 29 : if (*spc)
15172 : : {
15173 : 1 : tree c = *spc;
15174 : 1 : *spc = OMP_CLAUSE_CHAIN (c);
15175 : 1 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
15176 : 1 : *pc = c;
15177 : : }
15178 : : }
15179 : 37 : if (*pc == NULL_TREE)
15180 : : ;
15181 : 9 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE)
15182 : : {
15183 : : /* private clause will appear only on inner_for_stmt.
15184 : : Change it into firstprivate, and add private clause
15185 : : on for_stmt. */
15186 : 8 : tree c = copy_node (*pc);
15187 : 8 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
15188 : 8 : OMP_FOR_CLAUSES (for_stmt) = c;
15189 : 8 : OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE;
15190 : 8 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
15191 : : }
15192 : : else
15193 : : {
15194 : : /* lastprivate clause will appear on both inner_for_stmt
15195 : : and for_stmt. Add firstprivate clause to
15196 : : inner_for_stmt. */
15197 : 1 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (*pc),
15198 : : OMP_CLAUSE_FIRSTPRIVATE);
15199 : 1 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc);
15200 : 1 : OMP_CLAUSE_CHAIN (c) = *pc;
15201 : 1 : *pc = c;
15202 : 1 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
15203 : : }
15204 : 37 : tree c = build_omp_clause (UNKNOWN_LOCATION,
15205 : : OMP_CLAUSE_FIRSTPRIVATE);
15206 : 37 : OMP_CLAUSE_DECL (c) = last;
15207 : 37 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
15208 : 37 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
15209 : 37 : c = build_omp_clause (UNKNOWN_LOCATION,
15210 : 37 : *pc ? OMP_CLAUSE_SHARED
15211 : : : OMP_CLAUSE_FIRSTPRIVATE);
15212 : 37 : OMP_CLAUSE_DECL (c) = orig_decl;
15213 : 37 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
15214 : 37 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
15215 : : }
15216 : : /* Similarly, take care of C++ range for temporaries, those should
15217 : : be firstprivate on OMP_PARALLEL if any. */
15218 : 14509 : if (data[1])
15219 : 17800 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
15220 : 11257 : if (OMP_FOR_ORIG_DECLS (inner_for_stmt)
15221 : 5916 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
15222 : : i)) == TREE_LIST
15223 : 11330 : && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
15224 : : i)))
15225 : : {
15226 : 46 : tree orig
15227 : 46 : = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
15228 : 46 : tree v = TREE_CHAIN (orig);
15229 : 46 : tree c = build_omp_clause (UNKNOWN_LOCATION,
15230 : : OMP_CLAUSE_FIRSTPRIVATE);
15231 : : /* First add firstprivate clause for the __for_end artificial
15232 : : decl. */
15233 : 46 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 1);
15234 : 46 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
15235 : : == REFERENCE_TYPE)
15236 : 0 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
15237 : 46 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
15238 : 46 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
15239 : 46 : if (TREE_VEC_ELT (v, 0))
15240 : : {
15241 : : /* And now the same for __for_range artificial decl if it
15242 : : exists. */
15243 : 46 : c = build_omp_clause (UNKNOWN_LOCATION,
15244 : : OMP_CLAUSE_FIRSTPRIVATE);
15245 : 46 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 0);
15246 : 46 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
15247 : : == REFERENCE_TYPE)
15248 : 46 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
15249 : 46 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
15250 : 46 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
15251 : : }
15252 : : }
15253 : : }
15254 : :
15255 : 51900 : switch (TREE_CODE (for_stmt))
15256 : : {
15257 : 18271 : case OMP_FOR:
15258 : 30258 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
15259 : : {
15260 : 495 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
15261 : : OMP_CLAUSE_SCHEDULE))
15262 : 57 : error_at (EXPR_LOCATION (for_stmt),
15263 : : "%qs clause may not appear on non-rectangular %qs",
15264 : 32 : "schedule", lang_GNU_Fortran () ? "do" : "for");
15265 : 495 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED))
15266 : 42 : error_at (EXPR_LOCATION (for_stmt),
15267 : : "%qs clause may not appear on non-rectangular %qs",
15268 : 22 : "ordered", lang_GNU_Fortran () ? "do" : "for");
15269 : : }
15270 : : break;
15271 : 8496 : case OMP_DISTRIBUTE:
15272 : 9472 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)
15273 : 8496 : && omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
15274 : : OMP_CLAUSE_DIST_SCHEDULE))
15275 : 33 : error_at (EXPR_LOCATION (for_stmt),
15276 : : "%qs clause may not appear on non-rectangular %qs",
15277 : : "dist_schedule", "distribute");
15278 : : break;
15279 : : case OACC_LOOP:
15280 : : ort = ORT_ACC;
15281 : : break;
15282 : 1700 : case OMP_TASKLOOP:
15283 : 2695 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
15284 : : {
15285 : 38 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
15286 : : OMP_CLAUSE_GRAINSIZE))
15287 : 12 : error_at (EXPR_LOCATION (for_stmt),
15288 : : "%qs clause may not appear on non-rectangular %qs",
15289 : : "grainsize", "taskloop");
15290 : 38 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
15291 : : OMP_CLAUSE_NUM_TASKS))
15292 : 7 : error_at (EXPR_LOCATION (for_stmt),
15293 : : "%qs clause may not appear on non-rectangular %qs",
15294 : : "num_tasks", "taskloop");
15295 : : }
15296 : 1700 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED))
15297 : : ort = ORT_UNTIED_TASKLOOP;
15298 : : else
15299 : : ort = ORT_TASKLOOP;
15300 : : break;
15301 : 11439 : case OMP_SIMD:
15302 : 11439 : ort = ORT_SIMD;
15303 : 11439 : break;
15304 : 0 : default:
15305 : 0 : gcc_unreachable ();
15306 : : }
15307 : :
15308 : : /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear
15309 : : clause for the IV. */
15310 : 11494 : if (ort == ORT_SIMD && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
15311 : : {
15312 : 8584 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0);
15313 : 8584 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
15314 : 8584 : decl = TREE_OPERAND (t, 0);
15315 : 20901 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15316 : 13465 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15317 : 13465 : && OMP_CLAUSE_DECL (c) == decl)
15318 : : {
15319 : 1148 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
15320 : 1148 : break;
15321 : : }
15322 : : }
15323 : :
15324 : 51900 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP)
15325 : 52363 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort,
15326 : 2163 : loop_p && TREE_CODE (for_stmt) != OMP_SIMD
15327 : : ? OMP_LOOP : TREE_CODE (for_stmt));
15328 : :
15329 : 51900 : if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE)
15330 : 8496 : gimplify_omp_ctxp->distribute = true;
15331 : :
15332 : : /* Handle OMP_FOR_INIT. */
15333 : 51900 : for_pre_body = NULL;
15334 : 51900 : if ((ort == ORT_SIMD
15335 : 40461 : || (inner_for_stmt && TREE_CODE (inner_for_stmt) == OMP_SIMD))
15336 : 63177 : && OMP_FOR_PRE_BODY (for_stmt))
15337 : : {
15338 : 7603 : has_decl_expr = BITMAP_ALLOC (NULL);
15339 : 7603 : if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR
15340 : 7603 : && VAR_P (DECL_EXPR_DECL (OMP_FOR_PRE_BODY (for_stmt))))
15341 : : {
15342 : 24 : t = OMP_FOR_PRE_BODY (for_stmt);
15343 : 24 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
15344 : : }
15345 : 7579 : else if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == STATEMENT_LIST)
15346 : : {
15347 : 7577 : tree_stmt_iterator si;
15348 : 12048 : for (si = tsi_start (OMP_FOR_PRE_BODY (for_stmt)); !tsi_end_p (si);
15349 : 4471 : tsi_next (&si))
15350 : : {
15351 : 4471 : t = tsi_stmt (si);
15352 : 4471 : if (TREE_CODE (t) == DECL_EXPR
15353 : 4471 : && VAR_P (DECL_EXPR_DECL (t)))
15354 : 4398 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
15355 : : }
15356 : : }
15357 : : }
15358 : 51900 : if (OMP_FOR_PRE_BODY (for_stmt))
15359 : : {
15360 : 22092 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp)
15361 : 21281 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
15362 : : else
15363 : : {
15364 : 811 : struct gimplify_omp_ctx ctx;
15365 : 811 : memset (&ctx, 0, sizeof (ctx));
15366 : 811 : ctx.region_type = ORT_NONE;
15367 : 811 : gimplify_omp_ctxp = &ctx;
15368 : 811 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
15369 : 811 : gimplify_omp_ctxp = NULL;
15370 : : }
15371 : : }
15372 : 51900 : OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
15373 : :
15374 : 51900 : if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
15375 : 14509 : for_stmt = inner_for_stmt;
15376 : :
15377 : : /* For taskloop, need to gimplify the start, end and step before the
15378 : : taskloop, outside of the taskloop omp context. */
15379 : 51900 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
15380 : : {
15381 : 3647 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
15382 : : {
15383 : 1947 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
15384 : 1947 : gimple_seq *for_pre_p = (gimple_seq_empty_p (for_pre_body)
15385 : 1947 : ? pre_p : &for_pre_body);
15386 : 1947 : tree type = TREE_TYPE (TREE_OPERAND (t, 0));
15387 : 1947 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
15388 : : {
15389 : 36 : tree v = TREE_OPERAND (t, 1);
15390 : 36 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
15391 : : for_pre_p, orig_for_stmt);
15392 : 36 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
15393 : : for_pre_p, orig_for_stmt);
15394 : : }
15395 : : else
15396 : 1911 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
15397 : : orig_for_stmt);
15398 : :
15399 : : /* Handle OMP_FOR_COND. */
15400 : 1947 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
15401 : 1947 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
15402 : : {
15403 : 31 : tree v = TREE_OPERAND (t, 1);
15404 : 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
15405 : : for_pre_p, orig_for_stmt);
15406 : 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
15407 : : for_pre_p, orig_for_stmt);
15408 : : }
15409 : : else
15410 : 1916 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
15411 : : orig_for_stmt);
15412 : :
15413 : : /* Handle OMP_FOR_INCR. */
15414 : 1947 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
15415 : 1947 : if (TREE_CODE (t) == MODIFY_EXPR)
15416 : : {
15417 : 497 : decl = TREE_OPERAND (t, 0);
15418 : 497 : t = TREE_OPERAND (t, 1);
15419 : 497 : tree *tp = &TREE_OPERAND (t, 1);
15420 : 497 : if (TREE_CODE (t) == PLUS_EXPR && *tp == decl)
15421 : 22 : tp = &TREE_OPERAND (t, 0);
15422 : :
15423 : 497 : gimplify_omp_taskloop_expr (NULL_TREE, tp, for_pre_p,
15424 : : orig_for_stmt);
15425 : : }
15426 : : }
15427 : :
15428 : 1700 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort,
15429 : : OMP_TASKLOOP);
15430 : : }
15431 : :
15432 : 51900 : if (orig_for_stmt != for_stmt)
15433 : 14509 : gimplify_omp_ctxp->combined_loop = true;
15434 : :
15435 : 51900 : for_body = NULL;
15436 : 51900 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
15437 : : == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
15438 : 51900 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
15439 : : == TREE_VEC_LENGTH (OMP_FOR_INCR (for_stmt)));
15440 : :
15441 : 51900 : tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
15442 : 51900 : bool is_doacross = false;
15443 : 51900 : if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
15444 : : find_standalone_omp_ordered, NULL))
15445 : : {
15446 : 602 : OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
15447 : 602 : is_doacross = true;
15448 : 602 : int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
15449 : 602 : gimplify_omp_ctxp->loop_iter_var.create (len * 2);
15450 : 2393 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
15451 : 1791 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
15452 : : {
15453 : 12 : error_at (OMP_CLAUSE_LOCATION (*pc),
15454 : : "%<linear%> clause may not be specified together "
15455 : : "with %<ordered%> clause if stand-alone %<ordered%> "
15456 : : "construct is nested in it");
15457 : 12 : *pc = OMP_CLAUSE_CHAIN (*pc);
15458 : : }
15459 : : else
15460 : 1779 : pc = &OMP_CLAUSE_CHAIN (*pc);
15461 : : }
15462 : 51900 : int collapse = 1, tile = 0;
15463 : 51900 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
15464 : 51900 : if (c)
15465 : 13815 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
15466 : 51900 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
15467 : 51900 : if (c)
15468 : 443 : tile = list_length (OMP_CLAUSE_TILE_LIST (c));
15469 : 51900 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
15470 : 51900 : hash_set<tree> *allocate_uids = NULL;
15471 : 51900 : if (c)
15472 : : {
15473 : 291 : allocate_uids = new hash_set<tree>;
15474 : 1758 : for (; c; c = OMP_CLAUSE_CHAIN (c))
15475 : 1176 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
15476 : 500 : allocate_uids->add (OMP_CLAUSE_DECL (c));
15477 : : }
15478 : 125527 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
15479 : : {
15480 : 73627 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
15481 : 73627 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
15482 : 73627 : decl = TREE_OPERAND (t, 0);
15483 : 73627 : gcc_assert (DECL_P (decl));
15484 : 73627 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
15485 : : || POINTER_TYPE_P (TREE_TYPE (decl)));
15486 : 73627 : if (is_doacross)
15487 : : {
15488 : 1766 : if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt))
15489 : : {
15490 : 1073 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
15491 : 1073 : if (TREE_CODE (orig_decl) == TREE_LIST)
15492 : : {
15493 : 18 : orig_decl = TREE_PURPOSE (orig_decl);
15494 : 18 : if (!orig_decl)
15495 : 0 : orig_decl = decl;
15496 : : }
15497 : 1073 : gimplify_omp_ctxp->loop_iter_var.quick_push (orig_decl);
15498 : : }
15499 : : else
15500 : 693 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
15501 : 1766 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
15502 : : }
15503 : :
15504 : 73627 : if (for_stmt == orig_for_stmt)
15505 : : {
15506 : 50208 : tree orig_decl = decl;
15507 : 50208 : if (OMP_FOR_ORIG_DECLS (for_stmt))
15508 : : {
15509 : 25140 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
15510 : 25140 : if (TREE_CODE (orig_decl) == TREE_LIST)
15511 : : {
15512 : : orig_decl = TREE_PURPOSE (orig_decl);
15513 : : if (!orig_decl)
15514 : : orig_decl = decl;
15515 : : }
15516 : : }
15517 : 50208 : if (is_global_var (orig_decl) && DECL_THREAD_LOCAL_P (orig_decl))
15518 : 45 : error_at (EXPR_LOCATION (for_stmt),
15519 : : "threadprivate iteration variable %qD", orig_decl);
15520 : : }
15521 : :
15522 : : /* Make sure the iteration variable is private. */
15523 : 73627 : tree c = NULL_TREE;
15524 : 73627 : tree c2 = NULL_TREE;
15525 : 73627 : if (orig_for_stmt != for_stmt)
15526 : : {
15527 : : /* Preserve this information until we gimplify the inner simd. */
15528 : 23419 : if (has_decl_expr
15529 : 23419 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
15530 : 3541 : TREE_PRIVATE (t) = 1;
15531 : : }
15532 : 50208 : else if (ort == ORT_SIMD)
15533 : : {
15534 : 16548 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
15535 : : (splay_tree_key) decl);
15536 : 16548 : omp_is_private (gimplify_omp_ctxp, decl,
15537 : 16548 : 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
15538 : : != 1));
15539 : 16548 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
15540 : : {
15541 : 2630 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
15542 : 2630 : if (n->value & GOVD_LASTPRIVATE_CONDITIONAL)
15543 : 0 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
15544 : : OMP_CLAUSE_LASTPRIVATE);
15545 : 0 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
15546 : : OMP_CLAUSE_LASTPRIVATE))
15547 : 0 : if (OMP_CLAUSE_DECL (c3) == decl)
15548 : : {
15549 : 0 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
15550 : : "conditional %<lastprivate%> on loop "
15551 : : "iterator %qD ignored", decl);
15552 : 0 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
15553 : 0 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
15554 : : }
15555 : : }
15556 : 13918 : else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1 && !loop_p)
15557 : : {
15558 : 6186 : c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
15559 : 6186 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
15560 : 6186 : unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN;
15561 : 6186 : if ((has_decl_expr
15562 : 1570 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
15563 : 7070 : || TREE_PRIVATE (t))
15564 : : {
15565 : 2480 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
15566 : 2480 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
15567 : : }
15568 : 6186 : struct gimplify_omp_ctx *outer
15569 : 6186 : = gimplify_omp_ctxp->outer_context;
15570 : 6186 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
15571 : : {
15572 : 2625 : if (outer->region_type == ORT_WORKSHARE
15573 : 2342 : && outer->combined_loop)
15574 : : {
15575 : 2279 : n = splay_tree_lookup (outer->variables,
15576 : : (splay_tree_key)decl);
15577 : 2279 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
15578 : : {
15579 : 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
15580 : 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
15581 : : }
15582 : : else
15583 : : {
15584 : 2279 : struct gimplify_omp_ctx *octx = outer->outer_context;
15585 : 2279 : if (octx
15586 : 1781 : && octx->region_type == ORT_COMBINED_PARALLEL
15587 : 1528 : && octx->outer_context
15588 : 1235 : && (octx->outer_context->region_type
15589 : : == ORT_WORKSHARE)
15590 : 1105 : && octx->outer_context->combined_loop)
15591 : : {
15592 : 1105 : octx = octx->outer_context;
15593 : 1105 : n = splay_tree_lookup (octx->variables,
15594 : : (splay_tree_key)decl);
15595 : 1105 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
15596 : : {
15597 : 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
15598 : 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
15599 : : }
15600 : : }
15601 : : }
15602 : : }
15603 : : }
15604 : :
15605 : 6186 : OMP_CLAUSE_DECL (c) = decl;
15606 : 6186 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
15607 : 6186 : OMP_FOR_CLAUSES (for_stmt) = c;
15608 : 6186 : omp_add_variable (gimplify_omp_ctxp, decl, flags);
15609 : 6186 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
15610 : 2625 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
15611 : : true);
15612 : : }
15613 : : else
15614 : : {
15615 : 7732 : bool lastprivate
15616 : : = (!has_decl_expr
15617 : 7732 : || !bitmap_bit_p (has_decl_expr, DECL_UID (decl)));
15618 : 7732 : if (TREE_PRIVATE (t))
15619 : 1747 : lastprivate = false;
15620 : 7732 : if (loop_p && OMP_FOR_ORIG_DECLS (for_stmt))
15621 : : {
15622 : 642 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
15623 : 642 : if (TREE_CODE (elt) == TREE_LIST && TREE_PURPOSE (elt))
15624 : : lastprivate = false;
15625 : : }
15626 : :
15627 : 7732 : struct gimplify_omp_ctx *outer
15628 : 7732 : = gimplify_omp_ctxp->outer_context;
15629 : 7732 : if (outer && lastprivate)
15630 : 5021 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
15631 : : true);
15632 : :
15633 : 9717 : c = build_omp_clause (input_location,
15634 : : lastprivate ? OMP_CLAUSE_LASTPRIVATE
15635 : : : OMP_CLAUSE_PRIVATE);
15636 : 7732 : OMP_CLAUSE_DECL (c) = decl;
15637 : 7732 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
15638 : 7732 : OMP_FOR_CLAUSES (for_stmt) = c;
15639 : 7732 : omp_add_variable (gimplify_omp_ctxp, decl,
15640 : : (lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE)
15641 : : | GOVD_EXPLICIT | GOVD_SEEN);
15642 : 7732 : c = NULL_TREE;
15643 : : }
15644 : : }
15645 : 33660 : else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
15646 : : {
15647 : 7709 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
15648 : 7709 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
15649 : : (splay_tree_key) decl);
15650 : 7709 : if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL))
15651 : 96 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
15652 : : OMP_CLAUSE_LASTPRIVATE);
15653 : 96 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
15654 : : OMP_CLAUSE_LASTPRIVATE))
15655 : 48 : if (OMP_CLAUSE_DECL (c3) == decl)
15656 : : {
15657 : 48 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
15658 : : "conditional %<lastprivate%> on loop "
15659 : : "iterator %qD ignored", decl);
15660 : 48 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
15661 : 48 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
15662 : : }
15663 : : }
15664 : : else
15665 : 25951 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
15666 : :
15667 : : /* If DECL is not a gimple register, create a temporary variable to act
15668 : : as an iteration counter. This is valid, since DECL cannot be
15669 : : modified in the body of the loop. Similarly for any iteration vars
15670 : : in simd with collapse > 1 where the iterator vars must be
15671 : : lastprivate. And similarly for vars mentioned in allocate clauses. */
15672 : 73627 : if (orig_for_stmt != for_stmt)
15673 : 23419 : var = decl;
15674 : 50208 : else if (!is_gimple_reg (decl)
15675 : 46683 : || (ort == ORT_SIMD
15676 : 14801 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
15677 : 89804 : || (allocate_uids && allocate_uids->contains (decl)))
15678 : : {
15679 : 10644 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15680 : : /* Make sure omp_add_variable is not called on it prematurely.
15681 : : We call it ourselves a few lines later. */
15682 : 10644 : gimplify_omp_ctxp = NULL;
15683 : 10644 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
15684 : 10644 : gimplify_omp_ctxp = ctx;
15685 : 10644 : TREE_OPERAND (t, 0) = var;
15686 : :
15687 : 10644 : gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
15688 : :
15689 : 10644 : if (ort == ORT_SIMD
15690 : 10644 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
15691 : : {
15692 : 870 : c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
15693 : 870 : OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1;
15694 : 870 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1;
15695 : 870 : OMP_CLAUSE_DECL (c2) = var;
15696 : 870 : OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt);
15697 : 870 : OMP_FOR_CLAUSES (for_stmt) = c2;
15698 : 870 : omp_add_variable (gimplify_omp_ctxp, var,
15699 : : GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
15700 : 870 : if (c == NULL_TREE)
15701 : : {
15702 : 570 : c = c2;
15703 : 570 : c2 = NULL_TREE;
15704 : : }
15705 : : }
15706 : : else
15707 : 9774 : omp_add_variable (gimplify_omp_ctxp, var,
15708 : : GOVD_PRIVATE | GOVD_SEEN);
15709 : : }
15710 : : else
15711 : : var = decl;
15712 : :
15713 : 73627 : gimplify_omp_ctxp->in_for_exprs = true;
15714 : 73627 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
15715 : : {
15716 : 744 : tree lb = TREE_OPERAND (t, 1);
15717 : 744 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL,
15718 : : is_gimple_val, fb_rvalue, false);
15719 : 744 : ret = MIN (ret, tret);
15720 : 744 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL,
15721 : : is_gimple_val, fb_rvalue, false);
15722 : : }
15723 : : else
15724 : 72883 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
15725 : : is_gimple_val, fb_rvalue, false);
15726 : 73627 : gimplify_omp_ctxp->in_for_exprs = false;
15727 : 73627 : ret = MIN (ret, tret);
15728 : 73627 : if (ret == GS_ERROR)
15729 : : return ret;
15730 : :
15731 : : /* Handle OMP_FOR_COND. */
15732 : 73627 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
15733 : 73627 : gcc_assert (COMPARISON_CLASS_P (t));
15734 : 73627 : gcc_assert (TREE_OPERAND (t, 0) == decl);
15735 : :
15736 : 73627 : gimplify_omp_ctxp->in_for_exprs = true;
15737 : 73627 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
15738 : : {
15739 : 629 : tree ub = TREE_OPERAND (t, 1);
15740 : 629 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL,
15741 : : is_gimple_val, fb_rvalue, false);
15742 : 629 : ret = MIN (ret, tret);
15743 : 629 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL,
15744 : : is_gimple_val, fb_rvalue, false);
15745 : : }
15746 : : else
15747 : 72998 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
15748 : : is_gimple_val, fb_rvalue, false);
15749 : 73627 : gimplify_omp_ctxp->in_for_exprs = false;
15750 : 73627 : ret = MIN (ret, tret);
15751 : :
15752 : : /* Handle OMP_FOR_INCR. */
15753 : 73627 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
15754 : 73627 : switch (TREE_CODE (t))
15755 : : {
15756 : 37558 : case PREINCREMENT_EXPR:
15757 : 37558 : case POSTINCREMENT_EXPR:
15758 : 37558 : {
15759 : 37558 : tree decl = TREE_OPERAND (t, 0);
15760 : : /* c_omp_for_incr_canonicalize_ptr() should have been
15761 : : called to massage things appropriately. */
15762 : 37558 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
15763 : :
15764 : 37558 : if (orig_for_stmt != for_stmt)
15765 : : break;
15766 : 26473 : t = build_int_cst (TREE_TYPE (decl), 1);
15767 : 26473 : if (c)
15768 : 5082 : OMP_CLAUSE_LINEAR_STEP (c) = t;
15769 : 26473 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
15770 : 26473 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
15771 : 26473 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
15772 : 26473 : break;
15773 : : }
15774 : :
15775 : 3849 : case PREDECREMENT_EXPR:
15776 : 3849 : case POSTDECREMENT_EXPR:
15777 : : /* c_omp_for_incr_canonicalize_ptr() should have been
15778 : : called to massage things appropriately. */
15779 : 3849 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
15780 : 3849 : if (orig_for_stmt != for_stmt)
15781 : : break;
15782 : 2011 : t = build_int_cst (TREE_TYPE (decl), -1);
15783 : 2011 : if (c)
15784 : 113 : OMP_CLAUSE_LINEAR_STEP (c) = t;
15785 : 2011 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
15786 : 2011 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
15787 : 2011 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
15788 : 2011 : break;
15789 : :
15790 : 32220 : case MODIFY_EXPR:
15791 : 32220 : gcc_assert (TREE_OPERAND (t, 0) == decl);
15792 : 32220 : TREE_OPERAND (t, 0) = var;
15793 : :
15794 : 32220 : t = TREE_OPERAND (t, 1);
15795 : 32220 : switch (TREE_CODE (t))
15796 : : {
15797 : 25307 : case PLUS_EXPR:
15798 : 25307 : if (TREE_OPERAND (t, 1) == decl)
15799 : : {
15800 : 227 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
15801 : 227 : TREE_OPERAND (t, 0) = var;
15802 : 227 : break;
15803 : : }
15804 : :
15805 : : /* Fallthru. */
15806 : 31993 : case MINUS_EXPR:
15807 : 31993 : case POINTER_PLUS_EXPR:
15808 : 31993 : gcc_assert (TREE_OPERAND (t, 0) == decl);
15809 : 31993 : TREE_OPERAND (t, 0) = var;
15810 : 31993 : break;
15811 : 0 : default:
15812 : 0 : gcc_unreachable ();
15813 : : }
15814 : :
15815 : 32220 : gimplify_omp_ctxp->in_for_exprs = true;
15816 : 32220 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
15817 : : is_gimple_val, fb_rvalue, false);
15818 : 32220 : ret = MIN (ret, tret);
15819 : 32220 : if (c)
15820 : : {
15821 : 1561 : tree step = TREE_OPERAND (t, 1);
15822 : 1561 : tree stept = TREE_TYPE (decl);
15823 : 1561 : if (POINTER_TYPE_P (stept))
15824 : 282 : stept = sizetype;
15825 : 1561 : step = fold_convert (stept, step);
15826 : 1561 : if (TREE_CODE (t) == MINUS_EXPR)
15827 : 297 : step = fold_build1 (NEGATE_EXPR, stept, step);
15828 : 1561 : OMP_CLAUSE_LINEAR_STEP (c) = step;
15829 : 1561 : if (step != TREE_OPERAND (t, 1))
15830 : : {
15831 : 297 : tret = gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c),
15832 : : &for_pre_body, NULL,
15833 : : is_gimple_val, fb_rvalue, false);
15834 : 297 : ret = MIN (ret, tret);
15835 : : }
15836 : : }
15837 : 32220 : gimplify_omp_ctxp->in_for_exprs = false;
15838 : 32220 : break;
15839 : :
15840 : 0 : default:
15841 : 0 : gcc_unreachable ();
15842 : : }
15843 : :
15844 : 73627 : if (c2)
15845 : : {
15846 : 300 : gcc_assert (c);
15847 : 300 : OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
15848 : : }
15849 : :
15850 : 73627 : if ((var != decl || collapse > 1 || tile) && orig_for_stmt == for_stmt)
15851 : : {
15852 : 87152 : for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
15853 : 65454 : if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15854 : 16458 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
15855 : 56271 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15856 : 2403 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)
15857 : 1517 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
15858 : 76126 : && OMP_CLAUSE_DECL (c) == decl)
15859 : : {
15860 : 7761 : if (is_doacross && (collapse == 1 || i >= collapse))
15861 : : t = var;
15862 : : else
15863 : : {
15864 : 7688 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
15865 : 7688 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
15866 : 7688 : gcc_assert (TREE_OPERAND (t, 0) == var);
15867 : 7688 : t = TREE_OPERAND (t, 1);
15868 : 7688 : gcc_assert (TREE_CODE (t) == PLUS_EXPR
15869 : : || TREE_CODE (t) == MINUS_EXPR
15870 : : || TREE_CODE (t) == POINTER_PLUS_EXPR);
15871 : 7688 : gcc_assert (TREE_OPERAND (t, 0) == var);
15872 : 15274 : t = build2 (TREE_CODE (t), TREE_TYPE (decl),
15873 : : is_doacross ? var : decl,
15874 : 7688 : TREE_OPERAND (t, 1));
15875 : : }
15876 : 7761 : gimple_seq *seq;
15877 : 7761 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
15878 : 7075 : seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
15879 : : else
15880 : 686 : seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c);
15881 : 7761 : push_gimplify_context ();
15882 : 7761 : gimplify_assign (decl, t, seq);
15883 : 7761 : gimple *bind = NULL;
15884 : 7761 : if (gimplify_ctxp->temps)
15885 : : {
15886 : 2234 : bind = gimple_build_bind (NULL_TREE, *seq, NULL_TREE);
15887 : 2234 : *seq = NULL;
15888 : 2234 : gimplify_seq_add_stmt (seq, bind);
15889 : : }
15890 : 7761 : pop_gimplify_context (bind);
15891 : : }
15892 : : }
15893 : 73627 : if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl)
15894 : 2640 : for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
15895 : : {
15896 : 1210 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
15897 : 1210 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
15898 : 1210 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
15899 : 1210 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
15900 : 342 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
15901 : 1210 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
15902 : 1210 : gcc_assert (COMPARISON_CLASS_P (t));
15903 : 1210 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
15904 : 1210 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
15905 : 350 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
15906 : : }
15907 : : }
15908 : :
15909 : 51900 : BITMAP_FREE (has_decl_expr);
15910 : 52191 : delete allocate_uids;
15911 : :
15912 : 51900 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
15913 : 50200 : || (loop_p && orig_for_stmt == for_stmt))
15914 : : {
15915 : 2920 : push_gimplify_context ();
15916 : 2920 : if (TREE_CODE (OMP_FOR_BODY (orig_for_stmt)) != BIND_EXPR)
15917 : : {
15918 : 2105 : OMP_FOR_BODY (orig_for_stmt)
15919 : 2105 : = build3 (BIND_EXPR, void_type_node, NULL,
15920 : 2105 : OMP_FOR_BODY (orig_for_stmt), NULL);
15921 : 2105 : TREE_SIDE_EFFECTS (OMP_FOR_BODY (orig_for_stmt)) = 1;
15922 : : }
15923 : : }
15924 : :
15925 : 51900 : gimple *g = gimplify_and_return_first (OMP_FOR_BODY (orig_for_stmt),
15926 : : &for_body);
15927 : :
15928 : 51900 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
15929 : 50200 : || (loop_p && orig_for_stmt == for_stmt))
15930 : : {
15931 : 2920 : if (gimple_code (g) == GIMPLE_BIND)
15932 : 2920 : pop_gimplify_context (g);
15933 : : else
15934 : 0 : pop_gimplify_context (NULL);
15935 : : }
15936 : :
15937 : 51900 : if (orig_for_stmt != for_stmt)
15938 : 37928 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
15939 : : {
15940 : 23419 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
15941 : 23419 : decl = TREE_OPERAND (t, 0);
15942 : 23419 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15943 : 23419 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
15944 : 828 : gimplify_omp_ctxp = ctx->outer_context;
15945 : 23419 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
15946 : 23419 : gimplify_omp_ctxp = ctx;
15947 : 23419 : omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
15948 : 23419 : TREE_OPERAND (t, 0) = var;
15949 : 23419 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
15950 : 23419 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
15951 : 23419 : TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
15952 : 23419 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
15953 : 809 : for (int j = i + 1;
15954 : 809 : j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
15955 : : {
15956 : 383 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
15957 : 383 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
15958 : 383 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
15959 : 383 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
15960 : : {
15961 : 136 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
15962 : 136 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
15963 : : }
15964 : 383 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
15965 : 383 : gcc_assert (COMPARISON_CLASS_P (t));
15966 : 383 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
15967 : 383 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
15968 : : {
15969 : 70 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
15970 : 70 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
15971 : : }
15972 : : }
15973 : : }
15974 : :
15975 : 51900 : gimplify_adjust_omp_clauses (pre_p, for_body,
15976 : : &OMP_FOR_CLAUSES (orig_for_stmt),
15977 : 51900 : TREE_CODE (orig_for_stmt));
15978 : :
15979 : 51900 : int kind;
15980 : 51900 : switch (TREE_CODE (orig_for_stmt))
15981 : : {
15982 : : case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
15983 : 11439 : case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
15984 : 8496 : case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
15985 : 1700 : case OMP_TASKLOOP: kind = GF_OMP_FOR_KIND_TASKLOOP; break;
15986 : 11994 : case OACC_LOOP: kind = GF_OMP_FOR_KIND_OACC_LOOP; break;
15987 : 0 : default:
15988 : 0 : gcc_unreachable ();
15989 : : }
15990 : 51900 : if (loop_p && kind == GF_OMP_FOR_KIND_SIMD)
15991 : : {
15992 : 1220 : gimplify_seq_add_seq (pre_p, for_pre_body);
15993 : 1220 : for_pre_body = NULL;
15994 : : }
15995 : 51900 : gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
15996 : 51900 : TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
15997 : : for_pre_body);
15998 : 51900 : if (orig_for_stmt != for_stmt)
15999 : 14509 : gimple_omp_for_set_combined_p (gfor, true);
16000 : 51900 : if (gimplify_omp_ctxp
16001 : 42503 : && (gimplify_omp_ctxp->combined_loop
16002 : 34537 : || (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
16003 : 12042 : && gimplify_omp_ctxp->outer_context
16004 : 7936 : && gimplify_omp_ctxp->outer_context->combined_loop)))
16005 : : {
16006 : 14509 : gimple_omp_for_set_combined_into_p (gfor, true);
16007 : 14509 : if (gimplify_omp_ctxp->combined_loop)
16008 : 7966 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_SIMD);
16009 : : else
16010 : 6543 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_FOR);
16011 : : }
16012 : :
16013 : 125527 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16014 : : {
16015 : 73627 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
16016 : 73627 : gimple_omp_for_set_index (gfor, i, TREE_OPERAND (t, 0));
16017 : 73627 : gimple_omp_for_set_initial (gfor, i, TREE_OPERAND (t, 1));
16018 : 73627 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16019 : 73627 : gimple_omp_for_set_cond (gfor, i, TREE_CODE (t));
16020 : 73627 : gimple_omp_for_set_final (gfor, i, TREE_OPERAND (t, 1));
16021 : 73627 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
16022 : 73627 : gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1));
16023 : : }
16024 : :
16025 : : /* OMP_TASKLOOP is gimplified as two GIMPLE_OMP_FOR taskloop
16026 : : constructs with GIMPLE_OMP_TASK sandwiched in between them.
16027 : : The outer taskloop stands for computing the number of iterations,
16028 : : counts for collapsed loops and holding taskloop specific clauses.
16029 : : The task construct stands for the effect of data sharing on the
16030 : : explicit task it creates and the inner taskloop stands for expansion
16031 : : of the static loop inside of the explicit task construct. */
16032 : 51900 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
16033 : : {
16034 : 1700 : tree *gfor_clauses_ptr = gimple_omp_for_clauses_ptr (gfor);
16035 : 1700 : tree task_clauses = NULL_TREE;
16036 : 1700 : tree c = *gfor_clauses_ptr;
16037 : 1700 : tree *gtask_clauses_ptr = &task_clauses;
16038 : 1700 : tree outer_for_clauses = NULL_TREE;
16039 : 1700 : tree *gforo_clauses_ptr = &outer_for_clauses;
16040 : 1700 : bitmap lastprivate_uids = NULL;
16041 : 1700 : if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
16042 : : {
16043 : 32 : c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
16044 : 32 : if (c)
16045 : : {
16046 : 21 : lastprivate_uids = BITMAP_ALLOC (NULL);
16047 : 63 : for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
16048 : : OMP_CLAUSE_LASTPRIVATE))
16049 : 21 : bitmap_set_bit (lastprivate_uids,
16050 : 21 : DECL_UID (OMP_CLAUSE_DECL (c)));
16051 : : }
16052 : 32 : c = *gfor_clauses_ptr;
16053 : : }
16054 : 12401 : for (; c; c = OMP_CLAUSE_CHAIN (c))
16055 : 10701 : switch (OMP_CLAUSE_CODE (c))
16056 : : {
16057 : : /* These clauses are allowed on task, move them there. */
16058 : 5985 : case OMP_CLAUSE_SHARED:
16059 : 5985 : case OMP_CLAUSE_FIRSTPRIVATE:
16060 : 5985 : case OMP_CLAUSE_DEFAULT:
16061 : 5985 : case OMP_CLAUSE_IF:
16062 : 5985 : case OMP_CLAUSE_UNTIED:
16063 : 5985 : case OMP_CLAUSE_FINAL:
16064 : 5985 : case OMP_CLAUSE_MERGEABLE:
16065 : 5985 : case OMP_CLAUSE_PRIORITY:
16066 : 5985 : case OMP_CLAUSE_REDUCTION:
16067 : 5985 : case OMP_CLAUSE_IN_REDUCTION:
16068 : 5985 : *gtask_clauses_ptr = c;
16069 : 5985 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16070 : 5985 : break;
16071 : 2163 : case OMP_CLAUSE_PRIVATE:
16072 : 2163 : if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
16073 : : {
16074 : : /* We want private on outer for and firstprivate
16075 : : on task. */
16076 : 26 : *gtask_clauses_ptr
16077 : 26 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16078 : : OMP_CLAUSE_FIRSTPRIVATE);
16079 : 26 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
16080 : 26 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
16081 : : openacc);
16082 : 26 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
16083 : 26 : *gforo_clauses_ptr = c;
16084 : 26 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16085 : : }
16086 : : else
16087 : : {
16088 : 2137 : *gtask_clauses_ptr = c;
16089 : 2137 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16090 : : }
16091 : : break;
16092 : : /* These clauses go into outer taskloop clauses. */
16093 : 615 : case OMP_CLAUSE_GRAINSIZE:
16094 : 615 : case OMP_CLAUSE_NUM_TASKS:
16095 : 615 : case OMP_CLAUSE_NOGROUP:
16096 : 615 : *gforo_clauses_ptr = c;
16097 : 615 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16098 : 615 : break;
16099 : : /* Collapse clause we duplicate on both taskloops. */
16100 : 567 : case OMP_CLAUSE_COLLAPSE:
16101 : 567 : *gfor_clauses_ptr = c;
16102 : 567 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16103 : 567 : *gforo_clauses_ptr = copy_node (c);
16104 : 567 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
16105 : 567 : break;
16106 : : /* For lastprivate, keep the clause on inner taskloop, and add
16107 : : a shared clause on task. If the same decl is also firstprivate,
16108 : : add also firstprivate clause on the inner taskloop. */
16109 : 1307 : case OMP_CLAUSE_LASTPRIVATE:
16110 : 1307 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
16111 : : {
16112 : : /* For taskloop C++ lastprivate IVs, we want:
16113 : : 1) private on outer taskloop
16114 : : 2) firstprivate and shared on task
16115 : : 3) lastprivate on inner taskloop */
16116 : 38 : *gtask_clauses_ptr
16117 : 38 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16118 : : OMP_CLAUSE_FIRSTPRIVATE);
16119 : 38 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
16120 : 38 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
16121 : : openacc);
16122 : 38 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
16123 : 38 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
16124 : 38 : *gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16125 : : OMP_CLAUSE_PRIVATE);
16126 : 38 : OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
16127 : 38 : OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
16128 : 38 : TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
16129 : 38 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
16130 : : }
16131 : 1307 : *gfor_clauses_ptr = c;
16132 : 1307 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16133 : 1307 : *gtask_clauses_ptr
16134 : 1307 : = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_SHARED);
16135 : 1307 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
16136 : 1307 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
16137 : 343 : OMP_CLAUSE_SHARED_FIRSTPRIVATE (*gtask_clauses_ptr) = 1;
16138 : 1307 : gtask_clauses_ptr
16139 : 1307 : = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
16140 : 1307 : break;
16141 : : /* Allocate clause we duplicate on task and inner taskloop
16142 : : if the decl is lastprivate, otherwise just put on task. */
16143 : 64 : case OMP_CLAUSE_ALLOCATE:
16144 : 64 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
16145 : 64 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
16146 : : {
16147 : : /* Additionally, put firstprivate clause on task
16148 : : for the allocator if it is not constant. */
16149 : 42 : *gtask_clauses_ptr
16150 : 42 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16151 : : OMP_CLAUSE_FIRSTPRIVATE);
16152 : 42 : OMP_CLAUSE_DECL (*gtask_clauses_ptr)
16153 : 42 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
16154 : 42 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
16155 : : }
16156 : 64 : if (lastprivate_uids
16157 : 106 : && bitmap_bit_p (lastprivate_uids,
16158 : 42 : DECL_UID (OMP_CLAUSE_DECL (c))))
16159 : : {
16160 : 21 : *gfor_clauses_ptr = c;
16161 : 21 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16162 : 21 : *gtask_clauses_ptr = copy_node (c);
16163 : 21 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
16164 : : }
16165 : : else
16166 : : {
16167 : 43 : *gtask_clauses_ptr = c;
16168 : 43 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
16169 : : }
16170 : : break;
16171 : 0 : default:
16172 : 0 : gcc_unreachable ();
16173 : : }
16174 : 1700 : *gfor_clauses_ptr = NULL_TREE;
16175 : 1700 : *gtask_clauses_ptr = NULL_TREE;
16176 : 1700 : *gforo_clauses_ptr = NULL_TREE;
16177 : 1700 : BITMAP_FREE (lastprivate_uids);
16178 : 1700 : gimple_set_location (gfor, input_location);
16179 : 1700 : g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
16180 : 1700 : g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
16181 : : NULL_TREE, NULL_TREE, NULL_TREE);
16182 : 1700 : gimple_set_location (g, input_location);
16183 : 1700 : gimple_omp_task_set_taskloop_p (g, true);
16184 : 1700 : g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
16185 : 1700 : gomp_for *gforo
16186 : 1700 : = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
16187 : : gimple_omp_for_collapse (gfor),
16188 : : gimple_omp_for_pre_body (gfor));
16189 : 1700 : gimple_omp_for_set_pre_body (gfor, NULL);
16190 : 1700 : gimple_omp_for_set_combined_p (gforo, true);
16191 : 1700 : gimple_omp_for_set_combined_into_p (gfor, true);
16192 : 3647 : for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
16193 : : {
16194 : 1947 : tree type = TREE_TYPE (gimple_omp_for_index (gfor, i));
16195 : 1947 : tree v = create_tmp_var (type);
16196 : 1947 : gimple_omp_for_set_index (gforo, i, v);
16197 : 1947 : t = unshare_expr (gimple_omp_for_initial (gfor, i));
16198 : 1947 : gimple_omp_for_set_initial (gforo, i, t);
16199 : 1947 : gimple_omp_for_set_cond (gforo, i,
16200 : : gimple_omp_for_cond (gfor, i));
16201 : 1947 : t = unshare_expr (gimple_omp_for_final (gfor, i));
16202 : 1947 : gimple_omp_for_set_final (gforo, i, t);
16203 : 1947 : t = unshare_expr (gimple_omp_for_incr (gfor, i));
16204 : 1947 : gcc_assert (TREE_OPERAND (t, 0) == gimple_omp_for_index (gfor, i));
16205 : 1947 : TREE_OPERAND (t, 0) = v;
16206 : 1947 : gimple_omp_for_set_incr (gforo, i, t);
16207 : 1947 : t = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
16208 : 1947 : OMP_CLAUSE_DECL (t) = v;
16209 : 1947 : OMP_CLAUSE_CHAIN (t) = gimple_omp_for_clauses (gforo);
16210 : 1947 : gimple_omp_for_set_clauses (gforo, t);
16211 : 1947 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
16212 : : {
16213 : 94 : tree *p1 = NULL, *p2 = NULL;
16214 : 94 : t = gimple_omp_for_initial (gforo, i);
16215 : 94 : if (TREE_CODE (t) == TREE_VEC)
16216 : 36 : p1 = &TREE_VEC_ELT (t, 0);
16217 : 94 : t = gimple_omp_for_final (gforo, i);
16218 : 94 : if (TREE_CODE (t) == TREE_VEC)
16219 : : {
16220 : 31 : if (p1)
16221 : 23 : p2 = &TREE_VEC_ELT (t, 0);
16222 : : else
16223 : 8 : p1 = &TREE_VEC_ELT (t, 0);
16224 : : }
16225 : 94 : if (p1)
16226 : : {
16227 : : int j;
16228 : 60 : for (j = 0; j < i; j++)
16229 : 60 : if (*p1 == gimple_omp_for_index (gfor, j))
16230 : : {
16231 : 44 : *p1 = gimple_omp_for_index (gforo, j);
16232 : 44 : if (p2)
16233 : 23 : *p2 = *p1;
16234 : : break;
16235 : : }
16236 : 44 : gcc_assert (j < i);
16237 : : }
16238 : : }
16239 : : }
16240 : 1700 : gimplify_seq_add_stmt (pre_p, gforo);
16241 : : }
16242 : : else
16243 : 50200 : gimplify_seq_add_stmt (pre_p, gfor);
16244 : :
16245 : 51900 : if (TREE_CODE (orig_for_stmt) == OMP_FOR)
16246 : : {
16247 : 18271 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16248 : 18271 : unsigned lastprivate_conditional = 0;
16249 : 18271 : while (ctx
16250 : 18308 : && (ctx->region_type == ORT_TARGET_DATA
16251 : 13891 : || ctx->region_type == ORT_TASKGROUP))
16252 : 37 : ctx = ctx->outer_context;
16253 : 18271 : if (ctx && (ctx->region_type & ORT_PARALLEL) != 0)
16254 : 13618 : for (tree c = gimple_omp_for_clauses (gfor);
16255 : 63168 : c; c = OMP_CLAUSE_CHAIN (c))
16256 : 49550 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
16257 : 49550 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
16258 : 169 : ++lastprivate_conditional;
16259 : 13618 : if (lastprivate_conditional)
16260 : : {
16261 : 126 : struct omp_for_data fd;
16262 : 126 : omp_extract_for_data (gfor, &fd, NULL);
16263 : 126 : tree type = build_array_type_nelts (unsigned_type_for (fd.iter_type),
16264 : : lastprivate_conditional);
16265 : 126 : tree var = create_tmp_var_raw (type);
16266 : 126 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
16267 : 126 : OMP_CLAUSE_DECL (c) = var;
16268 : 126 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
16269 : 126 : gimple_omp_for_set_clauses (gfor, c);
16270 : 126 : omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
16271 : : }
16272 : : }
16273 : 33629 : else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
16274 : : {
16275 : 11439 : unsigned lastprivate_conditional = 0;
16276 : 52269 : for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
16277 : 40830 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
16278 : 40830 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
16279 : 126 : ++lastprivate_conditional;
16280 : 11439 : if (lastprivate_conditional)
16281 : : {
16282 : 98 : struct omp_for_data fd;
16283 : 98 : omp_extract_for_data (gfor, &fd, NULL);
16284 : 98 : tree type = unsigned_type_for (fd.iter_type);
16285 : 322 : while (lastprivate_conditional--)
16286 : : {
16287 : 126 : tree c = build_omp_clause (UNKNOWN_LOCATION,
16288 : : OMP_CLAUSE__CONDTEMP_);
16289 : 126 : OMP_CLAUSE_DECL (c) = create_tmp_var (type);
16290 : 126 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
16291 : 126 : gimple_omp_for_set_clauses (gfor, c);
16292 : : }
16293 : : }
16294 : : }
16295 : :
16296 : 51900 : if (ret != GS_ALL_DONE)
16297 : : return GS_ERROR;
16298 : 51900 : *expr_p = NULL_TREE;
16299 : 51900 : return GS_ALL_DONE;
16300 : : }
16301 : :
16302 : : /* Helper for gimplify_omp_loop, called through walk_tree. */
16303 : :
16304 : : static tree
16305 : 362 : note_no_context_vars (tree *tp, int *, void *data)
16306 : : {
16307 : 362 : if (VAR_P (*tp)
16308 : 70 : && DECL_CONTEXT (*tp) == NULL_TREE
16309 : 381 : && !is_global_var (*tp))
16310 : : {
16311 : 19 : vec<tree> *d = (vec<tree> *) data;
16312 : 19 : d->safe_push (*tp);
16313 : 19 : DECL_CONTEXT (*tp) = current_function_decl;
16314 : : }
16315 : 362 : return NULL_TREE;
16316 : : }
16317 : :
16318 : : /* Gimplify the gross structure of an OMP_LOOP statement. */
16319 : :
16320 : : static enum gimplify_status
16321 : 1220 : gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
16322 : : {
16323 : 1220 : tree for_stmt = *expr_p;
16324 : 1220 : tree clauses = OMP_FOR_CLAUSES (for_stmt);
16325 : 1220 : struct gimplify_omp_ctx *octx = gimplify_omp_ctxp;
16326 : 1220 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
16327 : 1220 : int i;
16328 : :
16329 : : /* If order is not present, the behavior is as if order(concurrent)
16330 : : appeared. */
16331 : 1220 : tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER);
16332 : 1220 : if (order == NULL_TREE)
16333 : : {
16334 : 933 : order = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_ORDER);
16335 : 933 : OMP_CLAUSE_CHAIN (order) = clauses;
16336 : 933 : OMP_FOR_CLAUSES (for_stmt) = clauses = order;
16337 : : }
16338 : :
16339 : 1220 : tree bind = omp_find_clause (clauses, OMP_CLAUSE_BIND);
16340 : 1220 : if (bind == NULL_TREE)
16341 : : {
16342 : 655 : if (!flag_openmp) /* flag_openmp_simd */
16343 : : ;
16344 : 634 : else if (octx && (octx->region_type & ORT_TEAMS) != 0)
16345 : : kind = OMP_CLAUSE_BIND_TEAMS;
16346 : 367 : else if (octx && (octx->region_type & ORT_PARALLEL) != 0)
16347 : : kind = OMP_CLAUSE_BIND_PARALLEL;
16348 : : else
16349 : : {
16350 : 229 : for (; octx; octx = octx->outer_context)
16351 : : {
16352 : 97 : if ((octx->region_type & ORT_ACC) != 0
16353 : 97 : || octx->region_type == ORT_NONE
16354 : 97 : || octx->region_type == ORT_IMPLICIT_TARGET)
16355 : 0 : continue;
16356 : : break;
16357 : : }
16358 : 229 : if (octx == NULL && !in_omp_construct)
16359 : 5 : error_at (EXPR_LOCATION (for_stmt),
16360 : : "%<bind%> clause not specified on a %<loop%> "
16361 : : "construct not nested inside another OpenMP construct");
16362 : : }
16363 : 655 : bind = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_BIND);
16364 : 655 : OMP_CLAUSE_CHAIN (bind) = clauses;
16365 : 655 : OMP_CLAUSE_BIND_KIND (bind) = kind;
16366 : 655 : OMP_FOR_CLAUSES (for_stmt) = bind;
16367 : : }
16368 : : else
16369 : 565 : switch (OMP_CLAUSE_BIND_KIND (bind))
16370 : : {
16371 : : case OMP_CLAUSE_BIND_THREAD:
16372 : : break;
16373 : 195 : case OMP_CLAUSE_BIND_PARALLEL:
16374 : 195 : if (!flag_openmp) /* flag_openmp_simd */
16375 : : {
16376 : 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
16377 : 0 : break;
16378 : : }
16379 : 280 : for (; octx; octx = octx->outer_context)
16380 : 90 : if (octx->region_type == ORT_SIMD
16381 : 90 : && omp_find_clause (octx->clauses, OMP_CLAUSE_BIND) == NULL_TREE)
16382 : : {
16383 : 5 : error_at (EXPR_LOCATION (for_stmt),
16384 : : "%<bind(parallel)%> on a %<loop%> construct nested "
16385 : : "inside %<simd%> construct");
16386 : 5 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
16387 : 5 : break;
16388 : : }
16389 : : kind = OMP_CLAUSE_BIND_PARALLEL;
16390 : : break;
16391 : 184 : case OMP_CLAUSE_BIND_TEAMS:
16392 : 184 : if (!flag_openmp) /* flag_openmp_simd */
16393 : : {
16394 : 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
16395 : 0 : break;
16396 : : }
16397 : 184 : if ((octx
16398 : 148 : && octx->region_type != ORT_IMPLICIT_TARGET
16399 : 129 : && octx->region_type != ORT_NONE
16400 : 129 : && (octx->region_type & ORT_TEAMS) == 0)
16401 : 119 : || in_omp_construct)
16402 : : {
16403 : 80 : error_at (EXPR_LOCATION (for_stmt),
16404 : : "%<bind(teams)%> on a %<loop%> region not strictly "
16405 : : "nested inside of a %<teams%> region");
16406 : 80 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
16407 : 80 : break;
16408 : : }
16409 : : kind = OMP_CLAUSE_BIND_TEAMS;
16410 : : break;
16411 : 0 : default:
16412 : 0 : gcc_unreachable ();
16413 : : }
16414 : :
16415 : 4899 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
16416 : 3679 : switch (OMP_CLAUSE_CODE (*pc))
16417 : : {
16418 : 393 : case OMP_CLAUSE_REDUCTION:
16419 : 393 : if (OMP_CLAUSE_REDUCTION_INSCAN (*pc))
16420 : : {
16421 : 5 : error_at (OMP_CLAUSE_LOCATION (*pc),
16422 : : "%<inscan%> %<reduction%> clause on "
16423 : : "%qs construct", "loop");
16424 : 5 : OMP_CLAUSE_REDUCTION_INSCAN (*pc) = 0;
16425 : : }
16426 : 393 : if (OMP_CLAUSE_REDUCTION_TASK (*pc))
16427 : : {
16428 : 10 : error_at (OMP_CLAUSE_LOCATION (*pc),
16429 : : "invalid %<task%> reduction modifier on construct "
16430 : : "other than %<parallel%>, %qs or %<sections%>",
16431 : 5 : lang_GNU_Fortran () ? "do" : "for");
16432 : 5 : OMP_CLAUSE_REDUCTION_TASK (*pc) = 0;
16433 : : }
16434 : 393 : pc = &OMP_CLAUSE_CHAIN (*pc);
16435 : 393 : break;
16436 : : case OMP_CLAUSE_LASTPRIVATE:
16437 : 331 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16438 : : {
16439 : 326 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
16440 : 326 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
16441 : 326 : if (OMP_CLAUSE_DECL (*pc) == TREE_OPERAND (t, 0))
16442 : : break;
16443 : 27 : if (OMP_FOR_ORIG_DECLS (for_stmt)
16444 : 26 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
16445 : : i)) == TREE_LIST
16446 : 49 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
16447 : : i)))
16448 : : {
16449 : 22 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
16450 : 22 : if (OMP_CLAUSE_DECL (*pc) == TREE_PURPOSE (orig))
16451 : : break;
16452 : : }
16453 : : }
16454 : 326 : if (i == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
16455 : : {
16456 : 5 : error_at (OMP_CLAUSE_LOCATION (*pc),
16457 : : "%<lastprivate%> clause on a %<loop%> construct refers "
16458 : : "to a variable %qD which is not the loop iterator",
16459 : 5 : OMP_CLAUSE_DECL (*pc));
16460 : 5 : *pc = OMP_CLAUSE_CHAIN (*pc);
16461 : 5 : break;
16462 : : }
16463 : 321 : pc = &OMP_CLAUSE_CHAIN (*pc);
16464 : 321 : break;
16465 : 2960 : default:
16466 : 2960 : pc = &OMP_CLAUSE_CHAIN (*pc);
16467 : 2960 : break;
16468 : : }
16469 : :
16470 : 1220 : TREE_SET_CODE (for_stmt, OMP_SIMD);
16471 : :
16472 : 1220 : int last;
16473 : 1220 : switch (kind)
16474 : : {
16475 : : case OMP_CLAUSE_BIND_THREAD: last = 0; break;
16476 : 465 : case OMP_CLAUSE_BIND_PARALLEL: last = 1; break;
16477 : 239 : case OMP_CLAUSE_BIND_TEAMS: last = 2; break;
16478 : : }
16479 : 2163 : for (int pass = 1; pass <= last; pass++)
16480 : : {
16481 : 943 : if (pass == 2)
16482 : : {
16483 : 239 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL,
16484 : : make_node (BLOCK));
16485 : 239 : append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind));
16486 : 239 : *expr_p = make_node (OMP_PARALLEL);
16487 : 239 : TREE_TYPE (*expr_p) = void_type_node;
16488 : 239 : OMP_PARALLEL_BODY (*expr_p) = bind;
16489 : 239 : OMP_PARALLEL_COMBINED (*expr_p) = 1;
16490 : 239 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (for_stmt));
16491 : 239 : tree *pc = &OMP_PARALLEL_CLAUSES (*expr_p);
16492 : 481 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16493 : 242 : if (OMP_FOR_ORIG_DECLS (for_stmt)
16494 : 242 : && (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i))
16495 : : == TREE_LIST))
16496 : : {
16497 : 16 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
16498 : 16 : if (TREE_PURPOSE (elt) && TREE_VALUE (elt))
16499 : : {
16500 : 13 : *pc = build_omp_clause (UNKNOWN_LOCATION,
16501 : : OMP_CLAUSE_FIRSTPRIVATE);
16502 : 13 : OMP_CLAUSE_DECL (*pc) = TREE_VALUE (elt);
16503 : 13 : pc = &OMP_CLAUSE_CHAIN (*pc);
16504 : : }
16505 : : }
16506 : : }
16507 : 943 : tree t = make_node (pass == 2 ? OMP_DISTRIBUTE : OMP_FOR);
16508 : 943 : tree *pc = &OMP_FOR_CLAUSES (t);
16509 : 943 : TREE_TYPE (t) = void_type_node;
16510 : 943 : OMP_FOR_BODY (t) = *expr_p;
16511 : 943 : SET_EXPR_LOCATION (t, EXPR_LOCATION (for_stmt));
16512 : 4380 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
16513 : 3437 : switch (OMP_CLAUSE_CODE (c))
16514 : : {
16515 : 2182 : case OMP_CLAUSE_BIND:
16516 : 2182 : case OMP_CLAUSE_ORDER:
16517 : 2182 : case OMP_CLAUSE_COLLAPSE:
16518 : 2182 : *pc = copy_node (c);
16519 : 2182 : pc = &OMP_CLAUSE_CHAIN (*pc);
16520 : 2182 : break;
16521 : : case OMP_CLAUSE_PRIVATE:
16522 : : case OMP_CLAUSE_FIRSTPRIVATE:
16523 : : /* Only needed on innermost. */
16524 : : break;
16525 : 394 : case OMP_CLAUSE_LASTPRIVATE:
16526 : 394 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) && pass != last)
16527 : : {
16528 : 7 : *pc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16529 : : OMP_CLAUSE_FIRSTPRIVATE);
16530 : 7 : OMP_CLAUSE_DECL (*pc) = OMP_CLAUSE_DECL (c);
16531 : 7 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
16532 : 7 : pc = &OMP_CLAUSE_CHAIN (*pc);
16533 : : }
16534 : 394 : *pc = copy_node (c);
16535 : 394 : OMP_CLAUSE_LASTPRIVATE_STMT (*pc) = NULL_TREE;
16536 : 394 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
16537 : 394 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
16538 : : {
16539 : 22 : if (pass != last)
16540 : 7 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (*pc) = 1;
16541 : : else
16542 : 15 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
16543 : 22 : OMP_CLAUSE_LASTPRIVATE_LOOP_IV (*pc) = 0;
16544 : : }
16545 : 394 : pc = &OMP_CLAUSE_CHAIN (*pc);
16546 : 394 : break;
16547 : 534 : case OMP_CLAUSE_REDUCTION:
16548 : 534 : *pc = copy_node (c);
16549 : 534 : OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c));
16550 : 534 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
16551 : 534 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc))
16552 : : {
16553 : 19 : auto_vec<tree> no_context_vars;
16554 : 19 : int walk_subtrees = 0;
16555 : 19 : note_no_context_vars (&OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
16556 : : &walk_subtrees, &no_context_vars);
16557 : 19 : if (tree p = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c))
16558 : 0 : note_no_context_vars (&p, &walk_subtrees, &no_context_vars);
16559 : 19 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (c),
16560 : : note_no_context_vars,
16561 : : &no_context_vars);
16562 : 19 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (c),
16563 : : note_no_context_vars,
16564 : : &no_context_vars);
16565 : :
16566 : 19 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)
16567 : 19 : = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
16568 : 19 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
16569 : 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)
16570 : 0 : = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c));
16571 : :
16572 : 19 : hash_map<tree, tree> decl_map;
16573 : 19 : decl_map.put (OMP_CLAUSE_DECL (c), OMP_CLAUSE_DECL (c));
16574 : 19 : decl_map.put (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
16575 : 19 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc));
16576 : 19 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
16577 : 0 : decl_map.put (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
16578 : 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc));
16579 : :
16580 : 19 : copy_body_data id;
16581 : 19 : memset (&id, 0, sizeof (id));
16582 : 19 : id.src_fn = current_function_decl;
16583 : 19 : id.dst_fn = current_function_decl;
16584 : 19 : id.src_cfun = cfun;
16585 : 19 : id.decl_map = &decl_map;
16586 : 19 : id.copy_decl = copy_decl_no_change;
16587 : 19 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
16588 : 19 : id.transform_new_cfg = true;
16589 : 19 : id.transform_return_to_modify = false;
16590 : 19 : id.eh_lp_nr = 0;
16591 : 19 : walk_tree (&OMP_CLAUSE_REDUCTION_INIT (*pc), copy_tree_body_r,
16592 : : &id, NULL);
16593 : 19 : walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (*pc), copy_tree_body_r,
16594 : : &id, NULL);
16595 : :
16596 : 76 : for (tree d : no_context_vars)
16597 : : {
16598 : 19 : DECL_CONTEXT (d) = NULL_TREE;
16599 : 19 : DECL_CONTEXT (*decl_map.get (d)) = NULL_TREE;
16600 : : }
16601 : 19 : }
16602 : : else
16603 : : {
16604 : 515 : OMP_CLAUSE_REDUCTION_INIT (*pc)
16605 : 515 : = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c));
16606 : 515 : OMP_CLAUSE_REDUCTION_MERGE (*pc)
16607 : 1030 : = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c));
16608 : : }
16609 : 534 : pc = &OMP_CLAUSE_CHAIN (*pc);
16610 : 534 : break;
16611 : 0 : default:
16612 : 0 : gcc_unreachable ();
16613 : : }
16614 : 943 : *pc = NULL_TREE;
16615 : 943 : *expr_p = t;
16616 : : }
16617 : 1220 : return gimplify_expr (expr_p, pre_p, NULL, is_gimple_stmt, fb_none);
16618 : : }
16619 : :
16620 : :
16621 : : /* Helper function of optimize_target_teams, find OMP_TEAMS inside
16622 : : of OMP_TARGET's body. */
16623 : :
16624 : : static tree
16625 : 70142 : find_omp_teams (tree *tp, int *walk_subtrees, void *)
16626 : : {
16627 : 70142 : *walk_subtrees = 0;
16628 : 70142 : switch (TREE_CODE (*tp))
16629 : : {
16630 : : case OMP_TEAMS:
16631 : : return *tp;
16632 : 22017 : case BIND_EXPR:
16633 : 22017 : case STATEMENT_LIST:
16634 : 22017 : *walk_subtrees = 1;
16635 : 22017 : break;
16636 : : default:
16637 : : break;
16638 : : }
16639 : : return NULL_TREE;
16640 : : }
16641 : :
16642 : : /* Helper function of optimize_target_teams, determine if the expression
16643 : : can be computed safely before the target construct on the host. */
16644 : :
16645 : : static tree
16646 : 1530 : computable_teams_clause (tree *tp, int *walk_subtrees, void *)
16647 : : {
16648 : 2144 : splay_tree_node n;
16649 : :
16650 : 2144 : if (TYPE_P (*tp))
16651 : : {
16652 : 0 : *walk_subtrees = 0;
16653 : 0 : return NULL_TREE;
16654 : : }
16655 : 2144 : switch (TREE_CODE (*tp))
16656 : : {
16657 : 1144 : case VAR_DECL:
16658 : 1144 : case PARM_DECL:
16659 : 1144 : case RESULT_DECL:
16660 : 1144 : *walk_subtrees = 0;
16661 : 1144 : if (error_operand_p (*tp)
16662 : 1144 : || !INTEGRAL_TYPE_P (TREE_TYPE (*tp))
16663 : 1144 : || DECL_HAS_VALUE_EXPR_P (*tp)
16664 : 1144 : || DECL_THREAD_LOCAL_P (*tp)
16665 : 1144 : || TREE_SIDE_EFFECTS (*tp)
16666 : 2288 : || TREE_THIS_VOLATILE (*tp))
16667 : 0 : return *tp;
16668 : 1144 : if (is_global_var (*tp)
16669 : 1144 : && (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (*tp))
16670 : 0 : || lookup_attribute ("omp declare target link",
16671 : 0 : DECL_ATTRIBUTES (*tp))))
16672 : 20 : return *tp;
16673 : 1124 : if (VAR_P (*tp)
16674 : 762 : && !DECL_SEEN_IN_BIND_EXPR_P (*tp)
16675 : 50 : && !is_global_var (*tp)
16676 : 1174 : && decl_function_context (*tp) == current_function_decl)
16677 : 50 : return *tp;
16678 : 2148 : n = splay_tree_lookup (gimplify_omp_ctxp->variables,
16679 : 1074 : (splay_tree_key) *tp);
16680 : 1074 : if (n == NULL)
16681 : : {
16682 : 320 : if (gimplify_omp_ctxp->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
16683 : : return NULL_TREE;
16684 : 24 : return *tp;
16685 : : }
16686 : 754 : else if (n->value & GOVD_LOCAL)
16687 : 0 : return *tp;
16688 : 754 : else if (n->value & GOVD_FIRSTPRIVATE)
16689 : : return NULL_TREE;
16690 : 140 : else if ((n->value & (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
16691 : : == (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
16692 : : return NULL_TREE;
16693 : 120 : return *tp;
16694 : 88 : case INTEGER_CST:
16695 : 88 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
16696 : : return *tp;
16697 : : return NULL_TREE;
16698 : 614 : case TARGET_EXPR:
16699 : 614 : if (TARGET_EXPR_INITIAL (*tp)
16700 : 614 : || TREE_CODE (TARGET_EXPR_SLOT (*tp)) != VAR_DECL)
16701 : : return *tp;
16702 : 614 : return computable_teams_clause (&TARGET_EXPR_SLOT (*tp),
16703 : 614 : walk_subtrees, NULL);
16704 : : /* Allow some reasonable subset of integral arithmetics. */
16705 : 233 : case PLUS_EXPR:
16706 : 233 : case MINUS_EXPR:
16707 : 233 : case MULT_EXPR:
16708 : 233 : case TRUNC_DIV_EXPR:
16709 : 233 : case CEIL_DIV_EXPR:
16710 : 233 : case FLOOR_DIV_EXPR:
16711 : 233 : case ROUND_DIV_EXPR:
16712 : 233 : case TRUNC_MOD_EXPR:
16713 : 233 : case CEIL_MOD_EXPR:
16714 : 233 : case FLOOR_MOD_EXPR:
16715 : 233 : case ROUND_MOD_EXPR:
16716 : 233 : case RDIV_EXPR:
16717 : 233 : case EXACT_DIV_EXPR:
16718 : 233 : case MIN_EXPR:
16719 : 233 : case MAX_EXPR:
16720 : 233 : case LSHIFT_EXPR:
16721 : 233 : case RSHIFT_EXPR:
16722 : 233 : case BIT_IOR_EXPR:
16723 : 233 : case BIT_XOR_EXPR:
16724 : 233 : case BIT_AND_EXPR:
16725 : 233 : case NEGATE_EXPR:
16726 : 233 : case ABS_EXPR:
16727 : 233 : case BIT_NOT_EXPR:
16728 : 233 : case NON_LVALUE_EXPR:
16729 : 233 : CASE_CONVERT:
16730 : 233 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
16731 : : return *tp;
16732 : : return NULL_TREE;
16733 : : /* And disallow anything else, except for comparisons. */
16734 : 65 : default:
16735 : 65 : if (COMPARISON_CLASS_P (*tp))
16736 : : return NULL_TREE;
16737 : : return *tp;
16738 : : }
16739 : : }
16740 : :
16741 : : /* Try to determine if the num_teams and/or thread_limit expressions
16742 : : can have their values determined already before entering the
16743 : : target construct.
16744 : : INTEGER_CSTs trivially are,
16745 : : integral decls that are firstprivate (explicitly or implicitly)
16746 : : or explicitly map(always, to:) or map(always, tofrom:) on the target
16747 : : region too, and expressions involving simple arithmetics on those
16748 : : too, function calls are not ok, dereferencing something neither etc.
16749 : : Add NUM_TEAMS and THREAD_LIMIT clauses to the OMP_CLAUSES of
16750 : : EXPR based on what we find:
16751 : : 0 stands for clause not specified at all, use implementation default
16752 : : -1 stands for value that can't be determined easily before entering
16753 : : the target construct.
16754 : : -2 means that no explicit teams construct was specified
16755 : : If teams construct is not present at all, use 1 for num_teams
16756 : : and 0 for thread_limit (only one team is involved, and the thread
16757 : : limit is implementation defined. */
16758 : :
16759 : : static void
16760 : 12437 : optimize_target_teams (tree target, gimple_seq *pre_p)
16761 : : {
16762 : 12437 : tree body = OMP_BODY (target);
16763 : 12437 : tree teams = walk_tree (&body, find_omp_teams, NULL, NULL);
16764 : 12437 : tree num_teams_lower = NULL_TREE;
16765 : 12437 : tree num_teams_upper = integer_zero_node;
16766 : 12437 : tree thread_limit = integer_zero_node;
16767 : 12437 : location_t num_teams_loc = EXPR_LOCATION (target);
16768 : 12437 : location_t thread_limit_loc = EXPR_LOCATION (target);
16769 : 12437 : tree c, *p, expr;
16770 : 12437 : struct gimplify_omp_ctx *target_ctx = gimplify_omp_ctxp;
16771 : :
16772 : 12437 : if (teams == NULL_TREE)
16773 : 6217 : num_teams_upper = build_int_cst (integer_type_node, -2);
16774 : : else
16775 : 11127 : for (c = OMP_TEAMS_CLAUSES (teams); c; c = OMP_CLAUSE_CHAIN (c))
16776 : : {
16777 : 4907 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS)
16778 : : {
16779 : 724 : p = &num_teams_upper;
16780 : 724 : num_teams_loc = OMP_CLAUSE_LOCATION (c);
16781 : 724 : if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c))
16782 : : {
16783 : 172 : expr = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c);
16784 : 172 : if (TREE_CODE (expr) == INTEGER_CST)
16785 : 24 : num_teams_lower = expr;
16786 : 148 : else if (walk_tree (&expr, computable_teams_clause,
16787 : : NULL, NULL))
16788 : 22 : num_teams_lower = integer_minus_one_node;
16789 : : else
16790 : : {
16791 : 126 : num_teams_lower = expr;
16792 : 126 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
16793 : 126 : if (gimplify_expr (&num_teams_lower, pre_p, NULL,
16794 : : is_gimple_val, fb_rvalue, false)
16795 : : == GS_ERROR)
16796 : : {
16797 : 0 : gimplify_omp_ctxp = target_ctx;
16798 : 0 : num_teams_lower = integer_minus_one_node;
16799 : : }
16800 : : else
16801 : : {
16802 : 126 : gimplify_omp_ctxp = target_ctx;
16803 : 126 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
16804 : 32 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
16805 : 64 : = num_teams_lower;
16806 : : }
16807 : : }
16808 : : }
16809 : : }
16810 : 4183 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
16811 : : {
16812 : 548 : p = &thread_limit;
16813 : 548 : thread_limit_loc = OMP_CLAUSE_LOCATION (c);
16814 : : }
16815 : : else
16816 : 3635 : continue;
16817 : 1272 : expr = OMP_CLAUSE_OPERAND (c, 0);
16818 : 1272 : if (TREE_CODE (expr) == INTEGER_CST)
16819 : : {
16820 : 211 : *p = expr;
16821 : 211 : continue;
16822 : : }
16823 : 1061 : if (walk_tree (&expr, computable_teams_clause, NULL, NULL))
16824 : : {
16825 : 257 : *p = integer_minus_one_node;
16826 : 257 : continue;
16827 : : }
16828 : 804 : *p = expr;
16829 : 804 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
16830 : 804 : if (gimplify_expr (p, pre_p, NULL, is_gimple_val, fb_rvalue, false)
16831 : : == GS_ERROR)
16832 : : {
16833 : 0 : gimplify_omp_ctxp = target_ctx;
16834 : 0 : *p = integer_minus_one_node;
16835 : 0 : continue;
16836 : : }
16837 : 804 : gimplify_omp_ctxp = target_ctx;
16838 : 804 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
16839 : 56 : OMP_CLAUSE_OPERAND (c, 0) = *p;
16840 : : }
16841 : 12437 : if (!omp_find_clause (OMP_TARGET_CLAUSES (target), OMP_CLAUSE_THREAD_LIMIT))
16842 : : {
16843 : 12126 : c = build_omp_clause (thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
16844 : 12126 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
16845 : 12126 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
16846 : 12126 : OMP_TARGET_CLAUSES (target) = c;
16847 : : }
16848 : 12437 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
16849 : 12437 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
16850 : 12437 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
16851 : 12437 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
16852 : 12437 : OMP_TARGET_CLAUSES (target) = c;
16853 : 12437 : }
16854 : :
16855 : : /* Gimplify the gross structure of several OMP constructs. */
16856 : :
16857 : : static void
16858 : 39074 : gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
16859 : : {
16860 : 39074 : tree expr = *expr_p;
16861 : 39074 : gimple *stmt;
16862 : 39074 : gimple_seq body = NULL;
16863 : 39074 : enum omp_region_type ort;
16864 : :
16865 : 39074 : switch (TREE_CODE (expr))
16866 : : {
16867 : : case OMP_SECTIONS:
16868 : : case OMP_SINGLE:
16869 : : ort = ORT_WORKSHARE;
16870 : : break;
16871 : 239 : case OMP_SCOPE:
16872 : 239 : ort = ORT_TASKGROUP;
16873 : 239 : break;
16874 : 12437 : case OMP_TARGET:
16875 : 12437 : ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET;
16876 : : break;
16877 : 2869 : case OACC_KERNELS:
16878 : 2869 : ort = ORT_ACC_KERNELS;
16879 : 2869 : break;
16880 : 8318 : case OACC_PARALLEL:
16881 : 8318 : ort = ORT_ACC_PARALLEL;
16882 : 8318 : break;
16883 : 159 : case OACC_SERIAL:
16884 : 159 : ort = ORT_ACC_SERIAL;
16885 : 159 : break;
16886 : 1892 : case OACC_DATA:
16887 : 1892 : ort = ORT_ACC_DATA;
16888 : 1892 : break;
16889 : 1906 : case OMP_TARGET_DATA:
16890 : 1906 : ort = ORT_TARGET_DATA;
16891 : 1906 : break;
16892 : 9060 : case OMP_TEAMS:
16893 : 9060 : ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS;
16894 : 9060 : if (gimplify_omp_ctxp == NULL
16895 : 6270 : || gimplify_omp_ctxp->region_type == ORT_IMPLICIT_TARGET)
16896 : 2790 : ort = (enum omp_region_type) (ort | ORT_HOST_TEAMS);
16897 : : break;
16898 : 134 : case OACC_HOST_DATA:
16899 : 134 : ort = ORT_ACC_HOST_DATA;
16900 : 134 : break;
16901 : 0 : default:
16902 : 0 : gcc_unreachable ();
16903 : : }
16904 : :
16905 : 39074 : bool save_in_omp_construct = in_omp_construct;
16906 : 39074 : if ((ort & ORT_ACC) == 0)
16907 : 25702 : in_omp_construct = false;
16908 : 39074 : gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
16909 : : TREE_CODE (expr));
16910 : 39074 : if (TREE_CODE (expr) == OMP_TARGET)
16911 : 12437 : optimize_target_teams (expr, pre_p);
16912 : 39074 : if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
16913 : 11359 : || (ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
16914 : : {
16915 : 30505 : push_gimplify_context ();
16916 : 30505 : gimple *g = gimplify_and_return_first (OMP_BODY (expr), &body);
16917 : 30505 : if (gimple_code (g) == GIMPLE_BIND)
16918 : 30505 : pop_gimplify_context (g);
16919 : : else
16920 : 0 : pop_gimplify_context (NULL);
16921 : 30505 : if ((ort & ORT_TARGET_DATA) != 0)
16922 : : {
16923 : 3932 : enum built_in_function end_ix;
16924 : 3932 : switch (TREE_CODE (expr))
16925 : : {
16926 : : case OACC_DATA:
16927 : : case OACC_HOST_DATA:
16928 : : end_ix = BUILT_IN_GOACC_DATA_END;
16929 : : break;
16930 : 1906 : case OMP_TARGET_DATA:
16931 : 1906 : end_ix = BUILT_IN_GOMP_TARGET_END_DATA;
16932 : 1906 : break;
16933 : 0 : default:
16934 : 0 : gcc_unreachable ();
16935 : : }
16936 : 3932 : tree fn = builtin_decl_explicit (end_ix);
16937 : 3932 : g = gimple_build_call (fn, 0);
16938 : 3932 : gimple_seq cleanup = NULL;
16939 : 3932 : gimple_seq_add_stmt (&cleanup, g);
16940 : 3932 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
16941 : 3932 : body = NULL;
16942 : 3932 : gimple_seq_add_stmt (&body, g);
16943 : : }
16944 : : }
16945 : : else
16946 : 8569 : gimplify_and_add (OMP_BODY (expr), &body);
16947 : 39074 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
16948 : 39074 : TREE_CODE (expr));
16949 : 39074 : in_omp_construct = save_in_omp_construct;
16950 : :
16951 : 39074 : switch (TREE_CODE (expr))
16952 : : {
16953 : 1892 : case OACC_DATA:
16954 : 3784 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_DATA,
16955 : 1892 : OMP_CLAUSES (expr));
16956 : 1892 : break;
16957 : 134 : case OACC_HOST_DATA:
16958 : 134 : if (omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT))
16959 : : {
16960 : 144 : for (tree c = OMP_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
16961 : 107 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16962 : 64 : OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c) = 1;
16963 : : }
16964 : :
16965 : 268 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_HOST_DATA,
16966 : 134 : OMP_CLAUSES (expr));
16967 : 134 : break;
16968 : 2869 : case OACC_KERNELS:
16969 : 5738 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS,
16970 : 2869 : OMP_CLAUSES (expr));
16971 : 2869 : break;
16972 : 8318 : case OACC_PARALLEL:
16973 : 16636 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_PARALLEL,
16974 : 8318 : OMP_CLAUSES (expr));
16975 : 8318 : break;
16976 : 159 : case OACC_SERIAL:
16977 : 318 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_SERIAL,
16978 : 159 : OMP_CLAUSES (expr));
16979 : 159 : break;
16980 : 723 : case OMP_SECTIONS:
16981 : 723 : stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
16982 : 723 : break;
16983 : 1337 : case OMP_SINGLE:
16984 : 1337 : stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
16985 : 1337 : break;
16986 : 239 : case OMP_SCOPE:
16987 : 239 : stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
16988 : 239 : break;
16989 : 12437 : case OMP_TARGET:
16990 : 24874 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
16991 : 12437 : OMP_CLAUSES (expr));
16992 : 12437 : break;
16993 : 1906 : case OMP_TARGET_DATA:
16994 : : /* Put use_device_{ptr,addr} clauses last, as map clauses are supposed
16995 : : to be evaluated before the use_device_{ptr,addr} clauses if they
16996 : : refer to the same variables. */
16997 : 1906 : {
16998 : 1906 : tree use_device_clauses;
16999 : 1906 : tree *pc, *uc = &use_device_clauses;
17000 : 9996 : for (pc = &OMP_CLAUSES (expr); *pc; )
17001 : 8090 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
17002 : 8090 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
17003 : : {
17004 : 1967 : *uc = *pc;
17005 : 1967 : *pc = OMP_CLAUSE_CHAIN (*pc);
17006 : 1967 : uc = &OMP_CLAUSE_CHAIN (*uc);
17007 : : }
17008 : : else
17009 : 6123 : pc = &OMP_CLAUSE_CHAIN (*pc);
17010 : 1906 : *uc = NULL_TREE;
17011 : 1906 : *pc = use_device_clauses;
17012 : 1906 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_DATA,
17013 : 1906 : OMP_CLAUSES (expr));
17014 : : }
17015 : 1906 : break;
17016 : 9060 : case OMP_TEAMS:
17017 : 9060 : stmt = gimple_build_omp_teams (body, OMP_CLAUSES (expr));
17018 : 9060 : if ((ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
17019 : 2790 : gimple_omp_teams_set_host (as_a <gomp_teams *> (stmt), true);
17020 : : break;
17021 : 0 : default:
17022 : 0 : gcc_unreachable ();
17023 : : }
17024 : :
17025 : 39074 : gimplify_seq_add_stmt (pre_p, stmt);
17026 : 39074 : *expr_p = NULL_TREE;
17027 : 39074 : }
17028 : :
17029 : : /* Gimplify the gross structure of OpenACC enter/exit data, update, and OpenMP
17030 : : target update constructs. */
17031 : :
17032 : : static void
17033 : 11926 : gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
17034 : : {
17035 : 11926 : tree expr = *expr_p;
17036 : 11926 : int kind;
17037 : 11926 : gomp_target *stmt;
17038 : 11926 : enum omp_region_type ort = ORT_WORKSHARE;
17039 : :
17040 : 11926 : switch (TREE_CODE (expr))
17041 : : {
17042 : : case OACC_ENTER_DATA:
17043 : : kind = GF_OMP_TARGET_KIND_OACC_ENTER_DATA;
17044 : : ort = ORT_ACC;
17045 : : break;
17046 : : case OACC_EXIT_DATA:
17047 : : kind = GF_OMP_TARGET_KIND_OACC_EXIT_DATA;
17048 : : ort = ORT_ACC;
17049 : : break;
17050 : : case OACC_UPDATE:
17051 : : kind = GF_OMP_TARGET_KIND_OACC_UPDATE;
17052 : : ort = ORT_ACC;
17053 : : break;
17054 : : case OMP_TARGET_UPDATE:
17055 : : kind = GF_OMP_TARGET_KIND_UPDATE;
17056 : : break;
17057 : : case OMP_TARGET_ENTER_DATA:
17058 : : kind = GF_OMP_TARGET_KIND_ENTER_DATA;
17059 : : break;
17060 : : case OMP_TARGET_EXIT_DATA:
17061 : : kind = GF_OMP_TARGET_KIND_EXIT_DATA;
17062 : : break;
17063 : 0 : default:
17064 : 0 : gcc_unreachable ();
17065 : : }
17066 : 11926 : gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
17067 : : ort, TREE_CODE (expr));
17068 : 11926 : gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
17069 : 11926 : TREE_CODE (expr));
17070 : 11926 : if (TREE_CODE (expr) == OACC_UPDATE
17071 : 11926 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
17072 : : OMP_CLAUSE_IF_PRESENT))
17073 : : {
17074 : : /* The runtime uses GOMP_MAP_{TO,FROM} to denote the if_present
17075 : : clause. */
17076 : 141 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
17077 : 111 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
17078 : 53 : switch (OMP_CLAUSE_MAP_KIND (c))
17079 : : {
17080 : 16 : case GOMP_MAP_FORCE_TO:
17081 : 16 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
17082 : 16 : break;
17083 : 28 : case GOMP_MAP_FORCE_FROM:
17084 : 28 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FROM);
17085 : 28 : break;
17086 : : default:
17087 : : break;
17088 : : }
17089 : : }
17090 : 11896 : else if (TREE_CODE (expr) == OACC_EXIT_DATA
17091 : 11896 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
17092 : : OMP_CLAUSE_FINALIZE))
17093 : : {
17094 : : /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote "finalize"
17095 : : semantics. */
17096 : 73 : bool have_clause = false;
17097 : 265 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
17098 : 192 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
17099 : 115 : switch (OMP_CLAUSE_MAP_KIND (c))
17100 : : {
17101 : 42 : case GOMP_MAP_FROM:
17102 : 42 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
17103 : 42 : have_clause = true;
17104 : 42 : break;
17105 : 44 : case GOMP_MAP_RELEASE:
17106 : 44 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
17107 : 44 : have_clause = true;
17108 : 44 : break;
17109 : : case GOMP_MAP_TO_PSET:
17110 : : /* Fortran arrays with descriptors must map that descriptor when
17111 : : doing standalone "attach" operations (in OpenACC). In that
17112 : : case GOMP_MAP_TO_PSET appears by itself with no preceding
17113 : : clause (see trans-openmp.cc:gfc_trans_omp_clauses). */
17114 : : break;
17115 : 2 : case GOMP_MAP_POINTER:
17116 : : /* TODO PR92929: we may see these here, but they'll always follow
17117 : : one of the clauses above, and will be handled by libgomp as
17118 : : one group, so no handling required here. */
17119 : 2 : gcc_assert (have_clause);
17120 : : break;
17121 : 26 : case GOMP_MAP_DETACH:
17122 : 26 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_DETACH);
17123 : 26 : have_clause = false;
17124 : 26 : break;
17125 : : case GOMP_MAP_STRUCT:
17126 : : case GOMP_MAP_STRUCT_UNORD:
17127 : 26 : have_clause = false;
17128 : : break;
17129 : 0 : default:
17130 : 0 : gcc_unreachable ();
17131 : : }
17132 : : }
17133 : 11926 : stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr));
17134 : :
17135 : 11926 : gimplify_seq_add_stmt (pre_p, stmt);
17136 : 11926 : *expr_p = NULL_TREE;
17137 : 11926 : }
17138 : :
17139 : : /* A subroutine of gimplify_omp_atomic. The front end is supposed to have
17140 : : stabilized the lhs of the atomic operation as *ADDR. Return true if
17141 : : EXPR is this stabilized form. */
17142 : :
17143 : : static bool
17144 : 39304 : goa_lhs_expr_p (tree expr, tree addr)
17145 : : {
17146 : : /* Also include casts to other type variants. The C front end is fond
17147 : : of adding these for e.g. volatile variables. This is like
17148 : : STRIP_TYPE_NOPS but includes the main variant lookup. */
17149 : 39304 : STRIP_USELESS_TYPE_CONVERSION (expr);
17150 : :
17151 : 39304 : if (INDIRECT_REF_P (expr))
17152 : : {
17153 : 5222 : expr = TREE_OPERAND (expr, 0);
17154 : 5222 : while (expr != addr
17155 : 104 : && (CONVERT_EXPR_P (expr)
17156 : 104 : || TREE_CODE (expr) == NON_LVALUE_EXPR)
17157 : 0 : && TREE_CODE (expr) == TREE_CODE (addr)
17158 : 5222 : && types_compatible_p (TREE_TYPE (expr), TREE_TYPE (addr)))
17159 : : {
17160 : 0 : expr = TREE_OPERAND (expr, 0);
17161 : 0 : addr = TREE_OPERAND (addr, 0);
17162 : : }
17163 : 5222 : if (expr == addr)
17164 : : return true;
17165 : 104 : return (TREE_CODE (addr) == ADDR_EXPR
17166 : 74 : && TREE_CODE (expr) == ADDR_EXPR
17167 : 104 : && TREE_OPERAND (addr, 0) == TREE_OPERAND (expr, 0));
17168 : : }
17169 : 34082 : if (TREE_CODE (addr) == ADDR_EXPR && expr == TREE_OPERAND (addr, 0))
17170 : : return true;
17171 : : return false;
17172 : : }
17173 : :
17174 : : /* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR. If an
17175 : : expression does not involve the lhs, evaluate it into a temporary.
17176 : : Return 1 if the lhs appeared as a subexpression, 0 if it did not,
17177 : : or -1 if an error was encountered. */
17178 : :
17179 : : static int
17180 : 39304 : goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
17181 : : tree lhs_var, tree &target_expr, bool rhs, int depth)
17182 : : {
17183 : 39304 : tree expr = *expr_p;
17184 : 39304 : int saw_lhs = 0;
17185 : :
17186 : 39304 : if (goa_lhs_expr_p (expr, lhs_addr))
17187 : : {
17188 : 9845 : if (pre_p)
17189 : 9123 : *expr_p = lhs_var;
17190 : 9845 : return 1;
17191 : : }
17192 : 29459 : if (is_gimple_val (expr))
17193 : : return 0;
17194 : :
17195 : : /* Maximum depth of lhs in expression is for the
17196 : : __builtin_clear_padding (...), __builtin_clear_padding (...),
17197 : : __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs; */
17198 : 18525 : if (++depth > 7)
17199 : 16 : goto finish;
17200 : :
17201 : 18509 : switch (TREE_CODE_CLASS (TREE_CODE (expr)))
17202 : : {
17203 : 10274 : case tcc_binary:
17204 : 10274 : case tcc_comparison:
17205 : 10274 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
17206 : : lhs_var, target_expr, true, depth);
17207 : : /* FALLTHRU */
17208 : 12476 : case tcc_unary:
17209 : 12476 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
17210 : : lhs_var, target_expr, true, depth);
17211 : 12476 : break;
17212 : 3183 : case tcc_expression:
17213 : 3183 : switch (TREE_CODE (expr))
17214 : : {
17215 : 844 : case TRUTH_ANDIF_EXPR:
17216 : 844 : case TRUTH_ORIF_EXPR:
17217 : 844 : case TRUTH_AND_EXPR:
17218 : 844 : case TRUTH_OR_EXPR:
17219 : 844 : case TRUTH_XOR_EXPR:
17220 : 844 : case BIT_INSERT_EXPR:
17221 : 844 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
17222 : : lhs_addr, lhs_var, target_expr, true,
17223 : : depth);
17224 : : /* FALLTHRU */
17225 : 896 : case TRUTH_NOT_EXPR:
17226 : 896 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
17227 : : lhs_addr, lhs_var, target_expr, true,
17228 : : depth);
17229 : 896 : break;
17230 : 595 : case MODIFY_EXPR:
17231 : 595 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
17232 : : target_expr, true, depth))
17233 : : break;
17234 : 589 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
17235 : : lhs_addr, lhs_var, target_expr, true,
17236 : : depth);
17237 : 589 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
17238 : : lhs_addr, lhs_var, target_expr, false,
17239 : : depth);
17240 : 589 : break;
17241 : : /* FALLTHRU */
17242 : 182 : case ADDR_EXPR:
17243 : 182 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
17244 : : target_expr, true, depth))
17245 : : break;
17246 : 153 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
17247 : : lhs_addr, lhs_var, target_expr, false,
17248 : : depth);
17249 : 153 : break;
17250 : : case COMPOUND_EXPR:
17251 : : /* Break out any preevaluations from cp_build_modify_expr. */
17252 : 94 : for (; TREE_CODE (expr) == COMPOUND_EXPR;
17253 : 47 : expr = TREE_OPERAND (expr, 1))
17254 : : {
17255 : : /* Special-case __builtin_clear_padding call before
17256 : : __builtin_memcmp. */
17257 : 47 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
17258 : : {
17259 : 2 : tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
17260 : 2 : if (fndecl
17261 : 2 : && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
17262 : 0 : && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
17263 : 2 : && (!pre_p
17264 : 0 : || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
17265 : : lhs_addr, lhs_var,
17266 : : target_expr, true, depth)))
17267 : : {
17268 : 0 : if (pre_p)
17269 : 0 : *expr_p = expr;
17270 : 0 : saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
17271 : : pre_p, lhs_addr, lhs_var,
17272 : : target_expr, true, depth);
17273 : 0 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
17274 : : pre_p, lhs_addr, lhs_var,
17275 : : target_expr, rhs, depth);
17276 : 0 : return saw_lhs;
17277 : : }
17278 : : }
17279 : :
17280 : 47 : if (pre_p)
17281 : 44 : gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
17282 : : }
17283 : 47 : if (!pre_p)
17284 : 3 : return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
17285 : 3 : target_expr, rhs, depth);
17286 : 44 : *expr_p = expr;
17287 : 44 : return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
17288 : 44 : target_expr, rhs, depth);
17289 : 484 : case COND_EXPR:
17290 : 484 : if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
17291 : : lhs_var, target_expr, true, depth))
17292 : : break;
17293 : 471 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
17294 : : lhs_addr, lhs_var, target_expr, true,
17295 : : depth);
17296 : 471 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
17297 : : lhs_addr, lhs_var, target_expr, true,
17298 : : depth);
17299 : 471 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
17300 : : lhs_addr, lhs_var, target_expr, true,
17301 : : depth);
17302 : 471 : break;
17303 : 958 : case TARGET_EXPR:
17304 : 958 : if (TARGET_EXPR_INITIAL (expr))
17305 : : {
17306 : 958 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
17307 : : lhs_var, target_expr, true,
17308 : : depth))
17309 : : break;
17310 : 765 : if (expr == target_expr)
17311 : : saw_lhs = 1;
17312 : : else
17313 : : {
17314 : 765 : saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
17315 : : pre_p, lhs_addr, lhs_var,
17316 : : target_expr, true, depth);
17317 : 765 : if (saw_lhs && target_expr == NULL_TREE && pre_p)
17318 : 29 : target_expr = expr;
17319 : : }
17320 : : }
17321 : : break;
17322 : : default:
17323 : : break;
17324 : : }
17325 : : break;
17326 : 647 : case tcc_reference:
17327 : 647 : if (TREE_CODE (expr) == BIT_FIELD_REF
17328 : 568 : || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
17329 : 420 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
17330 : : lhs_addr, lhs_var, target_expr, true,
17331 : : depth);
17332 : : break;
17333 : 62 : case tcc_vl_exp:
17334 : 62 : if (TREE_CODE (expr) == CALL_EXPR)
17335 : : {
17336 : 62 : if (tree fndecl = get_callee_fndecl (expr))
17337 : 62 : if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING,
17338 : : BUILT_IN_MEMCMP))
17339 : : {
17340 : 62 : int nargs = call_expr_nargs (expr);
17341 : 248 : for (int i = 0; i < nargs; i++)
17342 : 186 : saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
17343 : : pre_p, lhs_addr, lhs_var,
17344 : : target_expr, true, depth);
17345 : : }
17346 : : }
17347 : : break;
17348 : : default:
17349 : : break;
17350 : : }
17351 : :
17352 : 18478 : finish:
17353 : 18478 : if (saw_lhs == 0 && pre_p)
17354 : : {
17355 : 3738 : enum gimplify_status gs;
17356 : 3738 : if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
17357 : : {
17358 : 0 : gimplify_stmt (&expr, pre_p);
17359 : 0 : return saw_lhs;
17360 : : }
17361 : 3738 : else if (rhs)
17362 : 3545 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
17363 : : else
17364 : 193 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
17365 : 3738 : if (gs != GS_ALL_DONE)
17366 : 39304 : saw_lhs = -1;
17367 : : }
17368 : :
17369 : : return saw_lhs;
17370 : : }
17371 : :
17372 : : /* Gimplify an OMP_ATOMIC statement. */
17373 : :
17374 : : static enum gimplify_status
17375 : 10912 : gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
17376 : : {
17377 : 10912 : tree addr = TREE_OPERAND (*expr_p, 0);
17378 : 10912 : tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
17379 : 10912 : ? NULL : TREE_OPERAND (*expr_p, 1);
17380 : 10912 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
17381 : 10912 : tree tmp_load;
17382 : 10912 : gomp_atomic_load *loadstmt;
17383 : 10912 : gomp_atomic_store *storestmt;
17384 : 10912 : tree target_expr = NULL_TREE;
17385 : :
17386 : 10912 : tmp_load = create_tmp_reg (type);
17387 : 10912 : if (rhs
17388 : 10912 : && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
17389 : : true, 0) < 0)
17390 : : return GS_ERROR;
17391 : :
17392 : 10912 : if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
17393 : : != GS_ALL_DONE)
17394 : : return GS_ERROR;
17395 : :
17396 : 10912 : loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
17397 : 10912 : OMP_ATOMIC_MEMORY_ORDER (*expr_p));
17398 : 10912 : gimplify_seq_add_stmt (pre_p, loadstmt);
17399 : 10912 : if (rhs)
17400 : : {
17401 : : /* BIT_INSERT_EXPR is not valid for non-integral bitfield
17402 : : representatives. Use BIT_FIELD_REF on the lhs instead. */
17403 : 9689 : tree rhsarg = rhs;
17404 : 9689 : if (TREE_CODE (rhs) == COND_EXPR)
17405 : 471 : rhsarg = TREE_OPERAND (rhs, 1);
17406 : 9689 : if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
17407 : 9689 : && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
17408 : : {
17409 : 40 : tree bitpos = TREE_OPERAND (rhsarg, 2);
17410 : 40 : tree op1 = TREE_OPERAND (rhsarg, 1);
17411 : 40 : tree bitsize;
17412 : 40 : tree tmp_store = tmp_load;
17413 : 40 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
17414 : 15 : tmp_store = get_initialized_tmp_var (tmp_load, pre_p);
17415 : 40 : if (INTEGRAL_TYPE_P (TREE_TYPE (op1)))
17416 : 40 : bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
17417 : : else
17418 : 0 : bitsize = TYPE_SIZE (TREE_TYPE (op1));
17419 : 40 : gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
17420 : 40 : tree t = build2_loc (EXPR_LOCATION (rhsarg),
17421 : : MODIFY_EXPR, void_type_node,
17422 : 40 : build3_loc (EXPR_LOCATION (rhsarg),
17423 : 40 : BIT_FIELD_REF, TREE_TYPE (op1),
17424 : : tmp_store, bitsize, bitpos), op1);
17425 : 40 : if (TREE_CODE (rhs) == COND_EXPR)
17426 : 20 : t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
17427 : 20 : TREE_OPERAND (rhs, 0), t, void_node);
17428 : 40 : gimplify_and_add (t, pre_p);
17429 : 40 : rhs = tmp_store;
17430 : : }
17431 : 9689 : bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
17432 : 9689 : if (TREE_CODE (rhs) == COND_EXPR)
17433 : 451 : gimplify_ctxp->allow_rhs_cond_expr = true;
17434 : 9689 : enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
17435 : : is_gimple_val, fb_rvalue);
17436 : 9689 : gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
17437 : 9689 : if (gs != GS_ALL_DONE)
17438 : : return GS_ERROR;
17439 : : }
17440 : :
17441 : 10912 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
17442 : 1223 : rhs = tmp_load;
17443 : 10912 : storestmt
17444 : 10912 : = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
17445 : 10912 : if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
17446 : : {
17447 : 43 : gimple_omp_atomic_set_weak (loadstmt);
17448 : 43 : gimple_omp_atomic_set_weak (storestmt);
17449 : : }
17450 : 10912 : gimplify_seq_add_stmt (pre_p, storestmt);
17451 : 10912 : switch (TREE_CODE (*expr_p))
17452 : : {
17453 : 2163 : case OMP_ATOMIC_READ:
17454 : 2163 : case OMP_ATOMIC_CAPTURE_OLD:
17455 : 2163 : *expr_p = tmp_load;
17456 : 2163 : gimple_omp_atomic_set_need_value (loadstmt);
17457 : 2163 : break;
17458 : 909 : case OMP_ATOMIC_CAPTURE_NEW:
17459 : 909 : *expr_p = rhs;
17460 : 909 : gimple_omp_atomic_set_need_value (storestmt);
17461 : 909 : break;
17462 : 7840 : default:
17463 : 7840 : *expr_p = NULL;
17464 : 7840 : break;
17465 : : }
17466 : :
17467 : : return GS_ALL_DONE;
17468 : : }
17469 : :
17470 : : /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
17471 : : body, and adding some EH bits. */
17472 : :
17473 : : static enum gimplify_status
17474 : 545 : gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
17475 : : {
17476 : 545 : tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
17477 : 545 : gimple *body_stmt;
17478 : 545 : gtransaction *trans_stmt;
17479 : 545 : gimple_seq body = NULL;
17480 : 545 : int subcode = 0;
17481 : :
17482 : : /* Wrap the transaction body in a BIND_EXPR so we have a context
17483 : : where to put decls for OMP. */
17484 : 545 : if (TREE_CODE (tbody) != BIND_EXPR)
17485 : : {
17486 : 497 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
17487 : 497 : TREE_SIDE_EFFECTS (bind) = 1;
17488 : 497 : SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
17489 : 497 : TRANSACTION_EXPR_BODY (expr) = bind;
17490 : : }
17491 : :
17492 : 545 : push_gimplify_context ();
17493 : 545 : temp = voidify_wrapper_expr (*expr_p, NULL);
17494 : :
17495 : 545 : body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
17496 : 545 : pop_gimplify_context (body_stmt);
17497 : :
17498 : 545 : trans_stmt = gimple_build_transaction (body);
17499 : 545 : if (TRANSACTION_EXPR_OUTER (expr))
17500 : : subcode = GTMA_IS_OUTER;
17501 : 509 : else if (TRANSACTION_EXPR_RELAXED (expr))
17502 : 97 : subcode = GTMA_IS_RELAXED;
17503 : 545 : gimple_transaction_set_subcode (trans_stmt, subcode);
17504 : :
17505 : 545 : gimplify_seq_add_stmt (pre_p, trans_stmt);
17506 : :
17507 : 545 : if (temp)
17508 : : {
17509 : 80 : *expr_p = temp;
17510 : 80 : return GS_OK;
17511 : : }
17512 : :
17513 : 465 : *expr_p = NULL_TREE;
17514 : 465 : return GS_ALL_DONE;
17515 : : }
17516 : :
17517 : : /* Gimplify an OMP_ORDERED construct. EXPR is the tree version. BODY
17518 : : is the OMP_BODY of the original EXPR (which has already been
17519 : : gimplified so it's not present in the EXPR).
17520 : :
17521 : : Return the gimplified GIMPLE_OMP_ORDERED tuple. */
17522 : :
17523 : : static gimple *
17524 : 2217 : gimplify_omp_ordered (tree expr, gimple_seq body)
17525 : : {
17526 : 2217 : tree c, decls;
17527 : 2217 : int failures = 0;
17528 : 2217 : unsigned int i;
17529 : 2217 : tree source_c = NULL_TREE;
17530 : 2217 : tree sink_c = NULL_TREE;
17531 : :
17532 : 2217 : if (gimplify_omp_ctxp)
17533 : : {
17534 : 3727 : for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
17535 : 1723 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
17536 : 1723 : && gimplify_omp_ctxp->loop_iter_var.is_empty ())
17537 : : {
17538 : 92 : error_at (OMP_CLAUSE_LOCATION (c),
17539 : : "%<ordered%> construct with %qs clause must be "
17540 : : "closely nested inside a loop with %<ordered%> clause",
17541 : 92 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
17542 : 92 : failures++;
17543 : : }
17544 : 1631 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
17545 : 1631 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
17546 : : {
17547 : 706 : bool fail = false;
17548 : 706 : sink_c = c;
17549 : 706 : if (OMP_CLAUSE_DECL (c) == NULL_TREE)
17550 : 85 : continue; /* omp_cur_iteration - 1 */
17551 : 621 : for (decls = OMP_CLAUSE_DECL (c), i = 0;
17552 : 3331 : decls && TREE_CODE (decls) == TREE_LIST;
17553 : 2710 : decls = TREE_CHAIN (decls), ++i)
17554 : 5420 : if (i >= gimplify_omp_ctxp->loop_iter_var.length () / 2)
17555 : 5 : continue;
17556 : 5410 : else if (TREE_VALUE (decls)
17557 : 2705 : != gimplify_omp_ctxp->loop_iter_var[2 * i])
17558 : : {
17559 : 10 : error_at (OMP_CLAUSE_LOCATION (c),
17560 : : "variable %qE is not an iteration "
17561 : : "of outermost loop %d, expected %qE",
17562 : 10 : TREE_VALUE (decls), i + 1,
17563 : 10 : gimplify_omp_ctxp->loop_iter_var[2 * i]);
17564 : 10 : fail = true;
17565 : 10 : failures++;
17566 : : }
17567 : : else
17568 : 5390 : TREE_VALUE (decls)
17569 : 2695 : = gimplify_omp_ctxp->loop_iter_var[2 * i + 1];
17570 : 1237 : if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
17571 : : {
17572 : 20 : error_at (OMP_CLAUSE_LOCATION (c),
17573 : : "number of variables in %qs clause with "
17574 : : "%<sink%> modifier does not match number of "
17575 : : "iteration variables",
17576 : 20 : OMP_CLAUSE_DOACROSS_DEPEND (c)
17577 : : ? "depend" : "doacross");
17578 : 20 : failures++;
17579 : : }
17580 : : }
17581 : 925 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
17582 : 925 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
17583 : : {
17584 : 532 : if (source_c)
17585 : : {
17586 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
17587 : : "more than one %qs clause with %<source%> "
17588 : : "modifier on an %<ordered%> construct",
17589 : 5 : OMP_CLAUSE_DOACROSS_DEPEND (source_c)
17590 : : ? "depend" : "doacross");
17591 : 5 : failures++;
17592 : : }
17593 : : else
17594 : : source_c = c;
17595 : : }
17596 : : }
17597 : 2217 : if (source_c && sink_c)
17598 : : {
17599 : 5 : error_at (OMP_CLAUSE_LOCATION (source_c),
17600 : : "%qs clause with %<source%> modifier specified "
17601 : : "together with %qs clauses with %<sink%> modifier "
17602 : : "on the same construct",
17603 : 5 : OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
17604 : 5 : OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
17605 : 5 : failures++;
17606 : : }
17607 : :
17608 : 2217 : if (failures)
17609 : 127 : return gimple_build_nop ();
17610 : 2090 : return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
17611 : : }
17612 : :
17613 : : /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
17614 : : expression produces a value to be used as an operand inside a GIMPLE
17615 : : statement, the value will be stored back in *EXPR_P. This value will
17616 : : be a tree of class tcc_declaration, tcc_constant, tcc_reference or
17617 : : an SSA_NAME. The corresponding sequence of GIMPLE statements is
17618 : : emitted in PRE_P and POST_P.
17619 : :
17620 : : Additionally, this process may overwrite parts of the input
17621 : : expression during gimplification. Ideally, it should be
17622 : : possible to do non-destructive gimplification.
17623 : :
17624 : : EXPR_P points to the GENERIC expression to convert to GIMPLE. If
17625 : : the expression needs to evaluate to a value to be used as
17626 : : an operand in a GIMPLE statement, this value will be stored in
17627 : : *EXPR_P on exit. This happens when the caller specifies one
17628 : : of fb_lvalue or fb_rvalue fallback flags.
17629 : :
17630 : : PRE_P will contain the sequence of GIMPLE statements corresponding
17631 : : to the evaluation of EXPR and all the side-effects that must
17632 : : be executed before the main expression. On exit, the last
17633 : : statement of PRE_P is the core statement being gimplified. For
17634 : : instance, when gimplifying 'if (++a)' the last statement in
17635 : : PRE_P will be 'if (t.1)' where t.1 is the result of
17636 : : pre-incrementing 'a'.
17637 : :
17638 : : POST_P will contain the sequence of GIMPLE statements corresponding
17639 : : to the evaluation of all the side-effects that must be executed
17640 : : after the main expression. If this is NULL, the post
17641 : : side-effects are stored at the end of PRE_P.
17642 : :
17643 : : The reason why the output is split in two is to handle post
17644 : : side-effects explicitly. In some cases, an expression may have
17645 : : inner and outer post side-effects which need to be emitted in
17646 : : an order different from the one given by the recursive
17647 : : traversal. For instance, for the expression (*p--)++ the post
17648 : : side-effects of '--' must actually occur *after* the post
17649 : : side-effects of '++'. However, gimplification will first visit
17650 : : the inner expression, so if a separate POST sequence was not
17651 : : used, the resulting sequence would be:
17652 : :
17653 : : 1 t.1 = *p
17654 : : 2 p = p - 1
17655 : : 3 t.2 = t.1 + 1
17656 : : 4 *p = t.2
17657 : :
17658 : : However, the post-decrement operation in line #2 must not be
17659 : : evaluated until after the store to *p at line #4, so the
17660 : : correct sequence should be:
17661 : :
17662 : : 1 t.1 = *p
17663 : : 2 t.2 = t.1 + 1
17664 : : 3 *p = t.2
17665 : : 4 p = p - 1
17666 : :
17667 : : So, by specifying a separate post queue, it is possible
17668 : : to emit the post side-effects in the correct order.
17669 : : If POST_P is NULL, an internal queue will be used. Before
17670 : : returning to the caller, the sequence POST_P is appended to
17671 : : the main output sequence PRE_P.
17672 : :
17673 : : GIMPLE_TEST_F points to a function that takes a tree T and
17674 : : returns nonzero if T is in the GIMPLE form requested by the
17675 : : caller. The GIMPLE predicates are in gimple.cc.
17676 : :
17677 : : FALLBACK tells the function what sort of a temporary we want if
17678 : : gimplification cannot produce an expression that complies with
17679 : : GIMPLE_TEST_F.
17680 : :
17681 : : fb_none means that no temporary should be generated
17682 : : fb_rvalue means that an rvalue is OK to generate
17683 : : fb_lvalue means that an lvalue is OK to generate
17684 : : fb_either means that either is OK, but an lvalue is preferable.
17685 : : fb_mayfail means that gimplification may fail (in which case
17686 : : GS_ERROR will be returned)
17687 : :
17688 : : The return value is either GS_ERROR or GS_ALL_DONE, since this
17689 : : function iterates until EXPR is completely gimplified or an error
17690 : : occurs. */
17691 : :
17692 : : enum gimplify_status
17693 : 466193960 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
17694 : : bool (*gimple_test_f) (tree), fallback_t fallback)
17695 : : {
17696 : 466193960 : tree tmp;
17697 : 466193960 : gimple_seq internal_pre = NULL;
17698 : 466193960 : gimple_seq internal_post = NULL;
17699 : 466193960 : tree save_expr;
17700 : 466193960 : bool is_statement;
17701 : 466193960 : location_t saved_location;
17702 : 466193960 : enum gimplify_status ret;
17703 : 466193960 : gimple_stmt_iterator pre_last_gsi, post_last_gsi;
17704 : 466193960 : tree label;
17705 : :
17706 : 466193960 : save_expr = *expr_p;
17707 : 466193960 : if (save_expr == NULL_TREE)
17708 : : return GS_ALL_DONE;
17709 : :
17710 : : /* If we are gimplifying a top-level statement, PRE_P must be valid. */
17711 : 420021691 : is_statement = gimple_test_f == is_gimple_stmt;
17712 : 420021691 : if (is_statement)
17713 : 92490873 : gcc_assert (pre_p);
17714 : :
17715 : : /* Consistency checks. */
17716 : 420021691 : if (gimple_test_f == is_gimple_reg)
17717 : 5883213 : gcc_assert (fallback & (fb_rvalue | fb_lvalue));
17718 : 414138478 : else if (gimple_test_f == is_gimple_val
17719 : 306813543 : || gimple_test_f == is_gimple_call_addr
17720 : 292246146 : || gimple_test_f == is_gimple_condexpr_for_cond
17721 : 287205210 : || gimple_test_f == is_gimple_mem_rhs
17722 : 287063753 : || gimple_test_f == is_gimple_mem_rhs_or_call
17723 : 276991388 : || gimple_test_f == is_gimple_reg_rhs
17724 : 276465889 : || gimple_test_f == is_gimple_reg_rhs_or_call
17725 : 211260437 : || gimple_test_f == is_gimple_asm_val
17726 : 211215234 : || gimple_test_f == is_gimple_mem_ref_addr)
17727 : 216993260 : gcc_assert (fallback & fb_rvalue);
17728 : 197145218 : else if (gimple_test_f == is_gimple_min_lval
17729 : 169836292 : || gimple_test_f == is_gimple_lvalue)
17730 : 75608948 : gcc_assert (fallback & fb_lvalue);
17731 : 121536270 : else if (gimple_test_f == is_gimple_addressable)
17732 : 29045397 : gcc_assert (fallback & fb_either);
17733 : 92490873 : else if (gimple_test_f == is_gimple_stmt)
17734 : 92490873 : gcc_assert (fallback == fb_none);
17735 : : else
17736 : : {
17737 : : /* We should have recognized the GIMPLE_TEST_F predicate to
17738 : : know what kind of fallback to use in case a temporary is
17739 : : needed to hold the value or address of *EXPR_P. */
17740 : 0 : gcc_unreachable ();
17741 : : }
17742 : :
17743 : : /* We used to check the predicate here and return immediately if it
17744 : : succeeds. This is wrong; the design is for gimplification to be
17745 : : idempotent, and for the predicates to only test for valid forms, not
17746 : : whether they are fully simplified. */
17747 : 420021691 : if (pre_p == NULL)
17748 : 0 : pre_p = &internal_pre;
17749 : :
17750 : 420021691 : if (post_p == NULL)
17751 : 169347401 : post_p = &internal_post;
17752 : :
17753 : : /* Remember the last statements added to PRE_P and POST_P. Every
17754 : : new statement added by the gimplification helpers needs to be
17755 : : annotated with location information. To centralize the
17756 : : responsibility, we remember the last statement that had been
17757 : : added to both queues before gimplifying *EXPR_P. If
17758 : : gimplification produces new statements in PRE_P and POST_P, those
17759 : : statements will be annotated with the same location information
17760 : : as *EXPR_P. */
17761 : 420021691 : pre_last_gsi = gsi_last (*pre_p);
17762 : 420021691 : post_last_gsi = gsi_last (*post_p);
17763 : :
17764 : 420021691 : saved_location = input_location;
17765 : 420021691 : if (save_expr != error_mark_node
17766 : 420021691 : && EXPR_HAS_LOCATION (*expr_p))
17767 : 158041327 : input_location = EXPR_LOCATION (*expr_p);
17768 : :
17769 : : /* Loop over the specific gimplifiers until the toplevel node
17770 : : remains the same. */
17771 : 436545644 : do
17772 : : {
17773 : : /* Strip away as many useless type conversions as possible
17774 : : at the toplevel. */
17775 : 436545644 : STRIP_USELESS_TYPE_CONVERSION (*expr_p);
17776 : :
17777 : : /* Remember the expr. */
17778 : 436545644 : save_expr = *expr_p;
17779 : :
17780 : : /* Die, die, die, my darling. */
17781 : 436545644 : if (error_operand_p (save_expr))
17782 : : {
17783 : : ret = GS_ERROR;
17784 : : break;
17785 : : }
17786 : :
17787 : : /* Do any language-specific gimplification. */
17788 : 436542420 : ret = ((enum gimplify_status)
17789 : 436542420 : lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
17790 : 436542420 : if (ret == GS_OK)
17791 : : {
17792 : 24750471 : if (*expr_p == NULL_TREE)
17793 : : break;
17794 : 24750471 : if (*expr_p != save_expr)
17795 : 4386562 : continue;
17796 : : }
17797 : 411791949 : else if (ret != GS_UNHANDLED)
17798 : : break;
17799 : :
17800 : : /* Make sure that all the cases set 'ret' appropriately. */
17801 : 431638080 : ret = GS_UNHANDLED;
17802 : 431638080 : switch (TREE_CODE (*expr_p))
17803 : : {
17804 : : /* First deal with the special cases. */
17805 : :
17806 : 1094661 : case POSTINCREMENT_EXPR:
17807 : 1094661 : case POSTDECREMENT_EXPR:
17808 : 1094661 : case PREINCREMENT_EXPR:
17809 : 1094661 : case PREDECREMENT_EXPR:
17810 : 2189322 : ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
17811 : : fallback != fb_none,
17812 : 1094661 : TREE_TYPE (*expr_p));
17813 : 1094661 : break;
17814 : :
17815 : 613975 : case VIEW_CONVERT_EXPR:
17816 : 613975 : if ((fallback & fb_rvalue)
17817 : 613893 : && is_gimple_reg_type (TREE_TYPE (*expr_p))
17818 : 1054061 : && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
17819 : : {
17820 : 428397 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
17821 : : post_p, is_gimple_val, fb_rvalue);
17822 : 428397 : recalculate_side_effects (*expr_p);
17823 : 428397 : break;
17824 : : }
17825 : : /* Fallthru. */
17826 : :
17827 : 27246333 : case ARRAY_REF:
17828 : 27246333 : case ARRAY_RANGE_REF:
17829 : 27246333 : case REALPART_EXPR:
17830 : 27246333 : case IMAGPART_EXPR:
17831 : 27246333 : case COMPONENT_REF:
17832 : 27246333 : ret = gimplify_compound_lval (expr_p, pre_p, post_p,
17833 : : fallback ? fallback : fb_rvalue);
17834 : 27246333 : break;
17835 : :
17836 : 5722987 : case COND_EXPR:
17837 : 5722987 : ret = gimplify_cond_expr (expr_p, pre_p, fallback);
17838 : :
17839 : : /* C99 code may assign to an array in a structure value of a
17840 : : conditional expression, and this has undefined behavior
17841 : : only on execution, so create a temporary if an lvalue is
17842 : : required. */
17843 : 5722987 : if (fallback == fb_lvalue)
17844 : : {
17845 : 7 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
17846 : 7 : mark_addressable (*expr_p);
17847 : 7 : ret = GS_OK;
17848 : : }
17849 : : break;
17850 : :
17851 : 14909024 : case CALL_EXPR:
17852 : 14909024 : ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none);
17853 : :
17854 : : /* C99 code may assign to an array in a structure returned
17855 : : from a function, and this has undefined behavior only on
17856 : : execution, so create a temporary if an lvalue is
17857 : : required. */
17858 : 14909024 : if (fallback == fb_lvalue)
17859 : : {
17860 : 13681 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
17861 : 13681 : mark_addressable (*expr_p);
17862 : 13681 : ret = GS_OK;
17863 : : }
17864 : : break;
17865 : :
17866 : 0 : case TREE_LIST:
17867 : 0 : gcc_unreachable ();
17868 : :
17869 : 0 : case OMP_ARRAY_SECTION:
17870 : 0 : gcc_unreachable ();
17871 : :
17872 : 359500 : case COMPOUND_EXPR:
17873 : 359500 : ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
17874 : 359500 : break;
17875 : :
17876 : 36374 : case COMPOUND_LITERAL_EXPR:
17877 : 36374 : ret = gimplify_compound_literal_expr (expr_p, pre_p,
17878 : : gimple_test_f, fallback);
17879 : 36374 : break;
17880 : :
17881 : 45233233 : case MODIFY_EXPR:
17882 : 45233233 : case INIT_EXPR:
17883 : 45233233 : ret = gimplify_modify_expr (expr_p, pre_p, post_p,
17884 : : fallback != fb_none);
17885 : 45233233 : break;
17886 : :
17887 : 104215 : case TRUTH_ANDIF_EXPR:
17888 : 104215 : case TRUTH_ORIF_EXPR:
17889 : 104215 : {
17890 : : /* Preserve the original type of the expression and the
17891 : : source location of the outer expression. */
17892 : 104215 : tree org_type = TREE_TYPE (*expr_p);
17893 : 104215 : *expr_p = gimple_boolify (*expr_p);
17894 : 104215 : *expr_p = build3_loc (input_location, COND_EXPR,
17895 : : org_type, *expr_p,
17896 : : fold_convert_loc
17897 : : (input_location,
17898 : : org_type, boolean_true_node),
17899 : : fold_convert_loc
17900 : : (input_location,
17901 : : org_type, boolean_false_node));
17902 : 104215 : ret = GS_OK;
17903 : 104215 : break;
17904 : : }
17905 : :
17906 : 214354 : case TRUTH_NOT_EXPR:
17907 : 214354 : {
17908 : 214354 : tree type = TREE_TYPE (*expr_p);
17909 : : /* The parsers are careful to generate TRUTH_NOT_EXPR
17910 : : only with operands that are always zero or one.
17911 : : We do not fold here but handle the only interesting case
17912 : : manually, as fold may re-introduce the TRUTH_NOT_EXPR. */
17913 : 214354 : *expr_p = gimple_boolify (*expr_p);
17914 : 214354 : if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
17915 : 214354 : *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
17916 : 214354 : TREE_TYPE (*expr_p),
17917 : 214354 : TREE_OPERAND (*expr_p, 0));
17918 : : else
17919 : 0 : *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
17920 : 0 : TREE_TYPE (*expr_p),
17921 : 0 : TREE_OPERAND (*expr_p, 0),
17922 : 0 : build_int_cst (TREE_TYPE (*expr_p), 1));
17923 : 214354 : if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
17924 : 4670 : *expr_p = fold_convert_loc (input_location, type, *expr_p);
17925 : : ret = GS_OK;
17926 : : break;
17927 : : }
17928 : :
17929 : 29119903 : case ADDR_EXPR:
17930 : 29119903 : ret = gimplify_addr_expr (expr_p, pre_p, post_p);
17931 : 29119903 : break;
17932 : :
17933 : 3335 : case ANNOTATE_EXPR:
17934 : 3335 : {
17935 : 3335 : tree cond = TREE_OPERAND (*expr_p, 0);
17936 : 3335 : tree kind = TREE_OPERAND (*expr_p, 1);
17937 : 3335 : tree data = TREE_OPERAND (*expr_p, 2);
17938 : 3335 : tree type = TREE_TYPE (cond);
17939 : 3335 : if (!INTEGRAL_TYPE_P (type))
17940 : : {
17941 : 0 : *expr_p = cond;
17942 : 0 : ret = GS_OK;
17943 : 0 : break;
17944 : : }
17945 : 3335 : tree tmp = create_tmp_var (type);
17946 : 3335 : gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
17947 : 3335 : gcall *call
17948 : 3335 : = gimple_build_call_internal (IFN_ANNOTATE, 3, cond, kind, data);
17949 : 3335 : gimple_call_set_lhs (call, tmp);
17950 : 3335 : gimplify_seq_add_stmt (pre_p, call);
17951 : 3335 : *expr_p = tmp;
17952 : 3335 : ret = GS_ALL_DONE;
17953 : 3335 : break;
17954 : : }
17955 : :
17956 : 50879 : case VA_ARG_EXPR:
17957 : 50879 : ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
17958 : 50879 : break;
17959 : :
17960 : 15775250 : CASE_CONVERT:
17961 : 15775250 : if (IS_EMPTY_STMT (*expr_p))
17962 : : {
17963 : : ret = GS_ALL_DONE;
17964 : : break;
17965 : : }
17966 : :
17967 : 14232790 : if (VOID_TYPE_P (TREE_TYPE (*expr_p))
17968 : 14232790 : || fallback == fb_none)
17969 : : {
17970 : : /* Just strip a conversion to void (or in void context) and
17971 : : try again. */
17972 : 2432710 : *expr_p = TREE_OPERAND (*expr_p, 0);
17973 : 2432710 : ret = GS_OK;
17974 : 2432710 : break;
17975 : : }
17976 : :
17977 : 11800080 : ret = gimplify_conversion (expr_p);
17978 : 11800080 : if (ret == GS_ERROR)
17979 : : break;
17980 : 11800080 : if (*expr_p != save_expr)
17981 : : break;
17982 : : /* FALLTHRU */
17983 : :
17984 : 11925582 : case FIX_TRUNC_EXPR:
17985 : : /* unary_expr: ... | '(' cast ')' val | ... */
17986 : 11925582 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
17987 : : is_gimple_val, fb_rvalue);
17988 : 11925582 : recalculate_side_effects (*expr_p);
17989 : 11925582 : break;
17990 : :
17991 : 5822458 : case INDIRECT_REF:
17992 : 5822458 : {
17993 : 5822458 : bool volatilep = TREE_THIS_VOLATILE (*expr_p);
17994 : 5822458 : bool notrap = TREE_THIS_NOTRAP (*expr_p);
17995 : 5822458 : tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
17996 : :
17997 : 5822458 : *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
17998 : 5822458 : if (*expr_p != save_expr)
17999 : : {
18000 : : ret = GS_OK;
18001 : : break;
18002 : : }
18003 : :
18004 : 5808333 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
18005 : : is_gimple_reg, fb_rvalue);
18006 : 5808333 : if (ret == GS_ERROR)
18007 : : break;
18008 : :
18009 : 5808332 : recalculate_side_effects (*expr_p);
18010 : 5808332 : *expr_p = fold_build2_loc (input_location, MEM_REF,
18011 : 5808332 : TREE_TYPE (*expr_p),
18012 : 5808332 : TREE_OPERAND (*expr_p, 0),
18013 : 5808332 : build_int_cst (saved_ptr_type, 0));
18014 : 5808332 : TREE_THIS_VOLATILE (*expr_p) = volatilep;
18015 : 5808332 : TREE_THIS_NOTRAP (*expr_p) = notrap;
18016 : 5808332 : ret = GS_OK;
18017 : 5808332 : break;
18018 : : }
18019 : :
18020 : : /* We arrive here through the various re-gimplifcation paths. */
18021 : 14626282 : case MEM_REF:
18022 : : /* First try re-folding the whole thing. */
18023 : 14626282 : tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
18024 : : TREE_OPERAND (*expr_p, 0),
18025 : : TREE_OPERAND (*expr_p, 1));
18026 : 14626282 : if (tmp)
18027 : : {
18028 : 4796 : REF_REVERSE_STORAGE_ORDER (tmp)
18029 : 2398 : = REF_REVERSE_STORAGE_ORDER (*expr_p);
18030 : 2398 : *expr_p = tmp;
18031 : 2398 : recalculate_side_effects (*expr_p);
18032 : 2398 : ret = GS_OK;
18033 : 2398 : break;
18034 : : }
18035 : : /* Avoid re-gimplifying the address operand if it is already
18036 : : in suitable form. Re-gimplifying would mark the address
18037 : : operand addressable. Always gimplify when not in SSA form
18038 : : as we still may have to gimplify decls with value-exprs. */
18039 : 14623884 : if (!gimplify_ctxp || !gimple_in_ssa_p (cfun)
18040 : 15604913 : || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
18041 : : {
18042 : 13697548 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
18043 : : is_gimple_mem_ref_addr, fb_rvalue);
18044 : 13697548 : if (ret == GS_ERROR)
18045 : : break;
18046 : : }
18047 : 14623884 : recalculate_side_effects (*expr_p);
18048 : 14623884 : ret = GS_ALL_DONE;
18049 : 14623884 : break;
18050 : :
18051 : : /* Constants need not be gimplified. */
18052 : 39061057 : case INTEGER_CST:
18053 : 39061057 : case REAL_CST:
18054 : 39061057 : case FIXED_CST:
18055 : 39061057 : case STRING_CST:
18056 : 39061057 : case COMPLEX_CST:
18057 : 39061057 : case VECTOR_CST:
18058 : : /* Drop the overflow flag on constants, we do not want
18059 : : that in the GIMPLE IL. */
18060 : 39061057 : if (TREE_OVERFLOW_P (*expr_p))
18061 : 1385 : *expr_p = drop_tree_overflow (*expr_p);
18062 : : ret = GS_ALL_DONE;
18063 : : break;
18064 : :
18065 : 111364 : case CONST_DECL:
18066 : : /* If we require an lvalue, such as for ADDR_EXPR, retain the
18067 : : CONST_DECL node. Otherwise the decl is replaceable by its
18068 : : value. */
18069 : : /* ??? Should be == fb_lvalue, but ADDR_EXPR passes fb_either. */
18070 : 111364 : if (fallback & fb_lvalue)
18071 : : ret = GS_ALL_DONE;
18072 : : else
18073 : : {
18074 : 3061 : *expr_p = DECL_INITIAL (*expr_p);
18075 : 3061 : ret = GS_OK;
18076 : : }
18077 : : break;
18078 : :
18079 : 6168315 : case DECL_EXPR:
18080 : 6168315 : ret = gimplify_decl_expr (expr_p, pre_p);
18081 : 6168315 : break;
18082 : :
18083 : 5536354 : case BIND_EXPR:
18084 : 5536354 : ret = gimplify_bind_expr (expr_p, pre_p);
18085 : 5536354 : break;
18086 : :
18087 : 156567 : case LOOP_EXPR:
18088 : 156567 : ret = gimplify_loop_expr (expr_p, pre_p);
18089 : 156567 : break;
18090 : :
18091 : 48049 : case SWITCH_EXPR:
18092 : 48049 : ret = gimplify_switch_expr (expr_p, pre_p);
18093 : 48049 : break;
18094 : :
18095 : 3091 : case EXIT_EXPR:
18096 : 3091 : ret = gimplify_exit_expr (expr_p);
18097 : 3091 : break;
18098 : :
18099 : 1002575 : case GOTO_EXPR:
18100 : : /* If the target is not LABEL, then it is a computed jump
18101 : : and the target needs to be gimplified. */
18102 : 1002575 : if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
18103 : : {
18104 : 1100 : ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
18105 : : NULL, is_gimple_val, fb_rvalue);
18106 : 1100 : if (ret == GS_ERROR)
18107 : : break;
18108 : : }
18109 : 2005148 : gimplify_seq_add_stmt (pre_p,
18110 : 1002574 : gimple_build_goto (GOTO_DESTINATION (*expr_p)));
18111 : 1002574 : ret = GS_ALL_DONE;
18112 : 1002574 : break;
18113 : :
18114 : 99683 : case PREDICT_EXPR:
18115 : 398732 : gimplify_seq_add_stmt (pre_p,
18116 : 99683 : gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
18117 : 99683 : PREDICT_EXPR_OUTCOME (*expr_p)));
18118 : 99683 : ret = GS_ALL_DONE;
18119 : 99683 : break;
18120 : :
18121 : 2224384 : case LABEL_EXPR:
18122 : 2224384 : ret = gimplify_label_expr (expr_p, pre_p);
18123 : 2224384 : label = LABEL_EXPR_LABEL (*expr_p);
18124 : 2224384 : gcc_assert (decl_function_context (label) == current_function_decl);
18125 : :
18126 : : /* If the label is used in a goto statement, or address of the label
18127 : : is taken, we need to unpoison all variables that were seen so far.
18128 : : Doing so would prevent us from reporting a false positives. */
18129 : 2224384 : if (asan_poisoned_variables
18130 : 2043 : && asan_used_labels != NULL
18131 : 251 : && asan_used_labels->contains (label)
18132 : 2224556 : && !gimplify_omp_ctxp)
18133 : 164 : asan_poison_variables (asan_poisoned_variables, false, pre_p);
18134 : : break;
18135 : :
18136 : 1037493 : case CASE_LABEL_EXPR:
18137 : 1037493 : ret = gimplify_case_label_expr (expr_p, pre_p);
18138 : :
18139 : 1037493 : if (gimplify_ctxp->live_switch_vars)
18140 : 1037273 : asan_poison_variables (gimplify_ctxp->live_switch_vars, false,
18141 : : pre_p);
18142 : : break;
18143 : :
18144 : 1998678 : case RETURN_EXPR:
18145 : 1998678 : ret = gimplify_return_expr (*expr_p, pre_p);
18146 : 1998678 : break;
18147 : :
18148 : 922372 : case CONSTRUCTOR:
18149 : : /* Don't reduce this in place; let gimplify_init_constructor work its
18150 : : magic. Buf if we're just elaborating this for side effects, just
18151 : : gimplify any element that has side-effects. */
18152 : 922372 : if (fallback == fb_none)
18153 : : {
18154 : 271 : unsigned HOST_WIDE_INT ix;
18155 : 271 : tree val;
18156 : 271 : tree temp = NULL_TREE;
18157 : 287 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
18158 : 16 : if (TREE_SIDE_EFFECTS (val))
18159 : 4 : append_to_statement_list (val, &temp);
18160 : :
18161 : 271 : *expr_p = temp;
18162 : 271 : ret = temp ? GS_OK : GS_ALL_DONE;
18163 : : }
18164 : : /* C99 code may assign to an array in a constructed
18165 : : structure or union, and this has undefined behavior only
18166 : : on execution, so create a temporary if an lvalue is
18167 : : required. */
18168 : 922101 : else if (fallback == fb_lvalue)
18169 : : {
18170 : 3 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
18171 : 3 : mark_addressable (*expr_p);
18172 : 3 : ret = GS_OK;
18173 : : }
18174 : : else
18175 : : ret = GS_ALL_DONE;
18176 : : break;
18177 : :
18178 : : /* The following are special cases that are not handled by the
18179 : : original GIMPLE grammar. */
18180 : :
18181 : : /* SAVE_EXPR nodes are converted into a GIMPLE identifier and
18182 : : eliminated. */
18183 : 456217 : case SAVE_EXPR:
18184 : 456217 : ret = gimplify_save_expr (expr_p, pre_p, post_p);
18185 : 456217 : break;
18186 : :
18187 : 402394 : case BIT_FIELD_REF:
18188 : 402394 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
18189 : : post_p, is_gimple_lvalue, fb_either);
18190 : 402394 : recalculate_side_effects (*expr_p);
18191 : 402394 : break;
18192 : :
18193 : 1239 : case TARGET_MEM_REF:
18194 : 1239 : {
18195 : 1239 : enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
18196 : :
18197 : 1239 : if (TMR_BASE (*expr_p))
18198 : 1239 : r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
18199 : : post_p, is_gimple_mem_ref_addr, fb_either);
18200 : 1239 : if (TMR_INDEX (*expr_p))
18201 : 1053 : r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
18202 : : post_p, is_gimple_val, fb_rvalue);
18203 : 1239 : if (TMR_INDEX2 (*expr_p))
18204 : 57 : r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
18205 : : post_p, is_gimple_val, fb_rvalue);
18206 : : /* TMR_STEP and TMR_OFFSET are always integer constants. */
18207 : 1239 : ret = MIN (r0, r1);
18208 : : }
18209 : : break;
18210 : :
18211 : 0 : case NON_LVALUE_EXPR:
18212 : : /* This should have been stripped above. */
18213 : 0 : gcc_unreachable ();
18214 : :
18215 : 103710 : case ASM_EXPR:
18216 : 103710 : ret = gimplify_asm_expr (expr_p, pre_p, post_p);
18217 : 103710 : break;
18218 : :
18219 : 476922 : case TRY_FINALLY_EXPR:
18220 : 476922 : case TRY_CATCH_EXPR:
18221 : 476922 : {
18222 : 476922 : gimple_seq eval, cleanup;
18223 : 476922 : gtry *try_;
18224 : :
18225 : : /* Calls to destructors are generated automatically in FINALLY/CATCH
18226 : : block. They should have location as UNKNOWN_LOCATION. However,
18227 : : gimplify_call_expr will reset these call stmts to input_location
18228 : : if it finds stmt's location is unknown. To prevent resetting for
18229 : : destructors, we set the input_location to unknown.
18230 : : Note that this only affects the destructor calls in FINALLY/CATCH
18231 : : block, and will automatically reset to its original value by the
18232 : : end of gimplify_expr. */
18233 : 476922 : input_location = UNKNOWN_LOCATION;
18234 : 476922 : eval = cleanup = NULL;
18235 : 476922 : gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
18236 : 476922 : if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
18237 : 476922 : && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR)
18238 : : {
18239 : 0 : gimple_seq n = NULL, e = NULL;
18240 : 0 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
18241 : : 0), &n);
18242 : 0 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
18243 : : 1), &e);
18244 : 0 : if (!gimple_seq_empty_p (n) && !gimple_seq_empty_p (e))
18245 : : {
18246 : 0 : geh_else *stmt = gimple_build_eh_else (n, e);
18247 : 0 : gimple_seq_add_stmt (&cleanup, stmt);
18248 : : }
18249 : : }
18250 : : else
18251 : 476922 : gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
18252 : : /* Don't create bogus GIMPLE_TRY with empty cleanup. */
18253 : 476922 : if (gimple_seq_empty_p (cleanup))
18254 : : {
18255 : 27834 : gimple_seq_add_seq (pre_p, eval);
18256 : 27834 : ret = GS_ALL_DONE;
18257 : 27834 : break;
18258 : : }
18259 : 449088 : try_ = gimple_build_try (eval, cleanup,
18260 : 449088 : TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
18261 : : ? GIMPLE_TRY_FINALLY
18262 : : : GIMPLE_TRY_CATCH);
18263 : 449088 : if (EXPR_HAS_LOCATION (save_expr))
18264 : 821382 : gimple_set_location (try_, EXPR_LOCATION (save_expr));
18265 : 38397 : else if (LOCATION_LOCUS (saved_location) != UNKNOWN_LOCATION)
18266 : 28400 : gimple_set_location (try_, saved_location);
18267 : 449088 : if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
18268 : 175093 : gimple_try_set_catch_is_cleanup (try_,
18269 : 175093 : TRY_CATCH_IS_CLEANUP (*expr_p));
18270 : 449088 : gimplify_seq_add_stmt (pre_p, try_);
18271 : 449088 : ret = GS_ALL_DONE;
18272 : 449088 : break;
18273 : : }
18274 : :
18275 : 4857410 : case CLEANUP_POINT_EXPR:
18276 : 4857410 : ret = gimplify_cleanup_point_expr (expr_p, pre_p);
18277 : 4857410 : break;
18278 : :
18279 : 610878 : case TARGET_EXPR:
18280 : 610878 : ret = gimplify_target_expr (expr_p, pre_p, post_p);
18281 : 610878 : break;
18282 : :
18283 : 40607 : case CATCH_EXPR:
18284 : 40607 : {
18285 : 40607 : gimple *c;
18286 : 40607 : gimple_seq handler = NULL;
18287 : 40607 : gimplify_and_add (CATCH_BODY (*expr_p), &handler);
18288 : 40607 : c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
18289 : 40607 : gimplify_seq_add_stmt (pre_p, c);
18290 : 40607 : ret = GS_ALL_DONE;
18291 : 40607 : break;
18292 : : }
18293 : :
18294 : 3896 : case EH_FILTER_EXPR:
18295 : 3896 : {
18296 : 3896 : gimple *ehf;
18297 : 3896 : gimple_seq failure = NULL;
18298 : :
18299 : 3896 : gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
18300 : 3896 : ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
18301 : 3896 : copy_warning (ehf, *expr_p);
18302 : 3896 : gimplify_seq_add_stmt (pre_p, ehf);
18303 : 3896 : ret = GS_ALL_DONE;
18304 : 3896 : break;
18305 : : }
18306 : :
18307 : 46804 : case OBJ_TYPE_REF:
18308 : 46804 : {
18309 : 46804 : enum gimplify_status r0, r1;
18310 : 46804 : r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p,
18311 : : post_p, is_gimple_val, fb_rvalue);
18312 : 46804 : r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p,
18313 : : post_p, is_gimple_val, fb_rvalue);
18314 : 46804 : TREE_SIDE_EFFECTS (*expr_p) = 0;
18315 : 46804 : ret = MIN (r0, r1);
18316 : : }
18317 : : break;
18318 : :
18319 : 38104 : case LABEL_DECL:
18320 : : /* We get here when taking the address of a label. We mark
18321 : : the label as "forced"; meaning it can never be removed and
18322 : : it is a potential target for any computed goto. */
18323 : 38104 : FORCED_LABEL (*expr_p) = 1;
18324 : 38104 : ret = GS_ALL_DONE;
18325 : 38104 : break;
18326 : :
18327 : 8105341 : case STATEMENT_LIST:
18328 : 8105341 : ret = gimplify_statement_list (expr_p, pre_p);
18329 : 8105341 : break;
18330 : :
18331 : 1531 : case WITH_SIZE_EXPR:
18332 : 1531 : {
18333 : 1813 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
18334 : : post_p == &internal_post ? NULL : post_p,
18335 : : gimple_test_f, fallback);
18336 : 1531 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
18337 : : is_gimple_val, fb_rvalue);
18338 : 1531 : ret = GS_ALL_DONE;
18339 : : }
18340 : 1531 : break;
18341 : :
18342 : 97957231 : case VAR_DECL:
18343 : 97957231 : case PARM_DECL:
18344 : 97957231 : ret = gimplify_var_or_parm_decl (expr_p);
18345 : 97957231 : break;
18346 : :
18347 : 270632 : case RESULT_DECL:
18348 : : /* When within an OMP context, notice uses of variables. */
18349 : 270632 : if (gimplify_omp_ctxp)
18350 : 762 : omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
18351 : : ret = GS_ALL_DONE;
18352 : : break;
18353 : :
18354 : 0 : case DEBUG_EXPR_DECL:
18355 : 0 : gcc_unreachable ();
18356 : :
18357 : 2489824 : case DEBUG_BEGIN_STMT:
18358 : 4979648 : gimplify_seq_add_stmt (pre_p,
18359 : : gimple_build_debug_begin_stmt
18360 : 2489824 : (TREE_BLOCK (*expr_p),
18361 : 2489824 : EXPR_LOCATION (*expr_p)));
18362 : 2489824 : ret = GS_ALL_DONE;
18363 : 2489824 : *expr_p = NULL;
18364 : 2489824 : break;
18365 : :
18366 : : case SSA_NAME:
18367 : : /* Allow callbacks into the gimplifier during optimization. */
18368 : : ret = GS_ALL_DONE;
18369 : : break;
18370 : :
18371 : 18253 : case OMP_PARALLEL:
18372 : 18253 : gimplify_omp_parallel (expr_p, pre_p);
18373 : 18253 : ret = GS_ALL_DONE;
18374 : 18253 : break;
18375 : :
18376 : 4465 : case OMP_TASK:
18377 : 4465 : gimplify_omp_task (expr_p, pre_p);
18378 : 4465 : ret = GS_ALL_DONE;
18379 : 4465 : break;
18380 : :
18381 : 11439 : case OMP_SIMD:
18382 : 11439 : {
18383 : : /* Temporarily disable into_ssa, as scan_omp_simd
18384 : : which calls copy_gimple_seq_and_replace_locals can't deal
18385 : : with SSA_NAMEs defined outside of the body properly. */
18386 : 11439 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
18387 : 11439 : gimplify_ctxp->into_ssa = false;
18388 : 11439 : ret = gimplify_omp_for (expr_p, pre_p);
18389 : 11439 : gimplify_ctxp->into_ssa = saved_into_ssa;
18390 : 11439 : break;
18391 : : }
18392 : :
18393 : 44293 : case OMP_FOR:
18394 : 44293 : case OMP_DISTRIBUTE:
18395 : 44293 : case OMP_TASKLOOP:
18396 : 44293 : case OACC_LOOP:
18397 : 44293 : ret = gimplify_omp_for (expr_p, pre_p);
18398 : 44293 : break;
18399 : :
18400 : 1220 : case OMP_LOOP:
18401 : 1220 : ret = gimplify_omp_loop (expr_p, pre_p);
18402 : 1220 : break;
18403 : :
18404 : 855 : case OACC_CACHE:
18405 : 855 : gimplify_oacc_cache (expr_p, pre_p);
18406 : 855 : ret = GS_ALL_DONE;
18407 : 855 : break;
18408 : :
18409 : 312 : case OACC_DECLARE:
18410 : 312 : gimplify_oacc_declare (expr_p, pre_p);
18411 : 312 : ret = GS_ALL_DONE;
18412 : 312 : break;
18413 : :
18414 : 39074 : case OACC_HOST_DATA:
18415 : 39074 : case OACC_DATA:
18416 : 39074 : case OACC_KERNELS:
18417 : 39074 : case OACC_PARALLEL:
18418 : 39074 : case OACC_SERIAL:
18419 : 39074 : case OMP_SCOPE:
18420 : 39074 : case OMP_SECTIONS:
18421 : 39074 : case OMP_SINGLE:
18422 : 39074 : case OMP_TARGET:
18423 : 39074 : case OMP_TARGET_DATA:
18424 : 39074 : case OMP_TEAMS:
18425 : 39074 : gimplify_omp_workshare (expr_p, pre_p);
18426 : 39074 : ret = GS_ALL_DONE;
18427 : 39074 : break;
18428 : :
18429 : 11926 : case OACC_ENTER_DATA:
18430 : 11926 : case OACC_EXIT_DATA:
18431 : 11926 : case OACC_UPDATE:
18432 : 11926 : case OMP_TARGET_UPDATE:
18433 : 11926 : case OMP_TARGET_ENTER_DATA:
18434 : 11926 : case OMP_TARGET_EXIT_DATA:
18435 : 11926 : gimplify_omp_target_update (expr_p, pre_p);
18436 : 11926 : ret = GS_ALL_DONE;
18437 : 11926 : break;
18438 : :
18439 : 7673 : case OMP_SECTION:
18440 : 7673 : case OMP_STRUCTURED_BLOCK:
18441 : 7673 : case OMP_MASTER:
18442 : 7673 : case OMP_MASKED:
18443 : 7673 : case OMP_ORDERED:
18444 : 7673 : case OMP_CRITICAL:
18445 : 7673 : case OMP_SCAN:
18446 : 7673 : {
18447 : 7673 : gimple_seq body = NULL;
18448 : 7673 : gimple *g;
18449 : 7673 : bool saved_in_omp_construct = in_omp_construct;
18450 : :
18451 : 7673 : in_omp_construct = true;
18452 : 7673 : gimplify_and_add (OMP_BODY (*expr_p), &body);
18453 : 7673 : in_omp_construct = saved_in_omp_construct;
18454 : 7673 : switch (TREE_CODE (*expr_p))
18455 : : {
18456 : 1440 : case OMP_SECTION:
18457 : 1440 : g = gimple_build_omp_section (body);
18458 : 1440 : break;
18459 : 745 : case OMP_STRUCTURED_BLOCK:
18460 : 745 : g = gimple_build_omp_structured_block (body);
18461 : 745 : break;
18462 : 998 : case OMP_MASTER:
18463 : 998 : g = gimple_build_omp_master (body);
18464 : 998 : break;
18465 : 2217 : case OMP_ORDERED:
18466 : 2217 : g = gimplify_omp_ordered (*expr_p, body);
18467 : 2217 : if (OMP_BODY (*expr_p) == NULL_TREE
18468 : 2217 : && gimple_code (g) == GIMPLE_OMP_ORDERED)
18469 : 1146 : gimple_omp_ordered_standalone (g);
18470 : : break;
18471 : 434 : case OMP_MASKED:
18472 : 434 : gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p),
18473 : : pre_p, ORT_WORKSHARE, OMP_MASKED);
18474 : 434 : gimplify_adjust_omp_clauses (pre_p, body,
18475 : : &OMP_MASKED_CLAUSES (*expr_p),
18476 : : OMP_MASKED);
18477 : 868 : g = gimple_build_omp_masked (body,
18478 : 434 : OMP_MASKED_CLAUSES (*expr_p));
18479 : 434 : break;
18480 : 605 : case OMP_CRITICAL:
18481 : 605 : gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
18482 : : pre_p, ORT_WORKSHARE, OMP_CRITICAL);
18483 : 605 : gimplify_adjust_omp_clauses (pre_p, body,
18484 : : &OMP_CRITICAL_CLAUSES (*expr_p),
18485 : : OMP_CRITICAL);
18486 : 1815 : g = gimple_build_omp_critical (body,
18487 : 605 : OMP_CRITICAL_NAME (*expr_p),
18488 : 605 : OMP_CRITICAL_CLAUSES (*expr_p));
18489 : 605 : break;
18490 : 1234 : case OMP_SCAN:
18491 : 1234 : gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
18492 : : pre_p, ORT_WORKSHARE, OMP_SCAN);
18493 : 1234 : gimplify_adjust_omp_clauses (pre_p, body,
18494 : : &OMP_SCAN_CLAUSES (*expr_p),
18495 : : OMP_SCAN);
18496 : 1234 : g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
18497 : 1234 : break;
18498 : 0 : default:
18499 : 0 : gcc_unreachable ();
18500 : : }
18501 : 7673 : gimplify_seq_add_stmt (pre_p, g);
18502 : 7673 : ret = GS_ALL_DONE;
18503 : 7673 : break;
18504 : : }
18505 : :
18506 : 663 : case OMP_TASKGROUP:
18507 : 663 : {
18508 : 663 : gimple_seq body = NULL;
18509 : :
18510 : 663 : tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p);
18511 : 663 : bool saved_in_omp_construct = in_omp_construct;
18512 : 663 : gimplify_scan_omp_clauses (pclauses, pre_p, ORT_TASKGROUP,
18513 : : OMP_TASKGROUP);
18514 : 663 : gimplify_adjust_omp_clauses (pre_p, NULL, pclauses, OMP_TASKGROUP);
18515 : :
18516 : 663 : in_omp_construct = true;
18517 : 663 : gimplify_and_add (OMP_BODY (*expr_p), &body);
18518 : 663 : in_omp_construct = saved_in_omp_construct;
18519 : 663 : gimple_seq cleanup = NULL;
18520 : 663 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END);
18521 : 663 : gimple *g = gimple_build_call (fn, 0);
18522 : 663 : gimple_seq_add_stmt (&cleanup, g);
18523 : 663 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
18524 : 663 : body = NULL;
18525 : 663 : gimple_seq_add_stmt (&body, g);
18526 : 663 : g = gimple_build_omp_taskgroup (body, *pclauses);
18527 : 663 : gimplify_seq_add_stmt (pre_p, g);
18528 : 663 : ret = GS_ALL_DONE;
18529 : 663 : break;
18530 : : }
18531 : :
18532 : 10912 : case OMP_ATOMIC:
18533 : 10912 : case OMP_ATOMIC_READ:
18534 : 10912 : case OMP_ATOMIC_CAPTURE_OLD:
18535 : 10912 : case OMP_ATOMIC_CAPTURE_NEW:
18536 : 10912 : ret = gimplify_omp_atomic (expr_p, pre_p);
18537 : 10912 : break;
18538 : :
18539 : 545 : case TRANSACTION_EXPR:
18540 : 545 : ret = gimplify_transaction (expr_p, pre_p);
18541 : 545 : break;
18542 : :
18543 : 247293 : case TRUTH_AND_EXPR:
18544 : 247293 : case TRUTH_OR_EXPR:
18545 : 247293 : case TRUTH_XOR_EXPR:
18546 : 247293 : {
18547 : 247293 : tree orig_type = TREE_TYPE (*expr_p);
18548 : 247293 : tree new_type, xop0, xop1;
18549 : 247293 : *expr_p = gimple_boolify (*expr_p);
18550 : 247293 : new_type = TREE_TYPE (*expr_p);
18551 : 247293 : if (!useless_type_conversion_p (orig_type, new_type))
18552 : : {
18553 : 1050 : *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
18554 : 1050 : ret = GS_OK;
18555 : 1050 : break;
18556 : : }
18557 : :
18558 : : /* Boolified binary truth expressions are semantically equivalent
18559 : : to bitwise binary expressions. Canonicalize them to the
18560 : : bitwise variant. */
18561 : 246243 : switch (TREE_CODE (*expr_p))
18562 : : {
18563 : 157646 : case TRUTH_AND_EXPR:
18564 : 157646 : TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
18565 : 157646 : break;
18566 : 88013 : case TRUTH_OR_EXPR:
18567 : 88013 : TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
18568 : 88013 : break;
18569 : 584 : case TRUTH_XOR_EXPR:
18570 : 584 : TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
18571 : 584 : break;
18572 : : default:
18573 : : break;
18574 : : }
18575 : : /* Now make sure that operands have compatible type to
18576 : : expression's new_type. */
18577 : 246243 : xop0 = TREE_OPERAND (*expr_p, 0);
18578 : 246243 : xop1 = TREE_OPERAND (*expr_p, 1);
18579 : 246243 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
18580 : 326 : TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
18581 : : new_type,
18582 : : xop0);
18583 : 246243 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
18584 : 366 : TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
18585 : : new_type,
18586 : : xop1);
18587 : : /* Continue classified as tcc_binary. */
18588 : 246243 : goto expr_2;
18589 : : }
18590 : :
18591 : 9791 : case VEC_COND_EXPR:
18592 : 9791 : goto expr_3;
18593 : :
18594 : 132454 : case VEC_PERM_EXPR:
18595 : : /* Classified as tcc_expression. */
18596 : 132454 : goto expr_3;
18597 : :
18598 : 48 : case BIT_INSERT_EXPR:
18599 : : /* Argument 3 is a constant. */
18600 : 48 : goto expr_2;
18601 : :
18602 : 3657840 : case POINTER_PLUS_EXPR:
18603 : 3657840 : {
18604 : 3657840 : enum gimplify_status r0, r1;
18605 : 3657840 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
18606 : : post_p, is_gimple_val, fb_rvalue);
18607 : 3657840 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
18608 : : post_p, is_gimple_val, fb_rvalue);
18609 : 3657840 : recalculate_side_effects (*expr_p);
18610 : 3657840 : ret = MIN (r0, r1);
18611 : : break;
18612 : : }
18613 : :
18614 : 39224583 : default:
18615 : 39224583 : switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
18616 : : {
18617 : 6246368 : case tcc_comparison:
18618 : : /* Handle comparison of objects of non scalar mode aggregates
18619 : : with a call to memcmp. It would be nice to only have to do
18620 : : this for variable-sized objects, but then we'd have to allow
18621 : : the same nest of reference nodes we allow for MODIFY_EXPR and
18622 : : that's too complex.
18623 : :
18624 : : Compare scalar mode aggregates as scalar mode values. Using
18625 : : memcmp for them would be very inefficient at best, and is
18626 : : plain wrong if bitfields are involved. */
18627 : 6246368 : if (error_operand_p (TREE_OPERAND (*expr_p, 1)))
18628 : : ret = GS_ERROR;
18629 : : else
18630 : : {
18631 : 6246368 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
18632 : :
18633 : : /* Vector comparisons need no boolification. */
18634 : 6246368 : if (TREE_CODE (type) == VECTOR_TYPE)
18635 : 11445 : goto expr_2;
18636 : 6234923 : else if (!AGGREGATE_TYPE_P (type))
18637 : : {
18638 : 6234909 : tree org_type = TREE_TYPE (*expr_p);
18639 : 6234909 : *expr_p = gimple_boolify (*expr_p);
18640 : 6234909 : if (!useless_type_conversion_p (org_type,
18641 : 6234909 : TREE_TYPE (*expr_p)))
18642 : : {
18643 : 61019 : *expr_p = fold_convert_loc (input_location,
18644 : : org_type, *expr_p);
18645 : 61019 : ret = GS_OK;
18646 : : }
18647 : : else
18648 : 6173890 : goto expr_2;
18649 : : }
18650 : 14 : else if (TYPE_MODE (type) != BLKmode)
18651 : 14 : ret = gimplify_scalar_mode_aggregate_compare (expr_p);
18652 : : else
18653 : 0 : ret = gimplify_variable_sized_compare (expr_p);
18654 : : }
18655 : : break;
18656 : :
18657 : : /* If *EXPR_P does not need to be special-cased, handle it
18658 : : according to its class. */
18659 : 1447555 : case tcc_unary:
18660 : 1447555 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
18661 : : post_p, is_gimple_val, fb_rvalue);
18662 : 1447555 : break;
18663 : :
18664 : 23244362 : case tcc_binary:
18665 : 23244362 : expr_2:
18666 : 23244362 : {
18667 : 23244362 : enum gimplify_status r0, r1;
18668 : :
18669 : 23244362 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
18670 : : post_p, is_gimple_val, fb_rvalue);
18671 : 23244362 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
18672 : : post_p, is_gimple_val, fb_rvalue);
18673 : :
18674 : 23244362 : ret = MIN (r0, r1);
18675 : : break;
18676 : : }
18677 : :
18678 : 142245 : expr_3:
18679 : 142245 : {
18680 : 142245 : enum gimplify_status r0, r1, r2;
18681 : :
18682 : 142245 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
18683 : : post_p, is_gimple_val, fb_rvalue);
18684 : 142245 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
18685 : : post_p, is_gimple_val, fb_rvalue);
18686 : 142245 : r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
18687 : : post_p, is_gimple_val, fb_rvalue);
18688 : :
18689 : 142245 : ret = MIN (MIN (r0, r1), r2);
18690 : : break;
18691 : : }
18692 : :
18693 : 14717924 : case tcc_declaration:
18694 : 14717924 : case tcc_constant:
18695 : 14717924 : ret = GS_ALL_DONE;
18696 : 14717924 : goto dont_recalculate;
18697 : :
18698 : 0 : default:
18699 : 0 : gcc_unreachable ();
18700 : : }
18701 : :
18702 : 24895195 : recalculate_side_effects (*expr_p);
18703 : :
18704 : 431638080 : dont_recalculate:
18705 : : break;
18706 : : }
18707 : :
18708 : 431638080 : gcc_assert (*expr_p || ret != GS_OK);
18709 : : }
18710 : 436024642 : while (ret == GS_OK);
18711 : :
18712 : : /* If we encountered an error_mark somewhere nested inside, either
18713 : : stub out the statement or propagate the error back out. */
18714 : 420021691 : if (ret == GS_ERROR)
18715 : : {
18716 : 4275 : if (is_statement)
18717 : 3410 : *expr_p = NULL;
18718 : 4275 : goto out;
18719 : : }
18720 : :
18721 : : /* This was only valid as a return value from the langhook, which
18722 : : we handled. Make sure it doesn't escape from any other context. */
18723 : 420017416 : gcc_assert (ret != GS_UNHANDLED);
18724 : :
18725 : 420017416 : if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
18726 : : {
18727 : : /* We aren't looking for a value, and we don't have a valid
18728 : : statement. If it doesn't have side-effects, throw it away.
18729 : : We can also get here with code such as "*&&L;", where L is
18730 : : a LABEL_DECL that is marked as FORCED_LABEL. */
18731 : 954226 : if (TREE_CODE (*expr_p) == LABEL_DECL
18732 : 954226 : || !TREE_SIDE_EFFECTS (*expr_p))
18733 : 953220 : *expr_p = NULL;
18734 : 1006 : else if (!TREE_THIS_VOLATILE (*expr_p))
18735 : : {
18736 : : /* This is probably a _REF that contains something nested that
18737 : : has side effects. Recurse through the operands to find it. */
18738 : 0 : enum tree_code code = TREE_CODE (*expr_p);
18739 : :
18740 : 0 : switch (code)
18741 : : {
18742 : 0 : case COMPONENT_REF:
18743 : 0 : case REALPART_EXPR:
18744 : 0 : case IMAGPART_EXPR:
18745 : 0 : case VIEW_CONVERT_EXPR:
18746 : 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
18747 : : gimple_test_f, fallback);
18748 : 0 : break;
18749 : :
18750 : 0 : case ARRAY_REF:
18751 : 0 : case ARRAY_RANGE_REF:
18752 : 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
18753 : : gimple_test_f, fallback);
18754 : 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
18755 : : gimple_test_f, fallback);
18756 : 0 : break;
18757 : :
18758 : 0 : default:
18759 : : /* Anything else with side-effects must be converted to
18760 : : a valid statement before we get here. */
18761 : 0 : gcc_unreachable ();
18762 : : }
18763 : :
18764 : 0 : *expr_p = NULL;
18765 : : }
18766 : 1006 : else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
18767 : 951 : && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode
18768 : 1941 : && !is_empty_type (TREE_TYPE (*expr_p)))
18769 : : {
18770 : : /* Historically, the compiler has treated a bare reference
18771 : : to a non-BLKmode volatile lvalue as forcing a load. */
18772 : 866 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
18773 : :
18774 : : /* Normally, we do not want to create a temporary for a
18775 : : TREE_ADDRESSABLE type because such a type should not be
18776 : : copied by bitwise-assignment. However, we make an
18777 : : exception here, as all we are doing here is ensuring that
18778 : : we read the bytes that make up the type. We use
18779 : : create_tmp_var_raw because create_tmp_var will abort when
18780 : : given a TREE_ADDRESSABLE type. */
18781 : 866 : tree tmp = create_tmp_var_raw (type, "vol");
18782 : 866 : gimple_add_tmp_var (tmp);
18783 : 866 : gimplify_assign (tmp, *expr_p, pre_p);
18784 : 866 : *expr_p = NULL;
18785 : : }
18786 : : else
18787 : : /* We can't do anything useful with a volatile reference to
18788 : : an incomplete type, so just throw it away. Likewise for
18789 : : a BLKmode type, since any implicit inner load should
18790 : : already have been turned into an explicit one by the
18791 : : gimplification process. */
18792 : 140 : *expr_p = NULL;
18793 : : }
18794 : :
18795 : : /* If we are gimplifying at the statement level, we're done. Tack
18796 : : everything together and return. */
18797 : 420017416 : if (fallback == fb_none || is_statement)
18798 : : {
18799 : : /* Since *EXPR_P has been converted into a GIMPLE tuple, clear
18800 : : it out for GC to reclaim it. */
18801 : 92487463 : *expr_p = NULL_TREE;
18802 : :
18803 : 92487463 : if (!gimple_seq_empty_p (internal_pre)
18804 : 92487463 : || !gimple_seq_empty_p (internal_post))
18805 : : {
18806 : 19 : gimplify_seq_add_seq (&internal_pre, internal_post);
18807 : 19 : gimplify_seq_add_seq (pre_p, internal_pre);
18808 : : }
18809 : :
18810 : : /* The result of gimplifying *EXPR_P is going to be the last few
18811 : : statements in *PRE_P and *POST_P. Add location information
18812 : : to all the statements that were added by the gimplification
18813 : : helpers. */
18814 : 92487463 : if (!gimple_seq_empty_p (*pre_p))
18815 : 90170291 : annotate_all_with_location_after (*pre_p, pre_last_gsi, input_location);
18816 : :
18817 : 92487463 : if (!gimple_seq_empty_p (*post_p))
18818 : 19 : annotate_all_with_location_after (*post_p, post_last_gsi,
18819 : : input_location);
18820 : :
18821 : 92487463 : goto out;
18822 : : }
18823 : :
18824 : : #ifdef ENABLE_GIMPLE_CHECKING
18825 : 327529953 : if (*expr_p)
18826 : : {
18827 : 327529953 : enum tree_code code = TREE_CODE (*expr_p);
18828 : : /* These expressions should already be in gimple IR form. */
18829 : 327529953 : gcc_assert (code != MODIFY_EXPR
18830 : : && code != ASM_EXPR
18831 : : && code != BIND_EXPR
18832 : : && code != CATCH_EXPR
18833 : : && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
18834 : : && code != EH_FILTER_EXPR
18835 : : && code != GOTO_EXPR
18836 : : && code != LABEL_EXPR
18837 : : && code != LOOP_EXPR
18838 : : && code != SWITCH_EXPR
18839 : : && code != TRY_FINALLY_EXPR
18840 : : && code != EH_ELSE_EXPR
18841 : : && code != OACC_PARALLEL
18842 : : && code != OACC_KERNELS
18843 : : && code != OACC_SERIAL
18844 : : && code != OACC_DATA
18845 : : && code != OACC_HOST_DATA
18846 : : && code != OACC_DECLARE
18847 : : && code != OACC_UPDATE
18848 : : && code != OACC_ENTER_DATA
18849 : : && code != OACC_EXIT_DATA
18850 : : && code != OACC_CACHE
18851 : : && code != OMP_CRITICAL
18852 : : && code != OMP_FOR
18853 : : && code != OACC_LOOP
18854 : : && code != OMP_MASTER
18855 : : && code != OMP_MASKED
18856 : : && code != OMP_TASKGROUP
18857 : : && code != OMP_ORDERED
18858 : : && code != OMP_PARALLEL
18859 : : && code != OMP_SCAN
18860 : : && code != OMP_SECTIONS
18861 : : && code != OMP_SECTION
18862 : : && code != OMP_STRUCTURED_BLOCK
18863 : : && code != OMP_SINGLE
18864 : : && code != OMP_SCOPE);
18865 : : }
18866 : : #endif
18867 : :
18868 : : /* Otherwise we're gimplifying a subexpression, so the resulting
18869 : : value is interesting. If it's a valid operand that matches
18870 : : GIMPLE_TEST_F, we're done. Unless we are handling some
18871 : : post-effects internally; if that's the case, we need to copy into
18872 : : a temporary before adding the post-effects to POST_P. */
18873 : 327529953 : if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
18874 : 303794570 : goto out;
18875 : :
18876 : : /* Otherwise, we need to create a new temporary for the gimplified
18877 : : expression. */
18878 : :
18879 : : /* We can't return an lvalue if we have an internal postqueue. The
18880 : : object the lvalue refers to would (probably) be modified by the
18881 : : postqueue; we need to copy the value out first, which means an
18882 : : rvalue. */
18883 : 23735383 : if ((fallback & fb_lvalue)
18884 : 513907 : && gimple_seq_empty_p (internal_post)
18885 : 24249290 : && is_gimple_addressable (*expr_p))
18886 : : {
18887 : : /* An lvalue will do. Take the address of the expression, store it
18888 : : in a temporary, and replace the expression with an INDIRECT_REF of
18889 : : that temporary. */
18890 : 15 : tree ref_alias_type = reference_alias_ptr_type (*expr_p);
18891 : 15 : unsigned int ref_align = get_object_alignment (*expr_p);
18892 : 15 : tree ref_type = TREE_TYPE (*expr_p);
18893 : 15 : tmp = build_fold_addr_expr_loc (input_location, *expr_p);
18894 : 15 : gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
18895 : 15 : if (TYPE_ALIGN (ref_type) != ref_align)
18896 : 1 : ref_type = build_aligned_type (ref_type, ref_align);
18897 : 15 : *expr_p = build2 (MEM_REF, ref_type,
18898 : : tmp, build_zero_cst (ref_alias_type));
18899 : : }
18900 : 23735368 : else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
18901 : : {
18902 : : /* An rvalue will do. Assign the gimplified expression into a
18903 : : new temporary TMP and replace the original expression with
18904 : : TMP. First, make sure that the expression has a type so that
18905 : : it can be assigned into a temporary. */
18906 : 23735359 : gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
18907 : 23735359 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
18908 : : }
18909 : : else
18910 : : {
18911 : : #ifdef ENABLE_GIMPLE_CHECKING
18912 : 9 : if (!(fallback & fb_mayfail))
18913 : : {
18914 : 0 : fprintf (stderr, "gimplification failed:\n");
18915 : 0 : print_generic_expr (stderr, *expr_p);
18916 : 0 : debug_tree (*expr_p);
18917 : 0 : internal_error ("gimplification failed");
18918 : : }
18919 : : #endif
18920 : 9 : gcc_assert (fallback & fb_mayfail);
18921 : :
18922 : : /* If this is an asm statement, and the user asked for the
18923 : : impossible, don't die. Fail and let gimplify_asm_expr
18924 : : issue an error. */
18925 : 9 : ret = GS_ERROR;
18926 : 9 : goto out;
18927 : : }
18928 : :
18929 : : /* Make sure the temporary matches our predicate. */
18930 : 23735374 : gcc_assert ((*gimple_test_f) (*expr_p));
18931 : :
18932 : 23735374 : if (!gimple_seq_empty_p (internal_post))
18933 : : {
18934 : 0 : annotate_all_with_location (internal_post, input_location);
18935 : 0 : gimplify_seq_add_seq (pre_p, internal_post);
18936 : : }
18937 : :
18938 : 23735374 : out:
18939 : 420021691 : input_location = saved_location;
18940 : 420021691 : return ret;
18941 : : }
18942 : :
18943 : : /* Like gimplify_expr but make sure the gimplified result is not itself
18944 : : a SSA name (but a decl if it were). Temporaries required by
18945 : : evaluating *EXPR_P may be still SSA names. */
18946 : :
18947 : : static enum gimplify_status
18948 : 29471332 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
18949 : : bool (*gimple_test_f) (tree), fallback_t fallback,
18950 : : bool allow_ssa)
18951 : : {
18952 : 29471332 : enum gimplify_status ret = gimplify_expr (expr_p, pre_p, post_p,
18953 : : gimple_test_f, fallback);
18954 : 29471332 : if (! allow_ssa
18955 : 264434 : && TREE_CODE (*expr_p) == SSA_NAME)
18956 : 67710 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false);
18957 : 29471332 : return ret;
18958 : : }
18959 : :
18960 : : /* Look through TYPE for variable-sized objects and gimplify each such
18961 : : size that we find. Add to LIST_P any statements generated. */
18962 : :
18963 : : void
18964 : 7351552 : gimplify_type_sizes (tree type, gimple_seq *list_p)
18965 : : {
18966 : 7351552 : if (type == NULL || type == error_mark_node)
18967 : : return;
18968 : :
18969 : 7351297 : const bool ignored_p
18970 : 7351297 : = TYPE_NAME (type)
18971 : 3722636 : && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
18972 : 10878326 : && DECL_IGNORED_P (TYPE_NAME (type));
18973 : 7351297 : tree t;
18974 : :
18975 : : /* We first do the main variant, then copy into any other variants. */
18976 : 7351297 : type = TYPE_MAIN_VARIANT (type);
18977 : :
18978 : : /* Avoid infinite recursion. */
18979 : 7351297 : if (TYPE_SIZES_GIMPLIFIED (type))
18980 : : return;
18981 : :
18982 : 2178833 : TYPE_SIZES_GIMPLIFIED (type) = 1;
18983 : :
18984 : 2178833 : switch (TREE_CODE (type))
18985 : : {
18986 : 455666 : case INTEGER_TYPE:
18987 : 455666 : case ENUMERAL_TYPE:
18988 : 455666 : case BOOLEAN_TYPE:
18989 : 455666 : case REAL_TYPE:
18990 : 455666 : case FIXED_POINT_TYPE:
18991 : 455666 : gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
18992 : 455666 : gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
18993 : :
18994 : 7638840 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
18995 : : {
18996 : 7183174 : TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
18997 : 7183174 : TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
18998 : : }
18999 : : break;
19000 : :
19001 : 164605 : case ARRAY_TYPE:
19002 : : /* These types may not have declarations, so handle them here. */
19003 : 164605 : gimplify_type_sizes (TREE_TYPE (type), list_p);
19004 : 164605 : gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
19005 : : /* Ensure VLA bounds aren't removed, for -O0 they should be variables
19006 : : with assigned stack slots, for -O1+ -g they should be tracked
19007 : : by VTA. */
19008 : 164605 : if (!ignored_p
19009 : 164605 : && TYPE_DOMAIN (type)
19010 : 328975 : && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
19011 : : {
19012 : 164370 : t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
19013 : 164370 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
19014 : 0 : DECL_IGNORED_P (t) = 0;
19015 : 164370 : t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
19016 : 164370 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
19017 : 18195 : DECL_IGNORED_P (t) = 0;
19018 : : }
19019 : : break;
19020 : :
19021 : 439134 : case RECORD_TYPE:
19022 : 439134 : case UNION_TYPE:
19023 : 439134 : case QUAL_UNION_TYPE:
19024 : 9085986 : for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
19025 : 8646852 : if (TREE_CODE (field) == FIELD_DECL)
19026 : : {
19027 : 994138 : gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
19028 : : /* Likewise, ensure variable offsets aren't removed. */
19029 : 994138 : if (!ignored_p
19030 : 994138 : && (t = DECL_FIELD_OFFSET (field))
19031 : 994125 : && VAR_P (t)
19032 : 994297 : && DECL_ARTIFICIAL (t))
19033 : 159 : DECL_IGNORED_P (t) = 0;
19034 : 994138 : gimplify_one_sizepos (&DECL_SIZE (field), list_p);
19035 : 994138 : gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
19036 : 994138 : gimplify_type_sizes (TREE_TYPE (field), list_p);
19037 : : }
19038 : : break;
19039 : :
19040 : : case POINTER_TYPE:
19041 : : case REFERENCE_TYPE:
19042 : : /* We used to recurse on the pointed-to type here, which turned out to
19043 : : be incorrect because its definition might refer to variables not
19044 : : yet initialized at this point if a forward declaration is involved.
19045 : :
19046 : : It was actually useful for anonymous pointed-to types to ensure
19047 : : that the sizes evaluation dominates every possible later use of the
19048 : : values. Restricting to such types here would be safe since there
19049 : : is no possible forward declaration around, but would introduce an
19050 : : undesirable middle-end semantic to anonymity. We then defer to
19051 : : front-ends the responsibility of ensuring that the sizes are
19052 : : evaluated both early and late enough, e.g. by attaching artificial
19053 : : type declarations to the tree. */
19054 : : break;
19055 : :
19056 : : default:
19057 : : break;
19058 : : }
19059 : :
19060 : 2178833 : gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
19061 : 2178833 : gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
19062 : :
19063 : 12765718 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
19064 : : {
19065 : 10586885 : TYPE_SIZE (t) = TYPE_SIZE (type);
19066 : 10586885 : TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
19067 : 10586885 : TYPE_SIZES_GIMPLIFIED (t) = 1;
19068 : : }
19069 : : }
19070 : :
19071 : : /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
19072 : : a size or position, has had all of its SAVE_EXPRs evaluated.
19073 : : We add any required statements to *STMT_P. */
19074 : :
19075 : : void
19076 : 8269374 : gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
19077 : : {
19078 : 8269374 : tree expr = *expr_p;
19079 : :
19080 : : /* We don't do anything if the value isn't there, is constant, or contains
19081 : : A PLACEHOLDER_EXPR. We also don't want to do anything if it's already
19082 : : a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
19083 : : will want to replace it with a new variable, but that will cause problems
19084 : : if this type is from outside the function. It's OK to have that here. */
19085 : 8269374 : if (expr == NULL_TREE
19086 : 8272609 : || is_gimple_constant (expr)
19087 : 77994 : || VAR_P (expr)
19088 : 8344133 : || CONTAINS_PLACEHOLDER_P (expr))
19089 : 8194615 : return;
19090 : :
19091 : 74759 : *expr_p = unshare_expr (expr);
19092 : :
19093 : : /* SSA names in decl/type fields are a bad idea - they'll get reclaimed
19094 : : if the def vanishes. */
19095 : 74759 : gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false);
19096 : :
19097 : : /* If expr wasn't already is_gimple_sizepos or is_gimple_constant from the
19098 : : FE, ensure that it is a VAR_DECL, otherwise we might handle some decls
19099 : : as gimplify_vla_decl even when they would have all sizes INTEGER_CSTs. */
19100 : 74759 : if (is_gimple_constant (*expr_p))
19101 : 490 : *expr_p = get_initialized_tmp_var (*expr_p, stmt_p, NULL, false);
19102 : : }
19103 : :
19104 : : /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
19105 : : containing the sequence of corresponding GIMPLE statements. If DO_PARMS
19106 : : is true, also gimplify the parameters. */
19107 : :
19108 : : gbind *
19109 : 2599998 : gimplify_body (tree fndecl, bool do_parms)
19110 : : {
19111 : 2599998 : location_t saved_location = input_location;
19112 : 2599998 : gimple_seq parm_stmts, parm_cleanup = NULL, seq;
19113 : 2599998 : gimple *outer_stmt;
19114 : 2599998 : gbind *outer_bind;
19115 : :
19116 : 2599998 : timevar_push (TV_TREE_GIMPLIFY);
19117 : :
19118 : 2599998 : init_tree_ssa (cfun);
19119 : :
19120 : : /* Initialize for optimize_insn_for_s{ize,peed}_p possibly called during
19121 : : gimplification. */
19122 : 2599998 : default_rtl_profile ();
19123 : :
19124 : 2599998 : gcc_assert (gimplify_ctxp == NULL);
19125 : 2599998 : push_gimplify_context (true);
19126 : :
19127 : 2599998 : if (flag_openacc || flag_openmp)
19128 : : {
19129 : 40612 : gcc_assert (gimplify_omp_ctxp == NULL);
19130 : 40612 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)))
19131 : 3442 : gimplify_omp_ctxp = new_omp_context (ORT_IMPLICIT_TARGET);
19132 : : }
19133 : :
19134 : : /* Unshare most shared trees in the body and in that of any nested functions.
19135 : : It would seem we don't have to do this for nested functions because
19136 : : they are supposed to be output and then the outer function gimplified
19137 : : first, but the g++ front end doesn't always do it that way. */
19138 : 2599998 : unshare_body (fndecl);
19139 : 2599998 : unvisit_body (fndecl);
19140 : :
19141 : : /* Make sure input_location isn't set to something weird. */
19142 : 2599998 : input_location = DECL_SOURCE_LOCATION (fndecl);
19143 : :
19144 : : /* Resolve callee-copies. This has to be done before processing
19145 : : the body so that DECL_VALUE_EXPR gets processed correctly. */
19146 : 2599998 : parm_stmts = do_parms ? gimplify_parameters (&parm_cleanup) : NULL;
19147 : :
19148 : : /* Gimplify the function's body. */
19149 : 2599998 : seq = NULL;
19150 : 2599998 : gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
19151 : 2599998 : outer_stmt = gimple_seq_first_nondebug_stmt (seq);
19152 : 2599998 : if (!outer_stmt)
19153 : : {
19154 : 26782 : outer_stmt = gimple_build_nop ();
19155 : 26782 : gimplify_seq_add_stmt (&seq, outer_stmt);
19156 : : }
19157 : :
19158 : : /* The body must contain exactly one statement, a GIMPLE_BIND. If this is
19159 : : not the case, wrap everything in a GIMPLE_BIND to make it so. */
19160 : 2599998 : if (gimple_code (outer_stmt) == GIMPLE_BIND
19161 : 2599998 : && (gimple_seq_first_nondebug_stmt (seq)
19162 : 1426389 : == gimple_seq_last_nondebug_stmt (seq)))
19163 : : {
19164 : 1363822 : outer_bind = as_a <gbind *> (outer_stmt);
19165 : 1363822 : if (gimple_seq_first_stmt (seq) != outer_stmt
19166 : 1363822 : || gimple_seq_last_stmt (seq) != outer_stmt)
19167 : : {
19168 : : /* If there are debug stmts before or after outer_stmt, move them
19169 : : inside of outer_bind body. */
19170 : 1 : gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq);
19171 : 1 : gimple_seq second_seq = NULL;
19172 : 1 : if (gimple_seq_first_stmt (seq) != outer_stmt
19173 : 2 : && gimple_seq_last_stmt (seq) != outer_stmt)
19174 : : {
19175 : 0 : second_seq = gsi_split_seq_after (gsi);
19176 : 0 : gsi_remove (&gsi, false);
19177 : : }
19178 : 1 : else if (gimple_seq_first_stmt (seq) != outer_stmt)
19179 : 1 : gsi_remove (&gsi, false);
19180 : : else
19181 : : {
19182 : 0 : gsi_remove (&gsi, false);
19183 : 0 : second_seq = seq;
19184 : 0 : seq = NULL;
19185 : : }
19186 : 1 : gimple_seq_add_seq_without_update (&seq,
19187 : : gimple_bind_body (outer_bind));
19188 : 1 : gimple_seq_add_seq_without_update (&seq, second_seq);
19189 : 1 : gimple_bind_set_body (outer_bind, seq);
19190 : : }
19191 : : }
19192 : : else
19193 : 1236176 : outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
19194 : :
19195 : 2599998 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
19196 : :
19197 : : /* If we had callee-copies statements, insert them at the beginning
19198 : : of the function and clear DECL_VALUE_EXPR_P on the parameters. */
19199 : 2599998 : if (!gimple_seq_empty_p (parm_stmts))
19200 : : {
19201 : 41 : tree parm;
19202 : :
19203 : 41 : gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
19204 : 41 : if (parm_cleanup)
19205 : : {
19206 : 0 : gtry *g = gimple_build_try (parm_stmts, parm_cleanup,
19207 : : GIMPLE_TRY_FINALLY);
19208 : 0 : parm_stmts = NULL;
19209 : 0 : gimple_seq_add_stmt (&parm_stmts, g);
19210 : : }
19211 : 41 : gimple_bind_set_body (outer_bind, parm_stmts);
19212 : :
19213 : 41 : for (parm = DECL_ARGUMENTS (current_function_decl);
19214 : 101 : parm; parm = DECL_CHAIN (parm))
19215 : 60 : if (DECL_HAS_VALUE_EXPR_P (parm))
19216 : : {
19217 : 0 : DECL_HAS_VALUE_EXPR_P (parm) = 0;
19218 : 0 : DECL_IGNORED_P (parm) = 0;
19219 : : }
19220 : : }
19221 : :
19222 : 2599998 : if ((flag_openacc || flag_openmp || flag_openmp_simd)
19223 : 42952 : && gimplify_omp_ctxp)
19224 : : {
19225 : 3442 : delete_omp_context (gimplify_omp_ctxp);
19226 : 3442 : gimplify_omp_ctxp = NULL;
19227 : : }
19228 : :
19229 : 2599998 : pop_gimplify_context (outer_bind);
19230 : 2599998 : gcc_assert (gimplify_ctxp == NULL);
19231 : :
19232 : 2599998 : if (flag_checking && !seen_error ())
19233 : 2552739 : verify_gimple_in_seq (gimple_bind_body (outer_bind));
19234 : :
19235 : 2599998 : timevar_pop (TV_TREE_GIMPLIFY);
19236 : 2599998 : input_location = saved_location;
19237 : :
19238 : 2599998 : return outer_bind;
19239 : : }
19240 : :
19241 : : typedef char *char_p; /* For DEF_VEC_P. */
19242 : :
19243 : : /* Return whether we should exclude FNDECL from instrumentation. */
19244 : :
19245 : : static bool
19246 : 31 : flag_instrument_functions_exclude_p (tree fndecl)
19247 : : {
19248 : 31 : vec<char_p> *v;
19249 : :
19250 : 31 : v = (vec<char_p> *) flag_instrument_functions_exclude_functions;
19251 : 32 : if (v && v->length () > 0)
19252 : : {
19253 : 1 : const char *name;
19254 : 1 : int i;
19255 : 1 : char *s;
19256 : :
19257 : 1 : name = lang_hooks.decl_printable_name (fndecl, 1);
19258 : 2 : FOR_EACH_VEC_ELT (*v, i, s)
19259 : 1 : if (strstr (name, s) != NULL)
19260 : 2 : return true;
19261 : : }
19262 : :
19263 : 30 : v = (vec<char_p> *) flag_instrument_functions_exclude_files;
19264 : 31 : if (v && v->length () > 0)
19265 : : {
19266 : 1 : const char *name;
19267 : 1 : int i;
19268 : 1 : char *s;
19269 : :
19270 : 1 : name = DECL_SOURCE_FILE (fndecl);
19271 : 1 : FOR_EACH_VEC_ELT (*v, i, s)
19272 : 1 : if (strstr (name, s) != NULL)
19273 : 2 : return true;
19274 : : }
19275 : :
19276 : : return false;
19277 : : }
19278 : :
19279 : : /* Build a call to the instrumentation function FNCODE and add it to SEQ.
19280 : : If COND_VAR is not NULL, it is a boolean variable guarding the call to
19281 : : the instrumentation function. IF STMT is not NULL, it is a statement
19282 : : to be executed just before the call to the instrumentation function. */
19283 : :
19284 : : static void
19285 : 58 : build_instrumentation_call (gimple_seq *seq, enum built_in_function fncode,
19286 : : tree cond_var, gimple *stmt)
19287 : : {
19288 : : /* The instrumentation hooks aren't going to call the instrumented
19289 : : function and the address they receive is expected to be matchable
19290 : : against symbol addresses. Make sure we don't create a trampoline,
19291 : : in case the current function is nested. */
19292 : 58 : tree this_fn_addr = build_fold_addr_expr (current_function_decl);
19293 : 58 : TREE_NO_TRAMPOLINE (this_fn_addr) = 1;
19294 : :
19295 : 58 : tree label_true, label_false;
19296 : 58 : if (cond_var)
19297 : : {
19298 : 8 : label_true = create_artificial_label (UNKNOWN_LOCATION);
19299 : 8 : label_false = create_artificial_label (UNKNOWN_LOCATION);
19300 : 8 : gcond *cond = gimple_build_cond (EQ_EXPR, cond_var, boolean_false_node,
19301 : : label_true, label_false);
19302 : 8 : gimplify_seq_add_stmt (seq, cond);
19303 : 8 : gimplify_seq_add_stmt (seq, gimple_build_label (label_true));
19304 : 8 : gimplify_seq_add_stmt (seq, gimple_build_predict (PRED_COLD_LABEL,
19305 : : NOT_TAKEN));
19306 : : }
19307 : :
19308 : 58 : if (stmt)
19309 : 4 : gimplify_seq_add_stmt (seq, stmt);
19310 : :
19311 : 58 : tree x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
19312 : 58 : gcall *call = gimple_build_call (x, 1, integer_zero_node);
19313 : 58 : tree tmp_var = create_tmp_var (ptr_type_node, "return_addr");
19314 : 58 : gimple_call_set_lhs (call, tmp_var);
19315 : 58 : gimplify_seq_add_stmt (seq, call);
19316 : 58 : x = builtin_decl_implicit (fncode);
19317 : 58 : call = gimple_build_call (x, 2, this_fn_addr, tmp_var);
19318 : 58 : gimplify_seq_add_stmt (seq, call);
19319 : :
19320 : 58 : if (cond_var)
19321 : 8 : gimplify_seq_add_stmt (seq, gimple_build_label (label_false));
19322 : 58 : }
19323 : :
19324 : : /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
19325 : : node for the function we want to gimplify.
19326 : :
19327 : : Return the sequence of GIMPLE statements corresponding to the body
19328 : : of FNDECL. */
19329 : :
19330 : : void
19331 : 2599449 : gimplify_function_tree (tree fndecl)
19332 : : {
19333 : 2599449 : gimple_seq seq;
19334 : 2599449 : gbind *bind;
19335 : :
19336 : 2599449 : gcc_assert (!gimple_body (fndecl));
19337 : :
19338 : 2599449 : if (DECL_STRUCT_FUNCTION (fndecl))
19339 : 2596060 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
19340 : : else
19341 : 3389 : push_struct_function (fndecl);
19342 : :
19343 : 2599449 : reset_cond_uid ();
19344 : :
19345 : : /* Tentatively set PROP_gimple_lva here, and reset it in gimplify_va_arg_expr
19346 : : if necessary. */
19347 : 2599449 : cfun->curr_properties |= PROP_gimple_lva;
19348 : :
19349 : 2599449 : if (asan_sanitize_use_after_scope ())
19350 : 7802 : asan_poisoned_variables = new hash_set<tree> ();
19351 : 2599449 : bind = gimplify_body (fndecl, true);
19352 : 2599449 : if (asan_poisoned_variables)
19353 : : {
19354 : 7802 : delete asan_poisoned_variables;
19355 : 7802 : asan_poisoned_variables = NULL;
19356 : : }
19357 : :
19358 : : /* The tree body of the function is no longer needed, replace it
19359 : : with the new GIMPLE body. */
19360 : 2599449 : seq = NULL;
19361 : 2599449 : gimple_seq_add_stmt (&seq, bind);
19362 : 2599449 : gimple_set_body (fndecl, seq);
19363 : :
19364 : : /* If we're instrumenting function entry/exit, then prepend the call to
19365 : : the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
19366 : : catch the exit hook. */
19367 : : /* ??? Add some way to ignore exceptions for this TFE. */
19368 : 2599449 : if (flag_instrument_function_entry_exit
19369 : 84 : && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
19370 : : /* Do not instrument extern inline functions. */
19371 : 32 : && !(DECL_DECLARED_INLINE_P (fndecl)
19372 : 5 : && DECL_EXTERNAL (fndecl)
19373 : 1 : && DECL_DISREGARD_INLINE_LIMITS (fndecl))
19374 : 2599480 : && !flag_instrument_functions_exclude_p (fndecl))
19375 : : {
19376 : 29 : gimple_seq body = NULL, cleanup = NULL;
19377 : 29 : gassign *assign;
19378 : 29 : tree cond_var;
19379 : :
19380 : : /* If -finstrument-functions-once is specified, generate:
19381 : :
19382 : : static volatile bool C.0 = false;
19383 : : bool tmp_called;
19384 : :
19385 : : tmp_called = C.0;
19386 : : if (!tmp_called)
19387 : : {
19388 : : C.0 = true;
19389 : : [call profiling enter function]
19390 : : }
19391 : :
19392 : : without specific protection for data races. */
19393 : 29 : if (flag_instrument_function_entry_exit > 1)
19394 : : {
19395 : 4 : tree first_var
19396 : 4 : = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
19397 : : VAR_DECL,
19398 : : create_tmp_var_name ("C"),
19399 : : boolean_type_node);
19400 : 4 : DECL_ARTIFICIAL (first_var) = 1;
19401 : 4 : DECL_IGNORED_P (first_var) = 1;
19402 : 4 : TREE_STATIC (first_var) = 1;
19403 : 4 : TREE_THIS_VOLATILE (first_var) = 1;
19404 : 4 : TREE_USED (first_var) = 1;
19405 : 4 : DECL_INITIAL (first_var) = boolean_false_node;
19406 : 4 : varpool_node::add (first_var);
19407 : :
19408 : 4 : cond_var = create_tmp_var (boolean_type_node, "tmp_called");
19409 : 4 : assign = gimple_build_assign (cond_var, first_var);
19410 : 4 : gimplify_seq_add_stmt (&body, assign);
19411 : :
19412 : 4 : assign = gimple_build_assign (first_var, boolean_true_node);
19413 : : }
19414 : :
19415 : : else
19416 : : {
19417 : : cond_var = NULL_TREE;
19418 : : assign = NULL;
19419 : : }
19420 : :
19421 : 29 : build_instrumentation_call (&body, BUILT_IN_PROFILE_FUNC_ENTER,
19422 : : cond_var, assign);
19423 : :
19424 : : /* If -finstrument-functions-once is specified, generate:
19425 : :
19426 : : if (!tmp_called)
19427 : : [call profiling exit function]
19428 : :
19429 : : without specific protection for data races. */
19430 : 29 : build_instrumentation_call (&cleanup, BUILT_IN_PROFILE_FUNC_EXIT,
19431 : : cond_var, NULL);
19432 : :
19433 : 29 : gimple *tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
19434 : 29 : gimplify_seq_add_stmt (&body, tf);
19435 : 29 : gbind *new_bind = gimple_build_bind (NULL, body, NULL);
19436 : :
19437 : : /* Replace the current function body with the body
19438 : : wrapped in the try/finally TF. */
19439 : 29 : seq = NULL;
19440 : 29 : gimple_seq_add_stmt (&seq, new_bind);
19441 : 29 : gimple_set_body (fndecl, seq);
19442 : 29 : bind = new_bind;
19443 : : }
19444 : :
19445 : 2599449 : if (sanitize_flags_p (SANITIZE_THREAD)
19446 : 2599449 : && param_tsan_instrument_func_entry_exit)
19447 : : {
19448 : 1145 : gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
19449 : 1145 : gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
19450 : 1145 : gbind *new_bind = gimple_build_bind (NULL, tf, NULL);
19451 : : /* Replace the current function body with the body
19452 : : wrapped in the try/finally TF. */
19453 : 1145 : seq = NULL;
19454 : 1145 : gimple_seq_add_stmt (&seq, new_bind);
19455 : 1145 : gimple_set_body (fndecl, seq);
19456 : : }
19457 : :
19458 : 2599449 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
19459 : 2599449 : cfun->curr_properties |= PROP_gimple_any;
19460 : :
19461 : 2599449 : pop_cfun ();
19462 : :
19463 : 2599449 : dump_function (TDI_gimple, fndecl);
19464 : 2599449 : }
19465 : :
19466 : : /* Return a dummy expression of type TYPE in order to keep going after an
19467 : : error. */
19468 : :
19469 : : static tree
19470 : 34 : dummy_object (tree type)
19471 : : {
19472 : 34 : tree t = build_int_cst (build_pointer_type (type), 0);
19473 : 34 : return build2 (MEM_REF, type, t, t);
19474 : : }
19475 : :
19476 : : /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
19477 : : builtin function, but a very special sort of operator. */
19478 : :
19479 : : enum gimplify_status
19480 : 50879 : gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
19481 : : gimple_seq *post_p ATTRIBUTE_UNUSED)
19482 : : {
19483 : 50879 : tree promoted_type, have_va_type;
19484 : 50879 : tree valist = TREE_OPERAND (*expr_p, 0);
19485 : 50879 : tree type = TREE_TYPE (*expr_p);
19486 : 50879 : tree t, tag, aptag;
19487 : 50879 : location_t loc = EXPR_LOCATION (*expr_p);
19488 : :
19489 : : /* Verify that valist is of the proper type. */
19490 : 50879 : have_va_type = TREE_TYPE (valist);
19491 : 50879 : if (have_va_type == error_mark_node)
19492 : : return GS_ERROR;
19493 : 50857 : have_va_type = targetm.canonical_va_list_type (have_va_type);
19494 : 50857 : if (have_va_type == NULL_TREE
19495 : 50857 : && POINTER_TYPE_P (TREE_TYPE (valist)))
19496 : : /* Handle 'Case 1: Not an array type' from c-common.cc/build_va_arg. */
19497 : 258 : have_va_type
19498 : 258 : = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
19499 : 50857 : gcc_assert (have_va_type != NULL_TREE);
19500 : :
19501 : : /* Generate a diagnostic for requesting data of a type that cannot
19502 : : be passed through `...' due to type promotion at the call site. */
19503 : 50857 : if ((promoted_type = lang_hooks.types.type_promotes_to (type))
19504 : : != type)
19505 : : {
19506 : 34 : static bool gave_help;
19507 : 34 : bool warned;
19508 : : /* Use the expansion point to handle cases such as passing bool (defined
19509 : : in a system header) through `...'. */
19510 : 34 : location_t xloc
19511 : 34 : = expansion_point_location_if_in_system_header (loc);
19512 : :
19513 : : /* Unfortunately, this is merely undefined, rather than a constraint
19514 : : violation, so we cannot make this an error. If this call is never
19515 : : executed, the program is still strictly conforming. */
19516 : 34 : auto_diagnostic_group d;
19517 : 34 : warned = warning_at (xloc, 0,
19518 : : "%qT is promoted to %qT when passed through %<...%>",
19519 : : type, promoted_type);
19520 : 34 : if (!gave_help && warned)
19521 : : {
19522 : 17 : gave_help = true;
19523 : 17 : inform (xloc, "(so you should pass %qT not %qT to %<va_arg%>)",
19524 : : promoted_type, type);
19525 : : }
19526 : :
19527 : : /* We can, however, treat "undefined" any way we please.
19528 : : Call abort to encourage the user to fix the program. */
19529 : 27 : if (warned)
19530 : 27 : inform (xloc, "if this code is reached, the program will abort");
19531 : : /* Before the abort, allow the evaluation of the va_list
19532 : : expression to exit or longjmp. */
19533 : 34 : gimplify_and_add (valist, pre_p);
19534 : 68 : t = build_call_expr_loc (loc,
19535 : : builtin_decl_implicit (BUILT_IN_TRAP), 0);
19536 : 34 : gimplify_and_add (t, pre_p);
19537 : :
19538 : : /* This is dead code, but go ahead and finish so that the
19539 : : mode of the result comes out right. */
19540 : 34 : *expr_p = dummy_object (type);
19541 : 34 : return GS_ALL_DONE;
19542 : 34 : }
19543 : :
19544 : 50823 : tag = build_int_cst (build_pointer_type (type), 0);
19545 : 50823 : aptag = build_int_cst (TREE_TYPE (valist), 0);
19546 : :
19547 : 50823 : *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3,
19548 : : valist, tag, aptag);
19549 : :
19550 : : /* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
19551 : : needs to be expanded. */
19552 : 50823 : cfun->curr_properties &= ~PROP_gimple_lva;
19553 : :
19554 : 50823 : return GS_OK;
19555 : : }
19556 : :
19557 : : /* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P.
19558 : :
19559 : : DST/SRC are the destination and source respectively. You can pass
19560 : : ungimplified trees in DST or SRC, in which case they will be
19561 : : converted to a gimple operand if necessary.
19562 : :
19563 : : This function returns the newly created GIMPLE_ASSIGN tuple. */
19564 : :
19565 : : gimple *
19566 : 713958 : gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
19567 : : {
19568 : 713958 : tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
19569 : 713958 : gimplify_and_add (t, seq_p);
19570 : 713958 : ggc_free (t);
19571 : 713958 : return gimple_seq_last_stmt (*seq_p);
19572 : : }
19573 : :
19574 : : inline hashval_t
19575 : 1946744 : gimplify_hasher::hash (const elt_t *p)
19576 : : {
19577 : 1946744 : tree t = p->val;
19578 : 1946744 : return iterative_hash_expr (t, 0);
19579 : : }
19580 : :
19581 : : inline bool
19582 : 582052 : gimplify_hasher::equal (const elt_t *p1, const elt_t *p2)
19583 : : {
19584 : 582052 : tree t1 = p1->val;
19585 : 582052 : tree t2 = p2->val;
19586 : 582052 : enum tree_code code = TREE_CODE (t1);
19587 : :
19588 : 582052 : if (TREE_CODE (t2) != code
19589 : 582052 : || TREE_TYPE (t1) != TREE_TYPE (t2))
19590 : : return false;
19591 : :
19592 : 352273 : if (!operand_equal_p (t1, t2, 0))
19593 : : return false;
19594 : :
19595 : : /* Only allow them to compare equal if they also hash equal; otherwise
19596 : : results are nondeterminate, and we fail bootstrap comparison. */
19597 : 211546 : gcc_checking_assert (hash (p1) == hash (p2));
19598 : :
19599 : : return true;
19600 : : }
|