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-2025 Free Software Foundation, Inc.
4 : : Major work done by Sebastian Pop <s.pop@laposte.net>,
5 : : Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
6 : :
7 : : This file is part of GCC.
8 : :
9 : : GCC is free software; you can redistribute it and/or modify it under
10 : : the terms of the GNU General Public License as published by the Free
11 : : Software Foundation; either version 3, or (at your option) any later
12 : : version.
13 : :
14 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 : : for more details.
18 : :
19 : : You should have received a copy of the GNU General Public License
20 : : along with GCC; see the file COPYING3. If not see
21 : : <http://www.gnu.org/licenses/>. */
22 : :
23 : : #include "config.h"
24 : : #include "system.h"
25 : : #include "coretypes.h"
26 : : #include "backend.h"
27 : : #include "target.h"
28 : : #include "rtl.h"
29 : : #include "tree.h"
30 : : #include "memmodel.h"
31 : : #include "tm_p.h"
32 : : #include "gimple.h"
33 : : #include "gimple-predict.h"
34 : : #include "tree-pass.h" /* FIXME: only for PROP_gimple_any */
35 : : #include "ssa.h"
36 : : #include "cgraph.h"
37 : : #include "tree-pretty-print.h"
38 : : #include "diagnostic-core.h"
39 : : #include "diagnostic.h" /* For errorcount. */
40 : : #include "alias.h"
41 : : #include "fold-const.h"
42 : : #include "calls.h"
43 : : #include "varasm.h"
44 : : #include "stmt.h"
45 : : #include "expr.h"
46 : : #include "gimple-iterator.h"
47 : : #include "gimple-fold.h"
48 : : #include "tree-eh.h"
49 : : #include "gimplify.h"
50 : : #include "stor-layout.h"
51 : : #include "print-tree.h"
52 : : #include "tree-iterator.h"
53 : : #include "tree-inline.h"
54 : : #include "langhooks.h"
55 : : #include "tree-cfg.h"
56 : : #include "tree-ssa.h"
57 : : #include "tree-hash-traits.h"
58 : : #include "omp-general.h"
59 : : #include "omp-low.h"
60 : : #include "gimple-low.h"
61 : : #include "gomp-constants.h"
62 : : #include "splay-tree.h"
63 : : #include "gimple-walk.h"
64 : : #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
65 : : #include "builtins.h"
66 : : #include "stringpool.h"
67 : : #include "attribs.h"
68 : : #include "asan.h"
69 : : #include "dbgcnt.h"
70 : : #include "omp-offload.h"
71 : : #include "context.h"
72 : : #include "tree-nested.h"
73 : : #include "gcc-urlifier.h"
74 : : #include "insn-config.h"
75 : : #include "recog.h"
76 : : #include "output.h"
77 : : #include "gimplify_reg_info.h"
78 : :
79 : : /* Identifier for a basic condition, mapping it to other basic conditions of
80 : : its Boolean expression. Basic conditions given the same uid (in the same
81 : : function) are parts of the same ANDIF/ORIF expression. Used for condition
82 : : coverage. */
83 : : static unsigned nextconduid = 1;
84 : :
85 : : /* Annotated gconds so that basic conditions in the same expression map to
86 : : the same uid. This is used for condition coverage. */
87 : : static hash_map <tree, unsigned> *cond_uids;
88 : :
89 : : /* Get a fresh identifier for a new condition expression. This is used for
90 : : condition coverage. */
91 : : static unsigned
92 : 5774002 : next_cond_uid ()
93 : : {
94 : 5774002 : return nextconduid++;
95 : : }
96 : :
97 : : /* Reset the condition uid to the value it should have when compiling a new
98 : : function. 0 is already the default/untouched value, so start at non-zero.
99 : : A valid and set id should always be > 0. This is used for condition
100 : : coverage. */
101 : : static void
102 : 2945853 : reset_cond_uid ()
103 : : {
104 : 2945853 : nextconduid = 1;
105 : 0 : }
106 : :
107 : : /* Associate the condition STMT with the discriminator UID. STMTs that are
108 : : broken down with ANDIF/ORIF from the same Boolean expression should be given
109 : : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
110 : : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
111 : : for condition coverage. */
112 : : static void
113 : 1230844 : tree_associate_condition_with_expr (tree stmt, unsigned uid)
114 : : {
115 : 1230844 : if (!condition_coverage_flag)
116 : : return;
117 : :
118 : 527 : if (!cond_uids)
119 : 65 : cond_uids = new hash_map <tree, unsigned> ();
120 : :
121 : 527 : cond_uids->put (stmt, uid);
122 : : }
123 : :
124 : : /* Hash set of poisoned variables in a bind expr. */
125 : : static hash_set<tree> *asan_poisoned_variables = NULL;
126 : :
127 : : /* Hash set of already-resolved calls to OpenMP "declare variant"
128 : : functions. A call can resolve to the original function and
129 : : we don't want to repeat the resolution multiple times. */
130 : : static hash_set<tree> *omp_resolved_variant_calls = NULL;
131 : :
132 : : enum gimplify_omp_var_data
133 : : {
134 : : GOVD_SEEN = 0x000001,
135 : : GOVD_EXPLICIT = 0x000002,
136 : : GOVD_SHARED = 0x000004,
137 : : GOVD_PRIVATE = 0x000008,
138 : : GOVD_FIRSTPRIVATE = 0x000010,
139 : : GOVD_LASTPRIVATE = 0x000020,
140 : : GOVD_REDUCTION = 0x000040,
141 : : GOVD_LOCAL = 0x00080,
142 : : GOVD_MAP = 0x000100,
143 : : GOVD_DEBUG_PRIVATE = 0x000200,
144 : : GOVD_PRIVATE_OUTER_REF = 0x000400,
145 : : GOVD_LINEAR = 0x000800,
146 : : GOVD_ALIGNED = 0x001000,
147 : :
148 : : /* Flag for GOVD_MAP: don't copy back. */
149 : : GOVD_MAP_TO_ONLY = 0x002000,
150 : :
151 : : /* Flag for GOVD_LINEAR or GOVD_LASTPRIVATE: no outer reference. */
152 : : GOVD_LINEAR_LASTPRIVATE_NO_OUTER = 0x004000,
153 : :
154 : : GOVD_MAP_0LEN_ARRAY = 0x008000,
155 : :
156 : : /* Flag for GOVD_MAP, if it is always, to or always, tofrom mapping. */
157 : : GOVD_MAP_ALWAYS_TO = 0x010000,
158 : :
159 : : /* Flag for shared vars that are or might be stored to in the region. */
160 : : GOVD_WRITTEN = 0x020000,
161 : :
162 : : /* Flag for GOVD_MAP, if it is a forced mapping. */
163 : : GOVD_MAP_FORCE = 0x040000,
164 : :
165 : : /* Flag for GOVD_MAP: must be present already. */
166 : : GOVD_MAP_FORCE_PRESENT = 0x080000,
167 : :
168 : : /* Flag for GOVD_MAP: only allocate. */
169 : : GOVD_MAP_ALLOC_ONLY = 0x100000,
170 : :
171 : : /* Flag for GOVD_MAP: only copy back. */
172 : : GOVD_MAP_FROM_ONLY = 0x200000,
173 : :
174 : : GOVD_NONTEMPORAL = 0x400000,
175 : :
176 : : /* Flag for GOVD_LASTPRIVATE: conditional modifier. */
177 : : GOVD_LASTPRIVATE_CONDITIONAL = 0x800000,
178 : :
179 : : GOVD_CONDTEMP = 0x1000000,
180 : :
181 : : /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */
182 : : GOVD_REDUCTION_INSCAN = 0x2000000,
183 : :
184 : : /* Flag for GOVD_FIRSTPRIVATE: OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT. */
185 : : GOVD_FIRSTPRIVATE_IMPLICIT = 0x4000000,
186 : :
187 : : GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
188 : : | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
189 : : | GOVD_LOCAL)
190 : : };
191 : :
192 : :
193 : : enum omp_region_type
194 : : {
195 : : ORT_WORKSHARE = 0x00,
196 : : ORT_TASKGROUP = 0x01,
197 : : ORT_DISPATCH = 0x02,
198 : : ORT_SIMD = 0x04,
199 : :
200 : : ORT_PARALLEL = 0x08,
201 : : ORT_COMBINED_PARALLEL = ORT_PARALLEL | 1,
202 : :
203 : : ORT_TASK = 0x10,
204 : : ORT_UNTIED_TASK = ORT_TASK | 1,
205 : : ORT_TASKLOOP = ORT_TASK | 2,
206 : : ORT_UNTIED_TASKLOOP = ORT_UNTIED_TASK | 2,
207 : :
208 : : ORT_TEAMS = 0x20,
209 : : ORT_COMBINED_TEAMS = ORT_TEAMS | 1,
210 : : ORT_HOST_TEAMS = ORT_TEAMS | 2,
211 : : ORT_COMBINED_HOST_TEAMS = ORT_COMBINED_TEAMS | 2,
212 : :
213 : : /* Data region. */
214 : : ORT_TARGET_DATA = 0x40,
215 : :
216 : : /* Data region with offloading. */
217 : : ORT_TARGET = 0x80,
218 : : ORT_COMBINED_TARGET = ORT_TARGET | 1,
219 : : ORT_IMPLICIT_TARGET = ORT_TARGET | 2,
220 : :
221 : : /* OpenACC variants. */
222 : : ORT_ACC = 0x100, /* A generic OpenACC region. */
223 : : ORT_ACC_DATA = ORT_ACC | ORT_TARGET_DATA, /* Data construct. */
224 : : ORT_ACC_PARALLEL = ORT_ACC | ORT_TARGET, /* Parallel construct */
225 : : ORT_ACC_KERNELS = ORT_ACC | ORT_TARGET | 2, /* Kernels construct. */
226 : : ORT_ACC_SERIAL = ORT_ACC | ORT_TARGET | 4, /* Serial construct. */
227 : : ORT_ACC_HOST_DATA = ORT_ACC | ORT_TARGET_DATA | 2, /* Host data. */
228 : :
229 : : /* Dummy OpenMP region, used to disable expansion of
230 : : DECL_VALUE_EXPRs in taskloop pre body. */
231 : : ORT_NONE = 0x200
232 : : };
233 : :
234 : : /* Gimplify hashtable helper. */
235 : :
236 : : struct gimplify_hasher : free_ptr_hash <elt_t>
237 : : {
238 : : static inline hashval_t hash (const elt_t *);
239 : : static inline bool equal (const elt_t *, const elt_t *);
240 : : };
241 : :
242 : : struct gimplify_ctx
243 : : {
244 : : struct gimplify_ctx *prev_context;
245 : :
246 : : vec<gbind *> bind_expr_stack;
247 : : tree temps;
248 : : gimple_seq conditional_cleanups;
249 : : tree exit_label;
250 : : tree return_temp;
251 : :
252 : : vec<tree> case_labels;
253 : : hash_set<tree> *live_switch_vars;
254 : : /* The formal temporary table. Should this be persistent? */
255 : : hash_table<gimplify_hasher> *temp_htab;
256 : :
257 : : int conditions;
258 : : unsigned into_ssa : 1;
259 : : unsigned allow_rhs_cond_expr : 1;
260 : : unsigned in_cleanup_point_expr : 1;
261 : : unsigned keep_stack : 1;
262 : : unsigned save_stack : 1;
263 : : unsigned in_switch_expr : 1;
264 : : unsigned in_handler_expr : 1;
265 : : };
266 : :
267 : : enum gimplify_defaultmap_kind
268 : : {
269 : : GDMK_SCALAR,
270 : : GDMK_SCALAR_TARGET, /* w/ Fortran's target attr, implicit mapping, only. */
271 : : GDMK_AGGREGATE,
272 : : GDMK_ALLOCATABLE,
273 : : GDMK_POINTER
274 : : };
275 : :
276 : : struct gimplify_omp_ctx
277 : : {
278 : : struct gimplify_omp_ctx *outer_context;
279 : : splay_tree variables;
280 : : hash_map<omp_name_type<tree>, tree> *implicit_mappers;
281 : : hash_set<tree> *privatized_types;
282 : : tree clauses;
283 : : /* Iteration variables in an OMP_FOR. */
284 : : vec<tree> loop_iter_var;
285 : : location_t location;
286 : : enum omp_clause_default_kind default_kind;
287 : : enum omp_region_type region_type;
288 : : enum tree_code code;
289 : : bool combined_loop;
290 : : bool distribute;
291 : : bool target_firstprivatize_array_bases;
292 : : bool add_safelen1;
293 : : bool order_concurrent;
294 : : bool has_depend;
295 : : bool in_for_exprs;
296 : : bool in_call_args;
297 : : int defaultmap[5];
298 : : };
299 : :
300 : : static struct gimplify_ctx *gimplify_ctxp;
301 : : static struct gimplify_omp_ctx *gimplify_omp_ctxp;
302 : : static bool in_omp_construct;
303 : :
304 : : /* Forward declaration. */
305 : : static enum gimplify_status gimplify_compound_expr (tree *, gimple_seq *, bool);
306 : : static hash_map<tree, tree> *oacc_declare_returns;
307 : : static enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
308 : : bool (*) (tree), fallback_t, bool);
309 : : static void prepare_gimple_addressable (tree *, gimple_seq *);
310 : :
311 : : /* Shorter alias name for the above function for use in gimplify.cc
312 : : only. */
313 : :
314 : : static inline void
315 : 92593633 : gimplify_seq_add_stmt (gimple_seq *seq_p, gimple *gs)
316 : : {
317 : 92593633 : gimple_seq_add_stmt_without_update (seq_p, gs);
318 : 6669668 : }
319 : :
320 : : /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
321 : : NULL, a new sequence is allocated. This function is
322 : : similar to gimple_seq_add_seq, but does not scan the operands.
323 : : During gimplification, we need to manipulate statement sequences
324 : : before the def/use vectors have been constructed. */
325 : :
326 : : static void
327 : 9323413 : gimplify_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
328 : : {
329 : 9323413 : gimple_stmt_iterator si;
330 : :
331 : 9323413 : if (src == NULL)
332 : 4014076 : return;
333 : :
334 : 5309337 : si = gsi_last (*dst_p);
335 : 5309337 : gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
336 : : }
337 : :
338 : :
339 : : /* Pointer to a list of allocated gimplify_ctx structs to be used for pushing
340 : : and popping gimplify contexts. */
341 : :
342 : : static struct gimplify_ctx *ctx_pool = NULL;
343 : :
344 : : /* Return a gimplify context struct from the pool. */
345 : :
346 : : static inline struct gimplify_ctx *
347 : 9036839 : ctx_alloc (void)
348 : : {
349 : 9036839 : struct gimplify_ctx * c = ctx_pool;
350 : :
351 : 9036839 : if (c)
352 : 8773695 : ctx_pool = c->prev_context;
353 : : else
354 : 263144 : c = XNEW (struct gimplify_ctx);
355 : :
356 : 9036839 : memset (c, '\0', sizeof (*c));
357 : 9036839 : return c;
358 : : }
359 : :
360 : : /* Put gimplify context C back into the pool. */
361 : :
362 : : static inline void
363 : 9036835 : ctx_free (struct gimplify_ctx *c)
364 : : {
365 : 9036835 : c->prev_context = ctx_pool;
366 : 9036835 : ctx_pool = c;
367 : : }
368 : :
369 : : /* Free allocated ctx stack memory. */
370 : :
371 : : void
372 : 231576 : free_gimplify_stack (void)
373 : : {
374 : 231576 : struct gimplify_ctx *c;
375 : :
376 : 463767 : while ((c = ctx_pool))
377 : : {
378 : 232191 : ctx_pool = c->prev_context;
379 : 232191 : free (c);
380 : : }
381 : 231576 : }
382 : :
383 : :
384 : : /* Set up a context for the gimplifier. */
385 : :
386 : : void
387 : 9036839 : push_gimplify_context (bool in_ssa, bool rhs_cond_ok)
388 : : {
389 : 9036839 : struct gimplify_ctx *c = ctx_alloc ();
390 : :
391 : 9036839 : c->prev_context = gimplify_ctxp;
392 : 9036839 : gimplify_ctxp = c;
393 : 9036839 : gimplify_ctxp->into_ssa = in_ssa;
394 : 9036839 : gimplify_ctxp->allow_rhs_cond_expr = rhs_cond_ok;
395 : 9036839 : }
396 : :
397 : : /* Tear down a context for the gimplifier. If BODY is non-null, then
398 : : put the temporaries into the outer BIND_EXPR. Otherwise, put them
399 : : in the local_decls.
400 : :
401 : : BODY is not a sequence, but the first tuple in a sequence. */
402 : :
403 : : void
404 : 9036835 : pop_gimplify_context (gimple *body)
405 : : {
406 : 9036835 : struct gimplify_ctx *c = gimplify_ctxp;
407 : :
408 : 9036835 : gcc_assert (c
409 : : && (!c->bind_expr_stack.exists ()
410 : : || c->bind_expr_stack.is_empty ()));
411 : 9036835 : c->bind_expr_stack.release ();
412 : 9036835 : gimplify_ctxp = c->prev_context;
413 : :
414 : 9036835 : if (body)
415 : 3069292 : declare_vars (c->temps, body, false);
416 : : else
417 : 5967543 : record_vars (c->temps);
418 : :
419 : 9036835 : delete c->temp_htab;
420 : 9036835 : c->temp_htab = NULL;
421 : 9036835 : ctx_free (c);
422 : 9036835 : }
423 : :
424 : : /* Push a GIMPLE_BIND tuple onto the stack of bindings. */
425 : :
426 : : static void
427 : 5991066 : gimple_push_bind_expr (gbind *bind_stmt)
428 : : {
429 : 5991066 : gimplify_ctxp->bind_expr_stack.reserve (8);
430 : 5991066 : gimplify_ctxp->bind_expr_stack.safe_push (bind_stmt);
431 : 5991066 : }
432 : :
433 : : /* Pop the first element off the stack of bindings. */
434 : :
435 : : static void
436 : 5991066 : gimple_pop_bind_expr (void)
437 : : {
438 : 0 : gimplify_ctxp->bind_expr_stack.pop ();
439 : 1216 : }
440 : :
441 : : /* Return the first element of the stack of bindings. */
442 : :
443 : : gbind *
444 : 0 : gimple_current_bind_expr (void)
445 : : {
446 : 0 : return gimplify_ctxp->bind_expr_stack.last ();
447 : : }
448 : :
449 : : /* Return the stack of bindings created during gimplification. */
450 : :
451 : : vec<gbind *>
452 : 359 : gimple_bind_expr_stack (void)
453 : : {
454 : 359 : return gimplify_ctxp->bind_expr_stack;
455 : : }
456 : :
457 : : /* Return true iff there is a COND_EXPR between us and the innermost
458 : : CLEANUP_POINT_EXPR. This info is used by gimple_push_cleanup. */
459 : :
460 : : static bool
461 : 2876164 : gimple_conditional_context (void)
462 : : {
463 : 2876164 : return gimplify_ctxp->conditions > 0;
464 : : }
465 : :
466 : : /* Note that we've entered a COND_EXPR. */
467 : :
468 : : static void
469 : 5774437 : gimple_push_condition (void)
470 : : {
471 : : #ifdef ENABLE_GIMPLE_CHECKING
472 : 5774437 : if (gimplify_ctxp->conditions == 0)
473 : 3790527 : gcc_assert (gimple_seq_empty_p (gimplify_ctxp->conditional_cleanups));
474 : : #endif
475 : 5774437 : ++(gimplify_ctxp->conditions);
476 : 5774437 : }
477 : :
478 : : /* Note that we've left a COND_EXPR. If we're back at unconditional scope
479 : : now, add any conditional cleanups we've seen to the prequeue. */
480 : :
481 : : static void
482 : 5774437 : gimple_pop_condition (gimple_seq *pre_p)
483 : : {
484 : 5774437 : int conds = --(gimplify_ctxp->conditions);
485 : :
486 : 5774437 : gcc_assert (conds >= 0);
487 : 5774437 : if (conds == 0)
488 : : {
489 : 3790527 : gimplify_seq_add_seq (pre_p, gimplify_ctxp->conditional_cleanups);
490 : 3790527 : gimplify_ctxp->conditional_cleanups = NULL;
491 : : }
492 : 5774437 : }
493 : :
494 : : /* A stable comparison routine for use with splay trees and DECLs. */
495 : :
496 : : static int
497 : 17904957 : splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
498 : : {
499 : 17904957 : tree a = (tree) xa;
500 : 17904957 : tree b = (tree) xb;
501 : :
502 : 17904957 : return DECL_UID (a) - DECL_UID (b);
503 : : }
504 : :
505 : : /* Create a new omp construct that deals with variable remapping. */
506 : :
507 : : static struct gimplify_omp_ctx *
508 : 138966 : new_omp_context (enum omp_region_type region_type)
509 : : {
510 : 138966 : struct gimplify_omp_ctx *c;
511 : :
512 : 138966 : c = XCNEW (struct gimplify_omp_ctx);
513 : 138966 : c->outer_context = gimplify_omp_ctxp;
514 : 138966 : c->variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
515 : 138966 : c->implicit_mappers = new hash_map<omp_name_type<tree>, tree>;
516 : 138966 : c->privatized_types = new hash_set<tree>;
517 : 138966 : c->location = input_location;
518 : 138966 : c->region_type = region_type;
519 : 138966 : if ((region_type & ORT_TASK) == 0)
520 : 132931 : c->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
521 : : else
522 : 6035 : c->default_kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
523 : 138966 : c->defaultmap[GDMK_SCALAR] = GOVD_MAP;
524 : 138966 : c->defaultmap[GDMK_SCALAR_TARGET] = GOVD_MAP;
525 : 138966 : c->defaultmap[GDMK_AGGREGATE] = GOVD_MAP;
526 : 138966 : c->defaultmap[GDMK_ALLOCATABLE] = GOVD_MAP;
527 : 138966 : c->defaultmap[GDMK_POINTER] = GOVD_MAP;
528 : :
529 : 138966 : return c;
530 : : }
531 : :
532 : : /* Destroy an omp construct that deals with variable remapping. */
533 : :
534 : : static void
535 : 138407 : delete_omp_context (struct gimplify_omp_ctx *c)
536 : : {
537 : 138407 : splay_tree_delete (c->variables);
538 : 276814 : delete c->privatized_types;
539 : 276814 : delete c->implicit_mappers;
540 : 138407 : c->loop_iter_var.release ();
541 : 138407 : XDELETE (c);
542 : 138407 : }
543 : :
544 : : static void omp_add_variable (struct gimplify_omp_ctx *, tree, unsigned int);
545 : : static bool omp_notice_variable (struct gimplify_omp_ctx *, tree, bool);
546 : :
547 : : /* Both gimplify the statement T and append it to *SEQ_P. This function
548 : : behaves exactly as gimplify_stmt, but you don't have to pass T as a
549 : : reference. */
550 : :
551 : : void
552 : 38222580 : gimplify_and_add (tree t, gimple_seq *seq_p)
553 : : {
554 : 38222580 : gimplify_stmt (&t, seq_p);
555 : 38222580 : }
556 : :
557 : : /* Gimplify statement T into sequence *SEQ_P, and return the first
558 : : tuple in the sequence of generated tuples for this statement.
559 : : Return NULL if gimplifying T produced no tuples. */
560 : :
561 : : static gimple *
562 : 104342 : gimplify_and_return_first (tree t, gimple_seq *seq_p)
563 : : {
564 : 104342 : gimple_stmt_iterator last = gsi_last (*seq_p);
565 : :
566 : 104342 : gimplify_and_add (t, seq_p);
567 : :
568 : 104342 : if (!gsi_end_p (last))
569 : : {
570 : 4882 : gsi_next (&last);
571 : 4882 : return gsi_stmt (last);
572 : : }
573 : : else
574 : 99460 : return gimple_seq_first_stmt (*seq_p);
575 : : }
576 : :
577 : : /* Returns true iff T is a valid RHS for an assignment to an un-renamed
578 : : LHS, or for a call argument. */
579 : :
580 : : static bool
581 : 235555 : is_gimple_mem_rhs (tree t)
582 : : {
583 : : /* If we're dealing with a renamable type, either source or dest must be
584 : : a renamed variable. */
585 : 235555 : if (is_gimple_reg_type (TREE_TYPE (t)))
586 : 232203 : return is_gimple_val (t);
587 : : else
588 : 3352 : return is_gimple_val (t) || is_gimple_lvalue (t);
589 : : }
590 : :
591 : : /* Return true if T is a CALL_EXPR or an expression that can be
592 : : assigned to a temporary. Note that this predicate should only be
593 : : used during gimplification. See the rationale for this in
594 : : gimplify_modify_expr. */
595 : :
596 : : static bool
597 : 97600380 : is_gimple_reg_rhs_or_call (tree t)
598 : : {
599 : 71650693 : return (get_gimple_rhs_class (TREE_CODE (t)) != GIMPLE_INVALID_RHS
600 : 97600380 : || TREE_CODE (t) == CALL_EXPR);
601 : : }
602 : :
603 : : /* Return true if T is a valid memory RHS or a CALL_EXPR. Note that
604 : : this predicate should only be used during gimplification. See the
605 : : rationale for this in gimplify_modify_expr. */
606 : :
607 : : static bool
608 : 14451026 : is_gimple_mem_rhs_or_call (tree t)
609 : : {
610 : : /* If we're dealing with a renamable type, either source or dest must be
611 : : a renamed variable. */
612 : 14451026 : if (is_gimple_reg_type (TREE_TYPE (t)))
613 : 10971699 : return is_gimple_val (t);
614 : : else
615 : 3479327 : return (is_gimple_val (t)
616 : 1762176 : || is_gimple_lvalue (t)
617 : 1227737 : || (TREE_CODE (t) == CONSTRUCTOR && CONSTRUCTOR_NELTS (t) == 0)
618 : 4706674 : || TREE_CODE (t) == CALL_EXPR);
619 : : }
620 : :
621 : : /* Create a temporary with a name derived from VAL. Subroutine of
622 : : lookup_tmp_var; nobody else should call this function. */
623 : :
624 : : static inline tree
625 : 2131876 : create_tmp_from_val (tree val)
626 : : {
627 : : /* Drop all qualifiers and address-space information from the value type. */
628 : 2131876 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (val));
629 : 2131876 : tree var = create_tmp_var (type, get_name (val));
630 : 2131876 : return var;
631 : : }
632 : :
633 : : /* Create a temporary to hold the value of VAL. If IS_FORMAL, try to reuse
634 : : an existing expression temporary. If NOT_GIMPLE_REG, mark it as such. */
635 : :
636 : : static tree
637 : 2361767 : lookup_tmp_var (tree val, bool is_formal, bool not_gimple_reg)
638 : : {
639 : 2361767 : tree ret;
640 : :
641 : : /* We cannot mark a formal temporary with DECL_NOT_GIMPLE_REG_P. */
642 : 2361767 : gcc_assert (!is_formal || !not_gimple_reg);
643 : :
644 : : /* If not optimizing, never really reuse a temporary. local-alloc
645 : : won't allocate any variable that is used in more than one basic
646 : : block, which means it will go into memory, causing much extra
647 : : work in reload and final and poorer code generation, outweighing
648 : : the extra memory allocation here. */
649 : 2361767 : if (!optimize || !is_formal || TREE_SIDE_EFFECTS (val))
650 : : {
651 : 1086298 : ret = create_tmp_from_val (val);
652 : 1086298 : DECL_NOT_GIMPLE_REG_P (ret) = not_gimple_reg;
653 : : }
654 : : else
655 : : {
656 : 1275469 : elt_t elt, *elt_p;
657 : 1275469 : elt_t **slot;
658 : :
659 : 1275469 : elt.val = val;
660 : 1275469 : if (!gimplify_ctxp->temp_htab)
661 : 393452 : gimplify_ctxp->temp_htab = new hash_table<gimplify_hasher> (1000);
662 : 1275469 : slot = gimplify_ctxp->temp_htab->find_slot (&elt, INSERT);
663 : 1275469 : if (*slot == NULL)
664 : : {
665 : 1045578 : elt_p = XNEW (elt_t);
666 : 1045578 : elt_p->val = val;
667 : 1045578 : elt_p->temp = ret = create_tmp_from_val (val);
668 : 1045578 : *slot = elt_p;
669 : : }
670 : : else
671 : : {
672 : 229891 : elt_p = *slot;
673 : 229891 : ret = elt_p->temp;
674 : : }
675 : : }
676 : :
677 : 2361767 : return ret;
678 : : }
679 : :
680 : : /* Helper for get_formal_tmp_var and get_initialized_tmp_var. */
681 : :
682 : : static tree
683 : 26485641 : internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p,
684 : : bool is_formal, bool allow_ssa, bool not_gimple_reg)
685 : : {
686 : 26485641 : tree t, mod;
687 : :
688 : : /* Notice that we explicitly allow VAL to be a CALL_EXPR so that we
689 : : can create an INIT_EXPR and convert it into a GIMPLE_CALL below. */
690 : 26485641 : gimplify_expr (&val, pre_p, post_p, is_gimple_reg_rhs_or_call,
691 : : fb_rvalue);
692 : :
693 : 26485641 : if (allow_ssa
694 : 26223897 : && gimplify_ctxp->into_ssa
695 : 51290573 : && is_gimple_reg_type (TREE_TYPE (val)))
696 : : {
697 : 24123875 : t = make_ssa_name (TYPE_MAIN_VARIANT (TREE_TYPE (val)));
698 : 24123875 : if (! gimple_in_ssa_p (cfun))
699 : : {
700 : 20743373 : const char *name = get_name (val);
701 : 20743373 : if (name)
702 : 6795290 : SET_SSA_NAME_VAR_OR_IDENTIFIER (t, create_tmp_var_name (name));
703 : : }
704 : : }
705 : : else
706 : 2361766 : t = lookup_tmp_var (val, is_formal, not_gimple_reg);
707 : :
708 : 26485641 : mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val));
709 : :
710 : 26485641 : SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location));
711 : :
712 : : /* gimplify_modify_expr might want to reduce this further. */
713 : 26485641 : gimplify_and_add (mod, pre_p);
714 : 26485641 : ggc_free (mod);
715 : :
716 : : /* If we failed to gimplify VAL then we can end up with the temporary
717 : : SSA name not having a definition. In this case return a decl. */
718 : 26485641 : if (TREE_CODE (t) == SSA_NAME && ! SSA_NAME_DEF_STMT (t))
719 : 1 : return lookup_tmp_var (val, is_formal, not_gimple_reg);
720 : :
721 : : return t;
722 : : }
723 : :
724 : : /* Return a formal temporary variable initialized with VAL. PRE_P is as
725 : : in gimplify_expr. Only use this function if:
726 : :
727 : : 1) The value of the unfactored expression represented by VAL will not
728 : : change between the initialization and use of the temporary, and
729 : : 2) The temporary will not be otherwise modified.
730 : :
731 : : For instance, #1 means that this is inappropriate for SAVE_EXPR temps,
732 : : and #2 means it is inappropriate for && temps.
733 : :
734 : : For other cases, use get_initialized_tmp_var instead. */
735 : :
736 : : tree
737 : 25988317 : get_formal_tmp_var (tree val, gimple_seq *pre_p)
738 : : {
739 : 25988317 : return internal_get_tmp_var (val, pre_p, NULL, true, true, false);
740 : : }
741 : :
742 : : /* Return a temporary variable initialized with VAL. PRE_P and POST_P
743 : : are as in gimplify_expr. */
744 : :
745 : : tree
746 : 485328 : get_initialized_tmp_var (tree val, gimple_seq *pre_p,
747 : : gimple_seq *post_p /* = NULL */,
748 : : bool allow_ssa /* = true */)
749 : : {
750 : 485328 : return internal_get_tmp_var (val, pre_p, post_p, false, allow_ssa, false);
751 : : }
752 : :
753 : : /* Declare all the variables in VARS in SCOPE. If DEBUG_INFO is true,
754 : : generate debug info for them; otherwise don't. */
755 : :
756 : : void
757 : 3077071 : declare_vars (tree vars, gimple *gs, bool debug_info)
758 : : {
759 : 3077071 : tree last = vars;
760 : 3077071 : if (last)
761 : : {
762 : 1926071 : tree temps, block;
763 : :
764 : 1926071 : gbind *scope = as_a <gbind *> (gs);
765 : :
766 : 1926071 : temps = nreverse (last);
767 : :
768 : 1926071 : block = gimple_bind_block (scope);
769 : 1926071 : gcc_assert (!block || TREE_CODE (block) == BLOCK);
770 : 1926071 : if (!block || !debug_info)
771 : : {
772 : 1922466 : DECL_CHAIN (last) = gimple_bind_vars (scope);
773 : 1922466 : gimple_bind_set_vars (scope, temps);
774 : : }
775 : : else
776 : : {
777 : : /* We need to attach the nodes both to the BIND_EXPR and to its
778 : : associated BLOCK for debugging purposes. The key point here
779 : : is that the BLOCK_VARS of the BIND_EXPR_BLOCK of a BIND_EXPR
780 : : is a subchain of the BIND_EXPR_VARS of the BIND_EXPR. */
781 : 3605 : if (BLOCK_VARS (block))
782 : 3412 : BLOCK_VARS (block) = chainon (BLOCK_VARS (block), temps);
783 : : else
784 : : {
785 : 193 : gimple_bind_set_vars (scope,
786 : : chainon (gimple_bind_vars (scope), temps));
787 : 193 : BLOCK_VARS (block) = temps;
788 : : }
789 : : }
790 : : }
791 : 3077071 : }
792 : :
793 : : /* For VAR a VAR_DECL of variable size, try to find a constant upper bound
794 : : for the size and adjust DECL_SIZE/DECL_SIZE_UNIT accordingly. Abort if
795 : : no such upper bound can be obtained. */
796 : :
797 : : static void
798 : 0 : force_constant_size (tree var)
799 : : {
800 : : /* The only attempt we make is by querying the maximum size of objects
801 : : of the variable's type. */
802 : :
803 : 0 : HOST_WIDE_INT max_size;
804 : :
805 : 0 : gcc_assert (VAR_P (var));
806 : :
807 : 0 : max_size = max_int_size_in_bytes (TREE_TYPE (var));
808 : :
809 : 0 : gcc_assert (max_size >= 0);
810 : :
811 : 0 : DECL_SIZE_UNIT (var)
812 : 0 : = build_int_cst (TREE_TYPE (DECL_SIZE_UNIT (var)), max_size);
813 : 0 : DECL_SIZE (var)
814 : 0 : = build_int_cst (TREE_TYPE (DECL_SIZE (var)), max_size * BITS_PER_UNIT);
815 : 0 : }
816 : :
817 : : /* Push the temporary variable TMP into the current binding. */
818 : :
819 : : void
820 : 36253 : gimple_add_tmp_var_fn (struct function *fn, tree tmp)
821 : : {
822 : 36253 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
823 : :
824 : : /* Later processing assumes that the object size is constant, which might
825 : : not be true at this point. Force the use of a constant upper bound in
826 : : this case. */
827 : 36253 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
828 : 0 : force_constant_size (tmp);
829 : :
830 : 36253 : DECL_CONTEXT (tmp) = fn->decl;
831 : 36253 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
832 : :
833 : 36253 : record_vars_into (tmp, fn->decl);
834 : 36253 : }
835 : :
836 : : /* Push the temporary variable TMP into the current binding. */
837 : :
838 : : void
839 : 16382336 : gimple_add_tmp_var (tree tmp)
840 : : {
841 : 16382336 : gcc_assert (!DECL_CHAIN (tmp) && !DECL_SEEN_IN_BIND_EXPR_P (tmp));
842 : :
843 : : /* Later processing assumes that the object size is constant, which might
844 : : not be true at this point. Force the use of a constant upper bound in
845 : : this case. */
846 : 16382336 : if (!tree_fits_poly_uint64_p (DECL_SIZE_UNIT (tmp)))
847 : 0 : force_constant_size (tmp);
848 : :
849 : 16382336 : DECL_CONTEXT (tmp) = current_function_decl;
850 : 16382336 : DECL_SEEN_IN_BIND_EXPR_P (tmp) = 1;
851 : :
852 : 16382336 : if (gimplify_ctxp)
853 : : {
854 : 5633839 : DECL_CHAIN (tmp) = gimplify_ctxp->temps;
855 : 5633839 : gimplify_ctxp->temps = tmp;
856 : :
857 : : /* Mark temporaries local within the nearest enclosing parallel. */
858 : 5633839 : if (gimplify_omp_ctxp)
859 : : {
860 : : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
861 : 546080 : int flag = GOVD_LOCAL | GOVD_SEEN;
862 : : while (ctx
863 : 546080 : && (ctx->region_type == ORT_WORKSHARE
864 : : || ctx->region_type == ORT_TASKGROUP
865 : 398516 : || ctx->region_type == ORT_SIMD
866 : 348328 : || ctx->region_type == ORT_ACC))
867 : : {
868 : 204611 : if (ctx->region_type == ORT_SIMD
869 : 50188 : && TREE_ADDRESSABLE (tmp)
870 : 96 : && !TREE_STATIC (tmp))
871 : : {
872 : 96 : if (TREE_CODE (DECL_SIZE_UNIT (tmp)) != INTEGER_CST)
873 : 0 : ctx->add_safelen1 = true;
874 : 96 : else if (ctx->in_for_exprs)
875 : : flag = GOVD_PRIVATE;
876 : : else
877 : : flag = GOVD_PRIVATE | GOVD_SEEN;
878 : : break;
879 : : }
880 : 204515 : ctx = ctx->outer_context;
881 : : }
882 : 341469 : if (ctx)
883 : 314392 : omp_add_variable (ctx, tmp, flag);
884 : : }
885 : : }
886 : 10748497 : else if (cfun)
887 : 10748497 : record_vars (tmp);
888 : : else
889 : : {
890 : 0 : gimple_seq body_seq;
891 : :
892 : : /* This case is for nested functions. We need to expose the locals
893 : : they create. */
894 : 0 : body_seq = gimple_body (current_function_decl);
895 : 0 : declare_vars (tmp, gimple_seq_first_stmt (body_seq), false);
896 : : }
897 : 16382336 : }
898 : :
899 : :
900 : :
901 : : /* This page contains routines to unshare tree nodes, i.e. to duplicate tree
902 : : nodes that are referenced more than once in GENERIC functions. This is
903 : : necessary because gimplification (translation into GIMPLE) is performed
904 : : by modifying tree nodes in-place, so gimplication of a shared node in a
905 : : first context could generate an invalid GIMPLE form in a second context.
906 : :
907 : : This is achieved with a simple mark/copy/unmark algorithm that walks the
908 : : GENERIC representation top-down, marks nodes with TREE_VISITED the first
909 : : time it encounters them, duplicates them if they already have TREE_VISITED
910 : : set, and finally removes the TREE_VISITED marks it has set.
911 : :
912 : : The algorithm works only at the function level, i.e. it generates a GENERIC
913 : : representation of a function with no nodes shared within the function when
914 : : passed a GENERIC function (except for nodes that are allowed to be shared).
915 : :
916 : : At the global level, it is also necessary to unshare tree nodes that are
917 : : referenced in more than one function, for the same aforementioned reason.
918 : : This requires some cooperation from the front-end. There are 2 strategies:
919 : :
920 : : 1. Manual unsharing. The front-end needs to call unshare_expr on every
921 : : expression that might end up being shared across functions.
922 : :
923 : : 2. Deep unsharing. This is an extension of regular unsharing. Instead
924 : : of calling unshare_expr on expressions that might be shared across
925 : : functions, the front-end pre-marks them with TREE_VISITED. This will
926 : : ensure that they are unshared on the first reference within functions
927 : : when the regular unsharing algorithm runs. The counterpart is that
928 : : this algorithm must look deeper than for manual unsharing, which is
929 : : specified by LANG_HOOKS_DEEP_UNSHARING.
930 : :
931 : : If there are only few specific cases of node sharing across functions, it is
932 : : probably easier for a front-end to unshare the expressions manually. On the
933 : : contrary, if the expressions generated at the global level are as widespread
934 : : as expressions generated within functions, deep unsharing is very likely the
935 : : way to go. */
936 : :
937 : : /* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
938 : : These nodes model computations that must be done once. If we were to
939 : : unshare something like SAVE_EXPR(i++), the gimplification process would
940 : : create wrong code. However, if DATA is non-null, it must hold a pointer
941 : : set that is used to unshare the subtrees of these nodes. */
942 : :
943 : : static tree
944 : 2262028502 : mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
945 : : {
946 : 2262028502 : tree t = *tp;
947 : 2262028502 : enum tree_code code = TREE_CODE (t);
948 : :
949 : : /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
950 : : copy their subtrees if we can make sure to do it only once. */
951 : 2262028502 : if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
952 : : {
953 : 8735676 : if (data && !((hash_set<tree> *)data)->add (t))
954 : : ;
955 : : else
956 : 8735676 : *walk_subtrees = 0;
957 : : }
958 : :
959 : : /* Stop at types, decls, constants like copy_tree_r. */
960 : 2253292826 : else if (TREE_CODE_CLASS (code) == tcc_type
961 : : || TREE_CODE_CLASS (code) == tcc_declaration
962 : 2253292826 : || TREE_CODE_CLASS (code) == tcc_constant)
963 : 1365167898 : *walk_subtrees = 0;
964 : :
965 : : /* Cope with the statement expression extension. */
966 : 888124928 : else if (code == STATEMENT_LIST)
967 : : ;
968 : :
969 : : /* Leave the bulk of the work to copy_tree_r itself. */
970 : : else
971 : 888075293 : copy_tree_r (tp, walk_subtrees, NULL);
972 : :
973 : 2262028502 : return NULL_TREE;
974 : : }
975 : :
976 : : /* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
977 : : If *TP has been visited already, then *TP is deeply copied by calling
978 : : mostly_copy_tree_r. DATA is passed to mostly_copy_tree_r unmodified. */
979 : :
980 : : static tree
981 : 280170113 : copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
982 : : {
983 : 280170113 : tree t = *tp;
984 : 280170113 : enum tree_code code = TREE_CODE (t);
985 : :
986 : : /* Skip types, decls, and constants. But we do want to look at their
987 : : types and the bounds of types. Mark them as visited so we properly
988 : : unmark their subtrees on the unmark pass. If we've already seen them,
989 : : don't look down further. */
990 : 280170113 : if (TREE_CODE_CLASS (code) == tcc_type
991 : : || TREE_CODE_CLASS (code) == tcc_declaration
992 : 280170113 : || TREE_CODE_CLASS (code) == tcc_constant)
993 : : {
994 : 133053196 : if (TREE_VISITED (t))
995 : 81476066 : *walk_subtrees = 0;
996 : : else
997 : 51577130 : TREE_VISITED (t) = 1;
998 : : }
999 : :
1000 : : /* If this node has been visited already, unshare it and don't look
1001 : : any deeper. */
1002 : 147116917 : else if (TREE_VISITED (t))
1003 : : {
1004 : 1676936 : walk_tree (tp, mostly_copy_tree_r, data, NULL);
1005 : 1676936 : *walk_subtrees = 0;
1006 : : }
1007 : :
1008 : : /* Otherwise, mark the node as visited and keep looking. */
1009 : : else
1010 : 145439981 : TREE_VISITED (t) = 1;
1011 : :
1012 : 280170113 : return NULL_TREE;
1013 : : }
1014 : :
1015 : : /* Unshare most of the shared trees rooted at *TP. DATA is passed to the
1016 : : copy_if_shared_r callback unmodified. */
1017 : :
1018 : : void
1019 : 8914377 : copy_if_shared (tree *tp, void *data)
1020 : : {
1021 : 8914377 : walk_tree (tp, copy_if_shared_r, data, NULL);
1022 : 8914377 : }
1023 : :
1024 : : /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
1025 : : any nested functions. */
1026 : :
1027 : : static void
1028 : 2971459 : unshare_body (tree fndecl)
1029 : : {
1030 : 2971459 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
1031 : : /* If the language requires deep unsharing, we need a pointer set to make
1032 : : sure we don't repeatedly unshare subtrees of unshareable nodes. */
1033 : 2971459 : hash_set<tree> *visited
1034 : 2971459 : = lang_hooks.deep_unsharing ? new hash_set<tree> : NULL;
1035 : :
1036 : 2971459 : copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
1037 : 2971459 : copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
1038 : 2971459 : copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
1039 : :
1040 : 2974790 : delete visited;
1041 : :
1042 : 2971459 : if (cgn)
1043 : 5986388 : for (cgn = first_nested_function (cgn); cgn;
1044 : 25087 : cgn = next_nested_function (cgn))
1045 : 25087 : unshare_body (cgn->decl);
1046 : 2971459 : }
1047 : :
1048 : : /* Callback for walk_tree to unmark the visited trees rooted at *TP.
1049 : : Subtrees are walked until the first unvisited node is encountered. */
1050 : :
1051 : : static tree
1052 : 280169687 : unmark_visited_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
1053 : : {
1054 : 280169687 : tree t = *tp;
1055 : :
1056 : : /* If this node has been visited, unmark it and keep looking. */
1057 : 280169687 : if (TREE_VISITED (t))
1058 : 197021580 : TREE_VISITED (t) = 0;
1059 : :
1060 : : /* Otherwise, don't look any deeper. */
1061 : : else
1062 : 83148107 : *walk_subtrees = 0;
1063 : :
1064 : 280169687 : return NULL_TREE;
1065 : : }
1066 : :
1067 : : /* Unmark the visited trees rooted at *TP. */
1068 : :
1069 : : static inline void
1070 : 8914377 : unmark_visited (tree *tp)
1071 : : {
1072 : 8914377 : walk_tree (tp, unmark_visited_r, NULL, NULL);
1073 : 8914377 : }
1074 : :
1075 : : /* Likewise, but mark all trees as not visited. */
1076 : :
1077 : : static void
1078 : 2971459 : unvisit_body (tree fndecl)
1079 : : {
1080 : 2971459 : struct cgraph_node *cgn = cgraph_node::get (fndecl);
1081 : :
1082 : 2971459 : unmark_visited (&DECL_SAVED_TREE (fndecl));
1083 : 2971459 : unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
1084 : 2971459 : unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
1085 : :
1086 : 2971459 : if (cgn)
1087 : 2993194 : for (cgn = first_nested_function (cgn);
1088 : 2993194 : cgn; cgn = next_nested_function (cgn))
1089 : 25087 : unvisit_body (cgn->decl);
1090 : 2971459 : }
1091 : :
1092 : : /* Unconditionally make an unshared copy of EXPR. This is used when using
1093 : : stored expressions which span multiple functions, such as BINFO_VTABLE,
1094 : : as the normal unsharing process can't tell that they're shared. */
1095 : :
1096 : : tree
1097 : 1231642261 : unshare_expr (tree expr)
1098 : : {
1099 : 1231642261 : walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
1100 : 1231642261 : return expr;
1101 : : }
1102 : :
1103 : : /* Worker for unshare_expr_without_location. */
1104 : :
1105 : : static tree
1106 : 8487476 : prune_expr_location (tree *tp, int *walk_subtrees, void *)
1107 : : {
1108 : 8487476 : if (EXPR_P (*tp))
1109 : 3992169 : SET_EXPR_LOCATION (*tp, UNKNOWN_LOCATION);
1110 : : else
1111 : 4495307 : *walk_subtrees = 0;
1112 : 8487476 : return NULL_TREE;
1113 : : }
1114 : :
1115 : : /* Similar to unshare_expr but also prune all expression locations
1116 : : from EXPR. */
1117 : :
1118 : : tree
1119 : 21159207 : unshare_expr_without_location (tree expr)
1120 : : {
1121 : 21159207 : walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
1122 : 21159207 : if (EXPR_P (expr))
1123 : 2744295 : walk_tree (&expr, prune_expr_location, NULL, NULL);
1124 : 21159207 : return expr;
1125 : : }
1126 : :
1127 : : /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
1128 : : one, OR_ELSE otherwise. The location of a STATEMENT_LISTs
1129 : : comprising at least one DEBUG_BEGIN_STMT followed by exactly one
1130 : : EXPR is the location of the EXPR. */
1131 : :
1132 : : static location_t
1133 : 1173458 : rexpr_location (tree expr, location_t or_else = UNKNOWN_LOCATION)
1134 : : {
1135 : 1173458 : if (!expr)
1136 : : return or_else;
1137 : :
1138 : 1173458 : if (EXPR_HAS_LOCATION (expr))
1139 : 819303 : return EXPR_LOCATION (expr);
1140 : :
1141 : 354155 : if (TREE_CODE (expr) != STATEMENT_LIST)
1142 : : return or_else;
1143 : :
1144 : 0 : tree_stmt_iterator i = tsi_start (expr);
1145 : :
1146 : 0 : bool found = false;
1147 : 0 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
1148 : : {
1149 : 0 : found = true;
1150 : 0 : tsi_next (&i);
1151 : : }
1152 : :
1153 : 354155 : if (!found || !tsi_one_before_end_p (i))
1154 : : return or_else;
1155 : :
1156 : 0 : return rexpr_location (tsi_stmt (i), or_else);
1157 : : }
1158 : :
1159 : : /* Return TRUE iff EXPR (maybe recursively) has a location; see
1160 : : rexpr_location for the potential recursion. */
1161 : :
1162 : : static inline bool
1163 : 506733 : rexpr_has_location (tree expr)
1164 : : {
1165 : 296420 : return rexpr_location (expr) != UNKNOWN_LOCATION;
1166 : : }
1167 : :
1168 : :
1169 : : /* WRAPPER is a code such as BIND_EXPR or CLEANUP_POINT_EXPR which can both
1170 : : contain statements and have a value. Assign its value to a temporary
1171 : : and give it void_type_node. Return the temporary, or NULL_TREE if
1172 : : WRAPPER was already void. */
1173 : :
1174 : : tree
1175 : 20398060 : voidify_wrapper_expr (tree wrapper, tree temp)
1176 : : {
1177 : 20398060 : tree type = TREE_TYPE (wrapper);
1178 : 20398060 : if (type && !VOID_TYPE_P (type))
1179 : : {
1180 : : tree *p;
1181 : :
1182 : : /* Set p to point to the body of the wrapper. Loop until we find
1183 : : something that isn't a wrapper. */
1184 : 768614 : for (p = &wrapper; p && *p; )
1185 : : {
1186 : 768614 : switch (TREE_CODE (*p))
1187 : : {
1188 : 3113 : case BIND_EXPR:
1189 : 3113 : TREE_SIDE_EFFECTS (*p) = 1;
1190 : 3113 : TREE_TYPE (*p) = void_type_node;
1191 : : /* For a BIND_EXPR, the body is operand 1. */
1192 : 3113 : p = &BIND_EXPR_BODY (*p);
1193 : 3113 : break;
1194 : :
1195 : 357917 : case CLEANUP_POINT_EXPR:
1196 : 357917 : case TRY_FINALLY_EXPR:
1197 : 357917 : case TRY_CATCH_EXPR:
1198 : 357917 : TREE_SIDE_EFFECTS (*p) = 1;
1199 : 357917 : TREE_TYPE (*p) = void_type_node;
1200 : 357917 : p = &TREE_OPERAND (*p, 0);
1201 : 357917 : break;
1202 : :
1203 : 18381 : case STATEMENT_LIST:
1204 : 18381 : {
1205 : 18381 : tree_stmt_iterator i = tsi_last (*p);
1206 : 18381 : TREE_SIDE_EFFECTS (*p) = 1;
1207 : 18381 : TREE_TYPE (*p) = void_type_node;
1208 : 18381 : p = tsi_end_p (i) ? NULL : tsi_stmt_ptr (i);
1209 : : }
1210 : 18381 : break;
1211 : :
1212 : : case COMPOUND_EXPR:
1213 : : /* Advance to the last statement. Set all container types to
1214 : : void. */
1215 : 49306 : for (; TREE_CODE (*p) == COMPOUND_EXPR; p = &TREE_OPERAND (*p, 1))
1216 : : {
1217 : 24656 : TREE_SIDE_EFFECTS (*p) = 1;
1218 : 24656 : TREE_TYPE (*p) = void_type_node;
1219 : : }
1220 : : break;
1221 : :
1222 : 76 : case TRANSACTION_EXPR:
1223 : 76 : TREE_SIDE_EFFECTS (*p) = 1;
1224 : 76 : TREE_TYPE (*p) = void_type_node;
1225 : 76 : p = &TRANSACTION_EXPR_BODY (*p);
1226 : 76 : break;
1227 : :
1228 : 364477 : default:
1229 : : /* Assume that any tree upon which voidify_wrapper_expr is
1230 : : directly called is a wrapper, and that its body is op0. */
1231 : 364477 : if (p == &wrapper)
1232 : : {
1233 : 33 : TREE_SIDE_EFFECTS (*p) = 1;
1234 : 33 : TREE_TYPE (*p) = void_type_node;
1235 : 33 : p = &TREE_OPERAND (*p, 0);
1236 : 33 : break;
1237 : : }
1238 : 364444 : goto out;
1239 : : }
1240 : : }
1241 : :
1242 : 0 : out:
1243 : 364444 : if (p == NULL || IS_EMPTY_STMT (*p))
1244 : : temp = NULL_TREE;
1245 : 364444 : else if (temp)
1246 : : {
1247 : : /* The wrapper is on the RHS of an assignment that we're pushing
1248 : : down. */
1249 : 1717 : gcc_assert (TREE_CODE (temp) == INIT_EXPR
1250 : : || TREE_CODE (temp) == MODIFY_EXPR);
1251 : 1717 : TREE_OPERAND (temp, 1) = *p;
1252 : 1717 : *p = temp;
1253 : : }
1254 : : else
1255 : : {
1256 : 362727 : temp = create_tmp_var (type, "retval");
1257 : 362727 : *p = build2 (INIT_EXPR, type, temp, *p);
1258 : : }
1259 : :
1260 : 364444 : return temp;
1261 : : }
1262 : :
1263 : : return NULL_TREE;
1264 : : }
1265 : :
1266 : : /* Prepare calls to builtins to SAVE and RESTORE the stack as well as
1267 : : a temporary through which they communicate. */
1268 : :
1269 : : static void
1270 : 7814 : build_stack_save_restore (gcall **save, gcall **restore)
1271 : : {
1272 : 7814 : tree tmp_var;
1273 : :
1274 : 15628 : *save = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_SAVE), 0);
1275 : 7814 : tmp_var = create_tmp_var (ptr_type_node, "saved_stack");
1276 : 7814 : gimple_call_set_lhs (*save, tmp_var);
1277 : :
1278 : 7814 : *restore
1279 : 7814 : = gimple_build_call (builtin_decl_implicit (BUILT_IN_STACK_RESTORE),
1280 : : 1, tmp_var);
1281 : 7814 : }
1282 : :
1283 : : /* Generate IFN_ASAN_MARK call that poisons shadow memory of the DECL
1284 : : variable. */
1285 : :
1286 : : static tree
1287 : 428 : build_asan_poison_call_expr (tree decl)
1288 : : {
1289 : : /* Do not poison variables that have size equal to zero. */
1290 : 428 : tree unit_size = DECL_SIZE_UNIT (decl);
1291 : 428 : if (zerop (unit_size))
1292 : : return NULL_TREE;
1293 : :
1294 : 428 : tree base = build_fold_addr_expr (decl);
1295 : :
1296 : 428 : return build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_ASAN_MARK,
1297 : : void_type_node, 3,
1298 : : build_int_cst (integer_type_node,
1299 : : ASAN_MARK_POISON),
1300 : : base, unit_size);
1301 : : }
1302 : :
1303 : : /* Generate IFN_ASAN_MARK call that would poison or unpoison, depending
1304 : : on POISON flag, shadow memory of a DECL variable. The call will be
1305 : : put on location identified by IT iterator, where BEFORE flag drives
1306 : : position where the stmt will be put. */
1307 : :
1308 : : static void
1309 : 4725 : asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
1310 : : bool before)
1311 : : {
1312 : 4725 : tree unit_size = DECL_SIZE_UNIT (decl);
1313 : 4725 : tree base = build_fold_addr_expr (decl);
1314 : :
1315 : : /* Do not poison variables that have size equal to zero. */
1316 : 4725 : if (zerop (unit_size))
1317 : 4725 : return;
1318 : :
1319 : : /* It's necessary to have all stack variables aligned to ASAN granularity
1320 : : bytes. */
1321 : 4711 : gcc_assert (!hwasan_sanitize_p () || hwasan_sanitize_stack_p ());
1322 : 4711 : unsigned shadow_granularity
1323 : 4711 : = hwasan_sanitize_p () ? HWASAN_TAG_GRANULE_SIZE : ASAN_SHADOW_GRANULARITY;
1324 : 4711 : if (DECL_ALIGN_UNIT (decl) <= shadow_granularity)
1325 : 4509 : SET_DECL_ALIGN (decl, BITS_PER_UNIT * shadow_granularity);
1326 : :
1327 : 4711 : HOST_WIDE_INT flags = poison ? ASAN_MARK_POISON : ASAN_MARK_UNPOISON;
1328 : :
1329 : 4711 : gimple *g
1330 : 4711 : = gimple_build_call_internal (IFN_ASAN_MARK, 3,
1331 : 4711 : build_int_cst (integer_type_node, flags),
1332 : : base, unit_size);
1333 : :
1334 : 4711 : if (before)
1335 : 2426 : gsi_insert_before (it, g, GSI_NEW_STMT);
1336 : : else
1337 : 2285 : gsi_insert_after (it, g, GSI_NEW_STMT);
1338 : : }
1339 : :
1340 : : /* Generate IFN_ASAN_MARK internal call that depending on POISON flag
1341 : : either poisons or unpoisons a DECL. Created statement is appended
1342 : : to SEQ_P gimple sequence. */
1343 : :
1344 : : static void
1345 : 4297 : asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
1346 : : {
1347 : 4297 : gimple_stmt_iterator it = gsi_last (*seq_p);
1348 : 4297 : bool before = false;
1349 : :
1350 : 4297 : if (gsi_end_p (it))
1351 : 2218 : before = true;
1352 : :
1353 : 4297 : asan_poison_variable (decl, poison, &it, before);
1354 : 4297 : }
1355 : :
1356 : : /* Sort pair of VAR_DECLs A and B by DECL_UID. */
1357 : :
1358 : : static int
1359 : 135 : sort_by_decl_uid (const void *a, const void *b)
1360 : : {
1361 : 135 : const tree *t1 = (const tree *)a;
1362 : 135 : const tree *t2 = (const tree *)b;
1363 : :
1364 : 135 : int uid1 = DECL_UID (*t1);
1365 : 135 : int uid2 = DECL_UID (*t2);
1366 : :
1367 : 135 : if (uid1 < uid2)
1368 : : return -1;
1369 : 52 : else if (uid1 > uid2)
1370 : : return 1;
1371 : : else
1372 : 0 : return 0;
1373 : : }
1374 : :
1375 : : /* Generate IFN_ASAN_MARK internal call for all VARIABLES
1376 : : depending on POISON flag. Created statement is appended
1377 : : to SEQ_P gimple sequence. */
1378 : :
1379 : : static void
1380 : 1066035 : asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p)
1381 : : {
1382 : 1066035 : unsigned c = variables->elements ();
1383 : 1066035 : if (c == 0)
1384 : 1065859 : return;
1385 : :
1386 : 176 : auto_vec<tree> sorted_variables (c);
1387 : :
1388 : 176 : for (hash_set<tree>::iterator it = variables->begin ();
1389 : 570 : it != variables->end (); ++it)
1390 : 197 : sorted_variables.safe_push (*it);
1391 : :
1392 : 176 : sorted_variables.qsort (sort_by_decl_uid);
1393 : :
1394 : : unsigned i;
1395 : : tree var;
1396 : 549 : FOR_EACH_VEC_ELT (sorted_variables, i, var)
1397 : : {
1398 : 197 : asan_poison_variable (var, poison, seq_p);
1399 : :
1400 : : /* Add use_after_scope_memory attribute for the variable in order
1401 : : to prevent re-written into SSA. */
1402 : 197 : if (!lookup_attribute (ASAN_USE_AFTER_SCOPE_ATTRIBUTE,
1403 : 197 : DECL_ATTRIBUTES (var)))
1404 : 90 : DECL_ATTRIBUTES (var)
1405 : 180 : = tree_cons (get_identifier (ASAN_USE_AFTER_SCOPE_ATTRIBUTE),
1406 : : integer_one_node,
1407 : 90 : DECL_ATTRIBUTES (var));
1408 : : }
1409 : 176 : }
1410 : :
1411 : : /* Gimplify a BIND_EXPR. Just voidify and recurse. */
1412 : :
1413 : : static enum gimplify_status
1414 : 5989850 : gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
1415 : : {
1416 : 5989850 : tree bind_expr = *expr_p;
1417 : 5989850 : bool old_keep_stack = gimplify_ctxp->keep_stack;
1418 : 5989850 : bool old_save_stack = gimplify_ctxp->save_stack;
1419 : 5989850 : tree t;
1420 : 5989850 : gbind *bind_stmt;
1421 : 5989850 : gimple_seq body, cleanup;
1422 : 5989850 : gcall *stack_save;
1423 : 5989850 : location_t start_locus = 0, end_locus = 0;
1424 : 5989850 : tree ret_clauses = NULL;
1425 : :
1426 : 5989850 : tree temp = voidify_wrapper_expr (bind_expr, NULL);
1427 : :
1428 : : /* Mark variables seen in this bind expr. */
1429 : 12729358 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1430 : : {
1431 : 6739508 : if (VAR_P (t))
1432 : : {
1433 : 6085374 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
1434 : 6085374 : tree attr;
1435 : :
1436 : 6085374 : if (flag_openmp
1437 : 234307 : && !is_global_var (t)
1438 : 226405 : && !TREE_STATIC (t)
1439 : 226405 : && DECL_CONTEXT (t) == current_function_decl
1440 : 226405 : && TREE_USED (t)
1441 : 6310245 : && (attr = lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1442 : : != NULL_TREE)
1443 : : {
1444 : 74 : gcc_assert (!DECL_HAS_VALUE_EXPR_P (t));
1445 : 74 : tree alloc = TREE_PURPOSE (TREE_VALUE (attr));
1446 : 74 : tree align = TREE_VALUE (TREE_VALUE (attr));
1447 : : /* Allocate directives that appear in a target region must specify
1448 : : an allocator clause unless a requires directive with the
1449 : : dynamic_allocators clause is present in the same compilation
1450 : : unit. */
1451 : 74 : bool missing_dyn_alloc = false;
1452 : 74 : if (alloc == NULL_TREE
1453 : 48 : && ((omp_requires_mask & OMP_REQUIRES_DYNAMIC_ALLOCATORS)
1454 : : == 0))
1455 : : {
1456 : : /* This comes too early for omp_discover_declare_target...,
1457 : : but should at least catch the most common cases. */
1458 : 42 : missing_dyn_alloc
1459 : 42 : = cgraph_node::get (current_function_decl)->offloadable;
1460 : 42 : for (struct gimplify_omp_ctx *ctx2 = ctx;
1461 : 48 : ctx2 && !missing_dyn_alloc; ctx2 = ctx2->outer_context)
1462 : 6 : if (ctx2->code == OMP_TARGET)
1463 : 2 : missing_dyn_alloc = true;
1464 : : }
1465 : 42 : if (missing_dyn_alloc)
1466 : 4 : error_at (DECL_SOURCE_LOCATION (t),
1467 : : "%<allocate%> directive for %qD inside a target "
1468 : : "region must specify an %<allocator%> clause", t);
1469 : : /* Skip for omp_default_mem_alloc (= 1),
1470 : : unless align is present. For C/C++, there should be always a
1471 : : statement list following if TREE_USED, except for, e.g., using
1472 : : this decl in a static_assert; in that case, only a single
1473 : : DECL_EXPR remains, which can be skipped here. */
1474 : 70 : else if (!errorcount
1475 : 55 : && (align != NULL_TREE
1476 : 55 : || alloc == NULL_TREE
1477 : 10 : || !integer_onep (alloc))
1478 : 123 : && (lang_GNU_Fortran ()
1479 : 25 : || (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1480 : : != DECL_EXPR)))
1481 : : {
1482 : : /* Fortran might already use a pointer type internally;
1483 : : use that pointer except for type(C_ptr) and type(C_funptr);
1484 : : note that normal proc pointers are rejected. */
1485 : 53 : tree type = TREE_TYPE (t);
1486 : 53 : tree tmp, v;
1487 : 53 : if (lang_GNU_Fortran ()
1488 : 28 : && POINTER_TYPE_P (type)
1489 : 8 : && TREE_TYPE (type) != void_type_node
1490 : 59 : && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
1491 : : {
1492 : 6 : type = TREE_TYPE (type);
1493 : 6 : v = t;
1494 : : }
1495 : : else
1496 : : {
1497 : 47 : tmp = build_pointer_type (type);
1498 : 47 : v = create_tmp_var (tmp, get_name (t));
1499 : 47 : DECL_IGNORED_P (v) = 0;
1500 : 47 : DECL_ATTRIBUTES (v)
1501 : 47 : = tree_cons (get_identifier ("omp allocate var"),
1502 : : build_tree_list (NULL_TREE, t),
1503 : : remove_attribute ("omp allocate",
1504 : 47 : DECL_ATTRIBUTES (t)));
1505 : 47 : tmp = build_fold_indirect_ref (v);
1506 : 47 : TREE_THIS_NOTRAP (tmp) = 1;
1507 : 47 : SET_DECL_VALUE_EXPR (t, tmp);
1508 : 47 : DECL_HAS_VALUE_EXPR_P (t) = 1;
1509 : : }
1510 : 53 : tree sz = TYPE_SIZE_UNIT (type);
1511 : : /* The size to use in Fortran might not match TYPE_SIZE_UNIT;
1512 : : hence, for some decls, a size variable is saved in the
1513 : : attributes; use it, if available. */
1514 : 53 : if (TREE_CHAIN (TREE_VALUE (attr))
1515 : 28 : && TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))
1516 : 59 : && TREE_PURPOSE (
1517 : : TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)))))
1518 : : {
1519 : 6 : sz = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1520 : 6 : sz = TREE_PURPOSE (sz);
1521 : : }
1522 : 53 : if (alloc == NULL_TREE)
1523 : 36 : alloc = build_zero_cst (ptr_type_node);
1524 : 53 : if (align == NULL_TREE)
1525 : 42 : align = build_int_cst (size_type_node, DECL_ALIGN_UNIT (t));
1526 : : else
1527 : 11 : align = build_int_cst (size_type_node,
1528 : 11 : MAX (tree_to_uhwi (align),
1529 : : DECL_ALIGN_UNIT (t)));
1530 : 53 : location_t loc = DECL_SOURCE_LOCATION (t);
1531 : 53 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
1532 : 53 : tmp = build_call_expr_loc (loc, tmp, 3, align, sz, alloc);
1533 : 53 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1534 : 53 : fold_convert (TREE_TYPE (v), tmp));
1535 : 53 : gcc_assert (BIND_EXPR_BODY (bind_expr) != NULL_TREE);
1536 : : /* Ensure that either TREE_CHAIN (TREE_VALUE (attr) is set
1537 : : and GOMP_FREE added here or that DECL_HAS_VALUE_EXPR_P (t)
1538 : : is set, using in a condition much further below. */
1539 : 59 : gcc_assert (DECL_HAS_VALUE_EXPR_P (t)
1540 : : || TREE_CHAIN (TREE_VALUE (attr)));
1541 : 53 : if (TREE_CHAIN (TREE_VALUE (attr)))
1542 : : {
1543 : : /* Fortran is special as it does not have properly nest
1544 : : declarations in blocks. And as there is no
1545 : : initializer, there is also no expression to look for.
1546 : : Hence, the FE makes the statement list of the
1547 : : try-finally block available. We can put the GOMP_alloc
1548 : : at the top, unless an allocator or size expression
1549 : : requires to put it afterward; note that the size is
1550 : : always later in generated code; for strings, no
1551 : : size expr but still an expr might be available.
1552 : : As LTO does not handle a statement list, 'sl' has
1553 : : to be removed; done so by removing the attribute. */
1554 : 28 : DECL_ATTRIBUTES (t)
1555 : 28 : = remove_attribute ("omp allocate",
1556 : 28 : DECL_ATTRIBUTES (t));
1557 : 28 : tree sl = TREE_PURPOSE (TREE_CHAIN (TREE_VALUE (attr)));
1558 : 28 : tree_stmt_iterator e = tsi_start (sl);
1559 : 28 : tree needle = NULL_TREE;
1560 : 28 : if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1561 : : {
1562 : 6 : needle = TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr)));
1563 : 6 : needle = (TREE_VALUE (needle) ? TREE_VALUE (needle)
1564 : : : sz);
1565 : : }
1566 : 22 : else if (TREE_CHAIN (TREE_CHAIN (TREE_VALUE (attr))))
1567 : : needle = sz;
1568 : 22 : else if (DECL_P (alloc) && DECL_ARTIFICIAL (alloc))
1569 : : needle = alloc;
1570 : :
1571 : 10 : if (needle != NULL_TREE)
1572 : : {
1573 : 49 : while (!tsi_end_p (e))
1574 : : {
1575 : 49 : if (*e == needle
1576 : 49 : || (TREE_CODE (*e) == MODIFY_EXPR
1577 : 49 : && TREE_OPERAND (*e, 0) == needle))
1578 : : break;
1579 : 39 : ++e;
1580 : : }
1581 : 10 : gcc_assert (!tsi_end_p (e));
1582 : : }
1583 : 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1584 : :
1585 : : /* As the cleanup is in BIND_EXPR_BODY, GOMP_free is added
1586 : : here; for C/C++ it will be added in the 'cleanup'
1587 : : section after gimplification. But Fortran already has
1588 : : a try-finally block. */
1589 : 28 : sl = TREE_VALUE (TREE_CHAIN (TREE_VALUE (attr)));
1590 : 28 : e = tsi_last (sl);
1591 : 28 : tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1592 : 28 : tmp = build_call_expr_loc (EXPR_LOCATION (*e), tmp, 2, v,
1593 : : build_zero_cst (ptr_type_node));
1594 : 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1595 : 28 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1596 : 28 : tmp = fold_build2_loc (loc, MODIFY_EXPR, TREE_TYPE (v), v,
1597 : 28 : fold_convert (TREE_TYPE (v), tmp));
1598 : 28 : ++e;
1599 : 28 : tsi_link_after (&e, tmp, TSI_SAME_STMT);
1600 : : }
1601 : : else
1602 : : {
1603 : 25 : gcc_assert (TREE_CODE (BIND_EXPR_BODY (bind_expr))
1604 : : == STATEMENT_LIST);
1605 : 25 : tree_stmt_iterator e;
1606 : 25 : e = tsi_start (BIND_EXPR_BODY (bind_expr));
1607 : 113 : while (!tsi_end_p (e))
1608 : : {
1609 : 88 : if ((TREE_CODE (*e) == DECL_EXPR
1610 : 58 : && TREE_OPERAND (*e, 0) == t)
1611 : 121 : || (TREE_CODE (*e) == CLEANUP_POINT_EXPR
1612 : 0 : && (TREE_CODE (TREE_OPERAND (*e, 0))
1613 : : == DECL_EXPR)
1614 : 0 : && (TREE_OPERAND (TREE_OPERAND (*e, 0), 0)
1615 : : == t)))
1616 : : break;
1617 : 63 : ++e;
1618 : : }
1619 : 25 : gcc_assert (!tsi_end_p (e));
1620 : 25 : tsi_link_before (&e, tmp, TSI_SAME_STMT);
1621 : : }
1622 : : }
1623 : : }
1624 : :
1625 : : /* Mark variable as local. */
1626 : 6085374 : if (ctx && ctx->region_type != ORT_NONE && !DECL_EXTERNAL (t))
1627 : : {
1628 : 95611 : if (! DECL_SEEN_IN_BIND_EXPR_P (t)
1629 : 95611 : || splay_tree_lookup (ctx->variables,
1630 : : (splay_tree_key) t) == NULL)
1631 : : {
1632 : 95611 : int flag = GOVD_LOCAL;
1633 : 95611 : if (ctx->region_type == ORT_SIMD
1634 : 4374 : && TREE_ADDRESSABLE (t)
1635 : 81 : && !TREE_STATIC (t))
1636 : : {
1637 : 69 : if (TREE_CODE (DECL_SIZE_UNIT (t)) != INTEGER_CST)
1638 : 2 : ctx->add_safelen1 = true;
1639 : : else
1640 : : flag = GOVD_PRIVATE;
1641 : : }
1642 : 95611 : omp_add_variable (ctx, t, flag | GOVD_SEEN);
1643 : : }
1644 : : /* Static locals inside of target construct or offloaded
1645 : : routines need to be "omp declare target". */
1646 : 95611 : if (TREE_STATIC (t))
1647 : 1278 : for (; ctx; ctx = ctx->outer_context)
1648 : 1123 : if ((ctx->region_type & ORT_TARGET) != 0)
1649 : : {
1650 : 910 : if (!lookup_attribute ("omp declare target",
1651 : 910 : DECL_ATTRIBUTES (t)))
1652 : : {
1653 : 898 : tree id = get_identifier ("omp declare target");
1654 : 898 : DECL_ATTRIBUTES (t)
1655 : 898 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
1656 : 898 : varpool_node *node = varpool_node::get (t);
1657 : 898 : if (node)
1658 : : {
1659 : 33 : node->offloadable = 1;
1660 : 33 : if (ENABLE_OFFLOADING && !DECL_EXTERNAL (t))
1661 : : {
1662 : : g->have_offload = true;
1663 : : if (!in_lto_p)
1664 : : vec_safe_push (offload_vars, t);
1665 : : }
1666 : : }
1667 : : }
1668 : : break;
1669 : : }
1670 : : }
1671 : :
1672 : 6085374 : DECL_SEEN_IN_BIND_EXPR_P (t) = 1;
1673 : :
1674 : 6085374 : if (DECL_HARD_REGISTER (t) && !is_global_var (t) && cfun)
1675 : 1081 : cfun->has_local_explicit_reg_vars = true;
1676 : : }
1677 : : }
1678 : :
1679 : 11979700 : bind_stmt = gimple_build_bind (BIND_EXPR_VARS (bind_expr), NULL,
1680 : 5989850 : BIND_EXPR_BLOCK (bind_expr));
1681 : 5989850 : gimple_push_bind_expr (bind_stmt);
1682 : :
1683 : 5989850 : gimplify_ctxp->keep_stack = false;
1684 : 5989850 : gimplify_ctxp->save_stack = false;
1685 : :
1686 : : /* Gimplify the body into the GIMPLE_BIND tuple's body. */
1687 : 5989850 : body = NULL;
1688 : 5989850 : gimplify_stmt (&BIND_EXPR_BODY (bind_expr), &body);
1689 : 5989850 : gimple_bind_set_body (bind_stmt, body);
1690 : :
1691 : : /* Source location wise, the cleanup code (stack_restore and clobbers)
1692 : : belongs to the end of the block, so propagate what we have. The
1693 : : stack_save operation belongs to the beginning of block, which we can
1694 : : infer from the bind_expr directly if the block has no explicit
1695 : : assignment. */
1696 : 5989850 : if (BIND_EXPR_BLOCK (bind_expr))
1697 : : {
1698 : 5859474 : end_locus = BLOCK_SOURCE_END_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1699 : 5859474 : start_locus = BLOCK_SOURCE_LOCATION (BIND_EXPR_BLOCK (bind_expr));
1700 : : }
1701 : 5859474 : if (start_locus == 0)
1702 : 5989850 : start_locus = EXPR_LOCATION (bind_expr);
1703 : :
1704 : 5989850 : cleanup = NULL;
1705 : 5989850 : stack_save = NULL;
1706 : :
1707 : : /* Add clobbers for all variables that go out of scope. */
1708 : 12729358 : for (t = BIND_EXPR_VARS (bind_expr); t ; t = DECL_CHAIN (t))
1709 : : {
1710 : 6739508 : if (VAR_P (t)
1711 : 6085374 : && !is_global_var (t)
1712 : 12610405 : && DECL_CONTEXT (t) == current_function_decl)
1713 : : {
1714 : 5870897 : if (flag_openmp
1715 : 226398 : && DECL_HAS_VALUE_EXPR_P (t)
1716 : 1016 : && TREE_USED (t)
1717 : 5871897 : && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (t)))
1718 : : {
1719 : : /* For Fortran, TREE_CHAIN (TREE_VALUE (attr)) is set, which
1720 : : causes that the GOMP_free call is already added above;
1721 : : and "omp allocate" is removed from DECL_ATTRIBUTES. */
1722 : 25 : tree v = TREE_OPERAND (DECL_VALUE_EXPR (t), 0);
1723 : 25 : tree tmp = builtin_decl_explicit (BUILT_IN_GOMP_FREE);
1724 : 25 : tmp = build_call_expr_loc (end_locus, tmp, 2, v,
1725 : : build_zero_cst (ptr_type_node));
1726 : 25 : gimplify_and_add (tmp, &cleanup);
1727 : 25 : gimple *clobber_stmt;
1728 : 25 : tmp = build_clobber (TREE_TYPE (v), CLOBBER_STORAGE_END);
1729 : 25 : clobber_stmt = gimple_build_assign (v, tmp);
1730 : 25 : gimple_set_location (clobber_stmt, end_locus);
1731 : 25 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1732 : : }
1733 : 5870897 : if (!DECL_HARD_REGISTER (t)
1734 : 5869816 : && !TREE_THIS_VOLATILE (t)
1735 : 5830867 : && !DECL_HAS_VALUE_EXPR_P (t)
1736 : : /* Only care for variables that have to be in memory. Others
1737 : : will be rewritten into SSA names, hence moved to the
1738 : : top-level. */
1739 : 5727372 : && !is_gimple_reg (t)
1740 : 7107728 : && flag_stack_reuse != SR_NONE)
1741 : : {
1742 : 1233803 : tree clobber = build_clobber (TREE_TYPE (t), CLOBBER_STORAGE_END);
1743 : 1233803 : gimple *clobber_stmt;
1744 : 1233803 : clobber_stmt = gimple_build_assign (t, clobber);
1745 : 1233803 : gimple_set_location (clobber_stmt, end_locus);
1746 : 1233803 : gimplify_seq_add_stmt (&cleanup, clobber_stmt);
1747 : : }
1748 : :
1749 : 5870897 : if (flag_openacc && oacc_declare_returns != NULL)
1750 : : {
1751 : 207 : tree key = t;
1752 : 207 : if (DECL_HAS_VALUE_EXPR_P (key))
1753 : : {
1754 : 8 : key = DECL_VALUE_EXPR (key);
1755 : 8 : if (INDIRECT_REF_P (key))
1756 : 8 : key = TREE_OPERAND (key, 0);
1757 : : }
1758 : 207 : tree *c = oacc_declare_returns->get (key);
1759 : 207 : if (c != NULL)
1760 : : {
1761 : 116 : if (ret_clauses)
1762 : 64 : OMP_CLAUSE_CHAIN (*c) = ret_clauses;
1763 : :
1764 : 116 : ret_clauses = unshare_expr (*c);
1765 : :
1766 : 116 : oacc_declare_returns->remove (key);
1767 : :
1768 : 116 : if (oacc_declare_returns->is_empty ())
1769 : : {
1770 : 40 : delete oacc_declare_returns;
1771 : 40 : oacc_declare_returns = NULL;
1772 : : }
1773 : : }
1774 : : }
1775 : : }
1776 : :
1777 : 6739508 : if (asan_poisoned_variables != NULL
1778 : 6739508 : && asan_poisoned_variables->contains (t))
1779 : : {
1780 : 2050 : asan_poisoned_variables->remove (t);
1781 : 2050 : asan_poison_variable (t, true, &cleanup);
1782 : : }
1783 : :
1784 : 6739508 : if (gimplify_ctxp->live_switch_vars != NULL
1785 : 6739508 : && gimplify_ctxp->live_switch_vars->contains (t))
1786 : 55 : gimplify_ctxp->live_switch_vars->remove (t);
1787 : : }
1788 : :
1789 : : /* If the code both contains VLAs and calls alloca, then we cannot reclaim
1790 : : the stack space allocated to the VLAs. */
1791 : 5989850 : if (gimplify_ctxp->save_stack && !gimplify_ctxp->keep_stack)
1792 : : {
1793 : 7814 : gcall *stack_restore;
1794 : :
1795 : : /* Save stack on entry and restore it on exit. Add a try_finally
1796 : : block to achieve this. */
1797 : 7814 : build_stack_save_restore (&stack_save, &stack_restore);
1798 : :
1799 : 7814 : gimple_set_location (stack_save, start_locus);
1800 : 7814 : gimple_set_location (stack_restore, end_locus);
1801 : :
1802 : 7814 : gimplify_seq_add_stmt (&cleanup, stack_restore);
1803 : : }
1804 : :
1805 : 5989850 : if (ret_clauses)
1806 : : {
1807 : 52 : gomp_target *stmt;
1808 : 52 : gimple_stmt_iterator si = gsi_start (cleanup);
1809 : :
1810 : 52 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
1811 : : ret_clauses);
1812 : 52 : gsi_insert_seq_before_without_update (&si, stmt, GSI_NEW_STMT);
1813 : : }
1814 : :
1815 : 5989850 : if (cleanup)
1816 : : {
1817 : 752160 : gtry *gs;
1818 : 752160 : gimple_seq new_body;
1819 : :
1820 : 752160 : new_body = NULL;
1821 : 752160 : gs = gimple_build_try (gimple_bind_body (bind_stmt), cleanup,
1822 : : GIMPLE_TRY_FINALLY);
1823 : :
1824 : 752160 : if (stack_save)
1825 : 7814 : gimplify_seq_add_stmt (&new_body, stack_save);
1826 : 752160 : gimplify_seq_add_stmt (&new_body, gs);
1827 : 752160 : gimple_bind_set_body (bind_stmt, new_body);
1828 : : }
1829 : :
1830 : : /* keep_stack propagates all the way up to the outermost BIND_EXPR. */
1831 : 5989850 : if (!gimplify_ctxp->keep_stack)
1832 : 5973429 : gimplify_ctxp->keep_stack = old_keep_stack;
1833 : 5989850 : gimplify_ctxp->save_stack = old_save_stack;
1834 : :
1835 : 5989850 : gimple_pop_bind_expr ();
1836 : :
1837 : 5989850 : gimplify_seq_add_stmt (pre_p, bind_stmt);
1838 : :
1839 : 5989850 : if (temp)
1840 : : {
1841 : 1709 : *expr_p = temp;
1842 : 1709 : return GS_OK;
1843 : : }
1844 : :
1845 : 5988141 : *expr_p = NULL_TREE;
1846 : 5988141 : return GS_ALL_DONE;
1847 : : }
1848 : :
1849 : : /* Maybe add early return predict statement to PRE_P sequence. */
1850 : :
1851 : : static void
1852 : 2263957 : maybe_add_early_return_predict_stmt (gimple_seq *pre_p)
1853 : : {
1854 : : /* If we are not in a conditional context, add PREDICT statement. */
1855 : 2263957 : if (gimple_conditional_context ())
1856 : : {
1857 : 447621 : gimple *predict = gimple_build_predict (PRED_TREE_EARLY_RETURN,
1858 : : NOT_TAKEN);
1859 : 447621 : gimplify_seq_add_stmt (pre_p, predict);
1860 : : }
1861 : 2263957 : }
1862 : :
1863 : : /* Gimplify a RETURN_EXPR. If the expression to be returned is not a
1864 : : GIMPLE value, it is assigned to a new temporary and the statement is
1865 : : re-written to return the temporary.
1866 : :
1867 : : PRE_P points to the sequence where side effects that must happen before
1868 : : STMT should be stored. */
1869 : :
1870 : : static enum gimplify_status
1871 : 2263963 : gimplify_return_expr (tree stmt, gimple_seq *pre_p)
1872 : : {
1873 : 2263963 : greturn *ret;
1874 : 2263963 : tree ret_expr = TREE_OPERAND (stmt, 0);
1875 : 2263963 : tree result_decl, result;
1876 : :
1877 : 2263963 : if (ret_expr == error_mark_node)
1878 : : return GS_ERROR;
1879 : :
1880 : 2263957 : if (!ret_expr
1881 : 2172721 : || TREE_CODE (ret_expr) == RESULT_DECL)
1882 : : {
1883 : 105790 : maybe_add_early_return_predict_stmt (pre_p);
1884 : 105790 : greturn *ret = gimple_build_return (ret_expr);
1885 : 105790 : copy_warning (ret, stmt);
1886 : 105790 : gimplify_seq_add_stmt (pre_p, ret);
1887 : 105790 : return GS_ALL_DONE;
1888 : : }
1889 : :
1890 : 2158167 : if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
1891 : : result_decl = NULL_TREE;
1892 : 2157845 : else if (TREE_CODE (ret_expr) == COMPOUND_EXPR)
1893 : : {
1894 : : /* Used in C++ for handling EH cleanup of the return value if a local
1895 : : cleanup throws. Assume the front-end knows what it's doing. */
1896 : 5076 : result_decl = DECL_RESULT (current_function_decl);
1897 : : /* But crash if we end up trying to modify ret_expr below. */
1898 : 5076 : ret_expr = NULL_TREE;
1899 : : }
1900 : : else
1901 : : {
1902 : 2152769 : result_decl = TREE_OPERAND (ret_expr, 0);
1903 : :
1904 : : /* See through a return by reference. */
1905 : 2152769 : if (INDIRECT_REF_P (result_decl))
1906 : 44822 : result_decl = TREE_OPERAND (result_decl, 0);
1907 : :
1908 : 2152769 : gcc_assert ((TREE_CODE (ret_expr) == MODIFY_EXPR
1909 : : || TREE_CODE (ret_expr) == INIT_EXPR)
1910 : : && TREE_CODE (result_decl) == RESULT_DECL);
1911 : : }
1912 : :
1913 : : /* If aggregate_value_p is true, then we can return the bare RESULT_DECL.
1914 : : Recall that aggregate_value_p is FALSE for any aggregate type that is
1915 : : returned in registers. If we're returning values in registers, then
1916 : : we don't want to extend the lifetime of the RESULT_DECL, particularly
1917 : : across another call. In addition, for those aggregates for which
1918 : : hard_function_value generates a PARALLEL, we'll die during normal
1919 : : expansion of structure assignments; there's special code in expand_return
1920 : : to handle this case that does not exist in expand_expr. */
1921 : 5076 : if (!result_decl)
1922 : : result = NULL_TREE;
1923 : 2157845 : else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
1924 : : {
1925 : 183528 : if (!poly_int_tree_p (DECL_SIZE (result_decl)))
1926 : : {
1927 : 43 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
1928 : 0 : gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
1929 : : /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
1930 : : should be effectively allocated by the caller, i.e. all calls to
1931 : : this function must be subject to the Return Slot Optimization. */
1932 : 43 : gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
1933 : 43 : gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
1934 : : }
1935 : : result = result_decl;
1936 : : }
1937 : 1974317 : else if (gimplify_ctxp->return_temp)
1938 : : result = gimplify_ctxp->return_temp;
1939 : : else
1940 : : {
1941 : 1474653 : result = create_tmp_reg (TREE_TYPE (result_decl));
1942 : :
1943 : : /* ??? With complex control flow (usually involving abnormal edges),
1944 : : we can wind up warning about an uninitialized value for this. Due
1945 : : to how this variable is constructed and initialized, this is never
1946 : : true. Give up and never warn. */
1947 : 1474653 : suppress_warning (result, OPT_Wuninitialized);
1948 : :
1949 : 1474653 : gimplify_ctxp->return_temp = result;
1950 : : }
1951 : :
1952 : : /* Smash the lhs of the MODIFY_EXPR to the temporary we plan to use.
1953 : : Then gimplify the whole thing. */
1954 : 2158167 : if (result != result_decl)
1955 : 1974317 : TREE_OPERAND (ret_expr, 0) = result;
1956 : :
1957 : 2158167 : gimplify_and_add (TREE_OPERAND (stmt, 0), pre_p);
1958 : :
1959 : 2158167 : maybe_add_early_return_predict_stmt (pre_p);
1960 : 2158167 : ret = gimple_build_return (result);
1961 : 2158167 : copy_warning (ret, stmt);
1962 : 2158167 : gimplify_seq_add_stmt (pre_p, ret);
1963 : :
1964 : 2158167 : return GS_ALL_DONE;
1965 : : }
1966 : :
1967 : : /* Gimplify a variable-length array DECL. */
1968 : :
1969 : : static void
1970 : 8902 : gimplify_vla_decl (tree decl, gimple_seq *seq_p)
1971 : : {
1972 : : /* This is a variable-sized decl. Simplify its size and mark it
1973 : : for deferred expansion. */
1974 : 8902 : tree t, addr, ptr_type;
1975 : :
1976 : 8902 : gimplify_one_sizepos (&DECL_SIZE (decl), seq_p);
1977 : 8902 : gimplify_one_sizepos (&DECL_SIZE_UNIT (decl), seq_p);
1978 : :
1979 : : /* Don't mess with a DECL_VALUE_EXPR set by the front-end. */
1980 : 8902 : if (DECL_HAS_VALUE_EXPR_P (decl))
1981 : : return;
1982 : :
1983 : : /* All occurrences of this decl in final gimplified code will be
1984 : : replaced by indirection. Setting DECL_VALUE_EXPR does two
1985 : : things: First, it lets the rest of the gimplifier know what
1986 : : replacement to use. Second, it lets the debug info know
1987 : : where to find the value. */
1988 : 8897 : ptr_type = build_pointer_type (TREE_TYPE (decl));
1989 : 8897 : addr = create_tmp_var (ptr_type, get_name (decl));
1990 : 8897 : DECL_IGNORED_P (addr) = 0;
1991 : 8897 : t = build_fold_indirect_ref (addr);
1992 : 8897 : TREE_THIS_NOTRAP (t) = 1;
1993 : 8897 : SET_DECL_VALUE_EXPR (decl, t);
1994 : 8897 : DECL_HAS_VALUE_EXPR_P (decl) = 1;
1995 : :
1996 : 8897 : t = build_alloca_call_expr (DECL_SIZE_UNIT (decl), DECL_ALIGN (decl),
1997 : 8897 : max_int_size_in_bytes (TREE_TYPE (decl)));
1998 : : /* The call has been built for a variable-sized object. */
1999 : 8897 : CALL_ALLOCA_FOR_VAR_P (t) = 1;
2000 : 8897 : t = fold_convert (ptr_type, t);
2001 : 8897 : t = build2 (MODIFY_EXPR, TREE_TYPE (addr), addr, t);
2002 : :
2003 : 8897 : gimplify_and_add (t, seq_p);
2004 : :
2005 : : /* Record the dynamic allocation associated with DECL if requested. */
2006 : 8897 : if (flag_callgraph_info & CALLGRAPH_INFO_DYNAMIC_ALLOC)
2007 : 0 : record_dynamic_alloc (decl);
2008 : : }
2009 : :
2010 : : /* A helper function to be called via walk_tree. Mark all labels under *TP
2011 : : as being forced. To be called for DECL_INITIAL of static variables. */
2012 : :
2013 : : static tree
2014 : 869310 : force_labels_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
2015 : : {
2016 : 869310 : if (TYPE_P (*tp))
2017 : 0 : *walk_subtrees = 0;
2018 : 869310 : if (TREE_CODE (*tp) == LABEL_DECL)
2019 : : {
2020 : 926 : FORCED_LABEL (*tp) = 1;
2021 : 926 : cfun->has_forced_label_in_static = 1;
2022 : : }
2023 : :
2024 : 869310 : return NULL_TREE;
2025 : : }
2026 : :
2027 : : /* Generate an initialization to automatic variable DECL based on INIT_TYPE.
2028 : : Build a call to internal const function DEFERRED_INIT:
2029 : : 1st argument: SIZE of the DECL;
2030 : : 2nd argument: INIT_TYPE;
2031 : : 3rd argument: NAME of the DECL;
2032 : :
2033 : : as LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL). */
2034 : :
2035 : : static void
2036 : 169160 : gimple_add_init_for_auto_var (tree decl,
2037 : : enum auto_init_type init_type,
2038 : : gimple_seq *seq_p)
2039 : : {
2040 : 169160 : gcc_assert (auto_var_p (decl));
2041 : 169160 : gcc_assert (init_type > AUTO_INIT_UNINITIALIZED);
2042 : :
2043 : 169160 : const location_t loc = DECL_SOURCE_LOCATION (decl);
2044 : 169160 : tree decl_size = TYPE_SIZE_UNIT (TREE_TYPE (decl));
2045 : 169160 : tree init_type_node = build_int_cst (integer_type_node, (int) init_type);
2046 : 169160 : tree decl_name;
2047 : :
2048 : 169160 : if (DECL_NAME (decl))
2049 : 101139 : decl_name = build_string_literal (DECL_NAME (decl));
2050 : : else
2051 : : {
2052 : 68021 : char decl_name_anonymous[3 + (HOST_BITS_PER_INT + 2) / 3];
2053 : 68021 : sprintf (decl_name_anonymous, "D.%u", DECL_UID (decl));
2054 : 68021 : decl_name = build_string_literal (decl_name_anonymous);
2055 : : }
2056 : :
2057 : 169160 : tree call = build_call_expr_internal_loc (loc, IFN_DEFERRED_INIT,
2058 : 169160 : TREE_TYPE (decl), 3,
2059 : : decl_size, init_type_node,
2060 : : decl_name);
2061 : :
2062 : 169160 : gimplify_assign (decl, call, seq_p);
2063 : 169160 : }
2064 : :
2065 : : /* Generate padding initialization for automatic variable DECL.
2066 : : C guarantees that brace-init with fewer initializers than members
2067 : : aggregate will initialize the rest of the aggregate as-if it were
2068 : : static initialization. In turn static initialization guarantees
2069 : : that padding is initialized to zero. So, we always initialize paddings
2070 : : to zeroes regardless INIT_TYPE.
2071 : : To do the padding initialization, we insert a call to
2072 : : __builtin_clear_padding (&decl, 0, for_auto_init = true).
2073 : : Note, we add an additional dummy argument for __builtin_clear_padding,
2074 : : 'for_auto_init' to distinguish whether this call is for automatic
2075 : : variable initialization or not.
2076 : : */
2077 : : static void
2078 : 112 : gimple_add_padding_init_for_auto_var (tree decl, bool is_vla,
2079 : : gimple_seq *seq_p)
2080 : : {
2081 : 112 : tree addr_of_decl = NULL_TREE;
2082 : 112 : tree fn = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING);
2083 : :
2084 : 112 : if (is_vla)
2085 : : {
2086 : : /* The temporary address variable for this vla should be
2087 : : created in gimplify_vla_decl. */
2088 : 0 : gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
2089 : 0 : gcc_assert (INDIRECT_REF_P (DECL_VALUE_EXPR (decl)));
2090 : 0 : addr_of_decl = TREE_OPERAND (DECL_VALUE_EXPR (decl), 0);
2091 : : }
2092 : : else
2093 : : {
2094 : 112 : mark_addressable (decl);
2095 : 112 : addr_of_decl = build_fold_addr_expr (decl);
2096 : : }
2097 : :
2098 : 112 : gimple *call = gimple_build_call (fn, 2, addr_of_decl,
2099 : 112 : build_one_cst (TREE_TYPE (addr_of_decl)));
2100 : 112 : gimplify_seq_add_stmt (seq_p, call);
2101 : 112 : }
2102 : :
2103 : : /* Return true if the DECL need to be automaticly initialized by the
2104 : : compiler. */
2105 : : static bool
2106 : 4229172 : var_needs_auto_init_p (tree decl)
2107 : : {
2108 : 4229172 : if (auto_var_p (decl)
2109 : 4132476 : && (TREE_CODE (decl) != VAR_DECL || !DECL_HARD_REGISTER (decl))
2110 : 4131774 : && flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2111 : 314479 : && !lookup_attribute ("uninitialized", DECL_ATTRIBUTES (decl))
2112 : 314471 : && !lookup_attribute ("indeterminate", DECL_ATTRIBUTES (decl))
2113 : 314462 : && !OPAQUE_TYPE_P (TREE_TYPE (decl))
2114 : 4543634 : && !is_empty_type (TREE_TYPE (decl)))
2115 : : return true;
2116 : : return false;
2117 : : }
2118 : :
2119 : : /* Gimplify a DECL_EXPR node *STMT_P by making any necessary allocation
2120 : : and initialization explicit. */
2121 : :
2122 : : static enum gimplify_status
2123 : 6533668 : gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
2124 : : {
2125 : 6533668 : tree stmt = *stmt_p;
2126 : 6533668 : tree decl = DECL_EXPR_DECL (stmt);
2127 : :
2128 : 6533668 : *stmt_p = NULL_TREE;
2129 : :
2130 : 6533668 : if (TREE_TYPE (decl) == error_mark_node)
2131 : : return GS_ERROR;
2132 : :
2133 : 6533594 : if ((TREE_CODE (decl) == TYPE_DECL
2134 : 6490258 : || VAR_P (decl))
2135 : 13020812 : && !TYPE_SIZES_GIMPLIFIED (TREE_TYPE (decl)))
2136 : : {
2137 : 697494 : gimplify_type_sizes (TREE_TYPE (decl), seq_p);
2138 : 697494 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
2139 : 22700 : gimplify_type_sizes (TREE_TYPE (TREE_TYPE (decl)), seq_p);
2140 : : }
2141 : :
2142 : : /* ??? DECL_ORIGINAL_TYPE is streamed for LTO so it needs to be gimplified
2143 : : in case its size expressions contain problematic nodes like CALL_EXPR. */
2144 : 6533594 : if (TREE_CODE (decl) == TYPE_DECL
2145 : 43336 : && DECL_ORIGINAL_TYPE (decl)
2146 : 6538915 : && !TYPE_SIZES_GIMPLIFIED (DECL_ORIGINAL_TYPE (decl)))
2147 : : {
2148 : 0 : gimplify_type_sizes (DECL_ORIGINAL_TYPE (decl), seq_p);
2149 : 0 : if (TREE_CODE (DECL_ORIGINAL_TYPE (decl)) == REFERENCE_TYPE)
2150 : 0 : gimplify_type_sizes (TREE_TYPE (DECL_ORIGINAL_TYPE (decl)), seq_p);
2151 : : }
2152 : :
2153 : 6533594 : if (VAR_P (decl) && !DECL_EXTERNAL (decl))
2154 : : {
2155 : 6487218 : tree init = DECL_INITIAL (decl);
2156 : 6487218 : bool is_vla = false;
2157 : : /* Check whether a decl has FE created VALUE_EXPR here BEFORE
2158 : : gimplify_vla_decl creates VALUE_EXPR for a vla decl.
2159 : : If the decl has VALUE_EXPR that was created by FE (usually
2160 : : C++FE), it's a proxy varaible, and FE already initialized
2161 : : the VALUE_EXPR of it, we should not initialize it anymore. */
2162 : 6487218 : bool decl_had_value_expr_p = DECL_HAS_VALUE_EXPR_P (decl);
2163 : :
2164 : 6487218 : poly_uint64 size;
2165 : 6487218 : if (!poly_int_tree_p (DECL_SIZE_UNIT (decl), &size)
2166 : 6487218 : || (!TREE_STATIC (decl)
2167 : 6360843 : && flag_stack_check == GENERIC_STACK_CHECK
2168 : 234 : && maybe_gt (size,
2169 : : (unsigned HOST_WIDE_INT) STACK_CHECK_MAX_VAR_SIZE)))
2170 : : {
2171 : 8779 : gimplify_vla_decl (decl, seq_p);
2172 : 8779 : is_vla = true;
2173 : : }
2174 : :
2175 : 6487218 : if (asan_poisoned_variables
2176 : 4817 : && !is_vla
2177 : 4631 : && TREE_ADDRESSABLE (decl)
2178 : 2303 : && !TREE_STATIC (decl)
2179 : 2093 : && !DECL_HAS_VALUE_EXPR_P (decl)
2180 : 2058 : && DECL_ALIGN (decl) <= MAX_SUPPORTED_STACK_ALIGNMENT
2181 : 2058 : && dbg_cnt (asan_use_after_scope)
2182 : 2058 : && !gimplify_omp_ctxp
2183 : : /* GNAT introduces temporaries to hold return values of calls in
2184 : : initializers of variables defined in other units, so the
2185 : : declaration of the variable is discarded completely. We do not
2186 : : want to issue poison calls for such dropped variables. */
2187 : 6489268 : && (DECL_SEEN_IN_BIND_EXPR_P (decl)
2188 : 0 : || (DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)))
2189 : : {
2190 : 2050 : asan_poisoned_variables->add (decl);
2191 : 2050 : asan_poison_variable (decl, false, seq_p);
2192 : 2050 : if (!DECL_ARTIFICIAL (decl) && gimplify_ctxp->live_switch_vars)
2193 : 55 : gimplify_ctxp->live_switch_vars->add (decl);
2194 : : }
2195 : :
2196 : : /* Some front ends do not explicitly declare all anonymous
2197 : : artificial variables. We compensate here by declaring the
2198 : : variables, though it would be better if the front ends would
2199 : : explicitly declare them. */
2200 : 6487218 : if (!DECL_SEEN_IN_BIND_EXPR_P (decl)
2201 : 6487218 : && DECL_ARTIFICIAL (decl) && DECL_NAME (decl) == NULL_TREE)
2202 : 16831 : gimple_add_tmp_var (decl);
2203 : :
2204 : 6487218 : if (init && init != error_mark_node)
2205 : : {
2206 : 3693883 : if (!TREE_STATIC (decl))
2207 : : {
2208 : 3663783 : DECL_INITIAL (decl) = NULL_TREE;
2209 : 3663783 : init = build2 (INIT_EXPR, void_type_node, decl, init);
2210 : 3663783 : gimplify_and_add (init, seq_p);
2211 : 3663783 : ggc_free (init);
2212 : : /* Clear TREE_READONLY if we really have an initialization. */
2213 : 3663783 : if (!DECL_INITIAL (decl)
2214 : 3663783 : && !omp_privatize_by_reference (decl))
2215 : 3644860 : TREE_READONLY (decl) = 0;
2216 : : }
2217 : : else
2218 : : /* We must still examine initializers for static variables
2219 : : as they may contain a label address. */
2220 : 30100 : walk_tree (&init, force_labels_r, NULL, NULL);
2221 : : }
2222 : : /* When there is no explicit initializer, if the user requested,
2223 : : We should insert an artifical initializer for this automatic
2224 : : variable. */
2225 : 2793335 : else if (var_needs_auto_init_p (decl)
2226 : 2793335 : && !decl_had_value_expr_p)
2227 : : {
2228 : 106253 : gimple_add_init_for_auto_var (decl,
2229 : : flag_auto_var_init,
2230 : : seq_p);
2231 : : /* The expanding of a call to the above .DEFERRED_INIT will apply
2232 : : block initialization to the whole space covered by this variable.
2233 : : As a result, all the paddings will be initialized to zeroes
2234 : : for zero initialization and 0xFE byte-repeatable patterns for
2235 : : pattern initialization.
2236 : : In order to make the paddings as zeroes for pattern init, We
2237 : : should add a call to __builtin_clear_padding to clear the
2238 : : paddings to zero in compatiple with CLANG.
2239 : : We cannot insert this call if the variable is a gimple register
2240 : : since __builtin_clear_padding will take the address of the
2241 : : variable. As a result, if a long double/_Complex long double
2242 : : variable will spilled into stack later, its padding is 0XFE. */
2243 : 106253 : if (flag_auto_var_init == AUTO_INIT_PATTERN
2244 : 183 : && !is_gimple_reg (decl)
2245 : 106350 : && clear_padding_type_may_have_padding_p (TREE_TYPE (decl)))
2246 : 74 : gimple_add_padding_init_for_auto_var (decl, is_vla, seq_p);
2247 : : }
2248 : : }
2249 : :
2250 : : return GS_ALL_DONE;
2251 : : }
2252 : :
2253 : : /* Gimplify a LOOP_EXPR. Normally this just involves gimplifying the body
2254 : : and replacing the LOOP_EXPR with goto, but if the loop contains an
2255 : : EXIT_EXPR, we need to append a label for it to jump to. */
2256 : :
2257 : : static enum gimplify_status
2258 : 196194 : gimplify_loop_expr (tree *expr_p, gimple_seq *pre_p)
2259 : : {
2260 : 196194 : tree saved_label = gimplify_ctxp->exit_label;
2261 : 196194 : tree start_label = create_artificial_label (UNKNOWN_LOCATION);
2262 : :
2263 : 196194 : gimplify_seq_add_stmt (pre_p, gimple_build_label (start_label));
2264 : :
2265 : 196194 : gimplify_ctxp->exit_label = NULL_TREE;
2266 : :
2267 : 196194 : gimplify_and_add (LOOP_EXPR_BODY (*expr_p), pre_p);
2268 : :
2269 : 196194 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (start_label));
2270 : :
2271 : 196194 : if (gimplify_ctxp->exit_label)
2272 : 6194 : gimplify_seq_add_stmt (pre_p,
2273 : 3097 : gimple_build_label (gimplify_ctxp->exit_label));
2274 : :
2275 : 196194 : gimplify_ctxp->exit_label = saved_label;
2276 : :
2277 : 196194 : *expr_p = NULL;
2278 : 196194 : return GS_ALL_DONE;
2279 : : }
2280 : :
2281 : : /* Gimplify a statement list onto a sequence. These may be created either
2282 : : by an enlightened front-end, or by shortcut_cond_expr. */
2283 : :
2284 : : static enum gimplify_status
2285 : 8516084 : gimplify_statement_list (tree *expr_p, gimple_seq *pre_p)
2286 : : {
2287 : 8516084 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
2288 : :
2289 : 8516084 : tree_stmt_iterator i = tsi_start (*expr_p);
2290 : :
2291 : 54787710 : while (!tsi_end_p (i))
2292 : : {
2293 : 37755542 : gimplify_stmt (tsi_stmt_ptr (i), pre_p);
2294 : 37755542 : tsi_delink (&i);
2295 : : }
2296 : :
2297 : 8516084 : if (temp)
2298 : : {
2299 : 15268 : *expr_p = temp;
2300 : 15268 : return GS_OK;
2301 : : }
2302 : :
2303 : : return GS_ALL_DONE;
2304 : : }
2305 : :
2306 : :
2307 : : /* Emit warning for the unreachable statment STMT if needed.
2308 : : Return the gimple itself when the warning is emitted, otherwise
2309 : : return NULL. */
2310 : : static gimple *
2311 : 179 : emit_warn_switch_unreachable (gimple *stmt)
2312 : : {
2313 : 179 : if (gimple_code (stmt) == GIMPLE_GOTO
2314 : 48 : && TREE_CODE (gimple_goto_dest (stmt)) == LABEL_DECL
2315 : 227 : && DECL_ARTIFICIAL (gimple_goto_dest (stmt)))
2316 : : /* Don't warn for compiler-generated gotos. These occur
2317 : : in Duff's devices, for example. */
2318 : : return NULL;
2319 : : else
2320 : 131 : warning_at (gimple_location (stmt), OPT_Wswitch_unreachable,
2321 : : "statement will never be executed");
2322 : 131 : return stmt;
2323 : : }
2324 : :
2325 : : /* Callback for walk_gimple_seq. */
2326 : :
2327 : : static tree
2328 : 52600 : warn_switch_unreachable_and_auto_init_r (gimple_stmt_iterator *gsi_p,
2329 : : bool *handled_ops_p,
2330 : : struct walk_stmt_info *wi)
2331 : : {
2332 : 52600 : gimple *stmt = gsi_stmt (*gsi_p);
2333 : 52600 : bool unreachable_issued = wi->info != NULL;
2334 : :
2335 : 52600 : *handled_ops_p = true;
2336 : 52600 : switch (gimple_code (stmt))
2337 : : {
2338 : 139 : case GIMPLE_TRY:
2339 : : /* A compiler-generated cleanup or a user-written try block.
2340 : : If it's empty, don't dive into it--that would result in
2341 : : worse location info. */
2342 : 139 : if (gimple_try_eval (stmt) == NULL)
2343 : : {
2344 : 3 : if (warn_switch_unreachable && !unreachable_issued)
2345 : 3 : wi->info = emit_warn_switch_unreachable (stmt);
2346 : :
2347 : : /* Stop when auto var init warning is not on. */
2348 : 3 : if (!warn_trivial_auto_var_init)
2349 : 3 : return integer_zero_node;
2350 : : }
2351 : : /* Fall through. */
2352 : 3246 : case GIMPLE_BIND:
2353 : 3246 : case GIMPLE_CATCH:
2354 : 3246 : case GIMPLE_EH_FILTER:
2355 : 3246 : case GIMPLE_TRANSACTION:
2356 : : /* Walk the sub-statements. */
2357 : 3246 : *handled_ops_p = false;
2358 : 3246 : break;
2359 : :
2360 : : case GIMPLE_DEBUG:
2361 : : /* Ignore these. We may generate them before declarations that
2362 : : are never executed. If there's something to warn about,
2363 : : there will be non-debug stmts too, and we'll catch those. */
2364 : : break;
2365 : :
2366 : 60 : case GIMPLE_ASSIGN:
2367 : : /* See comment below in the GIMPLE_CALL case. */
2368 : 60 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2369 : 20 : && gimple_assign_single_p (stmt)
2370 : 79 : && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME)
2371 : : {
2372 : 6 : gimple *g = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
2373 : 6 : if (gimple_call_internal_p (g, IFN_DEFERRED_INIT))
2374 : : break;
2375 : : }
2376 : 54 : goto do_default;
2377 : :
2378 : 48217 : case GIMPLE_LABEL:
2379 : : /* Stop till the first Label. */
2380 : 48217 : return integer_zero_node;
2381 : 60 : case GIMPLE_CALL:
2382 : 60 : if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2383 : : {
2384 : 8 : *handled_ops_p = false;
2385 : 8 : break;
2386 : : }
2387 : : /* Don't warn for compiler-generated initializations for
2388 : : -ftrivial-auto-var-init for -Wswitch-unreachable. Though
2389 : : do warn for -Wtrivial-auto-var-init.
2390 : : There are 3 cases:
2391 : : case 1: a call to .DEFERRED_INIT;
2392 : : case 2: a call to __builtin_clear_padding with the 2nd argument is
2393 : : present and non-zero;
2394 : : case 3: a gimple assign store right after the call to .DEFERRED_INIT
2395 : : that has the LHS of .DEFERRED_INIT as the RHS as following:
2396 : : _1 = .DEFERRED_INIT (4, 2, &"i1"[0]);
2397 : : i1 = _1.
2398 : : case 3 is handled above in the GIMPLE_ASSIGN case. */
2399 : 52 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2400 : 52 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
2401 : : {
2402 : 31 : if (warn_trivial_auto_var_init)
2403 : : {
2404 : : /* Get the variable name from the 3rd argument of call. */
2405 : 12 : tree var_name = gimple_call_arg (stmt, 2);
2406 : 12 : var_name = TREE_OPERAND (TREE_OPERAND (var_name, 0), 0);
2407 : 12 : const char *var_name_str = TREE_STRING_POINTER (var_name);
2408 : :
2409 : 12 : warning_at (gimple_location (stmt), OPT_Wtrivial_auto_var_init,
2410 : : "%qs cannot be initialized with "
2411 : : "%<-ftrivial-auto-var_init%>", var_name_str);
2412 : : }
2413 : : break;
2414 : : }
2415 : 21 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2416 : 7 : && gimple_call_builtin_p (stmt, BUILT_IN_CLEAR_PADDING)
2417 : 24 : && (bool) TREE_INT_CST_LOW (gimple_call_arg (stmt, 1)))
2418 : : break;
2419 : : /* Fall through. */
2420 : 176 : default:
2421 : 176 : do_default:
2422 : : /* check the first "real" statement (not a decl/lexical scope/...), issue
2423 : : warning if needed. */
2424 : 176 : if (warn_switch_unreachable && !unreachable_issued)
2425 : 176 : wi->info = emit_warn_switch_unreachable (stmt);
2426 : : /* Stop when auto var init warning is not on. */
2427 : 176 : if (!warn_trivial_auto_var_init)
2428 : 176 : return integer_zero_node;
2429 : : break;
2430 : : }
2431 : : return NULL_TREE;
2432 : : }
2433 : :
2434 : :
2435 : : /* Possibly warn about unreachable statements between switch's controlling
2436 : : expression and the first case. Also warn about -ftrivial-auto-var-init
2437 : : cannot initialize the auto variable under such situation.
2438 : : SEQ is the body of a switch expression. */
2439 : :
2440 : : static void
2441 : 52188 : maybe_warn_switch_unreachable_and_auto_init (gimple_seq seq)
2442 : : {
2443 : 60 : if ((!warn_switch_unreachable && !warn_trivial_auto_var_init)
2444 : : /* This warning doesn't play well with Fortran when optimizations
2445 : : are on. */
2446 : 52128 : || lang_GNU_Fortran ()
2447 : 100756 : || seq == NULL)
2448 : 3789 : return;
2449 : :
2450 : 48399 : struct walk_stmt_info wi;
2451 : :
2452 : 48399 : memset (&wi, 0, sizeof (wi));
2453 : 48399 : walk_gimple_seq (seq, warn_switch_unreachable_and_auto_init_r, NULL, &wi);
2454 : : }
2455 : :
2456 : :
2457 : : /* A label entry that pairs label and a location. */
2458 : : struct label_entry
2459 : : {
2460 : : tree label;
2461 : : location_t loc;
2462 : : };
2463 : :
2464 : : /* Find LABEL in vector of label entries VEC. */
2465 : :
2466 : : static struct label_entry *
2467 : 11764 : find_label_entry (const auto_vec<struct label_entry> *vec, tree label)
2468 : : {
2469 : 11764 : unsigned int i;
2470 : 11764 : struct label_entry *l;
2471 : :
2472 : 22537 : FOR_EACH_VEC_ELT (*vec, i, l)
2473 : 19255 : if (l->label == label)
2474 : : return l;
2475 : : return NULL;
2476 : : }
2477 : :
2478 : : /* Return true if LABEL, a LABEL_DECL, represents a case label
2479 : : in a vector of labels CASES. */
2480 : :
2481 : : static bool
2482 : 15216 : case_label_p (const vec<tree> *cases, tree label)
2483 : : {
2484 : 15216 : unsigned int i;
2485 : 15216 : tree l;
2486 : :
2487 : 155978 : FOR_EACH_VEC_ELT (*cases, i, l)
2488 : 155652 : if (CASE_LABEL (l) == label)
2489 : : return true;
2490 : : return false;
2491 : : }
2492 : :
2493 : : /* Find the last nondebug statement in a scope STMT. */
2494 : :
2495 : : static gimple *
2496 : 2024 : last_stmt_in_scope (gimple *stmt)
2497 : : {
2498 : 3802 : if (!stmt)
2499 : : return NULL;
2500 : :
2501 : 6186 : auto last_stmt_in_seq = [] (gimple_seq s)
2502 : : {
2503 : 2395 : gimple_seq_node n;
2504 : 2395 : for (n = gimple_seq_last (s);
2505 : 2400 : n && (is_gimple_debug (n)
2506 : 2387 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2507 : 44 : && gimple_call_internal_p (n, IFN_DEFERRED_INIT)));
2508 : 5 : n = n->prev)
2509 : 7 : if (n == s)
2510 : : return (gimple *) NULL;
2511 : : return (gimple *) n;
2512 : : };
2513 : :
2514 : 3791 : switch (gimple_code (stmt))
2515 : : {
2516 : 1324 : case GIMPLE_BIND:
2517 : 1324 : {
2518 : 1324 : gbind *bind = as_a <gbind *> (stmt);
2519 : 1324 : stmt = last_stmt_in_seq (gimple_bind_body (bind));
2520 : 1324 : return last_stmt_in_scope (stmt);
2521 : : }
2522 : :
2523 : 617 : case GIMPLE_TRY:
2524 : 617 : {
2525 : 617 : gtry *try_stmt = as_a <gtry *> (stmt);
2526 : 617 : stmt = last_stmt_in_seq (gimple_try_eval (try_stmt));
2527 : 617 : gimple *last_eval = last_stmt_in_scope (stmt);
2528 : 617 : if (gimple_stmt_may_fallthru (last_eval)
2529 : 473 : && (last_eval == NULL
2530 : 470 : || !gimple_call_internal_p (last_eval, IFN_FALLTHROUGH))
2531 : 1083 : && gimple_try_kind (try_stmt) == GIMPLE_TRY_FINALLY)
2532 : : {
2533 : 454 : stmt = last_stmt_in_seq (gimple_try_cleanup (try_stmt));
2534 : 454 : return last_stmt_in_scope (stmt);
2535 : : }
2536 : : else
2537 : : return last_eval;
2538 : : }
2539 : :
2540 : 0 : case GIMPLE_DEBUG:
2541 : 0 : gcc_unreachable ();
2542 : :
2543 : : default:
2544 : : return stmt;
2545 : : }
2546 : : }
2547 : :
2548 : : /* Collect labels that may fall through into LABELS and return the statement
2549 : : preceding another case label, or a user-defined label. Store a location
2550 : : useful to give warnings at *PREVLOC (usually the location of the returned
2551 : : statement or of its surrounding scope). */
2552 : :
2553 : : static gimple *
2554 : 19610 : collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
2555 : : auto_vec <struct label_entry> *labels,
2556 : : location_t *prevloc)
2557 : : {
2558 : 19610 : gimple *prev = NULL;
2559 : :
2560 : 19610 : *prevloc = UNKNOWN_LOCATION;
2561 : 96204 : do
2562 : : {
2563 : 96204 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND)
2564 : : {
2565 : : /* Recognize the special GIMPLE_BIND added by gimplify_switch_expr,
2566 : : which starts on a GIMPLE_SWITCH and ends with a break label.
2567 : : Handle that as a single statement that can fall through. */
2568 : 1385 : gbind *bind = as_a <gbind *> (gsi_stmt (*gsi_p));
2569 : 1385 : gimple *first = gimple_seq_first_stmt (gimple_bind_body (bind));
2570 : 1385 : gimple *last = gimple_seq_last_stmt (gimple_bind_body (bind));
2571 : 1379 : if (last
2572 : 1379 : && gimple_code (first) == GIMPLE_SWITCH
2573 : 1481 : && gimple_code (last) == GIMPLE_LABEL)
2574 : : {
2575 : 102 : tree label = gimple_label_label (as_a <glabel *> (last));
2576 : 102 : if (SWITCH_BREAK_LABEL_P (label))
2577 : : {
2578 : 102 : prev = bind;
2579 : 102 : gsi_next (gsi_p);
2580 : 102 : continue;
2581 : : }
2582 : : }
2583 : : }
2584 : 96102 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_BIND
2585 : 96102 : || gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_TRY)
2586 : : {
2587 : : /* Nested scope. Only look at the last statement of
2588 : : the innermost scope. */
2589 : 1407 : location_t bind_loc = gimple_location (gsi_stmt (*gsi_p));
2590 : 1407 : gimple *last = last_stmt_in_scope (gsi_stmt (*gsi_p));
2591 : 1407 : if (last)
2592 : : {
2593 : 1399 : prev = last;
2594 : : /* It might be a label without a location. Use the
2595 : : location of the scope then. */
2596 : 1399 : if (!gimple_has_location (prev))
2597 : 616 : *prevloc = bind_loc;
2598 : : }
2599 : 1407 : gsi_next (gsi_p);
2600 : 1407 : continue;
2601 : 1407 : }
2602 : :
2603 : : /* Ifs are tricky. */
2604 : 94695 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_COND)
2605 : : {
2606 : 6953 : gcond *cond_stmt = as_a <gcond *> (gsi_stmt (*gsi_p));
2607 : 6953 : tree false_lab = gimple_cond_false_label (cond_stmt);
2608 : 6953 : location_t if_loc = gimple_location (cond_stmt);
2609 : :
2610 : : /* If we have e.g.
2611 : : if (i > 1) goto <D.2259>; else goto D;
2612 : : we can't do much with the else-branch. */
2613 : 6953 : if (!DECL_ARTIFICIAL (false_lab))
2614 : : break;
2615 : :
2616 : : /* Go on until the false label, then one step back. */
2617 : 53100 : for (; !gsi_end_p (*gsi_p); gsi_next (gsi_p))
2618 : : {
2619 : 53100 : gimple *stmt = gsi_stmt (*gsi_p);
2620 : 53100 : if (gimple_code (stmt) == GIMPLE_LABEL
2621 : 53100 : && gimple_label_label (as_a <glabel *> (stmt)) == false_lab)
2622 : : break;
2623 : : }
2624 : :
2625 : : /* Not found? Oops. */
2626 : 6953 : if (gsi_end_p (*gsi_p))
2627 : : break;
2628 : :
2629 : : /* A dead label can't fall through. */
2630 : 6953 : if (!UNUSED_LABEL_P (false_lab))
2631 : : {
2632 : 6906 : struct label_entry l = { false_lab, if_loc };
2633 : 6906 : labels->safe_push (l);
2634 : : }
2635 : :
2636 : : /* Go to the last statement of the then branch. */
2637 : 6953 : gsi_prev (gsi_p);
2638 : :
2639 : : /* if (i != 0) goto <D.1759>; else goto <D.1760>;
2640 : : <D.1759>:
2641 : : <stmt>;
2642 : : goto <D.1761>;
2643 : : <D.1760>:
2644 : : */
2645 : 6953 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2646 : 6953 : && !gimple_has_location (gsi_stmt (*gsi_p)))
2647 : : {
2648 : : /* Look at the statement before, it might be
2649 : : attribute fallthrough, in which case don't warn. */
2650 : 1435 : gsi_prev (gsi_p);
2651 : 1435 : bool fallthru_before_dest
2652 : 1435 : = gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_FALLTHROUGH);
2653 : 1435 : gsi_next (gsi_p);
2654 : 1435 : tree goto_dest = gimple_goto_dest (gsi_stmt (*gsi_p));
2655 : 1435 : if (!fallthru_before_dest)
2656 : : {
2657 : 1378 : struct label_entry l = { goto_dest, if_loc };
2658 : 1378 : labels->safe_push (l);
2659 : : }
2660 : : }
2661 : : /* This case is about
2662 : : if (1 != 0) goto <D.2022>; else goto <D.2023>;
2663 : : <D.2022>:
2664 : : n = n + 1; // #1
2665 : : <D.2023>: // #2
2666 : : <D.1988>: // #3
2667 : : where #2 is UNUSED_LABEL_P and we want to warn about #1 falling
2668 : : through to #3. So set PREV to #1. */
2669 : 5518 : else if (UNUSED_LABEL_P (false_lab))
2670 : 47 : prev = gsi_stmt (*gsi_p);
2671 : :
2672 : : /* And move back. */
2673 : 6953 : gsi_next (gsi_p);
2674 : : }
2675 : :
2676 : 94695 : tree lab;
2677 : : /* Remember the last statement. Skip labels that are of no interest
2678 : : to us. */
2679 : 94695 : if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2680 : : {
2681 : 11546 : tree label = gimple_label_label (as_a <glabel *> (gsi_stmt (*gsi_p)));
2682 : 11546 : if (find_label_entry (labels, label))
2683 : 70375 : prev = gsi_stmt (*gsi_p);
2684 : : }
2685 : 83149 : else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
2686 : : ;
2687 : 83149 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2688 : 83149 : && gimple_call_internal_p (gsi_stmt (*gsi_p),
2689 : : IFN_DEFERRED_INIT))
2690 : : ;
2691 : 83149 : else if (gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_PREDICT)
2692 : : ;
2693 : 81981 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2694 : 889 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_GOTO
2695 : 176 : && (lab = gimple_goto_dest (gsi_stmt (*gsi_p)))
2696 : 176 : && TREE_CODE (lab) == LABEL_DECL
2697 : 82156 : && VACUOUS_INIT_LABEL_P (lab))
2698 : : ;
2699 : 81981 : else if (!is_gimple_debug (gsi_stmt (*gsi_p)))
2700 : 70375 : prev = gsi_stmt (*gsi_p);
2701 : 94695 : gsi_next (gsi_p);
2702 : : }
2703 : 96204 : while (!gsi_end_p (*gsi_p)
2704 : : /* Stop if we find a case or a user-defined label. */
2705 : 192408 : && (gimple_code (gsi_stmt (*gsi_p)) != GIMPLE_LABEL
2706 : 20325 : || !gimple_has_location (gsi_stmt (*gsi_p))));
2707 : :
2708 : 19610 : if (prev && gimple_has_location (prev))
2709 : 19157 : *prevloc = gimple_location (prev);
2710 : 19610 : return prev;
2711 : : }
2712 : :
2713 : : /* Return true if the switch fallthough warning should occur. LABEL is
2714 : : the label statement that we're falling through to. */
2715 : :
2716 : : static bool
2717 : 15725 : should_warn_for_implicit_fallthrough (gimple_stmt_iterator *gsi_p, tree label)
2718 : : {
2719 : 15725 : gimple_stmt_iterator gsi = *gsi_p;
2720 : :
2721 : : /* Don't warn if the label is marked with a "falls through" comment. */
2722 : 15725 : if (FALLTHROUGH_LABEL_P (label))
2723 : : return false;
2724 : :
2725 : : /* Don't warn for non-case labels followed by a statement:
2726 : : case 0:
2727 : : foo ();
2728 : : label:
2729 : : bar ();
2730 : : as these are likely intentional. */
2731 : 14961 : if (!case_label_p (&gimplify_ctxp->case_labels, label))
2732 : : {
2733 : : tree l;
2734 : 326 : while (!gsi_end_p (gsi)
2735 : 326 : && ((gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2736 : 255 : && (l
2737 : 255 : = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi))))
2738 : 255 : && !case_label_p (&gimplify_ctxp->case_labels, l))
2739 : 149 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2740 : 31 : && gimple_call_internal_p (gsi_stmt (gsi),
2741 : : IFN_DEFERRED_INIT))))
2742 : 169 : gsi_next_nondebug (&gsi);
2743 : 157 : if (gsi_end_p (gsi) || gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
2744 : : return false;
2745 : : }
2746 : :
2747 : : /* Don't warn for terminated branches, i.e. when the subsequent case labels
2748 : : immediately breaks. */
2749 : 14890 : gsi = *gsi_p;
2750 : :
2751 : : /* Skip all immediately following labels. */
2752 : 33241 : while (!gsi_end_p (gsi)
2753 : 33241 : && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
2754 : 15025 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_PREDICT
2755 : 14824 : || (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2756 : 343 : && gimple_call_internal_p (gsi_stmt (gsi),
2757 : : IFN_DEFERRED_INIT))))
2758 : 18351 : gsi_next_nondebug (&gsi);
2759 : :
2760 : : /* { ... something; default:; } */
2761 : 14890 : if (gsi_end_p (gsi)
2762 : : /* { ... something; default: break; } or
2763 : : { ... something; default: goto L; } */
2764 : 14824 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
2765 : : /* { ... something; default: return; } */
2766 : 28627 : || gimple_code (gsi_stmt (gsi)) == GIMPLE_RETURN)
2767 : : return false;
2768 : :
2769 : : return true;
2770 : : }
2771 : :
2772 : : /* Callback for walk_gimple_seq. */
2773 : :
2774 : : static tree
2775 : 20470 : warn_implicit_fallthrough_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2776 : : struct walk_stmt_info *)
2777 : : {
2778 : 20470 : gimple *stmt = gsi_stmt (*gsi_p);
2779 : :
2780 : 20470 : *handled_ops_p = true;
2781 : 20470 : switch (gimple_code (stmt))
2782 : : {
2783 : 224 : case GIMPLE_TRY:
2784 : 224 : case GIMPLE_BIND:
2785 : 224 : case GIMPLE_CATCH:
2786 : 224 : case GIMPLE_EH_FILTER:
2787 : 224 : case GIMPLE_TRANSACTION:
2788 : : /* Walk the sub-statements. */
2789 : 224 : *handled_ops_p = false;
2790 : 224 : break;
2791 : :
2792 : : /* Find a sequence of form:
2793 : :
2794 : : GIMPLE_LABEL
2795 : : [...]
2796 : : <may fallthru stmt>
2797 : : GIMPLE_LABEL
2798 : :
2799 : : and possibly warn. */
2800 : : case GIMPLE_LABEL:
2801 : : {
2802 : : /* Found a label. Skip all immediately following labels. */
2803 : 46169 : while (!gsi_end_p (*gsi_p)
2804 : 46169 : && gimple_code (gsi_stmt (*gsi_p)) == GIMPLE_LABEL)
2805 : 26368 : gsi_next_nondebug (gsi_p);
2806 : :
2807 : : /* There might be no more statements. */
2808 : 19801 : if (gsi_end_p (*gsi_p))
2809 : 4069 : return integer_zero_node;
2810 : :
2811 : : /* Vector of labels that fall through. */
2812 : 19610 : auto_vec <struct label_entry> labels;
2813 : 19610 : location_t prevloc;
2814 : 19610 : gimple *prev = collect_fallthrough_labels (gsi_p, &labels, &prevloc);
2815 : :
2816 : : /* There might be no more statements. */
2817 : 19610 : if (gsi_end_p (*gsi_p))
2818 : 3878 : return integer_zero_node;
2819 : :
2820 : 15732 : gimple *next = gsi_stmt (*gsi_p);
2821 : 15732 : tree label;
2822 : : /* If what follows is a label, then we may have a fallthrough. */
2823 : 15732 : if (gimple_code (next) == GIMPLE_LABEL
2824 : 15732 : && gimple_has_location (next)
2825 : 15732 : && (label = gimple_label_label (as_a <glabel *> (next)))
2826 : 31464 : && prev != NULL)
2827 : : {
2828 : 15725 : struct label_entry *l;
2829 : 15725 : bool warned_p = false;
2830 : 15725 : auto_diagnostic_group d;
2831 : 15725 : if (!should_warn_for_implicit_fallthrough (gsi_p, label))
2832 : : /* Quiet. */;
2833 : 13710 : else if (gimple_code (prev) == GIMPLE_LABEL
2834 : 218 : && (label = gimple_label_label (as_a <glabel *> (prev)))
2835 : 13928 : && (l = find_label_entry (&labels, label)))
2836 : 198 : warned_p = warning_at (l->loc, OPT_Wimplicit_fallthrough_,
2837 : : "this statement may fall through");
2838 : 13512 : else if (!gimple_call_internal_p (prev, IFN_FALLTHROUGH)
2839 : : /* Try to be clever and don't warn when the statement
2840 : : can't actually fall through. */
2841 : 13111 : && gimple_stmt_may_fallthru (prev)
2842 : 13813 : && prevloc != UNKNOWN_LOCATION)
2843 : 301 : warned_p = warning_at (prevloc,
2844 : 301 : OPT_Wimplicit_fallthrough_,
2845 : : "this statement may fall through");
2846 : 499 : if (warned_p)
2847 : 499 : inform (gimple_location (next), "here");
2848 : :
2849 : : /* Mark this label as processed so as to prevent multiple
2850 : : warnings in nested switches. */
2851 : 15725 : FALLTHROUGH_LABEL_P (label) = true;
2852 : :
2853 : : /* So that next warn_implicit_fallthrough_r will start looking for
2854 : : a new sequence starting with this label. */
2855 : 15725 : gsi_prev (gsi_p);
2856 : 15725 : }
2857 : 3878 : }
2858 : 15732 : break;
2859 : : default:
2860 : : break;
2861 : : }
2862 : : return NULL_TREE;
2863 : : }
2864 : :
2865 : : /* Warn when a switch case falls through. */
2866 : :
2867 : : static void
2868 : 52188 : maybe_warn_implicit_fallthrough (gimple_seq seq)
2869 : : {
2870 : 52188 : if (!warn_implicit_fallthrough)
2871 : 48217 : return;
2872 : :
2873 : : /* This warning is meant for C/C++/ObjC/ObjC++ only. */
2874 : 3971 : if (!(lang_GNU_C ()
2875 : 1063 : || lang_GNU_CXX ()
2876 : 0 : || lang_GNU_OBJC ()))
2877 : : return;
2878 : :
2879 : 3971 : struct walk_stmt_info wi;
2880 : 3971 : memset (&wi, 0, sizeof (wi));
2881 : 3971 : walk_gimple_seq (seq, warn_implicit_fallthrough_r, NULL, &wi);
2882 : : }
2883 : :
2884 : : /* Callback for walk_gimple_seq. */
2885 : :
2886 : : static tree
2887 : 3379996 : expand_FALLTHROUGH_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
2888 : : struct walk_stmt_info *wi)
2889 : : {
2890 : 3379996 : gimple *stmt = gsi_stmt (*gsi_p);
2891 : :
2892 : 3379996 : *handled_ops_p = true;
2893 : 3379996 : switch (gimple_code (stmt))
2894 : : {
2895 : 155608 : case GIMPLE_TRY:
2896 : 155608 : case GIMPLE_BIND:
2897 : 155608 : case GIMPLE_CATCH:
2898 : 155608 : case GIMPLE_EH_FILTER:
2899 : 155608 : case GIMPLE_TRANSACTION:
2900 : : /* Walk the sub-statements. */
2901 : 155608 : *handled_ops_p = false;
2902 : 155608 : break;
2903 : 275103 : case GIMPLE_CALL:
2904 : 275103 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
2905 : 275103 : if (gimple_call_internal_p (stmt, IFN_FALLTHROUGH))
2906 : : {
2907 : 5551 : location_t loc = gimple_location (stmt);
2908 : 5551 : gsi_remove (gsi_p, true);
2909 : 5551 : wi->removed_stmt = true;
2910 : :
2911 : : /* nothrow flag is added by genericize_c_loop to mark fallthrough
2912 : : statement at the end of some loop's body. Those should be
2913 : : always diagnosed, either because they indeed don't precede
2914 : : a case label or default label, or because the next statement
2915 : : is not within the same iteration statement. */
2916 : 5551 : if ((stmt->subcode & GF_CALL_NOTHROW) != 0)
2917 : : {
2918 : 12 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
2919 : : "a case label or default label");
2920 : 12 : break;
2921 : : }
2922 : :
2923 : 5539 : if (gsi_end_p (*gsi_p))
2924 : : {
2925 : 32 : static_cast<location_t *>(wi->info)[0] = BUILTINS_LOCATION;
2926 : 32 : static_cast<location_t *>(wi->info)[1] = loc;
2927 : 32 : break;
2928 : : }
2929 : :
2930 : 5507 : bool found = false;
2931 : :
2932 : 5507 : gimple_stmt_iterator gsi2 = *gsi_p;
2933 : 5507 : stmt = gsi_stmt (gsi2);
2934 : 5507 : tree lab;
2935 : 5507 : if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2936 : 2586 : && gimple_code (stmt) == GIMPLE_GOTO
2937 : 20 : && (lab = gimple_goto_dest (stmt))
2938 : 20 : && TREE_CODE (lab) == LABEL_DECL
2939 : 5527 : && VACUOUS_INIT_LABEL_P (lab))
2940 : : {
2941 : : /* Handle for C++ artificial -ftrivial-auto-var-init=
2942 : : sequences. Those look like:
2943 : : goto lab1;
2944 : : lab2:;
2945 : : v1 = .DEFERRED_INIT (...);
2946 : : v2 = .DEFERRED_INIT (...);
2947 : : lab3:;
2948 : : v3 = .DEFERRED_INIT (...);
2949 : : lab1:;
2950 : : In this case, a case/default label can be either in between
2951 : : the GIMPLE_GOTO and the corresponding GIMPLE_LABEL, if jumps
2952 : : from the switch condition to the case/default label cross
2953 : : vacuous initialization of some variables, or after the
2954 : : corresponding GIMPLE_LABEL, if those jumps don't cross
2955 : : any such initialization but there is an adjacent named label
2956 : : which crosses such initialization. So, for the purpose of
2957 : : this function, just ignore the goto but until reaching the
2958 : : corresponding GIMPLE_LABEL allow also .DEFERRED_INIT
2959 : : calls. */
2960 : 5 : gsi_next (&gsi2);
2961 : : }
2962 : 5502 : else if (gimple_code (stmt) == GIMPLE_GOTO
2963 : 5502 : && !gimple_has_location (stmt))
2964 : : {
2965 : : /* Go on until the artificial label. */
2966 : 57 : tree goto_dest = gimple_goto_dest (stmt);
2967 : 414 : for (; !gsi_end_p (gsi2); gsi_next (&gsi2))
2968 : : {
2969 : 357 : if (gimple_code (gsi_stmt (gsi2)) == GIMPLE_LABEL
2970 : 357 : && gimple_label_label (as_a <glabel *> (gsi_stmt (gsi2)))
2971 : : == goto_dest)
2972 : : break;
2973 : : }
2974 : :
2975 : : /* Not found? Stop. */
2976 : 57 : if (gsi_end_p (gsi2))
2977 : : break;
2978 : :
2979 : : /* Look one past it. */
2980 : 57 : gsi_next (&gsi2);
2981 : : }
2982 : :
2983 : : /* We're looking for a case label or default label here. */
2984 : 5605 : while (!gsi_end_p (gsi2))
2985 : : {
2986 : 5605 : stmt = gsi_stmt (gsi2);
2987 : 5605 : if (gimple_code (stmt) == GIMPLE_LABEL)
2988 : : {
2989 : 5562 : tree label = gimple_label_label (as_a <glabel *> (stmt));
2990 : 5562 : if (gimple_has_location (stmt) && DECL_ARTIFICIAL (label))
2991 : : {
2992 : : found = true;
2993 : : break;
2994 : : }
2995 : : }
2996 : 43 : else if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
2997 : : ;
2998 : 43 : else if (flag_auto_var_init > AUTO_INIT_UNINITIALIZED
2999 : 43 : && gimple_call_internal_p (stmt, IFN_DEFERRED_INIT))
3000 : : ;
3001 : 43 : else if (!is_gimple_debug (stmt))
3002 : : /* Anything else is not expected. */
3003 : : break;
3004 : 98 : gsi_next (&gsi2);
3005 : : }
3006 : 5507 : if (!found)
3007 : 23 : pedwarn (loc, 0, "attribute %<fallthrough%> not preceding "
3008 : : "a case label or default label");
3009 : : }
3010 : : break;
3011 : 2949285 : default:
3012 : 2949285 : static_cast<location_t *>(wi->info)[0] = UNKNOWN_LOCATION;
3013 : 2949285 : break;
3014 : : }
3015 : 3379996 : return NULL_TREE;
3016 : : }
3017 : :
3018 : : /* Expand all FALLTHROUGH () calls in SEQ. */
3019 : :
3020 : : static void
3021 : 50867 : expand_FALLTHROUGH (gimple_seq *seq_p)
3022 : : {
3023 : 50867 : auto_urlify_attributes sentinel;
3024 : :
3025 : 50867 : struct walk_stmt_info wi;
3026 : 50867 : location_t loc[2];
3027 : 50867 : memset (&wi, 0, sizeof (wi));
3028 : 50867 : loc[0] = UNKNOWN_LOCATION;
3029 : 50867 : loc[1] = UNKNOWN_LOCATION;
3030 : 50867 : wi.info = (void *) &loc[0];
3031 : 50867 : walk_gimple_seq_mod (seq_p, expand_FALLTHROUGH_r, NULL, &wi);
3032 : 50867 : if (loc[0] != UNKNOWN_LOCATION)
3033 : : /* We've found [[fallthrough]]; at the end of a switch, which the C++
3034 : : standard says is ill-formed; see [dcl.attr.fallthrough]. */
3035 : 8 : pedwarn (loc[1], 0, "attribute %<fallthrough%> not preceding "
3036 : : "a case label or default label");
3037 : 50867 : }
3038 : :
3039 : :
3040 : : /* Gimplify a SWITCH_EXPR, and collect the vector of labels it can
3041 : : branch to. */
3042 : :
3043 : : static enum gimplify_status
3044 : 52188 : gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
3045 : : {
3046 : 52188 : tree switch_expr = *expr_p;
3047 : 52188 : gimple_seq switch_body_seq = NULL;
3048 : 52188 : enum gimplify_status ret;
3049 : 52188 : tree index_type = TREE_TYPE (switch_expr);
3050 : 52188 : if (index_type == NULL_TREE)
3051 : 11306 : index_type = TREE_TYPE (SWITCH_COND (switch_expr));
3052 : :
3053 : 52188 : ret = gimplify_expr (&SWITCH_COND (switch_expr), pre_p, NULL, is_gimple_val,
3054 : : fb_rvalue);
3055 : 52188 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
3056 : : return ret;
3057 : :
3058 : 52188 : if (SWITCH_BODY (switch_expr))
3059 : : {
3060 : 52188 : vec<tree> labels;
3061 : 52188 : vec<tree> saved_labels;
3062 : 52188 : hash_set<tree> *saved_live_switch_vars = NULL;
3063 : 52188 : tree default_case = NULL_TREE;
3064 : 52188 : gswitch *switch_stmt;
3065 : :
3066 : : /* Save old labels, get new ones from body, then restore the old
3067 : : labels. Save all the things from the switch body to append after. */
3068 : 52188 : saved_labels = gimplify_ctxp->case_labels;
3069 : 52188 : gimplify_ctxp->case_labels.create (8);
3070 : :
3071 : : /* Do not create live_switch_vars if SWITCH_BODY is not a BIND_EXPR. */
3072 : 52188 : saved_live_switch_vars = gimplify_ctxp->live_switch_vars;
3073 : 52188 : tree_code body_type = TREE_CODE (SWITCH_BODY (switch_expr));
3074 : 52188 : if (body_type == BIND_EXPR || body_type == STATEMENT_LIST)
3075 : 51906 : gimplify_ctxp->live_switch_vars = new hash_set<tree> (4);
3076 : : else
3077 : 282 : gimplify_ctxp->live_switch_vars = NULL;
3078 : :
3079 : 52188 : bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
3080 : 52188 : gimplify_ctxp->in_switch_expr = true;
3081 : :
3082 : 52188 : gimplify_stmt (&SWITCH_BODY (switch_expr), &switch_body_seq);
3083 : :
3084 : 52188 : gimplify_ctxp->in_switch_expr = old_in_switch_expr;
3085 : 52188 : maybe_warn_switch_unreachable_and_auto_init (switch_body_seq);
3086 : 52188 : maybe_warn_implicit_fallthrough (switch_body_seq);
3087 : : /* Only do this for the outermost GIMPLE_SWITCH. */
3088 : 52188 : if (!gimplify_ctxp->in_switch_expr)
3089 : 50867 : expand_FALLTHROUGH (&switch_body_seq);
3090 : :
3091 : 52188 : labels = gimplify_ctxp->case_labels;
3092 : 52188 : gimplify_ctxp->case_labels = saved_labels;
3093 : :
3094 : 52188 : if (gimplify_ctxp->live_switch_vars)
3095 : : {
3096 : 51906 : gcc_assert (gimplify_ctxp->live_switch_vars->is_empty ());
3097 : 51906 : delete gimplify_ctxp->live_switch_vars;
3098 : : }
3099 : 52188 : gimplify_ctxp->live_switch_vars = saved_live_switch_vars;
3100 : :
3101 : 52188 : preprocess_case_label_vec_for_gimple (labels, index_type,
3102 : : &default_case);
3103 : :
3104 : 52188 : bool add_bind = false;
3105 : 52188 : if (!default_case)
3106 : : {
3107 : 14673 : glabel *new_default;
3108 : :
3109 : 14673 : default_case
3110 : 14673 : = build_case_label (NULL_TREE, NULL_TREE,
3111 : : create_artificial_label (UNKNOWN_LOCATION));
3112 : 14673 : if (old_in_switch_expr)
3113 : : {
3114 : 762 : SWITCH_BREAK_LABEL_P (CASE_LABEL (default_case)) = 1;
3115 : 762 : add_bind = true;
3116 : : }
3117 : 14673 : new_default = gimple_build_label (CASE_LABEL (default_case));
3118 : 14673 : gimplify_seq_add_stmt (&switch_body_seq, new_default);
3119 : : }
3120 : 37515 : else if (old_in_switch_expr)
3121 : : {
3122 : 559 : gimple *last = gimple_seq_last_stmt (switch_body_seq);
3123 : 559 : if (last && gimple_code (last) == GIMPLE_LABEL)
3124 : : {
3125 : 302 : tree label = gimple_label_label (as_a <glabel *> (last));
3126 : 302 : if (SWITCH_BREAK_LABEL_P (label))
3127 : 52188 : add_bind = true;
3128 : : }
3129 : : }
3130 : :
3131 : 52188 : switch_stmt = gimple_build_switch (SWITCH_COND (switch_expr),
3132 : : default_case, labels);
3133 : 52188 : gimple_set_location (switch_stmt, EXPR_LOCATION (switch_expr));
3134 : : /* For the benefit of -Wimplicit-fallthrough, if switch_body_seq
3135 : : ends with a GIMPLE_LABEL holding SWITCH_BREAK_LABEL_P LABEL_DECL,
3136 : : wrap the GIMPLE_SWITCH up to that GIMPLE_LABEL into a GIMPLE_BIND,
3137 : : so that we can easily find the start and end of the switch
3138 : : statement. */
3139 : 52188 : if (add_bind)
3140 : : {
3141 : 1063 : gimple_seq bind_body = NULL;
3142 : 1063 : gimplify_seq_add_stmt (&bind_body, switch_stmt);
3143 : 1063 : gimple_seq_add_seq (&bind_body, switch_body_seq);
3144 : 1063 : gbind *bind = gimple_build_bind (NULL_TREE, bind_body, NULL_TREE);
3145 : 1063 : gimple_set_location (bind, EXPR_LOCATION (switch_expr));
3146 : 1063 : gimplify_seq_add_stmt (pre_p, bind);
3147 : : }
3148 : : else
3149 : : {
3150 : 51125 : gimplify_seq_add_stmt (pre_p, switch_stmt);
3151 : 51125 : gimplify_seq_add_seq (pre_p, switch_body_seq);
3152 : : }
3153 : 52188 : labels.release ();
3154 : : }
3155 : : else
3156 : 0 : gcc_unreachable ();
3157 : :
3158 : 52188 : return GS_ALL_DONE;
3159 : : }
3160 : :
3161 : : /* Gimplify the LABEL_EXPR pointed to by EXPR_P. */
3162 : :
3163 : : static enum gimplify_status
3164 : 2537957 : gimplify_label_expr (tree *expr_p, gimple_seq *pre_p)
3165 : : {
3166 : 2537957 : gcc_assert (decl_function_context (LABEL_EXPR_LABEL (*expr_p))
3167 : : == current_function_decl);
3168 : :
3169 : 2537957 : tree label = LABEL_EXPR_LABEL (*expr_p);
3170 : 2537957 : glabel *label_stmt = gimple_build_label (label);
3171 : 2537957 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3172 : 2537957 : gimplify_seq_add_stmt (pre_p, label_stmt);
3173 : :
3174 : 2537957 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3175 : 21 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3176 : : NOT_TAKEN));
3177 : 2537936 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3178 : 9 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3179 : : TAKEN));
3180 : :
3181 : 2537957 : return GS_ALL_DONE;
3182 : : }
3183 : :
3184 : : /* Gimplify the CASE_LABEL_EXPR pointed to by EXPR_P. */
3185 : :
3186 : : static enum gimplify_status
3187 : 1065416 : gimplify_case_label_expr (tree *expr_p, gimple_seq *pre_p)
3188 : : {
3189 : 1065416 : struct gimplify_ctx *ctxp;
3190 : 1065416 : glabel *label_stmt;
3191 : :
3192 : : /* Invalid programs can play Duff's Device type games with, for example,
3193 : : #pragma omp parallel. At least in the C front end, we don't
3194 : : detect such invalid branches until after gimplification, in the
3195 : : diagnose_omp_blocks pass. */
3196 : 1065426 : for (ctxp = gimplify_ctxp; ; ctxp = ctxp->prev_context)
3197 : 1065426 : if (ctxp->case_labels.exists ())
3198 : : break;
3199 : :
3200 : 1065416 : tree label = CASE_LABEL (*expr_p);
3201 : 1065416 : label_stmt = gimple_build_label (label);
3202 : 1065416 : gimple_set_location (label_stmt, EXPR_LOCATION (*expr_p));
3203 : 1065416 : ctxp->case_labels.safe_push (*expr_p);
3204 : 1065416 : gimplify_seq_add_stmt (pre_p, label_stmt);
3205 : :
3206 : 1065416 : if (lookup_attribute ("cold", DECL_ATTRIBUTES (label)))
3207 : 16 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_COLD_LABEL,
3208 : : NOT_TAKEN));
3209 : 1065400 : else if (lookup_attribute ("hot", DECL_ATTRIBUTES (label)))
3210 : 20 : gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_HOT_LABEL,
3211 : : TAKEN));
3212 : :
3213 : 1065416 : return GS_ALL_DONE;
3214 : : }
3215 : :
3216 : : /* Build a GOTO to the LABEL_DECL pointed to by LABEL_P, building it first
3217 : : if necessary. */
3218 : :
3219 : : tree
3220 : 1812803 : build_and_jump (tree *label_p)
3221 : : {
3222 : 1812803 : if (label_p == NULL)
3223 : : /* If there's nowhere to jump, just fall through. */
3224 : : return NULL_TREE;
3225 : :
3226 : 1227897 : if (*label_p == NULL_TREE)
3227 : : {
3228 : 705014 : tree label = create_artificial_label (UNKNOWN_LOCATION);
3229 : 705014 : *label_p = label;
3230 : : }
3231 : :
3232 : 1227897 : return build1 (GOTO_EXPR, void_type_node, *label_p);
3233 : : }
3234 : :
3235 : : /* Gimplify an EXIT_EXPR by converting to a GOTO_EXPR inside a COND_EXPR.
3236 : : This also involves building a label to jump to and communicating it to
3237 : : gimplify_loop_expr through gimplify_ctxp->exit_label. */
3238 : :
3239 : : static enum gimplify_status
3240 : 3097 : gimplify_exit_expr (tree *expr_p)
3241 : : {
3242 : 3097 : tree cond = TREE_OPERAND (*expr_p, 0);
3243 : 3097 : tree expr;
3244 : :
3245 : 3097 : expr = build_and_jump (&gimplify_ctxp->exit_label);
3246 : 3097 : expr = build3 (COND_EXPR, void_type_node, cond, expr, NULL_TREE);
3247 : 3097 : *expr_p = expr;
3248 : :
3249 : 3097 : return GS_OK;
3250 : : }
3251 : :
3252 : : /* *EXPR_P is a COMPONENT_REF being used as an rvalue. If its type is
3253 : : different from its canonical type, wrap the whole thing inside a
3254 : : NOP_EXPR and force the type of the COMPONENT_REF to be the canonical
3255 : : type.
3256 : :
3257 : : The canonical type of a COMPONENT_REF is the type of the field being
3258 : : referenced--unless the field is a bit-field which can be read directly
3259 : : in a smaller mode, in which case the canonical type is the
3260 : : sign-appropriate type corresponding to that mode. */
3261 : :
3262 : : static void
3263 : 18477207 : canonicalize_component_ref (tree *expr_p)
3264 : : {
3265 : 18477207 : tree expr = *expr_p;
3266 : 18477207 : tree type;
3267 : :
3268 : 18477207 : gcc_assert (TREE_CODE (expr) == COMPONENT_REF);
3269 : :
3270 : 18477207 : if (INTEGRAL_TYPE_P (TREE_TYPE (expr)))
3271 : 7397635 : type = TREE_TYPE (get_unwidened (expr, NULL_TREE));
3272 : : else
3273 : 11079572 : type = TREE_TYPE (TREE_OPERAND (expr, 1));
3274 : :
3275 : : /* One could argue that all the stuff below is not necessary for
3276 : : the non-bitfield case and declare it a FE error if type
3277 : : adjustment would be needed. */
3278 : 18477207 : if (TREE_TYPE (expr) != type)
3279 : : {
3280 : : #ifdef ENABLE_TYPES_CHECKING
3281 : 878673 : tree old_type = TREE_TYPE (expr);
3282 : : #endif
3283 : 878673 : int type_quals;
3284 : :
3285 : : /* We need to preserve qualifiers and propagate them from
3286 : : operand 0. */
3287 : 878673 : type_quals = TYPE_QUALS (type)
3288 : 878673 : | TYPE_QUALS (TREE_TYPE (TREE_OPERAND (expr, 0)));
3289 : 878673 : if (TYPE_QUALS (type) != type_quals)
3290 : 878388 : type = build_qualified_type (TYPE_MAIN_VARIANT (type), type_quals);
3291 : :
3292 : : /* Set the type of the COMPONENT_REF to the underlying type. */
3293 : 878673 : TREE_TYPE (expr) = type;
3294 : :
3295 : : #ifdef ENABLE_TYPES_CHECKING
3296 : : /* It is now a FE error, if the conversion from the canonical
3297 : : type to the original expression type is not useless. */
3298 : 878673 : gcc_assert (useless_type_conversion_p (old_type, type));
3299 : : #endif
3300 : : }
3301 : 18477207 : }
3302 : :
3303 : : /* If a NOP conversion is changing a pointer to array of foo to a pointer
3304 : : to foo, embed that change in the ADDR_EXPR by converting
3305 : : T array[U];
3306 : : (T *)&array
3307 : : ==>
3308 : : &array[L]
3309 : : where L is the lower bound. For simplicity, only do this for constant
3310 : : lower bound.
3311 : : The constraint is that the type of &array[L] is trivially convertible
3312 : : to T *. */
3313 : :
3314 : : static void
3315 : 522975 : canonicalize_addr_expr (tree *expr_p)
3316 : : {
3317 : 522975 : tree expr = *expr_p;
3318 : 522975 : tree addr_expr = TREE_OPERAND (expr, 0);
3319 : 522975 : tree datype, ddatype, pddatype;
3320 : :
3321 : : /* We simplify only conversions from an ADDR_EXPR to a pointer type. */
3322 : 1045604 : if (!POINTER_TYPE_P (TREE_TYPE (expr))
3323 : 522975 : || TREE_CODE (addr_expr) != ADDR_EXPR)
3324 : : return;
3325 : :
3326 : : /* The addr_expr type should be a pointer to an array. */
3327 : 346 : datype = TREE_TYPE (TREE_TYPE (addr_expr));
3328 : 346 : if (TREE_CODE (datype) != ARRAY_TYPE)
3329 : : return;
3330 : :
3331 : : /* The pointer to element type shall be trivially convertible to
3332 : : the expression pointer type. */
3333 : 28 : ddatype = TREE_TYPE (datype);
3334 : 28 : pddatype = build_pointer_type (ddatype);
3335 : 28 : if (!useless_type_conversion_p (TYPE_MAIN_VARIANT (TREE_TYPE (expr)),
3336 : : pddatype))
3337 : : return;
3338 : :
3339 : : /* The lower bound and element sizes must be constant. */
3340 : 0 : if (!TYPE_SIZE_UNIT (ddatype)
3341 : 0 : || TREE_CODE (TYPE_SIZE_UNIT (ddatype)) != INTEGER_CST
3342 : 0 : || !TYPE_DOMAIN (datype) || !TYPE_MIN_VALUE (TYPE_DOMAIN (datype))
3343 : 0 : || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (datype))) != INTEGER_CST)
3344 : : return;
3345 : :
3346 : : /* All checks succeeded. Build a new node to merge the cast. */
3347 : 0 : *expr_p = build4 (ARRAY_REF, ddatype, TREE_OPERAND (addr_expr, 0),
3348 : 0 : TYPE_MIN_VALUE (TYPE_DOMAIN (datype)),
3349 : : NULL_TREE, NULL_TREE);
3350 : 0 : *expr_p = build1 (ADDR_EXPR, pddatype, *expr_p);
3351 : :
3352 : : /* We can have stripped a required restrict qualifier above. */
3353 : 0 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
3354 : 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
3355 : : }
3356 : :
3357 : : /* *EXPR_P is a NOP_EXPR or CONVERT_EXPR. Remove it and/or other conversions
3358 : : underneath as appropriate. */
3359 : :
3360 : : static enum gimplify_status
3361 : 12737664 : gimplify_conversion (tree *expr_p)
3362 : : {
3363 : 12737664 : location_t loc = EXPR_LOCATION (*expr_p);
3364 : 12737664 : gcc_assert (CONVERT_EXPR_P (*expr_p));
3365 : :
3366 : : /* Then strip away all but the outermost conversion. */
3367 : 12737664 : STRIP_SIGN_NOPS (TREE_OPERAND (*expr_p, 0));
3368 : :
3369 : : /* And remove the outermost conversion if it's useless. */
3370 : 12737664 : if (tree_ssa_useless_type_conversion (*expr_p))
3371 : 0 : *expr_p = TREE_OPERAND (*expr_p, 0);
3372 : :
3373 : : /* If we still have a conversion at the toplevel,
3374 : : then canonicalize some constructs. */
3375 : 12737664 : if (CONVERT_EXPR_P (*expr_p))
3376 : : {
3377 : 12737664 : tree sub = TREE_OPERAND (*expr_p, 0);
3378 : :
3379 : : /* If a NOP conversion is changing the type of a COMPONENT_REF
3380 : : expression, then canonicalize its type now in order to expose more
3381 : : redundant conversions. */
3382 : 12737664 : if (TREE_CODE (sub) == COMPONENT_REF)
3383 : 271309 : canonicalize_component_ref (&TREE_OPERAND (*expr_p, 0));
3384 : :
3385 : : /* If a NOP conversion is changing a pointer to array of foo
3386 : : to a pointer to foo, embed that change in the ADDR_EXPR. */
3387 : 12466355 : else if (TREE_CODE (sub) == ADDR_EXPR)
3388 : 522975 : canonicalize_addr_expr (expr_p);
3389 : : }
3390 : :
3391 : : /* If we have a conversion to a non-register type force the
3392 : : use of a VIEW_CONVERT_EXPR instead. */
3393 : 12737664 : if (CONVERT_EXPR_P (*expr_p) && !is_gimple_reg_type (TREE_TYPE (*expr_p)))
3394 : 90 : *expr_p = fold_build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (*expr_p),
3395 : 90 : TREE_OPERAND (*expr_p, 0));
3396 : :
3397 : : /* Canonicalize CONVERT_EXPR to NOP_EXPR. */
3398 : 12737664 : if (TREE_CODE (*expr_p) == CONVERT_EXPR)
3399 : 233196 : TREE_SET_CODE (*expr_p, NOP_EXPR);
3400 : :
3401 : 12737664 : return GS_OK;
3402 : : }
3403 : :
3404 : : /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a
3405 : : DECL_VALUE_EXPR, and it's worth re-examining things. */
3406 : :
3407 : : static enum gimplify_status
3408 : 126698872 : gimplify_var_or_parm_decl (tree *expr_p)
3409 : : {
3410 : 126698872 : tree decl = *expr_p;
3411 : :
3412 : : /* ??? If this is a local variable, and it has not been seen in any
3413 : : outer BIND_EXPR, then it's probably the result of a duplicate
3414 : : declaration, for which we've already issued an error. It would
3415 : : be really nice if the front end wouldn't leak these at all.
3416 : : Currently the only known culprit is C++ destructors, as seen
3417 : : in g++.old-deja/g++.jason/binding.C.
3418 : : Another possible culpit are size expressions for variably modified
3419 : : types which are lost in the FE or not gimplified correctly. */
3420 : 126698872 : if (VAR_P (decl)
3421 : 98442675 : && !DECL_SEEN_IN_BIND_EXPR_P (decl)
3422 : 17037221 : && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
3423 : 126754112 : && decl_function_context (decl) == current_function_decl)
3424 : : {
3425 : 75 : gcc_assert (seen_error ());
3426 : : return GS_ERROR;
3427 : : }
3428 : :
3429 : : /* When within an OMP context, notice uses of variables. */
3430 : 126698797 : if (gimplify_omp_ctxp && omp_notice_variable (gimplify_omp_ctxp, decl, true))
3431 : : return GS_ALL_DONE;
3432 : :
3433 : : /* If the decl is an alias for another expression, substitute it now. */
3434 : 126693007 : if (DECL_HAS_VALUE_EXPR_P (decl))
3435 : : {
3436 : 439451 : *expr_p = unshare_expr (DECL_VALUE_EXPR (decl));
3437 : 439451 : return GS_OK;
3438 : : }
3439 : :
3440 : : return GS_ALL_DONE;
3441 : : }
3442 : :
3443 : : /* Recalculate the value of the TREE_SIDE_EFFECTS flag for T. */
3444 : :
3445 : : static void
3446 : 110590976 : recalculate_side_effects (tree t)
3447 : : {
3448 : 110590976 : enum tree_code code = TREE_CODE (t);
3449 : 110590976 : int len = TREE_OPERAND_LENGTH (t);
3450 : 110590976 : int i;
3451 : :
3452 : 110590976 : switch (TREE_CODE_CLASS (code))
3453 : : {
3454 : 667627 : case tcc_expression:
3455 : 667627 : switch (code)
3456 : : {
3457 : : case INIT_EXPR:
3458 : : case MODIFY_EXPR:
3459 : : case VA_ARG_EXPR:
3460 : : case PREDECREMENT_EXPR:
3461 : : case PREINCREMENT_EXPR:
3462 : : case POSTDECREMENT_EXPR:
3463 : : case POSTINCREMENT_EXPR:
3464 : : /* All of these have side-effects, no matter what their
3465 : : operands are. */
3466 : : return;
3467 : :
3468 : : default:
3469 : : break;
3470 : : }
3471 : : /* Fall through. */
3472 : :
3473 : 110590974 : case tcc_comparison: /* a comparison expression */
3474 : 110590974 : case tcc_unary: /* a unary arithmetic expression */
3475 : 110590974 : case tcc_binary: /* a binary arithmetic expression */
3476 : 110590974 : case tcc_reference: /* a reference */
3477 : 110590974 : case tcc_vl_exp: /* a function call */
3478 : 110590974 : TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
3479 : 360059761 : for (i = 0; i < len; ++i)
3480 : : {
3481 : 249468787 : tree op = TREE_OPERAND (t, i);
3482 : 249468787 : if (op && TREE_SIDE_EFFECTS (op))
3483 : 1297709 : TREE_SIDE_EFFECTS (t) = 1;
3484 : : }
3485 : : break;
3486 : :
3487 : : case tcc_constant:
3488 : : /* No side-effects. */
3489 : : return;
3490 : :
3491 : 2 : default:
3492 : 2 : if (code == SSA_NAME)
3493 : : /* No side-effects. */
3494 : : return;
3495 : 0 : gcc_unreachable ();
3496 : : }
3497 : : }
3498 : :
3499 : : /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR
3500 : : node *EXPR_P.
3501 : :
3502 : : compound_lval
3503 : : : min_lval '[' val ']'
3504 : : | min_lval '.' ID
3505 : : | compound_lval '[' val ']'
3506 : : | compound_lval '.' ID
3507 : :
3508 : : This is not part of the original SIMPLE definition, which separates
3509 : : array and member references, but it seems reasonable to handle them
3510 : : together. Also, this way we don't run into problems with union
3511 : : aliasing; gcc requires that for accesses through a union to alias, the
3512 : : union reference must be explicit, which was not always the case when we
3513 : : were splitting up array and member refs.
3514 : :
3515 : : PRE_P points to the sequence where side effects that must happen before
3516 : : *EXPR_P should be stored.
3517 : :
3518 : : POST_P points to the sequence where side effects that must happen after
3519 : : *EXPR_P should be stored. */
3520 : :
3521 : : static enum gimplify_status
3522 : 29986119 : gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3523 : : fallback_t fallback)
3524 : : {
3525 : 29986119 : tree *p;
3526 : 29986119 : enum gimplify_status ret = GS_ALL_DONE, tret;
3527 : 29986119 : int i;
3528 : 29986119 : location_t loc = EXPR_LOCATION (*expr_p);
3529 : 29986119 : tree expr = *expr_p;
3530 : :
3531 : : /* Create a stack of the subexpressions so later we can walk them in
3532 : : order from inner to outer. */
3533 : 29986119 : auto_vec<tree, 10> expr_stack;
3534 : :
3535 : : /* We can handle anything that get_inner_reference can deal with. */
3536 : 72147035 : for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
3537 : : {
3538 : 42160916 : restart:
3539 : : /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
3540 : 72206215 : if (TREE_CODE (*p) == INDIRECT_REF)
3541 : 3983552 : *p = fold_indirect_ref_loc (loc, *p);
3542 : :
3543 : 72206215 : if (handled_component_p (*p))
3544 : : ;
3545 : : /* Expand DECL_VALUE_EXPR now. In some cases that may expose
3546 : : additional COMPONENT_REFs. */
3547 : 13470320 : else if ((VAR_P (*p) || TREE_CODE (*p) == PARM_DECL)
3548 : 31496540 : && gimplify_var_or_parm_decl (p) == GS_OK)
3549 : 59180 : goto restart;
3550 : : else
3551 : : break;
3552 : :
3553 : 42160916 : expr_stack.safe_push (*p);
3554 : : }
3555 : :
3556 : 29986119 : gcc_assert (expr_stack.length ());
3557 : :
3558 : : /* Now EXPR_STACK is a stack of pointers to all the refs we've
3559 : : walked through and P points to the innermost expression.
3560 : :
3561 : : Java requires that we elaborated nodes in source order. That
3562 : : means we must gimplify the inner expression followed by each of
3563 : : the indices, in order. But we can't gimplify the inner
3564 : : expression until we deal with any variable bounds, sizes, or
3565 : : positions in order to deal with PLACEHOLDER_EXPRs.
3566 : :
3567 : : The base expression may contain a statement expression that
3568 : : has declarations used in size expressions, so has to be
3569 : : gimplified before gimplifying the size expressions.
3570 : :
3571 : : So we do this in three steps. First we deal with variable
3572 : : bounds, sizes, and positions, then we gimplify the base and
3573 : : ensure it is memory if needed, then we deal with the annotations
3574 : : for any variables in the components and any indices, from left
3575 : : to right. */
3576 : :
3577 : 29986119 : bool need_non_reg = false;
3578 : 72147032 : for (i = expr_stack.length () - 1; i >= 0; i--)
3579 : : {
3580 : 42160916 : tree t = expr_stack[i];
3581 : :
3582 : 42160916 : if (error_operand_p (TREE_OPERAND (t, 0)))
3583 : : return GS_ERROR;
3584 : :
3585 : 42160913 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3586 : : {
3587 : : /* Deal with the low bound and element type size and put them into
3588 : : the ARRAY_REF. If these values are set, they have already been
3589 : : gimplified. */
3590 : 8879865 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3591 : : {
3592 : 8815813 : tree low = unshare_expr (array_ref_low_bound (t));
3593 : 8815813 : if (!is_gimple_min_invariant (low))
3594 : : {
3595 : 0 : TREE_OPERAND (t, 2) = low;
3596 : : }
3597 : : }
3598 : :
3599 : 8879865 : if (TREE_OPERAND (t, 3) == NULL_TREE)
3600 : : {
3601 : 8862790 : tree elmt_size = array_ref_element_size (t);
3602 : 8862790 : if (!is_gimple_min_invariant (elmt_size))
3603 : : {
3604 : 8431 : elmt_size = unshare_expr (elmt_size);
3605 : 8431 : tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)));
3606 : 8431 : tree factor = size_int (TYPE_ALIGN_UNIT (elmt_type));
3607 : :
3608 : : /* Divide the element size by the alignment of the element
3609 : : type (above). */
3610 : 8431 : elmt_size = size_binop_loc (loc, EXACT_DIV_EXPR,
3611 : : elmt_size, factor);
3612 : :
3613 : 8431 : TREE_OPERAND (t, 3) = elmt_size;
3614 : : }
3615 : : }
3616 : : need_non_reg = true;
3617 : : }
3618 : 33281048 : else if (TREE_CODE (t) == COMPONENT_REF)
3619 : : {
3620 : : /* Set the field offset into T and gimplify it. */
3621 : 31993938 : if (TREE_OPERAND (t, 2) == NULL_TREE)
3622 : : {
3623 : 31993559 : tree offset = component_ref_field_offset (t);
3624 : 31993559 : if (!is_gimple_min_invariant (offset))
3625 : : {
3626 : 287 : offset = unshare_expr (offset);
3627 : 287 : tree field = TREE_OPERAND (t, 1);
3628 : 287 : tree factor
3629 : 287 : = size_int (DECL_OFFSET_ALIGN (field) / BITS_PER_UNIT);
3630 : :
3631 : : /* Divide the offset by its alignment. */
3632 : 287 : offset = size_binop_loc (loc, EXACT_DIV_EXPR,
3633 : : offset, factor);
3634 : :
3635 : 287 : TREE_OPERAND (t, 2) = offset;
3636 : : }
3637 : : }
3638 : : need_non_reg = true;
3639 : : }
3640 : 1287110 : else if (!is_gimple_reg_type (TREE_TYPE (t)))
3641 : : /* When the result of an operation, in particular a VIEW_CONVERT_EXPR
3642 : : is a non-register type then require the base object to be a
3643 : : non-register as well. */
3644 : 41151358 : need_non_reg = true;
3645 : : }
3646 : :
3647 : : /* Step 2 is to gimplify the base expression. Make sure lvalue is set
3648 : : so as to match the min_lval predicate. Failure to do so may result
3649 : : in the creation of large aggregate temporaries. */
3650 : 29986116 : tret = gimplify_expr (p, pre_p, post_p, is_gimple_min_lval,
3651 : : fallback | fb_lvalue);
3652 : 29986116 : ret = MIN (ret, tret);
3653 : 29986116 : if (ret == GS_ERROR)
3654 : : return GS_ERROR;
3655 : :
3656 : : /* Step 2a: if we have component references we do not support on
3657 : : registers then make sure the base isn't a register. Of course
3658 : : we can only do so if an rvalue is OK. */
3659 : 29986116 : if (need_non_reg && (fallback & fb_rvalue))
3660 : 22400932 : prepare_gimple_addressable (p, pre_p);
3661 : :
3662 : :
3663 : : /* Step 3: gimplify size expressions and the indices and operands of
3664 : : ARRAY_REF. During this loop we also remove any useless conversions.
3665 : : If we operate on a register also make sure to properly gimplify
3666 : : to individual operations. */
3667 : :
3668 : 29986116 : bool reg_operations = is_gimple_reg (*p);
3669 : 72147029 : for (; expr_stack.length () > 0; )
3670 : : {
3671 : 42160913 : tree t = expr_stack.pop ();
3672 : :
3673 : 42160913 : if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
3674 : : {
3675 : 8879865 : gcc_assert (!reg_operations);
3676 : :
3677 : : /* Gimplify the low bound and element type size. */
3678 : 8879865 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3679 : : is_gimple_reg, fb_rvalue);
3680 : 8879865 : ret = MIN (ret, tret);
3681 : :
3682 : 8879865 : tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
3683 : : is_gimple_reg, fb_rvalue);
3684 : 8879865 : ret = MIN (ret, tret);
3685 : :
3686 : : /* Gimplify the dimension. */
3687 : 8879865 : tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
3688 : : is_gimple_val, fb_rvalue);
3689 : 8879865 : ret = MIN (ret, tret);
3690 : : }
3691 : 33281048 : else if (TREE_CODE (t) == COMPONENT_REF)
3692 : : {
3693 : 31993938 : gcc_assert (!reg_operations);
3694 : :
3695 : 31993938 : tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
3696 : : is_gimple_reg, fb_rvalue);
3697 : 31993938 : ret = MIN (ret, tret);
3698 : : }
3699 : 1287110 : else if (reg_operations)
3700 : : {
3701 : 751945 : tret = gimplify_expr (&TREE_OPERAND (t, 0), pre_p, post_p,
3702 : : is_gimple_val, fb_rvalue);
3703 : 1287110 : ret = MIN (ret, tret);
3704 : : }
3705 : :
3706 : 42160913 : STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
3707 : :
3708 : : /* The innermost expression P may have originally had
3709 : : TREE_SIDE_EFFECTS set which would have caused all the outer
3710 : : expressions in *EXPR_P leading to P to also have had
3711 : : TREE_SIDE_EFFECTS set. */
3712 : 42160913 : recalculate_side_effects (t);
3713 : : }
3714 : :
3715 : : /* If the outermost expression is a COMPONENT_REF, canonicalize its type. */
3716 : 29986116 : if ((fallback & fb_rvalue) && TREE_CODE (*expr_p) == COMPONENT_REF)
3717 : : {
3718 : 18205898 : canonicalize_component_ref (expr_p);
3719 : : }
3720 : :
3721 : 29986116 : expr_stack.release ();
3722 : :
3723 : 29986116 : gcc_assert (*expr_p == expr || ret != GS_ALL_DONE);
3724 : :
3725 : : return ret;
3726 : 29986119 : }
3727 : :
3728 : : /* Gimplify the self modifying expression pointed to by EXPR_P
3729 : : (++, --, +=, -=).
3730 : :
3731 : : PRE_P points to the list where side effects that must happen before
3732 : : *EXPR_P should be stored.
3733 : :
3734 : : POST_P points to the list where side effects that must happen after
3735 : : *EXPR_P should be stored.
3736 : :
3737 : : WANT_VALUE is nonzero iff we want to use the value of this expression
3738 : : in another expression.
3739 : :
3740 : : ARITH_TYPE is the type the computation should be performed in. */
3741 : :
3742 : : enum gimplify_status
3743 : 1142084 : gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
3744 : : bool want_value, tree arith_type)
3745 : : {
3746 : 1142084 : enum tree_code code;
3747 : 1142084 : tree lhs, lvalue, rhs, t1;
3748 : 1142084 : gimple_seq post = NULL, *orig_post_p = post_p;
3749 : 1142084 : bool postfix;
3750 : 1142084 : enum tree_code arith_code;
3751 : 1142084 : enum gimplify_status ret;
3752 : 1142084 : location_t loc = EXPR_LOCATION (*expr_p);
3753 : :
3754 : 1142084 : code = TREE_CODE (*expr_p);
3755 : :
3756 : 1142084 : gcc_assert (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR
3757 : : || code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR);
3758 : :
3759 : : /* Prefix or postfix? */
3760 : 1142084 : if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
3761 : : /* Faster to treat as prefix if result is not used. */
3762 : : postfix = want_value;
3763 : : else
3764 : : postfix = false;
3765 : :
3766 : : /* For postfix, make sure the inner expression's post side effects
3767 : : are executed after side effects from this expression. */
3768 : 399860 : if (postfix)
3769 : 1142084 : post_p = &post;
3770 : :
3771 : : /* Add or subtract? */
3772 : 1142084 : if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
3773 : : arith_code = PLUS_EXPR;
3774 : : else
3775 : 49416 : arith_code = MINUS_EXPR;
3776 : :
3777 : : /* Gimplify the LHS into a GIMPLE lvalue. */
3778 : 1142084 : lvalue = TREE_OPERAND (*expr_p, 0);
3779 : 1142084 : ret = gimplify_expr (&lvalue, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
3780 : 1142084 : if (ret == GS_ERROR)
3781 : : return ret;
3782 : :
3783 : : /* Extract the operands to the arithmetic operation. */
3784 : 1142082 : lhs = lvalue;
3785 : 1142082 : rhs = TREE_OPERAND (*expr_p, 1);
3786 : :
3787 : : /* For postfix operator, we evaluate the LHS to an rvalue and then use
3788 : : that as the result value and in the postqueue operation. */
3789 : 1142082 : if (postfix)
3790 : : {
3791 : 190738 : ret = gimplify_expr (&lhs, pre_p, post_p, is_gimple_val, fb_rvalue);
3792 : 190738 : if (ret == GS_ERROR)
3793 : : return ret;
3794 : :
3795 : 190738 : lhs = get_initialized_tmp_var (lhs, pre_p);
3796 : : }
3797 : :
3798 : : /* For POINTERs increment, use POINTER_PLUS_EXPR. */
3799 : 1142082 : if (POINTER_TYPE_P (TREE_TYPE (lhs)))
3800 : : {
3801 : 243570 : rhs = convert_to_ptrofftype_loc (loc, rhs);
3802 : 243570 : if (arith_code == MINUS_EXPR)
3803 : 11026 : rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
3804 : 243570 : t1 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
3805 : : }
3806 : : else
3807 : 898512 : t1 = fold_convert (TREE_TYPE (*expr_p),
3808 : : fold_build2 (arith_code, arith_type,
3809 : : fold_convert (arith_type, lhs),
3810 : : fold_convert (arith_type, rhs)));
3811 : :
3812 : 1142082 : if (postfix)
3813 : : {
3814 : 190738 : gimplify_assign (lvalue, t1, pre_p);
3815 : 190738 : gimplify_seq_add_seq (orig_post_p, post);
3816 : 190738 : *expr_p = lhs;
3817 : 190738 : return GS_ALL_DONE;
3818 : : }
3819 : : else
3820 : : {
3821 : 951344 : *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
3822 : 951344 : return GS_OK;
3823 : : }
3824 : : }
3825 : :
3826 : : /* If *EXPR_P has a variable sized type, wrap it in a WITH_SIZE_EXPR. */
3827 : :
3828 : : static void
3829 : 81453626 : maybe_with_size_expr (tree *expr_p)
3830 : : {
3831 : 81453626 : tree expr = *expr_p;
3832 : 81453626 : tree type = TREE_TYPE (expr);
3833 : 81453626 : tree size;
3834 : :
3835 : : /* If we've already wrapped this or the type is error_mark_node, we can't do
3836 : : anything. */
3837 : 81453626 : if (TREE_CODE (expr) == WITH_SIZE_EXPR
3838 : 81453501 : || type == error_mark_node)
3839 : : return;
3840 : :
3841 : : /* If the size isn't known or is a constant, we have nothing to do. */
3842 : 81453218 : size = TYPE_SIZE_UNIT (type);
3843 : 81453218 : if (!size || poly_int_tree_p (size))
3844 : : return;
3845 : :
3846 : : /* Otherwise, make a WITH_SIZE_EXPR. */
3847 : 1648 : size = unshare_expr (size);
3848 : 1648 : size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, expr);
3849 : 1648 : *expr_p = build2 (WITH_SIZE_EXPR, type, expr, size);
3850 : : }
3851 : :
3852 : : /* Helper for gimplify_call_expr. Gimplify a single argument *ARG_P
3853 : : Store any side-effects in PRE_P. CALL_LOCATION is the location of
3854 : : the CALL_EXPR. If ALLOW_SSA is set the actual parameter may be
3855 : : gimplified to an SSA name. */
3856 : :
3857 : : enum gimplify_status
3858 : 33886948 : gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
3859 : : bool allow_ssa)
3860 : : {
3861 : 33886948 : bool (*test) (tree);
3862 : 33886948 : fallback_t fb;
3863 : :
3864 : : /* In general, we allow lvalues for function arguments to avoid
3865 : : extra overhead of copying large aggregates out of even larger
3866 : : aggregates into temporaries only to copy the temporaries to
3867 : : the argument list. Make optimizers happy by pulling out to
3868 : : temporaries those types that fit in registers. */
3869 : 33886948 : if (is_gimple_reg_type (TREE_TYPE (*arg_p)))
3870 : : test = is_gimple_val, fb = fb_rvalue;
3871 : : else
3872 : : {
3873 : 1595512 : test = is_gimple_lvalue, fb = fb_either;
3874 : : /* Also strip a TARGET_EXPR that would force an extra copy. */
3875 : 1595512 : if (TREE_CODE (*arg_p) == TARGET_EXPR)
3876 : : {
3877 : 341805 : tree init = TARGET_EXPR_INITIAL (*arg_p);
3878 : 341805 : if (init
3879 : 341802 : && !VOID_TYPE_P (TREE_TYPE (init))
3880 : : /* Currently, due to c++/116015, it is not desirable to
3881 : : strip a TARGET_EXPR whose initializer is a {}. The
3882 : : problem is that if we do elide it, we also have to
3883 : : replace all the occurrences of the slot temporary in the
3884 : : initializer with the temporary created for the argument.
3885 : : But we do not have that temporary yet so the replacement
3886 : : would be quite awkward and it might be needed to resort
3887 : : back to a PLACEHOLDER_EXPR. Note that stripping the
3888 : : TARGET_EXPR wouldn't help anyway, as gimplify_expr would
3889 : : just allocate a temporary to store the CONSTRUCTOR into.
3890 : : (FIXME PR116375.)
3891 : :
3892 : : See convert_for_arg_passing for the C++ code that marks
3893 : : the TARGET_EXPR as eliding or not. */
3894 : 640687 : && TREE_CODE (init) != CONSTRUCTOR)
3895 : 269588 : *arg_p = init;
3896 : : }
3897 : : }
3898 : :
3899 : : /* If this is a variable sized type, we must remember the size. */
3900 : 33886948 : maybe_with_size_expr (arg_p);
3901 : :
3902 : : /* FIXME diagnostics: This will mess up gcc.dg/Warray-bounds.c. */
3903 : : /* Make sure arguments have the same location as the function call
3904 : : itself. */
3905 : 33886948 : protected_set_expr_location (*arg_p, call_location);
3906 : :
3907 : : /* There is a sequence point before a function call. Side effects in
3908 : : the argument list must occur before the actual call. So, when
3909 : : gimplifying arguments, force gimplify_expr to use an internal
3910 : : post queue which is then appended to the end of PRE_P. */
3911 : 33886948 : return gimplify_expr (arg_p, pre_p, NULL, test, fb, allow_ssa);
3912 : : }
3913 : :
3914 : : /* Don't fold inside offloading or taskreg regions: it can break code by
3915 : : adding decl references that weren't in the source. We'll do it during
3916 : : omplower pass instead. */
3917 : :
3918 : : static bool
3919 : 59074314 : maybe_fold_stmt (gimple_stmt_iterator *gsi)
3920 : : {
3921 : 59074314 : struct gimplify_omp_ctx *ctx;
3922 : 59601846 : for (ctx = gimplify_omp_ctxp; ctx; ctx = ctx->outer_context)
3923 : 1179163 : if ((ctx->region_type & (ORT_TARGET | ORT_PARALLEL | ORT_TASK)) != 0)
3924 : : return false;
3925 : 532463 : else if ((ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
3926 : : return false;
3927 : : /* Delay folding of builtins until the IL is in consistent state
3928 : : so the diagnostic machinery can do a better job. */
3929 : 58422683 : if (gimple_call_builtin_p (gsi_stmt (*gsi)))
3930 : : return false;
3931 : 56055165 : return fold_stmt (gsi);
3932 : : }
3933 : :
3934 : : static tree
3935 : : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
3936 : : tree construct_context);
3937 : :
3938 : :
3939 : : /* Helper function for calls to omp_dynamic_cond: find the current
3940 : : enclosing block in the gimplification context. */
3941 : : static tree
3942 : 359 : find_supercontext (void)
3943 : : {
3944 : 359 : vec<gbind *>stack = gimple_bind_expr_stack ();
3945 : 686 : for (int i = stack.length () - 1; i >= 0; i++)
3946 : : {
3947 : 327 : gbind *b = stack[i];
3948 : 327 : if (b->block)
3949 : : return b->block;
3950 : : }
3951 : : return NULL_TREE;
3952 : : }
3953 : :
3954 : : /* OpenMP: Handle the append_args and adjust_args clauses of
3955 : : declare_variant for EXPR, which is a CALL_EXPR whose CALL_EXPR_FN
3956 : : is the variant, within a dispatch construct with clauses DISPATCH_CLAUSES.
3957 : : WANT_VALUE and POINTERIZE are as for expand_variant_call_expr.
3958 : :
3959 : : 'append_args' causes interop objects are added after the last regular
3960 : : (nonhidden, nonvariadic) arguments of the variant function.
3961 : : 'adjust_args' with need_device_{addr,ptr} converts the pointer target of
3962 : : a pointer from a host to a device address. This uses either the default
3963 : : device or the passed device number, which then sets the default device
3964 : : address. */
3965 : : static tree
3966 : 471 : modify_call_for_omp_dispatch (tree expr, tree dispatch_clauses,
3967 : : bool want_value, bool pointerize)
3968 : : {
3969 : 471 : location_t loc = EXPR_LOCATION (expr);
3970 : 471 : tree fndecl = get_callee_fndecl (expr);
3971 : :
3972 : : /* Skip processing if we don't get the expected call form. */
3973 : 471 : if (!fndecl)
3974 : : return expr;
3975 : :
3976 : 471 : tree init_code = NULL_TREE;
3977 : 471 : tree cleanup = NULL_TREE;
3978 : 471 : tree clobbers = NULL_TREE;
3979 : 471 : int nargs = call_expr_nargs (expr);
3980 : 471 : tree dispatch_device_num = NULL_TREE;
3981 : 471 : tree dispatch_interop = NULL_TREE;
3982 : 471 : tree dispatch_append_args = NULL_TREE;
3983 : 471 : int nfirst_args = 0;
3984 : 471 : tree dispatch_adjust_args_list
3985 : 471 : = lookup_attribute ("omp declare variant variant args",
3986 : 471 : DECL_ATTRIBUTES (fndecl));
3987 : :
3988 : 471 : if (dispatch_adjust_args_list)
3989 : : {
3990 : 389 : dispatch_adjust_args_list = TREE_VALUE (dispatch_adjust_args_list);
3991 : 389 : dispatch_append_args = TREE_CHAIN (dispatch_adjust_args_list);
3992 : 389 : if (TREE_PURPOSE (dispatch_adjust_args_list) == NULL_TREE
3993 : 389 : && TREE_VALUE (dispatch_adjust_args_list) == NULL_TREE)
3994 : : dispatch_adjust_args_list = NULL_TREE;
3995 : : }
3996 : 389 : if (dispatch_append_args)
3997 : : {
3998 : 245 : nfirst_args = tree_to_shwi (TREE_PURPOSE (dispatch_append_args));
3999 : 245 : dispatch_append_args = TREE_VALUE (dispatch_append_args);
4000 : : }
4001 : 471 : dispatch_device_num = omp_find_clause (dispatch_clauses, OMP_CLAUSE_DEVICE);
4002 : 471 : if (dispatch_device_num)
4003 : 287 : dispatch_device_num = OMP_CLAUSE_DEVICE_ID (dispatch_device_num);
4004 : 471 : dispatch_interop = omp_find_clause (dispatch_clauses, OMP_CLAUSE_INTEROP);
4005 : 471 : int nappend = 0, ninterop = 0;
4006 : 880 : for (tree t = dispatch_append_args; t; t = TREE_CHAIN (t))
4007 : 409 : nappend++;
4008 : :
4009 : : /* FIXME: error checking should be taken out of this function and
4010 : : handled before any attempt at filtering or resolution happens.
4011 : : Otherwise whether or not diagnostics appear is determined by
4012 : : GCC internals, how good the front ends are at constant-folding,
4013 : : the split between early/late resolution, etc instead of the code
4014 : : as written by the user. */
4015 : 471 : if (dispatch_interop)
4016 : 861 : for (tree t = dispatch_interop; t; t = TREE_CHAIN (t))
4017 : 605 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
4018 : 409 : ninterop++;
4019 : 471 : if (dispatch_interop && !dispatch_device_num)
4020 : : {
4021 : 7 : gcc_checking_assert (ninterop > 1);
4022 : 7 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
4023 : : "the %<device%> clause must be present if the %<interop%> "
4024 : : "clause has more than one list item");
4025 : : }
4026 : 471 : if (nappend < ninterop)
4027 : : {
4028 : 48 : error_at (OMP_CLAUSE_LOCATION (dispatch_interop),
4029 : : "number of list items in %<interop%> clause (%d) "
4030 : : "exceeds the number of %<append_args%> items (%d) for "
4031 : : "%<declare variant%> candidate %qD", ninterop, nappend, fndecl);
4032 : 88 : inform (dispatch_append_args
4033 : 8 : ? EXPR_LOCATION (TREE_PURPOSE (dispatch_append_args))
4034 : 40 : : DECL_SOURCE_LOCATION (fndecl),
4035 : : "%<declare variant%> candidate %qD declared here", fndecl);
4036 : 48 : ninterop = nappend;
4037 : : }
4038 : 471 : if (dispatch_append_args)
4039 : : {
4040 : 245 : tree *buffer = XALLOCAVEC (tree, nargs + nappend);
4041 : 245 : tree arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
4042 : : /* Copy the first arguments; insert then the interop objects,
4043 : : and then copy the rest (nargs - nfirst_args) args. */
4044 : 245 : int i;
4045 : 679 : for (i = 0; i < nfirst_args; i++)
4046 : : {
4047 : 434 : arg = TREE_CHAIN (arg);
4048 : 434 : buffer[i] = CALL_EXPR_ARG (expr, i);
4049 : : }
4050 : : int j = ninterop;
4051 : 583 : for (tree t = dispatch_interop; t && j > 0; t = TREE_CHAIN (t))
4052 : 338 : if (OMP_CLAUSE_CODE (t) == OMP_CLAUSE_INTEROP)
4053 : 338 : buffer[i + --j] = OMP_CLAUSE_DECL (t);
4054 : 245 : gcc_checking_assert (j == 0);
4055 : :
4056 : : /* Do we need to create additional interop objects? */
4057 : 245 : if (ninterop < nappend)
4058 : : {
4059 : 56 : if (dispatch_device_num == NULL_TREE)
4060 : : /* Not remapping device number. */
4061 : 22 : dispatch_device_num = build_int_cst (integer_type_node,
4062 : : GOMP_DEVICE_DEFAULT_OMP_61);
4063 : 56 : int nnew = nappend - ninterop;
4064 : 56 : tree nobjs = build_int_cst (integer_type_node, nnew);
4065 : 56 : tree a, t;
4066 : :
4067 : : /* Skip to the append_args clause for the first constructed
4068 : : interop argument. */
4069 : 56 : tree apparg = dispatch_append_args;
4070 : 83 : for (j = 0; j < ninterop; j++)
4071 : 27 : apparg = TREE_CHAIN (apparg);
4072 : :
4073 : : /* omp_interop_t *objs[n]; */
4074 : 56 : tree objtype = build_pointer_type (pointer_sized_int_node);
4075 : 56 : t = build_array_type_nelts (objtype, nnew);
4076 : 56 : tree objs = create_tmp_var (t, "interopobjs");
4077 : :
4078 : : /* int target_tgtsync[n]; */
4079 : 56 : t = build_array_type_nelts (integer_type_node, nnew);
4080 : 56 : tree target_tgtsync = create_tmp_var (t, "tgt_tgtsync");
4081 : :
4082 : : /* Scan first to determine if we need a prefer_type array. */
4083 : 56 : tree prefer_type = NULL_TREE;
4084 : 56 : tree prefer_type_type = NULL_TREE;
4085 : 141 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
4086 : 64 : if (TREE_VALUE (a) != NULL_TREE)
4087 : : {
4088 : : /* const char *prefer_type[n]; */
4089 : 35 : t = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
4090 : 35 : prefer_type_type = build_pointer_type (t);
4091 : 35 : t = build_array_type_nelts (prefer_type_type, nnew);
4092 : 35 : prefer_type = create_tmp_var (t, "pref_type");
4093 : 35 : break;
4094 : : }
4095 : :
4096 : : /* Initialize the arrays, generating temp vars and clobbers for
4097 : : the interobject objects. (The constructed array holding the
4098 : : pointers to these objects shouldn't need clobbering as there's
4099 : : no reason for GOMP_interop to modify its contents.) */
4100 : 127 : for (j = ninterop, a = apparg; j < nappend; j++, a = TREE_CHAIN (a))
4101 : : {
4102 : : /* The allocated temporaries for the interop objects
4103 : : have type omp_interop_t, which is an integer type that
4104 : : can encode a pointer. */
4105 : 71 : tree objvar = create_tmp_var (pointer_sized_int_node, "interop");
4106 : 71 : buffer[i + j] = objvar;
4107 : 71 : TREE_ADDRESSABLE (objvar) = 1;
4108 : : /* Generate a clobber for the temporary for when we're done
4109 : : with it. */
4110 : 71 : tree c = build_clobber (pointer_sized_int_node,
4111 : : CLOBBER_OBJECT_END);
4112 : 71 : c = build2 (MODIFY_EXPR, pointer_sized_int_node, objvar, c);
4113 : 71 : if (clobbers)
4114 : 15 : clobbers = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
4115 : : c, clobbers);
4116 : : else
4117 : : clobbers = c;
4118 : :
4119 : : /* objs[offset] = &objvar; */
4120 : 71 : tree offset = build_int_cst (integer_type_node, j - ninterop);
4121 : 71 : tree init = build4 (ARRAY_REF, objtype, objs, offset,
4122 : : NULL_TREE, NULL_TREE);
4123 : 71 : init = build2 (MODIFY_EXPR, objtype, init,
4124 : : build_fold_addr_expr (objvar));
4125 : 71 : if (init_code)
4126 : 15 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4127 : : init_code, init);
4128 : : else
4129 : : init_code = init;
4130 : :
4131 : : /* target_tgtsync[offset] = tgt;
4132 : : (Don't blame me, I didn't design the encoding of this
4133 : : info into the dispatch interop clause data structure,
4134 : : but the runtime wants a bit mask.) */
4135 : 71 : tree tree_tgt = TREE_OPERAND (TREE_PURPOSE (a), 0);
4136 : 71 : int tgt = 0;
4137 : 71 : if (TREE_PURPOSE (tree_tgt) == boolean_true_node)
4138 : 42 : tgt |= GOMP_INTEROP_TARGET;
4139 : 71 : if (TREE_VALUE (tree_tgt) == boolean_true_node)
4140 : 36 : tgt |= GOMP_INTEROP_TARGETSYNC;
4141 : 71 : init = build4 (ARRAY_REF, integer_type_node,
4142 : : target_tgtsync, offset, NULL_TREE, NULL_TREE);
4143 : 71 : init = build2 (MODIFY_EXPR, integer_type_node, init,
4144 : 71 : build_int_cst (integer_type_node, tgt));
4145 : 71 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4146 : : init_code, init);
4147 : :
4148 : 71 : if (prefer_type)
4149 : : {
4150 : 45 : tree pref = TREE_VALUE (a);
4151 : 45 : if (pref == NULL_TREE)
4152 : 6 : pref = null_pointer_node;
4153 : : else
4154 : 39 : pref = build_fold_addr_expr (pref);
4155 : 45 : init = build4 (ARRAY_REF, prefer_type_type, prefer_type,
4156 : : offset, NULL_TREE, NULL_TREE);
4157 : 45 : init = build2 (MODIFY_EXPR, prefer_type_type, init,
4158 : : pref);
4159 : 45 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4160 : : init_code, init);
4161 : : }
4162 : : }
4163 : :
4164 : 56 : objs = build_fold_addr_expr (objs);
4165 : 56 : target_tgtsync = build_fold_addr_expr (target_tgtsync);
4166 : 56 : prefer_type = prefer_type ? build_fold_addr_expr (prefer_type)
4167 : : : null_pointer_node;
4168 : 56 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_INTEROP);
4169 : 56 : tree create
4170 : 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4171 : : nobjs, objs, target_tgtsync, prefer_type,
4172 : : integer_zero_node, null_pointer_node,
4173 : : integer_zero_node, null_pointer_node,
4174 : : integer_zero_node, null_pointer_node);
4175 : 56 : if (init_code)
4176 : 56 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (create),
4177 : : init_code, create);
4178 : : else
4179 : : init_code = create;
4180 : :
4181 : 56 : cleanup
4182 : 56 : = build_call_expr_loc (loc, fn, 11, dispatch_device_num,
4183 : : integer_zero_node, null_pointer_node,
4184 : : null_pointer_node, null_pointer_node,
4185 : : integer_zero_node, null_pointer_node,
4186 : : nobjs, objs,
4187 : : integer_zero_node, null_pointer_node);
4188 : 56 : if (clobbers)
4189 : 56 : cleanup = build2 (COMPOUND_EXPR, TREE_TYPE (clobbers),
4190 : : cleanup, clobbers);
4191 : : }
4192 : :
4193 : 654 : for (j = 0; j < nappend; j++)
4194 : : {
4195 : : /* Fortran permits by-reference or by-value for the dummy arg
4196 : : and by-value, by-reference, ptr by-reference as actual
4197 : : argument. Handle this. */
4198 : 409 : tree obj = buffer[i + j]; // interop object
4199 : 409 : tree a2 = TREE_VALUE (arg); // parameter type
4200 : 766 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4201 : 436 : && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (obj))))
4202 : : {
4203 : 32 : tree t = TREE_TYPE (TREE_TYPE (obj));
4204 : 32 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (t)));
4205 : 32 : obj = fold_build1 (INDIRECT_REF, t, obj);
4206 : : }
4207 : 750 : if (POINTER_TYPE_P (TREE_TYPE (obj))
4208 : 420 : && INTEGRAL_TYPE_P (a2))
4209 : : {
4210 : 43 : tree t = TREE_TYPE (TREE_TYPE (obj));
4211 : 43 : gcc_checking_assert (INTEGRAL_TYPE_P (t));
4212 : 43 : obj = fold_build1 (INDIRECT_REF, t, obj);
4213 : : }
4214 : 497 : else if (INTEGRAL_TYPE_P (TREE_TYPE (obj))
4215 : 461 : && POINTER_TYPE_P (a2))
4216 : : {
4217 : 18 : gcc_checking_assert (INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4218 : 18 : obj = build_fold_addr_expr (obj);
4219 : : }
4220 : 348 : else if (!INTEGRAL_TYPE_P (a2)
4221 : 348 : || !INTEGRAL_TYPE_P (TREE_TYPE (obj)))
4222 : : {
4223 : 36 : tree t = TREE_TYPE (obj);
4224 : 36 : gcc_checking_assert (POINTER_TYPE_P (t)
4225 : : && POINTER_TYPE_P (a2)
4226 : : && INTEGRAL_TYPE_P (TREE_TYPE (t))
4227 : : && INTEGRAL_TYPE_P (TREE_TYPE (a2)));
4228 : : }
4229 : 409 : buffer[i + j] = obj;
4230 : 409 : arg = TREE_CHAIN (arg);
4231 : : }
4232 : 245 : i += nappend;
4233 : 534 : for (j = nfirst_args; j < nargs; j++)
4234 : 289 : buffer[i++] = CALL_EXPR_ARG (expr, j);
4235 : 245 : nargs += nappend;
4236 : 245 : tree call = expr;
4237 : 490 : expr = build_call_array_loc (EXPR_LOCATION (expr), TREE_TYPE (call),
4238 : 245 : CALL_EXPR_FN (call), nargs, buffer);
4239 : :
4240 : : /* Copy all CALL_EXPR flags. */
4241 : 245 : CALL_EXPR_STATIC_CHAIN (expr) = CALL_EXPR_STATIC_CHAIN (call);
4242 : 245 : CALL_EXPR_TAILCALL (expr) = CALL_EXPR_TAILCALL (call);
4243 : 245 : CALL_EXPR_RETURN_SLOT_OPT (expr)
4244 : 245 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4245 : 245 : CALL_FROM_THUNK_P (expr) = CALL_FROM_THUNK_P (call);
4246 : 245 : SET_EXPR_LOCATION (expr, EXPR_LOCATION (call));
4247 : 245 : CALL_EXPR_VA_ARG_PACK (expr) = CALL_EXPR_VA_ARG_PACK (call);
4248 : : }
4249 : :
4250 : : /* Nothing to do for adjust_args? */
4251 : 471 : if (!dispatch_adjust_args_list || !TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
4252 : 260 : goto add_cleanup;
4253 : :
4254 : : /* Handle adjust_args. */
4255 : 966 : for (int i = 0; i < nargs; i++)
4256 : : {
4257 : 755 : tree *arg_p = &CALL_EXPR_ARG (expr, i);
4258 : :
4259 : : /* Nothing to do if arg is constant null pointer. */
4260 : 755 : if (integer_zerop (*arg_p))
4261 : 6 : continue;
4262 : :
4263 : : bool need_device_ptr = false;
4264 : : bool need_device_addr = false;
4265 : 2247 : for (int need_addr = 0; need_addr <= 1; need_addr++)
4266 : 2301 : for (tree arg = (need_addr
4267 : 1498 : ? TREE_VALUE (dispatch_adjust_args_list)
4268 : 1498 : : TREE_PURPOSE (dispatch_adjust_args_list));
4269 : 2301 : arg != NULL; arg = TREE_CHAIN (arg))
4270 : : {
4271 : 1152 : if (TREE_VALUE (arg)
4272 : 1152 : && TREE_CODE (TREE_VALUE (arg)) == INTEGER_CST
4273 : 2304 : && wi::eq_p (i, wi::to_wide (TREE_VALUE (arg))))
4274 : : {
4275 : 349 : if (need_addr)
4276 : : need_device_addr = true;
4277 : : else
4278 : 349 : need_device_ptr = true;
4279 : : break;
4280 : : }
4281 : : }
4282 : :
4283 : 749 : if (need_device_ptr || need_device_addr)
4284 : : {
4285 : 740 : bool is_device_ptr = false;
4286 : 740 : bool has_device_addr = false;
4287 : :
4288 : 740 : for (tree c = dispatch_clauses; c; c = TREE_CHAIN (c))
4289 : : {
4290 : 454 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR
4291 : 454 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_HAS_DEVICE_ADDR)
4292 : : {
4293 : 164 : tree decl1 = DECL_NAME (OMP_CLAUSE_DECL (c));
4294 : 164 : tree decl2 = tree_strip_nop_conversions (*arg_p);
4295 : 164 : if (TREE_CODE (decl2) == ADDR_EXPR)
4296 : 19 : decl2 = TREE_OPERAND (decl2, 0);
4297 : 164 : if (VAR_P (decl2) || TREE_CODE (decl2) == PARM_DECL)
4298 : : {
4299 : 140 : decl2 = DECL_NAME (decl2);
4300 : 140 : if (decl1 == decl2
4301 : 203 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
4302 : : {
4303 : 58 : if (need_device_addr)
4304 : 0 : warning_at (OMP_CLAUSE_LOCATION (c),
4305 : 0 : OPT_Wopenmp,
4306 : : "%<is_device_ptr%> for %qD does"
4307 : : " not imply %<has_device_addr%> "
4308 : : "required for %<need_device_addr%>",
4309 : 0 : OMP_CLAUSE_DECL (c));
4310 : : is_device_ptr = true;
4311 : : break;
4312 : : }
4313 : 82 : else if (decl1 == decl2)
4314 : : {
4315 : 5 : if (need_device_ptr)
4316 : 10 : warning_at (OMP_CLAUSE_LOCATION (c),
4317 : 5 : OPT_Wopenmp,
4318 : : "%<has_device_addr%> for %qD does"
4319 : : " not imply %<is_device_ptr%> "
4320 : : "required for %<need_device_ptr%>",
4321 : 5 : OMP_CLAUSE_DECL (c));
4322 : : has_device_addr = true;
4323 : : break;
4324 : : }
4325 : : }
4326 : : }
4327 : : }
4328 : :
4329 : 349 : if ((need_device_ptr && !is_device_ptr)
4330 : 58 : || (need_device_addr && !has_device_addr))
4331 : : {
4332 : 291 : if (dispatch_device_num == NULL_TREE)
4333 : : {
4334 : : // device_num = omp_get_default_device ()
4335 : 105 : tree fn
4336 : 105 : = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
4337 : 105 : tree call = build_call_expr (fn, 0);
4338 : 105 : dispatch_device_num = create_tmp_var_raw (TREE_TYPE (call));
4339 : 105 : tree init
4340 : 105 : = build4 (TARGET_EXPR, TREE_TYPE (call),
4341 : : dispatch_device_num, call, NULL_TREE, NULL_TREE);
4342 : 105 : if (init_code)
4343 : 0 : init_code = build2 (COMPOUND_EXPR, TREE_TYPE (init),
4344 : : init_code, init);
4345 : : else
4346 : : init_code = init;
4347 : : }
4348 : :
4349 : : // We want to emit the following statement:
4350 : : // mapped_arg = omp_get_mapped_ptr (arg,
4351 : : // device_num)
4352 : : // but arg has to be the actual pointer, not a
4353 : : // reference or a conversion expression.
4354 : 291 : tree actual_ptr
4355 : 291 : = ((TREE_CODE (*arg_p) == ADDR_EXPR)
4356 : 291 : ? TREE_OPERAND (*arg_p, 0)
4357 : 38 : : *arg_p);
4358 : 291 : if (TREE_CODE (actual_ptr) == NOP_EXPR
4359 : 291 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (actual_ptr, 0)))
4360 : : == REFERENCE_TYPE))
4361 : : {
4362 : 6 : actual_ptr = TREE_OPERAND (actual_ptr, 0);
4363 : 6 : actual_ptr = build1 (INDIRECT_REF,
4364 : 6 : TREE_TYPE (actual_ptr),
4365 : : actual_ptr);
4366 : : }
4367 : 291 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_MAPPED_PTR);
4368 : 291 : tree mapped_arg = build_call_expr_loc (loc, fn, 2, actual_ptr,
4369 : : dispatch_device_num);
4370 : :
4371 : 291 : if (TREE_CODE (*arg_p) == ADDR_EXPR
4372 : 291 : || (TREE_CODE (TREE_TYPE (actual_ptr)) == REFERENCE_TYPE))
4373 : 47 : mapped_arg = build_fold_addr_expr (mapped_arg);
4374 : 244 : else if (TREE_CODE (*arg_p) == NOP_EXPR)
4375 : 35 : mapped_arg = build1 (NOP_EXPR, TREE_TYPE (*arg_p),
4376 : : mapped_arg);
4377 : 291 : *arg_p = mapped_arg;
4378 : : }
4379 : : }
4380 : : }
4381 : :
4382 : 471 : add_cleanup:
4383 : 471 : if (cleanup)
4384 : : {
4385 : 56 : tree result = NULL_TREE;
4386 : 56 : if (want_value && pointerize)
4387 : : {
4388 : 0 : tree tmp = create_tmp_var (build_pointer_type (TREE_TYPE (expr)),
4389 : : "cleanuptmp");
4390 : 0 : result = build_simple_mem_ref (tmp);
4391 : 0 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp,
4392 : : build_fold_addr_expr (expr));
4393 : : }
4394 : 56 : else if (want_value)
4395 : : {
4396 : 18 : tree tmp = create_tmp_var (TREE_TYPE (expr), "cleanuptmp");
4397 : 18 : result = tmp;
4398 : 18 : expr = build2 (INIT_EXPR, TREE_TYPE (tmp), tmp, expr);
4399 : : }
4400 : 56 : if (init_code)
4401 : 56 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4402 : 56 : expr = build2 (TRY_FINALLY_EXPR, void_type_node, expr, cleanup);
4403 : :
4404 : 56 : if (result)
4405 : 18 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (result), expr, result);
4406 : : }
4407 : 415 : else if (init_code)
4408 : 105 : expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init_code, expr);
4409 : :
4410 : : return expr;
4411 : : }
4412 : :
4413 : : /* Helper function for gimplify_call_expr: handle "declare variant"
4414 : : resolution and expansion of the CALL_EXPR EXPR. WANT_VALUE is true
4415 : : if the result value of the call is needed; POINTERIZE is true if it
4416 : : also needs to be pointerized. If OMP_DISPATCH_P is true, apply
4417 : : associated transformations using DISPATCH_CLAUSES.
4418 : : This function may return either the original call or some other
4419 : : expression such as a conditional to select one of multiple calls.
4420 : :
4421 : : FIXME: this function is written to be independent of gimplifier internals
4422 : : so that it could be moved to omp-general.cc and invoked from the
4423 : : front ends instead, per PR115076. */
4424 : :
4425 : : static tree
4426 : 1098 : expand_variant_call_expr (tree expr, bool want_value, bool pointerize,
4427 : : bool omp_dispatch_p, tree dispatch_clauses)
4428 : : {
4429 : : /* If we've already processed this call, stop now. This can happen
4430 : : if the variant call resolves to the original function, or to
4431 : : a dynamic conditional that includes the default call to the original
4432 : : function. */
4433 : 1098 : gcc_assert (omp_resolved_variant_calls != NULL);
4434 : 1098 : if (omp_resolved_variant_calls->contains (expr))
4435 : 102 : return expr;
4436 : :
4437 : 996 : tree fndecl = get_callee_fndecl (expr);
4438 : 996 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (expr));
4439 : 996 : location_t loc = EXPR_LOCATION (expr);
4440 : 996 : tree construct_context = omp_get_construct_context ();
4441 : 996 : vec<struct omp_variant> all_candidates
4442 : 996 : = omp_declare_variant_candidates (fndecl, construct_context);
4443 : 996 : gcc_assert (!all_candidates.is_empty ());
4444 : 996 : vec<struct omp_variant> candidates
4445 : 996 : = omp_get_dynamic_candidates (all_candidates, construct_context);
4446 : :
4447 : : /* If the variant call could be resolved now, build a nest of COND_EXPRs
4448 : : if there are dynamic candidates, and/or a new CALL_EXPR for each
4449 : : candidate call. */
4450 : 996 : if (!candidates.is_empty ())
4451 : : {
4452 : 984 : int n = candidates.length ();
4453 : 984 : tree tail = NULL_TREE;
4454 : :
4455 : 2006 : for (int i = n - 1; i >= 0; i--)
4456 : : {
4457 : 1022 : if (tail)
4458 : 38 : gcc_assert (candidates[i].dynamic_selector);
4459 : : else
4460 : 984 : gcc_assert (!candidates[i].dynamic_selector);
4461 : 1022 : if (candidates[i].alternative == fndecl)
4462 : : {
4463 : : /* We should only get the original function back as the
4464 : : default. */
4465 : 203 : gcc_assert (!tail);
4466 : 203 : omp_resolved_variant_calls->add (expr);
4467 : 203 : tail = expr;
4468 : : }
4469 : : else
4470 : : {
4471 : : /* For the final static selector, we can re-use the old
4472 : : CALL_EXPR and just replace the function, unless it may
4473 : : need dispatch argument modification. Otherwise,
4474 : : make a copy of it. */
4475 : 819 : tree thiscall = (tail || omp_dispatch_p
4476 : 819 : ? unshare_expr (expr) : expr);
4477 : 819 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype,
4478 : 819 : candidates[i].alternative);
4479 : 819 : if (omp_dispatch_p)
4480 : 471 : thiscall = modify_call_for_omp_dispatch (thiscall,
4481 : : dispatch_clauses,
4482 : : want_value,
4483 : : pointerize);
4484 : 819 : if (!tail)
4485 : : tail = thiscall;
4486 : : else
4487 : 76 : tail = build3 (COND_EXPR, TREE_TYPE (expr),
4488 : 38 : omp_dynamic_cond (candidates[i].selector,
4489 : : find_supercontext ()),
4490 : : thiscall, tail);
4491 : : }
4492 : : }
4493 : : return tail;
4494 : : }
4495 : :
4496 : : /* If we couldn't resolve the variant call now, expand it into a loop using
4497 : : a switch and OMP_NEXT_VARIANT for dispatch. The ompdevlow pass will
4498 : : handle OMP_NEXT_VARIANT expansion. */
4499 : : else
4500 : : {
4501 : : /* If we need a usable return value, we need a temporary
4502 : : and an assignment in each alternative. This logic was borrowed
4503 : : from gimplify_cond_expr. */
4504 : 12 : tree type = TREE_TYPE (expr);
4505 : 12 : tree tmp = NULL_TREE, result = NULL_TREE;
4506 : :
4507 : 12 : if (want_value)
4508 : : {
4509 : 12 : if (pointerize)
4510 : : {
4511 : 0 : type = build_pointer_type (type);
4512 : 0 : tmp = create_tmp_var (type, "iftmp");
4513 : 0 : result = build_simple_mem_ref_loc (loc, tmp);
4514 : : }
4515 : : else
4516 : : {
4517 : 12 : tmp = create_tmp_var (type, "iftmp");
4518 : 12 : result = tmp;
4519 : : }
4520 : : }
4521 : :
4522 : : /* Preprocess the all_candidates array so that the alternative field of
4523 : : each element holds the actual function call expression and possible
4524 : : assignment, instead of just the decl for the variant function. */
4525 : 60 : for (unsigned int i = 0; i < all_candidates.length (); i++)
4526 : : {
4527 : 48 : tree decl = all_candidates[i].alternative;
4528 : 48 : tree thiscall;
4529 : :
4530 : : /* We need to turn the decl from the candidate into a function
4531 : : call and possible assignment, and stuff that in
4532 : : the directive seq of the gomp_variant. */
4533 : 48 : if (decl == fndecl)
4534 : : {
4535 : 12 : thiscall = expr;
4536 : 12 : omp_resolved_variant_calls->add (expr);
4537 : : }
4538 : : else
4539 : : {
4540 : 36 : thiscall = unshare_expr (expr);
4541 : 36 : CALL_EXPR_FN (thiscall) = build1 (ADDR_EXPR, fnptrtype, decl);
4542 : 36 : if (omp_dispatch_p)
4543 : 0 : thiscall = modify_call_for_omp_dispatch (thiscall,
4544 : : dispatch_clauses,
4545 : : want_value,
4546 : : pointerize);
4547 : : }
4548 : 48 : if (pointerize)
4549 : 0 : thiscall = build_fold_addr_expr_loc (loc, thiscall);
4550 : 48 : if (want_value)
4551 : 48 : thiscall = build2 (INIT_EXPR, type, tmp, thiscall);
4552 : 48 : all_candidates[i].alternative = thiscall;
4553 : : }
4554 : :
4555 : 12 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
4556 : 12 : tree expansion = expand_late_variant_directive (all_candidates,
4557 : : construct_context);
4558 : 12 : if (result)
4559 : 12 : expansion = build2 (COMPOUND_EXPR, TREE_TYPE (result),
4560 : : expansion, result);
4561 : 12 : return expansion;
4562 : : }
4563 : : }
4564 : :
4565 : : /* Wrapper around expand_variant_call_expr to interface with gimplifier
4566 : : state. EXPR and OMP_DISPATCH_P are as for expand_variant_call_expr,
4567 : : FALLBACK is used to compute the WANT_VALUE and POINTERIZE arguments. */
4568 : : static tree
4569 : 1098 : gimplify_variant_call_expr (tree expr, fallback_t fallback,
4570 : : bool omp_dispatch_p)
4571 : : {
4572 : 1098 : tree type = TREE_TYPE (expr);
4573 : 1098 : bool want_value = (fallback != fb_none && !VOID_TYPE_P (type));
4574 : 487 : bool pointerize = false;
4575 : : /* If the result value must be an lvalue or the result type must
4576 : : live in memory, then we have to pointerize it if we need a temporary. */
4577 : 487 : if (want_value
4578 : 487 : && ((!(fallback & fb_rvalue) && (fallback & fb_lvalue))
4579 : 487 : || TREE_ADDRESSABLE (type)))
4580 : 0 : pointerize = true;
4581 : :
4582 : 1610 : return expand_variant_call_expr (expr, want_value, pointerize,
4583 : : omp_dispatch_p,
4584 : : (omp_dispatch_p
4585 : 512 : ? gimplify_omp_ctxp->clauses
4586 : 1098 : : NULL_TREE));
4587 : : }
4588 : :
4589 : :
4590 : : /* Helper function for gimplify_call_expr, called via walk_tree.
4591 : : Find used user labels. */
4592 : :
4593 : : static tree
4594 : 801 : find_used_user_labels (tree *tp, int *, void *)
4595 : : {
4596 : 801 : if (TREE_CODE (*tp) == LABEL_EXPR
4597 : 15 : && !DECL_ARTIFICIAL (LABEL_EXPR_LABEL (*tp))
4598 : 15 : && DECL_NAME (LABEL_EXPR_LABEL (*tp))
4599 : 816 : && TREE_USED (LABEL_EXPR_LABEL (*tp)))
4600 : 15 : return *tp;
4601 : : return NULL_TREE;
4602 : : }
4603 : :
4604 : :
4605 : : /* Gimplify the CALL_EXPR node *EXPR_P into the GIMPLE sequence PRE_P.
4606 : : WANT_VALUE is true if the result of the call is desired. */
4607 : :
4608 : : static enum gimplify_status
4609 : 17023038 : gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
4610 : : {
4611 : 17023038 : bool want_value = (fallback != fb_none);
4612 : 17023038 : tree fndecl, parms, p, fnptrtype;
4613 : 17023038 : enum gimplify_status ret;
4614 : 17023038 : int i, nargs;
4615 : 17023038 : gcall *call;
4616 : 17023038 : bool builtin_va_start_p = false, omp_dispatch_p = false;
4617 : 17023038 : location_t loc = EXPR_LOCATION (*expr_p);
4618 : :
4619 : 17023038 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4620 : :
4621 : : /* For reliable diagnostics during inlining, it is necessary that
4622 : : every call_expr be annotated with file and line. */
4623 : 17023038 : if (! EXPR_HAS_LOCATION (*expr_p))
4624 : 561620 : SET_EXPR_LOCATION (*expr_p, input_location);
4625 : :
4626 : : /* Gimplify internal functions created in the FEs. */
4627 : 17023038 : if (CALL_EXPR_FN (*expr_p) == NULL_TREE)
4628 : : {
4629 : 607027 : enum internal_fn ifn = CALL_EXPR_IFN (*expr_p);
4630 : 607027 : if (ifn == IFN_GOMP_DISPATCH)
4631 : : {
4632 : 878 : gcc_assert (flag_openmp
4633 : : && gimplify_omp_ctxp
4634 : : && gimplify_omp_ctxp->code == OMP_DISPATCH);
4635 : 878 : *expr_p = CALL_EXPR_ARG (*expr_p, 0);
4636 : 878 : gcc_assert (TREE_CODE (*expr_p) == CALL_EXPR);
4637 : 878 : if (! EXPR_HAS_LOCATION (*expr_p))
4638 : 94 : SET_EXPR_LOCATION (*expr_p, input_location);
4639 : : omp_dispatch_p = true;
4640 : : }
4641 : : else
4642 : : {
4643 : 606149 : if (want_value)
4644 : : return GS_ALL_DONE;
4645 : :
4646 : 22043 : nargs = call_expr_nargs (*expr_p);
4647 : 22043 : auto_vec<tree> vargs (nargs);
4648 : :
4649 : 22043 : if (ifn == IFN_ASSUME)
4650 : : {
4651 : 515 : if (simple_condition_p (CALL_EXPR_ARG (*expr_p, 0)))
4652 : : {
4653 : : /* If the [[assume (cond)]]; condition is simple
4654 : : enough and can be evaluated unconditionally
4655 : : without side-effects, expand it as
4656 : : if (!cond) __builtin_unreachable (); */
4657 : 293 : tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
4658 : 293 : *expr_p
4659 : 586 : = build3 (COND_EXPR, void_type_node,
4660 : 293 : CALL_EXPR_ARG (*expr_p, 0), void_node,
4661 : 293 : build_call_expr_loc (EXPR_LOCATION (*expr_p),
4662 : : fndecl, 0));
4663 : 293 : return GS_OK;
4664 : : }
4665 : : /* If not optimizing, ignore the assumptions unless there
4666 : : are used user labels in it. */
4667 : 222 : if ((!optimize
4668 : 102 : && !walk_tree_without_duplicates (&CALL_EXPR_ARG (*expr_p,
4669 : : 0),
4670 : : find_used_user_labels,
4671 : : NULL))
4672 : 237 : || seen_error ())
4673 : : {
4674 : 98 : *expr_p = NULL_TREE;
4675 : 98 : return GS_ALL_DONE;
4676 : : }
4677 : : /* Temporarily, until gimple lowering, transform
4678 : : .ASSUME (cond);
4679 : : into:
4680 : : [[assume (guard)]]
4681 : : {
4682 : : guard = cond;
4683 : : }
4684 : : such that gimple lowering can outline the condition into
4685 : : a separate function easily. */
4686 : 124 : tree guard = create_tmp_var (boolean_type_node);
4687 : 124 : *expr_p = build2 (MODIFY_EXPR, void_type_node, guard,
4688 : 124 : gimple_boolify (CALL_EXPR_ARG (*expr_p, 0)));
4689 : 124 : *expr_p = build3 (BIND_EXPR, void_type_node, NULL, *expr_p, NULL);
4690 : 124 : push_gimplify_context ();
4691 : 124 : gimple_seq body = NULL;
4692 : 124 : gimple *g = gimplify_and_return_first (*expr_p, &body);
4693 : 124 : pop_gimplify_context (g);
4694 : 124 : g = gimple_build_assume (guard, body);
4695 : 124 : gimple_set_location (g, loc);
4696 : 124 : gimplify_seq_add_stmt (pre_p, g);
4697 : 124 : *expr_p = NULL_TREE;
4698 : 124 : return GS_ALL_DONE;
4699 : : }
4700 : :
4701 : 46194 : for (i = 0; i < nargs; i++)
4702 : : {
4703 : 24666 : gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p,
4704 : 24666 : EXPR_LOCATION (*expr_p));
4705 : 24666 : vargs.quick_push (CALL_EXPR_ARG (*expr_p, i));
4706 : : }
4707 : :
4708 : 21528 : gcall *call = gimple_build_call_internal_vec (ifn, vargs);
4709 : 21528 : gimple_call_set_nothrow (call, TREE_NOTHROW (*expr_p));
4710 : 21528 : gimplify_seq_add_stmt (pre_p, call);
4711 : 21528 : return GS_ALL_DONE;
4712 : 22043 : }
4713 : : }
4714 : :
4715 : : /* This may be a call to a builtin function.
4716 : :
4717 : : Builtin function calls may be transformed into different
4718 : : (and more efficient) builtin function calls under certain
4719 : : circumstances. Unfortunately, gimplification can muck things
4720 : : up enough that the builtin expanders are not aware that certain
4721 : : transformations are still valid.
4722 : :
4723 : : So we attempt transformation/gimplification of the call before
4724 : : we gimplify the CALL_EXPR. At this time we do not manage to
4725 : : transform all calls in the same manner as the expanders do, but
4726 : : we do transform most of them. */
4727 : 16416889 : fndecl = get_callee_fndecl (*expr_p);
4728 : 16416889 : if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
4729 : 3959810 : switch (DECL_FUNCTION_CODE (fndecl))
4730 : : {
4731 : 94609 : CASE_BUILT_IN_ALLOCA:
4732 : : /* If the call has been built for a variable-sized object, then we
4733 : : want to restore the stack level when the enclosing BIND_EXPR is
4734 : : exited to reclaim the allocated space; otherwise, we precisely
4735 : : need to do the opposite and preserve the latest stack level. */
4736 : 94609 : if (CALL_ALLOCA_FOR_VAR_P (*expr_p))
4737 : 8897 : gimplify_ctxp->save_stack = true;
4738 : : else
4739 : 85712 : gimplify_ctxp->keep_stack = true;
4740 : : break;
4741 : :
4742 : 20775 : case BUILT_IN_VA_START:
4743 : 20775 : {
4744 : 20775 : builtin_va_start_p = true;
4745 : 20775 : if (call_expr_nargs (*expr_p) < 2)
4746 : : {
4747 : 1 : error ("too few arguments to function %<va_start%>");
4748 : 1 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4749 : 1 : return GS_OK;
4750 : : }
4751 : :
4752 : 20774 : if (fold_builtin_next_arg (*expr_p, true))
4753 : : {
4754 : 8 : *expr_p = build_empty_stmt (EXPR_LOCATION (*expr_p));
4755 : 8 : return GS_OK;
4756 : : }
4757 : : break;
4758 : : }
4759 : :
4760 : 30 : case BUILT_IN_EH_RETURN:
4761 : 30 : cfun->calls_eh_return = true;
4762 : 30 : break;
4763 : :
4764 : 1022 : case BUILT_IN_CLEAR_PADDING:
4765 : 1022 : if (call_expr_nargs (*expr_p) == 1)
4766 : : {
4767 : : /* Remember the original type of the argument in an internal
4768 : : dummy second argument, as in GIMPLE pointer conversions are
4769 : : useless. Also mark this call as not for automatic
4770 : : initialization in the internal dummy third argument. */
4771 : 511 : p = CALL_EXPR_ARG (*expr_p, 0);
4772 : 511 : *expr_p
4773 : 511 : = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 2, p,
4774 : 511 : build_zero_cst (TREE_TYPE (p)));
4775 : 511 : return GS_OK;
4776 : : }
4777 : : break;
4778 : :
4779 : : default:
4780 : : ;
4781 : : }
4782 : 16416369 : if (fndecl && fndecl_built_in_p (fndecl))
4783 : : {
4784 : 4194236 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4785 : 4194236 : if (new_tree && new_tree != *expr_p)
4786 : : {
4787 : : /* There was a transformation of this call which computes the
4788 : : same value, but in a more efficient way. Return and try
4789 : : again. */
4790 : 717 : *expr_p = new_tree;
4791 : 717 : return GS_OK;
4792 : : }
4793 : : }
4794 : :
4795 : : /* Remember the original function pointer type. */
4796 : 16415652 : fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
4797 : :
4798 : : /* Handle "declare variant" resolution and arglist processing. */
4799 : 16415652 : if (flag_openmp
4800 : 439715 : && fndecl
4801 : 439013 : && cfun
4802 : 439013 : && (cfun->curr_properties & PROP_gimple_any) == 0
4803 : 242517 : && !omp_has_novariants ()
4804 : 16658063 : && lookup_attribute ("omp declare variant base",
4805 : 242411 : DECL_ATTRIBUTES (fndecl)))
4806 : : {
4807 : 1098 : tree orig = *expr_p;
4808 : 1098 : *expr_p = gimplify_variant_call_expr (*expr_p, fallback,
4809 : : omp_dispatch_p);
4810 : :
4811 : : /* This may resolve to the same call, or the call expr with just
4812 : : the function replaced, in which case we should just continue to
4813 : : gimplify it normally. Otherwise, if we get something else back,
4814 : : stop here and re-gimplify the whole replacement expr. */
4815 : 1098 : if (*expr_p != orig)
4816 : : return GS_OK;
4817 : : }
4818 : :
4819 : : /* There is a sequence point before the call, so any side effects in
4820 : : the calling expression must occur before the actual call. Force
4821 : : gimplify_expr to use an internal post queue. */
4822 : 16415163 : ret = gimplify_expr (&CALL_EXPR_FN (*expr_p), pre_p, NULL,
4823 : : is_gimple_call_addr, fb_rvalue);
4824 : :
4825 : 16415163 : if (ret == GS_ERROR)
4826 : : return GS_ERROR;
4827 : :
4828 : 16415161 : nargs = call_expr_nargs (*expr_p);
4829 : :
4830 : : /* Get argument types for verification. */
4831 : 16415161 : fndecl = get_callee_fndecl (*expr_p);
4832 : 16415161 : parms = NULL_TREE;
4833 : 16415161 : if (fndecl)
4834 : 16194114 : parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
4835 : : else
4836 : 221047 : parms = TYPE_ARG_TYPES (TREE_TYPE (fnptrtype));
4837 : :
4838 : 32609275 : if (fndecl && DECL_ARGUMENTS (fndecl))
4839 : : p = DECL_ARGUMENTS (fndecl);
4840 : 7287169 : else if (parms)
4841 : : p = parms;
4842 : : else
4843 : : p = NULL_TREE;
4844 : 43504396 : for (i = 0; i < nargs && p; i++, p = TREE_CHAIN (p))
4845 : : ;
4846 : :
4847 : : /* If the last argument is __builtin_va_arg_pack () and it is not
4848 : : passed as a named argument, decrease the number of CALL_EXPR
4849 : : arguments and set instead the CALL_EXPR_VA_ARG_PACK flag. */
4850 : 16415161 : if (!p
4851 : 16415161 : && i < nargs
4852 : 16415161 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, nargs - 1)) == CALL_EXPR)
4853 : : {
4854 : 5994 : tree last_arg = CALL_EXPR_ARG (*expr_p, nargs - 1);
4855 : 5994 : tree last_arg_fndecl = get_callee_fndecl (last_arg);
4856 : :
4857 : 5994 : if (last_arg_fndecl
4858 : 5994 : && fndecl_built_in_p (last_arg_fndecl, BUILT_IN_VA_ARG_PACK))
4859 : : {
4860 : 130 : tree call = *expr_p;
4861 : :
4862 : 130 : --nargs;
4863 : 260 : *expr_p = build_call_array_loc (loc, TREE_TYPE (call),
4864 : 130 : CALL_EXPR_FN (call),
4865 : 130 : nargs, CALL_EXPR_ARGP (call));
4866 : :
4867 : : /* Copy all CALL_EXPR flags, location and block, except
4868 : : CALL_EXPR_VA_ARG_PACK flag. */
4869 : 130 : CALL_EXPR_STATIC_CHAIN (*expr_p) = CALL_EXPR_STATIC_CHAIN (call);
4870 : 130 : CALL_EXPR_TAILCALL (*expr_p) = CALL_EXPR_TAILCALL (call);
4871 : 130 : CALL_EXPR_RETURN_SLOT_OPT (*expr_p)
4872 : 130 : = CALL_EXPR_RETURN_SLOT_OPT (call);
4873 : 130 : CALL_FROM_THUNK_P (*expr_p) = CALL_FROM_THUNK_P (call);
4874 : 130 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (call));
4875 : :
4876 : : /* Set CALL_EXPR_VA_ARG_PACK. */
4877 : 130 : CALL_EXPR_VA_ARG_PACK (*expr_p) = 1;
4878 : : }
4879 : : }
4880 : :
4881 : : /* If the call returns twice then after building the CFG the call
4882 : : argument computations will no longer dominate the call because
4883 : : we add an abnormal incoming edge to the call. So do not use SSA
4884 : : vars there. */
4885 : 16415161 : bool returns_twice = call_expr_flags (*expr_p) & ECF_RETURNS_TWICE;
4886 : :
4887 : :
4888 : : /* Gimplify the function arguments. */
4889 : 16415161 : if (nargs > 0)
4890 : : {
4891 : 14231518 : for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
4892 : 42772509 : PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
4893 : 28540991 : PUSH_ARGS_REVERSED ? i-- : i++)
4894 : : {
4895 : 28540991 : enum gimplify_status t;
4896 : :
4897 : : /* Avoid gimplifying the second argument to va_start, which needs to
4898 : : be the plain PARM_DECL. */
4899 : 28540991 : if ((i != 1) || !builtin_va_start_p)
4900 : : {
4901 : 28520225 : tree *arg_p = &CALL_EXPR_ARG (*expr_p, i);
4902 : :
4903 : 28520225 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4904 : 6685 : gimplify_omp_ctxp->in_call_args = true;
4905 : 28520225 : t = gimplify_arg (arg_p, pre_p, EXPR_LOCATION (*expr_p),
4906 : 28520225 : !returns_twice);
4907 : 28520225 : if (gimplify_omp_ctxp && gimplify_omp_ctxp->code == OMP_DISPATCH)
4908 : 6685 : gimplify_omp_ctxp->in_call_args = false;
4909 : :
4910 : 28520225 : if (t == GS_ERROR)
4911 : 28540991 : ret = GS_ERROR;
4912 : : }
4913 : : }
4914 : : }
4915 : :
4916 : : /* Gimplify the static chain. */
4917 : 16415161 : if (CALL_EXPR_STATIC_CHAIN (*expr_p))
4918 : : {
4919 : 28852 : if (fndecl && !DECL_STATIC_CHAIN (fndecl))
4920 : 3 : CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL;
4921 : : else
4922 : : {
4923 : 28173 : enum gimplify_status t;
4924 : 28173 : t = gimplify_arg (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p,
4925 : 28173 : EXPR_LOCATION (*expr_p), ! returns_twice);
4926 : 28173 : if (t == GS_ERROR)
4927 : 16415161 : ret = GS_ERROR;
4928 : : }
4929 : : }
4930 : :
4931 : : /* Verify the function result. */
4932 : 16415161 : if (want_value && fndecl
4933 : 16415161 : && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype))))
4934 : : {
4935 : 0 : error_at (loc, "using result of function returning %<void%>");
4936 : 0 : ret = GS_ERROR;
4937 : : }
4938 : :
4939 : : /* Try this again in case gimplification exposed something. */
4940 : 16415161 : if (ret != GS_ERROR)
4941 : : {
4942 : 16414878 : tree new_tree = fold_call_expr (input_location, *expr_p, !want_value);
4943 : :
4944 : 16414878 : if (new_tree && new_tree != *expr_p)
4945 : : {
4946 : : /* There was a transformation of this call which computes the
4947 : : same value, but in a more efficient way. Return and try
4948 : : again. */
4949 : 11512 : *expr_p = new_tree;
4950 : 11512 : return GS_OK;
4951 : : }
4952 : : }
4953 : : else
4954 : : {
4955 : 283 : *expr_p = error_mark_node;
4956 : 283 : return GS_ERROR;
4957 : : }
4958 : :
4959 : : /* If the function is "const" or "pure", then clear TREE_SIDE_EFFECTS on its
4960 : : decl. This allows us to eliminate redundant or useless
4961 : : calls to "const" functions. */
4962 : 16403366 : if (TREE_CODE (*expr_p) == CALL_EXPR)
4963 : : {
4964 : 16403366 : int flags = call_expr_flags (*expr_p);
4965 : 16403366 : if (flags & (ECF_CONST | ECF_PURE)
4966 : : /* An infinite loop is considered a side effect. */
4967 : 2454708 : && !(flags & (ECF_LOOPING_CONST_OR_PURE)))
4968 : 2044563 : TREE_SIDE_EFFECTS (*expr_p) = 0;
4969 : : }
4970 : :
4971 : : /* If the value is not needed by the caller, emit a new GIMPLE_CALL
4972 : : and clear *EXPR_P. Otherwise, leave *EXPR_P in its gimplified
4973 : : form and delegate the creation of a GIMPLE_CALL to
4974 : : gimplify_modify_expr. This is always possible because when
4975 : : WANT_VALUE is true, the caller wants the result of this call into
4976 : : a temporary, which means that we will emit an INIT_EXPR in
4977 : : internal_get_tmp_var which will then be handled by
4978 : : gimplify_modify_expr. */
4979 : 16403366 : if (!want_value)
4980 : : {
4981 : : /* The CALL_EXPR in *EXPR_P is already in GIMPLE form, so all we
4982 : : have to do is replicate it as a GIMPLE_CALL tuple. */
4983 : 6235906 : gimple_stmt_iterator gsi;
4984 : 6235906 : call = gimple_build_call_from_tree (*expr_p, fnptrtype);
4985 : 6235906 : notice_special_calls (call);
4986 : 6235906 : gimplify_seq_add_stmt (pre_p, call);
4987 : 6235906 : gsi = gsi_last (*pre_p);
4988 : 6235906 : maybe_fold_stmt (&gsi);
4989 : 6235906 : *expr_p = NULL_TREE;
4990 : : }
4991 : : else
4992 : : /* Remember the original function type. */
4993 : 10167460 : CALL_EXPR_FN (*expr_p) = build1 (NOP_EXPR, fnptrtype,
4994 : 10167460 : CALL_EXPR_FN (*expr_p));
4995 : :
4996 : : return ret;
4997 : : }
4998 : :
4999 : : /* Handle shortcut semantics in the predicate operand of a COND_EXPR by
5000 : : rewriting it into multiple COND_EXPRs, and possibly GOTO_EXPRs.
5001 : :
5002 : : TRUE_LABEL_P and FALSE_LABEL_P point to the labels to jump to if the
5003 : : condition is true or false, respectively. If null, we should generate
5004 : : our own to skip over the evaluation of this specific expression.
5005 : :
5006 : : LOCUS is the source location of the COND_EXPR.
5007 : :
5008 : : The condition_uid is a discriminator tag for condition coverage used to map
5009 : : conditions to its corresponding full Boolean function.
5010 : :
5011 : : This function is the tree equivalent of do_jump.
5012 : :
5013 : : shortcut_cond_r should only be called by shortcut_cond_expr. */
5014 : :
5015 : : static tree
5016 : 1335000 : shortcut_cond_r (tree pred, tree *true_label_p, tree *false_label_p,
5017 : : location_t locus, unsigned condition_uid)
5018 : : {
5019 : 1335000 : tree local_label = NULL_TREE;
5020 : 1335000 : tree t, expr = NULL;
5021 : :
5022 : : /* OK, it's not a simple case; we need to pull apart the COND_EXPR to
5023 : : retain the shortcut semantics. Just insert the gotos here;
5024 : : shortcut_cond_expr will append the real blocks later. */
5025 : 1335000 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
5026 : : {
5027 : 127971 : location_t new_locus;
5028 : :
5029 : : /* Turn if (a && b) into
5030 : :
5031 : : if (a); else goto no;
5032 : : if (b) goto yes; else goto no;
5033 : : (no:) */
5034 : :
5035 : 127971 : if (false_label_p == NULL)
5036 : 4038 : false_label_p = &local_label;
5037 : :
5038 : : /* Keep the original source location on the first 'if'. */
5039 : 127971 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), NULL, false_label_p, locus,
5040 : : condition_uid);
5041 : 127971 : append_to_statement_list (t, &expr);
5042 : :
5043 : : /* Set the source location of the && on the second 'if'. */
5044 : 127971 : new_locus = rexpr_location (pred, locus);
5045 : 127971 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
5046 : : new_locus, condition_uid);
5047 : 127971 : append_to_statement_list (t, &expr);
5048 : : }
5049 : 1207029 : else if (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5050 : : {
5051 : 382681 : location_t new_locus;
5052 : :
5053 : : /* Turn if (a || b) into
5054 : :
5055 : : if (a) goto yes;
5056 : : if (b) goto yes; else goto no;
5057 : : (yes:) */
5058 : :
5059 : 382681 : if (true_label_p == NULL)
5060 : 229892 : true_label_p = &local_label;
5061 : :
5062 : : /* Keep the original source location on the first 'if'. */
5063 : 382681 : t = shortcut_cond_r (TREE_OPERAND (pred, 0), true_label_p, NULL, locus,
5064 : : condition_uid);
5065 : 382681 : append_to_statement_list (t, &expr);
5066 : :
5067 : : /* Set the source location of the || on the second 'if'. */
5068 : 382681 : new_locus = rexpr_location (pred, locus);
5069 : 382681 : t = shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p, false_label_p,
5070 : : new_locus, condition_uid);
5071 : 382681 : append_to_statement_list (t, &expr);
5072 : : }
5073 : 824348 : else if (TREE_CODE (pred) == COND_EXPR
5074 : 848 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 1)))
5075 : 825196 : && !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (pred, 2))))
5076 : : {
5077 : 842 : location_t new_locus;
5078 : :
5079 : : /* As long as we're messing with gotos, turn if (a ? b : c) into
5080 : : if (a)
5081 : : if (b) goto yes; else goto no;
5082 : : else
5083 : : if (c) goto yes; else goto no;
5084 : :
5085 : : Don't do this if one of the arms has void type, which can happen
5086 : : in C++ when the arm is throw. */
5087 : :
5088 : : /* Keep the original source location on the first 'if'. Set the source
5089 : : location of the ? on the second 'if'. */
5090 : 842 : new_locus = rexpr_location (pred, locus);
5091 : 1684 : expr = build3 (COND_EXPR, void_type_node, TREE_OPERAND (pred, 0),
5092 : 842 : shortcut_cond_r (TREE_OPERAND (pred, 1), true_label_p,
5093 : : false_label_p, locus, condition_uid),
5094 : 842 : shortcut_cond_r (TREE_OPERAND (pred, 2), true_label_p,
5095 : : false_label_p, new_locus,
5096 : : condition_uid));
5097 : 842 : tree_associate_condition_with_expr (expr, condition_uid);
5098 : : }
5099 : : else
5100 : : {
5101 : 823506 : expr = build3 (COND_EXPR, void_type_node, pred,
5102 : : build_and_jump (true_label_p),
5103 : : build_and_jump (false_label_p));
5104 : 823506 : SET_EXPR_LOCATION (expr, locus);
5105 : 823506 : tree_associate_condition_with_expr (expr, condition_uid);
5106 : : }
5107 : :
5108 : 1335000 : if (local_label)
5109 : : {
5110 : 233930 : t = build1 (LABEL_EXPR, void_type_node, local_label);
5111 : 233930 : append_to_statement_list (t, &expr);
5112 : : }
5113 : :
5114 : 1335000 : return expr;
5115 : : }
5116 : :
5117 : : /* If EXPR is a GOTO_EXPR, return it. If it is a STATEMENT_LIST, skip
5118 : : any of its leading DEBUG_BEGIN_STMTS and recurse on the subsequent
5119 : : statement, if it is the last one. Otherwise, return NULL. */
5120 : :
5121 : : static tree
5122 : 11461980 : find_goto (tree expr)
5123 : : {
5124 : 11775008 : if (!expr)
5125 : : return NULL_TREE;
5126 : :
5127 : 9829089 : if (TREE_CODE (expr) == GOTO_EXPR)
5128 : : return expr;
5129 : :
5130 : 7838843 : if (TREE_CODE (expr) != STATEMENT_LIST)
5131 : : return NULL_TREE;
5132 : :
5133 : 1001031 : tree_stmt_iterator i = tsi_start (expr);
5134 : :
5135 : 1343684 : while (!tsi_end_p (i) && TREE_CODE (tsi_stmt (i)) == DEBUG_BEGIN_STMT)
5136 : 342653 : tsi_next (&i);
5137 : :
5138 : 10375110 : if (!tsi_one_before_end_p (i))
5139 : : return NULL_TREE;
5140 : :
5141 : 313028 : return find_goto (tsi_stmt (i));
5142 : : }
5143 : :
5144 : : /* Same as find_goto, except that it returns NULL if the destination
5145 : : is not a LABEL_DECL. */
5146 : :
5147 : : static inline tree
5148 : 11461980 : find_goto_label (tree expr)
5149 : : {
5150 : 11461980 : tree dest = find_goto (expr);
5151 : 13452226 : if (dest && TREE_CODE (GOTO_DESTINATION (dest)) == LABEL_DECL)
5152 : 1990135 : return dest;
5153 : : return NULL_TREE;
5154 : : }
5155 : :
5156 : :
5157 : : /* Given a multi-term condition (ANDIF, ORIF), walk the predicate PRED and tag
5158 : : every basic condition with CONDITION_UID. Two basic conditions share the
5159 : : CONDITION_UID discriminator when they belong to the same predicate, which is
5160 : : used by the condition coverage. Doing this as an explicit step makes for a
5161 : : simpler implementation than weaving it into the splitting code as the
5162 : : splitting code eventually calls the entry point gimplfiy_expr which makes
5163 : : bookkeeping complicated. */
5164 : : static void
5165 : 573399 : tag_shortcut_cond (tree pred, unsigned condition_uid)
5166 : : {
5167 : 612079 : if (TREE_CODE (pred) == TRUTH_ANDIF_EXPR
5168 : 612079 : || TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5169 : : {
5170 : 563360 : tree fst = TREE_OPERAND (pred, 0);
5171 : 563360 : tree lst = TREE_OPERAND (pred, 1);
5172 : :
5173 : 563360 : if (TREE_CODE (fst) == TRUTH_ANDIF_EXPR
5174 : 563360 : || TREE_CODE (fst) == TRUTH_ORIF_EXPR)
5175 : 167585 : tag_shortcut_cond (fst, condition_uid);
5176 : 395775 : else if (TREE_CODE (fst) == COND_EXPR)
5177 : 244 : tree_associate_condition_with_expr (fst, condition_uid);
5178 : :
5179 : 563360 : if (TREE_CODE (lst) == TRUTH_ANDIF_EXPR
5180 : 563360 : || TREE_CODE (lst) == TRUTH_ORIF_EXPR)
5181 : : tag_shortcut_cond (lst, condition_uid);
5182 : 524680 : else if (TREE_CODE (lst) == COND_EXPR)
5183 : 438 : tree_associate_condition_with_expr (lst, condition_uid);
5184 : : }
5185 : 573399 : }
5186 : :
5187 : : /* Given a conditional expression EXPR with short-circuit boolean
5188 : : predicates using TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR, break the
5189 : : predicate apart into the equivalent sequence of conditionals. CONDITION_UID
5190 : : is a the tag/discriminator for this EXPR - all basic conditions in the
5191 : : expression will be given the same CONDITION_UID. */
5192 : : static tree
5193 : 405814 : shortcut_cond_expr (tree expr, unsigned condition_uid)
5194 : : {
5195 : 405814 : tree pred = TREE_OPERAND (expr, 0);
5196 : 405814 : tree then_ = TREE_OPERAND (expr, 1);
5197 : 405814 : tree else_ = TREE_OPERAND (expr, 2);
5198 : 405814 : tree true_label, false_label, end_label, t;
5199 : 405814 : tree *true_label_p;
5200 : 405814 : tree *false_label_p;
5201 : 405814 : bool emit_end, emit_false, jump_over_else;
5202 : 405814 : bool then_se = then_ && TREE_SIDE_EFFECTS (then_);
5203 : 405814 : bool else_se = else_ && TREE_SIDE_EFFECTS (else_);
5204 : :
5205 : 405814 : tag_shortcut_cond (pred, condition_uid);
5206 : :
5207 : : /* First do simple transformations. */
5208 : 405814 : if (!else_se)
5209 : : {
5210 : : /* If there is no 'else', turn
5211 : : if (a && b) then c
5212 : : into
5213 : : if (a) if (b) then c. */
5214 : 287683 : while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR)
5215 : : {
5216 : : /* Keep the original source location on the first 'if'. */
5217 : 49537 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5218 : 49537 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5219 : : /* Set the source location of the && on the second 'if'. */
5220 : 49537 : if (rexpr_has_location (pred))
5221 : 48517 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5222 : 49537 : then_ = shortcut_cond_expr (expr, condition_uid);
5223 : 49537 : then_se = then_ && TREE_SIDE_EFFECTS (then_);
5224 : 49537 : pred = TREE_OPERAND (pred, 0);
5225 : 49537 : expr = build3 (COND_EXPR, void_type_node, pred, then_, NULL_TREE);
5226 : 49537 : SET_EXPR_LOCATION (expr, locus);
5227 : : }
5228 : : }
5229 : :
5230 : 405814 : if (!then_se)
5231 : : {
5232 : : /* If there is no 'then', turn
5233 : : if (a || b); else d
5234 : : into
5235 : : if (a); else if (b); else d. */
5236 : 26590 : while (TREE_CODE (pred) == TRUTH_ORIF_EXPR)
5237 : : {
5238 : : /* Keep the original source location on the first 'if'. */
5239 : 818 : location_t locus = EXPR_LOC_OR_LOC (expr, input_location);
5240 : 818 : TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1);
5241 : : /* Set the source location of the || on the second 'if'. */
5242 : 818 : if (rexpr_has_location (pred))
5243 : 817 : SET_EXPR_LOCATION (expr, rexpr_location (pred));
5244 : 818 : else_ = shortcut_cond_expr (expr, condition_uid);
5245 : 818 : else_se = else_ && TREE_SIDE_EFFECTS (else_);
5246 : 818 : pred = TREE_OPERAND (pred, 0);
5247 : 818 : expr = build3 (COND_EXPR, void_type_node, pred, NULL_TREE, else_);
5248 : 818 : SET_EXPR_LOCATION (expr, locus);
5249 : : }
5250 : : }
5251 : :
5252 : : /* The expr tree should also have the expression id set. */
5253 : 405814 : tree_associate_condition_with_expr (expr, condition_uid);
5254 : :
5255 : : /* If we're done, great. */
5256 : 405814 : if (TREE_CODE (pred) != TRUTH_ANDIF_EXPR
5257 : 405814 : && TREE_CODE (pred) != TRUTH_ORIF_EXPR)
5258 : 93802 : return expr;
5259 : :
5260 : : /* Otherwise we need to mess with gotos. Change
5261 : : if (a) c; else d;
5262 : : to
5263 : : if (a); else goto no;
5264 : : c; goto end;
5265 : : no: d; end:
5266 : : and recursively gimplify the condition. */
5267 : :
5268 : 312012 : true_label = false_label = end_label = NULL_TREE;
5269 : :
5270 : : /* If our arms just jump somewhere, hijack those labels so we don't
5271 : : generate jumps to jumps. */
5272 : :
5273 : 312012 : if (tree then_goto = find_goto_label (then_))
5274 : : {
5275 : 4600 : true_label = GOTO_DESTINATION (then_goto);
5276 : 4600 : then_ = NULL;
5277 : 4600 : then_se = false;
5278 : : }
5279 : :
5280 : 312012 : if (tree else_goto = find_goto_label (else_))
5281 : : {
5282 : 4193 : false_label = GOTO_DESTINATION (else_goto);
5283 : 4193 : else_ = NULL;
5284 : 4193 : else_se = false;
5285 : : }
5286 : :
5287 : : /* If we aren't hijacking a label for the 'then' branch, it falls through. */
5288 : 312012 : if (true_label)
5289 : : true_label_p = &true_label;
5290 : : else
5291 : 307412 : true_label_p = NULL;
5292 : :
5293 : : /* The 'else' branch also needs a label if it contains interesting code. */
5294 : 312012 : if (false_label || else_se)
5295 : : false_label_p = &false_label;
5296 : : else
5297 : : false_label_p = NULL;
5298 : :
5299 : : /* If there was nothing else in our arms, just forward the label(s). */
5300 : 149550 : if (!then_se && !else_se)
5301 : 8530 : return shortcut_cond_r (pred, true_label_p, false_label_p,
5302 : 12795 : EXPR_LOC_OR_LOC (expr, input_location), condition_uid);
5303 : :
5304 : : /* If our last subexpression already has a terminal label, reuse it. */
5305 : 307747 : if (else_se)
5306 : 162462 : t = expr_last (else_);
5307 : 145285 : else if (then_se)
5308 : 145285 : t = expr_last (then_);
5309 : : else
5310 : : t = NULL;
5311 : 307747 : if (t && TREE_CODE (t) == LABEL_EXPR)
5312 : 946 : end_label = LABEL_EXPR_LABEL (t);
5313 : :
5314 : : /* If we don't care about jumping to the 'else' branch, jump to the end
5315 : : if the condition is false. */
5316 : 307747 : if (!false_label_p)
5317 : 145043 : false_label_p = &end_label;
5318 : :
5319 : : /* We only want to emit these labels if we aren't hijacking them. */
5320 : 307747 : emit_end = (end_label == NULL_TREE);
5321 : 307747 : emit_false = (false_label == NULL_TREE);
5322 : :
5323 : : /* We only emit the jump over the else clause if we have to--if the
5324 : : then clause may fall through. Otherwise we can wind up with a
5325 : : useless jump and a useless label at the end of gimplified code,
5326 : : which will cause us to think that this conditional as a whole
5327 : : falls through even if it doesn't. If we then inline a function
5328 : : which ends with such a condition, that can cause us to issue an
5329 : : inappropriate warning about control reaching the end of a
5330 : : non-void function. */
5331 : 307747 : jump_over_else = block_may_fallthru (then_);
5332 : :
5333 : 614871 : pred = shortcut_cond_r (pred, true_label_p, false_label_p,
5334 : 614871 : EXPR_LOC_OR_LOC (expr, input_location),
5335 : : condition_uid);
5336 : :
5337 : 307747 : expr = NULL;
5338 : 307747 : append_to_statement_list (pred, &expr);
5339 : :
5340 : 307747 : append_to_statement_list (then_, &expr);
5341 : 307747 : if (else_se)
5342 : : {
5343 : 162462 : if (jump_over_else)
5344 : : {
5345 : 159958 : tree last = expr_last (expr);
5346 : 159958 : t = build_and_jump (&end_label);
5347 : 159958 : if (rexpr_has_location (last))
5348 : 39836 : SET_EXPR_LOCATION (t, rexpr_location (last));
5349 : 159958 : append_to_statement_list (t, &expr);
5350 : : }
5351 : 162462 : if (emit_false)
5352 : : {
5353 : 162462 : t = build1 (LABEL_EXPR, void_type_node, false_label);
5354 : 162462 : append_to_statement_list (t, &expr);
5355 : : }
5356 : 162462 : append_to_statement_list (else_, &expr);
5357 : : }
5358 : 307747 : if (emit_end && end_label)
5359 : : {
5360 : 304060 : t = build1 (LABEL_EXPR, void_type_node, end_label);
5361 : 304060 : append_to_statement_list (t, &expr);
5362 : : }
5363 : :
5364 : 307747 : return expr;
5365 : : }
5366 : :
5367 : : /* EXPR is used in a boolean context; make sure it has BOOLEAN_TYPE. */
5368 : :
5369 : : tree
5370 : 16436073 : gimple_boolify (tree expr)
5371 : : {
5372 : 16436073 : tree type = TREE_TYPE (expr);
5373 : 16436073 : location_t loc = EXPR_LOCATION (expr);
5374 : :
5375 : 16436073 : if (TREE_CODE (expr) == NE_EXPR
5376 : 5663426 : && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR
5377 : 17367822 : && integer_zerop (TREE_OPERAND (expr, 1)))
5378 : : {
5379 : 481143 : tree call = TREE_OPERAND (expr, 0);
5380 : 481143 : tree fn = get_callee_fndecl (call);
5381 : :
5382 : : /* For __builtin_expect ((long) (x), y) recurse into x as well
5383 : : if x is truth_value_p. */
5384 : 481143 : if (fn
5385 : 480562 : && fndecl_built_in_p (fn, BUILT_IN_EXPECT)
5386 : 609534 : && call_expr_nargs (call) == 2)
5387 : : {
5388 : 128391 : tree arg = CALL_EXPR_ARG (call, 0);
5389 : 128391 : if (arg)
5390 : : {
5391 : 128391 : if (TREE_CODE (arg) == NOP_EXPR
5392 : 128391 : && TREE_TYPE (arg) == TREE_TYPE (call))
5393 : 62153 : arg = TREE_OPERAND (arg, 0);
5394 : 128391 : if (truth_value_p (TREE_CODE (arg)))
5395 : : {
5396 : 106172 : arg = gimple_boolify (arg);
5397 : 106172 : CALL_EXPR_ARG (call, 0)
5398 : 212344 : = fold_convert_loc (loc, TREE_TYPE (call), arg);
5399 : : }
5400 : : }
5401 : : }
5402 : : }
5403 : :
5404 : 16436073 : switch (TREE_CODE (expr))
5405 : : {
5406 : 1237235 : case TRUTH_AND_EXPR:
5407 : 1237235 : case TRUTH_OR_EXPR:
5408 : 1237235 : case TRUTH_XOR_EXPR:
5409 : 1237235 : case TRUTH_ANDIF_EXPR:
5410 : 1237235 : case TRUTH_ORIF_EXPR:
5411 : : /* Also boolify the arguments of truth exprs. */
5412 : 1237235 : TREE_OPERAND (expr, 1) = gimple_boolify (TREE_OPERAND (expr, 1));
5413 : : /* FALLTHRU */
5414 : :
5415 : 1653724 : case TRUTH_NOT_EXPR:
5416 : 1653724 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5417 : :
5418 : : /* These expressions always produce boolean results. */
5419 : 1653724 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5420 : 306816 : TREE_TYPE (expr) = boolean_type_node;
5421 : : return expr;
5422 : :
5423 : 5177 : case ANNOTATE_EXPR:
5424 : 5177 : switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1)))
5425 : : {
5426 : 5177 : case annot_expr_ivdep_kind:
5427 : 5177 : case annot_expr_unroll_kind:
5428 : 5177 : case annot_expr_no_vector_kind:
5429 : 5177 : case annot_expr_vector_kind:
5430 : 5177 : case annot_expr_parallel_kind:
5431 : 5177 : case annot_expr_maybe_infinite_kind:
5432 : 5177 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5433 : 5177 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5434 : 3239 : TREE_TYPE (expr) = boolean_type_node;
5435 : : return expr;
5436 : 0 : default:
5437 : 0 : gcc_unreachable ();
5438 : : }
5439 : :
5440 : 14777172 : default:
5441 : 14777172 : if (COMPARISON_CLASS_P (expr))
5442 : : {
5443 : : /* These expressions always produce boolean results. */
5444 : 12942353 : if (TREE_CODE (type) != BOOLEAN_TYPE)
5445 : 1568570 : TREE_TYPE (expr) = boolean_type_node;
5446 : 12942353 : return expr;
5447 : : }
5448 : : /* Other expressions that get here must have boolean values, but
5449 : : might need to be converted to the appropriate mode. */
5450 : 1834819 : if (TREE_CODE (type) == BOOLEAN_TYPE)
5451 : : return expr;
5452 : 199721 : return fold_convert_loc (loc, boolean_type_node, expr);
5453 : : }
5454 : : }
5455 : :
5456 : : /* Given a conditional expression *EXPR_P without side effects, gimplify
5457 : : its operands. New statements are inserted to PRE_P. */
5458 : :
5459 : : static enum gimplify_status
5460 : 45969 : gimplify_pure_cond_expr (tree *expr_p, gimple_seq *pre_p)
5461 : : {
5462 : 45969 : tree expr = *expr_p, cond;
5463 : 45969 : enum gimplify_status ret, tret;
5464 : 45969 : enum tree_code code;
5465 : :
5466 : 45969 : cond = gimple_boolify (COND_EXPR_COND (expr));
5467 : :
5468 : : /* We need to handle && and || specially, as their gimplification
5469 : : creates pure cond_expr, thus leading to an infinite cycle otherwise. */
5470 : 45969 : code = TREE_CODE (cond);
5471 : 45969 : if (code == TRUTH_ANDIF_EXPR)
5472 : 32 : TREE_SET_CODE (cond, TRUTH_AND_EXPR);
5473 : 45937 : else if (code == TRUTH_ORIF_EXPR)
5474 : 4588 : TREE_SET_CODE (cond, TRUTH_OR_EXPR);
5475 : 45969 : ret = gimplify_expr (&cond, pre_p, NULL, is_gimple_val, fb_rvalue);
5476 : 45969 : COND_EXPR_COND (*expr_p) = cond;
5477 : :
5478 : 45969 : tret = gimplify_expr (&COND_EXPR_THEN (expr), pre_p, NULL,
5479 : : is_gimple_val, fb_rvalue);
5480 : 45969 : ret = MIN (ret, tret);
5481 : 45969 : tret = gimplify_expr (&COND_EXPR_ELSE (expr), pre_p, NULL,
5482 : : is_gimple_val, fb_rvalue);
5483 : :
5484 : 45969 : return MIN (ret, tret);
5485 : : }
5486 : :
5487 : : /* Return true if evaluating EXPR could trap.
5488 : : EXPR is GENERIC, while tree_could_trap_p can be called
5489 : : only on GIMPLE. */
5490 : :
5491 : : bool
5492 : 13268318 : generic_expr_could_trap_p (tree expr)
5493 : : {
5494 : 13268318 : unsigned i, n;
5495 : :
5496 : 13268318 : if (!expr || is_gimple_val (expr))
5497 : 5455499 : return false;
5498 : :
5499 : 7812819 : if (!EXPR_P (expr) || tree_could_trap_p (expr))
5500 : 2414799 : return true;
5501 : :
5502 : 5398020 : n = TREE_OPERAND_LENGTH (expr);
5503 : 12151436 : for (i = 0; i < n; i++)
5504 : 9041334 : if (generic_expr_could_trap_p (TREE_OPERAND (expr, i)))
5505 : : return true;
5506 : :
5507 : : return false;
5508 : : }
5509 : :
5510 : : /* Associate the condition STMT with the discriminator UID. STMTs that are
5511 : : broken down with ANDIF/ORIF from the same Boolean expression should be given
5512 : : the same UID; 'if (a && b && c) { if (d || e) ... } ...' should yield the
5513 : : { a: 1, b: 1, c: 1, d: 2, e: 2 } when gimplification is done. This is used
5514 : : for condition coverage. */
5515 : : static void
5516 : 5418978 : gimple_associate_condition_with_expr (struct function *fn, gcond *stmt,
5517 : : unsigned uid)
5518 : : {
5519 : 5418978 : if (!condition_coverage_flag)
5520 : : return;
5521 : :
5522 : 636 : if (!fn->cond_uids)
5523 : 135 : fn->cond_uids = new hash_map <gcond*, unsigned> ();
5524 : :
5525 : 636 : fn->cond_uids->put (stmt, uid);
5526 : : }
5527 : :
5528 : : /* Convert the conditional expression pointed to by EXPR_P '(p) ? a : b;'
5529 : : into
5530 : :
5531 : : if (p) if (p)
5532 : : t1 = a; a;
5533 : : else or else
5534 : : t1 = b; b;
5535 : : t1;
5536 : :
5537 : : The second form is used when *EXPR_P is of type void.
5538 : :
5539 : : PRE_P points to the list where side effects that must happen before
5540 : : *EXPR_P should be stored. */
5541 : :
5542 : : static enum gimplify_status
5543 : 6193480 : gimplify_cond_expr (tree *expr_p, gimple_seq *pre_p, fallback_t fallback)
5544 : : {
5545 : 6193480 : tree expr = *expr_p;
5546 : 6193480 : tree type = TREE_TYPE (expr);
5547 : 6193480 : location_t loc = EXPR_LOCATION (expr);
5548 : 6193480 : tree tmp, arm1, arm2;
5549 : 6193480 : enum gimplify_status ret;
5550 : 6193480 : tree label_true, label_false, label_cont;
5551 : 6193480 : bool have_then_clause_p, have_else_clause_p;
5552 : 6193480 : gcond *cond_stmt;
5553 : 6193480 : enum tree_code pred_code;
5554 : 6193480 : gimple_seq seq = NULL;
5555 : :
5556 : : /* If this COND_EXPR has a value, copy the values into a temporary within
5557 : : the arms. */
5558 : 6193480 : if (!VOID_TYPE_P (type))
5559 : : {
5560 : 418276 : tree then_ = TREE_OPERAND (expr, 1), else_ = TREE_OPERAND (expr, 2);
5561 : 418276 : tree result;
5562 : :
5563 : : /* If either an rvalue is ok or we do not require an lvalue, create the
5564 : : temporary. But we cannot do that if the type is addressable. */
5565 : 418276 : if (((fallback & fb_rvalue) || !(fallback & fb_lvalue))
5566 : 418269 : && !TREE_ADDRESSABLE (type))
5567 : : {
5568 : 418269 : if (gimplify_ctxp->allow_rhs_cond_expr
5569 : : /* If either branch has side effects or could trap, it can't be
5570 : : evaluated unconditionally. */
5571 : 45969 : && !TREE_SIDE_EFFECTS (then_)
5572 : 45969 : && !generic_expr_could_trap_p (then_)
5573 : 45969 : && !TREE_SIDE_EFFECTS (else_)
5574 : 464238 : && !generic_expr_could_trap_p (else_))
5575 : 45969 : return gimplify_pure_cond_expr (expr_p, pre_p);
5576 : :
5577 : 372300 : tmp = create_tmp_var (type, "iftmp");
5578 : 372300 : result = tmp;
5579 : : }
5580 : :
5581 : : /* Otherwise, only create and copy references to the values. */
5582 : : else
5583 : : {
5584 : 7 : type = build_pointer_type (type);
5585 : :
5586 : 7 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5587 : 7 : then_ = build_fold_addr_expr_loc (loc, then_);
5588 : :
5589 : 7 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5590 : 7 : else_ = build_fold_addr_expr_loc (loc, else_);
5591 : :
5592 : 7 : expr
5593 : 7 : = build3 (COND_EXPR, type, TREE_OPERAND (expr, 0), then_, else_);
5594 : :
5595 : 7 : tmp = create_tmp_var (type, "iftmp");
5596 : 7 : result = build_simple_mem_ref_loc (loc, tmp);
5597 : : }
5598 : :
5599 : : /* Build the new then clause, `tmp = then_;'. But don't build the
5600 : : assignment if the value is void; in C++ it can be if it's a throw. */
5601 : 372307 : if (!VOID_TYPE_P (TREE_TYPE (then_)))
5602 : 290747 : TREE_OPERAND (expr, 1) = build2 (INIT_EXPR, type, tmp, then_);
5603 : :
5604 : : /* Similarly, build the new else clause, `tmp = else_;'. */
5605 : 372307 : if (!VOID_TYPE_P (TREE_TYPE (else_)))
5606 : 361681 : TREE_OPERAND (expr, 2) = build2 (INIT_EXPR, type, tmp, else_);
5607 : :
5608 : 372307 : TREE_TYPE (expr) = void_type_node;
5609 : 372307 : recalculate_side_effects (expr);
5610 : :
5611 : : /* Move the COND_EXPR to the prequeue. */
5612 : 372307 : gimplify_stmt (&expr, pre_p);
5613 : :
5614 : 372307 : *expr_p = result;
5615 : 372307 : return GS_ALL_DONE;
5616 : : }
5617 : :
5618 : : /* Remove any COMPOUND_EXPR so the following cases will be caught. */
5619 : 5789768 : STRIP_TYPE_NOPS (TREE_OPERAND (expr, 0));
5620 : 5775204 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == COMPOUND_EXPR)
5621 : 80349 : gimplify_compound_expr (&TREE_OPERAND (expr, 0), pre_p, true);
5622 : :
5623 : : /* Make sure the condition has BOOLEAN_TYPE. */
5624 : 5775204 : TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
5625 : :
5626 : : /* Break apart && and || conditions. */
5627 : 5775204 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ANDIF_EXPR
5628 : 5775204 : || TREE_CODE (TREE_OPERAND (expr, 0)) == TRUTH_ORIF_EXPR)
5629 : : {
5630 : 355459 : expr = shortcut_cond_expr (expr, next_cond_uid ());
5631 : :
5632 : 355459 : if (expr != *expr_p)
5633 : : {
5634 : 355459 : *expr_p = expr;
5635 : :
5636 : : /* We can't rely on gimplify_expr to re-gimplify the expanded
5637 : : form properly, as cleanups might cause the target labels to be
5638 : : wrapped in a TRY_FINALLY_EXPR. To prevent that, we need to
5639 : : set up a conditional context. */
5640 : 355459 : gimple_push_condition ();
5641 : 355459 : gimplify_stmt (expr_p, &seq);
5642 : 355459 : gimple_pop_condition (pre_p);
5643 : 355459 : gimple_seq_add_seq (pre_p, seq);
5644 : :
5645 : 355459 : return GS_ALL_DONE;
5646 : : }
5647 : : }
5648 : :
5649 : : /* Now do the normal gimplification. */
5650 : :
5651 : : /* Gimplify condition. */
5652 : 5419745 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, NULL,
5653 : : is_gimple_condexpr_for_cond, fb_rvalue);
5654 : 5419745 : if (ret == GS_ERROR)
5655 : : return GS_ERROR;
5656 : 5418978 : gcc_assert (TREE_OPERAND (expr, 0) != NULL_TREE);
5657 : :
5658 : 5418978 : gimple_push_condition ();
5659 : :
5660 : 5418978 : have_then_clause_p = have_else_clause_p = false;
5661 : 5418978 : label_true = find_goto_label (TREE_OPERAND (expr, 1));
5662 : 5418978 : if (label_true
5663 : 1257705 : && DECL_CONTEXT (GOTO_DESTINATION (label_true)) == current_function_decl
5664 : : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5665 : : have different locations, otherwise we end up with incorrect
5666 : : location information on the branches. */
5667 : 6676683 : && (optimize
5668 : 224046 : || !EXPR_HAS_LOCATION (expr)
5669 : 197266 : || !rexpr_has_location (label_true)
5670 : 65919 : || EXPR_LOCATION (expr) == rexpr_location (label_true)))
5671 : : {
5672 : 1256557 : have_then_clause_p = true;
5673 : 1256557 : label_true = GOTO_DESTINATION (label_true);
5674 : : }
5675 : : else
5676 : 4162421 : label_true = create_artificial_label (UNKNOWN_LOCATION);
5677 : 5418978 : label_false = find_goto_label (TREE_OPERAND (expr, 2));
5678 : 5418978 : if (label_false
5679 : 723637 : && DECL_CONTEXT (GOTO_DESTINATION (label_false)) == current_function_decl
5680 : : /* For -O0 avoid this optimization if the COND_EXPR and GOTO_EXPR
5681 : : have different locations, otherwise we end up with incorrect
5682 : : location information on the branches. */
5683 : 6142615 : && (optimize
5684 : 100003 : || !EXPR_HAS_LOCATION (expr)
5685 : 99154 : || !rexpr_has_location (label_false)
5686 : 142 : || EXPR_LOCATION (expr) == rexpr_location (label_false)))
5687 : : {
5688 : 723507 : have_else_clause_p = true;
5689 : 723507 : label_false = GOTO_DESTINATION (label_false);
5690 : : }
5691 : : else
5692 : 4695471 : label_false = create_artificial_label (UNKNOWN_LOCATION);
5693 : :
5694 : 5418978 : unsigned cond_uid = 0;
5695 : 5418978 : if (cond_uids)
5696 : 455 : if (unsigned *v = cond_uids->get (expr))
5697 : 435 : cond_uid = *v;
5698 : 435 : if (cond_uid == 0)
5699 : 5418543 : cond_uid = next_cond_uid ();
5700 : :
5701 : 5418978 : gimple_cond_get_ops_from_tree (COND_EXPR_COND (expr), &pred_code, &arm1,
5702 : : &arm2);
5703 : 5418978 : cond_stmt = gimple_build_cond (pred_code, arm1, arm2, label_true,
5704 : : label_false);
5705 : 5418978 : gimple_set_location (cond_stmt, EXPR_LOCATION (expr));
5706 : 5418978 : gimple_associate_condition_with_expr (cfun, cond_stmt, cond_uid);
5707 : 5418978 : copy_warning (cond_stmt, COND_EXPR_COND (expr));
5708 : 5418978 : gimplify_seq_add_stmt (&seq, cond_stmt);
5709 : 5418978 : gimple_stmt_iterator gsi = gsi_last (seq);
5710 : 5418978 : maybe_fold_stmt (&gsi);
5711 : :
5712 : 5418978 : label_cont = NULL_TREE;
5713 : 5418978 : if (!have_then_clause_p)
5714 : : {
5715 : : /* For if (...) {} else { code; } put label_true after
5716 : : the else block. */
5717 : 4162421 : if (TREE_OPERAND (expr, 1) == NULL_TREE
5718 : 207595 : && !have_else_clause_p
5719 : 4163212 : && TREE_OPERAND (expr, 2) != NULL_TREE)
5720 : : {
5721 : : /* For if (0) {} else { code; } tell -Wimplicit-fallthrough
5722 : : handling that label_cont == label_true can be only reached
5723 : : through fallthrough from { code; }. */
5724 : 791 : if (integer_zerop (COND_EXPR_COND (expr)))
5725 : 0 : UNUSED_LABEL_P (label_true) = 1;
5726 : : label_cont = label_true;
5727 : : }
5728 : : else
5729 : : {
5730 : 4161630 : bool then_side_effects
5731 : 4161630 : = (TREE_OPERAND (expr, 1)
5732 : 4161630 : && TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)));
5733 : 4161630 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_true));
5734 : 4161630 : have_then_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 1), &seq);
5735 : : /* For if (...) { code; } else {} or
5736 : : if (...) { code; } else goto label; or
5737 : : if (...) { code; return; } else { ... }
5738 : : label_cont isn't needed. */
5739 : 4161630 : if (!have_else_clause_p
5740 : 3953674 : && TREE_OPERAND (expr, 2) != NULL_TREE
5741 : 6907314 : && gimple_seq_may_fallthru (seq))
5742 : : {
5743 : 1922283 : gimple *g;
5744 : 1922283 : label_cont = create_artificial_label (UNKNOWN_LOCATION);
5745 : :
5746 : : /* For if (0) { non-side-effect-code } else { code }
5747 : : tell -Wimplicit-fallthrough handling that label_cont can
5748 : : be only reached through fallthrough from { code }. */
5749 : 1922283 : if (integer_zerop (COND_EXPR_COND (expr)))
5750 : : {
5751 : 67095 : UNUSED_LABEL_P (label_true) = 1;
5752 : 67095 : if (!then_side_effects)
5753 : 11466 : UNUSED_LABEL_P (label_cont) = 1;
5754 : : }
5755 : :
5756 : 1922283 : g = gimple_build_goto (label_cont);
5757 : :
5758 : : /* GIMPLE_COND's are very low level; they have embedded
5759 : : gotos. This particular embedded goto should not be marked
5760 : : with the location of the original COND_EXPR, as it would
5761 : : correspond to the COND_EXPR's condition, not the ELSE or the
5762 : : THEN arms. To avoid marking it with the wrong location, flag
5763 : : it as "no location". */
5764 : 1922283 : gimple_set_do_not_emit_location (g);
5765 : :
5766 : 1922283 : gimplify_seq_add_stmt (&seq, g);
5767 : : }
5768 : : }
5769 : : }
5770 : 5418978 : if (!have_else_clause_p)
5771 : : {
5772 : : /* For if (1) { code } or if (1) { code } else { non-side-effect-code }
5773 : : tell -Wimplicit-fallthrough handling that label_false can be only
5774 : : reached through fallthrough from { code }. */
5775 : 4695471 : if (integer_nonzerop (COND_EXPR_COND (expr))
5776 : 4695471 : && (TREE_OPERAND (expr, 2) == NULL_TREE
5777 : 56554 : || !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 2))))
5778 : 6979 : UNUSED_LABEL_P (label_false) = 1;
5779 : 4695471 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_false));
5780 : 4695471 : have_else_clause_p = gimplify_stmt (&TREE_OPERAND (expr, 2), &seq);
5781 : : }
5782 : 5418978 : if (label_cont)
5783 : 1923074 : gimplify_seq_add_stmt (&seq, gimple_build_label (label_cont));
5784 : :
5785 : 5418978 : gimple_pop_condition (pre_p);
5786 : 5418978 : gimple_seq_add_seq (pre_p, seq);
5787 : :
5788 : 5418978 : if (ret == GS_ERROR)
5789 : : ; /* Do nothing. */
5790 : 5418978 : else if (have_then_clause_p || have_else_clause_p)
5791 : : ret = GS_ALL_DONE;
5792 : : else
5793 : : {
5794 : : /* Both arms are empty; replace the COND_EXPR with its predicate. */
5795 : 2709 : expr = TREE_OPERAND (expr, 0);
5796 : 2709 : gimplify_stmt (&expr, pre_p);
5797 : : }
5798 : :
5799 : 5418978 : *expr_p = NULL;
5800 : 5418978 : return ret;
5801 : : }
5802 : :
5803 : : /* Prepare the node pointed to by EXPR_P, an is_gimple_addressable expression,
5804 : : to be marked addressable.
5805 : :
5806 : : We cannot rely on such an expression being directly markable if a temporary
5807 : : has been created by the gimplification. In this case, we create another
5808 : : temporary and initialize it with a copy, which will become a store after we
5809 : : mark it addressable. This can happen if the front-end passed us something
5810 : : that it could not mark addressable yet, like a Fortran pass-by-reference
5811 : : parameter (int) floatvar. */
5812 : :
5813 : : static void
5814 : 55799534 : prepare_gimple_addressable (tree *expr_p, gimple_seq *seq_p)
5815 : : {
5816 : 61348565 : while (handled_component_p (*expr_p))
5817 : 5549031 : expr_p = &TREE_OPERAND (*expr_p, 0);
5818 : :
5819 : : /* Do not allow an SSA name as the temporary. */
5820 : 55799534 : if (is_gimple_reg (*expr_p))
5821 : 11996 : *expr_p = internal_get_tmp_var (*expr_p, seq_p, NULL, false, false, true);
5822 : 55799534 : }
5823 : :
5824 : : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5825 : : a call to __builtin_memcpy. */
5826 : :
5827 : : static enum gimplify_status
5828 : 1074 : gimplify_modify_expr_to_memcpy (tree *expr_p, tree size, bool want_value,
5829 : : gimple_seq *seq_p)
5830 : : {
5831 : 1074 : tree t, to, to_ptr, from, from_ptr;
5832 : 1074 : gcall *gs;
5833 : 1074 : location_t loc = EXPR_LOCATION (*expr_p);
5834 : :
5835 : 1074 : to = TREE_OPERAND (*expr_p, 0);
5836 : 1074 : from = TREE_OPERAND (*expr_p, 1);
5837 : 1074 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to)))
5838 : : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))));
5839 : :
5840 : : /* Mark the RHS addressable. Beware that it may not be possible to do so
5841 : : directly if a temporary has been created by the gimplification. */
5842 : 1074 : prepare_gimple_addressable (&from, seq_p);
5843 : :
5844 : 1074 : mark_addressable (from);
5845 : 1074 : from_ptr = build_fold_addr_expr_loc (loc, from);
5846 : 1074 : gimplify_arg (&from_ptr, seq_p, loc);
5847 : :
5848 : 1074 : mark_addressable (to);
5849 : 1074 : to_ptr = build_fold_addr_expr_loc (loc, to);
5850 : 1074 : gimplify_arg (&to_ptr, seq_p, loc);
5851 : :
5852 : 1074 : t = builtin_decl_implicit (BUILT_IN_MEMCPY);
5853 : :
5854 : 1074 : gs = gimple_build_call (t, 3, to_ptr, from_ptr, size);
5855 : 1074 : gimple_call_set_alloca_for_var (gs, true);
5856 : :
5857 : 1074 : if (want_value)
5858 : : {
5859 : : /* tmp = memcpy() */
5860 : 8 : t = create_tmp_var (TREE_TYPE (to_ptr));
5861 : 8 : gimple_call_set_lhs (gs, t);
5862 : 8 : gimplify_seq_add_stmt (seq_p, gs);
5863 : :
5864 : 8 : *expr_p = build_simple_mem_ref (t);
5865 : 8 : return GS_ALL_DONE;
5866 : : }
5867 : :
5868 : 1066 : gimplify_seq_add_stmt (seq_p, gs);
5869 : 1066 : *expr_p = NULL;
5870 : 1066 : return GS_ALL_DONE;
5871 : : }
5872 : :
5873 : : /* A subroutine of gimplify_modify_expr. Replace a MODIFY_EXPR with
5874 : : a call to __builtin_memset. In this case we know that the RHS is
5875 : : a CONSTRUCTOR with an empty element list. */
5876 : :
5877 : : static enum gimplify_status
5878 : 78 : gimplify_modify_expr_to_memset (tree *expr_p, tree size, bool want_value,
5879 : : gimple_seq *seq_p)
5880 : : {
5881 : 78 : tree t, from, to, to_ptr;
5882 : 78 : gcall *gs;
5883 : 78 : location_t loc = EXPR_LOCATION (*expr_p);
5884 : :
5885 : : /* Assert our assumptions, to abort instead of producing wrong code
5886 : : silently if they are not met. Beware that the RHS CONSTRUCTOR might
5887 : : not be immediately exposed. */
5888 : 78 : from = TREE_OPERAND (*expr_p, 1);
5889 : 78 : if (TREE_CODE (from) == WITH_SIZE_EXPR)
5890 : 78 : from = TREE_OPERAND (from, 0);
5891 : :
5892 : 78 : gcc_assert (TREE_CODE (from) == CONSTRUCTOR
5893 : : && vec_safe_is_empty (CONSTRUCTOR_ELTS (from)));
5894 : :
5895 : : /* Now proceed. */
5896 : 78 : to = TREE_OPERAND (*expr_p, 0);
5897 : 78 : gcc_assert (ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (to))));
5898 : :
5899 : 78 : to_ptr = build_fold_addr_expr_loc (loc, to);
5900 : 78 : gimplify_arg (&to_ptr, seq_p, loc);
5901 : 78 : t = builtin_decl_implicit (BUILT_IN_MEMSET);
5902 : :
5903 : 78 : gs = gimple_build_call (t, 3, to_ptr, integer_zero_node, size);
5904 : :
5905 : 78 : if (want_value)
5906 : : {
5907 : : /* tmp = memset() */
5908 : 0 : t = create_tmp_var (TREE_TYPE (to_ptr));
5909 : 0 : gimple_call_set_lhs (gs, t);
5910 : 0 : gimplify_seq_add_stmt (seq_p, gs);
5911 : :
5912 : 0 : *expr_p = build1 (INDIRECT_REF, TREE_TYPE (to), t);
5913 : 0 : return GS_ALL_DONE;
5914 : : }
5915 : :
5916 : 78 : gimplify_seq_add_stmt (seq_p, gs);
5917 : 78 : *expr_p = NULL;
5918 : 78 : return GS_ALL_DONE;
5919 : : }
5920 : :
5921 : : /* A subroutine of gimplify_init_ctor_preeval. Called via walk_tree,
5922 : : determine, cautiously, if a CONSTRUCTOR overlaps the lhs of an
5923 : : assignment. Return non-null if we detect a potential overlap. */
5924 : :
5925 : : struct gimplify_init_ctor_preeval_data
5926 : : {
5927 : : /* The base decl of the lhs object. May be NULL, in which case we
5928 : : have to assume the lhs is indirect. */
5929 : : tree lhs_base_decl;
5930 : :
5931 : : /* The alias set of the lhs object. */
5932 : : alias_set_type lhs_alias_set;
5933 : : };
5934 : :
5935 : : static tree
5936 : 115185 : gimplify_init_ctor_preeval_1 (tree *tp, int *walk_subtrees, void *xdata)
5937 : : {
5938 : 115185 : struct gimplify_init_ctor_preeval_data *data
5939 : : = (struct gimplify_init_ctor_preeval_data *) xdata;
5940 : 115185 : tree t = *tp;
5941 : :
5942 : : /* If we find the base object, obviously we have overlap. */
5943 : 115185 : if (data->lhs_base_decl == t)
5944 : : return t;
5945 : :
5946 : : /* If the constructor component is indirect, determine if we have a
5947 : : potential overlap with the lhs. The only bits of information we
5948 : : have to go on at this point are addressability and alias sets. */
5949 : 115184 : if ((INDIRECT_REF_P (t)
5950 : 115184 : || TREE_CODE (t) == MEM_REF)
5951 : 643 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5952 : 115696 : && alias_sets_conflict_p (data->lhs_alias_set, get_alias_set (t)))
5953 : : return t;
5954 : :
5955 : : /* If the constructor component is a call, determine if it can hide a
5956 : : potential overlap with the lhs through an INDIRECT_REF like above.
5957 : : ??? Ugh - this is completely broken. In fact this whole analysis
5958 : : doesn't look conservative. */
5959 : 114672 : if (TREE_CODE (t) == CALL_EXPR)
5960 : : {
5961 : 0 : tree type, fntype = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (t)));
5962 : :
5963 : 0 : for (type = TYPE_ARG_TYPES (fntype); type; type = TREE_CHAIN (type))
5964 : 0 : if (POINTER_TYPE_P (TREE_VALUE (type))
5965 : 0 : && (!data->lhs_base_decl || TREE_ADDRESSABLE (data->lhs_base_decl))
5966 : 0 : && alias_sets_conflict_p (data->lhs_alias_set,
5967 : : get_alias_set
5968 : 0 : (TREE_TYPE (TREE_VALUE (type)))))
5969 : : return t;
5970 : : }
5971 : :
5972 : 114672 : if (IS_TYPE_OR_DECL_P (t))
5973 : 10964 : *walk_subtrees = 0;
5974 : : return NULL;
5975 : : }
5976 : :
5977 : : /* A subroutine of gimplify_init_constructor. Pre-evaluate EXPR,
5978 : : force values that overlap with the lhs (as described by *DATA)
5979 : : into temporaries. */
5980 : :
5981 : : static void
5982 : 410026 : gimplify_init_ctor_preeval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
5983 : : struct gimplify_init_ctor_preeval_data *data)
5984 : : {
5985 : 410026 : enum gimplify_status one;
5986 : :
5987 : : /* If the value is constant, then there's nothing to pre-evaluate. */
5988 : 410026 : if (TREE_CONSTANT (*expr_p))
5989 : : {
5990 : : /* Ensure it does not have side effects, it might contain a reference to
5991 : : the object we're initializing. */
5992 : 194110 : gcc_assert (!TREE_SIDE_EFFECTS (*expr_p));
5993 : : return;
5994 : : }
5995 : :
5996 : : /* If the type has non-trivial constructors, we can't pre-evaluate. */
5997 : 215916 : if (TREE_ADDRESSABLE (TREE_TYPE (*expr_p)))
5998 : : return;
5999 : :
6000 : : /* Recurse for nested constructors. */
6001 : 215916 : if (TREE_CODE (*expr_p) == CONSTRUCTOR)
6002 : : {
6003 : 73101 : unsigned HOST_WIDE_INT ix;
6004 : 73101 : constructor_elt *ce;
6005 : 73101 : vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (*expr_p);
6006 : :
6007 : 269157 : FOR_EACH_VEC_SAFE_ELT (v, ix, ce)
6008 : 196056 : gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data);
6009 : :
6010 : : return;
6011 : : }
6012 : :
6013 : : /* If this is a variable sized type, we must remember the size. */
6014 : 142815 : maybe_with_size_expr (expr_p);
6015 : :
6016 : : /* Gimplify the constructor element to something appropriate for the rhs
6017 : : of a MODIFY_EXPR. Given that we know the LHS is an aggregate, we know
6018 : : the gimplifier will consider this a store to memory. Doing this
6019 : : gimplification now means that we won't have to deal with complicated
6020 : : language-specific trees, nor trees like SAVE_EXPR that can induce
6021 : : exponential search behavior. */
6022 : 142815 : one = gimplify_expr (expr_p, pre_p, post_p, is_gimple_mem_rhs, fb_rvalue);
6023 : 142815 : if (one == GS_ERROR)
6024 : : {
6025 : 0 : *expr_p = NULL;
6026 : 0 : return;
6027 : : }
6028 : :
6029 : : /* If we gimplified to a bare decl, we can be sure that it doesn't overlap
6030 : : with the lhs, since "a = { .x=a }" doesn't make sense. This will
6031 : : always be true for all scalars, since is_gimple_mem_rhs insists on a
6032 : : temporary variable for them. */
6033 : 142815 : if (DECL_P (*expr_p))
6034 : : return;
6035 : :
6036 : : /* If this is of variable size, we have no choice but to assume it doesn't
6037 : : overlap since we can't make a temporary for it. */
6038 : 103641 : if (TREE_CODE (TYPE_SIZE (TREE_TYPE (*expr_p))) != INTEGER_CST)
6039 : : return;
6040 : :
6041 : : /* Otherwise, we must search for overlap ... */
6042 : 103641 : if (!walk_tree (expr_p, gimplify_init_ctor_preeval_1, data, NULL))
6043 : : return;
6044 : :
6045 : : /* ... and if found, force the value into a temporary. */
6046 : 513 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
6047 : : }
6048 : :
6049 : : /* A subroutine of gimplify_init_ctor_eval. Create a loop for
6050 : : a RANGE_EXPR in a CONSTRUCTOR for an array.
6051 : :
6052 : : var = lower;
6053 : : loop_entry:
6054 : : object[var] = value;
6055 : : if (var == upper)
6056 : : goto loop_exit;
6057 : : var = var + 1;
6058 : : goto loop_entry;
6059 : : loop_exit:
6060 : :
6061 : : We increment var _after_ the loop exit check because we might otherwise
6062 : : fail if upper == TYPE_MAX_VALUE (type for upper).
6063 : :
6064 : : Note that we never have to deal with SAVE_EXPRs here, because this has
6065 : : already been taken care of for us, in gimplify_init_ctor_preeval(). */
6066 : :
6067 : : static void gimplify_init_ctor_eval (tree, vec<constructor_elt, va_gc> *,
6068 : : gimple_seq *, bool);
6069 : :
6070 : : static void
6071 : 423 : gimplify_init_ctor_eval_range (tree object, tree lower, tree upper,
6072 : : tree value, tree array_elt_type,
6073 : : gimple_seq *pre_p, bool cleared)
6074 : : {
6075 : 423 : tree loop_entry_label, loop_exit_label, fall_thru_label;
6076 : 423 : tree var, var_type, cref, tmp;
6077 : :
6078 : 423 : loop_entry_label = create_artificial_label (UNKNOWN_LOCATION);
6079 : 423 : loop_exit_label = create_artificial_label (UNKNOWN_LOCATION);
6080 : 423 : fall_thru_label = create_artificial_label (UNKNOWN_LOCATION);
6081 : :
6082 : : /* Create and initialize the index variable. */
6083 : 423 : var_type = TREE_TYPE (upper);
6084 : 423 : var = create_tmp_var (var_type);
6085 : 423 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, lower));
6086 : :
6087 : : /* Add the loop entry label. */
6088 : 423 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_entry_label));
6089 : :
6090 : : /* Build the reference. */
6091 : 423 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
6092 : : var, NULL_TREE, NULL_TREE);
6093 : :
6094 : : /* If we are a constructor, just call gimplify_init_ctor_eval to do
6095 : : the store. Otherwise just assign value to the reference. */
6096 : :
6097 : 423 : if (TREE_CODE (value) == CONSTRUCTOR)
6098 : : /* NB we might have to call ourself recursively through
6099 : : gimplify_init_ctor_eval if the value is a constructor. */
6100 : 111 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
6101 : : pre_p, cleared);
6102 : : else
6103 : : {
6104 : 312 : if (gimplify_expr (&value, pre_p, NULL, is_gimple_val, fb_rvalue)
6105 : : != GS_ERROR)
6106 : 312 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (cref, value));
6107 : : }
6108 : :
6109 : : /* We exit the loop when the index var is equal to the upper bound. */
6110 : 846 : gimplify_seq_add_stmt (pre_p,
6111 : 423 : gimple_build_cond (EQ_EXPR, var, upper,
6112 : : loop_exit_label, fall_thru_label));
6113 : :
6114 : 423 : gimplify_seq_add_stmt (pre_p, gimple_build_label (fall_thru_label));
6115 : :
6116 : : /* Otherwise, increment the index var... */
6117 : 423 : tmp = build2 (PLUS_EXPR, var_type, var,
6118 : : fold_convert (var_type, integer_one_node));
6119 : 423 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (var, tmp));
6120 : :
6121 : : /* ...and jump back to the loop entry. */
6122 : 423 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (loop_entry_label));
6123 : :
6124 : : /* Add the loop exit label. */
6125 : 423 : gimplify_seq_add_stmt (pre_p, gimple_build_label (loop_exit_label));
6126 : 423 : }
6127 : :
6128 : : /* A subroutine of gimplify_init_constructor. Generate individual
6129 : : MODIFY_EXPRs for a CONSTRUCTOR. OBJECT is the LHS against which the
6130 : : assignments should happen. ELTS is the CONSTRUCTOR_ELTS of the
6131 : : CONSTRUCTOR. CLEARED is true if the entire LHS object has been
6132 : : zeroed first. */
6133 : :
6134 : : static void
6135 : 1245201 : gimplify_init_ctor_eval (tree object, vec<constructor_elt, va_gc> *elts,
6136 : : gimple_seq *pre_p, bool cleared)
6137 : : {
6138 : 1245201 : tree array_elt_type = NULL;
6139 : 1245201 : unsigned HOST_WIDE_INT ix;
6140 : 1245201 : tree purpose, value;
6141 : :
6142 : 1245201 : if (TREE_CODE (TREE_TYPE (object)) == ARRAY_TYPE)
6143 : 138457 : array_elt_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (object)));
6144 : :
6145 : 4664667 : FOR_EACH_CONSTRUCTOR_ELT (elts, ix, purpose, value)
6146 : : {
6147 : 3419466 : tree cref;
6148 : :
6149 : : /* NULL values are created above for gimplification errors. */
6150 : 3419466 : if (value == NULL)
6151 : 368247 : continue;
6152 : :
6153 : 3419466 : if (cleared && initializer_zerop (value))
6154 : 367656 : continue;
6155 : :
6156 : : /* ??? Here's to hoping the front end fills in all of the indices,
6157 : : so we don't have to figure out what's missing ourselves. */
6158 : 3051810 : gcc_assert (purpose);
6159 : :
6160 : : /* Skip zero-sized fields, unless value has side-effects. This can
6161 : : happen with calls to functions returning a empty type, which
6162 : : we shouldn't discard. As a number of downstream passes don't
6163 : : expect sets of empty type fields, we rely on the gimplification of
6164 : : the MODIFY_EXPR we make below to drop the assignment statement. */
6165 : 3051810 : if (!TREE_SIDE_EFFECTS (value)
6166 : 2757269 : && TREE_CODE (purpose) == FIELD_DECL
6167 : 5348161 : && is_empty_type (TREE_TYPE (purpose)))
6168 : 168 : continue;
6169 : :
6170 : : /* If we have a RANGE_EXPR, we have to build a loop to assign the
6171 : : whole range. */
6172 : 3051642 : if (TREE_CODE (purpose) == RANGE_EXPR)
6173 : : {
6174 : 433 : tree lower = TREE_OPERAND (purpose, 0);
6175 : 433 : tree upper = TREE_OPERAND (purpose, 1);
6176 : :
6177 : : /* If the lower bound is equal to upper, just treat it as if
6178 : : upper was the index. */
6179 : 433 : if (simple_cst_equal (lower, upper))
6180 : : purpose = upper;
6181 : : else
6182 : : {
6183 : 423 : gimplify_init_ctor_eval_range (object, lower, upper, value,
6184 : : array_elt_type, pre_p, cleared);
6185 : 423 : continue;
6186 : : }
6187 : : }
6188 : :
6189 : 3051219 : if (array_elt_type)
6190 : : {
6191 : : /* Do not use bitsizetype for ARRAY_REF indices. */
6192 : 552483 : if (TYPE_DOMAIN (TREE_TYPE (object)))
6193 : 552483 : purpose
6194 : 552483 : = fold_convert (TREE_TYPE (TYPE_DOMAIN (TREE_TYPE (object))),
6195 : : purpose);
6196 : 552483 : cref = build4 (ARRAY_REF, array_elt_type, unshare_expr (object),
6197 : : purpose, NULL_TREE, NULL_TREE);
6198 : : }
6199 : : else
6200 : : {
6201 : 2498736 : gcc_assert (TREE_CODE (purpose) == FIELD_DECL);
6202 : 2498736 : cref = build3 (COMPONENT_REF, TREE_TYPE (purpose),
6203 : : unshare_expr (object), purpose, NULL_TREE);
6204 : : }
6205 : :
6206 : 3051219 : if (TREE_CODE (value) == CONSTRUCTOR
6207 : 3051219 : && TREE_CODE (TREE_TYPE (value)) != VECTOR_TYPE)
6208 : 299385 : gimplify_init_ctor_eval (cref, CONSTRUCTOR_ELTS (value),
6209 : : pre_p, cleared);
6210 : 2751834 : else if (TREE_CODE (value) == RAW_DATA_CST)
6211 : : {
6212 : 37 : if (RAW_DATA_LENGTH (value) <= 32)
6213 : : {
6214 : 13 : for (unsigned int i = 0; i < (unsigned) RAW_DATA_LENGTH (value);
6215 : : ++i)
6216 : 12 : if (!cleared || RAW_DATA_POINTER (value)[i])
6217 : : {
6218 : 12 : if (i)
6219 : : {
6220 : 11 : tree p
6221 : 11 : = fold_build2 (PLUS_EXPR, TREE_TYPE (purpose),
6222 : : purpose,
6223 : : build_int_cst (TREE_TYPE (purpose),
6224 : : i));
6225 : 11 : cref = build4 (ARRAY_REF, array_elt_type,
6226 : : unshare_expr (object), p, NULL_TREE,
6227 : : NULL_TREE);
6228 : : }
6229 : 12 : tree init
6230 : 12 : = build2 (INIT_EXPR, TREE_TYPE (cref), cref,
6231 : 12 : build_int_cst (TREE_TYPE (value),
6232 : 12 : RAW_DATA_UCHAR_ELT (value, i)));
6233 : 12 : gimplify_and_add (init, pre_p);
6234 : 12 : ggc_free (init);
6235 : : }
6236 : : }
6237 : : else
6238 : : {
6239 : 36 : tree rtype = build_array_type_nelts (TREE_TYPE (value),
6240 : 36 : RAW_DATA_LENGTH (value));
6241 : 36 : tree rctor = build_constructor_single (rtype, bitsize_zero_node,
6242 : : value);
6243 : 36 : tree addr = build_fold_addr_expr (cref);
6244 : 36 : cref = build2 (MEM_REF, rtype, addr,
6245 : : build_int_cst (ptr_type_node, 0));
6246 : 36 : rctor = tree_output_constant_def (rctor);
6247 : 36 : if (!useless_type_conversion_p (rtype, TREE_TYPE (rctor)))
6248 : 4 : rctor = build1 (VIEW_CONVERT_EXPR, rtype, rctor);
6249 : 36 : if (gimplify_expr (&cref, pre_p, NULL, is_gimple_lvalue,
6250 : : fb_lvalue) != GS_ERROR)
6251 : 72 : gimplify_seq_add_stmt (pre_p,
6252 : 36 : gimple_build_assign (cref, rctor));
6253 : : }
6254 : : }
6255 : : else
6256 : : {
6257 : 2751797 : tree init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
6258 : 2751797 : gimplify_and_add (init, pre_p);
6259 : 2751797 : ggc_free (init);
6260 : : }
6261 : : }
6262 : 1245201 : }
6263 : :
6264 : : /* Return the appropriate RHS predicate for this LHS. */
6265 : :
6266 : : gimple_predicate
6267 : 48630211 : rhs_predicate_for (tree lhs)
6268 : : {
6269 : 48630211 : if (is_gimple_reg (lhs))
6270 : : return is_gimple_reg_rhs_or_call;
6271 : : else
6272 : 11560311 : return is_gimple_mem_rhs_or_call;
6273 : : }
6274 : :
6275 : : /* Return the initial guess for an appropriate RHS predicate for this LHS,
6276 : : before the LHS has been gimplified. */
6277 : :
6278 : : static gimple_predicate
6279 : 47423785 : initial_rhs_predicate_for (tree lhs)
6280 : : {
6281 : 47423785 : if (is_gimple_reg_type (TREE_TYPE (lhs)))
6282 : : return is_gimple_reg_rhs_or_call;
6283 : : else
6284 : 2437324 : return is_gimple_mem_rhs_or_call;
6285 : : }
6286 : :
6287 : : /* Gimplify a C99 compound literal expression. This just means adding
6288 : : the DECL_EXPR before the current statement and using its anonymous
6289 : : decl instead. */
6290 : :
6291 : : static enum gimplify_status
6292 : 36832 : gimplify_compound_literal_expr (tree *expr_p, gimple_seq *pre_p,
6293 : : bool (*gimple_test_f) (tree),
6294 : : fallback_t fallback)
6295 : : {
6296 : 36832 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (*expr_p);
6297 : 36832 : tree decl = DECL_EXPR_DECL (decl_s);
6298 : 36832 : tree init = DECL_INITIAL (decl);
6299 : : /* Mark the decl as addressable if the compound literal
6300 : : expression is addressable now, otherwise it is marked too late
6301 : : after we gimplify the initialization expression. */
6302 : 36832 : if (TREE_ADDRESSABLE (*expr_p))
6303 : 525 : TREE_ADDRESSABLE (decl) = 1;
6304 : : /* Otherwise, if we don't need an lvalue and have a literal directly
6305 : : substitute it. Check if it matches the gimple predicate, as
6306 : : otherwise we'd generate a new temporary, and we can as well just
6307 : : use the decl we already have. */
6308 : 36307 : else if (!TREE_ADDRESSABLE (decl)
6309 : 36307 : && !TREE_THIS_VOLATILE (decl)
6310 : 36302 : && init
6311 : 36295 : && (fallback & fb_lvalue) == 0
6312 : 72475 : && gimple_test_f (init))
6313 : : {
6314 : 35099 : *expr_p = init;
6315 : 35099 : return GS_OK;
6316 : : }
6317 : :
6318 : : /* If the decl is not addressable, then it is being used in some
6319 : : expression or on the right hand side of a statement, and it can
6320 : : be put into a readonly data section. */
6321 : 1733 : if (!TREE_ADDRESSABLE (decl) && (fallback & fb_lvalue) == 0)
6322 : 1074 : TREE_READONLY (decl) = 1;
6323 : :
6324 : : /* This decl isn't mentioned in the enclosing block, so add it to the
6325 : : list of temps. FIXME it seems a bit of a kludge to say that
6326 : : anonymous artificial vars aren't pushed, but everything else is. */
6327 : 1733 : if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
6328 : 2 : gimple_add_tmp_var (decl);
6329 : :
6330 : 1733 : gimplify_and_add (decl_s, pre_p);
6331 : 1733 : *expr_p = decl;
6332 : 1733 : return GS_OK;
6333 : : }
6334 : :
6335 : : /* Optimize embedded COMPOUND_LITERAL_EXPRs within a CONSTRUCTOR,
6336 : : return a new CONSTRUCTOR if something changed. */
6337 : :
6338 : : static tree
6339 : 1845354 : optimize_compound_literals_in_ctor (tree orig_ctor)
6340 : : {
6341 : 1845354 : tree ctor = orig_ctor;
6342 : 1845354 : vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
6343 : 1845354 : unsigned int idx, num = vec_safe_length (elts);
6344 : :
6345 : 6206764 : for (idx = 0; idx < num; idx++)
6346 : : {
6347 : 4361410 : tree value = (*elts)[idx].value;
6348 : 4361410 : tree newval = value;
6349 : 4361410 : if (TREE_CODE (value) == CONSTRUCTOR)
6350 : 535777 : newval = optimize_compound_literals_in_ctor (value);
6351 : 3825633 : else if (TREE_CODE (value) == COMPOUND_LITERAL_EXPR)
6352 : : {
6353 : 79 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (value);
6354 : 79 : tree decl = DECL_EXPR_DECL (decl_s);
6355 : 79 : tree init = DECL_INITIAL (decl);
6356 : :
6357 : 79 : if (!TREE_ADDRESSABLE (value)
6358 : 79 : && !TREE_ADDRESSABLE (decl)
6359 : 79 : && init
6360 : 79 : && TREE_CODE (init) == CONSTRUCTOR)
6361 : 48 : newval = optimize_compound_literals_in_ctor (init);
6362 : : }
6363 : 4361410 : if (newval == value)
6364 : 4361354 : continue;
6365 : :
6366 : 56 : if (ctor == orig_ctor)
6367 : : {
6368 : 45 : ctor = copy_node (orig_ctor);
6369 : 90 : CONSTRUCTOR_ELTS (ctor) = vec_safe_copy (elts);
6370 : 45 : elts = CONSTRUCTOR_ELTS (ctor);
6371 : : }
6372 : 56 : (*elts)[idx].value = newval;
6373 : : }
6374 : 1845354 : return ctor;
6375 : : }
6376 : :
6377 : : /* A subroutine of gimplify_modify_expr. Break out elements of a
6378 : : CONSTRUCTOR used as an initializer into separate MODIFY_EXPRs.
6379 : :
6380 : : Note that we still need to clear any elements that don't have explicit
6381 : : initializers, so if not all elements are initialized we keep the
6382 : : original MODIFY_EXPR, we just remove all of the constructor elements.
6383 : :
6384 : : If NOTIFY_TEMP_CREATION is true, do not gimplify, just return
6385 : : GS_ERROR if we would have to create a temporary when gimplifying
6386 : : this constructor. Otherwise, return GS_OK.
6387 : :
6388 : : If NOTIFY_TEMP_CREATION is false, just do the gimplification. */
6389 : :
6390 : : static enum gimplify_status
6391 : 1309529 : gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
6392 : : bool want_value, bool notify_temp_creation)
6393 : : {
6394 : 1309529 : tree object, ctor, type;
6395 : 1309529 : enum gimplify_status ret;
6396 : 1309529 : vec<constructor_elt, va_gc> *elts;
6397 : 1309529 : bool cleared = false;
6398 : 1309529 : bool is_empty_ctor = false;
6399 : 1309529 : bool is_init_expr = (TREE_CODE (*expr_p) == INIT_EXPR);
6400 : :
6401 : 1309529 : gcc_assert (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == CONSTRUCTOR);
6402 : :
6403 : 1309529 : if (!notify_temp_creation)
6404 : : {
6405 : 1301059 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
6406 : : is_gimple_lvalue, fb_lvalue);
6407 : 1301059 : if (ret == GS_ERROR)
6408 : : return ret;
6409 : : }
6410 : :
6411 : 1309529 : object = TREE_OPERAND (*expr_p, 0);
6412 : 1309529 : ctor = TREE_OPERAND (*expr_p, 1)
6413 : 1309529 : = optimize_compound_literals_in_ctor (TREE_OPERAND (*expr_p, 1));
6414 : 1309529 : type = TREE_TYPE (ctor);
6415 : 1309529 : elts = CONSTRUCTOR_ELTS (ctor);
6416 : 1309529 : ret = GS_ALL_DONE;
6417 : :
6418 : 1309529 : switch (TREE_CODE (type))
6419 : : {
6420 : 1302869 : case RECORD_TYPE:
6421 : 1302869 : case UNION_TYPE:
6422 : 1302869 : case QUAL_UNION_TYPE:
6423 : 1302869 : case ARRAY_TYPE:
6424 : 1302869 : {
6425 : : /* Use readonly data for initializers of this or smaller size
6426 : : regardless of the num_nonzero_elements / num_unique_nonzero_elements
6427 : : ratio. */
6428 : 1302869 : const HOST_WIDE_INT min_unique_size = 64;
6429 : : /* If num_nonzero_elements / num_unique_nonzero_elements ratio
6430 : : is smaller than this, use readonly data. */
6431 : 1302869 : const int unique_nonzero_ratio = 8;
6432 : : /* True if a single access of the object must be ensured. This is the
6433 : : case if the target is volatile, the type is non-addressable and more
6434 : : than one field need to be assigned. */
6435 : 1302869 : const bool ensure_single_access
6436 : 1302869 : = TREE_THIS_VOLATILE (object)
6437 : 234 : && !TREE_ADDRESSABLE (type)
6438 : 1303069 : && vec_safe_length (elts) > 1;
6439 : 1302869 : struct gimplify_init_ctor_preeval_data preeval_data;
6440 : 1302869 : HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
6441 : 1302869 : HOST_WIDE_INT num_unique_nonzero_elements;
6442 : 1302869 : int complete_p;
6443 : 1302869 : bool valid_const_initializer;
6444 : :
6445 : : /* Aggregate types must lower constructors to initialization of
6446 : : individual elements. The exception is that a CONSTRUCTOR node
6447 : : with no elements indicates zero-initialization of the whole. */
6448 : 1302869 : if (vec_safe_is_empty (elts))
6449 : : {
6450 : 328459 : if (notify_temp_creation)
6451 : 10049 : return GS_OK;
6452 : :
6453 : : /* The var will be initialized and so appear on lhs of
6454 : : assignment, it can't be TREE_READONLY anymore. */
6455 : 328411 : if (VAR_P (object))
6456 : 186753 : TREE_READONLY (object) = 0;
6457 : :
6458 : : is_empty_ctor = true;
6459 : 330301 : break;
6460 : : }
6461 : :
6462 : : /* Fetch information about the constructor to direct later processing.
6463 : : We might want to make static versions of it in various cases, and
6464 : : can only do so if it known to be a valid constant initializer. */
6465 : 974410 : valid_const_initializer
6466 : 974410 : = categorize_ctor_elements (ctor, &num_nonzero_elements,
6467 : : &num_unique_nonzero_elements,
6468 : : &num_ctor_elements, &complete_p);
6469 : :
6470 : : /* If a const aggregate variable is being initialized, then it
6471 : : should never be a lose to promote the variable to be static. */
6472 : 974410 : if (valid_const_initializer
6473 : 597989 : && num_nonzero_elements > 1
6474 : 443378 : && TREE_READONLY (object)
6475 : 4806 : && VAR_P (object)
6476 : 4420 : && !DECL_REGISTER (object)
6477 : 4413 : && (flag_merge_constants >= 2 || !TREE_ADDRESSABLE (object)
6478 : 4208 : || DECL_MERGEABLE (object))
6479 : : /* For ctors that have many repeated nonzero elements
6480 : : represented through RANGE_EXPRs, prefer initializing
6481 : : those through runtime loops over copies of large amounts
6482 : : of data from readonly data section. */
6483 : 974410 : && (num_unique_nonzero_elements
6484 : 1890 : > num_nonzero_elements / unique_nonzero_ratio
6485 : 0 : || ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
6486 : : <= (unsigned HOST_WIDE_INT) min_unique_size)))
6487 : : {
6488 : 1890 : if (notify_temp_creation)
6489 : : return GS_ERROR;
6490 : :
6491 : 1890 : DECL_INITIAL (object) = ctor;
6492 : 1890 : TREE_STATIC (object) = 1;
6493 : 1890 : if (!DECL_NAME (object) || DECL_NAMELESS (object))
6494 : 1708 : DECL_NAME (object) = create_tmp_var_name ("C");
6495 : 1890 : walk_tree (&DECL_INITIAL (object), force_labels_r, NULL, NULL);
6496 : :
6497 : : /* ??? C++ doesn't automatically append a .<number> to the
6498 : : assembler name, and even when it does, it looks at FE private
6499 : : data structures to figure out what that number should be,
6500 : : which are not set for this variable. I suppose this is
6501 : : important for local statics for inline functions, which aren't
6502 : : "local" in the object file sense. So in order to get a unique
6503 : : TU-local symbol, we must invoke the lhd version now. */
6504 : 1890 : lhd_set_decl_assembler_name (object);
6505 : :
6506 : 1890 : *expr_p = NULL_TREE;
6507 : 1890 : break;
6508 : : }
6509 : :
6510 : : /* The var will be initialized and so appear on lhs of
6511 : : assignment, it can't be TREE_READONLY anymore. */
6512 : 972520 : if (VAR_P (object) && !notify_temp_creation)
6513 : 770415 : TREE_READONLY (object) = 0;
6514 : :
6515 : : /* If there are "lots" of initialized elements, even discounting
6516 : : those that are not address constants (and thus *must* be
6517 : : computed at runtime), then partition the constructor into
6518 : : constant and non-constant parts. Block copy the constant
6519 : : parts in, then generate code for the non-constant parts. */
6520 : : /* TODO. There's code in cp/typeck.cc to do this. */
6521 : :
6522 : 972520 : if (int_size_in_bytes (TREE_TYPE (ctor)) < 0)
6523 : : /* store_constructor will ignore the clearing of variable-sized
6524 : : objects. Initializers for such objects must explicitly set
6525 : : every field that needs to be set. */
6526 : : cleared = false;
6527 : 972500 : else if (!complete_p)
6528 : : /* If the constructor isn't complete, clear the whole object
6529 : : beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
6530 : :
6531 : : ??? This ought not to be needed. For any element not present
6532 : : in the initializer, we should simply set them to zero. Except
6533 : : we'd need to *find* the elements that are not present, and that
6534 : : requires trickery to avoid quadratic compile-time behavior in
6535 : : large cases or excessive memory use in small cases. */
6536 : 181889 : cleared = !CONSTRUCTOR_NO_CLEARING (ctor);
6537 : 790611 : else if (num_ctor_elements - num_nonzero_elements
6538 : 790611 : > CLEAR_RATIO (optimize_function_for_speed_p (cfun))
6539 : 790611 : && num_nonzero_elements < num_ctor_elements / 4)
6540 : : /* If there are "lots" of zeros, it's more efficient to clear
6541 : : the memory and then set the nonzero elements. */
6542 : : cleared = true;
6543 : 789711 : else if (ensure_single_access && num_nonzero_elements == 0)
6544 : : /* If a single access to the target must be ensured and all elements
6545 : : are zero, then it's optimal to clear whatever their number. */
6546 : : cleared = true;
6547 : : /* If the object is small enough to go in registers, and it's
6548 : : not required to be constructed in memory, clear it first.
6549 : : That will avoid wasting cycles preserving any padding bits
6550 : : that might be there, and if there aren't any, the compiler
6551 : : is smart enough to optimize the clearing out. */
6552 : 789706 : else if (complete_p <= 0
6553 : 14328 : && !TREE_ADDRESSABLE (ctor)
6554 : 14314 : && !TREE_THIS_VOLATILE (object)
6555 : 14311 : && (TYPE_MODE (type) != BLKmode || TYPE_NO_FORCE_BLK (type))
6556 : 796229 : && optimize)
6557 : : cleared = true;
6558 : : else
6559 : : cleared = false;
6560 : :
6561 : : /* If there are "lots" of initialized elements, and all of them
6562 : : are valid address constants, then the entire initializer can
6563 : : be dropped to memory, and then memcpy'd out. Don't do this
6564 : : for sparse arrays, though, as it's more efficient to follow
6565 : : the standard CONSTRUCTOR behavior of memset followed by
6566 : : individual element initialization. Also don't do this for small
6567 : : all-zero initializers (which aren't big enough to merit
6568 : : clearing), and don't try to make bitwise copies of
6569 : : TREE_ADDRESSABLE types. */
6570 : 972520 : if (valid_const_initializer
6571 : 596099 : && complete_p
6572 : 428875 : && !(cleared || num_nonzero_elements == 0)
6573 : 335140 : && !TREE_ADDRESSABLE (type))
6574 : : {
6575 : 333995 : HOST_WIDE_INT size = int_size_in_bytes (type);
6576 : 333995 : unsigned int align;
6577 : :
6578 : : /* ??? We can still get unbounded array types, at least
6579 : : from the C++ front end. This seems wrong, but attempt
6580 : : to work around it for now. */
6581 : 333995 : if (size < 0)
6582 : : {
6583 : 9 : size = int_size_in_bytes (TREE_TYPE (object));
6584 : 9 : if (size >= 0)
6585 : 0 : TREE_TYPE (ctor) = type = TREE_TYPE (object);
6586 : : }
6587 : :
6588 : : /* Find the maximum alignment we can assume for the object. */
6589 : : /* ??? Make use of DECL_OFFSET_ALIGN. */
6590 : 333995 : if (DECL_P (object))
6591 : 320381 : align = DECL_ALIGN (object);
6592 : : else
6593 : 13614 : align = TYPE_ALIGN (type);
6594 : :
6595 : : /* Do a block move either if the size is so small as to make
6596 : : each individual move a sub-unit move on average, or if it
6597 : : is so large as to make individual moves inefficient. */
6598 : 333995 : if (size > 0
6599 : 333986 : && num_nonzero_elements > 1
6600 : : /* For ctors that have many repeated nonzero elements
6601 : : represented through RANGE_EXPRs, prefer initializing
6602 : : those through runtime loops over copies of large amounts
6603 : : of data from readonly data section. */
6604 : 301795 : && (num_unique_nonzero_elements
6605 : 301795 : > num_nonzero_elements / unique_nonzero_ratio
6606 : 67 : || size <= min_unique_size)
6607 : 635723 : && (size < num_nonzero_elements
6608 : 301622 : || !can_move_by_pieces (size, align)))
6609 : : {
6610 : 2840 : if (notify_temp_creation)
6611 : : return GS_ERROR;
6612 : :
6613 : 1422 : walk_tree (&ctor, force_labels_r, NULL, NULL);
6614 : 1422 : ctor = tree_output_constant_def (ctor);
6615 : 1422 : if (!useless_type_conversion_p (type, TREE_TYPE (ctor)))
6616 : 0 : ctor = build1 (VIEW_CONVERT_EXPR, type, ctor);
6617 : 1422 : TREE_OPERAND (*expr_p, 1) = ctor;
6618 : :
6619 : : /* This is no longer an assignment of a CONSTRUCTOR, but
6620 : : we still may have processing to do on the LHS. So
6621 : : pretend we didn't do anything here to let that happen. */
6622 : 1422 : return GS_UNHANDLED;
6623 : : }
6624 : : }
6625 : :
6626 : : /* If a single access to the target must be ensured and there are
6627 : : nonzero elements or the zero elements are not assigned en masse,
6628 : : initialize the target from a temporary. */
6629 : 969680 : if (ensure_single_access && (num_nonzero_elements > 0 || !cleared))
6630 : : {
6631 : 163 : if (notify_temp_creation)
6632 : : return GS_ERROR;
6633 : :
6634 : 157 : tree temp = create_tmp_var (TYPE_MAIN_VARIANT (type));
6635 : 157 : TREE_OPERAND (*expr_p, 0) = temp;
6636 : 157 : *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
6637 : : *expr_p,
6638 : : build2 (MODIFY_EXPR, void_type_node,
6639 : : object, temp));
6640 : 157 : return GS_OK;
6641 : : }
6642 : :
6643 : 969517 : if (notify_temp_creation)
6644 : : return GS_OK;
6645 : :
6646 : : /* If there are nonzero elements and if needed, pre-evaluate to capture
6647 : : elements overlapping with the lhs into temporaries. We must do this
6648 : : before clearing to fetch the values before they are zeroed-out. */
6649 : 962519 : if (num_nonzero_elements > 0 && TREE_CODE (*expr_p) != INIT_EXPR)
6650 : : {
6651 : 213970 : preeval_data.lhs_base_decl = get_base_address (object);
6652 : 213970 : if (!DECL_P (preeval_data.lhs_base_decl))
6653 : 40843 : preeval_data.lhs_base_decl = NULL;
6654 : 213970 : preeval_data.lhs_alias_set = get_alias_set (object);
6655 : :
6656 : 213970 : gimplify_init_ctor_preeval (&TREE_OPERAND (*expr_p, 1),
6657 : : pre_p, post_p, &preeval_data);
6658 : : }
6659 : :
6660 : 962519 : bool ctor_has_side_effects_p
6661 : 962519 : = TREE_SIDE_EFFECTS (TREE_OPERAND (*expr_p, 1));
6662 : :
6663 : 962519 : if (cleared)
6664 : : {
6665 : : /* Zap the CONSTRUCTOR element list, which simplifies this case.
6666 : : Note that we still have to gimplify, in order to handle the
6667 : : case of variable sized types. Avoid shared tree structures. */
6668 : 188532 : CONSTRUCTOR_ELTS (ctor) = NULL;
6669 : 188532 : TREE_SIDE_EFFECTS (ctor) = 0;
6670 : 188532 : object = unshare_expr (object);
6671 : 188532 : gimplify_stmt (expr_p, pre_p);
6672 : : }
6673 : :
6674 : : /* If we have not block cleared the object, or if there are nonzero
6675 : : elements in the constructor, or if the constructor has side effects,
6676 : : add assignments to the individual scalar fields of the object. */
6677 : 188532 : if (!cleared
6678 : 188532 : || num_nonzero_elements > 0
6679 : 17185 : || ctor_has_side_effects_p)
6680 : 945705 : gimplify_init_ctor_eval (object, elts, pre_p, cleared);
6681 : :
6682 : 962519 : *expr_p = NULL_TREE;
6683 : : }
6684 : 962519 : break;
6685 : :
6686 : 0 : case COMPLEX_TYPE:
6687 : 0 : {
6688 : 0 : tree r, i;
6689 : :
6690 : 0 : if (notify_temp_creation)
6691 : : return GS_OK;
6692 : :
6693 : : /* Extract the real and imaginary parts out of the ctor. */
6694 : 0 : gcc_assert (elts->length () == 2);
6695 : 0 : r = (*elts)[0].value;
6696 : 0 : i = (*elts)[1].value;
6697 : 0 : if (r == NULL || i == NULL)
6698 : : {
6699 : 0 : tree zero = build_zero_cst (TREE_TYPE (type));
6700 : 0 : if (r == NULL)
6701 : 0 : r = zero;
6702 : 0 : if (i == NULL)
6703 : 0 : i = zero;
6704 : : }
6705 : :
6706 : : /* Complex types have either COMPLEX_CST or COMPLEX_EXPR to
6707 : : represent creation of a complex value. */
6708 : 0 : if (TREE_CONSTANT (r) && TREE_CONSTANT (i))
6709 : : {
6710 : 0 : ctor = build_complex (type, r, i);
6711 : 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6712 : : }
6713 : : else
6714 : : {
6715 : 0 : ctor = build2 (COMPLEX_EXPR, type, r, i);
6716 : 0 : TREE_OPERAND (*expr_p, 1) = ctor;
6717 : 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 1),
6718 : : pre_p,
6719 : : post_p,
6720 : 0 : rhs_predicate_for (TREE_OPERAND (*expr_p, 0)),
6721 : : fb_rvalue);
6722 : : }
6723 : : }
6724 : : break;
6725 : :
6726 : 6660 : case VECTOR_TYPE:
6727 : 6660 : {
6728 : 6660 : unsigned HOST_WIDE_INT ix;
6729 : 6660 : constructor_elt *ce;
6730 : :
6731 : 6660 : if (notify_temp_creation)
6732 : 1309529 : return GS_OK;
6733 : :
6734 : : /* Vector types use CONSTRUCTOR all the way through gimple
6735 : : compilation as a general initializer. */
6736 : 61781 : FOR_EACH_VEC_SAFE_ELT (elts, ix, ce)
6737 : : {
6738 : 55121 : enum gimplify_status tret;
6739 : 55121 : tret = gimplify_expr (&ce->value, pre_p, post_p, is_gimple_val,
6740 : : fb_rvalue);
6741 : 55121 : if (tret == GS_ERROR)
6742 : : ret = GS_ERROR;
6743 : 55120 : else if (TREE_STATIC (ctor)
6744 : 55152 : && !initializer_constant_valid_p (ce->value,
6745 : 32 : TREE_TYPE (ce->value)))
6746 : 32 : TREE_STATIC (ctor) = 0;
6747 : : }
6748 : 6660 : recompute_constructor_flags (ctor);
6749 : :
6750 : : /* Go ahead and simplify constant constructors to VECTOR_CST. */
6751 : 6660 : if (TREE_CONSTANT (ctor))
6752 : : {
6753 : 697 : bool constant_p = true;
6754 : : tree value;
6755 : :
6756 : : /* Even when ctor is constant, it might contain non-*_CST
6757 : : elements, such as addresses or trapping values like
6758 : : 1.0/0.0 - 1.0/0.0. Such expressions don't belong
6759 : : in VECTOR_CST nodes. */
6760 : 697 : FOR_EACH_CONSTRUCTOR_VALUE (elts, ix, value)
6761 : 478 : if (!CONSTANT_CLASS_P (value))
6762 : : {
6763 : : constant_p = false;
6764 : : break;
6765 : : }
6766 : :
6767 : 219 : if (constant_p)
6768 : : {
6769 : 219 : TREE_OPERAND (*expr_p, 1) = build_vector_from_ctor (type, elts);
6770 : 219 : break;
6771 : : }
6772 : : }
6773 : :
6774 : 6441 : if (!is_gimple_reg (TREE_OPERAND (*expr_p, 0)))
6775 : 915 : TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (ctor, pre_p);
6776 : : }
6777 : : break;
6778 : :
6779 : 0 : default:
6780 : : /* So how did we get a CONSTRUCTOR for a scalar type? */
6781 : 0 : gcc_unreachable ();
6782 : : }
6783 : :
6784 : 1299480 : if (ret == GS_ERROR)
6785 : : return GS_ERROR;
6786 : : /* If we have gimplified both sides of the initializer but have
6787 : : not emitted an assignment, do so now. */
6788 : 1299479 : if (*expr_p
6789 : : /* If the type is an empty type, we don't need to emit the
6790 : : assignment. */
6791 : 1299479 : && !is_empty_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
6792 : : {
6793 : 331284 : tree lhs = TREE_OPERAND (*expr_p, 0);
6794 : 331284 : tree rhs = TREE_OPERAND (*expr_p, 1);
6795 : 331284 : if (want_value && object == lhs)
6796 : 12 : lhs = unshare_expr (lhs);
6797 : 331284 : gassign *init = gimple_build_assign (lhs, rhs);
6798 : 331284 : gimplify_seq_add_stmt (pre_p, init);
6799 : : }
6800 : 1299479 : if (want_value)
6801 : : {
6802 : 19 : *expr_p = object;
6803 : 19 : ret = GS_OK;
6804 : : }
6805 : : else
6806 : : {
6807 : 1299460 : *expr_p = NULL;
6808 : 1299460 : ret = GS_ALL_DONE;
6809 : : }
6810 : :
6811 : : /* If the user requests to initialize automatic variables, we
6812 : : should initialize paddings inside the variable. Add a call to
6813 : : __builtin_clear_pading (&object, 0, for_auto_init = true) to
6814 : : initialize paddings of object always to zero regardless of
6815 : : INIT_TYPE. Note, we will not insert this call if the aggregate
6816 : : variable has be completely cleared already or it's initialized
6817 : : with an empty constructor. We cannot insert this call if the
6818 : : variable is a gimple register since __builtin_clear_padding will take
6819 : : the address of the variable. As a result, if a long double/_Complex long
6820 : : double variable will be spilled into stack later, its padding cannot
6821 : : be cleared with __builtin_clear_padding. We should clear its padding
6822 : : when it is spilled into memory. */
6823 : 1299479 : if (is_init_expr
6824 : 925841 : && !is_gimple_reg (object)
6825 : 921857 : && clear_padding_type_may_have_padding_p (type)
6826 : 881950 : && ((AGGREGATE_TYPE_P (type) && !cleared && !is_empty_ctor)
6827 : 223430 : || !AGGREGATE_TYPE_P (type))
6828 : 658520 : && var_needs_auto_init_p (object)
6829 : 1324005 : && flag_auto_var_init != AUTO_INIT_CXX26)
6830 : 38 : gimple_add_padding_init_for_auto_var (object, false, pre_p);
6831 : :
6832 : : return ret;
6833 : : }
6834 : :
6835 : : /* Given a pointer value OP0, return a simplified version of an
6836 : : indirection through OP0, or NULL_TREE if no simplification is
6837 : : possible. This may only be applied to a rhs of an expression.
6838 : : Note that the resulting type may be different from the type pointed
6839 : : to in the sense that it is still compatible from the langhooks
6840 : : point of view. */
6841 : :
6842 : : static tree
6843 : 538519 : gimple_fold_indirect_ref_rhs (tree t)
6844 : : {
6845 : 0 : return gimple_fold_indirect_ref (t);
6846 : : }
6847 : :
6848 : : /* Subroutine of gimplify_modify_expr to do simplifications of
6849 : : MODIFY_EXPRs based on the code of the RHS. We loop for as long as
6850 : : something changes. */
6851 : :
6852 : : static enum gimplify_status
6853 : 96897191 : gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p,
6854 : : gimple_seq *pre_p, gimple_seq *post_p,
6855 : : bool want_value)
6856 : : {
6857 : 96897191 : enum gimplify_status ret = GS_UNHANDLED;
6858 : 97573723 : bool changed;
6859 : :
6860 : 96120771 : do
6861 : : {
6862 : 97573723 : changed = false;
6863 : 97573723 : switch (TREE_CODE (*from_p))
6864 : : {
6865 : 11908413 : case VAR_DECL:
6866 : : /* If we're assigning from a read-only variable initialized with
6867 : : a constructor and not volatile, do the direct assignment from
6868 : : the constructor, but only if the target is not volatile either
6869 : : since this latter assignment might end up being done on a per
6870 : : field basis. However, if the target is volatile and the type
6871 : : is aggregate and non-addressable, gimplify_init_constructor
6872 : : knows that it needs to ensure a single access to the target
6873 : : and it will return GS_OK only in this case. */
6874 : 11908413 : if (TREE_READONLY (*from_p)
6875 : 102797 : && DECL_INITIAL (*from_p)
6876 : 66062 : && TREE_CODE (DECL_INITIAL (*from_p)) == CONSTRUCTOR
6877 : 8470 : && !TREE_THIS_VOLATILE (*from_p)
6878 : 11916883 : && (!TREE_THIS_VOLATILE (*to_p)
6879 : 6 : || (AGGREGATE_TYPE_P (TREE_TYPE (*to_p))
6880 : 6 : && !TREE_ADDRESSABLE (TREE_TYPE (*to_p)))))
6881 : : {
6882 : 8470 : tree old_from = *from_p;
6883 : 8470 : enum gimplify_status subret;
6884 : :
6885 : : /* Move the constructor into the RHS. */
6886 : 8470 : *from_p = unshare_expr (DECL_INITIAL (*from_p));
6887 : :
6888 : : /* Let's see if gimplify_init_constructor will need to put
6889 : : it in memory. */
6890 : 8470 : subret = gimplify_init_constructor (expr_p, NULL, NULL,
6891 : : false, true);
6892 : 8470 : if (subret == GS_ERROR)
6893 : : {
6894 : : /* If so, revert the change. */
6895 : 1424 : *from_p = old_from;
6896 : : }
6897 : : else
6898 : : {
6899 : : ret = GS_OK;
6900 : : changed = true;
6901 : : }
6902 : : }
6903 : : break;
6904 : 543739 : case INDIRECT_REF:
6905 : 543739 : if (!TREE_ADDRESSABLE (TREE_TYPE (*from_p)))
6906 : : /* If we have code like
6907 : :
6908 : : *(const A*)(A*)&x
6909 : :
6910 : : where the type of "x" is a (possibly cv-qualified variant
6911 : : of "A"), treat the entire expression as identical to "x".
6912 : : This kind of code arises in C++ when an object is bound
6913 : : to a const reference, and if "x" is a TARGET_EXPR we want
6914 : : to take advantage of the optimization below. But not if
6915 : : the type is TREE_ADDRESSABLE; then C++17 says that the
6916 : : TARGET_EXPR needs to be a temporary. */
6917 : 1077038 : if (tree t
6918 : 538519 : = gimple_fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)))
6919 : : {
6920 : 142586 : bool volatile_p = TREE_THIS_VOLATILE (*from_p);
6921 : 142586 : if (TREE_THIS_VOLATILE (t) != volatile_p)
6922 : : {
6923 : 5 : if (DECL_P (t))
6924 : 0 : t = build_simple_mem_ref_loc (EXPR_LOCATION (*from_p),
6925 : : build_fold_addr_expr (t));
6926 : 5 : if (REFERENCE_CLASS_P (t))
6927 : 5 : TREE_THIS_VOLATILE (t) = volatile_p;
6928 : : }
6929 : 142586 : *from_p = t;
6930 : 142586 : ret = GS_OK;
6931 : 142586 : changed = true;
6932 : : }
6933 : : break;
6934 : :
6935 : 222877 : case TARGET_EXPR:
6936 : 222877 : {
6937 : : /* If we are initializing something from a TARGET_EXPR, strip the
6938 : : TARGET_EXPR and initialize it directly, if possible. This can't
6939 : : be done if the initializer is void, since that implies that the
6940 : : temporary is set in some non-trivial way.
6941 : :
6942 : : ??? What about code that pulls out the temp and uses it
6943 : : elsewhere? I think that such code never uses the TARGET_EXPR as
6944 : : an initializer. If I'm wrong, we'll die because the temp won't
6945 : : have any RTL. In that case, I guess we'll need to replace
6946 : : references somehow. */
6947 : 222877 : tree init = TARGET_EXPR_INITIAL (*from_p);
6948 : :
6949 : 222877 : if (init
6950 : 222161 : && (TREE_CODE (*expr_p) != MODIFY_EXPR
6951 : 69887 : || !TARGET_EXPR_NO_ELIDE (*from_p))
6952 : 444748 : && !VOID_TYPE_P (TREE_TYPE (init)))
6953 : : {
6954 : 196431 : *from_p = init;
6955 : 196431 : ret = GS_OK;
6956 : 196431 : changed = true;
6957 : : }
6958 : : }
6959 : : break;
6960 : :
6961 : 330118 : case COMPOUND_EXPR:
6962 : : /* Remove any COMPOUND_EXPR in the RHS so the following cases will be
6963 : : caught. */
6964 : 330118 : gimplify_compound_expr (from_p, pre_p, true);
6965 : 330118 : ret = GS_OK;
6966 : 330118 : changed = true;
6967 : 330118 : break;
6968 : :
6969 : 1323365 : case CONSTRUCTOR:
6970 : : /* If we already made some changes, let the front end have a
6971 : : crack at this before we break it down. */
6972 : 1323365 : if (ret != GS_UNHANDLED)
6973 : : break;
6974 : :
6975 : : /* If we're initializing from a CONSTRUCTOR, break this into
6976 : : individual MODIFY_EXPRs. */
6977 : 1301059 : ret = gimplify_init_constructor (expr_p, pre_p, post_p, want_value,
6978 : : false);
6979 : 1301059 : return ret;
6980 : :
6981 : 227425 : case COND_EXPR:
6982 : : /* If we're assigning to a non-register type, push the assignment
6983 : : down into the branches. This is mandatory for ADDRESSABLE types,
6984 : : since we cannot generate temporaries for such, but it saves a
6985 : : copy in other cases as well.
6986 : : Also avoid an extra temporary and copy when assigning to
6987 : : a register. */
6988 : 227425 : if (!is_gimple_reg_type (TREE_TYPE (*from_p))
6989 : 227425 : || (is_gimple_reg (*to_p) && !gimplify_ctxp->allow_rhs_cond_expr))
6990 : : {
6991 : : /* This code should mirror the code in gimplify_cond_expr. */
6992 : 145912 : enum tree_code code = TREE_CODE (*expr_p);
6993 : 145912 : tree cond = *from_p;
6994 : 145912 : tree result = *to_p;
6995 : :
6996 : 145912 : ret = gimplify_expr (&result, pre_p, post_p,
6997 : : is_gimple_lvalue, fb_lvalue);
6998 : 145912 : if (ret != GS_ERROR)
6999 : 145912 : ret = GS_OK;
7000 : :
7001 : : /* If we are going to write RESULT more than once, clear
7002 : : TREE_READONLY flag, otherwise we might incorrectly promote
7003 : : the variable to static const and initialize it at compile
7004 : : time in one of the branches. */
7005 : 145912 : if (VAR_P (result)
7006 : 144864 : && TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node
7007 : 281703 : && TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
7008 : 135692 : TREE_READONLY (result) = 0;
7009 : 145912 : if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
7010 : 136703 : TREE_OPERAND (cond, 1)
7011 : 273406 : = build2 (code, void_type_node, result,
7012 : 136703 : TREE_OPERAND (cond, 1));
7013 : 145912 : if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
7014 : 145813 : TREE_OPERAND (cond, 2)
7015 : 291626 : = build2 (code, void_type_node, unshare_expr (result),
7016 : 145813 : TREE_OPERAND (cond, 2));
7017 : :
7018 : 145912 : TREE_TYPE (cond) = void_type_node;
7019 : 145912 : recalculate_side_effects (cond);
7020 : :
7021 : 145912 : if (want_value)
7022 : : {
7023 : 66 : gimplify_and_add (cond, pre_p);
7024 : 66 : *expr_p = unshare_expr (result);
7025 : : }
7026 : : else
7027 : 145846 : *expr_p = cond;
7028 : 145912 : return ret;
7029 : : }
7030 : : break;
7031 : :
7032 : 10102835 : case CALL_EXPR:
7033 : : /* For calls that return in memory, give *to_p as the CALL_EXPR's
7034 : : return slot so that we don't generate a temporary. */
7035 : 10102835 : if (!CALL_EXPR_RETURN_SLOT_OPT (*from_p)
7036 : 10102835 : && aggregate_value_p (*from_p, *from_p))
7037 : : {
7038 : 251510 : bool use_target;
7039 : :
7040 : 251510 : if (!(rhs_predicate_for (*to_p))(*from_p))
7041 : : /* If we need a temporary, *to_p isn't accurate. */
7042 : : use_target = false;
7043 : : /* It's OK to use the return slot directly unless it's an NRV. */
7044 : 250767 : else if (TREE_CODE (*to_p) == RESULT_DECL
7045 : 5213 : && DECL_NAME (*to_p) == NULL_TREE
7046 : 255844 : && needs_to_live_in_memory (*to_p))
7047 : : use_target = true;
7048 : 245690 : else if (is_gimple_reg_type (TREE_TYPE (*to_p))
7049 : 245690 : || (DECL_P (*to_p) && DECL_REGISTER (*to_p)))
7050 : : /* Don't force regs into memory. */
7051 : : use_target = false;
7052 : 231638 : else if (TREE_CODE (*expr_p) == INIT_EXPR)
7053 : : /* It's OK to use the target directly if it's being
7054 : : initialized. */
7055 : : use_target = true;
7056 : 13862 : else if (TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (*to_p)))
7057 : : != INTEGER_CST)
7058 : : /* Always use the target and thus RSO for variable-sized types.
7059 : : GIMPLE cannot deal with a variable-sized assignment
7060 : : embedded in a call statement. */
7061 : : use_target = true;
7062 : 13834 : else if (TREE_CODE (*to_p) != SSA_NAME
7063 : 13834 : && (!is_gimple_variable (*to_p)
7064 : 10776 : || needs_to_live_in_memory (*to_p)))
7065 : : /* Don't use the original target if it's already addressable;
7066 : : if its address escapes, and the called function uses the
7067 : : NRV optimization, a conforming program could see *to_p
7068 : : change before the called function returns; see c++/19317.
7069 : : When optimizing, the return_slot pass marks more functions
7070 : : as safe after we have escape info. */
7071 : : use_target = false;
7072 : : else
7073 : : use_target = true;
7074 : :
7075 : : if (use_target)
7076 : : {
7077 : 224957 : CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1;
7078 : 224957 : mark_addressable (*to_p);
7079 : : }
7080 : : }
7081 : : break;
7082 : :
7083 : 1516 : case WITH_SIZE_EXPR:
7084 : : /* Likewise for calls that return an aggregate of non-constant size,
7085 : : since we would not be able to generate a temporary at all. */
7086 : 1516 : if (TREE_CODE (TREE_OPERAND (*from_p, 0)) == CALL_EXPR)
7087 : : {
7088 : 338 : *from_p = TREE_OPERAND (*from_p, 0);
7089 : : /* We don't change ret in this case because the
7090 : : WITH_SIZE_EXPR might have been added in
7091 : : gimplify_modify_expr, so returning GS_OK would lead to an
7092 : : infinite loop. */
7093 : 338 : changed = true;
7094 : : }
7095 : : break;
7096 : :
7097 : : /* If we're initializing from a container, push the initialization
7098 : : inside it. */
7099 : 1717 : case CLEANUP_POINT_EXPR:
7100 : 1717 : case BIND_EXPR:
7101 : 1717 : case STATEMENT_LIST:
7102 : 1717 : {
7103 : 1717 : tree wrap = *from_p;
7104 : 1717 : tree t;
7105 : :
7106 : 1717 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_min_lval,
7107 : : fb_lvalue);
7108 : 1717 : if (ret != GS_ERROR)
7109 : 1717 : ret = GS_OK;
7110 : :
7111 : 1717 : t = voidify_wrapper_expr (wrap, *expr_p);
7112 : 1717 : gcc_assert (t == *expr_p);
7113 : :
7114 : 1717 : if (want_value)
7115 : : {
7116 : 6 : gimplify_and_add (wrap, pre_p);
7117 : 6 : *expr_p = unshare_expr (*to_p);
7118 : : }
7119 : : else
7120 : 1711 : *expr_p = wrap;
7121 : : return GS_OK;
7122 : : }
7123 : :
7124 : 9396608 : case NOP_EXPR:
7125 : : /* Pull out compound literal expressions from a NOP_EXPR.
7126 : : Those are created in the C FE to drop qualifiers during
7127 : : lvalue conversion. */
7128 : 9396608 : if ((TREE_CODE (TREE_OPERAND (*from_p, 0)) == COMPOUND_LITERAL_EXPR)
7129 : 9396608 : && tree_ssa_useless_type_conversion (*from_p))
7130 : : {
7131 : 13 : *from_p = TREE_OPERAND (*from_p, 0);
7132 : 13 : ret = GS_OK;
7133 : 13 : changed = true;
7134 : : }
7135 : : break;
7136 : :
7137 : 4264 : case COMPOUND_LITERAL_EXPR:
7138 : 4264 : {
7139 : 4264 : tree complit = TREE_OPERAND (*expr_p, 1);
7140 : 4264 : tree decl_s = COMPOUND_LITERAL_EXPR_DECL_EXPR (complit);
7141 : 4264 : tree decl = DECL_EXPR_DECL (decl_s);
7142 : 4264 : tree init = DECL_INITIAL (decl);
7143 : :
7144 : : /* struct T x = (struct T) { 0, 1, 2 } can be optimized
7145 : : into struct T x = { 0, 1, 2 } if the address of the
7146 : : compound literal has never been taken. */
7147 : 4264 : if (!TREE_ADDRESSABLE (complit)
7148 : 4264 : && !TREE_ADDRESSABLE (decl)
7149 : 4264 : && init)
7150 : : {
7151 : 4264 : *expr_p = copy_node (*expr_p);
7152 : 4264 : TREE_OPERAND (*expr_p, 1) = init;
7153 : 4264 : return GS_OK;
7154 : : }
7155 : : }
7156 : :
7157 : : default:
7158 : : break;
7159 : : }
7160 : : }
7161 : : while (changed);
7162 : :
7163 : : return ret;
7164 : : }
7165 : :
7166 : :
7167 : : /* Return true if T looks like a valid GIMPLE statement. */
7168 : :
7169 : : static bool
7170 : 19220239 : is_gimple_stmt (tree t)
7171 : : {
7172 : 19220239 : const enum tree_code code = TREE_CODE (t);
7173 : :
7174 : 19220239 : switch (code)
7175 : : {
7176 : 1704782 : case NOP_EXPR:
7177 : : /* The only valid NOP_EXPR is the empty statement. */
7178 : 1704782 : return IS_EMPTY_STMT (t);
7179 : :
7180 : 0 : case BIND_EXPR:
7181 : 0 : case COND_EXPR:
7182 : : /* These are only valid if they're void. */
7183 : 0 : return TREE_TYPE (t) == NULL || VOID_TYPE_P (TREE_TYPE (t));
7184 : :
7185 : : case SWITCH_EXPR:
7186 : : case GOTO_EXPR:
7187 : : case RETURN_EXPR:
7188 : : case LABEL_EXPR:
7189 : : case CASE_LABEL_EXPR:
7190 : : case TRY_CATCH_EXPR:
7191 : : case TRY_FINALLY_EXPR:
7192 : : case EH_FILTER_EXPR:
7193 : : case CATCH_EXPR:
7194 : : case ASM_EXPR:
7195 : : case STATEMENT_LIST:
7196 : : case OACC_PARALLEL:
7197 : : case OACC_KERNELS:
7198 : : case OACC_SERIAL:
7199 : : case OACC_DATA:
7200 : : case OACC_HOST_DATA:
7201 : : case OACC_DECLARE:
7202 : : case OACC_UPDATE:
7203 : : case OACC_ENTER_DATA:
7204 : : case OACC_EXIT_DATA:
7205 : : case OACC_CACHE:
7206 : : case OMP_PARALLEL:
7207 : : case OMP_FOR:
7208 : : case OMP_SIMD:
7209 : : case OMP_DISTRIBUTE:
7210 : : case OMP_LOOP:
7211 : : case OMP_TILE:
7212 : : case OMP_UNROLL:
7213 : : case OACC_LOOP:
7214 : : case OMP_SCAN:
7215 : : case OMP_SCOPE:
7216 : : case OMP_DISPATCH:
7217 : : case OMP_SECTIONS:
7218 : : case OMP_SECTION:
7219 : : case OMP_STRUCTURED_BLOCK:
7220 : : case OMP_SINGLE:
7221 : : case OMP_MASTER:
7222 : : case OMP_MASKED:
7223 : : case OMP_TASKGROUP:
7224 : : case OMP_ORDERED:
7225 : : case OMP_CRITICAL:
7226 : : case OMP_METADIRECTIVE:
7227 : : case OMP_TASK:
7228 : : case OMP_TARGET:
7229 : : case OMP_TARGET_DATA:
7230 : : case OMP_TARGET_UPDATE:
7231 : : case OMP_TARGET_ENTER_DATA:
7232 : : case OMP_TARGET_EXIT_DATA:
7233 : : case OMP_TASKLOOP:
7234 : : case OMP_TEAMS:
7235 : : /* These are always void. */
7236 : : return true;
7237 : :
7238 : : case CALL_EXPR:
7239 : : case MODIFY_EXPR:
7240 : : case PREDICT_EXPR:
7241 : : /* These are valid regardless of their type. */
7242 : : return true;
7243 : :
7244 : : default:
7245 : : return false;
7246 : : }
7247 : : }
7248 : :
7249 : :
7250 : : /* Promote partial stores to COMPLEX variables to total stores. *EXPR_P is
7251 : : a MODIFY_EXPR with a lhs of a REAL/IMAGPART_EXPR of a gimple register.
7252 : :
7253 : : IMPORTANT NOTE: This promotion is performed by introducing a load of the
7254 : : other, unmodified part of the complex object just before the total store.
7255 : : As a consequence, if the object is still uninitialized, an undefined value
7256 : : will be loaded into a register, which may result in a spurious exception
7257 : : if the register is floating-point and the value happens to be a signaling
7258 : : NaN for example. Then the fully-fledged complex operations lowering pass
7259 : : followed by a DCE pass are necessary in order to fix things up. */
7260 : :
7261 : : static enum gimplify_status
7262 : 1960 : gimplify_modify_expr_complex_part (tree *expr_p, gimple_seq *pre_p,
7263 : : bool want_value)
7264 : : {
7265 : 1960 : enum tree_code code, ocode;
7266 : 1960 : tree lhs, rhs, new_rhs, other, realpart, imagpart;
7267 : :
7268 : 1960 : lhs = TREE_OPERAND (*expr_p, 0);
7269 : 1960 : rhs = TREE_OPERAND (*expr_p, 1);
7270 : 1960 : code = TREE_CODE (lhs);
7271 : 1960 : lhs = TREE_OPERAND (lhs, 0);
7272 : :
7273 : 1960 : ocode = code == REALPART_EXPR ? IMAGPART_EXPR : REALPART_EXPR;
7274 : 1960 : other = build1 (ocode, TREE_TYPE (rhs), lhs);
7275 : 1960 : suppress_warning (other);
7276 : 1960 : other = get_formal_tmp_var (other, pre_p);
7277 : :
7278 : 1960 : realpart = code == REALPART_EXPR ? rhs : other;
7279 : 966 : imagpart = code == REALPART_EXPR ? other : rhs;
7280 : :
7281 : 1960 : if (TREE_CONSTANT (realpart) && TREE_CONSTANT (imagpart))
7282 : 0 : new_rhs = build_complex (TREE_TYPE (lhs), realpart, imagpart);
7283 : : else
7284 : 1960 : new_rhs = build2 (COMPLEX_EXPR, TREE_TYPE (lhs), realpart, imagpart);
7285 : :
7286 : 1960 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (lhs, new_rhs));
7287 : 1960 : *expr_p = (want_value) ? rhs : NULL_TREE;
7288 : :
7289 : 1960 : return GS_ALL_DONE;
7290 : : }
7291 : :
7292 : : /* Gimplify the MODIFY_EXPR node pointed to by EXPR_P.
7293 : :
7294 : : modify_expr
7295 : : : varname '=' rhs
7296 : : | '*' ID '=' rhs
7297 : :
7298 : : PRE_P points to the list where side effects that must happen before
7299 : : *EXPR_P should be stored.
7300 : :
7301 : : POST_P points to the list where side effects that must happen after
7302 : : *EXPR_P should be stored.
7303 : :
7304 : : WANT_VALUE is nonzero iff we want to use the value of this expression
7305 : : in another expression. */
7306 : :
7307 : : static enum gimplify_status
7308 : 50060173 : gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
7309 : : bool want_value)
7310 : : {
7311 : 50060173 : tree *from_p = &TREE_OPERAND (*expr_p, 1);
7312 : 50060173 : tree *to_p = &TREE_OPERAND (*expr_p, 0);
7313 : 50060173 : enum gimplify_status ret = GS_UNHANDLED;
7314 : 50060173 : gimple *assign;
7315 : 50060173 : location_t loc = EXPR_LOCATION (*expr_p);
7316 : 50060173 : gimple_stmt_iterator gsi;
7317 : :
7318 : 50060173 : if (error_operand_p (*from_p) || error_operand_p (*to_p))
7319 : : return GS_ERROR;
7320 : :
7321 : 50060146 : gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
7322 : : || TREE_CODE (*expr_p) == INIT_EXPR);
7323 : :
7324 : : /* Trying to simplify a clobber using normal logic doesn't work,
7325 : : so handle it here. */
7326 : 50060146 : if (TREE_CLOBBER_P (*from_p))
7327 : : {
7328 : 586302 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7329 : 586302 : if (ret == GS_ERROR)
7330 : : return ret;
7331 : 586302 : gcc_assert (!want_value);
7332 : 586302 : if (!VAR_P (*to_p) && TREE_CODE (*to_p) != MEM_REF)
7333 : : {
7334 : 213 : tree addr = get_initialized_tmp_var (build_fold_addr_expr (*to_p),
7335 : : pre_p, post_p);
7336 : 213 : *to_p = build_simple_mem_ref_loc (EXPR_LOCATION (*to_p), addr);
7337 : : }
7338 : 586302 : gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
7339 : 586302 : *expr_p = NULL;
7340 : 586302 : return GS_ALL_DONE;
7341 : : }
7342 : :
7343 : : /* Convert initialization from an empty variable-size CONSTRUCTOR to
7344 : : memset. */
7345 : 49473844 : if (TREE_TYPE (*from_p) != error_mark_node
7346 : 49473844 : && TYPE_SIZE_UNIT (TREE_TYPE (*from_p))
7347 : 49473844 : && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p)))
7348 : 1543 : && TREE_CODE (*from_p) == CONSTRUCTOR
7349 : 49473942 : && CONSTRUCTOR_NELTS (*from_p) == 0)
7350 : : {
7351 : 78 : maybe_with_size_expr (from_p);
7352 : 78 : gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR);
7353 : 78 : return gimplify_modify_expr_to_memset (expr_p,
7354 : 78 : TREE_OPERAND (*from_p, 1),
7355 : 78 : want_value, pre_p);
7356 : : }
7357 : :
7358 : : /* Insert pointer conversions required by the middle-end that are not
7359 : : required by the frontend. This fixes middle-end type checking for
7360 : : for example gcc.dg/redecl-6.c. */
7361 : 49473766 : if (POINTER_TYPE_P (TREE_TYPE (*to_p)))
7362 : : {
7363 : 13375250 : STRIP_USELESS_TYPE_CONVERSION (*from_p);
7364 : 13375250 : if (!useless_type_conversion_p (TREE_TYPE (*to_p), TREE_TYPE (*from_p)))
7365 : 501 : *from_p = fold_convert_loc (loc, TREE_TYPE (*to_p), *from_p);
7366 : : }
7367 : :
7368 : : /* See if any simplifications can be done based on what the RHS is. */
7369 : 49473766 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7370 : : want_value);
7371 : 49473766 : if (ret != GS_UNHANDLED)
7372 : : return ret;
7373 : :
7374 : : /* For empty types only gimplify the left hand side and right hand
7375 : : side as statements and throw away the assignment. Do this after
7376 : : gimplify_modify_expr_rhs so we handle TARGET_EXPRs of addressable
7377 : : types properly. */
7378 : 47425838 : if (is_empty_type (TREE_TYPE (*from_p))
7379 : 13633 : && !want_value
7380 : : /* Don't do this for calls that return addressable types, expand_call
7381 : : relies on those having a lhs. */
7382 : 47439464 : && !(TREE_ADDRESSABLE (TREE_TYPE (*from_p))
7383 : 11573 : && TREE_CODE (*from_p) == CALL_EXPR))
7384 : : {
7385 : 2053 : suppress_warning (*from_p, OPT_Wunused_result);
7386 : 2053 : gimplify_stmt (from_p, pre_p);
7387 : 2053 : gimplify_stmt (to_p, pre_p);
7388 : 2053 : *expr_p = NULL_TREE;
7389 : 2053 : return GS_ALL_DONE;
7390 : : }
7391 : :
7392 : : /* If the value being copied is of variable width, compute the length
7393 : : of the copy into a WITH_SIZE_EXPR. Note that we need to do this
7394 : : before gimplifying any of the operands so that we can resolve any
7395 : : PLACEHOLDER_EXPRs in the size. Also note that the RTL expander uses
7396 : : the size of the expression to be copied, not of the destination, so
7397 : : that is what we must do here. */
7398 : 47423785 : maybe_with_size_expr (from_p);
7399 : :
7400 : : /* As a special case, we have to temporarily allow for assignments
7401 : : with a CALL_EXPR on the RHS. Since in GIMPLE a function call is
7402 : : a toplevel statement, when gimplifying the GENERIC expression
7403 : : MODIFY_EXPR <a, CALL_EXPR <foo>>, we cannot create the tuple
7404 : : GIMPLE_ASSIGN <a, GIMPLE_CALL <foo>>.
7405 : :
7406 : : Instead, we need to create the tuple GIMPLE_CALL <a, foo>. To
7407 : : prevent gimplify_expr from trying to create a new temporary for
7408 : : foo's LHS, we tell it that it should only gimplify until it
7409 : : reaches the CALL_EXPR. On return from gimplify_expr, the newly
7410 : : created GIMPLE_CALL <foo> will be the last statement in *PRE_P
7411 : : and all we need to do here is set 'a' to be its LHS. */
7412 : :
7413 : : /* Gimplify the RHS first for C++17 and bug 71104. */
7414 : 47423785 : gimple_predicate initial_pred = initial_rhs_predicate_for (*to_p);
7415 : 47423785 : ret = gimplify_expr (from_p, pre_p, post_p, initial_pred, fb_rvalue);
7416 : 47423785 : if (ret == GS_ERROR)
7417 : : return ret;
7418 : :
7419 : : /* Then gimplify the LHS. */
7420 : : /* If we gimplified the RHS to a CALL_EXPR and that call may return
7421 : : twice we have to make sure to gimplify into non-SSA as otherwise
7422 : : the abnormal edge added later will make those defs not dominate
7423 : : their uses.
7424 : : ??? Technically this applies only to the registers used in the
7425 : : resulting non-register *TO_P. */
7426 : 47423500 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
7427 : 47423500 : if (saved_into_ssa
7428 : 45117913 : && TREE_CODE (*from_p) == CALL_EXPR
7429 : 52549560 : && call_expr_flags (*from_p) & ECF_RETURNS_TWICE)
7430 : 1481 : gimplify_ctxp->into_ssa = false;
7431 : 47423500 : ret = gimplify_expr (to_p, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
7432 : 47423500 : gimplify_ctxp->into_ssa = saved_into_ssa;
7433 : 47423500 : if (ret == GS_ERROR)
7434 : : return ret;
7435 : :
7436 : : /* Now that the LHS is gimplified, re-gimplify the RHS if our initial
7437 : : guess for the predicate was wrong. */
7438 : 47423425 : gimple_predicate final_pred = rhs_predicate_for (*to_p);
7439 : 47423425 : if (final_pred != initial_pred)
7440 : : {
7441 : 8092868 : ret = gimplify_expr (from_p, pre_p, post_p, final_pred, fb_rvalue);
7442 : 8092868 : if (ret == GS_ERROR)
7443 : : return ret;
7444 : : }
7445 : :
7446 : : /* In case of va_arg internal fn wrappped in a WITH_SIZE_EXPR, add the type
7447 : : size as argument to the call. */
7448 : 47423425 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7449 : : {
7450 : 1413 : tree call = TREE_OPERAND (*from_p, 0);
7451 : 1413 : tree vlasize = TREE_OPERAND (*from_p, 1);
7452 : :
7453 : 1413 : if (TREE_CODE (call) == CALL_EXPR
7454 : 1413 : && CALL_EXPR_IFN (call) == IFN_VA_ARG)
7455 : : {
7456 : 95 : int nargs = call_expr_nargs (call);
7457 : 95 : tree type = TREE_TYPE (call);
7458 : 95 : tree ap = CALL_EXPR_ARG (call, 0);
7459 : 95 : tree tag = CALL_EXPR_ARG (call, 1);
7460 : 95 : tree aptag = CALL_EXPR_ARG (call, 2);
7461 : 95 : tree newcall = build_call_expr_internal_loc (EXPR_LOCATION (call),
7462 : : IFN_VA_ARG, type,
7463 : : nargs + 1, ap, tag,
7464 : : aptag, vlasize);
7465 : 95 : TREE_OPERAND (*from_p, 0) = newcall;
7466 : : }
7467 : : }
7468 : :
7469 : : /* Now see if the above changed *from_p to something we handle specially. */
7470 : 47423425 : ret = gimplify_modify_expr_rhs (expr_p, from_p, to_p, pre_p, post_p,
7471 : : want_value);
7472 : 47423425 : if (ret != GS_UNHANDLED)
7473 : : return ret;
7474 : :
7475 : : /* If we've got a variable sized assignment between two lvalues (i.e. does
7476 : : not involve a call), then we can make things a bit more straightforward
7477 : : by converting the assignment to memcpy or memset. */
7478 : 47422464 : if (TREE_CODE (*from_p) == WITH_SIZE_EXPR)
7479 : : {
7480 : 1075 : tree from = TREE_OPERAND (*from_p, 0);
7481 : 1075 : tree size = TREE_OPERAND (*from_p, 1);
7482 : :
7483 : 1075 : if (TREE_CODE (from) == CONSTRUCTOR)
7484 : 0 : return gimplify_modify_expr_to_memset (expr_p, size, want_value, pre_p);
7485 : 1075 : else if (is_gimple_addressable (from)
7486 : 1075 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (*to_p)))
7487 : 2149 : && ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (from))))
7488 : : {
7489 : 1074 : *from_p = from;
7490 : 1074 : return gimplify_modify_expr_to_memcpy (expr_p, size, want_value,
7491 : 1074 : pre_p);
7492 : : }
7493 : : }
7494 : :
7495 : : /* Transform partial stores to non-addressable complex variables into
7496 : : total stores. This allows us to use real instead of virtual operands
7497 : : for these variables, which improves optimization. */
7498 : 47421390 : if ((TREE_CODE (*to_p) == REALPART_EXPR
7499 : 47421390 : || TREE_CODE (*to_p) == IMAGPART_EXPR)
7500 : 47421390 : && is_gimple_reg (TREE_OPERAND (*to_p, 0)))
7501 : 1960 : return gimplify_modify_expr_complex_part (expr_p, pre_p, want_value);
7502 : :
7503 : : /* Try to alleviate the effects of the gimplification creating artificial
7504 : : temporaries (see for example is_gimple_reg_rhs) on the debug info, but
7505 : : make sure not to create DECL_DEBUG_EXPR links across functions. */
7506 : 47419430 : if (!gimplify_ctxp->into_ssa
7507 : 2304688 : && VAR_P (*from_p)
7508 : 456399 : && DECL_IGNORED_P (*from_p)
7509 : 334230 : && DECL_P (*to_p)
7510 : 125067 : && !DECL_IGNORED_P (*to_p)
7511 : 29313 : && decl_function_context (*to_p) == current_function_decl
7512 : 47443291 : && decl_function_context (*from_p) == current_function_decl)
7513 : : {
7514 : 23856 : if (!DECL_NAME (*from_p) && DECL_NAME (*to_p))
7515 : 18523 : DECL_NAME (*from_p)
7516 : 37046 : = create_tmp_var_name (IDENTIFIER_POINTER (DECL_NAME (*to_p)));
7517 : 23856 : DECL_HAS_DEBUG_EXPR_P (*from_p) = 1;
7518 : 23856 : SET_DECL_DEBUG_EXPR (*from_p, *to_p);
7519 : : }
7520 : :
7521 : 47419430 : if (want_value && TREE_THIS_VOLATILE (*to_p))
7522 : 773 : *from_p = get_initialized_tmp_var (*from_p, pre_p, post_p);
7523 : :
7524 : 47419430 : if (TREE_CODE (*from_p) == CALL_EXPR)
7525 : : {
7526 : : /* Since the RHS is a CALL_EXPR, we need to create a GIMPLE_CALL
7527 : : instead of a GIMPLE_ASSIGN. */
7528 : 4820798 : gcall *call_stmt;
7529 : 4820798 : if (CALL_EXPR_FN (*from_p) == NULL_TREE)
7530 : : {
7531 : : /* Gimplify internal functions created in the FEs. */
7532 : 345474 : int nargs = call_expr_nargs (*from_p), i;
7533 : 345474 : enum internal_fn ifn = CALL_EXPR_IFN (*from_p);
7534 : 345474 : auto_vec<tree> vargs (nargs);
7535 : :
7536 : 1746790 : for (i = 0; i < nargs; i++)
7537 : : {
7538 : 1055842 : gimplify_arg (&CALL_EXPR_ARG (*from_p, i), pre_p,
7539 : 1055842 : EXPR_LOCATION (*from_p));
7540 : 1055842 : vargs.quick_push (CALL_EXPR_ARG (*from_p, i));
7541 : : }
7542 : 345474 : call_stmt = gimple_build_call_internal_vec (ifn, vargs);
7543 : 345474 : gimple_call_set_nothrow (call_stmt, TREE_NOTHROW (*from_p));
7544 : 690948 : gimple_set_location (call_stmt, EXPR_LOCATION (*expr_p));
7545 : 345474 : }
7546 : : else
7547 : : {
7548 : 4475324 : tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*from_p));
7549 : 4475324 : CALL_EXPR_FN (*from_p) = TREE_OPERAND (CALL_EXPR_FN (*from_p), 0);
7550 : 4475324 : STRIP_USELESS_TYPE_CONVERSION (CALL_EXPR_FN (*from_p));
7551 : 4475324 : tree fndecl = get_callee_fndecl (*from_p);
7552 : 4475324 : if (fndecl
7553 : 4360621 : && fndecl_built_in_p (fndecl, BUILT_IN_EXPECT)
7554 : 4602964 : && call_expr_nargs (*from_p) == 3)
7555 : 64413 : call_stmt = gimple_build_call_internal (IFN_BUILTIN_EXPECT, 3,
7556 : 64413 : CALL_EXPR_ARG (*from_p, 0),
7557 : 64413 : CALL_EXPR_ARG (*from_p, 1),
7558 : 64413 : CALL_EXPR_ARG (*from_p, 2));
7559 : : else
7560 : : {
7561 : 4410911 : call_stmt = gimple_build_call_from_tree (*from_p, fnptrtype);
7562 : : }
7563 : : }
7564 : 4820798 : notice_special_calls (call_stmt);
7565 : 4820798 : if (!gimple_call_noreturn_p (call_stmt) || !should_remove_lhs_p (*to_p))
7566 : 4820672 : gimple_call_set_lhs (call_stmt, *to_p);
7567 : 126 : else if (TREE_CODE (*to_p) == SSA_NAME)
7568 : : /* The above is somewhat premature, avoid ICEing later for a
7569 : : SSA name w/o a definition. We may have uses in the GIMPLE IL.
7570 : : ??? This doesn't make it a default-def. */
7571 : 35 : SSA_NAME_DEF_STMT (*to_p) = gimple_build_nop ();
7572 : :
7573 : : assign = call_stmt;
7574 : : }
7575 : : else
7576 : : {
7577 : 42598632 : assign = gimple_build_assign (*to_p, *from_p);
7578 : 42598632 : gimple_set_location (assign, EXPR_LOCATION (*expr_p));
7579 : 42598632 : if (COMPARISON_CLASS_P (*from_p))
7580 : 1221130 : copy_warning (assign, *from_p);
7581 : : }
7582 : :
7583 : 47419430 : if (gimplify_ctxp->into_ssa && is_gimple_reg (*to_p))
7584 : : {
7585 : : /* We should have got an SSA name from the start. */
7586 : 35053727 : gcc_assert (TREE_CODE (*to_p) == SSA_NAME
7587 : : || ! gimple_in_ssa_p (cfun));
7588 : : }
7589 : :
7590 : 47419430 : gimplify_seq_add_stmt (pre_p, assign);
7591 : 47419430 : gsi = gsi_last (*pre_p);
7592 : 47419430 : maybe_fold_stmt (&gsi);
7593 : :
7594 : 47419430 : if (want_value)
7595 : : {
7596 : 648496 : *expr_p = TREE_THIS_VOLATILE (*to_p) ? *from_p : unshare_expr (*to_p);
7597 : 648496 : return GS_OK;
7598 : : }
7599 : : else
7600 : 46770934 : *expr_p = NULL;
7601 : :
7602 : 46770934 : return GS_ALL_DONE;
7603 : : }
7604 : :
7605 : : /* Gimplify a comparison between two variable-sized objects. Do this
7606 : : with a call to BUILT_IN_MEMCMP. */
7607 : :
7608 : : static enum gimplify_status
7609 : 0 : gimplify_variable_sized_compare (tree *expr_p)
7610 : : {
7611 : 0 : location_t loc = EXPR_LOCATION (*expr_p);
7612 : 0 : tree op0 = TREE_OPERAND (*expr_p, 0);
7613 : 0 : tree op1 = TREE_OPERAND (*expr_p, 1);
7614 : 0 : tree t, arg, dest, src, expr;
7615 : :
7616 : 0 : arg = TYPE_SIZE_UNIT (TREE_TYPE (op0));
7617 : 0 : arg = unshare_expr (arg);
7618 : 0 : arg = SUBSTITUTE_PLACEHOLDER_IN_EXPR (arg, op0);
7619 : 0 : src = build_fold_addr_expr_loc (loc, op1);
7620 : 0 : dest = build_fold_addr_expr_loc (loc, op0);
7621 : 0 : t = builtin_decl_implicit (BUILT_IN_MEMCMP);
7622 : 0 : t = build_call_expr_loc (loc, t, 3, dest, src, arg);
7623 : :
7624 : 0 : expr
7625 : 0 : = build2 (TREE_CODE (*expr_p), TREE_TYPE (*expr_p), t, integer_zero_node);
7626 : 0 : SET_EXPR_LOCATION (expr, loc);
7627 : 0 : *expr_p = expr;
7628 : :
7629 : 0 : return GS_OK;
7630 : : }
7631 : :
7632 : : /* Gimplify a comparison between two aggregate objects of integral scalar
7633 : : mode as a comparison between the bitwise equivalent scalar values. */
7634 : :
7635 : : static enum gimplify_status
7636 : 16 : gimplify_scalar_mode_aggregate_compare (tree *expr_p)
7637 : : {
7638 : 16 : const location_t loc = EXPR_LOCATION (*expr_p);
7639 : 16 : const enum tree_code code = TREE_CODE (*expr_p);
7640 : 16 : tree op0 = TREE_OPERAND (*expr_p, 0);
7641 : 16 : tree op1 = TREE_OPERAND (*expr_p, 1);
7642 : 16 : tree type = TREE_TYPE (op0);
7643 : 16 : tree scalar_type = lang_hooks.types.type_for_mode (TYPE_MODE (type), 1);
7644 : :
7645 : 16 : op0 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op0);
7646 : 16 : op1 = fold_build1_loc (loc, VIEW_CONVERT_EXPR, scalar_type, op1);
7647 : :
7648 : : /* We need to perform ordering comparisons in memory order like memcmp and,
7649 : : therefore, may need to byte-swap operands for little-endian targets. */
7650 : 16 : if (code != EQ_EXPR && code != NE_EXPR)
7651 : : {
7652 : 0 : gcc_assert (BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN);
7653 : 0 : gcc_assert (TREE_CODE (scalar_type) == INTEGER_TYPE);
7654 : 0 : tree fndecl;
7655 : :
7656 : 0 : if (BYTES_BIG_ENDIAN)
7657 : : fndecl = NULL_TREE;
7658 : : else
7659 : 0 : switch (int_size_in_bytes (scalar_type))
7660 : : {
7661 : : case 1:
7662 : : fndecl = NULL_TREE;
7663 : : break;
7664 : 0 : case 2:
7665 : 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP16);
7666 : 0 : break;
7667 : 0 : case 4:
7668 : 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP32);
7669 : 0 : break;
7670 : 0 : case 8:
7671 : 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP64);
7672 : 0 : break;
7673 : 0 : case 16:
7674 : 0 : fndecl = builtin_decl_implicit (BUILT_IN_BSWAP128);
7675 : 0 : break;
7676 : 0 : default:
7677 : 0 : gcc_unreachable ();
7678 : : }
7679 : :
7680 : 0 : if (fndecl)
7681 : : {
7682 : 0 : op0 = build_call_expr_loc (loc, fndecl, 1, op0);
7683 : 0 : op1 = build_call_expr_loc (loc, fndecl, 1, op1);
7684 : : }
7685 : : }
7686 : :
7687 : 16 : *expr_p = fold_build2_loc (loc, code, TREE_TYPE (*expr_p), op0, op1);
7688 : :
7689 : 16 : return GS_OK;
7690 : : }
7691 : :
7692 : : /* Gimplify an expression sequence. This function gimplifies each
7693 : : expression and rewrites the original expression with the last
7694 : : expression of the sequence in GIMPLE form.
7695 : :
7696 : : PRE_P points to the list where the side effects for all the
7697 : : expressions in the sequence will be emitted.
7698 : :
7699 : : WANT_VALUE is true when the result of the last COMPOUND_EXPR is used. */
7700 : :
7701 : : static enum gimplify_status
7702 : 1096651 : gimplify_compound_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
7703 : : {
7704 : 1096651 : tree t = *expr_p;
7705 : :
7706 : 1183374 : do
7707 : : {
7708 : 1183374 : tree *sub_p = &TREE_OPERAND (t, 0);
7709 : :
7710 : 1183374 : if (TREE_CODE (*sub_p) == COMPOUND_EXPR)
7711 : 202516 : gimplify_compound_expr (sub_p, pre_p, false);
7712 : : else
7713 : 980858 : gimplify_stmt (sub_p, pre_p);
7714 : :
7715 : 1183374 : t = TREE_OPERAND (t, 1);
7716 : : }
7717 : 1183374 : while (TREE_CODE (t) == COMPOUND_EXPR);
7718 : :
7719 : 1096651 : *expr_p = t;
7720 : 1096651 : if (want_value)
7721 : : return GS_OK;
7722 : : else
7723 : : {
7724 : 596711 : gimplify_stmt (expr_p, pre_p);
7725 : 596711 : return GS_ALL_DONE;
7726 : : }
7727 : : }
7728 : :
7729 : : /* Gimplify a SAVE_EXPR node. EXPR_P points to the expression to
7730 : : gimplify. After gimplification, EXPR_P will point to a new temporary
7731 : : that holds the original value of the SAVE_EXPR node.
7732 : :
7733 : : PRE_P points to the list where side effects that must happen before
7734 : : *EXPR_P should be stored. */
7735 : :
7736 : : static enum gimplify_status
7737 : 425817 : gimplify_save_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7738 : : {
7739 : 425817 : enum gimplify_status ret = GS_ALL_DONE;
7740 : 425817 : tree val;
7741 : :
7742 : 425817 : gcc_assert (TREE_CODE (*expr_p) == SAVE_EXPR);
7743 : 425817 : val = TREE_OPERAND (*expr_p, 0);
7744 : :
7745 : 425817 : if (val && TREE_TYPE (val) == error_mark_node)
7746 : : return GS_ERROR;
7747 : :
7748 : : /* If the SAVE_EXPR has not been resolved, then evaluate it once. */
7749 : 425815 : if (!SAVE_EXPR_RESOLVED_P (*expr_p))
7750 : : {
7751 : : /* The operand may be a void-valued expression. It is
7752 : : being executed only for its side-effects. */
7753 : 161706 : if (TREE_TYPE (val) == void_type_node)
7754 : : {
7755 : 0 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
7756 : : is_gimple_stmt, fb_none);
7757 : 0 : val = NULL;
7758 : : }
7759 : : else
7760 : : /* The temporary may not be an SSA name as later abnormal and EH
7761 : : control flow may invalidate use/def domination. When in SSA
7762 : : form then assume there are no such issues and SAVE_EXPRs only
7763 : : appear via GENERIC foldings. */
7764 : 323412 : val = get_initialized_tmp_var (val, pre_p, post_p,
7765 : 323412 : gimple_in_ssa_p (cfun));
7766 : :
7767 : 161706 : TREE_OPERAND (*expr_p, 0) = val;
7768 : 161706 : SAVE_EXPR_RESOLVED_P (*expr_p) = 1;
7769 : : }
7770 : :
7771 : 425815 : *expr_p = val;
7772 : :
7773 : 425815 : return ret;
7774 : : }
7775 : :
7776 : : /* Rewrite the ADDR_EXPR node pointed to by EXPR_P
7777 : :
7778 : : unary_expr
7779 : : : ...
7780 : : | '&' varname
7781 : : ...
7782 : :
7783 : : PRE_P points to the list where side effects that must happen before
7784 : : *EXPR_P should be stored.
7785 : :
7786 : : POST_P points to the list where side effects that must happen after
7787 : : *EXPR_P should be stored. */
7788 : :
7789 : : static enum gimplify_status
7790 : 33478391 : gimplify_addr_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7791 : : {
7792 : 33478391 : tree expr = *expr_p;
7793 : 33478391 : tree op0 = TREE_OPERAND (expr, 0);
7794 : 33478391 : enum gimplify_status ret;
7795 : 33478391 : location_t loc = EXPR_LOCATION (*expr_p);
7796 : :
7797 : 33478391 : switch (TREE_CODE (op0))
7798 : : {
7799 : 97043 : case INDIRECT_REF:
7800 : 97043 : do_indirect_ref:
7801 : : /* Check if we are dealing with an expression of the form '&*ptr'.
7802 : : While the front end folds away '&*ptr' into 'ptr', these
7803 : : expressions may be generated internally by the compiler (e.g.,
7804 : : builtins like __builtin_va_end). */
7805 : : /* Caution: the silent array decomposition semantics we allow for
7806 : : ADDR_EXPR means we can't always discard the pair. */
7807 : : /* Gimplification of the ADDR_EXPR operand may drop
7808 : : cv-qualification conversions, so make sure we add them if
7809 : : needed. */
7810 : 97043 : {
7811 : 97043 : tree op00 = TREE_OPERAND (op0, 0);
7812 : 97043 : tree t_expr = TREE_TYPE (expr);
7813 : 97043 : tree t_op00 = TREE_TYPE (op00);
7814 : :
7815 : 97043 : if (!useless_type_conversion_p (t_expr, t_op00))
7816 : 0 : op00 = fold_convert_loc (loc, TREE_TYPE (expr), op00);
7817 : 97043 : *expr_p = op00;
7818 : 97043 : ret = GS_OK;
7819 : : }
7820 : 97043 : break;
7821 : :
7822 : 0 : case VIEW_CONVERT_EXPR:
7823 : : /* Take the address of our operand and then convert it to the type of
7824 : : this ADDR_EXPR.
7825 : :
7826 : : ??? The interactions of VIEW_CONVERT_EXPR and aliasing is not at
7827 : : all clear. The impact of this transformation is even less clear. */
7828 : :
7829 : : /* If the operand is a useless conversion, look through it. Doing so
7830 : : guarantees that the ADDR_EXPR and its operand will remain of the
7831 : : same type. */
7832 : 0 : if (tree_ssa_useless_type_conversion (TREE_OPERAND (op0, 0)))
7833 : 0 : op0 = TREE_OPERAND (op0, 0);
7834 : :
7835 : 0 : *expr_p = fold_convert_loc (loc, TREE_TYPE (expr),
7836 : : build_fold_addr_expr_loc (loc,
7837 : 0 : TREE_OPERAND (op0, 0)));
7838 : 0 : ret = GS_OK;
7839 : 0 : break;
7840 : :
7841 : 61766 : case MEM_REF:
7842 : 61766 : if (integer_zerop (TREE_OPERAND (op0, 1)))
7843 : 36103 : goto do_indirect_ref;
7844 : :
7845 : : /* fall through */
7846 : :
7847 : 33397513 : default:
7848 : : /* If we see a call to a declared builtin or see its address
7849 : : being taken (we can unify those cases here) then we can mark
7850 : : the builtin for implicit generation by GCC. */
7851 : 33397513 : if (TREE_CODE (op0) == FUNCTION_DECL
7852 : 16528290 : && fndecl_built_in_p (op0, BUILT_IN_NORMAL)
7853 : 37356856 : && builtin_decl_declared_p (DECL_FUNCTION_CODE (op0)))
7854 : 1291293 : set_builtin_decl_implicit_p (DECL_FUNCTION_CODE (op0), true);
7855 : :
7856 : : /* We use fb_either here because the C frontend sometimes takes
7857 : : the address of a call that returns a struct; see
7858 : : gcc.dg/c99-array-lval-1.c. The gimplifier will correctly make
7859 : : the implied temporary explicit. */
7860 : :
7861 : : /* Make the operand addressable. */
7862 : 33397513 : ret = gimplify_expr (&TREE_OPERAND (expr, 0), pre_p, post_p,
7863 : : is_gimple_addressable, fb_either);
7864 : 33397513 : if (ret == GS_ERROR)
7865 : : break;
7866 : :
7867 : : /* Then mark it. Beware that it may not be possible to do so directly
7868 : : if a temporary has been created by the gimplification. */
7869 : 33397511 : prepare_gimple_addressable (&TREE_OPERAND (expr, 0), pre_p);
7870 : :
7871 : 33397511 : op0 = TREE_OPERAND (expr, 0);
7872 : :
7873 : : /* For various reasons, the gimplification of the expression
7874 : : may have made a new INDIRECT_REF. */
7875 : 33397511 : if (INDIRECT_REF_P (op0)
7876 : 33397511 : || (TREE_CODE (op0) == MEM_REF
7877 : 41828 : && integer_zerop (TREE_OPERAND (op0, 1))))
7878 : 16165 : goto do_indirect_ref;
7879 : :
7880 : 33381346 : mark_addressable (TREE_OPERAND (expr, 0));
7881 : :
7882 : : /* The FEs may end up building ADDR_EXPRs early on a decl with
7883 : : an incomplete type. Re-build ADDR_EXPRs in canonical form
7884 : : here. */
7885 : 33381346 : if (!types_compatible_p (TREE_TYPE (op0), TREE_TYPE (TREE_TYPE (expr))))
7886 : 143868 : *expr_p = build_fold_addr_expr (op0);
7887 : :
7888 : : /* Make sure TREE_CONSTANT and TREE_SIDE_EFFECTS are set properly. */
7889 : 33381346 : if (TREE_CODE (*expr_p) == ADDR_EXPR)
7890 : 33381345 : recompute_tree_invariant_for_addr_expr (*expr_p);
7891 : :
7892 : : /* If we re-built the ADDR_EXPR add a conversion to the original type
7893 : : if required. */
7894 : 33381346 : if (!useless_type_conversion_p (TREE_TYPE (expr), TREE_TYPE (*expr_p)))
7895 : 0 : *expr_p = fold_convert (TREE_TYPE (expr), *expr_p);
7896 : :
7897 : : break;
7898 : : }
7899 : :
7900 : 33478391 : return ret;
7901 : : }
7902 : :
7903 : : /* Return the number of times character C occurs in string S. */
7904 : :
7905 : : static int
7906 : 91579 : num_occurrences (int c, const char *s)
7907 : : {
7908 : 91579 : int n = 0;
7909 : 248728 : while (*s)
7910 : 157149 : n += (*s++ == c);
7911 : 91579 : return n;
7912 : : }
7913 : :
7914 : : /* A subroutine of gimplify_asm_expr. Check that all operands have
7915 : : the same number of alternatives. Return -1 if this is violated. Otherwise
7916 : : return the number of alternatives. */
7917 : :
7918 : : static int
7919 : 193050 : num_alternatives (const_tree link)
7920 : : {
7921 : 193050 : if (link == nullptr)
7922 : : return 0;
7923 : :
7924 : 47316 : const char *constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7925 : 47316 : int num = num_occurrences (',', constraint);
7926 : :
7927 : 47316 : if (num + 1 > MAX_RECOG_ALTERNATIVES)
7928 : : return -1;
7929 : :
7930 : 91579 : for (link = TREE_CHAIN (link); link; link = TREE_CHAIN (link))
7931 : : {
7932 : 44263 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
7933 : 88526 : if (num_occurrences (',', constraint) != num)
7934 : : return -1;
7935 : : }
7936 : 47316 : return num + 1;
7937 : : }
7938 : :
7939 : : /* Gimplify the operands of an ASM_EXPR. Input operands should be a gimple
7940 : : value; output operands should be a gimple lvalue. */
7941 : :
7942 : : static enum gimplify_status
7943 : 96525 : gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
7944 : : {
7945 : 96525 : tree expr;
7946 : 96525 : int noutputs;
7947 : 96525 : const char **oconstraints;
7948 : 96525 : int i;
7949 : 96525 : tree link;
7950 : 96525 : const char *constraint;
7951 : 96525 : bool allows_mem, allows_reg, is_inout;
7952 : 96525 : enum gimplify_status ret, tret;
7953 : 96525 : gasm *stmt;
7954 : 96525 : vec<tree, va_gc> *inputs;
7955 : 96525 : vec<tree, va_gc> *outputs;
7956 : 96525 : vec<tree, va_gc> *clobbers;
7957 : 96525 : vec<tree, va_gc> *labels;
7958 : 96525 : tree link_next;
7959 : :
7960 : 96525 : expr = *expr_p;
7961 : 96525 : noutputs = list_length (ASM_OUTPUTS (expr));
7962 : 96525 : oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *));
7963 : :
7964 : 96525 : inputs = NULL;
7965 : 96525 : outputs = NULL;
7966 : 96525 : clobbers = NULL;
7967 : 96525 : labels = NULL;
7968 : :
7969 : 96525 : int num_alternatives_out = num_alternatives (ASM_OUTPUTS (expr));
7970 : 96525 : int num_alternatives_in = num_alternatives (ASM_INPUTS (expr));
7971 : 96525 : if (num_alternatives_out == -1 || num_alternatives_in == -1
7972 : 96525 : || (num_alternatives_out > 0 && num_alternatives_in > 0
7973 : 16626 : && num_alternatives_out != num_alternatives_in))
7974 : : {
7975 : 0 : error ("operand constraints for %<asm%> differ "
7976 : : "in number of alternatives");
7977 : 0 : return GS_ERROR;
7978 : : }
7979 : 96525 : int num_alternatives = MAX (num_alternatives_out, num_alternatives_in);
7980 : :
7981 : 96525 : gimplify_reg_info reg_info (num_alternatives, noutputs);
7982 : :
7983 : 96525 : link_next = NULL_TREE;
7984 : 191012 : for (link = ASM_CLOBBERS (expr); link; link = link_next)
7985 : : {
7986 : : /* The clobber entry could also be an error marker. */
7987 : 94487 : if (TREE_CODE (TREE_VALUE (link)) == STRING_CST)
7988 : : {
7989 : 94464 : const char *regname= TREE_STRING_POINTER (TREE_VALUE (link));
7990 : 94464 : int regno = decode_reg_name (regname);
7991 : 94464 : if (regno >= 0)
7992 : 41248 : reg_info.set_clobbered (regno);
7993 : : }
7994 : 94487 : link_next = TREE_CHAIN (link);
7995 : 94487 : TREE_CHAIN (link) = NULL_TREE;
7996 : 94487 : vec_safe_push (clobbers, link);
7997 : : }
7998 : :
7999 : 96525 : ret = GS_ALL_DONE;
8000 : 96525 : link_next = NULL_TREE;
8001 : 155810 : for (i = 0, link = ASM_OUTPUTS (expr); link; ++i, link = link_next)
8002 : : {
8003 : 59318 : bool ok;
8004 : 59318 : size_t constraint_len;
8005 : :
8006 : 59318 : if (error_operand_p (TREE_VALUE (link)))
8007 : : return GS_ERROR;
8008 : 59297 : link_next = TREE_CHAIN (link);
8009 : :
8010 : 118594 : oconstraints[i]
8011 : 59297 : = constraint
8012 : 59297 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8013 : 59297 : constraint_len = strlen (constraint);
8014 : 59297 : if (constraint_len == 0)
8015 : 0 : continue;
8016 : :
8017 : 59297 : reg_info.operand = TREE_VALUE (link);
8018 : 59297 : ok = parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
8019 : : &allows_reg, &is_inout, ®_info);
8020 : 59297 : if (!ok)
8021 : : {
8022 : 7 : ret = GS_ERROR;
8023 : 7 : is_inout = false;
8024 : : }
8025 : :
8026 : : /* If we can't make copies, we can only accept memory.
8027 : : Similarly for VLAs. */
8028 : 59297 : tree outtype = TREE_TYPE (TREE_VALUE (link));
8029 : 59297 : if (TREE_ADDRESSABLE (outtype)
8030 : 59282 : || !COMPLETE_TYPE_P (outtype)
8031 : 118554 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (outtype)))
8032 : : {
8033 : 276 : if (allows_mem)
8034 : 264 : allows_reg = 0;
8035 : : else
8036 : : {
8037 : 12 : error ("impossible constraint in %<asm%>");
8038 : 12 : error ("non-memory output %d must stay in memory", i);
8039 : 12 : return GS_ERROR;
8040 : : }
8041 : : }
8042 : :
8043 : 59285 : if (!allows_reg && allows_mem)
8044 : 1644 : mark_addressable (TREE_VALUE (link));
8045 : :
8046 : 59285 : tree orig = TREE_VALUE (link);
8047 : 109914 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8048 : : is_inout ? is_gimple_min_lval : is_gimple_lvalue,
8049 : : fb_lvalue | fb_mayfail);
8050 : 59285 : if (tret == GS_ERROR)
8051 : : {
8052 : 0 : if (orig != error_mark_node)
8053 : 0 : error ("invalid lvalue in %<asm%> output %d", i);
8054 : : ret = tret;
8055 : : }
8056 : :
8057 : : /* If the gimplified operand is a register we do not allow memory. */
8058 : 59285 : if (allows_reg
8059 : 57638 : && allows_mem
8060 : 65044 : && (is_gimple_reg (TREE_VALUE (link))
8061 : 267 : || (handled_component_p (TREE_VALUE (link))
8062 : 36 : && is_gimple_reg (TREE_OPERAND (TREE_VALUE (link), 0)))))
8063 : 5493 : allows_mem = 0;
8064 : :
8065 : : /* If the constraint does not allow memory make sure we gimplify
8066 : : it to a register if it is not already but its base is. This
8067 : : happens for complex and vector components. */
8068 : 59285 : if (!allows_mem)
8069 : : {
8070 : 57375 : tree op = TREE_VALUE (link);
8071 : 57375 : if (! is_gimple_val (op)
8072 : 21054 : && is_gimple_reg_type (TREE_TYPE (op))
8073 : 78428 : && is_gimple_reg (get_base_address (op)))
8074 : : {
8075 : 19 : tree tem = create_tmp_reg (TREE_TYPE (op));
8076 : 19 : tree ass;
8077 : 19 : if (is_inout)
8078 : : {
8079 : 7 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem),
8080 : : tem, unshare_expr (op));
8081 : 7 : gimplify_and_add (ass, pre_p);
8082 : : }
8083 : 19 : ass = build2 (MODIFY_EXPR, TREE_TYPE (tem), op, tem);
8084 : 19 : gimplify_and_add (ass, post_p);
8085 : :
8086 : 19 : TREE_VALUE (link) = tem;
8087 : 19 : tret = GS_OK;
8088 : : }
8089 : : }
8090 : :
8091 : 59285 : vec_safe_push (outputs, link);
8092 : 59285 : TREE_CHAIN (link) = NULL_TREE;
8093 : :
8094 : 59285 : if (is_inout)
8095 : : {
8096 : : /* An input/output operand. To give the optimizers more
8097 : : flexibility, split it into separate input and output
8098 : : operands. */
8099 : 8656 : tree input;
8100 : : /* Buffer big enough to format a 32-bit UINT_MAX into. */
8101 : 8656 : char buf[11];
8102 : :
8103 : : /* Turn the in/out constraint into an output constraint. */
8104 : 8656 : char *p = xstrdup (constraint);
8105 : 8656 : p[0] = '=';
8106 : 8656 : TREE_PURPOSE (link) = unshare_expr (TREE_PURPOSE (link));
8107 : 8656 : TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
8108 : :
8109 : : /* And add a matching input constraint. */
8110 : 8656 : if (allows_reg)
8111 : : {
8112 : 8158 : sprintf (buf, "%u", i);
8113 : :
8114 : : /* If there are multiple alternatives in the constraint,
8115 : : handle each of them individually. Those that allow register
8116 : : will be replaced with operand number, the others will stay
8117 : : unchanged. */
8118 : 8158 : if (strchr (p, ',') != NULL)
8119 : : {
8120 : 100 : size_t len = 0, buflen = strlen (buf);
8121 : 100 : char *beg, *end, *str, *dst;
8122 : :
8123 : 100 : for (beg = p + 1;;)
8124 : : {
8125 : 200 : end = strchr (beg, ',');
8126 : 200 : if (end == NULL)
8127 : 100 : end = strchr (beg, '\0');
8128 : 200 : if ((size_t) (end - beg) < buflen)
8129 : 28 : len += buflen + 1;
8130 : : else
8131 : 172 : len += end - beg + 1;
8132 : 200 : if (*end)
8133 : 100 : beg = end + 1;
8134 : : else
8135 : : break;
8136 : : }
8137 : :
8138 : 100 : str = (char *) alloca (len);
8139 : 100 : for (beg = p + 1, dst = str;;)
8140 : : {
8141 : 200 : const char *tem;
8142 : 200 : bool mem_p, reg_p, inout_p;
8143 : :
8144 : 200 : end = strchr (beg, ',');
8145 : 200 : if (end)
8146 : 100 : *end = '\0';
8147 : 200 : beg[-1] = '=';
8148 : 200 : tem = beg - 1;
8149 : 200 : parse_output_constraint (&tem, i, 0, 0, &mem_p, ®_p,
8150 : : &inout_p, nullptr);
8151 : 200 : if (dst != str)
8152 : 100 : *dst++ = ',';
8153 : 200 : if (reg_p)
8154 : : {
8155 : 115 : memcpy (dst, buf, buflen);
8156 : 115 : dst += buflen;
8157 : : }
8158 : : else
8159 : : {
8160 : 85 : if (end)
8161 : 0 : len = end - beg;
8162 : : else
8163 : 85 : len = strlen (beg);
8164 : 85 : memcpy (dst, beg, len);
8165 : 85 : dst += len;
8166 : : }
8167 : 200 : if (end)
8168 : 100 : beg = end + 1;
8169 : : else
8170 : : break;
8171 : 100 : }
8172 : 100 : *dst = '\0';
8173 : 100 : input = build_string (dst - str, str);
8174 : : }
8175 : : else
8176 : 8058 : input = build_string (strlen (buf), buf);
8177 : : }
8178 : : else
8179 : 498 : input = build_string (constraint_len - 1, constraint + 1);
8180 : :
8181 : 8656 : free (p);
8182 : :
8183 : 8656 : input = build_tree_list (build_tree_list (NULL_TREE, input),
8184 : 8656 : unshare_expr (TREE_VALUE (link)));
8185 : 8656 : ASM_INPUTS (expr) = chainon (ASM_INPUTS (expr), input);
8186 : : }
8187 : : }
8188 : :
8189 : : /* After all output operands have been gimplified, verify that each output
8190 : : operand is used at most once in case of hard register constraints. Thus,
8191 : : error out in cases like
8192 : : asm ("" : "={0}" (x), "={1}" (x));
8193 : : or even for
8194 : : asm ("" : "=r" (x), "={1}" (x));
8195 : :
8196 : : FIXME: Ideally we would also error out for cases like
8197 : : int x;
8198 : : asm ("" : "=r" (x), "=r" (x));
8199 : : However, since code like that was previously accepted, erroring out now might
8200 : : break existing code. On the other hand, we already error out for register
8201 : : asm like
8202 : : register int x asm ("0");
8203 : : asm ("" : "=r" (x), "=r" (x));
8204 : : Thus, maybe it wouldn't be too bad to also error out in the former
8205 : : non-register-asm case.
8206 : : */
8207 : 155773 : for (unsigned i = 0; i < vec_safe_length (outputs); ++i)
8208 : : {
8209 : 59283 : tree link = (*outputs)[i];
8210 : 59283 : tree op1 = TREE_VALUE (link);
8211 : 59283 : const char *constraint
8212 : 59283 : = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8213 : 59283 : if (strchr (constraint, '{') != nullptr)
8214 : 226 : for (unsigned j = 0; j < vec_safe_length (outputs); ++j)
8215 : : {
8216 : 137 : if (i == j)
8217 : 90 : continue;
8218 : 47 : tree link2 = (*outputs)[j];
8219 : 47 : tree op2 = TREE_VALUE (link2);
8220 : 47 : if (op1 == op2)
8221 : : {
8222 : 2 : error ("multiple outputs to lvalue %qE", op2);
8223 : 2 : return GS_ERROR;
8224 : : }
8225 : : }
8226 : : }
8227 : :
8228 : 96490 : link_next = NULL_TREE;
8229 : 96490 : int input_num = 0;
8230 : 137349 : for (link = ASM_INPUTS (expr); link; ++input_num, ++i, link = link_next)
8231 : : {
8232 : 40913 : if (error_operand_p (TREE_VALUE (link)))
8233 : : return GS_ERROR;
8234 : 40868 : link_next = TREE_CHAIN (link);
8235 : 40868 : constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
8236 : 40868 : reg_info.operand = TREE_VALUE (link);
8237 : 40868 : bool ok = parse_input_constraint (&constraint, input_num, 0, noutputs, 0,
8238 : : oconstraints, &allows_mem, &allows_reg,
8239 : : ®_info);
8240 : 40868 : if (!ok)
8241 : : {
8242 : 27 : ret = GS_ERROR;
8243 : 27 : is_inout = false;
8244 : : }
8245 : :
8246 : : /* If we can't make copies, we can only accept memory. */
8247 : 40868 : tree intype = TREE_TYPE (TREE_VALUE (link));
8248 : 40868 : if (TREE_ADDRESSABLE (intype)
8249 : 40850 : || !COMPLETE_TYPE_P (intype)
8250 : 81679 : || !tree_fits_poly_uint64_p (TYPE_SIZE_UNIT (intype)))
8251 : : {
8252 : 285 : if (allows_mem)
8253 : 276 : allows_reg = 0;
8254 : : else
8255 : : {
8256 : 9 : error ("impossible constraint in %<asm%>");
8257 : 9 : error ("non-memory input %d must stay in memory", i);
8258 : 9 : return GS_ERROR;
8259 : : }
8260 : : }
8261 : :
8262 : : /* If the operand is a memory input, it should be an lvalue. */
8263 : 40859 : if (!allows_reg && allows_mem)
8264 : : {
8265 : 1986 : tree inputv = TREE_VALUE (link);
8266 : 1986 : STRIP_NOPS (inputv);
8267 : 1986 : if (TREE_CODE (inputv) == PREDECREMENT_EXPR
8268 : : || TREE_CODE (inputv) == PREINCREMENT_EXPR
8269 : : || TREE_CODE (inputv) == POSTDECREMENT_EXPR
8270 : 1986 : || TREE_CODE (inputv) == POSTINCREMENT_EXPR
8271 : 1974 : || TREE_CODE (inputv) == MODIFY_EXPR
8272 : 3958 : || VOID_TYPE_P (TREE_TYPE (inputv)))
8273 : 38 : TREE_VALUE (link) = error_mark_node;
8274 : 1986 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8275 : : is_gimple_lvalue, fb_lvalue | fb_mayfail);
8276 : 1986 : if (tret != GS_ERROR)
8277 : : {
8278 : : /* Unlike output operands, memory inputs are not guaranteed
8279 : : to be lvalues by the FE, and while the expressions are
8280 : : marked addressable there, if it is e.g. a statement
8281 : : expression, temporaries in it might not end up being
8282 : : addressable. They might be already used in the IL and thus
8283 : : it is too late to make them addressable now though. */
8284 : 1940 : tree x = TREE_VALUE (link);
8285 : 2081 : while (handled_component_p (x))
8286 : 141 : x = TREE_OPERAND (x, 0);
8287 : 1940 : if (TREE_CODE (x) == MEM_REF
8288 : 1940 : && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
8289 : 0 : x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
8290 : 1940 : if ((VAR_P (x)
8291 : : || TREE_CODE (x) == PARM_DECL
8292 : : || TREE_CODE (x) == RESULT_DECL)
8293 : 1511 : && !TREE_ADDRESSABLE (x)
8294 : 23 : && is_gimple_reg (x))
8295 : : {
8296 : 17 : warning_at (EXPR_LOC_OR_LOC (TREE_VALUE (link),
8297 : 17 : input_location), 0,
8298 : : "memory input %d is not directly addressable",
8299 : : i);
8300 : 17 : prepare_gimple_addressable (&TREE_VALUE (link), pre_p);
8301 : : }
8302 : : }
8303 : 1986 : mark_addressable (TREE_VALUE (link));
8304 : 1986 : if (tret == GS_ERROR)
8305 : : {
8306 : 46 : if (inputv != error_mark_node)
8307 : 46 : error_at (EXPR_LOC_OR_LOC (TREE_VALUE (link), input_location),
8308 : : "memory input %d is not directly addressable", i);
8309 : : ret = tret;
8310 : : }
8311 : : }
8312 : : else
8313 : : {
8314 : 38873 : tret = gimplify_expr (&TREE_VALUE (link), pre_p, post_p,
8315 : : is_gimple_asm_val, fb_rvalue);
8316 : 38873 : if (tret == GS_ERROR)
8317 : 46 : ret = tret;
8318 : : }
8319 : :
8320 : 40859 : TREE_CHAIN (link) = NULL_TREE;
8321 : 40859 : vec_safe_push (inputs, link);
8322 : : }
8323 : :
8324 : 96436 : link_next = NULL_TREE;
8325 : 97233 : for (link = ASM_LABELS (expr); link; link = link_next)
8326 : : {
8327 : 797 : link_next = TREE_CHAIN (link);
8328 : 797 : TREE_CHAIN (link) = NULL_TREE;
8329 : 797 : vec_safe_push (labels, link);
8330 : : }
8331 : :
8332 : : /* Do not add ASMs with errors to the gimple IL stream. */
8333 : 96436 : if (ret != GS_ERROR)
8334 : : {
8335 : 96360 : stmt = gimple_build_asm_vec (TREE_STRING_POINTER (ASM_STRING (expr)),
8336 : : inputs, outputs, clobbers, labels);
8337 : :
8338 : : /* asm is volatile if it was marked by the user as volatile or
8339 : : there are no outputs or this is an asm goto. */
8340 : 192720 : gimple_asm_set_volatile (stmt,
8341 : 96360 : ASM_VOLATILE_P (expr)
8342 : 7474 : || noutputs == 0
8343 : 103820 : || labels);
8344 : 96360 : gimple_asm_set_basic (stmt, ASM_BASIC_P (expr));
8345 : 96360 : gimple_asm_set_inline (stmt, ASM_INLINE_P (expr));
8346 : :
8347 : 96360 : gimplify_seq_add_stmt (pre_p, stmt);
8348 : : }
8349 : :
8350 : : return ret;
8351 : 96525 : }
8352 : :
8353 : : /* Gimplify a CLEANUP_POINT_EXPR. Currently this works by adding
8354 : : GIMPLE_WITH_CLEANUP_EXPRs to the prequeue as we encounter cleanups while
8355 : : gimplifying the body, and converting them to TRY_FINALLY_EXPRs when we
8356 : : return to this function.
8357 : :
8358 : : FIXME should we complexify the prequeue handling instead? Or use flags
8359 : : for all the cleanups and let the optimizer tighten them up? The current
8360 : : code seems pretty fragile; it will break on a cleanup within any
8361 : : non-conditional nesting. But any such nesting would be broken, anyway;
8362 : : we can't write a TRY_FINALLY_EXPR that starts inside a nesting construct
8363 : : and continues out of it. We can do that at the RTL level, though, so
8364 : : having an optimizer to tighten up try/finally regions would be a Good
8365 : : Thing. */
8366 : :
8367 : : static enum gimplify_status
8368 : 5283883 : gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
8369 : : {
8370 : 5283883 : gimple_stmt_iterator iter;
8371 : 5283883 : gimple_seq body_sequence = NULL;
8372 : :
8373 : 5283883 : tree temp = voidify_wrapper_expr (*expr_p, NULL);
8374 : :
8375 : : /* We only care about the number of conditions between the innermost
8376 : : CLEANUP_POINT_EXPR and the cleanup. So save and reset the count and
8377 : : any cleanups collected outside the CLEANUP_POINT_EXPR. */
8378 : 5283883 : int old_conds = gimplify_ctxp->conditions;
8379 : 5283883 : gimple_seq old_cleanups = gimplify_ctxp->conditional_cleanups;
8380 : 5283883 : bool old_in_cleanup_point_expr = gimplify_ctxp->in_cleanup_point_expr;
8381 : 5283883 : gimplify_ctxp->conditions = 0;
8382 : 5283883 : gimplify_ctxp->conditional_cleanups = NULL;
8383 : 5283883 : gimplify_ctxp->in_cleanup_point_expr = true;
8384 : :
8385 : 5283883 : gimplify_stmt (&TREE_OPERAND (*expr_p, 0), &body_sequence);
8386 : :
8387 : 5283883 : gimplify_ctxp->conditions = old_conds;
8388 : 5283883 : gimplify_ctxp->conditional_cleanups = old_cleanups;
8389 : 5283883 : gimplify_ctxp->in_cleanup_point_expr = old_in_cleanup_point_expr;
8390 : :
8391 : 27573598 : for (iter = gsi_start (body_sequence); !gsi_end_p (iter); )
8392 : : {
8393 : 17044496 : gimple *wce = gsi_stmt (iter);
8394 : :
8395 : 17044496 : if (gimple_code (wce) == GIMPLE_WITH_CLEANUP_EXPR)
8396 : : {
8397 : 612207 : if (gsi_one_before_end_p (iter))
8398 : : {
8399 : : /* Note that gsi_insert_seq_before and gsi_remove do not
8400 : : scan operands, unlike some other sequence mutators. */
8401 : 3236 : if (!gimple_wce_cleanup_eh_only (wce))
8402 : 3236 : gsi_insert_seq_before_without_update (&iter,
8403 : : gimple_wce_cleanup (wce),
8404 : : GSI_SAME_STMT);
8405 : 3236 : gsi_remove (&iter, true);
8406 : 3236 : break;
8407 : : }
8408 : : else
8409 : : {
8410 : 608971 : gtry *gtry;
8411 : 608971 : gimple_seq seq;
8412 : 608971 : enum gimple_try_flags kind;
8413 : :
8414 : 608971 : if (gimple_wce_cleanup_eh_only (wce))
8415 : : kind = GIMPLE_TRY_CATCH;
8416 : : else
8417 : 596032 : kind = GIMPLE_TRY_FINALLY;
8418 : 608971 : seq = gsi_split_seq_after (iter);
8419 : :
8420 : 608971 : gtry = gimple_build_try (seq, gimple_wce_cleanup (wce), kind);
8421 : : /* Do not use gsi_replace here, as it may scan operands.
8422 : : We want to do a simple structural modification only. */
8423 : 608971 : gsi_set_stmt (&iter, gtry);
8424 : 1217942 : iter = gsi_start (gtry->eval);
8425 : : }
8426 : : }
8427 : : else
8428 : 16432289 : gsi_next (&iter);
8429 : : }
8430 : :
8431 : 5283883 : gimplify_seq_add_seq (pre_p, body_sequence);
8432 : 5283883 : if (temp)
8433 : : {
8434 : 345641 : *expr_p = temp;
8435 : 345641 : return GS_OK;
8436 : : }
8437 : : else
8438 : : {
8439 : 4938242 : *expr_p = NULL;
8440 : 4938242 : return GS_ALL_DONE;
8441 : : }
8442 : : }
8443 : :
8444 : : /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
8445 : : is the cleanup action required. EH_ONLY is true if the cleanup should
8446 : : only be executed if an exception is thrown, not on normal exit.
8447 : : If FORCE_UNCOND is true perform the cleanup unconditionally; this is
8448 : : only valid for clobbers. */
8449 : :
8450 : : static void
8451 : 618042 : gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
8452 : : bool force_uncond = false)
8453 : : {
8454 : 618042 : gimple *wce;
8455 : 618042 : gimple_seq cleanup_stmts = NULL;
8456 : :
8457 : : /* Errors can result in improperly nested cleanups. Which results in
8458 : : confusion when trying to resolve the GIMPLE_WITH_CLEANUP_EXPR. */
8459 : 618042 : if (seen_error ())
8460 : 5835 : return;
8461 : :
8462 : 612207 : if (gimple_conditional_context ())
8463 : : {
8464 : : /* If we're in a conditional context, this is more complex. We only
8465 : : want to run the cleanup if we actually ran the initialization that
8466 : : necessitates it, but we want to run it after the end of the
8467 : : conditional context. So we wrap the try/finally around the
8468 : : condition and use a flag to determine whether or not to actually
8469 : : run the destructor. Thus
8470 : :
8471 : : test ? f(A()) : 0
8472 : :
8473 : : becomes (approximately)
8474 : :
8475 : : flag = 0;
8476 : : try {
8477 : : if (test) { A::A(temp); flag = 1; val = f(temp); }
8478 : : else { val = 0; }
8479 : : } finally {
8480 : : if (flag) A::~A(temp);
8481 : : }
8482 : : val
8483 : : */
8484 : 12883 : if (force_uncond)
8485 : : {
8486 : 12010 : gimplify_stmt (&cleanup, &cleanup_stmts);
8487 : 12010 : wce = gimple_build_wce (cleanup_stmts);
8488 : 12010 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8489 : : }
8490 : : else
8491 : : {
8492 : 873 : tree flag = create_tmp_var (boolean_type_node, "cleanup");
8493 : 873 : gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
8494 : 873 : gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
8495 : :
8496 : 873 : cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
8497 : 873 : gimplify_stmt (&cleanup, &cleanup_stmts);
8498 : 873 : wce = gimple_build_wce (cleanup_stmts);
8499 : 873 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8500 : :
8501 : 873 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
8502 : 873 : gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
8503 : 873 : gimplify_seq_add_stmt (pre_p, ftrue);
8504 : :
8505 : : /* Because of this manipulation, and the EH edges that jump
8506 : : threading cannot redirect, the temporary (VAR) will appear
8507 : : to be used uninitialized. Don't warn. */
8508 : 873 : suppress_warning (var, OPT_Wuninitialized);
8509 : : }
8510 : : }
8511 : : else
8512 : : {
8513 : 599324 : gimplify_stmt (&cleanup, &cleanup_stmts);
8514 : 599324 : wce = gimple_build_wce (cleanup_stmts);
8515 : 599324 : gimple_wce_set_cleanup_eh_only (wce, eh_only);
8516 : 599324 : gimplify_seq_add_stmt (pre_p, wce);
8517 : : }
8518 : : }
8519 : :
8520 : : /* Gimplify a TARGET_EXPR which doesn't appear on the rhs of an INIT_EXPR. */
8521 : :
8522 : : static enum gimplify_status
8523 : 813932 : gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
8524 : : {
8525 : 813932 : tree targ = *expr_p;
8526 : 813932 : tree temp = TARGET_EXPR_SLOT (targ);
8527 : 813932 : tree init = TARGET_EXPR_INITIAL (targ);
8528 : 813932 : enum gimplify_status ret;
8529 : :
8530 : 813932 : bool unpoison_empty_seq = false;
8531 : 813932 : gimple_stmt_iterator unpoison_it;
8532 : :
8533 : 813932 : if (init)
8534 : : {
8535 : 777317 : gimple_seq init_pre_p = NULL;
8536 : 777317 : bool is_vla = false;
8537 : :
8538 : : /* TARGET_EXPR temps aren't part of the enclosing block, so add it
8539 : : to the temps list. Handle also variable length TARGET_EXPRs. */
8540 : 777317 : if (!poly_int_tree_p (DECL_SIZE (temp)))
8541 : : {
8542 : 42 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
8543 : 1 : gimplify_type_sizes (TREE_TYPE (temp), &init_pre_p);
8544 : : /* FIXME: this is correct only when the size of the type does
8545 : : not depend on expressions evaluated in init. */
8546 : 42 : gimplify_vla_decl (temp, &init_pre_p);
8547 : 42 : is_vla = true;
8548 : : }
8549 : : else
8550 : : {
8551 : : /* Save location where we need to place unpoisoning. It's possible
8552 : : that a variable will be converted to needs_to_live_in_memory. */
8553 : 777275 : unpoison_it = gsi_last (*pre_p);
8554 : 777275 : unpoison_empty_seq = gsi_end_p (unpoison_it);
8555 : :
8556 : 777275 : gimple_add_tmp_var (temp);
8557 : : }
8558 : :
8559 : 777317 : if (var_needs_auto_init_p (temp) && VOID_TYPE_P (TREE_TYPE (init)))
8560 : : {
8561 : 62907 : gimple_add_init_for_auto_var (temp, flag_auto_var_init, &init_pre_p);
8562 : 62907 : if (flag_auto_var_init == AUTO_INIT_PATTERN
8563 : 0 : && !is_gimple_reg (temp)
8564 : 62907 : && clear_padding_type_may_have_padding_p (TREE_TYPE (temp)))
8565 : 0 : gimple_add_padding_init_for_auto_var (temp, is_vla, &init_pre_p);
8566 : : }
8567 : :
8568 : : /* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
8569 : : expression is supposed to initialize the slot. */
8570 : 777317 : if (VOID_TYPE_P (TREE_TYPE (init)))
8571 : 334016 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8572 : : fb_none);
8573 : : else
8574 : : {
8575 : 443301 : tree init_expr = build2 (INIT_EXPR, void_type_node, temp, init);
8576 : 443301 : init = init_expr;
8577 : 443301 : ret = gimplify_expr (&init, &init_pre_p, post_p, is_gimple_stmt,
8578 : : fb_none);
8579 : 443301 : init = NULL;
8580 : 443301 : ggc_free (init_expr);
8581 : : }
8582 : 777317 : if (ret == GS_ERROR)
8583 : : {
8584 : : /* PR c++/28266 Make sure this is expanded only once. */
8585 : 15 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8586 : 15 : return GS_ERROR;
8587 : : }
8588 : :
8589 : 777302 : if (init)
8590 : 0 : gimplify_and_add (init, &init_pre_p);
8591 : :
8592 : : /* Add a clobber for the temporary going out of scope, like
8593 : : gimplify_bind_expr. But only if we did not promote the
8594 : : temporary to static storage. */
8595 : 777302 : if (gimplify_ctxp->in_cleanup_point_expr
8596 : 628843 : && !TREE_STATIC (temp)
8597 : 1404637 : && needs_to_live_in_memory (temp))
8598 : : {
8599 : 476276 : if (flag_stack_reuse == SR_ALL)
8600 : : {
8601 : 475840 : tree clobber = build_clobber (TREE_TYPE (temp),
8602 : : CLOBBER_STORAGE_END);
8603 : 475840 : clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
8604 : 475840 : gimple_push_cleanup (temp, clobber, false, pre_p, true);
8605 : : }
8606 : 476276 : if (asan_poisoned_variables
8607 : 436 : && DECL_ALIGN (temp) <= MAX_SUPPORTED_STACK_ALIGNMENT
8608 : 436 : && !TREE_STATIC (temp)
8609 : 436 : && dbg_cnt (asan_use_after_scope)
8610 : 476712 : && !gimplify_omp_ctxp)
8611 : : {
8612 : 428 : tree asan_cleanup = build_asan_poison_call_expr (temp);
8613 : 428 : if (asan_cleanup)
8614 : : {
8615 : 428 : if (unpoison_empty_seq)
8616 : 216 : unpoison_it = gsi_start (*pre_p);
8617 : :
8618 : 428 : asan_poison_variable (temp, false, &unpoison_it,
8619 : : unpoison_empty_seq);
8620 : 428 : gimple_push_cleanup (temp, asan_cleanup, false, pre_p);
8621 : : }
8622 : : }
8623 : : }
8624 : :
8625 : 777302 : gimple_seq_add_seq (pre_p, init_pre_p);
8626 : :
8627 : : /* If needed, push the cleanup for the temp. */
8628 : 777302 : if (TARGET_EXPR_CLEANUP (targ))
8629 : 141774 : gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
8630 : 141774 : CLEANUP_EH_ONLY (targ), pre_p);
8631 : :
8632 : : /* Only expand this once. */
8633 : 777302 : TREE_OPERAND (targ, 3) = init;
8634 : 777302 : TARGET_EXPR_INITIAL (targ) = NULL_TREE;
8635 : : }
8636 : : else
8637 : : /* We should have expanded this before. */
8638 : 36615 : gcc_assert (DECL_SEEN_IN_BIND_EXPR_P (temp));
8639 : :
8640 : 813917 : *expr_p = temp;
8641 : 813917 : return GS_OK;
8642 : : }
8643 : :
8644 : : /* Gimplification of expression trees. */
8645 : :
8646 : : /* Gimplify an expression which appears at statement context. The
8647 : : corresponding GIMPLE statements are added to *SEQ_P. If *SEQ_P is
8648 : : NULL, a new sequence is allocated.
8649 : :
8650 : : Return true if we actually added a statement to the queue. */
8651 : :
8652 : : bool
8653 : 102220885 : gimplify_stmt (tree *stmt_p, gimple_seq *seq_p)
8654 : : {
8655 : 102220885 : gimple_seq_node last;
8656 : :
8657 : 102220885 : last = gimple_seq_last (*seq_p);
8658 : 102220885 : gimplify_expr (stmt_p, seq_p, NULL, is_gimple_stmt, fb_none);
8659 : 102220885 : return last != gimple_seq_last (*seq_p);
8660 : : }
8661 : :
8662 : : /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
8663 : : to CTX. If entries already exist, force them to be some flavor of private.
8664 : : If there is no enclosing parallel, do nothing. */
8665 : :
8666 : : void
8667 : 123684 : omp_firstprivatize_variable (struct gimplify_omp_ctx *ctx, tree decl)
8668 : : {
8669 : 123684 : splay_tree_node n;
8670 : :
8671 : 123684 : if (decl == NULL || !DECL_P (decl) || ctx->region_type == ORT_NONE)
8672 : : return;
8673 : :
8674 : 36579 : do
8675 : : {
8676 : 36579 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8677 : 36579 : if (n != NULL)
8678 : : {
8679 : 4289 : if (n->value & GOVD_SHARED)
8680 : 183 : n->value = GOVD_FIRSTPRIVATE | (n->value & GOVD_SEEN);
8681 : 4106 : else if (n->value & GOVD_MAP)
8682 : 55 : n->value |= GOVD_MAP_TO_ONLY;
8683 : : else
8684 : : return;
8685 : : }
8686 : 32290 : else if ((ctx->region_type & ORT_TARGET) != 0)
8687 : : {
8688 : 6795 : if (ctx->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
8689 : 4040 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8690 : : else
8691 : 2755 : omp_add_variable (ctx, decl, GOVD_MAP | GOVD_MAP_TO_ONLY);
8692 : : }
8693 : 25495 : else if (ctx->region_type != ORT_WORKSHARE
8694 : : && ctx->region_type != ORT_TASKGROUP
8695 : 23666 : && ctx->region_type != ORT_SIMD
8696 : 23042 : && ctx->region_type != ORT_ACC
8697 : 22932 : && !(ctx->region_type & ORT_TARGET_DATA))
8698 : 14351 : omp_add_variable (ctx, decl, GOVD_FIRSTPRIVATE);
8699 : :
8700 : 32528 : ctx = ctx->outer_context;
8701 : : }
8702 : 32528 : while (ctx);
8703 : : }
8704 : :
8705 : : /* Similarly for each of the type sizes of TYPE. */
8706 : :
8707 : : static void
8708 : 40504 : omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
8709 : : {
8710 : 40504 : if (type == NULL || type == error_mark_node)
8711 : : return;
8712 : 40500 : type = TYPE_MAIN_VARIANT (type);
8713 : :
8714 : 40500 : if (ctx->privatized_types->add (type))
8715 : : return;
8716 : :
8717 : 30745 : switch (TREE_CODE (type))
8718 : : {
8719 : 13003 : case INTEGER_TYPE:
8720 : 13003 : case ENUMERAL_TYPE:
8721 : 13003 : case BOOLEAN_TYPE:
8722 : 13003 : case REAL_TYPE:
8723 : 13003 : case FIXED_POINT_TYPE:
8724 : 13003 : omp_firstprivatize_variable (ctx, TYPE_MIN_VALUE (type));
8725 : 13003 : omp_firstprivatize_variable (ctx, TYPE_MAX_VALUE (type));
8726 : 13003 : break;
8727 : :
8728 : 5362 : case ARRAY_TYPE:
8729 : 5362 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8730 : 5362 : omp_firstprivatize_type_sizes (ctx, TYPE_DOMAIN (type));
8731 : 5362 : break;
8732 : :
8733 : 2507 : case RECORD_TYPE:
8734 : 2507 : case UNION_TYPE:
8735 : 2507 : case QUAL_UNION_TYPE:
8736 : 2507 : {
8737 : 2507 : tree field;
8738 : 26710 : for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
8739 : 24203 : if (TREE_CODE (field) == FIELD_DECL)
8740 : : {
8741 : 9004 : omp_firstprivatize_variable (ctx, DECL_FIELD_OFFSET (field));
8742 : 9004 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (field));
8743 : : }
8744 : : }
8745 : : break;
8746 : :
8747 : 9225 : case POINTER_TYPE:
8748 : 9225 : case REFERENCE_TYPE:
8749 : 9225 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (type));
8750 : 9225 : break;
8751 : :
8752 : : default:
8753 : : break;
8754 : : }
8755 : :
8756 : 30745 : omp_firstprivatize_variable (ctx, TYPE_SIZE (type));
8757 : 30745 : omp_firstprivatize_variable (ctx, TYPE_SIZE_UNIT (type));
8758 : 30745 : lang_hooks.types.omp_firstprivatize_type_sizes (ctx, type);
8759 : : }
8760 : :
8761 : : /* Add an entry for DECL in the OMP context CTX with FLAGS. */
8762 : :
8763 : : static void
8764 : 701811 : omp_add_variable (struct gimplify_omp_ctx *ctx, tree decl, unsigned int flags)
8765 : : {
8766 : 701811 : splay_tree_node n;
8767 : 701811 : unsigned int nflags;
8768 : 701811 : tree t;
8769 : :
8770 : 701811 : if (error_operand_p (decl) || ctx->region_type == ORT_NONE)
8771 : : return;
8772 : :
8773 : : /* Never elide decls whose type has TREE_ADDRESSABLE set. This means
8774 : : there are constructors involved somewhere. Exception is a shared clause,
8775 : : there is nothing privatized in that case. */
8776 : 701666 : if ((flags & GOVD_SHARED) == 0
8777 : 701666 : && (TREE_ADDRESSABLE (TREE_TYPE (decl))
8778 : 641475 : || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
8779 : 7668 : flags |= GOVD_SEEN;
8780 : :
8781 : 701666 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8782 : 701666 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
8783 : : {
8784 : : /* We shouldn't be re-adding the decl with the same data
8785 : : sharing class. */
8786 : 824 : gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
8787 : 824 : nflags = n->value | flags;
8788 : : /* The only combination of data sharing classes we should see is
8789 : : FIRSTPRIVATE and LASTPRIVATE. However, OpenACC permits
8790 : : reduction variables to be used in data sharing clauses. */
8791 : 824 : gcc_assert ((ctx->region_type & ORT_ACC) != 0
8792 : : || ((nflags & GOVD_DATA_SHARE_CLASS)
8793 : : == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE))
8794 : : || (flags & GOVD_DATA_SHARE_CLASS) == 0);
8795 : 824 : n->value = nflags;
8796 : 824 : return;
8797 : : }
8798 : :
8799 : : /* When adding a variable-sized variable, we have to handle all sorts
8800 : : of additional bits of data: the pointer replacement variable, and
8801 : : the parameters of the type. */
8802 : 700842 : if (DECL_SIZE (decl) && !poly_int_tree_p (DECL_SIZE (decl)))
8803 : : {
8804 : : /* Add the pointer replacement variable as PRIVATE if the variable
8805 : : replacement is private, else FIRSTPRIVATE since we'll need the
8806 : : address of the original variable either for SHARED, or for the
8807 : : copy into or out of the context. */
8808 : 1312 : if (!(flags & GOVD_LOCAL) && ctx->region_type != ORT_TASKGROUP)
8809 : : {
8810 : 1222 : if (flags & GOVD_MAP)
8811 : : nflags = GOVD_MAP | GOVD_MAP_TO_ONLY | GOVD_EXPLICIT;
8812 : 515 : else if (flags & GOVD_PRIVATE)
8813 : : nflags = GOVD_PRIVATE;
8814 : 431 : else if (((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
8815 : 48 : && (flags & GOVD_FIRSTPRIVATE))
8816 : 423 : || (ctx->region_type == ORT_TARGET_DATA
8817 : 6 : && (flags & GOVD_DATA_SHARE_CLASS) == 0))
8818 : : nflags = GOVD_PRIVATE | GOVD_EXPLICIT;
8819 : : else
8820 : 1222 : nflags = GOVD_FIRSTPRIVATE;
8821 : 1222 : nflags |= flags & GOVD_SEEN;
8822 : 1222 : t = DECL_VALUE_EXPR (decl);
8823 : 1222 : gcc_assert (INDIRECT_REF_P (t));
8824 : 1222 : t = TREE_OPERAND (t, 0);
8825 : 1222 : gcc_assert (DECL_P (t));
8826 : 1222 : omp_add_variable (ctx, t, nflags);
8827 : : }
8828 : :
8829 : : /* Add all of the variable and type parameters (which should have
8830 : : been gimplified to a formal temporary) as FIRSTPRIVATE. */
8831 : 1312 : omp_firstprivatize_variable (ctx, DECL_SIZE_UNIT (decl));
8832 : 1312 : omp_firstprivatize_variable (ctx, DECL_SIZE (decl));
8833 : 1312 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8834 : :
8835 : : /* The variable-sized variable itself is never SHARED, only some form
8836 : : of PRIVATE. The sharing would take place via the pointer variable
8837 : : which we remapped above. */
8838 : 1312 : if (flags & GOVD_SHARED)
8839 : 276 : flags = GOVD_SHARED | GOVD_DEBUG_PRIVATE
8840 : 276 : | (flags & (GOVD_SEEN | GOVD_EXPLICIT));
8841 : :
8842 : : /* We're going to make use of the TYPE_SIZE_UNIT at least in the
8843 : : alloca statement we generate for the variable, so make sure it
8844 : : is available. This isn't automatically needed for the SHARED
8845 : : case, since we won't be allocating local storage then.
8846 : : For local variables TYPE_SIZE_UNIT might not be gimplified yet,
8847 : : in this case omp_notice_variable will be called later
8848 : : on when it is gimplified. */
8849 : 1036 : else if (! (flags & (GOVD_LOCAL | GOVD_MAP))
8850 : 1036 : && DECL_P (TYPE_SIZE_UNIT (TREE_TYPE (decl))))
8851 : 267 : omp_notice_variable (ctx, TYPE_SIZE_UNIT (TREE_TYPE (decl)), true);
8852 : : }
8853 : 699530 : else if ((flags & (GOVD_MAP | GOVD_LOCAL)) == 0
8854 : 699530 : && omp_privatize_by_reference (decl))
8855 : : {
8856 : 10239 : omp_firstprivatize_type_sizes (ctx, TREE_TYPE (decl));
8857 : :
8858 : : /* Similar to the direct variable sized case above, we'll need the
8859 : : size of references being privatized. */
8860 : 10239 : if ((flags & GOVD_SHARED) == 0)
8861 : : {
8862 : 6437 : t = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl)));
8863 : 6437 : if (t && DECL_P (t))
8864 : 1337 : omp_notice_variable (ctx, t, true);
8865 : : }
8866 : : }
8867 : :
8868 : 700842 : if (n != NULL)
8869 : 1809 : n->value |= flags;
8870 : : else
8871 : 699033 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, flags);
8872 : :
8873 : : /* For reductions clauses in OpenACC loop directives, by default create a
8874 : : copy clause on the enclosing parallel construct for carrying back the
8875 : : results. */
8876 : 700842 : if (ctx->region_type == ORT_ACC && (flags & GOVD_REDUCTION))
8877 : : {
8878 : 4716 : struct gimplify_omp_ctx *outer_ctx = ctx->outer_context;
8879 : 6454 : while (outer_ctx)
8880 : : {
8881 : 5788 : n = splay_tree_lookup (outer_ctx->variables, (splay_tree_key)decl);
8882 : 5788 : if (n != NULL)
8883 : : {
8884 : : /* Ignore local variables and explicitly declared clauses. */
8885 : 3990 : if (n->value & (GOVD_LOCAL | GOVD_EXPLICIT))
8886 : : break;
8887 : 443 : else if (outer_ctx->region_type == ORT_ACC_KERNELS)
8888 : : {
8889 : : /* According to the OpenACC spec, such a reduction variable
8890 : : should already have a copy map on a kernels construct,
8891 : : verify that here. */
8892 : 143 : gcc_assert (!(n->value & GOVD_FIRSTPRIVATE)
8893 : : && (n->value & GOVD_MAP));
8894 : : }
8895 : 300 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8896 : : {
8897 : : /* Remove firstprivate and make it a copy map. */
8898 : 150 : n->value &= ~GOVD_FIRSTPRIVATE;
8899 : 150 : n->value |= GOVD_MAP;
8900 : : }
8901 : : }
8902 : 1798 : else if (outer_ctx->region_type == ORT_ACC_PARALLEL)
8903 : : {
8904 : 503 : splay_tree_insert (outer_ctx->variables, (splay_tree_key)decl,
8905 : : GOVD_MAP | GOVD_SEEN);
8906 : 503 : break;
8907 : : }
8908 : 1738 : outer_ctx = outer_ctx->outer_context;
8909 : : }
8910 : : }
8911 : : }
8912 : :
8913 : : /* Notice a threadprivate variable DECL used in OMP context CTX.
8914 : : This just prints out diagnostics about threadprivate variable uses
8915 : : in untied tasks. If DECL2 is non-NULL, prevent this warning
8916 : : on that variable. */
8917 : :
8918 : : static bool
8919 : 14183 : omp_notice_threadprivate_variable (struct gimplify_omp_ctx *ctx, tree decl,
8920 : : tree decl2)
8921 : : {
8922 : 14183 : splay_tree_node n;
8923 : 14183 : struct gimplify_omp_ctx *octx;
8924 : :
8925 : 28798 : for (octx = ctx; octx; octx = octx->outer_context)
8926 : 14615 : if ((octx->region_type & ORT_TARGET) != 0
8927 : 14615 : || octx->order_concurrent)
8928 : : {
8929 : 112 : n = splay_tree_lookup (octx->variables, (splay_tree_key)decl);
8930 : 112 : if (n == NULL)
8931 : : {
8932 : 20 : if (octx->order_concurrent)
8933 : : {
8934 : 20 : error ("threadprivate variable %qE used in a region with"
8935 : 20 : " %<order(concurrent)%> clause", DECL_NAME (decl));
8936 : 20 : inform (octx->location, "enclosing region");
8937 : : }
8938 : : else
8939 : : {
8940 : 0 : error ("threadprivate variable %qE used in target region",
8941 : 0 : DECL_NAME (decl));
8942 : 0 : inform (octx->location, "enclosing target region");
8943 : : }
8944 : 20 : splay_tree_insert (octx->variables, (splay_tree_key)decl, 0);
8945 : : }
8946 : 112 : if (decl2)
8947 : 0 : splay_tree_insert (octx->variables, (splay_tree_key)decl2, 0);
8948 : : }
8949 : :
8950 : 14183 : if (ctx->region_type != ORT_UNTIED_TASK)
8951 : : return false;
8952 : 37 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
8953 : 37 : if (n == NULL)
8954 : : {
8955 : 6 : error ("threadprivate variable %qE used in untied task",
8956 : 6 : DECL_NAME (decl));
8957 : 6 : inform (ctx->location, "enclosing task");
8958 : 6 : splay_tree_insert (ctx->variables, (splay_tree_key)decl, 0);
8959 : : }
8960 : 37 : if (decl2)
8961 : 4 : splay_tree_insert (ctx->variables, (splay_tree_key)decl2, 0);
8962 : : return false;
8963 : : }
8964 : :
8965 : : /* Return true if global var DECL is device resident. */
8966 : :
8967 : : static bool
8968 : 641 : device_resident_p (tree decl)
8969 : : {
8970 : 641 : tree attr = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (decl));
8971 : :
8972 : 641 : if (!attr)
8973 : : return false;
8974 : :
8975 : 0 : for (tree t = TREE_VALUE (attr); t; t = TREE_PURPOSE (t))
8976 : : {
8977 : 0 : tree c = TREE_VALUE (t);
8978 : 0 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DEVICE_RESIDENT)
8979 : : return true;
8980 : : }
8981 : :
8982 : : return false;
8983 : : }
8984 : :
8985 : : /* Return true if DECL has an ACC DECLARE attribute. */
8986 : :
8987 : : static bool
8988 : 9097 : is_oacc_declared (tree decl)
8989 : : {
8990 : 9097 : tree t = TREE_CODE (decl) == MEM_REF ? TREE_OPERAND (decl, 0) : decl;
8991 : 9097 : tree declared = lookup_attribute ("oacc declare target", DECL_ATTRIBUTES (t));
8992 : 9097 : return declared != NULL_TREE;
8993 : : }
8994 : :
8995 : : /* Determine outer default flags for DECL mentioned in an OMP region
8996 : : but not declared in an enclosing clause.
8997 : :
8998 : : ??? Some compiler-generated variables (like SAVE_EXPRs) could be
8999 : : remapped firstprivate instead of shared. To some extent this is
9000 : : addressed in omp_firstprivatize_type_sizes, but not
9001 : : effectively. */
9002 : :
9003 : : static unsigned
9004 : 47833 : omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
9005 : : bool in_code, unsigned flags)
9006 : : {
9007 : 47833 : enum omp_clause_default_kind default_kind = ctx->default_kind;
9008 : 47833 : enum omp_clause_default_kind kind;
9009 : :
9010 : 47833 : kind = lang_hooks.decls.omp_predetermined_sharing (decl);
9011 : 47833 : if (ctx->region_type & ORT_TASK)
9012 : : {
9013 : 3961 : tree detach_clause = omp_find_clause (ctx->clauses, OMP_CLAUSE_DETACH);
9014 : :
9015 : : /* The event-handle specified by a detach clause should always be firstprivate,
9016 : : regardless of the current default. */
9017 : 4173 : if (detach_clause && OMP_CLAUSE_DECL (detach_clause) == decl)
9018 : : kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
9019 : : }
9020 : 47833 : if (kind != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
9021 : : default_kind = kind;
9022 : 45021 : else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
9023 : : default_kind = OMP_CLAUSE_DEFAULT_SHARED;
9024 : : /* For C/C++ default({,first}private), variables with static storage duration
9025 : : declared in a namespace or global scope and referenced in construct
9026 : : must be explicitly specified, i.e. acts as default(none). */
9027 : 45020 : else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
9028 : 45020 : || default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
9029 : 360 : && VAR_P (decl)
9030 : 321 : && is_global_var (decl)
9031 : 184 : && (DECL_FILE_SCOPE_P (decl)
9032 : 104 : || (DECL_CONTEXT (decl)
9033 : 104 : && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
9034 : 45148 : && !lang_GNU_Fortran ())
9035 : : default_kind = OMP_CLAUSE_DEFAULT_NONE;
9036 : :
9037 : 47704 : switch (default_kind)
9038 : : {
9039 : 267 : case OMP_CLAUSE_DEFAULT_NONE:
9040 : 267 : {
9041 : 267 : const char *rtype;
9042 : :
9043 : 267 : if (ctx->region_type & ORT_PARALLEL)
9044 : : rtype = "parallel";
9045 : 108 : else if ((ctx->region_type & ORT_TASKLOOP) == ORT_TASKLOOP)
9046 : : rtype = "taskloop";
9047 : 72 : else if (ctx->region_type & ORT_TASK)
9048 : : rtype = "task";
9049 : 36 : else if (ctx->region_type & ORT_TEAMS)
9050 : : rtype = "teams";
9051 : : else
9052 : 0 : gcc_unreachable ();
9053 : :
9054 : 267 : error ("%qE not specified in enclosing %qs",
9055 : 267 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)), rtype);
9056 : 267 : inform (ctx->location, "enclosing %qs", rtype);
9057 : : }
9058 : : /* FALLTHRU */
9059 : 44214 : case OMP_CLAUSE_DEFAULT_SHARED:
9060 : 44214 : flags |= GOVD_SHARED;
9061 : 44214 : break;
9062 : 155 : case OMP_CLAUSE_DEFAULT_PRIVATE:
9063 : 155 : flags |= GOVD_PRIVATE;
9064 : 155 : break;
9065 : 269 : case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
9066 : 269 : flags |= GOVD_FIRSTPRIVATE;
9067 : 269 : break;
9068 : 3195 : case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
9069 : : /* decl will be either GOVD_FIRSTPRIVATE or GOVD_SHARED. */
9070 : 3195 : gcc_assert ((ctx->region_type & ORT_TASK) != 0);
9071 : 3195 : if (struct gimplify_omp_ctx *octx = ctx->outer_context)
9072 : : {
9073 : 2158 : omp_notice_variable (octx, decl, in_code);
9074 : 2986 : for (; octx; octx = octx->outer_context)
9075 : : {
9076 : 2930 : splay_tree_node n2;
9077 : :
9078 : 2930 : n2 = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
9079 : 2930 : if ((octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)) != 0
9080 : 5 : && (n2 == NULL || (n2->value & GOVD_DATA_SHARE_CLASS) == 0))
9081 : 5 : continue;
9082 : 2925 : if (n2 && (n2->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED)
9083 : : {
9084 : 896 : flags |= GOVD_FIRSTPRIVATE;
9085 : 896 : goto found_outer;
9086 : : }
9087 : 2029 : if ((octx->region_type & (ORT_PARALLEL | ORT_TEAMS)) != 0)
9088 : : {
9089 : 1206 : flags |= GOVD_SHARED;
9090 : 1206 : goto found_outer;
9091 : : }
9092 : : }
9093 : : }
9094 : :
9095 : 1093 : if (TREE_CODE (decl) == PARM_DECL
9096 : 1093 : || (!is_global_var (decl)
9097 : 291 : && DECL_CONTEXT (decl) == current_function_decl))
9098 : 716 : flags |= GOVD_FIRSTPRIVATE;
9099 : : else
9100 : 377 : flags |= GOVD_SHARED;
9101 : 47833 : found_outer:
9102 : : break;
9103 : :
9104 : 0 : default:
9105 : 0 : gcc_unreachable ();
9106 : : }
9107 : :
9108 : 47833 : return flags;
9109 : : }
9110 : :
9111 : : /* Return string name for types of OpenACC constructs from ORT_* values. */
9112 : :
9113 : : static const char *
9114 : 570 : oacc_region_type_name (enum omp_region_type region_type)
9115 : : {
9116 : 570 : switch (region_type)
9117 : : {
9118 : : case ORT_ACC_DATA:
9119 : : return "data";
9120 : 140 : case ORT_ACC_PARALLEL:
9121 : 140 : return "parallel";
9122 : 140 : case ORT_ACC_KERNELS:
9123 : 140 : return "kernels";
9124 : 140 : case ORT_ACC_SERIAL:
9125 : 140 : return "serial";
9126 : 0 : default:
9127 : 0 : gcc_unreachable ();
9128 : : }
9129 : : }
9130 : :
9131 : : /* Determine outer default flags for DECL mentioned in an OACC region
9132 : : but not declared in an enclosing clause. */
9133 : :
9134 : : static unsigned
9135 : 8835 : oacc_default_clause (struct gimplify_omp_ctx *ctx, tree decl, unsigned flags)
9136 : : {
9137 : 8835 : struct gimplify_omp_ctx *ctx_default = ctx;
9138 : : /* If no 'default' clause appears on this compute construct... */
9139 : 8835 : if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED)
9140 : : {
9141 : : /* ..., see if one appears on a lexically containing 'data'
9142 : : construct. */
9143 : 9614 : while ((ctx_default = ctx_default->outer_context))
9144 : : {
9145 : 1534 : if (ctx_default->region_type == ORT_ACC_DATA
9146 : 1534 : && ctx_default->default_kind != OMP_CLAUSE_DEFAULT_SHARED)
9147 : : break;
9148 : : }
9149 : : /* If not, reset. */
9150 : 8256 : if (!ctx_default)
9151 : 8659 : ctx_default = ctx;
9152 : : }
9153 : :
9154 : 8835 : bool on_device = false;
9155 : 8835 : bool is_private = false;
9156 : 8835 : bool declared = is_oacc_declared (decl);
9157 : 8835 : tree type = TREE_TYPE (decl);
9158 : :
9159 : 8835 : if (omp_privatize_by_reference (decl))
9160 : 338 : type = TREE_TYPE (type);
9161 : :
9162 : : /* For Fortran COMMON blocks, only used variables in those blocks are
9163 : : transfered and remapped. The block itself will have a private clause to
9164 : : avoid transfering the data twice.
9165 : : The hook evaluates to false by default. For a variable in Fortran's COMMON
9166 : : or EQUIVALENCE block, returns 'true' (as we have shared=false) - as only
9167 : : the variables in such a COMMON/EQUIVALENCE block shall be privatized not
9168 : : the whole block. For C++ and Fortran, it can also be true under certain
9169 : : other conditions, if DECL_HAS_VALUE_EXPR. */
9170 : 8835 : if (RECORD_OR_UNION_TYPE_P (type))
9171 : 982 : is_private = lang_hooks.decls.omp_disregard_value_expr (decl, false);
9172 : :
9173 : 8835 : if ((ctx->region_type & (ORT_ACC_PARALLEL | ORT_ACC_KERNELS)) != 0
9174 : 8835 : && is_global_var (decl)
9175 : 641 : && device_resident_p (decl)
9176 : 8835 : && !is_private)
9177 : : {
9178 : 0 : on_device = true;
9179 : 0 : flags |= GOVD_MAP_TO_ONLY;
9180 : : }
9181 : :
9182 : 8835 : switch (ctx->region_type)
9183 : : {
9184 : 1456 : case ORT_ACC_KERNELS:
9185 : 1456 : if (is_private)
9186 : 0 : flags |= GOVD_FIRSTPRIVATE;
9187 : 1456 : else if (AGGREGATE_TYPE_P (type))
9188 : : {
9189 : : /* Aggregates default to 'present_or_copy', or 'present'. */
9190 : 414 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9191 : 396 : flags |= GOVD_MAP;
9192 : : else
9193 : 18 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9194 : : }
9195 : : else
9196 : : /* Scalars default to 'copy'. */
9197 : 1042 : flags |= GOVD_MAP | GOVD_MAP_FORCE;
9198 : :
9199 : : break;
9200 : :
9201 : 7379 : case ORT_ACC_PARALLEL:
9202 : 7379 : case ORT_ACC_SERIAL:
9203 : 7379 : if (is_private)
9204 : 0 : flags |= GOVD_FIRSTPRIVATE;
9205 : 7379 : else if (on_device || declared)
9206 : 17 : flags |= GOVD_MAP;
9207 : 7362 : else if (AGGREGATE_TYPE_P (type))
9208 : : {
9209 : : /* Aggregates default to 'present_or_copy', or 'present'. */
9210 : 3697 : if (ctx_default->default_kind != OMP_CLAUSE_DEFAULT_PRESENT)
9211 : 3431 : flags |= GOVD_MAP;
9212 : : else
9213 : 266 : flags |= GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
9214 : : }
9215 : : else
9216 : : /* Scalars default to 'firstprivate'. */
9217 : 3665 : flags |= GOVD_FIRSTPRIVATE;
9218 : :
9219 : : break;
9220 : :
9221 : 0 : default:
9222 : 0 : gcc_unreachable ();
9223 : : }
9224 : :
9225 : 8835 : if (DECL_ARTIFICIAL (decl))
9226 : : ; /* We can get compiler-generated decls, and should not complain
9227 : : about them. */
9228 : 8527 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_NONE)
9229 : : {
9230 : 420 : error ("%qE not specified in enclosing OpenACC %qs construct",
9231 : 210 : DECL_NAME (lang_hooks.decls.omp_report_decl (decl)),
9232 : : oacc_region_type_name (ctx->region_type));
9233 : 210 : if (ctx_default != ctx)
9234 : 150 : inform (ctx->location, "enclosing OpenACC %qs construct and",
9235 : : oacc_region_type_name (ctx->region_type));
9236 : 210 : inform (ctx_default->location,
9237 : : "enclosing OpenACC %qs construct with %qs clause",
9238 : : oacc_region_type_name (ctx_default->region_type),
9239 : : "default(none)");
9240 : : }
9241 : 8317 : else if (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_PRESENT)
9242 : : ; /* Handled above. */
9243 : : else
9244 : 7784 : gcc_checking_assert (ctx_default->default_kind == OMP_CLAUSE_DEFAULT_SHARED);
9245 : :
9246 : 8835 : return flags;
9247 : : }
9248 : :
9249 : : /* Record the fact that DECL was used within the OMP context CTX.
9250 : : IN_CODE is true when real code uses DECL, and false when we should
9251 : : merely emit default(none) errors. Return true if DECL is going to
9252 : : be remapped and thus DECL shouldn't be gimplified into its
9253 : : DECL_VALUE_EXPR (if any). */
9254 : :
9255 : : static bool
9256 : 3828026 : omp_notice_variable (struct gimplify_omp_ctx *ctx, tree decl, bool in_code)
9257 : : {
9258 : 3828026 : splay_tree_node n;
9259 : 3828026 : unsigned flags = in_code ? GOVD_SEEN : 0;
9260 : 3828026 : bool ret = false, shared;
9261 : :
9262 : 3828026 : if (error_operand_p (decl))
9263 : : return false;
9264 : :
9265 : 3828026 : if (DECL_ARTIFICIAL (decl))
9266 : : {
9267 : 2190618 : tree attr = lookup_attribute ("omp allocate var", DECL_ATTRIBUTES (decl));
9268 : 2190618 : if (attr)
9269 : 531 : decl = TREE_VALUE (TREE_VALUE (attr));
9270 : : }
9271 : :
9272 : 3828026 : if (ctx->region_type == ORT_NONE)
9273 : 247 : return lang_hooks.decls.omp_disregard_value_expr (decl, false);
9274 : :
9275 : 3827779 : if (is_global_var (decl))
9276 : : {
9277 : : /* Threadprivate variables are predetermined. */
9278 : 469853 : if (DECL_THREAD_LOCAL_P (decl))
9279 : 13565 : return omp_notice_threadprivate_variable (ctx, decl, NULL_TREE);
9280 : :
9281 : 456288 : if (DECL_HAS_VALUE_EXPR_P (decl))
9282 : : {
9283 : 4380 : if (ctx->region_type & ORT_ACC)
9284 : : /* For OpenACC, defer expansion of value to avoid transfering
9285 : : privatized common block data instead of im-/explicitly transfered
9286 : : variables which are in common blocks. */
9287 : : ;
9288 : : else
9289 : : {
9290 : 2104 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
9291 : :
9292 : 2104 : if (value && DECL_P (value) && DECL_THREAD_LOCAL_P (value))
9293 : 618 : return omp_notice_threadprivate_variable (ctx, decl, value);
9294 : : }
9295 : : }
9296 : :
9297 : 455670 : if (gimplify_omp_ctxp->outer_context == NULL
9298 : 83713 : && VAR_P (decl)
9299 : 539383 : && oacc_get_fn_attrib (current_function_decl))
9300 : : {
9301 : 765 : location_t loc = DECL_SOURCE_LOCATION (decl);
9302 : :
9303 : 765 : if (lookup_attribute ("omp declare target link",
9304 : 765 : DECL_ATTRIBUTES (decl)))
9305 : : {
9306 : 48 : error_at (loc,
9307 : : "%qE with %<link%> clause used in %<routine%> function",
9308 : 24 : DECL_NAME (decl));
9309 : 24 : return false;
9310 : : }
9311 : 741 : else if (!lookup_attribute ("omp declare target",
9312 : 741 : DECL_ATTRIBUTES (decl)))
9313 : : {
9314 : 132 : error_at (loc,
9315 : : "%qE requires a %<declare%> directive for use "
9316 : 66 : "in a %<routine%> function", DECL_NAME (decl));
9317 : 66 : return false;
9318 : : }
9319 : : }
9320 : : }
9321 : :
9322 : 3813506 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9323 : 3813506 : if ((ctx->region_type & ORT_TARGET) != 0)
9324 : : {
9325 : 772606 : if (n == NULL)
9326 : : {
9327 : 44859 : unsigned nflags = flags;
9328 : 44859 : if ((ctx->region_type & ORT_ACC) == 0)
9329 : : {
9330 : 33909 : bool is_declare_target = false;
9331 : 33909 : if (is_global_var (decl)
9332 : 33909 : && varpool_node::get_create (decl)->offloadable)
9333 : : {
9334 : 7004 : struct gimplify_omp_ctx *octx;
9335 : 7004 : for (octx = ctx->outer_context;
9336 : 7012 : octx; octx = octx->outer_context)
9337 : : {
9338 : 9 : n = splay_tree_lookup (octx->variables,
9339 : : (splay_tree_key)decl);
9340 : 9 : if (n
9341 : 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != GOVD_SHARED
9342 : 9 : && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
9343 : : break;
9344 : : }
9345 : 7004 : is_declare_target = octx == NULL;
9346 : : }
9347 : 7004 : if (!is_declare_target)
9348 : : {
9349 : 26906 : int gdmk;
9350 : 26906 : enum omp_clause_defaultmap_kind kind;
9351 : 26906 : if (lang_hooks.decls.omp_allocatable_p (decl))
9352 : : gdmk = GDMK_ALLOCATABLE;
9353 : 26550 : else if (lang_hooks.decls.omp_scalar_target_p (decl))
9354 : : gdmk = GDMK_SCALAR_TARGET;
9355 : 26475 : else if (lang_hooks.decls.omp_scalar_p (decl, false))
9356 : : gdmk = GDMK_SCALAR;
9357 : 11504 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
9358 : 11504 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
9359 : 3159 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
9360 : : == POINTER_TYPE)))
9361 : : gdmk = GDMK_POINTER;
9362 : : else
9363 : : gdmk = GDMK_AGGREGATE;
9364 : 26906 : kind = lang_hooks.decls.omp_predetermined_mapping (decl);
9365 : 26906 : if (kind != OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
9366 : : {
9367 : 945 : if (kind == OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE)
9368 : 101 : nflags |= GOVD_FIRSTPRIVATE;
9369 : 844 : else if (kind == OMP_CLAUSE_DEFAULTMAP_TO)
9370 : 844 : nflags |= GOVD_MAP | GOVD_MAP_TO_ONLY;
9371 : : else
9372 : 0 : gcc_unreachable ();
9373 : : }
9374 : 25961 : else if (ctx->defaultmap[gdmk] == 0)
9375 : : {
9376 : 75 : tree d = lang_hooks.decls.omp_report_decl (decl);
9377 : 75 : error ("%qE not specified in enclosing %<target%>",
9378 : 75 : DECL_NAME (d));
9379 : 75 : inform (ctx->location, "enclosing %<target%>");
9380 : : }
9381 : 25886 : else if (ctx->defaultmap[gdmk]
9382 : 25886 : & (GOVD_MAP_0LEN_ARRAY | GOVD_FIRSTPRIVATE))
9383 : 8951 : nflags |= ctx->defaultmap[gdmk];
9384 : 16935 : else if (ctx->defaultmap[gdmk] & GOVD_MAP_FORCE_PRESENT)
9385 : : {
9386 : 42 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9387 : 42 : nflags |= ctx->defaultmap[gdmk] | GOVD_MAP_ALLOC_ONLY;
9388 : : }
9389 : : else
9390 : : {
9391 : 16893 : gcc_assert (ctx->defaultmap[gdmk] & GOVD_MAP);
9392 : 16893 : nflags |= ctx->defaultmap[gdmk] & ~GOVD_MAP;
9393 : : }
9394 : : }
9395 : : }
9396 : :
9397 : 44859 : struct gimplify_omp_ctx *octx = ctx->outer_context;
9398 : 44859 : if ((ctx->region_type & ORT_ACC) && octx)
9399 : : {
9400 : : /* Look in outer OpenACC contexts, to see if there's a
9401 : : data attribute for this variable. */
9402 : 3535 : omp_notice_variable (octx, decl, in_code);
9403 : :
9404 : 5307 : for (; octx; octx = octx->outer_context)
9405 : : {
9406 : 3883 : if (!(octx->region_type & (ORT_TARGET_DATA | ORT_TARGET)))
9407 : : break;
9408 : 3883 : splay_tree_node n2
9409 : 3883 : = splay_tree_lookup (octx->variables,
9410 : : (splay_tree_key) decl);
9411 : 3883 : if (n2)
9412 : : {
9413 : 2111 : if (octx->region_type == ORT_ACC_HOST_DATA)
9414 : 4 : error ("variable %qE declared in enclosing "
9415 : 4 : "%<host_data%> region", DECL_NAME (decl));
9416 : 2111 : nflags |= GOVD_MAP;
9417 : 2111 : if (octx->region_type == ORT_ACC_DATA
9418 : 2107 : && (n2->value & GOVD_MAP_0LEN_ARRAY))
9419 : 288 : nflags |= GOVD_MAP_0LEN_ARRAY;
9420 : 2111 : goto found_outer;
9421 : : }
9422 : : }
9423 : : }
9424 : :
9425 : 42748 : if ((nflags & ~(GOVD_MAP_TO_ONLY | GOVD_MAP_FROM_ONLY
9426 : : | GOVD_MAP_ALLOC_ONLY)) == flags)
9427 : : {
9428 : 32810 : tree type = TREE_TYPE (decl);
9429 : 32810 : location_t loc = DECL_SOURCE_LOCATION (decl);
9430 : :
9431 : 32810 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases
9432 : 32810 : && omp_privatize_by_reference (decl))
9433 : 29 : type = TREE_TYPE (type);
9434 : :
9435 : 32810 : if (!verify_type_context (loc, TCTX_OMP_MAP_IMP_REF, type))
9436 : : /* Check if TYPE can appear in a target region.
9437 : : verify_type_context has already issued an error if it
9438 : : can't. */
9439 : 0 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9440 : 32810 : else if (!omp_mappable_type (type))
9441 : : {
9442 : 8 : error ("%qD referenced in target region does not have "
9443 : : "a mappable type", decl);
9444 : 8 : nflags |= GOVD_MAP | GOVD_EXPLICIT;
9445 : : }
9446 : : else
9447 : : {
9448 : 32802 : if ((ctx->region_type & ORT_ACC) != 0)
9449 : 8835 : nflags = oacc_default_clause (ctx, decl, flags);
9450 : : else
9451 : 23967 : nflags |= GOVD_MAP;
9452 : : }
9453 : : }
9454 : 9938 : found_outer:
9455 : 44859 : omp_add_variable (ctx, decl, nflags);
9456 : 44859 : if (ctx->region_type & ORT_ACC)
9457 : : /* For OpenACC, as remarked above, defer expansion. */
9458 : : shared = false;
9459 : : else
9460 : 33909 : shared = (nflags & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9461 : 44859 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9462 : : }
9463 : : else
9464 : : {
9465 : 727747 : if (ctx->region_type & ORT_ACC)
9466 : : /* For OpenACC, as remarked above, defer expansion. */
9467 : : shared = false;
9468 : : else
9469 : 431609 : shared = ((n->value | flags)
9470 : 431609 : & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0;
9471 : 727747 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9472 : : /* If nothing changed, there's nothing left to do. */
9473 : 727747 : if ((n->value & flags) == flags)
9474 : : return ret;
9475 : 15766 : flags |= n->value;
9476 : 15766 : n->value = flags;
9477 : : }
9478 : 60625 : goto do_outer;
9479 : : }
9480 : :
9481 : 3040900 : if (n == NULL)
9482 : : {
9483 : 1181483 : if (ctx->region_type == ORT_WORKSHARE
9484 : : || ctx->region_type == ORT_TASKGROUP
9485 : 560538 : || ctx->region_type == ORT_SIMD
9486 : 288522 : || ctx->region_type == ORT_ACC
9487 : 92293 : || (ctx->region_type & ORT_TARGET_DATA) != 0)
9488 : 1133650 : goto do_outer;
9489 : :
9490 : 47833 : flags = omp_default_clause (ctx, decl, in_code, flags);
9491 : :
9492 : 47833 : if ((flags & GOVD_PRIVATE)
9493 : 47833 : && lang_hooks.decls.omp_private_outer_ref (decl))
9494 : 6 : flags |= GOVD_PRIVATE_OUTER_REF;
9495 : :
9496 : 47833 : omp_add_variable (ctx, decl, flags);
9497 : :
9498 : 47833 : shared = (flags & GOVD_SHARED) != 0;
9499 : 47833 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9500 : 47833 : goto do_outer;
9501 : : }
9502 : :
9503 : : /* Don't mark as GOVD_SEEN addressable temporaries seen only in simd
9504 : : lb, b or incr expressions, those shouldn't be turned into simd arrays. */
9505 : 1859417 : if (ctx->region_type == ORT_SIMD
9506 : 151268 : && ctx->in_for_exprs
9507 : 70 : && ((n->value & (GOVD_PRIVATE | GOVD_SEEN | GOVD_EXPLICIT))
9508 : : == GOVD_PRIVATE))
9509 : 1859417 : flags &= ~GOVD_SEEN;
9510 : :
9511 : 1859417 : if ((n->value & (GOVD_SEEN | GOVD_LOCAL)) == 0
9512 : 31713 : && (flags & (GOVD_SEEN | GOVD_LOCAL)) == GOVD_SEEN
9513 : 1891091 : && DECL_SIZE (decl))
9514 : : {
9515 : 31673 : tree size;
9516 : 31673 : if (!poly_int_tree_p (DECL_SIZE (decl)))
9517 : : {
9518 : 140 : splay_tree_node n2;
9519 : 140 : tree t = DECL_VALUE_EXPR (decl);
9520 : 140 : gcc_assert (INDIRECT_REF_P (t));
9521 : 140 : t = TREE_OPERAND (t, 0);
9522 : 140 : gcc_assert (DECL_P (t));
9523 : 140 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
9524 : 140 : n2->value |= GOVD_SEEN;
9525 : : }
9526 : 31533 : else if (omp_privatize_by_reference (decl)
9527 : 4205 : && (size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))))
9528 : 35701 : && !poly_int_tree_p (size))
9529 : : {
9530 : 1324 : splay_tree_node n2;
9531 : 1324 : gcc_assert (DECL_P (size));
9532 : 1324 : n2 = splay_tree_lookup (ctx->variables, (splay_tree_key) size);
9533 : 1324 : if (n2)
9534 : 617 : omp_notice_variable (ctx, size, true);
9535 : : }
9536 : : }
9537 : :
9538 : 1859417 : if (ctx->region_type & ORT_ACC)
9539 : : /* For OpenACC, as remarked above, defer expansion. */
9540 : : shared = false;
9541 : : else
9542 : 1677600 : shared = ((flags | n->value) & GOVD_SHARED) != 0;
9543 : 1859417 : ret = lang_hooks.decls.omp_disregard_value_expr (decl, shared);
9544 : :
9545 : : /* If nothing changed, there's nothing left to do. */
9546 : 1859417 : if ((n->value & flags) == flags)
9547 : : return ret;
9548 : 31674 : flags |= n->value;
9549 : 31674 : n->value = flags;
9550 : :
9551 : 1273782 : do_outer:
9552 : : /* If the variable is private in the current context, then we don't
9553 : : need to propagate anything to an outer context. */
9554 : 1273782 : if ((flags & GOVD_PRIVATE) && !(flags & GOVD_PRIVATE_OUTER_REF))
9555 : : return ret;
9556 : 1263469 : if ((flags & (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9557 : : == (GOVD_LINEAR | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9558 : : return ret;
9559 : 1263409 : if ((flags & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
9560 : : | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9561 : : == (GOVD_LASTPRIVATE | GOVD_LINEAR_LASTPRIVATE_NO_OUTER))
9562 : : return ret;
9563 : 1263409 : if (ctx->outer_context
9564 : 1263409 : && omp_notice_variable (ctx->outer_context, decl, in_code))
9565 : : return true;
9566 : : return ret;
9567 : : }
9568 : :
9569 : : /* Verify that DECL is private within CTX. If there's specific information
9570 : : to the contrary in the innermost scope, generate an error. */
9571 : :
9572 : : static bool
9573 : 50086 : omp_is_private (struct gimplify_omp_ctx *ctx, tree decl, int simd)
9574 : : {
9575 : 95755 : splay_tree_node n;
9576 : :
9577 : 95755 : n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
9578 : 95755 : if (n != NULL)
9579 : : {
9580 : 17943 : if (n->value & GOVD_SHARED)
9581 : : {
9582 : 407 : if (ctx == gimplify_omp_ctxp)
9583 : : {
9584 : 0 : if (simd)
9585 : 0 : error ("iteration variable %qE is predetermined linear",
9586 : 0 : DECL_NAME (decl));
9587 : : else
9588 : 0 : error ("iteration variable %qE should be private",
9589 : 0 : DECL_NAME (decl));
9590 : 0 : n->value = GOVD_PRIVATE;
9591 : 0 : return true;
9592 : : }
9593 : : else
9594 : : return false;
9595 : : }
9596 : 17536 : else if ((n->value & GOVD_EXPLICIT) != 0
9597 : 9703 : && (ctx == gimplify_omp_ctxp
9598 : 334 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9599 : 214 : && gimplify_omp_ctxp->outer_context == ctx)))
9600 : : {
9601 : 9583 : if ((n->value & GOVD_FIRSTPRIVATE) != 0)
9602 : 4 : error ("iteration variable %qE should not be firstprivate",
9603 : 4 : DECL_NAME (decl));
9604 : 9579 : else if ((n->value & GOVD_REDUCTION) != 0)
9605 : 8 : error ("iteration variable %qE should not be reduction",
9606 : 8 : DECL_NAME (decl));
9607 : 9571 : else if (simd != 1 && (n->value & GOVD_LINEAR) != 0)
9608 : 58 : error ("iteration variable %qE should not be linear",
9609 : 58 : DECL_NAME (decl));
9610 : : }
9611 : 17536 : return (ctx == gimplify_omp_ctxp
9612 : 17536 : || (ctx->region_type == ORT_COMBINED_PARALLEL
9613 : 19405 : && gimplify_omp_ctxp->outer_context == ctx));
9614 : : }
9615 : :
9616 : 77812 : if (ctx->region_type != ORT_WORKSHARE
9617 : : && ctx->region_type != ORT_TASKGROUP
9618 : 49400 : && ctx->region_type != ORT_SIMD
9619 : 36140 : && ctx->region_type != ORT_ACC)
9620 : : return false;
9621 : 53845 : else if (ctx->outer_context)
9622 : : return omp_is_private (ctx->outer_context, decl, simd);
9623 : : return false;
9624 : : }
9625 : :
9626 : : /* Return true if DECL is private within a parallel region
9627 : : that binds to the current construct's context or in parallel
9628 : : region's REDUCTION clause. */
9629 : :
9630 : : static bool
9631 : 11533 : omp_check_private (struct gimplify_omp_ctx *ctx, tree decl, bool copyprivate)
9632 : : {
9633 : 11605 : splay_tree_node n;
9634 : :
9635 : 11605 : do
9636 : : {
9637 : 11605 : ctx = ctx->outer_context;
9638 : 11605 : if (ctx == NULL)
9639 : : {
9640 : 2764 : if (is_global_var (decl))
9641 : : return false;
9642 : :
9643 : : /* References might be private, but might be shared too,
9644 : : when checking for copyprivate, assume they might be
9645 : : private, otherwise assume they might be shared. */
9646 : 1290 : if (copyprivate)
9647 : : return true;
9648 : :
9649 : 1244 : if (omp_privatize_by_reference (decl))
9650 : : return false;
9651 : :
9652 : : /* Treat C++ privatized non-static data members outside
9653 : : of the privatization the same. */
9654 : 1198 : if (omp_member_access_dummy_var (decl))
9655 : : return false;
9656 : :
9657 : : return true;
9658 : : }
9659 : :
9660 : 8841 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
9661 : :
9662 : 8841 : if ((ctx->region_type & (ORT_TARGET | ORT_TARGET_DATA)) != 0
9663 : 1291 : && (n == NULL || (n->value & GOVD_DATA_SHARE_CLASS) == 0))
9664 : : {
9665 : 242 : if ((ctx->region_type & ORT_TARGET_DATA) != 0
9666 : 238 : || n == NULL
9667 : 230 : || (n->value & GOVD_MAP) == 0)
9668 : 12 : continue;
9669 : : return false;
9670 : : }
9671 : :
9672 : 7550 : if (n != NULL)
9673 : : {
9674 : 5346 : if ((n->value & GOVD_LOCAL) != 0
9675 : 5346 : && omp_member_access_dummy_var (decl))
9676 : : return false;
9677 : 5307 : return (n->value & GOVD_SHARED) == 0;
9678 : : }
9679 : :
9680 : 3253 : if (ctx->region_type == ORT_WORKSHARE
9681 : : || ctx->region_type == ORT_TASKGROUP
9682 : 3197 : || ctx->region_type == ORT_SIMD
9683 : 3193 : || ctx->region_type == ORT_ACC)
9684 : 60 : continue;
9685 : :
9686 : : break;
9687 : : }
9688 : : while (1);
9689 : : return false;
9690 : : }
9691 : :
9692 : : /* Callback for walk_tree to find a DECL_EXPR for the given DECL. */
9693 : :
9694 : : static tree
9695 : 3148 : find_decl_expr (tree *tp, int *walk_subtrees, void *data)
9696 : : {
9697 : 3148 : tree t = *tp;
9698 : :
9699 : : /* If this node has been visited, unmark it and keep looking. */
9700 : 3148 : if (TREE_CODE (t) == DECL_EXPR && DECL_EXPR_DECL (t) == (tree) data)
9701 : : return t;
9702 : :
9703 : 2724 : if (IS_TYPE_OR_DECL_P (t))
9704 : 452 : *walk_subtrees = 0;
9705 : : return NULL_TREE;
9706 : : }
9707 : :
9708 : :
9709 : : /* Gimplify the affinity clause but effectively ignore it.
9710 : : Generate:
9711 : : var = begin;
9712 : : if ((step > 1) ? var <= end : var > end)
9713 : : locatator_var_expr; */
9714 : :
9715 : : static void
9716 : 374 : gimplify_omp_affinity (tree *list_p, gimple_seq *pre_p)
9717 : : {
9718 : 374 : tree last_iter = NULL_TREE;
9719 : 374 : tree last_bind = NULL_TREE;
9720 : 374 : tree label = NULL_TREE;
9721 : 374 : tree *last_body = NULL;
9722 : 1011 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
9723 : 637 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY)
9724 : : {
9725 : 637 : tree t = OMP_CLAUSE_DECL (c);
9726 : 637 : if (OMP_ITERATOR_DECL_P (t))
9727 : : {
9728 : 389 : if (TREE_VALUE (t) == null_pointer_node)
9729 : 201 : continue;
9730 : 188 : if (TREE_PURPOSE (t) != last_iter)
9731 : : {
9732 : 127 : if (last_bind)
9733 : : {
9734 : 9 : append_to_statement_list (label, last_body);
9735 : 9 : gimplify_and_add (last_bind, pre_p);
9736 : 9 : last_bind = NULL_TREE;
9737 : : }
9738 : 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9739 : : {
9740 : 147 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
9741 : : is_gimple_val, fb_rvalue) == GS_ERROR
9742 : 147 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
9743 : : is_gimple_val, fb_rvalue) == GS_ERROR
9744 : 147 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
9745 : : is_gimple_val, fb_rvalue) == GS_ERROR
9746 : 294 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
9747 : : is_gimple_val, fb_rvalue)
9748 : : == GS_ERROR))
9749 : 0 : return;
9750 : : }
9751 : 127 : last_iter = TREE_PURPOSE (t);
9752 : 127 : tree block = TREE_VEC_ELT (TREE_PURPOSE (t), 5);
9753 : 127 : last_bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
9754 : : NULL, block);
9755 : 127 : last_body = &BIND_EXPR_BODY (last_bind);
9756 : 127 : tree cond = NULL_TREE;
9757 : 127 : location_t loc = OMP_CLAUSE_LOCATION (c);
9758 : 274 : for (tree it = TREE_PURPOSE (t); it; it = TREE_CHAIN (it))
9759 : : {
9760 : 147 : tree var = TREE_VEC_ELT (it, 0);
9761 : 147 : tree begin = TREE_VEC_ELT (it, 1);
9762 : 147 : tree end = TREE_VEC_ELT (it, 2);
9763 : 147 : tree step = TREE_VEC_ELT (it, 3);
9764 : 147 : loc = DECL_SOURCE_LOCATION (var);
9765 : 147 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node,
9766 : : var, begin);
9767 : 147 : append_to_statement_list_force (tem, last_body);
9768 : :
9769 : 147 : tree cond1 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9770 : 147 : step, build_zero_cst (TREE_TYPE (step)));
9771 : 147 : tree cond2 = fold_build2_loc (loc, LE_EXPR, boolean_type_node,
9772 : : var, end);
9773 : 147 : tree cond3 = fold_build2_loc (loc, GT_EXPR, boolean_type_node,
9774 : : var, end);
9775 : 147 : cond1 = fold_build3_loc (loc, COND_EXPR, boolean_type_node,
9776 : : cond1, cond2, cond3);
9777 : 147 : if (cond)
9778 : 20 : cond = fold_build2_loc (loc, TRUTH_AND_EXPR,
9779 : : boolean_type_node, cond, cond1);
9780 : : else
9781 : : cond = cond1;
9782 : : }
9783 : 127 : tree cont_label = create_artificial_label (loc);
9784 : 127 : label = build1 (LABEL_EXPR, void_type_node, cont_label);
9785 : 127 : tree tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9786 : : void_node,
9787 : : build_and_jump (&cont_label));
9788 : 127 : append_to_statement_list_force (tem, last_body);
9789 : : }
9790 : 188 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
9791 : : {
9792 : 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t), 0),
9793 : : last_body);
9794 : 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
9795 : : }
9796 : 188 : if (error_operand_p (TREE_VALUE (t)))
9797 : : return;
9798 : 188 : append_to_statement_list_force (TREE_VALUE (t), last_body);
9799 : 188 : TREE_VALUE (t) = null_pointer_node;
9800 : : }
9801 : : else
9802 : : {
9803 : 248 : if (last_bind)
9804 : : {
9805 : 9 : append_to_statement_list (label, last_body);
9806 : 9 : gimplify_and_add (last_bind, pre_p);
9807 : 9 : last_bind = NULL_TREE;
9808 : : }
9809 : 248 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
9810 : : {
9811 : 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
9812 : : NULL, is_gimple_val, fb_rvalue);
9813 : 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
9814 : : }
9815 : 248 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
9816 : : return;
9817 : 248 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
9818 : : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
9819 : : return;
9820 : 248 : gimplify_and_add (OMP_CLAUSE_DECL (c), pre_p);
9821 : : }
9822 : : }
9823 : 374 : if (last_bind)
9824 : : {
9825 : 109 : append_to_statement_list (label, last_body);
9826 : 109 : gimplify_and_add (last_bind, pre_p);
9827 : : }
9828 : : return;
9829 : : }
9830 : :
9831 : : /* Returns a tree expression containing the total iteration count of the
9832 : : OpenMP iterator IT. */
9833 : :
9834 : : static tree
9835 : 320 : compute_omp_iterator_count (tree it, gimple_seq *pre_p)
9836 : : {
9837 : 320 : tree tcnt = size_one_node;
9838 : 706 : for (; it; it = TREE_CHAIN (it))
9839 : : {
9840 : 386 : if (gimplify_expr (&TREE_VEC_ELT (it, 1), pre_p, NULL,
9841 : : is_gimple_val, fb_rvalue) == GS_ERROR
9842 : 386 : || gimplify_expr (&TREE_VEC_ELT (it, 2), pre_p, NULL,
9843 : : is_gimple_val, fb_rvalue) == GS_ERROR
9844 : 386 : || gimplify_expr (&TREE_VEC_ELT (it, 3), pre_p, NULL,
9845 : : is_gimple_val, fb_rvalue) == GS_ERROR
9846 : 772 : || (gimplify_expr (&TREE_VEC_ELT (it, 4), pre_p, NULL,
9847 : : is_gimple_val, fb_rvalue) == GS_ERROR))
9848 : 0 : return NULL_TREE;
9849 : 386 : tree var = TREE_VEC_ELT (it, 0);
9850 : 386 : tree begin = TREE_VEC_ELT (it, 1);
9851 : 386 : tree end = TREE_VEC_ELT (it, 2);
9852 : 386 : tree step = TREE_VEC_ELT (it, 3);
9853 : 386 : tree orig_step = TREE_VEC_ELT (it, 4);
9854 : 386 : tree type = TREE_TYPE (var);
9855 : 386 : tree stype = TREE_TYPE (step);
9856 : 386 : location_t loc = DECL_SOURCE_LOCATION (var);
9857 : 386 : tree endmbegin;
9858 : : /* Compute count for this iterator as
9859 : : orig_step > 0
9860 : : ? (begin < end ? (end - begin + (step - 1)) / step : 0)
9861 : : : (begin > end ? (end - begin + (step + 1)) / step : 0)
9862 : : and compute product of those for the entire clause. */
9863 : 386 : if (POINTER_TYPE_P (type))
9864 : 42 : endmbegin = fold_build2_loc (loc, POINTER_DIFF_EXPR, stype, end, begin);
9865 : : else
9866 : 344 : endmbegin = fold_build2_loc (loc, MINUS_EXPR, type, end, begin);
9867 : 386 : tree stepm1 = fold_build2_loc (loc, MINUS_EXPR, stype, step,
9868 : : build_int_cst (stype, 1));
9869 : 386 : tree stepp1 = fold_build2_loc (loc, PLUS_EXPR, stype, step,
9870 : : build_int_cst (stype, 1));
9871 : 386 : tree pos = fold_build2_loc (loc, PLUS_EXPR, stype,
9872 : : unshare_expr (endmbegin), stepm1);
9873 : 386 : pos = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, pos, step);
9874 : 386 : tree neg = fold_build2_loc (loc, PLUS_EXPR, stype, endmbegin, stepp1);
9875 : 386 : if (TYPE_UNSIGNED (stype))
9876 : : {
9877 : 31 : neg = fold_build1_loc (loc, NEGATE_EXPR, stype, neg);
9878 : 31 : step = fold_build1_loc (loc, NEGATE_EXPR, stype, step);
9879 : : }
9880 : 386 : neg = fold_build2_loc (loc, TRUNC_DIV_EXPR, stype, neg, step);
9881 : 386 : step = NULL_TREE;
9882 : 386 : tree cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node, begin, end);
9883 : 386 : pos = fold_build3_loc (loc, COND_EXPR, stype, cond, pos,
9884 : : build_int_cst (stype, 0));
9885 : 386 : cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node, end, begin);
9886 : 386 : neg = fold_build3_loc (loc, COND_EXPR, stype, cond, neg,
9887 : : build_int_cst (stype, 0));
9888 : 386 : tree osteptype = TREE_TYPE (orig_step);
9889 : 386 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9890 : : build_int_cst (osteptype, 0));
9891 : 386 : tree cnt = fold_build3_loc (loc, COND_EXPR, stype, cond, pos, neg);
9892 : 386 : cnt = fold_convert_loc (loc, sizetype, cnt);
9893 : 386 : if (gimplify_expr (&cnt, pre_p, NULL, is_gimple_val,
9894 : : fb_rvalue) == GS_ERROR)
9895 : : return NULL_TREE;
9896 : 386 : tcnt = size_binop_loc (loc, MULT_EXPR, tcnt, cnt);
9897 : : }
9898 : 320 : if (gimplify_expr (&tcnt, pre_p, NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
9899 : : return NULL_TREE;
9900 : :
9901 : 320 : return tcnt;
9902 : : }
9903 : :
9904 : : /* Build loops iterating over the space defined by the OpenMP iterator IT.
9905 : : Returns a pointer to the BIND_EXPR_BODY in the innermost loop body.
9906 : : LAST_BIND is set to point to the BIND_EXPR containing the whole loop. */
9907 : :
9908 : : static tree *
9909 : 320 : build_omp_iterator_loop (tree it, gimple_seq *pre_p, tree *last_bind)
9910 : : {
9911 : 320 : if (*last_bind)
9912 : 31 : gimplify_and_add (*last_bind, pre_p);
9913 : 320 : tree block = TREE_VEC_ELT (it, 5);
9914 : 320 : *last_bind = build3 (BIND_EXPR, void_type_node,
9915 : 320 : BLOCK_VARS (block), NULL, block);
9916 : 320 : TREE_SIDE_EFFECTS (*last_bind) = 1;
9917 : 320 : tree *p = &BIND_EXPR_BODY (*last_bind);
9918 : 706 : for (; it; it = TREE_CHAIN (it))
9919 : : {
9920 : 386 : tree var = TREE_VEC_ELT (it, 0);
9921 : 386 : tree begin = TREE_VEC_ELT (it, 1);
9922 : 386 : tree end = TREE_VEC_ELT (it, 2);
9923 : 386 : tree step = TREE_VEC_ELT (it, 3);
9924 : 386 : tree orig_step = TREE_VEC_ELT (it, 4);
9925 : 386 : tree type = TREE_TYPE (var);
9926 : 386 : location_t loc = DECL_SOURCE_LOCATION (var);
9927 : : /* Emit:
9928 : : var = begin;
9929 : : goto cond_label;
9930 : : beg_label:
9931 : : ...
9932 : : var = var + step;
9933 : : cond_label:
9934 : : if (orig_step > 0) {
9935 : : if (var < end) goto beg_label;
9936 : : } else {
9937 : : if (var > end) goto beg_label;
9938 : : }
9939 : : for each iterator, with inner iterators added to
9940 : : the ... above. */
9941 : 386 : tree beg_label = create_artificial_label (loc);
9942 : 386 : tree cond_label = NULL_TREE;
9943 : 386 : tree tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, begin);
9944 : 386 : append_to_statement_list_force (tem, p);
9945 : 386 : tem = build_and_jump (&cond_label);
9946 : 386 : append_to_statement_list_force (tem, p);
9947 : 386 : tem = build1 (LABEL_EXPR, void_type_node, beg_label);
9948 : 386 : append_to_statement_list (tem, p);
9949 : 386 : tree bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
9950 : : NULL_TREE, NULL_TREE);
9951 : 386 : TREE_SIDE_EFFECTS (bind) = 1;
9952 : 386 : SET_EXPR_LOCATION (bind, loc);
9953 : 386 : append_to_statement_list_force (bind, p);
9954 : 386 : if (POINTER_TYPE_P (type))
9955 : 42 : tem = build2_loc (loc, POINTER_PLUS_EXPR, type,
9956 : : var, fold_convert_loc (loc, sizetype, step));
9957 : : else
9958 : 344 : tem = build2_loc (loc, PLUS_EXPR, type, var, step);
9959 : 386 : tem = build2_loc (loc, MODIFY_EXPR, void_type_node, var, tem);
9960 : 386 : append_to_statement_list_force (tem, p);
9961 : 386 : tem = build1 (LABEL_EXPR, void_type_node, cond_label);
9962 : 386 : append_to_statement_list (tem, p);
9963 : 386 : tree cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node, var, end);
9964 : 386 : tree pos = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9965 : : build_and_jump (&beg_label), void_node);
9966 : 386 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, var, end);
9967 : 386 : tree neg = fold_build3_loc (loc, COND_EXPR, void_type_node, cond,
9968 : : build_and_jump (&beg_label), void_node);
9969 : 386 : tree osteptype = TREE_TYPE (orig_step);
9970 : 386 : cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, orig_step,
9971 : : build_int_cst (osteptype, 0));
9972 : 386 : tem = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, pos, neg);
9973 : 386 : append_to_statement_list_force (tem, p);
9974 : 386 : p = &BIND_EXPR_BODY (bind);
9975 : : }
9976 : :
9977 : 320 : return p;
9978 : : }
9979 : :
9980 : :
9981 : : /* Callback for walk_tree to find a VAR_DECL (stored in DATA) in the
9982 : : tree TP. */
9983 : :
9984 : : static tree
9985 : 2306 : find_var_decl (tree *tp, int *, void *data)
9986 : : {
9987 : 2306 : if (*tp == (tree) data)
9988 : 206 : return *tp;
9989 : :
9990 : : return NULL_TREE;
9991 : : }
9992 : :
9993 : : /* Returns an element-by-element copy of OMP iterator tree IT. */
9994 : :
9995 : : static tree
9996 : 198 : copy_omp_iterator (tree it, int elem_count = -1)
9997 : : {
9998 : 198 : if (elem_count < 0)
9999 : 60 : elem_count = TREE_VEC_LENGTH (it);
10000 : 198 : tree new_it = make_tree_vec (elem_count);
10001 : 1386 : for (int i = 0; i < TREE_VEC_LENGTH (it); i++)
10002 : 1188 : TREE_VEC_ELT (new_it, i) = TREE_VEC_ELT (it, i);
10003 : :
10004 : 198 : return new_it;
10005 : : }
10006 : :
10007 : : /* Helper function for walk_tree in remap_omp_iterator_var. */
10008 : :
10009 : : static tree
10010 : 871 : remap_omp_iterator_var_1 (tree *tp, int *, void *data)
10011 : : {
10012 : 871 : tree old_var = ((tree *) data)[0];
10013 : 871 : tree new_var = ((tree *) data)[1];
10014 : :
10015 : 871 : if (*tp == old_var)
10016 : 92 : *tp = new_var;
10017 : 871 : return NULL_TREE;
10018 : : }
10019 : :
10020 : : /* Replace instances of OLD_VAR in TP with NEW_VAR. */
10021 : :
10022 : : static void
10023 : 184 : remap_omp_iterator_var (tree *tp, tree old_var, tree new_var)
10024 : : {
10025 : 184 : tree vars[2] = { old_var, new_var };
10026 : 184 : walk_tree (tp, remap_omp_iterator_var_1, vars, NULL);
10027 : 184 : }
10028 : :
10029 : : /* Scan through all clauses using OpenMP iterators in LIST_P. If any
10030 : : clauses have iterators with variables that are not used by the clause
10031 : : decl or size, issue a warning and replace the iterator with a copy with
10032 : : the unused variables removed. */
10033 : :
10034 : : static void
10035 : 24563 : remove_unused_omp_iterator_vars (tree *list_p)
10036 : : {
10037 : 24563 : auto_vec< vec<tree> > iter_vars;
10038 : 24563 : auto_vec<tree> new_iterators;
10039 : :
10040 : 66056 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10041 : : {
10042 : 41493 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10043 : 41437 : continue;
10044 : 146 : auto_vec<tree> vars;
10045 : 146 : bool need_new_iterators = false;
10046 : 416 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
10047 : : {
10048 : 270 : tree var = TREE_VEC_ELT (it, 0);
10049 : 270 : tree t = walk_tree (&OMP_CLAUSE_DECL (c), find_var_decl, var, NULL);
10050 : 270 : if (t == NULL_TREE)
10051 : 126 : t = walk_tree (&OMP_CLAUSE_SIZE (c), find_var_decl, var, NULL);
10052 : 126 : if (t == NULL_TREE)
10053 : : {
10054 : 64 : need_new_iterators = true;
10055 : 64 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
10056 : 44 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
10057 : 28 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM))
10058 : 44 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
10059 : 92 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
10060 : 40 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
10061 : : "iterator variable %qE not used in clause "
10062 : 40 : "expression", DECL_NAME (var));
10063 : : }
10064 : : else
10065 : 206 : vars.safe_push (var);
10066 : : }
10067 : 146 : if (!need_new_iterators)
10068 : 82 : continue;
10069 : 64 : if (need_new_iterators && vars.is_empty ())
10070 : : {
10071 : : /* No iteration variables are used in the clause - remove the
10072 : : iterator from the clause. */
10073 : 8 : OMP_CLAUSE_ITERATORS (c) = NULL_TREE;
10074 : 8 : continue;
10075 : : }
10076 : :
10077 : : /* If a new iterator has been created for the current set of used
10078 : : iterator variables, then use that as the iterator. Otherwise,
10079 : : create a new iterator for the current iterator variable set. */
10080 : : unsigned i;
10081 : 92 : for (i = 0; i < iter_vars.length (); i++)
10082 : : {
10083 : 112 : if (vars.length () != iter_vars[i].length ())
10084 : 0 : continue;
10085 : : bool identical_p = true;
10086 : 136 : for (unsigned j = 0; j < vars.length () && identical_p; j++)
10087 : 80 : identical_p = vars[j] == iter_vars[i][j];
10088 : :
10089 : 56 : if (identical_p)
10090 : : break;
10091 : : }
10092 : 56 : if (i < iter_vars.length ())
10093 : 20 : OMP_CLAUSE_ITERATORS (c) = new_iterators[i];
10094 : : else
10095 : : {
10096 : 36 : tree new_iters = NULL_TREE;
10097 : 36 : tree *new_iters_p = &new_iters;
10098 : 36 : tree new_vars = NULL_TREE;
10099 : 36 : tree *new_vars_p = &new_vars;
10100 : 36 : i = 0;
10101 : 112 : for (tree it = OMP_CLAUSE_ITERATORS (c); it && i < vars.length();
10102 : 76 : it = TREE_CHAIN (it))
10103 : : {
10104 : 76 : tree var = TREE_VEC_ELT (it, 0);
10105 : 76 : if (var == vars[i])
10106 : : {
10107 : 60 : *new_iters_p = copy_omp_iterator (it);
10108 : 60 : *new_vars_p = build_decl (OMP_CLAUSE_LOCATION (c), VAR_DECL,
10109 : 60 : DECL_NAME (var), TREE_TYPE (var));
10110 : 60 : DECL_ARTIFICIAL (*new_vars_p) = 1;
10111 : 60 : DECL_CONTEXT (*new_vars_p) = DECL_CONTEXT (var);
10112 : 60 : TREE_VEC_ELT (*new_iters_p, 0) = *new_vars_p;
10113 : 60 : new_iters_p = &TREE_CHAIN (*new_iters_p);
10114 : 60 : new_vars_p = &DECL_CHAIN (*new_vars_p);
10115 : 60 : i++;
10116 : : }
10117 : : }
10118 : 36 : tree new_block = make_node (BLOCK);
10119 : 36 : BLOCK_VARS (new_block) = new_vars;
10120 : 36 : TREE_VEC_ELT (new_iters, 5) = new_block;
10121 : 36 : new_iterators.safe_push (new_iters);
10122 : 36 : iter_vars.safe_push (vars.copy ());
10123 : 36 : OMP_CLAUSE_ITERATORS (c) = new_iters;
10124 : : }
10125 : :
10126 : : /* Remap clause to use the new variables. */
10127 : 56 : i = 0;
10128 : 148 : for (tree it = OMP_CLAUSE_ITERATORS (c); it; it = TREE_CHAIN (it))
10129 : : {
10130 : 92 : tree old_var = vars[i++];
10131 : 92 : tree new_var = TREE_VEC_ELT (it, 0);
10132 : 92 : remap_omp_iterator_var (&OMP_CLAUSE_DECL (c), old_var, new_var);
10133 : 92 : remap_omp_iterator_var (&OMP_CLAUSE_SIZE (c), old_var, new_var);
10134 : : }
10135 : 146 : }
10136 : :
10137 : 24599 : for (unsigned i = 0; i < iter_vars.length (); i++)
10138 : 36 : iter_vars[i].release ();
10139 : 24563 : }
10140 : :
10141 : 140 : struct iterator_loop_info_t
10142 : : {
10143 : : tree bind;
10144 : : tree count;
10145 : : tree index;
10146 : : tree body_label;
10147 : : auto_vec<tree> clauses;
10148 : : };
10149 : :
10150 : : typedef hash_map<tree, iterator_loop_info_t> iterator_loop_info_map_t;
10151 : :
10152 : : /* Builds a loop to expand any OpenMP iterators in the clauses in LIST_P,
10153 : : reusing any previously built loops if they use the same set of iterators.
10154 : : Generated Gimple statements are placed into LOOPS_SEQ_P. The clause
10155 : : iterators are updated with information on how and where to insert code into
10156 : : the loop body. */
10157 : :
10158 : : static void
10159 : 24563 : build_omp_iterators_loops (tree *list_p, gimple_seq *loops_seq_p)
10160 : : {
10161 : 24563 : iterator_loop_info_map_t loops;
10162 : :
10163 : 66056 : for (tree c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10164 : : {
10165 : 41493 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10166 : 41355 : continue;
10167 : :
10168 : 138 : bool built_p;
10169 : 138 : iterator_loop_info_t &loop
10170 : 138 : = loops.get_or_insert (OMP_CLAUSE_ITERATORS (c), &built_p);
10171 : :
10172 : 138 : if (!built_p)
10173 : : {
10174 : 70 : loop.count = compute_omp_iterator_count (OMP_CLAUSE_ITERATORS (c),
10175 : : loops_seq_p);
10176 : 70 : if (!loop.count)
10177 : 0 : continue;
10178 : 70 : if (integer_zerop (loop.count))
10179 : 8 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
10180 : : "iteration count is zero");
10181 : :
10182 : 70 : loop.bind = NULL_TREE;
10183 : 70 : tree *body = build_omp_iterator_loop (OMP_CLAUSE_ITERATORS (c),
10184 : : loops_seq_p, &loop.bind);
10185 : :
10186 : 70 : loop.index = create_tmp_var (sizetype);
10187 : 70 : SET_EXPR_LOCATION (loop.bind, OMP_CLAUSE_LOCATION (c));
10188 : :
10189 : : /* BEFORE LOOP: */
10190 : : /* idx = -1; */
10191 : : /* This should be initialized to before the individual elements,
10192 : : as idx is pre-incremented in the loop body. */
10193 : 70 : gimple *assign = gimple_build_assign (loop.index, size_int (-1));
10194 : 70 : gimple_seq_add_stmt (loops_seq_p, assign);
10195 : :
10196 : : /* IN LOOP BODY: */
10197 : : /* Create a label so we can find this point later. */
10198 : 70 : loop.body_label = create_artificial_label (OMP_CLAUSE_LOCATION (c));
10199 : 70 : tree tem = build1 (LABEL_EXPR, void_type_node, loop.body_label);
10200 : 70 : append_to_statement_list_force (tem, body);
10201 : :
10202 : : /* idx += 2; */
10203 : 70 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10204 : : void_type_node, loop.index,
10205 : : size_binop (PLUS_EXPR, loop.index, size_int (2)));
10206 : 70 : append_to_statement_list_force (tem, body);
10207 : : }
10208 : :
10209 : : /* Create array to hold expanded values. */
10210 : 138 : tree last_count_2 = size_binop (MULT_EXPR, loop.count, size_int (2));
10211 : 138 : tree arr_length = size_binop (PLUS_EXPR, last_count_2, size_int (1));
10212 : 138 : tree elems = NULL_TREE;
10213 : 138 : if (TREE_CONSTANT (arr_length))
10214 : : {
10215 : 138 : tree type = build_array_type (ptr_type_node,
10216 : : build_index_type (arr_length));
10217 : 138 : elems = create_tmp_var_raw (type, "omp_iter_data");
10218 : 138 : TREE_ADDRESSABLE (elems) = 1;
10219 : 138 : gimple_add_tmp_var (elems);
10220 : : }
10221 : : else
10222 : : {
10223 : : /* Handle dynamic sizes. */
10224 : 0 : sorry ("dynamic iterator sizes not implemented yet");
10225 : : }
10226 : :
10227 : : /* BEFORE LOOP: */
10228 : : /* elems[0] = count; */
10229 : 138 : tree lhs = build4 (ARRAY_REF, ptr_type_node, elems, size_int (0),
10230 : : NULL_TREE, NULL_TREE);
10231 : 138 : tree tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10232 : : void_type_node, lhs, loop.count);
10233 : 138 : gimplify_and_add (tem, loops_seq_p);
10234 : :
10235 : : /* Make a copy of the iterator with extra info at the end. */
10236 : 138 : int elem_count = TREE_VEC_LENGTH (OMP_CLAUSE_ITERATORS (c));
10237 : 138 : tree new_iterator = copy_omp_iterator (OMP_CLAUSE_ITERATORS (c),
10238 : : elem_count + 3);
10239 : 138 : TREE_VEC_ELT (new_iterator, elem_count) = loop.body_label;
10240 : 138 : TREE_VEC_ELT (new_iterator, elem_count + 1) = elems;
10241 : 138 : TREE_VEC_ELT (new_iterator, elem_count + 2) = loop.index;
10242 : 138 : TREE_CHAIN (new_iterator) = TREE_CHAIN (OMP_CLAUSE_ITERATORS (c));
10243 : 138 : OMP_CLAUSE_ITERATORS (c) = new_iterator;
10244 : :
10245 : 138 : loop.clauses.safe_push (c);
10246 : : }
10247 : :
10248 : : /* Now gimplify and add all the loops that were built. */
10249 : 24633 : for (hash_map<tree, iterator_loop_info_t>::iterator it = loops.begin ();
10250 : 49266 : it != loops.end (); ++it)
10251 : 70 : gimplify_and_add ((*it).second.bind, loops_seq_p);
10252 : 24563 : }
10253 : :
10254 : : /* Helper function for enter_omp_iterator_loop_context. */
10255 : :
10256 : : static gimple_seq *
10257 : 1546 : enter_omp_iterator_loop_context_1 (tree iterator, gimple_seq *loops_seq_p)
10258 : : {
10259 : : /* Drill into the nested bind expressions to get to the loop body. */
10260 : 1546 : for (gimple_stmt_iterator gsi = gsi_start (*loops_seq_p);
10261 : 9672 : !gsi_end_p (gsi); gsi_next (&gsi))
10262 : : {
10263 : 9296 : gimple *stmt = gsi_stmt (gsi);
10264 : :
10265 : 9296 : switch (gimple_code (stmt))
10266 : : {
10267 : 1216 : case GIMPLE_BIND:
10268 : 1216 : {
10269 : 1216 : gbind *bind_stmt = as_a<gbind *> (stmt);
10270 : 1216 : gimple_push_bind_expr (bind_stmt);
10271 : 1216 : gimple_seq *bind_body_p = gimple_bind_body_ptr (bind_stmt);
10272 : 1216 : gimple_seq *seq =
10273 : 1216 : enter_omp_iterator_loop_context_1 (iterator, bind_body_p);
10274 : 1216 : if (seq)
10275 : : return seq;
10276 : 376 : gimple_pop_bind_expr ();
10277 : : }
10278 : 376 : break;
10279 : 0 : case GIMPLE_TRY:
10280 : 0 : {
10281 : 0 : gimple_seq *try_eval_p = gimple_try_eval_ptr (stmt);
10282 : 0 : gimple_seq *seq =
10283 : 0 : enter_omp_iterator_loop_context_1 (iterator, try_eval_p);
10284 : 0 : if (seq)
10285 : : return seq;
10286 : : }
10287 : : break;
10288 : 1712 : case GIMPLE_LABEL:
10289 : 1712 : {
10290 : 1712 : glabel *label_stmt = as_a<glabel *> (stmt);
10291 : 1712 : tree label = gimple_label_label (label_stmt);
10292 : 1712 : if (label == TREE_VEC_ELT (iterator, 6))
10293 : : return loops_seq_p;
10294 : : }
10295 : : break;
10296 : : default:
10297 : : break;
10298 : : }
10299 : : }
10300 : :
10301 : : return NULL;
10302 : : }
10303 : :
10304 : : /* Enter the Gimplification context in LOOPS_SEQ_P for the iterator loop
10305 : : associated with OpenMP clause C. Returns the gimple_seq for the loop body
10306 : : if C has OpenMP iterators, or ALT_SEQ_P if not. */
10307 : :
10308 : : static gimple_seq *
10309 : 61588 : enter_omp_iterator_loop_context (tree c, gimple_seq *loops_seq_p,
10310 : : gimple_seq *alt_seq_p)
10311 : : {
10312 : 61588 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10313 : : return alt_seq_p;
10314 : :
10315 : 330 : push_gimplify_context ();
10316 : :
10317 : 330 : gimple_seq *seq = enter_omp_iterator_loop_context_1 (OMP_CLAUSE_ITERATORS (c),
10318 : : loops_seq_p);
10319 : 330 : gcc_assert (seq);
10320 : : return seq;
10321 : : }
10322 : :
10323 : : /* Enter the Gimplification context in STMT for the iterator loop associated
10324 : : with OpenMP clause C. Returns the gimple_seq for the loop body if C has
10325 : : OpenMP iterators, or ALT_SEQ_P if not. */
10326 : :
10327 : : gimple_seq *
10328 : 192 : enter_omp_iterator_loop_context (tree c, gomp_target *stmt,
10329 : : gimple_seq *alt_seq_p)
10330 : : {
10331 : 192 : gimple_seq *loops_seq_p = gimple_omp_target_iterator_loops_ptr (stmt);
10332 : 192 : return enter_omp_iterator_loop_context (c, loops_seq_p, alt_seq_p);
10333 : : }
10334 : :
10335 : : /* Exit the Gimplification context for the OpenMP clause C. */
10336 : :
10337 : : void
10338 : 61588 : exit_omp_iterator_loop_context (tree c)
10339 : : {
10340 : 61588 : if (!OMP_CLAUSE_HAS_ITERATORS (c))
10341 : : return;
10342 : 1170 : while (!gimplify_ctxp->bind_expr_stack.is_empty ())
10343 : 840 : gimple_pop_bind_expr ();
10344 : 330 : pop_gimplify_context (NULL);
10345 : : }
10346 : :
10347 : : /* If *LIST_P contains any OpenMP depend clauses with iterators,
10348 : : lower all the depend clauses by populating corresponding depend
10349 : : array. Returns 0 if there are no such depend clauses, or
10350 : : 2 if all depend clauses should be removed, 1 otherwise. */
10351 : :
10352 : : static int
10353 : 1898 : gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
10354 : : {
10355 : 1898 : tree c;
10356 : 1898 : gimple *g;
10357 : 1898 : size_t n[5] = { 0, 0, 0, 0, 0 };
10358 : 1898 : bool unused[5];
10359 : 1898 : tree counts[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
10360 : 1898 : tree last_iter = NULL_TREE, last_count = NULL_TREE;
10361 : 1898 : size_t i, j;
10362 : 1898 : location_t first_loc = UNKNOWN_LOCATION;
10363 : :
10364 : 6236 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10365 : 4338 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10366 : : {
10367 : 2200 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10368 : : {
10369 : : case OMP_CLAUSE_DEPEND_IN:
10370 : : i = 2;
10371 : : break;
10372 : : case OMP_CLAUSE_DEPEND_OUT:
10373 : : case OMP_CLAUSE_DEPEND_INOUT:
10374 : : i = 0;
10375 : : break;
10376 : : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10377 : : i = 1;
10378 : : break;
10379 : : case OMP_CLAUSE_DEPEND_DEPOBJ:
10380 : : i = 3;
10381 : : break;
10382 : : case OMP_CLAUSE_DEPEND_INOUTSET:
10383 : : i = 4;
10384 : : break;
10385 : 0 : default:
10386 : 0 : gcc_unreachable ();
10387 : : }
10388 : 2200 : tree t = OMP_CLAUSE_DECL (c);
10389 : 2200 : if (first_loc == UNKNOWN_LOCATION)
10390 : 1898 : first_loc = OMP_CLAUSE_LOCATION (c);
10391 : 2200 : if (OMP_ITERATOR_DECL_P (t))
10392 : : {
10393 : 297 : if (TREE_PURPOSE (t) != last_iter)
10394 : : {
10395 : 250 : tree tcnt = compute_omp_iterator_count (TREE_PURPOSE (t),
10396 : : pre_p);
10397 : 250 : if (!tcnt)
10398 : : return 2;
10399 : 250 : last_iter = TREE_PURPOSE (t);
10400 : 250 : last_count = tcnt;
10401 : : }
10402 : 297 : if (counts[i] == NULL_TREE)
10403 : 243 : counts[i] = last_count;
10404 : : else
10405 : 54 : counts[i] = size_binop_loc (OMP_CLAUSE_LOCATION (c),
10406 : : PLUS_EXPR, counts[i], last_count);
10407 : : }
10408 : : else
10409 : 1903 : n[i]++;
10410 : : }
10411 : 10601 : for (i = 0; i < 5; i++)
10412 : 8908 : if (counts[i])
10413 : : break;
10414 : 1898 : if (i == 5)
10415 : : return 0;
10416 : :
10417 : 205 : tree total = size_zero_node;
10418 : 1230 : for (i = 0; i < 5; i++)
10419 : : {
10420 : 1025 : unused[i] = counts[i] == NULL_TREE && n[i] == 0;
10421 : 1025 : if (counts[i] == NULL_TREE)
10422 : 782 : counts[i] = size_zero_node;
10423 : 1025 : if (n[i])
10424 : 44 : counts[i] = size_binop (PLUS_EXPR, counts[i], size_int (n[i]));
10425 : 1025 : if (gimplify_expr (&counts[i], pre_p, NULL, is_gimple_val,
10426 : : fb_rvalue) == GS_ERROR)
10427 : : return 2;
10428 : 1025 : total = size_binop (PLUS_EXPR, total, counts[i]);
10429 : : }
10430 : :
10431 : 205 : if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
10432 : : == GS_ERROR)
10433 : : return 2;
10434 : 205 : bool is_old = unused[1] && unused[3] && unused[4];
10435 : 205 : tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
10436 : : size_int (is_old ? 1 : 4));
10437 : 205 : if (!unused[4])
10438 : 3 : totalpx = size_binop (PLUS_EXPR, totalpx,
10439 : : size_binop (MULT_EXPR, counts[4], size_int (2)));
10440 : 205 : tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
10441 : 205 : tree array = create_tmp_var_raw (type);
10442 : 205 : TREE_ADDRESSABLE (array) = 1;
10443 : 205 : if (!poly_int_tree_p (totalpx))
10444 : : {
10445 : 81 : if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (array)))
10446 : 81 : gimplify_type_sizes (TREE_TYPE (array), pre_p);
10447 : 81 : if (gimplify_omp_ctxp)
10448 : : {
10449 : : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
10450 : : while (ctx
10451 : 20 : && (ctx->region_type == ORT_WORKSHARE
10452 : : || ctx->region_type == ORT_TASKGROUP
10453 : 20 : || ctx->region_type == ORT_SIMD
10454 : 20 : || ctx->region_type == ORT_ACC))
10455 : 0 : ctx = ctx->outer_context;
10456 : 20 : if (ctx)
10457 : 20 : omp_add_variable (ctx, array, GOVD_LOCAL | GOVD_SEEN);
10458 : : }
10459 : 81 : gimplify_vla_decl (array, pre_p);
10460 : : }
10461 : : else
10462 : 124 : gimple_add_tmp_var (array);
10463 : 205 : tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
10464 : : NULL_TREE);
10465 : 205 : tree tem;
10466 : 205 : if (!is_old)
10467 : : {
10468 : 31 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10469 : : build_int_cst (ptr_type_node, 0));
10470 : 31 : gimplify_and_add (tem, pre_p);
10471 : 31 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
10472 : : NULL_TREE);
10473 : : }
10474 : 205 : tem = build2 (MODIFY_EXPR, void_type_node, r,
10475 : : fold_convert (ptr_type_node, total));
10476 : 205 : gimplify_and_add (tem, pre_p);
10477 : 801 : for (i = 1; i < (is_old ? 2 : 4); i++)
10478 : : {
10479 : 267 : r = build4 (ARRAY_REF, ptr_type_node, array, size_int (i + !is_old),
10480 : : NULL_TREE, NULL_TREE);
10481 : 267 : tem = build2 (MODIFY_EXPR, void_type_node, r, counts[i - 1]);
10482 : 267 : gimplify_and_add (tem, pre_p);
10483 : : }
10484 : :
10485 : : tree cnts[6];
10486 : 717 : for (j = 5; j; j--)
10487 : 717 : if (!unused[j - 1])
10488 : : break;
10489 : 1230 : for (i = 0; i < 5; i++)
10490 : : {
10491 : 1025 : if (i && (i >= j || unused[i - 1]))
10492 : : {
10493 : 770 : cnts[i] = cnts[i - 1];
10494 : 770 : continue;
10495 : : }
10496 : 255 : cnts[i] = create_tmp_var (sizetype);
10497 : 255 : if (i == 0)
10498 : 236 : g = gimple_build_assign (cnts[i], size_int (is_old ? 2 : 5));
10499 : : else
10500 : : {
10501 : 50 : tree t;
10502 : 50 : if (is_old)
10503 : 38 : t = size_binop (PLUS_EXPR, counts[0], size_int (2));
10504 : : else
10505 : 12 : t = size_binop (PLUS_EXPR, cnts[i - 1], counts[i - 1]);
10506 : 50 : if (gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue)
10507 : : == GS_ERROR)
10508 : 0 : return 2;
10509 : 50 : g = gimple_build_assign (cnts[i], t);
10510 : : }
10511 : 255 : gimple_seq_add_stmt (pre_p, g);
10512 : : }
10513 : 205 : if (unused[4])
10514 : 202 : cnts[5] = NULL_TREE;
10515 : : else
10516 : : {
10517 : 3 : tree t = size_binop (PLUS_EXPR, total, size_int (5));
10518 : 3 : cnts[5] = create_tmp_var (sizetype);
10519 : 3 : g = gimple_build_assign (cnts[i], t);
10520 : 3 : gimple_seq_add_stmt (pre_p, g);
10521 : : }
10522 : :
10523 : 205 : last_iter = NULL_TREE;
10524 : 205 : tree last_bind = NULL_TREE;
10525 : 205 : tree *last_body = NULL;
10526 : 563 : for (c = *list_p; c; c = OMP_CLAUSE_CHAIN (c))
10527 : 358 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10528 : : {
10529 : 343 : switch (OMP_CLAUSE_DEPEND_KIND (c))
10530 : : {
10531 : : case OMP_CLAUSE_DEPEND_IN:
10532 : : i = 2;
10533 : : break;
10534 : : case OMP_CLAUSE_DEPEND_OUT:
10535 : : case OMP_CLAUSE_DEPEND_INOUT:
10536 : : i = 0;
10537 : : break;
10538 : : case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
10539 : : i = 1;
10540 : : break;
10541 : : case OMP_CLAUSE_DEPEND_DEPOBJ:
10542 : : i = 3;
10543 : : break;
10544 : : case OMP_CLAUSE_DEPEND_INOUTSET:
10545 : : i = 4;
10546 : : break;
10547 : 0 : default:
10548 : 0 : gcc_unreachable ();
10549 : : }
10550 : 343 : tree t = OMP_CLAUSE_DECL (c);
10551 : 343 : if (OMP_ITERATOR_DECL_P (t))
10552 : : {
10553 : 297 : if (TREE_PURPOSE (t) != last_iter)
10554 : : {
10555 : 250 : last_body = build_omp_iterator_loop (TREE_PURPOSE (t), pre_p,
10556 : : &last_bind);
10557 : 250 : SET_EXPR_LOCATION (last_bind, OMP_CLAUSE_LOCATION (c));
10558 : : }
10559 : 297 : last_iter = TREE_PURPOSE (t);
10560 : 297 : if (TREE_CODE (TREE_VALUE (t)) == COMPOUND_EXPR)
10561 : : {
10562 : 0 : append_to_statement_list (TREE_OPERAND (TREE_VALUE (t),
10563 : : 0), last_body);
10564 : 0 : TREE_VALUE (t) = TREE_OPERAND (TREE_VALUE (t), 1);
10565 : : }
10566 : 297 : if (error_operand_p (TREE_VALUE (t)))
10567 : : return 2;
10568 : 297 : if (TREE_VALUE (t) != null_pointer_node)
10569 : 291 : TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
10570 : 297 : if (i == 4)
10571 : : {
10572 : 3 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10573 : : NULL_TREE, NULL_TREE);
10574 : 3 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10575 : : NULL_TREE, NULL_TREE);
10576 : 3 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10577 : 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10578 : : void_type_node, r, r2);
10579 : 3 : append_to_statement_list_force (tem, last_body);
10580 : 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10581 : : void_type_node, cnts[i],
10582 : : size_binop (PLUS_EXPR, cnts[i],
10583 : : size_int (1)));
10584 : 3 : append_to_statement_list_force (tem, last_body);
10585 : 3 : i = 5;
10586 : : }
10587 : 297 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10588 : : NULL_TREE, NULL_TREE);
10589 : 594 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10590 : 297 : void_type_node, r, TREE_VALUE (t));
10591 : 297 : append_to_statement_list_force (tem, last_body);
10592 : 297 : if (i == 5)
10593 : : {
10594 : 3 : r = build4 (ARRAY_REF, ptr_type_node, array,
10595 : : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10596 : : NULL_TREE, NULL_TREE);
10597 : 3 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10598 : 3 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10599 : : void_type_node, r, tem);
10600 : 3 : append_to_statement_list_force (tem, last_body);
10601 : : }
10602 : 297 : tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
10603 : : void_type_node, cnts[i],
10604 : 297 : size_binop (PLUS_EXPR, cnts[i],
10605 : : size_int (1 + (i == 5))));
10606 : 297 : append_to_statement_list_force (tem, last_body);
10607 : 297 : TREE_VALUE (t) = null_pointer_node;
10608 : : }
10609 : : else
10610 : : {
10611 : 46 : if (last_bind)
10612 : : {
10613 : 18 : gimplify_and_add (last_bind, pre_p);
10614 : 18 : last_bind = NULL_TREE;
10615 : : }
10616 : 46 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
10617 : : {
10618 : 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
10619 : : NULL, is_gimple_val, fb_rvalue);
10620 : 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
10621 : : }
10622 : 46 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
10623 : : return 2;
10624 : 46 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
10625 : 46 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
10626 : 46 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
10627 : : is_gimple_val, fb_rvalue) == GS_ERROR)
10628 : : return 2;
10629 : 46 : if (i == 4)
10630 : : {
10631 : 0 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10632 : : NULL_TREE, NULL_TREE);
10633 : 0 : tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
10634 : : NULL_TREE, NULL_TREE);
10635 : 0 : r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
10636 : 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, r2);
10637 : 0 : gimplify_and_add (tem, pre_p);
10638 : 0 : g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR,
10639 : : cnts[i],
10640 : : size_int (1)));
10641 : 0 : gimple_seq_add_stmt (pre_p, g);
10642 : 0 : i = 5;
10643 : : }
10644 : 46 : r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
10645 : : NULL_TREE, NULL_TREE);
10646 : 46 : tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
10647 : 46 : gimplify_and_add (tem, pre_p);
10648 : 46 : if (i == 5)
10649 : : {
10650 : 0 : r = build4 (ARRAY_REF, ptr_type_node, array,
10651 : : size_binop (PLUS_EXPR, cnts[i], size_int (1)),
10652 : : NULL_TREE, NULL_TREE);
10653 : 0 : tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
10654 : 0 : tem = build2 (MODIFY_EXPR, void_type_node, r, tem);
10655 : 0 : append_to_statement_list_force (tem, last_body);
10656 : 0 : gimplify_and_add (tem, pre_p);
10657 : : }
10658 : 46 : g = gimple_build_assign (cnts[i],
10659 : 46 : size_binop (PLUS_EXPR, cnts[i],
10660 : : size_int (1 + (i == 5))));
10661 : 46 : gimple_seq_add_stmt (pre_p, g);
10662 : : }
10663 : : }
10664 : 205 : if (last_bind)
10665 : 201 : gimplify_and_add (last_bind, pre_p);
10666 : 205 : tree cond = boolean_false_node;
10667 : 205 : if (is_old)
10668 : : {
10669 : 174 : if (!unused[0])
10670 : 88 : cond = build2_loc (first_loc, NE_EXPR, boolean_type_node, cnts[0],
10671 : : size_binop_loc (first_loc, PLUS_EXPR, counts[0],
10672 : : size_int (2)));
10673 : 174 : if (!unused[2])
10674 : 124 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10675 : : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10676 : : cnts[2],
10677 : : size_binop_loc (first_loc, PLUS_EXPR,
10678 : : totalpx,
10679 : : size_int (1))));
10680 : : }
10681 : : else
10682 : : {
10683 : 31 : tree prev = size_int (5);
10684 : 186 : for (i = 0; i < 5; i++)
10685 : : {
10686 : 155 : if (unused[i])
10687 : 112 : continue;
10688 : 43 : prev = size_binop_loc (first_loc, PLUS_EXPR, counts[i], prev);
10689 : 43 : cond = build2_loc (first_loc, TRUTH_OR_EXPR, boolean_type_node, cond,
10690 : : build2_loc (first_loc, NE_EXPR, boolean_type_node,
10691 : : cnts[i], unshare_expr (prev)));
10692 : : }
10693 : : }
10694 : 205 : tem = build3_loc (first_loc, COND_EXPR, void_type_node, cond,
10695 : : build_call_expr_loc (first_loc,
10696 : : builtin_decl_explicit (BUILT_IN_TRAP),
10697 : : 0), void_node);
10698 : 205 : gimplify_and_add (tem, pre_p);
10699 : 205 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
10700 : 205 : OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
10701 : 205 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
10702 : 205 : OMP_CLAUSE_CHAIN (c) = *list_p;
10703 : 205 : *list_p = c;
10704 : 205 : return 1;
10705 : : }
10706 : :
10707 : : /* True if mapping node C maps, or unmaps, a (Fortran) array descriptor. */
10708 : :
10709 : : static bool
10710 : 113523 : omp_map_clause_descriptor_p (tree c)
10711 : : {
10712 : 113523 : if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
10713 : : return false;
10714 : :
10715 : 113521 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO_PSET)
10716 : : return true;
10717 : :
10718 : 74948 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_RELEASE
10719 : 69276 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DELETE)
10720 : 75388 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (c))
10721 : 4042 : return true;
10722 : :
10723 : : return false;
10724 : : }
10725 : :
10726 : : /* For a set of mappings describing an array section pointed to by a struct
10727 : : (or derived type, etc.) component, create an "alloc" or "release" node to
10728 : : insert into a list following a GOMP_MAP_STRUCT node. For some types of
10729 : : mapping (e.g. Fortran arrays with descriptors), an additional mapping may
10730 : : be created that is inserted into the list of mapping nodes attached to the
10731 : : directive being processed -- not part of the sorted list of nodes after
10732 : : GOMP_MAP_STRUCT.
10733 : :
10734 : : CODE is the code of the directive being processed. GRP_START and GRP_END
10735 : : are the first and last of two or three nodes representing this array section
10736 : : mapping (e.g. a data movement node like GOMP_MAP_{TO,FROM}, optionally a
10737 : : GOMP_MAP_TO_PSET, and finally a GOMP_MAP_ALWAYS_POINTER). EXTRA_NODE is
10738 : : filled with the additional node described above, if needed.
10739 : :
10740 : : This function does not add the new nodes to any lists itself. It is the
10741 : : responsibility of the caller to do that. */
10742 : :
10743 : : static tree
10744 : 1717 : build_omp_struct_comp_nodes (enum tree_code code, tree grp_start, tree grp_end,
10745 : : tree *extra_node)
10746 : : {
10747 : 1524 : enum gomp_map_kind mkind
10748 : 1717 : = (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
10749 : 1717 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
10750 : :
10751 : 1717 : gcc_assert (grp_start != grp_end);
10752 : :
10753 : 1717 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10754 : 1717 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
10755 : 1717 : OMP_CLAUSE_DECL (c2) = unshare_expr (OMP_CLAUSE_DECL (grp_end));
10756 : 1717 : OMP_CLAUSE_CHAIN (c2) = NULL_TREE;
10757 : 1717 : tree grp_mid = NULL_TREE;
10758 : 1717 : if (OMP_CLAUSE_CHAIN (grp_start) != grp_end)
10759 : 185 : grp_mid = OMP_CLAUSE_CHAIN (grp_start);
10760 : :
10761 : 185 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
10762 : 0 : OMP_CLAUSE_SIZE (c2) = OMP_CLAUSE_SIZE (grp_mid);
10763 : : else
10764 : 1717 : OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (ptr_type_node);
10765 : :
10766 : 1717 : if (grp_mid
10767 : 185 : && OMP_CLAUSE_CODE (grp_mid) == OMP_CLAUSE_MAP
10768 : 1902 : && OMP_CLAUSE_MAP_KIND (grp_mid) == GOMP_MAP_ALWAYS_POINTER)
10769 : : {
10770 : 0 : tree c3
10771 : 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
10772 : 0 : OMP_CLAUSE_SET_MAP_KIND (c3, mkind);
10773 : 0 : OMP_CLAUSE_DECL (c3) = unshare_expr (OMP_CLAUSE_DECL (grp_mid));
10774 : 0 : OMP_CLAUSE_SIZE (c3) = TYPE_SIZE_UNIT (ptr_type_node);
10775 : 0 : OMP_CLAUSE_CHAIN (c3) = NULL_TREE;
10776 : :
10777 : 0 : *extra_node = c3;
10778 : : }
10779 : : else
10780 : 1717 : *extra_node = NULL_TREE;
10781 : :
10782 : 1717 : return c2;
10783 : : }
10784 : :
10785 : : /* Strip ARRAY_REFS or an indirect ref off BASE, find the containing object,
10786 : : and set *BITPOSP and *POFFSETP to the bit offset of the access.
10787 : : If BASE_REF is non-NULL and the containing object is a reference, set
10788 : : *BASE_REF to that reference before dereferencing the object.
10789 : : If BASE_REF is NULL, check that the containing object is a COMPONENT_REF or
10790 : : has array type, else return NULL. */
10791 : :
10792 : : static tree
10793 : 6541 : extract_base_bit_offset (tree base, poly_int64 *bitposp,
10794 : : poly_offset_int *poffsetp,
10795 : : bool *variable_offset)
10796 : : {
10797 : 6541 : tree offset;
10798 : 6541 : poly_int64 bitsize, bitpos;
10799 : 6541 : machine_mode mode;
10800 : 6541 : int unsignedp, reversep, volatilep = 0;
10801 : 6541 : poly_offset_int poffset;
10802 : :
10803 : 6541 : STRIP_NOPS (base);
10804 : :
10805 : 6541 : base = get_inner_reference (base, &bitsize, &bitpos, &offset, &mode,
10806 : : &unsignedp, &reversep, &volatilep);
10807 : :
10808 : 6541 : STRIP_NOPS (base);
10809 : :
10810 : 6541 : if (offset && poly_int_tree_p (offset))
10811 : : {
10812 : 0 : poffset = wi::to_poly_offset (offset);
10813 : 0 : *variable_offset = false;
10814 : : }
10815 : : else
10816 : : {
10817 : 6541 : poffset = 0;
10818 : 6541 : *variable_offset = (offset != NULL_TREE);
10819 : : }
10820 : :
10821 : 6541 : if (maybe_ne (bitpos, 0))
10822 : 4939 : poffset += bits_to_bytes_round_down (bitpos);
10823 : :
10824 : 6541 : *bitposp = bitpos;
10825 : 6541 : *poffsetp = poffset;
10826 : :
10827 : 6541 : return base;
10828 : : }
10829 : :
10830 : : /* Used for topological sorting of mapping groups. UNVISITED means we haven't
10831 : : started processing the group yet. The TEMPORARY mark is used when we first
10832 : : encounter a group on a depth-first traversal, and the PERMANENT mark is used
10833 : : when we have processed all the group's children (i.e. all the base pointers
10834 : : referred to by the group's mapping nodes, recursively). */
10835 : :
10836 : : enum omp_tsort_mark {
10837 : : UNVISITED,
10838 : : TEMPORARY,
10839 : : PERMANENT
10840 : : };
10841 : :
10842 : : /* Hash for trees based on operand_equal_p. Like tree_operand_hash
10843 : : but ignores side effects in the equality comparisons. */
10844 : :
10845 : : struct tree_operand_hash_no_se : tree_operand_hash
10846 : : {
10847 : : static inline bool equal (const value_type &,
10848 : : const compare_type &);
10849 : : };
10850 : :
10851 : : inline bool
10852 : 361432 : tree_operand_hash_no_se::equal (const value_type &t1,
10853 : : const compare_type &t2)
10854 : : {
10855 : 361432 : return operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS);
10856 : : }
10857 : :
10858 : : /* A group of OMP_CLAUSE_MAP nodes that correspond to a single "map"
10859 : : clause. */
10860 : :
10861 : : struct omp_mapping_group {
10862 : : tree *grp_start;
10863 : : tree grp_end;
10864 : : omp_tsort_mark mark;
10865 : : /* If we've removed the group but need to reindex, mark the group as
10866 : : deleted. */
10867 : : bool deleted;
10868 : : /* The group points to an already-created "GOMP_MAP_STRUCT
10869 : : GOMP_MAP_ATTACH_DETACH" pair. */
10870 : : bool reprocess_struct;
10871 : : /* The group should use "zero-length" allocations for pointers that are not
10872 : : mapped "to" on the same directive. */
10873 : : bool fragile;
10874 : : struct omp_mapping_group *sibling;
10875 : : struct omp_mapping_group *next;
10876 : : };
10877 : :
10878 : : DEBUG_FUNCTION void
10879 : 0 : debug_mapping_group (omp_mapping_group *grp)
10880 : : {
10881 : 0 : tree tmp = OMP_CLAUSE_CHAIN (grp->grp_end);
10882 : 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = NULL;
10883 : 0 : debug_generic_expr (*grp->grp_start);
10884 : 0 : OMP_CLAUSE_CHAIN (grp->grp_end) = tmp;
10885 : 0 : }
10886 : :
10887 : : /* Return the OpenMP "base pointer" of an expression EXPR, or NULL if there
10888 : : isn't one. */
10889 : :
10890 : : static tree
10891 : 33027 : omp_get_base_pointer (tree expr)
10892 : : {
10893 : 33027 : while (TREE_CODE (expr) == ARRAY_REF
10894 : 38317 : || TREE_CODE (expr) == COMPONENT_REF)
10895 : 5290 : expr = TREE_OPERAND (expr, 0);
10896 : :
10897 : 33027 : if (INDIRECT_REF_P (expr)
10898 : 33027 : || (TREE_CODE (expr) == MEM_REF
10899 : 0 : && integer_zerop (TREE_OPERAND (expr, 1))))
10900 : : {
10901 : 9654 : expr = TREE_OPERAND (expr, 0);
10902 : 9691 : while (TREE_CODE (expr) == COMPOUND_EXPR)
10903 : 37 : expr = TREE_OPERAND (expr, 1);
10904 : 9654 : if (TREE_CODE (expr) == POINTER_PLUS_EXPR)
10905 : 837 : expr = TREE_OPERAND (expr, 0);
10906 : 9654 : if (TREE_CODE (expr) == SAVE_EXPR)
10907 : 31 : expr = TREE_OPERAND (expr, 0);
10908 : 9654 : STRIP_NOPS (expr);
10909 : 9654 : return expr;
10910 : : }
10911 : :
10912 : : return NULL_TREE;
10913 : : }
10914 : :
10915 : : /* An attach or detach operation depends directly on the address being
10916 : : attached/detached. Return that address, or none if there are no
10917 : : attachments/detachments. */
10918 : :
10919 : : static tree
10920 : 15099 : omp_get_attachment (omp_mapping_group *grp)
10921 : : {
10922 : 15099 : tree node = *grp->grp_start;
10923 : :
10924 : 15099 : switch (OMP_CLAUSE_MAP_KIND (node))
10925 : : {
10926 : 12589 : case GOMP_MAP_TO:
10927 : 12589 : case GOMP_MAP_FROM:
10928 : 12589 : case GOMP_MAP_TOFROM:
10929 : 12589 : case GOMP_MAP_ALWAYS_FROM:
10930 : 12589 : case GOMP_MAP_ALWAYS_TO:
10931 : 12589 : case GOMP_MAP_ALWAYS_TOFROM:
10932 : 12589 : case GOMP_MAP_FORCE_FROM:
10933 : 12589 : case GOMP_MAP_FORCE_TO:
10934 : 12589 : case GOMP_MAP_FORCE_TOFROM:
10935 : 12589 : case GOMP_MAP_FORCE_PRESENT:
10936 : 12589 : case GOMP_MAP_PRESENT_ALLOC:
10937 : 12589 : case GOMP_MAP_PRESENT_FROM:
10938 : 12589 : case GOMP_MAP_PRESENT_TO:
10939 : 12589 : case GOMP_MAP_PRESENT_TOFROM:
10940 : 12589 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
10941 : 12589 : case GOMP_MAP_ALWAYS_PRESENT_TO:
10942 : 12589 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
10943 : 12589 : case GOMP_MAP_ALLOC:
10944 : 12589 : case GOMP_MAP_RELEASE:
10945 : 12589 : case GOMP_MAP_DELETE:
10946 : 12589 : case GOMP_MAP_FORCE_ALLOC:
10947 : 12589 : if (node == grp->grp_end)
10948 : : return NULL_TREE;
10949 : :
10950 : 5994 : node = OMP_CLAUSE_CHAIN (node);
10951 : 5994 : if (node && omp_map_clause_descriptor_p (node))
10952 : : {
10953 : 1002 : gcc_assert (node != grp->grp_end);
10954 : 1002 : node = OMP_CLAUSE_CHAIN (node);
10955 : : }
10956 : 5994 : if (node)
10957 : 5994 : switch (OMP_CLAUSE_MAP_KIND (node))
10958 : : {
10959 : : case GOMP_MAP_POINTER:
10960 : : case GOMP_MAP_ALWAYS_POINTER:
10961 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
10962 : : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
10963 : : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
10964 : : return NULL_TREE;
10965 : :
10966 : 2087 : case GOMP_MAP_ATTACH_DETACH:
10967 : 2087 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
10968 : 2087 : case GOMP_MAP_DETACH:
10969 : 2087 : return OMP_CLAUSE_DECL (node);
10970 : :
10971 : 0 : default:
10972 : 0 : internal_error ("unexpected mapping node");
10973 : : }
10974 : 0 : return error_mark_node;
10975 : :
10976 : 0 : case GOMP_MAP_TO_PSET:
10977 : 0 : gcc_assert (node != grp->grp_end);
10978 : 0 : node = OMP_CLAUSE_CHAIN (node);
10979 : 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
10980 : 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
10981 : 0 : return OMP_CLAUSE_DECL (node);
10982 : : else
10983 : 0 : internal_error ("unexpected mapping node");
10984 : : return error_mark_node;
10985 : :
10986 : 447 : case GOMP_MAP_ATTACH:
10987 : 447 : case GOMP_MAP_DETACH:
10988 : 447 : node = OMP_CLAUSE_CHAIN (node);
10989 : 447 : if (!node || *grp->grp_start == grp->grp_end)
10990 : 447 : return OMP_CLAUSE_DECL (*grp->grp_start);
10991 : 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
10992 : 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
10993 : 0 : return OMP_CLAUSE_DECL (*grp->grp_start);
10994 : : else
10995 : 0 : internal_error ("unexpected mapping node");
10996 : : return error_mark_node;
10997 : :
10998 : : case GOMP_MAP_STRUCT:
10999 : : case GOMP_MAP_STRUCT_UNORD:
11000 : : case GOMP_MAP_FORCE_DEVICEPTR:
11001 : : case GOMP_MAP_DEVICE_RESIDENT:
11002 : : case GOMP_MAP_LINK:
11003 : : case GOMP_MAP_IF_PRESENT:
11004 : : case GOMP_MAP_FIRSTPRIVATE:
11005 : : case GOMP_MAP_FIRSTPRIVATE_INT:
11006 : : case GOMP_MAP_USE_DEVICE_PTR:
11007 : : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11008 : : return NULL_TREE;
11009 : :
11010 : 0 : default:
11011 : 0 : internal_error ("unexpected mapping node");
11012 : : }
11013 : :
11014 : : return error_mark_node;
11015 : : }
11016 : :
11017 : : /* Given a pointer START_P to the start of a group of related (e.g. pointer)
11018 : : mappings, return the chain pointer to the end of that group in the list. */
11019 : :
11020 : : static tree *
11021 : 104930 : omp_group_last (tree *start_p)
11022 : : {
11023 : 104930 : tree c = *start_p, nc, *grp_last_p = start_p;
11024 : :
11025 : 104930 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
11026 : :
11027 : 104930 : nc = OMP_CLAUSE_CHAIN (c);
11028 : :
11029 : 183472 : if (!nc || OMP_CLAUSE_CODE (nc) != OMP_CLAUSE_MAP)
11030 : : return grp_last_p;
11031 : :
11032 : 66421 : switch (OMP_CLAUSE_MAP_KIND (c))
11033 : : {
11034 : : default:
11035 : : while (nc
11036 : 107084 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11037 : 224652 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11038 : 99922 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
11039 : 89717 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH
11040 : 79016 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
11041 : 53139 : || (OMP_CLAUSE_MAP_KIND (nc)
11042 : : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
11043 : 53123 : || (OMP_CLAUSE_MAP_KIND (nc)
11044 : : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)
11045 : 52756 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH
11046 : 52701 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ALWAYS_POINTER
11047 : 50797 : || omp_map_clause_descriptor_p (nc)))
11048 : : {
11049 : 62962 : tree nc2 = OMP_CLAUSE_CHAIN (nc);
11050 : 62962 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH)
11051 : : {
11052 : : /* In the specific case we're doing "exit data" on an array
11053 : : slice of a reference-to-pointer struct component, we will see
11054 : : DETACH followed by ATTACH_DETACH here. We want to treat that
11055 : : as a single group. In other cases DETACH might represent a
11056 : : stand-alone "detach" clause, so we don't want to consider
11057 : : that part of the group. */
11058 : 55 : if (nc2
11059 : 16 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
11060 : 71 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH_DETACH)
11061 : 0 : goto consume_two_nodes;
11062 : : else
11063 : : break;
11064 : : }
11065 : 62907 : if (nc2
11066 : 45914 : && OMP_CLAUSE_CODE (nc2) == OMP_CLAUSE_MAP
11067 : 39401 : && (OMP_CLAUSE_MAP_KIND (nc)
11068 : : == GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION)
11069 : 62923 : && OMP_CLAUSE_MAP_KIND (nc2) == GOMP_MAP_ATTACH)
11070 : : {
11071 : 16 : consume_two_nodes:
11072 : 16 : grp_last_p = &OMP_CLAUSE_CHAIN (nc);
11073 : 16 : c = nc2;
11074 : 16 : nc = OMP_CLAUSE_CHAIN (nc2);
11075 : : }
11076 : : else
11077 : : {
11078 : 62891 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11079 : 62891 : c = nc;
11080 : 62891 : nc = nc2;
11081 : : }
11082 : : }
11083 : : break;
11084 : :
11085 : 195 : case GOMP_MAP_ATTACH:
11086 : 195 : case GOMP_MAP_DETACH:
11087 : : /* This is a weird artifact of how directives are parsed: bare attach or
11088 : : detach clauses get a subsequent (meaningless) FIRSTPRIVATE_POINTER or
11089 : : FIRSTPRIVATE_REFERENCE node. FIXME. */
11090 : 195 : if (nc
11091 : 195 : && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11092 : 195 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11093 : 195 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER))
11094 : 0 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11095 : : break;
11096 : :
11097 : 27 : case GOMP_MAP_TO_PSET:
11098 : 27 : if (OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
11099 : 27 : && (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH
11100 : 6 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_DETACH))
11101 : 27 : grp_last_p = &OMP_CLAUSE_CHAIN (c);
11102 : : break;
11103 : :
11104 : 5025 : case GOMP_MAP_STRUCT:
11105 : 5025 : case GOMP_MAP_STRUCT_UNORD:
11106 : 5025 : {
11107 : 5025 : unsigned HOST_WIDE_INT num_mappings
11108 : 5025 : = tree_to_uhwi (OMP_CLAUSE_SIZE (c));
11109 : 5025 : if (OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_POINTER
11110 : 4687 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
11111 : 9230 : || OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_ATTACH_DETACH)
11112 : 1134 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11113 : 12261 : for (unsigned i = 0; i < num_mappings; i++)
11114 : 7236 : grp_last_p = &OMP_CLAUSE_CHAIN (*grp_last_p);
11115 : : }
11116 : : break;
11117 : : }
11118 : :
11119 : : return grp_last_p;
11120 : : }
11121 : :
11122 : : /* Walk through LIST_P, and return a list of groups of mappings found (e.g.
11123 : : OMP_CLAUSE_MAP with GOMP_MAP_{TO/FROM/TOFROM} followed by one or two
11124 : : associated GOMP_MAP_POINTER mappings). Return a vector of omp_mapping_group
11125 : : if we have more than one such group, else return NULL. */
11126 : :
11127 : : static void
11128 : 86468 : omp_gather_mapping_groups_1 (tree *list_p, vec<omp_mapping_group> *groups,
11129 : : tree gather_sentinel)
11130 : : {
11131 : 86468 : for (tree *cp = list_p;
11132 : 256264 : *cp && *cp != gather_sentinel;
11133 : 169796 : cp = &OMP_CLAUSE_CHAIN (*cp))
11134 : : {
11135 : 169796 : if (OMP_CLAUSE_CODE (*cp) != OMP_CLAUSE_MAP)
11136 : 95032 : continue;
11137 : :
11138 : 74764 : tree *grp_last_p = omp_group_last (cp);
11139 : 74764 : omp_mapping_group grp;
11140 : :
11141 : 74764 : grp.grp_start = cp;
11142 : 74764 : grp.grp_end = *grp_last_p;
11143 : 74764 : grp.mark = UNVISITED;
11144 : 74764 : grp.sibling = NULL;
11145 : 74764 : grp.deleted = false;
11146 : 74764 : grp.reprocess_struct = false;
11147 : 74764 : grp.fragile = false;
11148 : 74764 : grp.next = NULL;
11149 : 74764 : groups->safe_push (grp);
11150 : :
11151 : 74764 : cp = grp_last_p;
11152 : : }
11153 : 86468 : }
11154 : :
11155 : : static vec<omp_mapping_group> *
11156 : 86150 : omp_gather_mapping_groups (tree *list_p)
11157 : : {
11158 : 86150 : vec<omp_mapping_group> *groups = new vec<omp_mapping_group> ();
11159 : :
11160 : 86150 : omp_gather_mapping_groups_1 (list_p, groups, NULL_TREE);
11161 : :
11162 : 86150 : if (groups->length () > 0)
11163 : : return groups;
11164 : : else
11165 : : {
11166 : 43822 : delete groups;
11167 : 43822 : return NULL;
11168 : : }
11169 : : }
11170 : :
11171 : : /* A pointer mapping group GRP may define a block of memory starting at some
11172 : : base address, and maybe also define a firstprivate pointer or firstprivate
11173 : : reference that points to that block. The return value is a node containing
11174 : : the former, and the *FIRSTPRIVATE pointer is set if we have the latter.
11175 : : If we define several base pointers, i.e. for a GOMP_MAP_STRUCT mapping,
11176 : : return the number of consecutive chained nodes in CHAINED. */
11177 : :
11178 : : static tree
11179 : 75158 : omp_group_base (omp_mapping_group *grp, unsigned int *chained,
11180 : : tree *firstprivate)
11181 : : {
11182 : 75158 : tree node = *grp->grp_start;
11183 : :
11184 : 75158 : *firstprivate = NULL_TREE;
11185 : 75158 : *chained = 1;
11186 : :
11187 : 75158 : switch (OMP_CLAUSE_MAP_KIND (node))
11188 : : {
11189 : 71434 : case GOMP_MAP_TO:
11190 : 71434 : case GOMP_MAP_FROM:
11191 : 71434 : case GOMP_MAP_TOFROM:
11192 : 71434 : case GOMP_MAP_ALWAYS_FROM:
11193 : 71434 : case GOMP_MAP_ALWAYS_TO:
11194 : 71434 : case GOMP_MAP_ALWAYS_TOFROM:
11195 : 71434 : case GOMP_MAP_FORCE_FROM:
11196 : 71434 : case GOMP_MAP_FORCE_TO:
11197 : 71434 : case GOMP_MAP_FORCE_TOFROM:
11198 : 71434 : case GOMP_MAP_FORCE_PRESENT:
11199 : 71434 : case GOMP_MAP_PRESENT_ALLOC:
11200 : 71434 : case GOMP_MAP_PRESENT_FROM:
11201 : 71434 : case GOMP_MAP_PRESENT_TO:
11202 : 71434 : case GOMP_MAP_PRESENT_TOFROM:
11203 : 71434 : case GOMP_MAP_ALWAYS_PRESENT_FROM:
11204 : 71434 : case GOMP_MAP_ALWAYS_PRESENT_TO:
11205 : 71434 : case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
11206 : 71434 : case GOMP_MAP_ALLOC:
11207 : 71434 : case GOMP_MAP_RELEASE:
11208 : 71434 : case GOMP_MAP_DELETE:
11209 : 71434 : case GOMP_MAP_FORCE_ALLOC:
11210 : 71434 : case GOMP_MAP_IF_PRESENT:
11211 : 71434 : if (node == grp->grp_end)
11212 : : return node;
11213 : :
11214 : 32717 : node = OMP_CLAUSE_CHAIN (node);
11215 : 32717 : if (!node)
11216 : 0 : internal_error ("unexpected mapping node");
11217 : 32717 : if (omp_map_clause_descriptor_p (node))
11218 : : {
11219 : 9678 : if (node == grp->grp_end)
11220 : 0 : return *grp->grp_start;
11221 : 9678 : node = OMP_CLAUSE_CHAIN (node);
11222 : : }
11223 : 32717 : switch (OMP_CLAUSE_MAP_KIND (node))
11224 : : {
11225 : 23006 : case GOMP_MAP_POINTER:
11226 : 23006 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11227 : 23006 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11228 : 23006 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11229 : 23006 : *firstprivate = OMP_CLAUSE_DECL (node);
11230 : 23006 : return *grp->grp_start;
11231 : :
11232 : 9711 : case GOMP_MAP_ALWAYS_POINTER:
11233 : 9711 : case GOMP_MAP_ATTACH_DETACH:
11234 : 9711 : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11235 : 9711 : case GOMP_MAP_DETACH:
11236 : 9711 : return *grp->grp_start;
11237 : :
11238 : 0 : default:
11239 : 0 : internal_error ("unexpected mapping node");
11240 : : }
11241 : : return error_mark_node;
11242 : :
11243 : 18 : case GOMP_MAP_TO_PSET:
11244 : 18 : gcc_assert (node != grp->grp_end);
11245 : 18 : node = OMP_CLAUSE_CHAIN (node);
11246 : 18 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH
11247 : 18 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_DETACH)
11248 : : return NULL_TREE;
11249 : : else
11250 : 0 : internal_error ("unexpected mapping node");
11251 : : return error_mark_node;
11252 : :
11253 : 999 : case GOMP_MAP_ATTACH:
11254 : 999 : case GOMP_MAP_DETACH:
11255 : 999 : node = OMP_CLAUSE_CHAIN (node);
11256 : 999 : if (!node || *grp->grp_start == grp->grp_end)
11257 : : return NULL_TREE;
11258 : 0 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11259 : 0 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11260 : : {
11261 : : /* We're mapping the base pointer itself in a bare attach or detach
11262 : : node. This is a side effect of how parsing works, and the mapping
11263 : : will be removed anyway (at least for enter/exit data directives).
11264 : : We should ignore the mapping here. FIXME. */
11265 : : return NULL_TREE;
11266 : : }
11267 : : else
11268 : 0 : internal_error ("unexpected mapping node");
11269 : : return error_mark_node;
11270 : :
11271 : 2423 : case GOMP_MAP_STRUCT:
11272 : 2423 : case GOMP_MAP_STRUCT_UNORD:
11273 : 2423 : {
11274 : 2423 : unsigned HOST_WIDE_INT num_mappings
11275 : 2423 : = tree_to_uhwi (OMP_CLAUSE_SIZE (node));
11276 : 2423 : node = OMP_CLAUSE_CHAIN (node);
11277 : 2423 : if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_POINTER
11278 : 2423 : || OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11279 : : {
11280 : 393 : *firstprivate = OMP_CLAUSE_DECL (node);
11281 : 393 : node = OMP_CLAUSE_CHAIN (node);
11282 : : }
11283 : 2030 : else if (OMP_CLAUSE_MAP_KIND (node) == GOMP_MAP_ATTACH_DETACH)
11284 : 314 : node = OMP_CLAUSE_CHAIN (node);
11285 : 2423 : *chained = num_mappings;
11286 : 2423 : return node;
11287 : : }
11288 : :
11289 : : case GOMP_MAP_FORCE_DEVICEPTR:
11290 : : case GOMP_MAP_DEVICE_RESIDENT:
11291 : : case GOMP_MAP_LINK:
11292 : : case GOMP_MAP_FIRSTPRIVATE:
11293 : : case GOMP_MAP_FIRSTPRIVATE_INT:
11294 : : case GOMP_MAP_USE_DEVICE_PTR:
11295 : : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
11296 : : return NULL_TREE;
11297 : :
11298 : 0 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11299 : 0 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11300 : 0 : case GOMP_MAP_POINTER:
11301 : 0 : case GOMP_MAP_ALWAYS_POINTER:
11302 : 0 : case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
11303 : : /* These shouldn't appear by themselves. */
11304 : 0 : if (!seen_error ())
11305 : 0 : internal_error ("unexpected pointer mapping node");
11306 : 0 : return error_mark_node;
11307 : :
11308 : 0 : default:
11309 : 0 : gcc_unreachable ();
11310 : : }
11311 : :
11312 : : return error_mark_node;
11313 : : }
11314 : :
11315 : : /* Given a vector of omp_mapping_groups, build a hash table so we can look up
11316 : : nodes by tree_operand_hash_no_se. */
11317 : :
11318 : : static void
11319 : 42812 : omp_index_mapping_groups_1 (hash_map<tree_operand_hash_no_se,
11320 : : omp_mapping_group *> *grpmap,
11321 : : vec<omp_mapping_group> *groups,
11322 : : tree reindex_sentinel)
11323 : : {
11324 : 42812 : omp_mapping_group *grp;
11325 : 42812 : unsigned int i;
11326 : 42812 : bool reindexing = reindex_sentinel != NULL_TREE, above_hwm = false;
11327 : :
11328 : 118424 : FOR_EACH_VEC_ELT (*groups, i, grp)
11329 : : {
11330 : 75612 : if (reindexing && *grp->grp_start == reindex_sentinel)
11331 : 75612 : above_hwm = true;
11332 : :
11333 : 75612 : if (reindexing && !above_hwm)
11334 : 52213 : continue;
11335 : :
11336 : 75312 : if (grp->reprocess_struct)
11337 : 154 : continue;
11338 : :
11339 : 75158 : tree fpp;
11340 : 75158 : unsigned int chained;
11341 : 75158 : tree node = omp_group_base (grp, &chained, &fpp);
11342 : :
11343 : 75158 : if (node == error_mark_node || (!node && !fpp))
11344 : 1301 : continue;
11345 : :
11346 : : for (unsigned j = 0;
11347 : 148791 : node && j < chained;
11348 : 74934 : node = OMP_CLAUSE_CHAIN (node), j++)
11349 : : {
11350 : 74934 : tree decl = OMP_CLAUSE_DECL (node);
11351 : : /* Sometimes we see zero-offset MEM_REF instead of INDIRECT_REF,
11352 : : meaning node-hash lookups don't work. This is a workaround for
11353 : : that, but ideally we should just create the INDIRECT_REF at
11354 : : source instead. FIXME. */
11355 : 74934 : if (TREE_CODE (decl) == MEM_REF
11356 : 74934 : && integer_zerop (TREE_OPERAND (decl, 1)))
11357 : 0 : decl = build_fold_indirect_ref (TREE_OPERAND (decl, 0));
11358 : :
11359 : 74934 : omp_mapping_group **prev = grpmap->get (decl);
11360 : :
11361 : 74934 : if (prev && *prev == grp)
11362 : : /* Empty. */;
11363 : 74934 : else if (prev)
11364 : : {
11365 : : /* Mapping the same thing twice is normally diagnosed as an error,
11366 : : but can happen under some circumstances, e.g. in pr99928-16.c,
11367 : : the directive:
11368 : :
11369 : : #pragma omp target simd reduction(+:a[:3]) \
11370 : : map(always, tofrom: a[:6])
11371 : : ...
11372 : :
11373 : : will result in two "a[0]" mappings (of different sizes). */
11374 : :
11375 : 140 : grp->sibling = (*prev)->sibling;
11376 : 140 : (*prev)->sibling = grp;
11377 : : }
11378 : : else
11379 : 74794 : grpmap->put (decl, grp);
11380 : : }
11381 : :
11382 : 73857 : if (!fpp)
11383 : 50458 : continue;
11384 : :
11385 : 23399 : omp_mapping_group **prev = grpmap->get (fpp);
11386 : 23399 : if (prev && *prev != grp)
11387 : : {
11388 : 12 : grp->sibling = (*prev)->sibling;
11389 : 12 : (*prev)->sibling = grp;
11390 : : }
11391 : : else
11392 : 23387 : grpmap->put (fpp, grp);
11393 : : }
11394 : 42812 : }
11395 : :
11396 : : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11397 : 42328 : omp_index_mapping_groups (vec<omp_mapping_group> *groups)
11398 : : {
11399 : 42328 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11400 : 42328 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11401 : :
11402 : 42328 : omp_index_mapping_groups_1 (grpmap, groups, NULL_TREE);
11403 : :
11404 : 42328 : return grpmap;
11405 : : }
11406 : :
11407 : : /* Rebuild group map from partially-processed clause list (during
11408 : : omp_build_struct_sibling_lists). We have already processed nodes up until
11409 : : a high-water mark (HWM). This is a bit tricky because the list is being
11410 : : reordered as it is scanned, but we know:
11411 : :
11412 : : 1. The list after HWM has not been touched yet, so we can reindex it safely.
11413 : :
11414 : : 2. The list before and including HWM has been altered, but remains
11415 : : well-formed throughout the sibling-list building operation.
11416 : :
11417 : : so, we can do the reindex operation in two parts, on the processed and
11418 : : then the unprocessed halves of the list. */
11419 : :
11420 : : static hash_map<tree_operand_hash_no_se, omp_mapping_group *> *
11421 : 318 : omp_reindex_mapping_groups (tree *list_p,
11422 : : vec<omp_mapping_group> *groups,
11423 : : vec<omp_mapping_group> *processed_groups,
11424 : : tree sentinel)
11425 : : {
11426 : 318 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap
11427 : 318 : = new hash_map<tree_operand_hash_no_se, omp_mapping_group *>;
11428 : :
11429 : 318 : processed_groups->truncate (0);
11430 : :
11431 : 318 : omp_gather_mapping_groups_1 (list_p, processed_groups, sentinel);
11432 : 318 : omp_index_mapping_groups_1 (grpmap, processed_groups, NULL_TREE);
11433 : 318 : if (sentinel)
11434 : 166 : omp_index_mapping_groups_1 (grpmap, groups, sentinel);
11435 : :
11436 : 318 : return grpmap;
11437 : : }
11438 : :
11439 : : /* Find the immediately-containing struct for a component ref (etc.)
11440 : : expression EXPR. */
11441 : :
11442 : : static tree
11443 : 37435 : omp_containing_struct (tree expr)
11444 : : {
11445 : 37435 : tree expr0 = expr;
11446 : :
11447 : 37435 : STRIP_NOPS (expr);
11448 : :
11449 : : /* Note: don't strip NOPs unless we're also stripping off array refs or a
11450 : : component ref. */
11451 : 37435 : if (TREE_CODE (expr) != ARRAY_REF && TREE_CODE (expr) != COMPONENT_REF)
11452 : : return expr0;
11453 : :
11454 : 18569 : while (TREE_CODE (expr) == ARRAY_REF)
11455 : 2142 : expr = TREE_OPERAND (expr, 0);
11456 : :
11457 : 16427 : if (TREE_CODE (expr) == COMPONENT_REF)
11458 : 15506 : expr = TREE_OPERAND (expr, 0);
11459 : :
11460 : : return expr;
11461 : : }
11462 : :
11463 : : /* Return TRUE if DECL describes a component that is part of a whole structure
11464 : : that is mapped elsewhere in GRPMAP. *MAPPED_BY_GROUP is set to the group
11465 : : that maps that structure, if present. */
11466 : :
11467 : : static bool
11468 : 22002 : omp_mapped_by_containing_struct (hash_map<tree_operand_hash_no_se,
11469 : : omp_mapping_group *> *grpmap,
11470 : : tree decl,
11471 : : omp_mapping_group **mapped_by_group)
11472 : : {
11473 : 22002 : tree wsdecl = NULL_TREE;
11474 : :
11475 : 22002 : *mapped_by_group = NULL;
11476 : :
11477 : 37435 : while (true)
11478 : : {
11479 : 37435 : wsdecl = omp_containing_struct (decl);
11480 : 37435 : if (wsdecl == decl)
11481 : : break;
11482 : 16427 : omp_mapping_group **wholestruct = grpmap->get (wsdecl);
11483 : 16427 : if (!wholestruct
11484 : 15433 : && TREE_CODE (wsdecl) == MEM_REF
11485 : 16427 : && integer_zerop (TREE_OPERAND (wsdecl, 1)))
11486 : : {
11487 : 0 : tree deref = TREE_OPERAND (wsdecl, 0);
11488 : 0 : deref = build_fold_indirect_ref (deref);
11489 : 0 : wholestruct = grpmap->get (deref);
11490 : : }
11491 : 16427 : if (wholestruct)
11492 : : {
11493 : 994 : *mapped_by_group = *wholestruct;
11494 : 994 : return true;
11495 : : }
11496 : : decl = wsdecl;
11497 : : }
11498 : :
11499 : : return false;
11500 : : }
11501 : :
11502 : : /* Helper function for omp_tsort_mapping_groups. Returns TRUE on success, or
11503 : : FALSE on error. */
11504 : :
11505 : : static bool
11506 : 18290 : omp_tsort_mapping_groups_1 (omp_mapping_group ***outlist,
11507 : : vec<omp_mapping_group> *groups,
11508 : : hash_map<tree_operand_hash_no_se,
11509 : : omp_mapping_group *> *grpmap,
11510 : : omp_mapping_group *grp)
11511 : : {
11512 : 18290 : if (grp->mark == PERMANENT)
11513 : : return true;
11514 : 15099 : if (grp->mark == TEMPORARY)
11515 : : {
11516 : 0 : fprintf (stderr, "when processing group:\n");
11517 : 0 : debug_mapping_group (grp);
11518 : 0 : internal_error ("base pointer cycle detected");
11519 : : return false;
11520 : : }
11521 : 15099 : grp->mark = TEMPORARY;
11522 : :
11523 : 15099 : tree attaches_to = omp_get_attachment (grp);
11524 : :
11525 : 15099 : if (attaches_to)
11526 : : {
11527 : 2534 : omp_mapping_group **basep = grpmap->get (attaches_to);
11528 : :
11529 : 2534 : if (basep && *basep != grp)
11530 : : {
11531 : 2920 : for (omp_mapping_group *w = *basep; w; w = w->sibling)
11532 : 1460 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11533 : : return false;
11534 : : }
11535 : : }
11536 : :
11537 : 15099 : tree decl = OMP_CLAUSE_DECL (*grp->grp_start);
11538 : :
11539 : 20584 : while (decl)
11540 : : {
11541 : 20584 : tree base = omp_get_base_pointer (decl);
11542 : :
11543 : 20584 : if (!base)
11544 : : break;
11545 : :
11546 : 8062 : omp_mapping_group **innerp = grpmap->get (base);
11547 : 8062 : omp_mapping_group *wholestruct;
11548 : :
11549 : : /* We should treat whole-structure mappings as if all (pointer, in this
11550 : : case) members are mapped as individual list items. Check if we have
11551 : : such a whole-structure mapping, if we don't have an explicit reference
11552 : : to the pointer member itself. */
11553 : 8062 : if (!innerp
11554 : 3318 : && TREE_CODE (base) == COMPONENT_REF
11555 : 9453 : && omp_mapped_by_containing_struct (grpmap, base, &wholestruct))
11556 : : innerp = &wholestruct;
11557 : :
11558 : 8062 : if (innerp && *innerp != grp)
11559 : : {
11560 : 5154 : for (omp_mapping_group *w = *innerp; w; w = w->sibling)
11561 : 2577 : if (!omp_tsort_mapping_groups_1 (outlist, groups, grpmap, w))
11562 : 0 : return false;
11563 : : break;
11564 : : }
11565 : :
11566 : 5485 : decl = base;
11567 : : }
11568 : :
11569 : 15099 : grp->mark = PERMANENT;
11570 : :
11571 : : /* Emit grp to output list. */
11572 : :
11573 : 15099 : **outlist = grp;
11574 : 15099 : *outlist = &grp->next;
11575 : :
11576 : 15099 : return true;
11577 : : }
11578 : :
11579 : : /* Topologically sort GROUPS, so that OMP 5.0-defined base pointers come
11580 : : before mappings that use those pointers. This is an implementation of the
11581 : : depth-first search algorithm, described e.g. at:
11582 : :
11583 : : https://en.wikipedia.org/wiki/Topological_sorting
11584 : : */
11585 : :
11586 : : static omp_mapping_group *
11587 : 7735 : omp_tsort_mapping_groups (vec<omp_mapping_group> *groups,
11588 : : hash_map<tree_operand_hash_no_se, omp_mapping_group *>
11589 : : *grpmap,
11590 : : bool enter_exit_data)
11591 : : {
11592 : 7735 : omp_mapping_group *grp, *outlist = NULL, **cursor;
11593 : 7735 : unsigned int i;
11594 : 7735 : bool saw_runtime_implicit = false;
11595 : :
11596 : 7735 : cursor = &outlist;
11597 : :
11598 : 22834 : FOR_EACH_VEC_ELT (*groups, i, grp)
11599 : : {
11600 : 15099 : if (grp->mark != PERMANENT)
11601 : : {
11602 : 14253 : if (OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11603 : : {
11604 : 238 : saw_runtime_implicit = true;
11605 : 238 : continue;
11606 : : }
11607 : 14015 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11608 : : return NULL;
11609 : : }
11610 : : }
11611 : :
11612 : 7735 : if (!saw_runtime_implicit)
11613 : 7589 : return outlist;
11614 : :
11615 : 629 : FOR_EACH_VEC_ELT (*groups, i, grp)
11616 : : {
11617 : 483 : if (grp->mark != PERMANENT
11618 : 483 : && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start))
11619 : : {
11620 : : /* Clear the flag for enter/exit data because it is currently
11621 : : meaningless for those operations in libgomp. */
11622 : 238 : if (enter_exit_data)
11623 : 41 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (*grp->grp_start) = 0;
11624 : :
11625 : 238 : if (!omp_tsort_mapping_groups_1 (&cursor, groups, grpmap, grp))
11626 : : return NULL;
11627 : : }
11628 : : }
11629 : :
11630 : 146 : return outlist;
11631 : : }
11632 : :
11633 : : /* Split INLIST into three parts:
11634 : :
11635 : : - "present" alloc/to/from groups
11636 : : - other to/from groups
11637 : : - other alloc/release/delete groups
11638 : :
11639 : : These sub-lists are then concatenated together to form the final list.
11640 : : Each sub-list retains the order of the original list.
11641 : : Note that ATTACH nodes are later moved to the end of the list in
11642 : : gimplify_adjust_omp_clauses, for target regions. */
11643 : :
11644 : : static omp_mapping_group *
11645 : 7735 : omp_segregate_mapping_groups (omp_mapping_group *inlist)
11646 : : {
11647 : 7735 : omp_mapping_group *ard_groups = NULL, *tf_groups = NULL;
11648 : 7735 : omp_mapping_group *p_groups = NULL;
11649 : 7735 : omp_mapping_group **ard_tail = &ard_groups, **tf_tail = &tf_groups;
11650 : 7735 : omp_mapping_group **p_tail = &p_groups;
11651 : :
11652 : 22834 : for (omp_mapping_group *w = inlist; w;)
11653 : : {
11654 : 15099 : tree c = *w->grp_start;
11655 : 15099 : omp_mapping_group *next = w->next;
11656 : :
11657 : 15099 : gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP);
11658 : :
11659 : 15099 : switch (OMP_CLAUSE_MAP_KIND (c))
11660 : : {
11661 : 1673 : case GOMP_MAP_ALLOC:
11662 : 1673 : case GOMP_MAP_RELEASE:
11663 : 1673 : case GOMP_MAP_DELETE:
11664 : 1673 : *ard_tail = w;
11665 : 1673 : w->next = NULL;
11666 : 1673 : ard_tail = &w->next;
11667 : 1673 : break;
11668 : :
11669 : : /* These map types are all semantically identical, so are moved into a
11670 : : single group. They will each be changed into GOMP_MAP_FORCE_PRESENT
11671 : : in gimplify_adjust_omp_clauses. */
11672 : 123 : case GOMP_MAP_PRESENT_ALLOC:
11673 : 123 : case GOMP_MAP_PRESENT_FROM:
11674 : 123 : case GOMP_MAP_PRESENT_TO:
11675 : 123 : case GOMP_MAP_PRESENT_TOFROM:
11676 : 123 : *p_tail = w;
11677 : 123 : w->next = NULL;
11678 : 123 : p_tail = &w->next;
11679 : 123 : break;
11680 : :
11681 : 13303 : default:
11682 : 13303 : *tf_tail = w;
11683 : 13303 : w->next = NULL;
11684 : 13303 : tf_tail = &w->next;
11685 : : }
11686 : :
11687 : : w = next;
11688 : : }
11689 : :
11690 : : /* Now splice the lists together... */
11691 : 7735 : *tf_tail = ard_groups;
11692 : 7735 : *p_tail = tf_groups;
11693 : :
11694 : 7735 : return p_groups;
11695 : : }
11696 : :
11697 : : /* Given a list LIST_P containing groups of mappings given by GROUPS, reorder
11698 : : those groups based on the output list of omp_tsort_mapping_groups --
11699 : : singly-linked, threaded through each element's NEXT pointer starting at
11700 : : HEAD. Each list element appears exactly once in that linked list.
11701 : :
11702 : : Each element of GROUPS may correspond to one or several mapping nodes.
11703 : : Node groups are kept together, and in the reordered list, the positions of
11704 : : the original groups are reused for the positions of the reordered list.
11705 : : Hence if we have e.g.
11706 : :
11707 : : {to ptr ptr} firstprivate {tofrom ptr} ...
11708 : : ^ ^ ^
11709 : : first group non-"map" second group
11710 : :
11711 : : and say the second group contains a base pointer for the first so must be
11712 : : moved before it, the resulting list will contain:
11713 : :
11714 : : {tofrom ptr} firstprivate {to ptr ptr} ...
11715 : : ^ prev. second group ^ prev. first group
11716 : : */
11717 : :
11718 : : static tree *
11719 : 7735 : omp_reorder_mapping_groups (vec<omp_mapping_group> *groups,
11720 : : omp_mapping_group *head,
11721 : : tree *list_p)
11722 : : {
11723 : 7735 : omp_mapping_group *grp;
11724 : 7735 : unsigned int i;
11725 : 7735 : unsigned numgroups = groups->length ();
11726 : 7735 : auto_vec<tree> old_heads (numgroups);
11727 : 7735 : auto_vec<tree *> old_headps (numgroups);
11728 : 7735 : auto_vec<tree> new_heads (numgroups);
11729 : 7735 : auto_vec<tree> old_succs (numgroups);
11730 : 7735 : bool map_at_start = (list_p == (*groups)[0].grp_start);
11731 : :
11732 : 7735 : tree *new_grp_tail = NULL;
11733 : :
11734 : : /* Stash the start & end nodes of each mapping group before we start
11735 : : modifying the list. */
11736 : 22834 : FOR_EACH_VEC_ELT (*groups, i, grp)
11737 : : {
11738 : 15099 : old_headps.quick_push (grp->grp_start);
11739 : 15099 : old_heads.quick_push (*grp->grp_start);
11740 : 15099 : old_succs.quick_push (OMP_CLAUSE_CHAIN (grp->grp_end));
11741 : : }
11742 : :
11743 : : /* And similarly, the heads of the groups in the order we want to rearrange
11744 : : the list to. */
11745 : 22834 : for (omp_mapping_group *w = head; w; w = w->next)
11746 : 15099 : new_heads.quick_push (*w->grp_start);
11747 : :
11748 : 22834 : FOR_EACH_VEC_ELT (*groups, i, grp)
11749 : : {
11750 : 15099 : gcc_assert (head);
11751 : :
11752 : 15099 : if (new_grp_tail && old_succs[i - 1] == old_heads[i])
11753 : : {
11754 : : /* a {b c d} {e f g} h i j (original)
11755 : : -->
11756 : : a {k l m} {e f g} h i j (inserted new group on last iter)
11757 : : -->
11758 : : a {k l m} {n o p} h i j (this time, chain last group to new one)
11759 : : ^new_grp_tail
11760 : : */
11761 : 6742 : *new_grp_tail = new_heads[i];
11762 : : }
11763 : 8357 : else if (new_grp_tail)
11764 : : {
11765 : : /* a {b c d} e {f g h} i j k (original)
11766 : : -->
11767 : : a {l m n} e {f g h} i j k (gap after last iter's group)
11768 : : -->
11769 : : a {l m n} e {o p q} h i j (chain last group to old successor)
11770 : : ^new_grp_tail
11771 : : */
11772 : 622 : *new_grp_tail = old_succs[i - 1];
11773 : 622 : *old_headps[i] = new_heads[i];
11774 : : }
11775 : : else
11776 : : {
11777 : : /* The first inserted group -- point to new group, and leave end
11778 : : open.
11779 : : a {b c d} e f
11780 : : -->
11781 : : a {g h i...
11782 : : */
11783 : 7735 : *grp->grp_start = new_heads[i];
11784 : : }
11785 : :
11786 : 15099 : new_grp_tail = &OMP_CLAUSE_CHAIN (head->grp_end);
11787 : :
11788 : 15099 : head = head->next;
11789 : : }
11790 : :
11791 : 7735 : if (new_grp_tail)
11792 : 7735 : *new_grp_tail = old_succs[numgroups - 1];
11793 : :
11794 : 7735 : gcc_assert (!head);
11795 : :
11796 : 10821 : return map_at_start ? (*groups)[0].grp_start : list_p;
11797 : 7735 : }
11798 : :
11799 : : /* DECL is supposed to have lastprivate semantics in the outer contexts
11800 : : of combined/composite constructs, starting with OCTX.
11801 : : Add needed lastprivate, shared or map clause if no data sharing or
11802 : : mapping clause are present. IMPLICIT_P is true if it is an implicit
11803 : : clause (IV on simd), in which case the lastprivate will not be
11804 : : copied to some constructs. */
11805 : :
11806 : : static void
11807 : 14648 : omp_lastprivate_for_combined_outer_constructs (struct gimplify_omp_ctx *octx,
11808 : : tree decl, bool implicit_p)
11809 : : {
11810 : 14648 : struct gimplify_omp_ctx *orig_octx = octx;
11811 : 26969 : for (; octx; octx = octx->outer_context)
11812 : : {
11813 : 25900 : if ((octx->region_type == ORT_COMBINED_PARALLEL
11814 : 20864 : || (octx->region_type & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS)
11815 : 25331 : && splay_tree_lookup (octx->variables,
11816 : : (splay_tree_key) decl) == NULL)
11817 : : {
11818 : 3887 : omp_add_variable (octx, decl, GOVD_SHARED | GOVD_SEEN);
11819 : 3887 : continue;
11820 : : }
11821 : 18374 : if ((octx->region_type & ORT_TASK) != 0
11822 : 575 : && octx->combined_loop
11823 : 18655 : && splay_tree_lookup (octx->variables,
11824 : : (splay_tree_key) decl) == NULL)
11825 : : {
11826 : 248 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11827 : 248 : continue;
11828 : : }
11829 : 22710 : if (implicit_p
11830 : 13619 : && octx->region_type == ORT_WORKSHARE
11831 : 10405 : && octx->combined_loop
11832 : 10300 : && splay_tree_lookup (octx->variables,
11833 : : (splay_tree_key) decl) == NULL
11834 : 10300 : && octx->outer_context
11835 : 8907 : && octx->outer_context->region_type == ORT_COMBINED_PARALLEL
11836 : 22717 : && splay_tree_lookup (octx->outer_context->variables,
11837 : : (splay_tree_key) decl) == NULL)
11838 : : {
11839 : 4832 : octx = octx->outer_context;
11840 : 4832 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11841 : 4832 : continue;
11842 : : }
11843 : 5564 : if ((octx->region_type == ORT_WORKSHARE || octx->region_type == ORT_ACC)
11844 : 7482 : && octx->combined_loop
11845 : 7295 : && splay_tree_lookup (octx->variables,
11846 : : (splay_tree_key) decl) == NULL
11847 : 19071 : && !omp_check_private (octx, decl, false))
11848 : : {
11849 : 3354 : omp_add_variable (octx, decl, GOVD_LASTPRIVATE | GOVD_SEEN);
11850 : 3354 : continue;
11851 : : }
11852 : 9692 : if (octx->region_type == ORT_COMBINED_TARGET)
11853 : : {
11854 : 2008 : splay_tree_node n = splay_tree_lookup (octx->variables,
11855 : : (splay_tree_key) decl);
11856 : 2008 : if (n == NULL)
11857 : : {
11858 : 1986 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11859 : 1986 : octx = octx->outer_context;
11860 : : }
11861 : 22 : else if (!implicit_p
11862 : 22 : && (n->value & GOVD_FIRSTPRIVATE_IMPLICIT))
11863 : : {
11864 : 12 : n->value &= ~(GOVD_FIRSTPRIVATE
11865 : : | GOVD_FIRSTPRIVATE_IMPLICIT
11866 : : | GOVD_EXPLICIT);
11867 : 12 : omp_add_variable (octx, decl, GOVD_MAP | GOVD_SEEN);
11868 : 12 : octx = octx->outer_context;
11869 : : }
11870 : : }
11871 : : break;
11872 : : }
11873 : 14648 : if (octx && (implicit_p || octx != orig_octx))
11874 : 4046 : omp_notice_variable (octx, decl, true);
11875 : 14648 : }
11876 : :
11877 : : /* We might have indexed several groups for DECL, e.g. a "TO" mapping and also
11878 : : a "FIRSTPRIVATE" mapping. Return the one that isn't firstprivate, etc. */
11879 : :
11880 : : static omp_mapping_group *
11881 : 5313 : omp_get_nonfirstprivate_group (hash_map<tree_operand_hash_no_se,
11882 : : omp_mapping_group *> *grpmap,
11883 : : tree decl, bool allow_deleted = false)
11884 : : {
11885 : 5313 : omp_mapping_group **to_group_p = grpmap->get (decl);
11886 : :
11887 : 5313 : if (!to_group_p)
11888 : : return NULL;
11889 : :
11890 : 2335 : omp_mapping_group *to_group = *to_group_p;
11891 : :
11892 : 3566 : for (; to_group; to_group = to_group->sibling)
11893 : : {
11894 : 2372 : tree grp_end = to_group->grp_end;
11895 : 2372 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
11896 : : {
11897 : : case GOMP_MAP_FIRSTPRIVATE_POINTER:
11898 : : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
11899 : : break;
11900 : :
11901 : 1143 : default:
11902 : 1143 : if (allow_deleted || !to_group->deleted)
11903 : : return to_group;
11904 : : }
11905 : : }
11906 : :
11907 : : return NULL;
11908 : : }
11909 : :
11910 : : /* Return TRUE if the directive (whose clauses are described by the hash table
11911 : : of mapping groups, GRPMAP) maps DECL explicitly. If TO_SPECIFICALLY is
11912 : : true, only count TO mappings. If ALLOW_DELETED is true, ignore the
11913 : : "deleted" flag for groups. If CONTAINED_IN_STRUCT is true, also return
11914 : : TRUE if DECL is mapped as a member of a whole-struct mapping. */
11915 : :
11916 : : static bool
11917 : 3881 : omp_directive_maps_explicitly (hash_map<tree_operand_hash_no_se,
11918 : : omp_mapping_group *> *grpmap,
11919 : : tree decl, omp_mapping_group **base_group,
11920 : : bool to_specifically, bool allow_deleted,
11921 : : bool contained_in_struct)
11922 : : {
11923 : 3881 : omp_mapping_group *decl_group
11924 : 3881 : = omp_get_nonfirstprivate_group (grpmap, decl, allow_deleted);
11925 : :
11926 : 3881 : *base_group = NULL;
11927 : :
11928 : 3881 : if (decl_group)
11929 : : {
11930 : 1024 : tree grp_first = *decl_group->grp_start;
11931 : : /* We might be called during omp_build_struct_sibling_lists, when
11932 : : GOMP_MAP_STRUCT might have been inserted at the start of the group.
11933 : : Skip over that, and also possibly the node after it. */
11934 : 1024 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT
11935 : 1024 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_STRUCT_UNORD)
11936 : : {
11937 : 6 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11938 : 6 : if (OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_FIRSTPRIVATE_POINTER
11939 : 6 : || (OMP_CLAUSE_MAP_KIND (grp_first)
11940 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
11941 : 12 : || OMP_CLAUSE_MAP_KIND (grp_first) == GOMP_MAP_ATTACH_DETACH)
11942 : 0 : grp_first = OMP_CLAUSE_CHAIN (grp_first);
11943 : : }
11944 : 1024 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
11945 : 1024 : if (!to_specifically
11946 : 574 : || GOMP_MAP_COPY_TO_P (first_kind)
11947 : 365 : || first_kind == GOMP_MAP_ALLOC)
11948 : : {
11949 : 959 : *base_group = decl_group;
11950 : 959 : return true;
11951 : : }
11952 : : }
11953 : :
11954 : 2922 : if (contained_in_struct
11955 : 2922 : && omp_mapped_by_containing_struct (grpmap, decl, base_group))
11956 : : return true;
11957 : :
11958 : : return false;
11959 : : }
11960 : :
11961 : : /* If we have mappings INNER and OUTER, where INNER is a component access and
11962 : : OUTER is a mapping of the whole containing struct, check that the mappings
11963 : : are compatible. We'll be deleting the inner mapping, so we need to make
11964 : : sure the outer mapping does (at least) the same transfers to/from the device
11965 : : as the inner mapping. */
11966 : :
11967 : : bool
11968 : 172 : omp_check_mapping_compatibility (location_t loc,
11969 : : omp_mapping_group *outer,
11970 : : omp_mapping_group *inner)
11971 : : {
11972 : 172 : tree first_outer = *outer->grp_start, first_inner = *inner->grp_start;
11973 : :
11974 : 172 : gcc_assert (OMP_CLAUSE_CODE (first_outer) == OMP_CLAUSE_MAP);
11975 : 172 : gcc_assert (OMP_CLAUSE_CODE (first_inner) == OMP_CLAUSE_MAP);
11976 : :
11977 : 172 : enum gomp_map_kind outer_kind = OMP_CLAUSE_MAP_KIND (first_outer);
11978 : 172 : enum gomp_map_kind inner_kind = OMP_CLAUSE_MAP_KIND (first_inner);
11979 : :
11980 : 172 : if (outer_kind == inner_kind)
11981 : : return true;
11982 : :
11983 : 70 : switch (outer_kind)
11984 : : {
11985 : 0 : case GOMP_MAP_ALWAYS_TO:
11986 : 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11987 : 0 : || inner_kind == GOMP_MAP_ALLOC
11988 : 0 : || inner_kind == GOMP_MAP_TO)
11989 : : return true;
11990 : : break;
11991 : :
11992 : 0 : case GOMP_MAP_ALWAYS_FROM:
11993 : 0 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
11994 : 0 : || inner_kind == GOMP_MAP_RELEASE
11995 : : || inner_kind == GOMP_MAP_FROM)
11996 : : return true;
11997 : : break;
11998 : :
11999 : 10 : case GOMP_MAP_TO:
12000 : 10 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
12001 : 10 : || inner_kind == GOMP_MAP_ALLOC)
12002 : : return true;
12003 : : break;
12004 : :
12005 : 8 : case GOMP_MAP_FROM:
12006 : 8 : if (inner_kind == GOMP_MAP_RELEASE
12007 : 8 : || inner_kind == GOMP_MAP_FORCE_PRESENT)
12008 : : return true;
12009 : : break;
12010 : :
12011 : 32 : case GOMP_MAP_ALWAYS_TOFROM:
12012 : 32 : case GOMP_MAP_TOFROM:
12013 : 32 : if (inner_kind == GOMP_MAP_FORCE_PRESENT
12014 : 32 : || inner_kind == GOMP_MAP_ALLOC
12015 : : || inner_kind == GOMP_MAP_TO
12016 : 24 : || inner_kind == GOMP_MAP_FROM
12017 : 12 : || inner_kind == GOMP_MAP_TOFROM)
12018 : : return true;
12019 : : break;
12020 : :
12021 : 28 : default:
12022 : 28 : ;
12023 : : }
12024 : :
12025 : 84 : error_at (loc, "data movement for component %qE is not compatible with "
12026 : 28 : "movement for struct %qE", OMP_CLAUSE_DECL (first_inner),
12027 : 28 : OMP_CLAUSE_DECL (first_outer));
12028 : :
12029 : 28 : return false;
12030 : : }
12031 : :
12032 : : /* This function handles several cases where clauses on a mapping directive
12033 : : can interact with each other.
12034 : :
12035 : : If we have a FIRSTPRIVATE_POINTER node and we're also mapping the pointer
12036 : : on the same directive, change the mapping of the first node to
12037 : : ATTACH_DETACH. We should have detected that this will happen already in
12038 : : c-omp.cc:c_omp_adjust_map_clauses and marked the appropriate decl
12039 : : as addressable. (If we didn't, bail out.)
12040 : :
12041 : : If we have a FIRSTPRIVATE_REFERENCE (for a reference to pointer) and we're
12042 : : mapping the base pointer also, we may need to change the mapping type to
12043 : : ATTACH_DETACH and synthesize an alloc node for the reference itself.
12044 : :
12045 : : If we have an ATTACH_DETACH node, this is an array section with a pointer
12046 : : base. If we're mapping the base on the same directive too, we can drop its
12047 : : mapping. However, if we have a reference to pointer, make other appropriate
12048 : : adjustments to the mapping nodes instead.
12049 : :
12050 : : If we have an ATTACH_DETACH node with a Fortran pointer-set (array
12051 : : descriptor) mapping for a derived-type component, and we're also mapping the
12052 : : whole of the derived-type variable on another clause, the pointer-set
12053 : : mapping is removed.
12054 : :
12055 : : If we have a component access but we're also mapping the whole of the
12056 : : containing struct, drop the former access.
12057 : :
12058 : : If the expression is a component access, and we're also mapping a base
12059 : : pointer used in that component access in the same expression, change the
12060 : : mapping type of the latter to ALLOC (ready for processing by
12061 : : omp_build_struct_sibling_lists). */
12062 : :
12063 : : void
12064 : 7735 : omp_resolve_clause_dependencies (enum tree_code code,
12065 : : vec<omp_mapping_group> *groups,
12066 : : hash_map<tree_operand_hash_no_se,
12067 : : omp_mapping_group *> *grpmap)
12068 : : {
12069 : 7735 : int i;
12070 : 7735 : omp_mapping_group *grp;
12071 : 7735 : bool repair_chain = false;
12072 : :
12073 : 21989 : FOR_EACH_VEC_ELT (*groups, i, grp)
12074 : : {
12075 : 14254 : tree grp_end = grp->grp_end;
12076 : 14254 : tree decl = OMP_CLAUSE_DECL (grp_end);
12077 : :
12078 : 14254 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12079 : :
12080 : 14254 : switch (OMP_CLAUSE_MAP_KIND (grp_end))
12081 : : {
12082 : 1120 : case GOMP_MAP_FIRSTPRIVATE_POINTER:
12083 : 1120 : {
12084 : 1120 : omp_mapping_group *to_group
12085 : 1120 : = omp_get_nonfirstprivate_group (grpmap, decl);
12086 : :
12087 : 1120 : if (!to_group || to_group == grp)
12088 : 1095 : continue;
12089 : :
12090 : 25 : tree grp_first = *to_group->grp_start;
12091 : 25 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12092 : :
12093 : 25 : if ((GOMP_MAP_COPY_TO_P (first_kind)
12094 : 7 : || first_kind == GOMP_MAP_ALLOC)
12095 : 50 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12096 : : != GOMP_MAP_FIRSTPRIVATE_POINTER))
12097 : : {
12098 : 25 : gcc_assert (TREE_ADDRESSABLE (OMP_CLAUSE_DECL (grp_end)));
12099 : 25 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12100 : : }
12101 : : }
12102 : : break;
12103 : :
12104 : 156 : case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
12105 : 156 : {
12106 : 156 : tree ptr = build_fold_indirect_ref (decl);
12107 : :
12108 : 156 : omp_mapping_group *to_group
12109 : 156 : = omp_get_nonfirstprivate_group (grpmap, ptr);
12110 : :
12111 : 156 : if (!to_group || to_group == grp)
12112 : 152 : continue;
12113 : :
12114 : 4 : tree grp_first = *to_group->grp_start;
12115 : 4 : enum gomp_map_kind first_kind = OMP_CLAUSE_MAP_KIND (grp_first);
12116 : :
12117 : 4 : if (GOMP_MAP_COPY_TO_P (first_kind)
12118 : 4 : || first_kind == GOMP_MAP_ALLOC)
12119 : : {
12120 : 4 : OMP_CLAUSE_SET_MAP_KIND (grp_end, GOMP_MAP_ATTACH_DETACH);
12121 : 4 : OMP_CLAUSE_DECL (grp_end) = ptr;
12122 : 4 : if ((OMP_CLAUSE_CHAIN (*to_group->grp_start)
12123 : 4 : == to_group->grp_end)
12124 : 4 : && (OMP_CLAUSE_MAP_KIND (to_group->grp_end)
12125 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
12126 : : {
12127 : 0 : gcc_assert (TREE_ADDRESSABLE
12128 : : (OMP_CLAUSE_DECL (to_group->grp_end)));
12129 : 0 : OMP_CLAUSE_SET_MAP_KIND (to_group->grp_end,
12130 : : GOMP_MAP_ATTACH_DETACH);
12131 : :
12132 : 0 : location_t loc = OMP_CLAUSE_LOCATION (to_group->grp_end);
12133 : 0 : tree alloc
12134 : 0 : = build_omp_clause (loc, OMP_CLAUSE_MAP);
12135 : 0 : OMP_CLAUSE_SET_MAP_KIND (alloc, GOMP_MAP_ALLOC);
12136 : 0 : tree tmp = build_fold_addr_expr (OMP_CLAUSE_DECL
12137 : : (to_group->grp_end));
12138 : 0 : tree char_ptr_type = build_pointer_type (char_type_node);
12139 : 0 : OMP_CLAUSE_DECL (alloc)
12140 : 0 : = build2 (MEM_REF, char_type_node,
12141 : : tmp,
12142 : : build_int_cst (char_ptr_type, 0));
12143 : 0 : OMP_CLAUSE_SIZE (alloc) = TYPE_SIZE_UNIT (TREE_TYPE (tmp));
12144 : :
12145 : 0 : OMP_CLAUSE_CHAIN (alloc)
12146 : 0 : = OMP_CLAUSE_CHAIN (*to_group->grp_start);
12147 : 0 : OMP_CLAUSE_CHAIN (*to_group->grp_start) = alloc;
12148 : : }
12149 : : }
12150 : : }
12151 : : break;
12152 : :
12153 : : case GOMP_MAP_ATTACH_DETACH:
12154 : : case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
12155 : : {
12156 : 2064 : tree base_ptr, referenced_ptr_node = NULL_TREE;
12157 : :
12158 : 2064 : while (TREE_CODE (decl) == ARRAY_REF)
12159 : 0 : decl = TREE_OPERAND (decl, 0);
12160 : :
12161 : 2064 : if (TREE_CODE (decl) == INDIRECT_REF)
12162 : 13 : decl = TREE_OPERAND (decl, 0);
12163 : :
12164 : : /* Only component accesses. */
12165 : 2064 : if (DECL_P (decl))
12166 : 217 : continue;
12167 : :
12168 : : /* We want the pointer itself when checking if the base pointer is
12169 : : mapped elsewhere in the same directive -- if we have a
12170 : : reference to the pointer, don't use that. */
12171 : :
12172 : 1847 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
12173 : 1847 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
12174 : : {
12175 : 394 : referenced_ptr_node = OMP_CLAUSE_CHAIN (*grp->grp_start);
12176 : 394 : base_ptr = OMP_CLAUSE_DECL (referenced_ptr_node);
12177 : : }
12178 : : else
12179 : : base_ptr = decl;
12180 : :
12181 : 1669 : gomp_map_kind zlas_kind
12182 : 1847 : = (code == OACC_EXIT_DATA || code == OMP_TARGET_EXIT_DATA)
12183 : 1847 : ? GOMP_MAP_DETACH : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION;
12184 : :
12185 : 1847 : if (TREE_CODE (TREE_TYPE (base_ptr)) == POINTER_TYPE)
12186 : : {
12187 : : /* If we map the base TO, and we're doing an attachment, we can
12188 : : skip the TO mapping altogether and create an ALLOC mapping
12189 : : instead, since the attachment will overwrite the device
12190 : : pointer in that location immediately anyway. Otherwise,
12191 : : change our mapping to
12192 : : GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION in case the
12193 : : attachment target has not been copied to the device already
12194 : : by some earlier directive. */
12195 : :
12196 : 1423 : bool base_mapped_to = false;
12197 : :
12198 : 1423 : omp_mapping_group *base_group;
12199 : :
12200 : 1423 : if (omp_directive_maps_explicitly (grpmap, base_ptr,
12201 : : &base_group, false, true,
12202 : : false))
12203 : : {
12204 : 450 : if (referenced_ptr_node)
12205 : : {
12206 : 129 : base_mapped_to = true;
12207 : 129 : if ((OMP_CLAUSE_MAP_KIND (base_group->grp_end)
12208 : : == GOMP_MAP_ATTACH_DETACH)
12209 : 129 : && (OMP_CLAUSE_CHAIN (*base_group->grp_start)
12210 : : == base_group->grp_end))
12211 : : {
12212 : 258 : OMP_CLAUSE_CHAIN (*base_group->grp_start)
12213 : 129 : = OMP_CLAUSE_CHAIN (base_group->grp_end);
12214 : 129 : base_group->grp_end = *base_group->grp_start;
12215 : 129 : repair_chain = true;
12216 : : }
12217 : : }
12218 : : else
12219 : : {
12220 : 321 : base_group->deleted = true;
12221 : 321 : OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end) = 1;
12222 : : }
12223 : : }
12224 : :
12225 : : /* We're dealing with a reference to a pointer, and we are
12226 : : attaching both the reference and the pointer. We know the
12227 : : reference itself is on the target, because we are going to
12228 : : create an ALLOC node for it in accumulate_sibling_list. The
12229 : : pointer might be on the target already or it might not, but
12230 : : if it isn't then it's not an error, so use
12231 : : GOMP_MAP_ATTACH_ZLAS for it. */
12232 : 1423 : if (!base_mapped_to && referenced_ptr_node)
12233 : 56 : OMP_CLAUSE_SET_MAP_KIND (referenced_ptr_node, zlas_kind);
12234 : :
12235 : 1423 : omp_mapping_group *struct_group;
12236 : 1423 : tree desc;
12237 : 1423 : if ((desc = OMP_CLAUSE_CHAIN (*grp->grp_start))
12238 : 1423 : && omp_map_clause_descriptor_p (desc)
12239 : 2017 : && omp_mapped_by_containing_struct (grpmap, decl,
12240 : : &struct_group))
12241 : : /* If we have a pointer set but we're mapping (or unmapping)
12242 : : the whole of the containing struct, we can remove the
12243 : : pointer set mapping. */
12244 : 15 : OMP_CLAUSE_CHAIN (*grp->grp_start) = OMP_CLAUSE_CHAIN (desc);
12245 : : }
12246 : 424 : else if (TREE_CODE (TREE_TYPE (base_ptr)) == REFERENCE_TYPE
12247 : 424 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (base_ptr)))
12248 : : == ARRAY_TYPE)
12249 : 562 : && OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION
12250 : : (*grp->grp_start))
12251 : 92 : OMP_CLAUSE_SET_MAP_KIND (grp->grp_end, zlas_kind);
12252 : : }
12253 : : break;
12254 : :
12255 : : case GOMP_MAP_ATTACH:
12256 : : /* Ignore standalone attach here. */
12257 : : break;
12258 : :
12259 : 10851 : default:
12260 : 10851 : {
12261 : 10851 : omp_mapping_group *struct_group;
12262 : 10851 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12263 : 10851 : && *grp->grp_start == grp_end)
12264 : : {
12265 : 94 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12266 : : struct_group, grp);
12267 : : /* Remove the whole of this mapping -- redundant. */
12268 : 94 : grp->deleted = true;
12269 : : }
12270 : :
12271 : : tree base = decl;
12272 : 12443 : while ((base = omp_get_base_pointer (base)))
12273 : : {
12274 : 1592 : omp_mapping_group *base_group;
12275 : :
12276 : 1592 : if (omp_directive_maps_explicitly (grpmap, base, &base_group,
12277 : : true, true, false))
12278 : : {
12279 : 342 : tree grp_first = *base_group->grp_start;
12280 : 342 : OMP_CLAUSE_SET_MAP_KIND (grp_first, GOMP_MAP_ALLOC);
12281 : : }
12282 : : }
12283 : : }
12284 : : }
12285 : : }
12286 : :
12287 : 7735 : if (repair_chain)
12288 : : {
12289 : : /* Group start pointers may have become detached from the
12290 : : OMP_CLAUSE_CHAIN of previous groups if elements were removed from the
12291 : : end of those groups. Fix that now. */
12292 : : tree *new_next = NULL;
12293 : 716 : FOR_EACH_VEC_ELT (*groups, i, grp)
12294 : : {
12295 : 587 : if (new_next)
12296 : 458 : grp->grp_start = new_next;
12297 : :
12298 : 587 : new_next = &OMP_CLAUSE_CHAIN (grp->grp_end);
12299 : : }
12300 : : }
12301 : 7735 : }
12302 : :
12303 : : /* Similar to omp_resolve_clause_dependencies, but for OpenACC. The only
12304 : : clause dependencies we handle for now are struct element mappings and
12305 : : whole-struct mappings on the same directive, and duplicate clause
12306 : : detection. */
12307 : :
12308 : : void
12309 : 9457 : oacc_resolve_clause_dependencies (vec<omp_mapping_group> *groups,
12310 : : hash_map<tree_operand_hash_no_se,
12311 : : omp_mapping_group *> *grpmap)
12312 : : {
12313 : 9457 : int i;
12314 : 9457 : omp_mapping_group *grp;
12315 : 9457 : hash_set<tree_operand_hash> *seen_components = NULL;
12316 : 9457 : hash_set<tree_operand_hash> *shown_error = NULL;
12317 : :
12318 : 24629 : FOR_EACH_VEC_ELT (*groups, i, grp)
12319 : : {
12320 : 15172 : tree grp_end = grp->grp_end;
12321 : 15172 : tree decl = OMP_CLAUSE_DECL (grp_end);
12322 : :
12323 : 15172 : gcc_assert (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP);
12324 : :
12325 : 15172 : if (DECL_P (grp_end))
12326 : 14655 : continue;
12327 : :
12328 : 15172 : tree c = OMP_CLAUSE_DECL (*grp->grp_start);
12329 : 16797 : while (TREE_CODE (c) == ARRAY_REF)
12330 : 1625 : c = TREE_OPERAND (c, 0);
12331 : 15172 : if (TREE_CODE (c) != COMPONENT_REF)
12332 : 14655 : continue;
12333 : 517 : if (!seen_components)
12334 : 474 : seen_components = new hash_set<tree_operand_hash> ();
12335 : 517 : if (!shown_error)
12336 : 474 : shown_error = new hash_set<tree_operand_hash> ();
12337 : 517 : if (seen_components->contains (c)
12338 : 517 : && !shown_error->contains (c))
12339 : : {
12340 : 10 : error_at (OMP_CLAUSE_LOCATION (grp_end),
12341 : : "%qE appears more than once in map clauses",
12342 : 5 : OMP_CLAUSE_DECL (grp_end));
12343 : 5 : shown_error->add (c);
12344 : : }
12345 : : else
12346 : 512 : seen_components->add (c);
12347 : :
12348 : 517 : omp_mapping_group *struct_group;
12349 : 517 : if (omp_mapped_by_containing_struct (grpmap, decl, &struct_group)
12350 : 517 : && *grp->grp_start == grp_end)
12351 : : {
12352 : 78 : omp_check_mapping_compatibility (OMP_CLAUSE_LOCATION (grp_end),
12353 : : struct_group, grp);
12354 : : /* Remove the whole of this mapping -- redundant. */
12355 : 78 : grp->deleted = true;
12356 : : }
12357 : : }
12358 : :
12359 : 9457 : if (seen_components)
12360 : 474 : delete seen_components;
12361 : 9457 : if (shown_error)
12362 : 474 : delete shown_error;
12363 : 9457 : }
12364 : :
12365 : : /* Link node NEWNODE so it is pointed to by chain INSERT_AT. NEWNODE's chain
12366 : : is linked to the previous node pointed to by INSERT_AT. */
12367 : :
12368 : : static tree *
12369 : 1076 : omp_siblist_insert_node_after (tree newnode, tree *insert_at)
12370 : : {
12371 : 1076 : OMP_CLAUSE_CHAIN (newnode) = *insert_at;
12372 : 1076 : *insert_at = newnode;
12373 : 1076 : return &OMP_CLAUSE_CHAIN (newnode);
12374 : : }
12375 : :
12376 : : /* Move NODE (which is currently pointed to by the chain OLD_POS) so it is
12377 : : pointed to by chain MOVE_AFTER instead. */
12378 : :
12379 : : static void
12380 : 863 : omp_siblist_move_node_after (tree node, tree *old_pos, tree *move_after)
12381 : : {
12382 : 863 : gcc_assert (node == *old_pos);
12383 : 863 : *old_pos = OMP_CLAUSE_CHAIN (node);
12384 : 863 : OMP_CLAUSE_CHAIN (node) = *move_after;
12385 : 863 : *move_after = node;
12386 : 863 : }
12387 : :
12388 : : /* Move nodes from FIRST_PTR (pointed to by previous node's chain) to
12389 : : LAST_NODE to after MOVE_AFTER chain. Similar to below function, but no
12390 : : new nodes are prepended to the list before splicing into the new position.
12391 : : Return the position we should continue scanning the list at, or NULL to
12392 : : stay where we were. */
12393 : :
12394 : : static tree *
12395 : 254 : omp_siblist_move_nodes_after (tree *first_ptr, tree last_node,
12396 : : tree *move_after)
12397 : : {
12398 : 254 : if (first_ptr == move_after)
12399 : : return NULL;
12400 : :
12401 : 243 : tree tmp = *first_ptr;
12402 : 243 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12403 : 243 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12404 : 243 : *move_after = tmp;
12405 : :
12406 : 243 : return first_ptr;
12407 : : }
12408 : :
12409 : : /* Concatenate two lists described by [FIRST_NEW, LAST_NEW_TAIL] and
12410 : : [FIRST_PTR, LAST_NODE], and insert them in the OMP clause list after chain
12411 : : pointer MOVE_AFTER.
12412 : :
12413 : : The latter list was previously part of the OMP clause list, and the former
12414 : : (prepended) part is comprised of new nodes.
12415 : :
12416 : : We start with a list of nodes starting with a struct mapping node. We
12417 : : rearrange the list so that new nodes starting from FIRST_NEW and whose last
12418 : : node's chain is LAST_NEW_TAIL comes directly after MOVE_AFTER, followed by
12419 : : the group of mapping nodes we are currently processing (from the chain
12420 : : FIRST_PTR to LAST_NODE). The return value is the pointer to the next chain
12421 : : we should continue processing from, or NULL to stay where we were.
12422 : :
12423 : : The transformation (in the case where MOVE_AFTER and FIRST_PTR are
12424 : : different) is worked through below. Here we are processing LAST_NODE, and
12425 : : FIRST_PTR points at the preceding mapping clause:
12426 : :
12427 : : #. mapping node chain
12428 : : ---------------------------------------------------
12429 : : A. struct_node [->B]
12430 : : B. comp_1 [->C]
12431 : : C. comp_2 [->D (move_after)]
12432 : : D. map_to_3 [->E]
12433 : : E. attach_3 [->F (first_ptr)]
12434 : : F. map_to_4 [->G (continue_at)]
12435 : : G. attach_4 (last_node) [->H]
12436 : : H. ...
12437 : :
12438 : : *last_new_tail = *first_ptr;
12439 : :
12440 : : I. new_node (first_new) [->F (last_new_tail)]
12441 : :
12442 : : *first_ptr = OMP_CLAUSE_CHAIN (last_node)
12443 : :
12444 : : #. mapping node chain
12445 : : ----------------------------------------------------
12446 : : A. struct_node [->B]
12447 : : B. comp_1 [->C]
12448 : : C. comp_2 [->D (move_after)]
12449 : : D. map_to_3 [->E]
12450 : : E. attach_3 [->H (first_ptr)]
12451 : : F. map_to_4 [->G (continue_at)]
12452 : : G. attach_4 (last_node) [->H]
12453 : : H. ...
12454 : :
12455 : : I. new_node (first_new) [->F (last_new_tail)]
12456 : :
12457 : : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12458 : :
12459 : : #. mapping node chain
12460 : : ---------------------------------------------------
12461 : : A. struct_node [->B]
12462 : : B. comp_1 [->C]
12463 : : C. comp_2 [->D (move_after)]
12464 : : D. map_to_3 [->E]
12465 : : E. attach_3 [->H (continue_at)]
12466 : : F. map_to_4 [->G]
12467 : : G. attach_4 (last_node) [->D]
12468 : : H. ...
12469 : :
12470 : : I. new_node (first_new) [->F (last_new_tail)]
12471 : :
12472 : : *move_after = first_new;
12473 : :
12474 : : #. mapping node chain
12475 : : ---------------------------------------------------
12476 : : A. struct_node [->B]
12477 : : B. comp_1 [->C]
12478 : : C. comp_2 [->I (move_after)]
12479 : : D. map_to_3 [->E]
12480 : : E. attach_3 [->H (continue_at)]
12481 : : F. map_to_4 [->G]
12482 : : G. attach_4 (last_node) [->D]
12483 : : H. ...
12484 : : I. new_node (first_new) [->F (last_new_tail)]
12485 : :
12486 : : or, in order:
12487 : :
12488 : : #. mapping node chain
12489 : : ---------------------------------------------------
12490 : : A. struct_node [->B]
12491 : : B. comp_1 [->C]
12492 : : C. comp_2 [->I (move_after)]
12493 : : I. new_node (first_new) [->F (last_new_tail)]
12494 : : F. map_to_4 [->G]
12495 : : G. attach_4 (last_node) [->D]
12496 : : D. map_to_3 [->E]
12497 : : E. attach_3 [->H (continue_at)]
12498 : : H. ...
12499 : : */
12500 : :
12501 : : static tree *
12502 : 71 : omp_siblist_move_concat_nodes_after (tree first_new, tree *last_new_tail,
12503 : : tree *first_ptr, tree last_node,
12504 : : tree *move_after)
12505 : : {
12506 : 71 : tree *continue_at = NULL;
12507 : 71 : *last_new_tail = *first_ptr;
12508 : 71 : if (first_ptr == move_after)
12509 : 12 : *move_after = first_new;
12510 : : else
12511 : : {
12512 : 59 : *first_ptr = OMP_CLAUSE_CHAIN (last_node);
12513 : 59 : continue_at = first_ptr;
12514 : 59 : OMP_CLAUSE_CHAIN (last_node) = *move_after;
12515 : 59 : *move_after = first_new;
12516 : : }
12517 : 71 : return continue_at;
12518 : : }
12519 : :
12520 : : static omp_addr_token *
12521 : 10049 : omp_first_chained_access_token (vec<omp_addr_token *> &addr_tokens)
12522 : : {
12523 : 10049 : using namespace omp_addr_tokenizer;
12524 : 10049 : int idx = addr_tokens.length () - 1;
12525 : 10049 : gcc_assert (idx >= 0);
12526 : 10049 : if (addr_tokens[idx]->type != ACCESS_METHOD)
12527 : : return addr_tokens[idx];
12528 : 10076 : while (idx > 0 && addr_tokens[idx - 1]->type == ACCESS_METHOD)
12529 : : idx--;
12530 : 10049 : return addr_tokens[idx];
12531 : : }
12532 : :
12533 : : /* Mapping struct members causes an additional set of nodes to be created,
12534 : : starting with GOMP_MAP_STRUCT followed by a number of mappings equal to the
12535 : : number of members being mapped, in order of ascending position (address or
12536 : : bitwise).
12537 : :
12538 : : We scan through the list of mapping clauses, calling this function for each
12539 : : struct member mapping we find, and build up the list of mappings after the
12540 : : initial GOMP_MAP_STRUCT node. For pointer members, these will be
12541 : : newly-created ALLOC nodes. For non-pointer members, the existing mapping is
12542 : : moved into place in the sorted list.
12543 : :
12544 : : struct {
12545 : : int *a;
12546 : : int *b;
12547 : : int c;
12548 : : int *d;
12549 : : };
12550 : :
12551 : : #pragma (acc|omp directive) copy(struct.a[0:n], struct.b[0:n], struct.c,
12552 : : struct.d[0:n])
12553 : :
12554 : : GOMP_MAP_STRUCT (4)
12555 : : [GOMP_MAP_FIRSTPRIVATE_REFERENCE -- for refs to structs]
12556 : : GOMP_MAP_ALLOC (struct.a)
12557 : : GOMP_MAP_ALLOC (struct.b)
12558 : : GOMP_MAP_TO (struct.c)
12559 : : GOMP_MAP_ALLOC (struct.d)
12560 : : ...
12561 : :
12562 : : In the case where we are mapping references to pointers, or in Fortran if
12563 : : we are mapping an array with a descriptor, additional nodes may be created
12564 : : after the struct node list also.
12565 : :
12566 : : The return code is either a pointer to the next node to process (if the
12567 : : list has been rearranged), else NULL to continue with the next node in the
12568 : : original list. */
12569 : :
12570 : : static tree *
12571 : 4049 : omp_accumulate_sibling_list (enum omp_region_type region_type,
12572 : : enum tree_code code,
12573 : : hash_map<tree_operand_hash, tree>
12574 : : *&struct_map_to_clause,
12575 : : hash_map<tree_operand_hash_no_se,
12576 : : omp_mapping_group *> *group_map,
12577 : : tree *grp_start_p, tree grp_end,
12578 : : vec<omp_addr_token *> &addr_tokens, tree **inner,
12579 : : bool *fragile_p, bool reprocessing_struct,
12580 : : tree **added_tail)
12581 : : {
12582 : 4049 : using namespace omp_addr_tokenizer;
12583 : 4049 : poly_offset_int coffset;
12584 : 4049 : poly_int64 cbitpos;
12585 : 4049 : tree ocd = OMP_CLAUSE_DECL (grp_end);
12586 : 4049 : bool openmp = !(region_type & ORT_ACC);
12587 : 4049 : bool target = (region_type & ORT_TARGET) != 0;
12588 : 4049 : tree *continue_at = NULL;
12589 : :
12590 : 4362 : while (TREE_CODE (ocd) == ARRAY_REF)
12591 : 313 : ocd = TREE_OPERAND (ocd, 0);
12592 : :
12593 : 4049 : if (*fragile_p)
12594 : : {
12595 : 156 : omp_mapping_group *to_group
12596 : 156 : = omp_get_nonfirstprivate_group (group_map, ocd, true);
12597 : :
12598 : 156 : if (to_group)
12599 : : return NULL;
12600 : : }
12601 : :
12602 : 3961 : omp_addr_token *last_token = omp_first_chained_access_token (addr_tokens);
12603 : 3961 : if (last_token->type == ACCESS_METHOD)
12604 : : {
12605 : 3961 : switch (last_token->u.access_kind)
12606 : : {
12607 : 735 : case ACCESS_REF:
12608 : 735 : case ACCESS_REF_TO_POINTER:
12609 : 735 : case ACCESS_REF_TO_POINTER_OFFSET:
12610 : 735 : case ACCESS_INDEXED_REF_TO_ARRAY:
12611 : : /* We may see either a bare reference or a dereferenced
12612 : : "convert_from_reference"-like one here. Handle either way. */
12613 : 735 : if (TREE_CODE (ocd) == INDIRECT_REF)
12614 : 64 : ocd = TREE_OPERAND (ocd, 0);
12615 : 735 : gcc_assert (TREE_CODE (TREE_TYPE (ocd)) == REFERENCE_TYPE);
12616 : : break;
12617 : :
12618 : : default:
12619 : : ;
12620 : : }
12621 : : }
12622 : :
12623 : 3961 : bool variable_offset;
12624 : 3961 : tree base
12625 : 3961 : = extract_base_bit_offset (ocd, &cbitpos, &coffset, &variable_offset);
12626 : :
12627 : 3961 : int base_token;
12628 : 19977 : for (base_token = addr_tokens.length () - 1; base_token >= 0; base_token--)
12629 : : {
12630 : 16016 : if (addr_tokens[base_token]->type == ARRAY_BASE
12631 : 16016 : || addr_tokens[base_token]->type == STRUCTURE_BASE)
12632 : : break;
12633 : : }
12634 : :
12635 : : /* The two expressions in the assertion below aren't quite the same: if we
12636 : : have 'struct_base_decl access_indexed_array' for something like
12637 : : "myvar[2].x" then base will be "myvar" and addr_tokens[base_token]->expr
12638 : : will be "myvar[2]" -- the actual base of the structure.
12639 : : The former interpretation leads to a strange situation where we get
12640 : : struct(myvar) alloc(myvar[2].ptr1)
12641 : : That is, the array of structures is kind of treated as one big structure
12642 : : for the purposes of gathering sibling lists, etc. */
12643 : : /* gcc_assert (base == addr_tokens[base_token]->expr); */
12644 : :
12645 : 3961 : bool attach_detach = ((OMP_CLAUSE_MAP_KIND (grp_end)
12646 : : == GOMP_MAP_ATTACH_DETACH)
12647 : 3961 : || (OMP_CLAUSE_MAP_KIND (grp_end)
12648 : 3961 : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
12649 : 3961 : bool has_descriptor = false;
12650 : 3961 : if (OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
12651 : : {
12652 : 2421 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
12653 : 2421 : if (grp_mid && omp_map_clause_descriptor_p (grp_mid))
12654 : : has_descriptor = true;
12655 : : }
12656 : :
12657 : 3961 : if (!struct_map_to_clause || struct_map_to_clause->get (base) == NULL)
12658 : : {
12659 : 2704 : enum gomp_map_kind str_kind = GOMP_MAP_STRUCT;
12660 : :
12661 : 2704 : if (struct_map_to_clause == NULL)
12662 : 2276 : struct_map_to_clause = new hash_map<tree_operand_hash, tree>;
12663 : :
12664 : 2704 : if (variable_offset)
12665 : 108 : str_kind = GOMP_MAP_STRUCT_UNORD;
12666 : :
12667 : 2704 : tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP);
12668 : :
12669 : 2704 : OMP_CLAUSE_SET_MAP_KIND (l, str_kind);
12670 : 2704 : OMP_CLAUSE_DECL (l) = unshare_expr (base);
12671 : 2704 : OMP_CLAUSE_SIZE (l) = size_int (1);
12672 : :
12673 : 2704 : struct_map_to_clause->put (base, l);
12674 : :
12675 : : /* On first iterating through the clause list, we insert the struct node
12676 : : just before the component access node that triggers the initial
12677 : : omp_accumulate_sibling_list call for a particular sibling list (and
12678 : : it then forms the first entry in that list). When reprocessing
12679 : : struct bases that are themselves component accesses, we insert the
12680 : : struct node on an off-side list to avoid inserting the new
12681 : : GOMP_MAP_STRUCT into the middle of the old one. */
12682 : 2704 : tree *insert_node_pos = reprocessing_struct ? *added_tail : grp_start_p;
12683 : :
12684 : 2704 : if (has_descriptor)
12685 : : {
12686 : 474 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
12687 : 474 : if (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA)
12688 : 97 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
12689 : 474 : tree sc = *insert_node_pos;
12690 : 474 : OMP_CLAUSE_CHAIN (l) = desc;
12691 : 474 : OMP_CLAUSE_CHAIN (*grp_start_p) = OMP_CLAUSE_CHAIN (desc);
12692 : 474 : OMP_CLAUSE_CHAIN (desc) = sc;
12693 : 474 : *insert_node_pos = l;
12694 : : }
12695 : 2230 : else if (attach_detach)
12696 : : {
12697 : 1384 : tree extra_node;
12698 : 1384 : tree alloc_node
12699 : 1384 : = build_omp_struct_comp_nodes (code, *grp_start_p, grp_end,
12700 : : &extra_node);
12701 : 1384 : tree *tail;
12702 : 1384 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12703 : :
12704 : 1384 : if (extra_node)
12705 : : {
12706 : 0 : OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos;
12707 : 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
12708 : 0 : tail = &OMP_CLAUSE_CHAIN (extra_node);
12709 : : }
12710 : : else
12711 : : {
12712 : 1384 : OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos;
12713 : 1384 : tail = &OMP_CLAUSE_CHAIN (alloc_node);
12714 : : }
12715 : :
12716 : : /* For OpenMP semantics, we don't want to implicitly allocate
12717 : : space for the pointer here for non-compute regions (e.g. "enter
12718 : : data"). A FRAGILE_P node is only being created so that
12719 : : omp-low.cc is able to rewrite the struct properly.
12720 : : For references (to pointers), we want to actually allocate the
12721 : : space for the reference itself in the sorted list following the
12722 : : struct node.
12723 : : For pointers, we want to allocate space if we had an explicit
12724 : : mapping of the attachment point, but not otherwise. */
12725 : 1384 : if (*fragile_p
12726 : 1384 : || (openmp
12727 : : && !target
12728 : : && attach_detach
12729 : 222 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
12730 : 76 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
12731 : : {
12732 : 121 : if (!lang_GNU_Fortran ())
12733 : : /* In Fortran, pointers are dereferenced automatically, but may
12734 : : be unassociated. So we still want to allocate space for the
12735 : : pointer (as the base for an attach operation that should be
12736 : : present in the same directive's clause list also). */
12737 : 103 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
12738 : 121 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
12739 : : }
12740 : :
12741 : 1384 : *insert_node_pos = l;
12742 : :
12743 : 1384 : if (reprocessing_struct)
12744 : : {
12745 : : /* When reprocessing a struct node group used as the base of a
12746 : : subcomponent access, if we have a reference-to-pointer base,
12747 : : we will see:
12748 : : struct(**ptr) attach(*ptr)
12749 : : whereas for a non-reprocess-struct group, we see, e.g.:
12750 : : tofrom(**ptr) attach(*ptr) attach(ptr)
12751 : : and we create the "alloc" for the second "attach", i.e.
12752 : : for the reference itself. When reprocessing a struct group we
12753 : : thus change the pointer attachment into a reference attachment
12754 : : by stripping the indirection. (The attachment of the
12755 : : referenced pointer must happen elsewhere, either on the same
12756 : : directive, or otherwise.) */
12757 : 180 : tree adecl = OMP_CLAUSE_DECL (alloc_node);
12758 : :
12759 : 180 : if ((TREE_CODE (adecl) == INDIRECT_REF
12760 : 148 : || (TREE_CODE (adecl) == MEM_REF
12761 : 0 : && integer_zerop (TREE_OPERAND (adecl, 1))))
12762 : 32 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (adecl, 0)))
12763 : : == REFERENCE_TYPE)
12764 : 212 : && (TREE_CODE (TREE_TYPE (TREE_TYPE
12765 : : (TREE_OPERAND (adecl, 0)))) == POINTER_TYPE))
12766 : 32 : OMP_CLAUSE_DECL (alloc_node) = TREE_OPERAND (adecl, 0);
12767 : :
12768 : 180 : *added_tail = tail;
12769 : : }
12770 : : }
12771 : : else
12772 : : {
12773 : 846 : gcc_assert (*grp_start_p == grp_end);
12774 : 846 : if (reprocessing_struct)
12775 : : {
12776 : : /* If we don't have an attach/detach node, this is a
12777 : : "target data" directive or similar, not an offload region.
12778 : : Synthesize an "alloc" node using just the initiating
12779 : : GOMP_MAP_STRUCT decl. */
12780 : 16 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
12781 : 32 : || code == OACC_EXIT_DATA)
12782 : 32 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
12783 : 32 : tree alloc_node
12784 : 32 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12785 : : OMP_CLAUSE_MAP);
12786 : 32 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
12787 : 32 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
12788 : 64 : OMP_CLAUSE_SIZE (alloc_node)
12789 : 32 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
12790 : :
12791 : 32 : OMP_CLAUSE_CHAIN (alloc_node) = OMP_CLAUSE_CHAIN (l);
12792 : 32 : OMP_CLAUSE_CHAIN (l) = alloc_node;
12793 : 32 : *insert_node_pos = l;
12794 : 32 : *added_tail = &OMP_CLAUSE_CHAIN (alloc_node);
12795 : : }
12796 : : else
12797 : 814 : grp_start_p = omp_siblist_insert_node_after (l, insert_node_pos);
12798 : : }
12799 : :
12800 : 2704 : unsigned last_access = base_token + 1;
12801 : :
12802 : 2704 : while (last_access + 1 < addr_tokens.length ()
12803 : 2872 : && addr_tokens[last_access + 1]->type == ACCESS_METHOD)
12804 : : last_access++;
12805 : :
12806 : 2704 : if ((region_type & ORT_TARGET)
12807 : 2704 : && addr_tokens[base_token + 1]->type == ACCESS_METHOD)
12808 : : {
12809 : 1652 : bool base_ref = false;
12810 : 1652 : access_method_kinds access_kind
12811 : 1652 : = addr_tokens[last_access]->u.access_kind;
12812 : :
12813 : 1652 : switch (access_kind)
12814 : : {
12815 : : case ACCESS_DIRECT:
12816 : : case ACCESS_INDEXED_ARRAY:
12817 : 1004 : return NULL;
12818 : :
12819 : 403 : case ACCESS_REF:
12820 : 403 : case ACCESS_REF_TO_POINTER:
12821 : 403 : case ACCESS_REF_TO_POINTER_OFFSET:
12822 : 403 : case ACCESS_INDEXED_REF_TO_ARRAY:
12823 : 403 : base_ref = true;
12824 : 403 : break;
12825 : :
12826 : 866 : default:
12827 : 866 : ;
12828 : : }
12829 : 866 : tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
12830 : : OMP_CLAUSE_MAP);
12831 : 866 : enum gomp_map_kind mkind;
12832 : 866 : omp_mapping_group *decl_group;
12833 : 866 : tree use_base;
12834 : 866 : switch (access_kind)
12835 : : {
12836 : 463 : case ACCESS_POINTER:
12837 : 463 : case ACCESS_POINTER_OFFSET:
12838 : 463 : use_base = addr_tokens[last_access]->expr;
12839 : 463 : break;
12840 : 198 : case ACCESS_REF_TO_POINTER:
12841 : 198 : case ACCESS_REF_TO_POINTER_OFFSET:
12842 : 198 : use_base
12843 : 198 : = build_fold_indirect_ref (addr_tokens[last_access]->expr);
12844 : 198 : break;
12845 : 205 : default:
12846 : 205 : use_base = addr_tokens[base_token]->expr;
12847 : : }
12848 : 866 : bool mapped_to_p
12849 : 866 : = omp_directive_maps_explicitly (group_map, use_base, &decl_group,
12850 : : true, false, true);
12851 : 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12852 : 866 : && DECL_P (addr_tokens[last_access]->expr)
12853 : 1372 : && !mapped_to_p)
12854 : 444 : mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE
12855 : : : GOMP_MAP_FIRSTPRIVATE_POINTER;
12856 : : else
12857 : : mkind = GOMP_MAP_ATTACH_DETACH;
12858 : :
12859 : 866 : OMP_CLAUSE_SET_MAP_KIND (c2, mkind);
12860 : : /* If we have a reference to pointer base, we want to attach the
12861 : : pointer here, not the reference. The reference attachment happens
12862 : : elsewhere. */
12863 : 866 : bool ref_to_ptr
12864 : 866 : = (access_kind == ACCESS_REF_TO_POINTER
12865 : 866 : || access_kind == ACCESS_REF_TO_POINTER_OFFSET);
12866 : 866 : tree sdecl = addr_tokens[last_access]->expr;
12867 : 866 : tree sdecl_ptr = ref_to_ptr ? build_fold_indirect_ref (sdecl)
12868 : : : sdecl;
12869 : : /* For the FIRSTPRIVATE_REFERENCE after the struct node, we
12870 : : want to use the reference itself for the decl, but we
12871 : : still want to use the pointer to calculate the bias. */
12872 : 866 : OMP_CLAUSE_DECL (c2) = (mkind == GOMP_MAP_ATTACH_DETACH)
12873 : 866 : ? sdecl_ptr : sdecl;
12874 : 866 : sdecl = sdecl_ptr;
12875 : 866 : tree baddr = build_fold_addr_expr (base);
12876 : 866 : baddr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12877 : : ptrdiff_type_node, baddr);
12878 : 866 : tree decladdr = fold_convert_loc (OMP_CLAUSE_LOCATION (grp_end),
12879 : : ptrdiff_type_node, sdecl);
12880 : 866 : OMP_CLAUSE_SIZE (c2)
12881 : 866 : = fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR,
12882 : : ptrdiff_type_node, baddr, decladdr);
12883 : : /* Insert after struct node. */
12884 : 866 : OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l);
12885 : 866 : OMP_CLAUSE_CHAIN (l) = c2;
12886 : :
12887 : 866 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12888 : 866 : && (addr_tokens[base_token]->u.structure_base_kind
12889 : : == BASE_COMPONENT_EXPR)
12890 : 286 : && mkind == GOMP_MAP_ATTACH_DETACH
12891 : 1152 : && addr_tokens[last_access]->u.access_kind != ACCESS_REF)
12892 : : {
12893 : 218 : *inner = insert_node_pos;
12894 : 218 : if (openmp)
12895 : 166 : *fragile_p = true;
12896 : 218 : return NULL;
12897 : : }
12898 : : }
12899 : :
12900 : 1700 : if (addr_tokens[base_token]->type == STRUCTURE_BASE
12901 : 1700 : && (addr_tokens[base_token]->u.structure_base_kind
12902 : : == BASE_COMPONENT_EXPR)
12903 : 2015 : && addr_tokens[last_access]->u.access_kind == ACCESS_REF)
12904 : 100 : *inner = insert_node_pos;
12905 : :
12906 : 1700 : return NULL;
12907 : : }
12908 : 1257 : else if (struct_map_to_clause)
12909 : : {
12910 : 1257 : tree *osc = struct_map_to_clause->get (base);
12911 : 1257 : tree *sc = NULL, *scp = NULL;
12912 : 1257 : bool unordered = false;
12913 : :
12914 : 1257 : if (osc && OMP_CLAUSE_MAP_KIND (*osc) == GOMP_MAP_STRUCT_UNORD)
12915 : : unordered = true;
12916 : :
12917 : 1257 : unsigned HOST_WIDE_INT i, elems = tree_to_uhwi (OMP_CLAUSE_SIZE (*osc));
12918 : 1257 : sc = &OMP_CLAUSE_CHAIN (*osc);
12919 : : /* The struct mapping might be immediately followed by a
12920 : : FIRSTPRIVATE_POINTER, FIRSTPRIVATE_REFERENCE or an ATTACH_DETACH --
12921 : : if it's an indirect access or a reference, or if the structure base
12922 : : is not a decl. The FIRSTPRIVATE_* nodes are removed in omp-low.cc
12923 : : after they have been processed there, and ATTACH_DETACH nodes are
12924 : : recomputed and moved out of the GOMP_MAP_STRUCT construct once
12925 : : sibling list building is complete. */
12926 : 1257 : if (OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_POINTER
12927 : 1212 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_FIRSTPRIVATE_REFERENCE
12928 : 2424 : || OMP_CLAUSE_MAP_KIND (*sc) == GOMP_MAP_ATTACH_DETACH)
12929 : 201 : sc = &OMP_CLAUSE_CHAIN (*sc);
12930 : 3453 : for (i = 0; i < elems; i++, sc = &OMP_CLAUSE_CHAIN (*sc))
12931 : 2580 : if (attach_detach && sc == grp_start_p)
12932 : : break;
12933 : 2580 : else if (TREE_CODE (OMP_CLAUSE_DECL (*sc)) != COMPONENT_REF
12934 : 182 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != INDIRECT_REF
12935 : 2762 : && TREE_CODE (OMP_CLAUSE_DECL (*sc)) != ARRAY_REF)
12936 : : break;
12937 : : else
12938 : : {
12939 : 2580 : tree sc_decl = OMP_CLAUSE_DECL (*sc);
12940 : 2580 : poly_offset_int offset;
12941 : 2580 : poly_int64 bitpos;
12942 : :
12943 : 2580 : if (TREE_CODE (sc_decl) == ARRAY_REF)
12944 : : {
12945 : 366 : while (TREE_CODE (sc_decl) == ARRAY_REF)
12946 : 184 : sc_decl = TREE_OPERAND (sc_decl, 0);
12947 : 182 : if (TREE_CODE (sc_decl) != COMPONENT_REF
12948 : 182 : || TREE_CODE (TREE_TYPE (sc_decl)) != ARRAY_TYPE)
12949 : : break;
12950 : : }
12951 : 2398 : else if (INDIRECT_REF_P (sc_decl)
12952 : 0 : && TREE_CODE (TREE_OPERAND (sc_decl, 0)) == COMPONENT_REF
12953 : 2398 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (sc_decl, 0)))
12954 : : == REFERENCE_TYPE))
12955 : 0 : sc_decl = TREE_OPERAND (sc_decl, 0);
12956 : :
12957 : 2580 : bool variable_offset2;
12958 : 2580 : tree base2 = extract_base_bit_offset (sc_decl, &bitpos, &offset,
12959 : : &variable_offset2);
12960 : 2580 : if (!base2 || !operand_equal_p (base2, base, 0))
12961 : : break;
12962 : 2580 : if (scp)
12963 : 220 : continue;
12964 : 2360 : if (variable_offset2)
12965 : : {
12966 : 48 : OMP_CLAUSE_SET_MAP_KIND (*osc, GOMP_MAP_STRUCT_UNORD);
12967 : 48 : unordered = true;
12968 : 48 : break;
12969 : : }
12970 : 2312 : else if ((region_type & ORT_ACC) != 0)
12971 : : {
12972 : : /* For OpenACC, allow (ignore) duplicate struct accesses in
12973 : : the middle of a mapping clause, e.g. "mystruct->foo" in:
12974 : : copy(mystruct->foo->bar) copy(mystruct->foo->qux). */
12975 : 223 : if (reprocessing_struct
12976 : 8 : && known_eq (coffset, offset)
12977 : 223 : && known_eq (cbitpos, bitpos))
12978 : 21 : return NULL;
12979 : : }
12980 : 2089 : else if (known_eq (coffset, offset)
12981 : 2089 : && known_eq (cbitpos, bitpos))
12982 : : {
12983 : : /* Having two struct members at the same offset doesn't work,
12984 : : so make sure we don't. (We're allowed to ignore this.
12985 : : Should we report the error?) */
12986 : : /*error_at (OMP_CLAUSE_LOCATION (grp_end),
12987 : : "duplicate struct member %qE in map clauses",
12988 : : OMP_CLAUSE_DECL (grp_end));*/
12989 : : return NULL;
12990 : : }
12991 : 2291 : if (maybe_lt (coffset, offset)
12992 : 4001 : || (known_eq (coffset, offset)
12993 : 2 : && maybe_lt (cbitpos, bitpos)))
12994 : : {
12995 : 581 : if (attach_detach)
12996 : : scp = sc;
12997 : : else
12998 : : break;
12999 : : }
13000 : : }
13001 : :
13002 : : /* If this is an unordered struct, just insert the new element at the
13003 : : end of the list. */
13004 : 1236 : if (unordered)
13005 : : {
13006 : 102 : for (; i < elems; i++)
13007 : 54 : sc = &OMP_CLAUSE_CHAIN (*sc);
13008 : : scp = NULL;
13009 : : }
13010 : :
13011 : 1236 : OMP_CLAUSE_SIZE (*osc)
13012 : 1236 : = size_binop (PLUS_EXPR, OMP_CLAUSE_SIZE (*osc), size_one_node);
13013 : :
13014 : 1236 : if (reprocessing_struct)
13015 : : {
13016 : : /* If we're reprocessing a struct node, we don't want to do most of
13017 : : the list manipulation below. We only need to handle the (pointer
13018 : : or reference) attach/detach case. */
13019 : 8 : tree extra_node, alloc_node;
13020 : 8 : if (has_descriptor)
13021 : 0 : gcc_unreachable ();
13022 : 8 : else if (attach_detach)
13023 : 8 : alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
13024 : : grp_end, &extra_node);
13025 : : else
13026 : : {
13027 : : /* If we don't have an attach/detach node, this is a
13028 : : "target data" directive or similar, not an offload region.
13029 : : Synthesize an "alloc" node using just the initiating
13030 : : GOMP_MAP_STRUCT decl. */
13031 : 0 : gomp_map_kind k = (code == OMP_TARGET_EXIT_DATA
13032 : 0 : || code == OACC_EXIT_DATA)
13033 : 0 : ? GOMP_MAP_RELEASE : GOMP_MAP_ALLOC;
13034 : 0 : alloc_node
13035 : 0 : = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end),
13036 : : OMP_CLAUSE_MAP);
13037 : 0 : OMP_CLAUSE_SET_MAP_KIND (alloc_node, k);
13038 : 0 : OMP_CLAUSE_DECL (alloc_node) = unshare_expr (last_token->expr);
13039 : 0 : OMP_CLAUSE_SIZE (alloc_node)
13040 : 0 : = TYPE_SIZE_UNIT (TREE_TYPE (OMP_CLAUSE_DECL (alloc_node)));
13041 : : }
13042 : :
13043 : 8 : if (scp)
13044 : 0 : omp_siblist_insert_node_after (alloc_node, scp);
13045 : : else
13046 : : {
13047 : 8 : tree *new_end = omp_siblist_insert_node_after (alloc_node, sc);
13048 : 8 : if (sc == *added_tail)
13049 : 8 : *added_tail = new_end;
13050 : : }
13051 : :
13052 : 8 : return NULL;
13053 : : }
13054 : :
13055 : 1228 : if (has_descriptor)
13056 : : {
13057 : 339 : tree desc = OMP_CLAUSE_CHAIN (*grp_start_p);
13058 : 339 : if (code == OMP_TARGET_EXIT_DATA
13059 : 339 : || code == OACC_EXIT_DATA)
13060 : 19 : OMP_CLAUSE_SET_MAP_KIND (desc, GOMP_MAP_RELEASE);
13061 : 678 : omp_siblist_move_node_after (desc,
13062 : 339 : &OMP_CLAUSE_CHAIN (*grp_start_p),
13063 : : scp ? scp : sc);
13064 : : }
13065 : 889 : else if (attach_detach)
13066 : : {
13067 : 325 : tree cl = NULL_TREE, extra_node;
13068 : 325 : tree alloc_node = build_omp_struct_comp_nodes (code, *grp_start_p,
13069 : : grp_end, &extra_node);
13070 : 325 : tree *tail_chain = NULL;
13071 : :
13072 : 325 : if (*fragile_p
13073 : 325 : || (openmp
13074 : : && !target
13075 : : && attach_detach
13076 : 62 : && TREE_CODE (TREE_TYPE (ocd)) == POINTER_TYPE
13077 : 23 : && !OMP_CLAUSE_ATTACHMENT_MAPPING_ERASED (grp_end)))
13078 : : {
13079 : 6 : if (!lang_GNU_Fortran ())
13080 : 6 : OMP_CLAUSE_SIZE (alloc_node) = size_zero_node;
13081 : 6 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (alloc_node) = 1;
13082 : : }
13083 : :
13084 : : /* Here, we have:
13085 : :
13086 : : grp_end : the last (or only) node in this group.
13087 : : grp_start_p : pointer to the first node in a pointer mapping group
13088 : : up to and including GRP_END.
13089 : : sc : pointer to the chain for the end of the struct component
13090 : : list.
13091 : : scp : pointer to the chain for the sorted position at which we
13092 : : should insert in the middle of the struct component list
13093 : : (else NULL to insert at end).
13094 : : alloc_node : the "alloc" node for the structure (pointer-type)
13095 : : component. We insert at SCP (if present), else SC
13096 : : (the end of the struct component list).
13097 : : extra_node : a newly-synthesized node for an additional indirect
13098 : : pointer mapping or a Fortran pointer set, if needed.
13099 : : cl : first node to prepend before grp_start_p.
13100 : : tail_chain : pointer to chain of last prepended node.
13101 : :
13102 : : The general idea is we move the nodes for this struct mapping
13103 : : together: the alloc node goes into the sorted list directly after
13104 : : the struct mapping, and any extra nodes (together with the nodes
13105 : : mapping arrays pointed to by struct components) get moved after
13106 : : that list. When SCP is NULL, we insert the nodes at SC, i.e. at
13107 : : the end of the struct component mapping list. It's important that
13108 : : the alloc_node comes first in that case because it's part of the
13109 : : sorted component mapping list (but subsequent nodes are not!). */
13110 : :
13111 : 325 : if (scp)
13112 : 254 : omp_siblist_insert_node_after (alloc_node, scp);
13113 : :
13114 : : /* Make [cl,tail_chain] a list of the alloc node (if we haven't
13115 : : already inserted it) and the extra_node (if it is present). The
13116 : : list can be empty if we added alloc_node above and there is no
13117 : : extra node. */
13118 : 254 : if (scp && extra_node)
13119 : : {
13120 : 0 : cl = extra_node;
13121 : 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13122 : : }
13123 : 325 : else if (extra_node)
13124 : : {
13125 : 0 : OMP_CLAUSE_CHAIN (alloc_node) = extra_node;
13126 : 0 : cl = alloc_node;
13127 : 0 : tail_chain = &OMP_CLAUSE_CHAIN (extra_node);
13128 : : }
13129 : 325 : else if (!scp)
13130 : : {
13131 : 71 : cl = alloc_node;
13132 : 71 : tail_chain = &OMP_CLAUSE_CHAIN (alloc_node);
13133 : : }
13134 : :
13135 : 325 : continue_at
13136 : 71 : = cl ? omp_siblist_move_concat_nodes_after (cl, tail_chain,
13137 : : grp_start_p, grp_end,
13138 : : sc)
13139 : 254 : : omp_siblist_move_nodes_after (grp_start_p, grp_end, sc);
13140 : : }
13141 : 564 : else if (*sc != grp_end)
13142 : : {
13143 : 524 : gcc_assert (*grp_start_p == grp_end);
13144 : :
13145 : : /* We are moving the current node back to a previous struct node:
13146 : : the node that used to point to the current node will now point to
13147 : : the next node. */
13148 : 524 : continue_at = grp_start_p;
13149 : : /* In the non-pointer case, the mapping clause itself is moved into
13150 : : the correct position in the struct component list, which in this
13151 : : case is just SC. */
13152 : 524 : omp_siblist_move_node_after (*grp_start_p, grp_start_p, sc);
13153 : : }
13154 : : }
13155 : : return continue_at;
13156 : : }
13157 : :
13158 : : /* Scan through GROUPS, and create sorted structure sibling lists without
13159 : : gimplifying. */
13160 : :
13161 : : static bool
13162 : 17192 : omp_build_struct_sibling_lists (enum tree_code code,
13163 : : enum omp_region_type region_type,
13164 : : vec<omp_mapping_group> *groups,
13165 : : hash_map<tree_operand_hash_no_se,
13166 : : omp_mapping_group *> **grpmap,
13167 : : tree *list_p)
13168 : : {
13169 : 17192 : using namespace omp_addr_tokenizer;
13170 : 17192 : unsigned i;
13171 : 17192 : omp_mapping_group *grp;
13172 : 17192 : hash_map<tree_operand_hash, tree> *struct_map_to_clause = NULL;
13173 : 17192 : bool success = true;
13174 : 17192 : tree *new_next = NULL;
13175 : 34384 : tree *tail = &OMP_CLAUSE_CHAIN ((*groups)[groups->length () - 1].grp_end);
13176 : 17192 : tree added_nodes = NULL_TREE;
13177 : 17192 : tree *added_tail = &added_nodes;
13178 : 17192 : auto_vec<omp_mapping_group> pre_hwm_groups;
13179 : :
13180 : 64128 : FOR_EACH_VEC_ELT (*groups, i, grp)
13181 : : {
13182 : 29744 : tree c = grp->grp_end;
13183 : 29744 : tree decl = OMP_CLAUSE_DECL (c);
13184 : 29744 : tree grp_end = grp->grp_end;
13185 : 29744 : auto_vec<omp_addr_token *> addr_tokens;
13186 : 29744 : tree sentinel = OMP_CLAUSE_CHAIN (grp_end);
13187 : :
13188 : 29744 : if (new_next && !grp->reprocess_struct)
13189 : 510 : grp->grp_start = new_next;
13190 : :
13191 : 29744 : new_next = NULL;
13192 : :
13193 : 29744 : tree *grp_start_p = grp->grp_start;
13194 : :
13195 : 29744 : if (DECL_P (decl))
13196 : 20422 : continue;
13197 : :
13198 : : /* Skip groups we marked for deletion in
13199 : : {omp,oacc}_resolve_clause_dependencies. */
13200 : 9322 : if (grp->deleted)
13201 : 462 : continue;
13202 : :
13203 : 8860 : if (OMP_CLAUSE_CHAIN (*grp_start_p)
13204 : 8860 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
13205 : : {
13206 : : /* Don't process an array descriptor that isn't inside a derived type
13207 : : as a struct (the GOMP_MAP_POINTER following will have the form
13208 : : "var.data", but such mappings are handled specially). */
13209 : 5406 : tree grpmid = OMP_CLAUSE_CHAIN (*grp_start_p);
13210 : 5406 : if (omp_map_clause_descriptor_p (grpmid)
13211 : 9038 : && DECL_P (OMP_CLAUSE_DECL (grpmid)))
13212 : 2772 : continue;
13213 : : }
13214 : :
13215 : : tree expr = decl;
13216 : :
13217 : 7115 : while (TREE_CODE (expr) == ARRAY_REF)
13218 : 1027 : expr = TREE_OPERAND (expr, 0);
13219 : :
13220 : 6088 : if (!omp_parse_expr (addr_tokens, expr))
13221 : 0 : continue;
13222 : :
13223 : 6088 : omp_addr_token *last_token
13224 : 6088 : = omp_first_chained_access_token (addr_tokens);
13225 : :
13226 : : /* A mapping of a reference to a pointer member that doesn't specify an
13227 : : array section, etc., like this:
13228 : : *mystruct.ref_to_ptr
13229 : : should not be processed by the struct sibling-list handling code --
13230 : : it just transfers the referenced pointer.
13231 : :
13232 : : In contrast, the quite similar-looking construct:
13233 : : *mystruct.ptr
13234 : : which is equivalent to e.g.
13235 : : mystruct.ptr[0]
13236 : : *does* trigger sibling-list processing.
13237 : :
13238 : : An exception for the former case is for "fragile" groups where the
13239 : : reference itself is not handled otherwise; this is subject to special
13240 : : handling in omp_accumulate_sibling_list also. */
13241 : :
13242 : 6088 : if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
13243 : 2847 : && last_token->type == ACCESS_METHOD
13244 : 2847 : && last_token->u.access_kind == ACCESS_REF
13245 : 6372 : && !grp->fragile)
13246 : 219 : continue;
13247 : :
13248 : 5869 : tree d = decl;
13249 : 5869 : if (TREE_CODE (d) == ARRAY_REF)
13250 : : {
13251 : 1998 : while (TREE_CODE (d) == ARRAY_REF)
13252 : 1010 : d = TREE_OPERAND (d, 0);
13253 : 988 : if (TREE_CODE (d) == COMPONENT_REF
13254 : 988 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
13255 : : decl = d;
13256 : : }
13257 : 5869 : if (d == decl
13258 : 5192 : && INDIRECT_REF_P (decl)
13259 : 716 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
13260 : 105 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
13261 : : == REFERENCE_TYPE)
13262 : 5966 : && (OMP_CLAUSE_MAP_KIND (c)
13263 : : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
13264 : 97 : decl = TREE_OPERAND (decl, 0);
13265 : :
13266 : 5869 : STRIP_NOPS (decl);
13267 : :
13268 : 5869 : if (TREE_CODE (decl) != COMPONENT_REF)
13269 : 1338 : continue;
13270 : :
13271 : : /* If we're mapping the whole struct in another node, skip adding this
13272 : : node to a sibling list. */
13273 : 4531 : omp_mapping_group *wholestruct;
13274 : 4531 : if (omp_mapped_by_containing_struct (*grpmap, OMP_CLAUSE_DECL (c),
13275 : : &wholestruct))
13276 : 125 : continue;
13277 : :
13278 : 4406 : if (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_TO_PSET
13279 : 4406 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
13280 : 4305 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
13281 : : && code != OACC_UPDATE
13282 : 8646 : && code != OMP_TARGET_UPDATE)
13283 : : {
13284 : 4049 : if (error_operand_p (decl))
13285 : : {
13286 : 0 : success = false;
13287 : 0 : goto error_out;
13288 : : }
13289 : :
13290 : 4049 : tree stype = TREE_TYPE (decl);
13291 : 4049 : if (TREE_CODE (stype) == REFERENCE_TYPE)
13292 : 768 : stype = TREE_TYPE (stype);
13293 : 4049 : if (TYPE_SIZE_UNIT (stype) == NULL
13294 : 4049 : || TREE_CODE (TYPE_SIZE_UNIT (stype)) != INTEGER_CST)
13295 : : {
13296 : 0 : error_at (OMP_CLAUSE_LOCATION (c),
13297 : : "mapping field %qE of variable length "
13298 : 0 : "structure", OMP_CLAUSE_DECL (c));
13299 : 0 : success = false;
13300 : 0 : goto error_out;
13301 : : }
13302 : :
13303 : 4049 : tree *inner = NULL;
13304 : 4049 : bool fragile_p = grp->fragile;
13305 : :
13306 : 4049 : new_next
13307 : 8098 : = omp_accumulate_sibling_list (region_type, code,
13308 : : struct_map_to_clause, *grpmap,
13309 : : grp_start_p, grp_end, addr_tokens,
13310 : : &inner, &fragile_p,
13311 : 4049 : grp->reprocess_struct, &added_tail);
13312 : :
13313 : 4049 : if (inner)
13314 : : {
13315 : 318 : omp_mapping_group newgrp;
13316 : 318 : newgrp.grp_start = inner;
13317 : 318 : if (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (*inner))
13318 : : == GOMP_MAP_ATTACH_DETACH)
13319 : 286 : newgrp.grp_end = OMP_CLAUSE_CHAIN (*inner);
13320 : : else
13321 : 32 : newgrp.grp_end = *inner;
13322 : 318 : newgrp.mark = UNVISITED;
13323 : 318 : newgrp.sibling = NULL;
13324 : 318 : newgrp.deleted = false;
13325 : 318 : newgrp.reprocess_struct = true;
13326 : 318 : newgrp.fragile = fragile_p;
13327 : 318 : newgrp.next = NULL;
13328 : 318 : groups->safe_push (newgrp);
13329 : :
13330 : : /* !!! Growing GROUPS might invalidate the pointers in the group
13331 : : map. Rebuild it here. This is a bit inefficient, but
13332 : : shouldn't happen very often. */
13333 : 636 : delete (*grpmap);
13334 : 318 : *grpmap
13335 : 318 : = omp_reindex_mapping_groups (list_p, groups, &pre_hwm_groups,
13336 : : sentinel);
13337 : : }
13338 : : }
13339 : 29744 : }
13340 : :
13341 : : /* Delete groups marked for deletion above. At this point the order of the
13342 : : groups may no longer correspond to the order of the underlying list,
13343 : : which complicates this a little. First clear out OMP_CLAUSE_DECL for
13344 : : deleted nodes... */
13345 : :
13346 : 46936 : FOR_EACH_VEC_ELT (*groups, i, grp)
13347 : 29744 : if (grp->deleted)
13348 : 462 : for (tree d = *grp->grp_start;
13349 : 924 : d != OMP_CLAUSE_CHAIN (grp->grp_end);
13350 : 462 : d = OMP_CLAUSE_CHAIN (d))
13351 : 462 : OMP_CLAUSE_DECL (d) = NULL_TREE;
13352 : :
13353 : : /* ...then sweep through the list removing the now-empty nodes. */
13354 : :
13355 : : tail = list_p;
13356 : 90953 : while (*tail)
13357 : : {
13358 : 73761 : if (OMP_CLAUSE_CODE (*tail) == OMP_CLAUSE_MAP
13359 : 73761 : && OMP_CLAUSE_DECL (*tail) == NULL_TREE)
13360 : 462 : *tail = OMP_CLAUSE_CHAIN (*tail);
13361 : : else
13362 : 73299 : tail = &OMP_CLAUSE_CHAIN (*tail);
13363 : : }
13364 : :
13365 : : /* Tack on the struct nodes added during nested struct reprocessing. */
13366 : 17192 : if (added_nodes)
13367 : : {
13368 : 192 : *tail = added_nodes;
13369 : 192 : tail = added_tail;
13370 : : }
13371 : :
13372 : : /* Now we have finished building the struct sibling lists, reprocess
13373 : : newly-added "attach" nodes: we need the address of the first
13374 : : mapped element of each struct sibling list for the bias of the attach
13375 : : operation -- not necessarily the base address of the whole struct. */
13376 : 17192 : if (struct_map_to_clause)
13377 : 4980 : for (hash_map<tree_operand_hash, tree>::iterator iter
13378 : 2276 : = struct_map_to_clause->begin ();
13379 : 7256 : iter != struct_map_to_clause->end ();
13380 : 2704 : ++iter)
13381 : : {
13382 : 2704 : tree struct_node = (*iter).second;
13383 : 2704 : gcc_assert (OMP_CLAUSE_CODE (struct_node) == OMP_CLAUSE_MAP);
13384 : 2704 : tree attach = OMP_CLAUSE_CHAIN (struct_node);
13385 : :
13386 : 2704 : if (OMP_CLAUSE_CODE (attach) != OMP_CLAUSE_MAP
13387 : 2704 : || OMP_CLAUSE_MAP_KIND (attach) != GOMP_MAP_ATTACH_DETACH)
13388 : 2282 : continue;
13389 : :
13390 : 422 : OMP_CLAUSE_SET_MAP_KIND (attach, GOMP_MAP_ATTACH);
13391 : :
13392 : : /* Sanity check: the standalone attach node will not work if we have
13393 : : an "enter data" operation (because for those, variables need to be
13394 : : mapped separately and attach nodes must be grouped together with the
13395 : : base they attach to). We should only have created the
13396 : : ATTACH_DETACH node after GOMP_MAP_STRUCT for a target region, so
13397 : : this should never be true. */
13398 : 422 : gcc_assert ((region_type & ORT_TARGET) != 0);
13399 : :
13400 : : /* This is the first sorted node in the struct sibling list. Use it
13401 : : to recalculate the correct bias to use.
13402 : : (&first_node - attach_decl).
13403 : : For GOMP_MAP_STRUCT_UNORD, we need e.g. the
13404 : : min(min(min(first,second),third),fourth) element, because the
13405 : : elements aren't in any particular order. */
13406 : 422 : tree lowest_addr;
13407 : 422 : if (OMP_CLAUSE_MAP_KIND (struct_node) == GOMP_MAP_STRUCT_UNORD)
13408 : : {
13409 : 4 : tree first_node = OMP_CLAUSE_CHAIN (attach);
13410 : 4 : unsigned HOST_WIDE_INT num_mappings
13411 : 4 : = tree_to_uhwi (OMP_CLAUSE_SIZE (struct_node));
13412 : 4 : lowest_addr = OMP_CLAUSE_DECL (first_node);
13413 : 4 : lowest_addr = build_fold_addr_expr (lowest_addr);
13414 : 4 : lowest_addr = fold_convert (pointer_sized_int_node, lowest_addr);
13415 : 4 : tree next_node = OMP_CLAUSE_CHAIN (first_node);
13416 : 8 : while (num_mappings > 1)
13417 : : {
13418 : 4 : tree tmp = OMP_CLAUSE_DECL (next_node);
13419 : 4 : tmp = build_fold_addr_expr (tmp);
13420 : 4 : tmp = fold_convert (pointer_sized_int_node, tmp);
13421 : 4 : lowest_addr = fold_build2 (MIN_EXPR, pointer_sized_int_node,
13422 : : lowest_addr, tmp);
13423 : 4 : next_node = OMP_CLAUSE_CHAIN (next_node);
13424 : 4 : num_mappings--;
13425 : : }
13426 : 4 : lowest_addr = fold_convert (ptrdiff_type_node, lowest_addr);
13427 : : }
13428 : : else
13429 : : {
13430 : 418 : tree first_node = OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (attach));
13431 : 418 : first_node = build_fold_addr_expr (first_node);
13432 : 418 : lowest_addr = fold_convert (ptrdiff_type_node, first_node);
13433 : : }
13434 : 422 : tree attach_decl = OMP_CLAUSE_DECL (attach);
13435 : 422 : attach_decl = fold_convert (ptrdiff_type_node, attach_decl);
13436 : 422 : OMP_CLAUSE_SIZE (attach)
13437 : 422 : = fold_build2 (MINUS_EXPR, ptrdiff_type_node, lowest_addr,
13438 : : attach_decl);
13439 : :
13440 : : /* Remove GOMP_MAP_ATTACH node from after struct node. */
13441 : 422 : OMP_CLAUSE_CHAIN (struct_node) = OMP_CLAUSE_CHAIN (attach);
13442 : : /* ...and re-insert it at the end of our clause list. */
13443 : 422 : *tail = attach;
13444 : 422 : OMP_CLAUSE_CHAIN (attach) = NULL_TREE;
13445 : 422 : tail = &OMP_CLAUSE_CHAIN (attach);
13446 : : }
13447 : :
13448 : 14916 : error_out:
13449 : 17192 : if (struct_map_to_clause)
13450 : 2276 : delete struct_map_to_clause;
13451 : :
13452 : 17192 : return success;
13453 : 17192 : }
13454 : :
13455 : : struct instantiate_mapper_info
13456 : : {
13457 : : tree *mapper_clauses_p;
13458 : : struct gimplify_omp_ctx *omp_ctx;
13459 : : gimple_seq *pre_p;
13460 : : };
13461 : :
13462 : : /* Helper function for omp_instantiate_mapper. */
13463 : :
13464 : : static tree
13465 : 1272 : remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data)
13466 : : {
13467 : 1272 : copy_body_data *id = (copy_body_data *) data;
13468 : :
13469 : 1272 : if (DECL_P (*tp))
13470 : : {
13471 : 564 : tree replacement = remap_decl (*tp, id);
13472 : 564 : if (*tp != replacement)
13473 : : {
13474 : 289 : *tp = unshare_expr (replacement);
13475 : 289 : *walk_subtrees = 0;
13476 : : }
13477 : : }
13478 : :
13479 : 1272 : return NULL_TREE;
13480 : : }
13481 : :
13482 : : /* A copy_decl implementation (for use with tree-inline.cc functions) that
13483 : : only transform decls or SSA names that are part of a map we already
13484 : : prepared. */
13485 : :
13486 : : static tree
13487 : 94 : omp_mapper_copy_decl (tree var, copy_body_data *cb)
13488 : : {
13489 : 94 : tree *repl = cb->decl_map->get (var);
13490 : :
13491 : 94 : if (repl)
13492 : 0 : return *repl;
13493 : :
13494 : 94 : return var;
13495 : : }
13496 : :
13497 : : static tree *
13498 : 80 : omp_instantiate_mapper (gimple_seq *pre_p,
13499 : : hash_map<omp_name_type<tree>, tree> *implicit_mappers,
13500 : : tree mapperfn, tree expr, enum gomp_map_kind outer_kind,
13501 : : tree *mapper_clauses_p)
13502 : : {
13503 : 80 : tree mapper_name = NULL_TREE;
13504 : 80 : tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapperfn);
13505 : 80 : gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER);
13506 : :
13507 : 80 : tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper);
13508 : 80 : tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper);
13509 : :
13510 : : /* The "extraction map" is used to map the mapper variable in the "declare
13511 : : mapper" directive, and also any temporary variables that have been created
13512 : : as part of expanding the mapper function's body (which are expanded as a
13513 : : "bind" expression in the pre_p sequence). */
13514 : 80 : hash_map<tree, tree> extraction_map;
13515 : :
13516 : 80 : extraction_map.put (dummy_var, expr);
13517 : 80 : extraction_map.put (expr, expr);
13518 : :
13519 : : /* This copy_body_data is only used to remap the decls in the
13520 : : OMP_DECLARE_MAPPER tree node expansion itself. All relevant decls should
13521 : : already be in the current function. */
13522 : 80 : copy_body_data id;
13523 : 80 : memset (&id, 0, sizeof (id));
13524 : 80 : id.src_fn = current_function_decl;
13525 : 80 : id.dst_fn = current_function_decl;
13526 : 80 : id.src_cfun = cfun;
13527 : 80 : id.decl_map = &extraction_map;
13528 : 80 : id.copy_decl = omp_mapper_copy_decl;
13529 : 80 : id.transform_call_graph_edges = CB_CGE_DUPLICATE; // ???
13530 : 80 : id.transform_new_cfg = true; // ???
13531 : :
13532 : 238 : for (; clause; clause = OMP_CLAUSE_CHAIN (clause))
13533 : : {
13534 : 158 : enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (clause);
13535 : 158 : tree *nested_mapper_p = NULL;
13536 : :
13537 : 158 : if (map_kind == GOMP_MAP_PUSH_MAPPER_NAME)
13538 : : {
13539 : 0 : mapper_name = OMP_CLAUSE_DECL (clause);
13540 : 23 : continue;
13541 : : }
13542 : 158 : else if (map_kind == GOMP_MAP_POP_MAPPER_NAME)
13543 : : {
13544 : 0 : mapper_name = NULL_TREE;
13545 : 0 : continue;
13546 : : }
13547 : :
13548 : 158 : tree decl = OMP_CLAUSE_DECL (clause);
13549 : 158 : tree unshared, type;
13550 : 158 : bool nonunit_array_with_mapper = false;
13551 : :
13552 : 158 : if (TREE_CODE (decl) == OMP_ARRAY_SECTION)
13553 : : {
13554 : 62 : location_t loc = OMP_CLAUSE_LOCATION (clause);
13555 : 62 : tree tmp = lang_hooks.decls.omp_map_array_section (loc, decl);
13556 : 62 : if (tmp == decl)
13557 : : {
13558 : 48 : unshared = unshare_expr (clause);
13559 : 48 : nonunit_array_with_mapper = true;
13560 : 48 : type = TREE_TYPE (TREE_TYPE (decl));
13561 : : }
13562 : : else
13563 : : {
13564 : 14 : unshared = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
13565 : 14 : OMP_CLAUSE_CODE (clause));
13566 : 14 : OMP_CLAUSE_DECL (unshared) = tmp;
13567 : 14 : OMP_CLAUSE_SIZE (unshared)
13568 : 28 : = DECL_P (tmp) ? DECL_SIZE_UNIT (tmp)
13569 : 14 : : TYPE_SIZE_UNIT (TREE_TYPE (tmp));
13570 : 14 : type = TREE_TYPE (tmp);
13571 : : }
13572 : : }
13573 : : else
13574 : : {
13575 : 96 : unshared = unshare_expr (clause);
13576 : 96 : type = TREE_TYPE (decl);
13577 : : }
13578 : :
13579 : 158 : walk_tree (&unshared, remap_mapper_decl_1, &id, NULL);
13580 : :
13581 : 158 : if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET)
13582 : 28 : OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind);
13583 : :
13584 : 158 : decl = OMP_CLAUSE_DECL (unshared);
13585 : 158 : type = TYPE_MAIN_VARIANT (type);
13586 : :
13587 : 158 : nested_mapper_p = implicit_mappers->get ({ mapper_name, type });
13588 : :
13589 : 158 : if (nested_mapper_p && *nested_mapper_p != mapperfn)
13590 : : {
13591 : 23 : if (nonunit_array_with_mapper)
13592 : : {
13593 : 8 : sorry ("user-defined mapper with non-unit length array section");
13594 : 8 : continue;
13595 : : }
13596 : :
13597 : 15 : if (map_kind == GOMP_MAP_UNSET)
13598 : 0 : map_kind = outer_kind;
13599 : :
13600 : 15 : mapper_clauses_p
13601 : 15 : = omp_instantiate_mapper (pre_p, implicit_mappers,
13602 : : *nested_mapper_p, decl, map_kind,
13603 : : mapper_clauses_p);
13604 : 15 : continue;
13605 : : }
13606 : :
13607 : 135 : *mapper_clauses_p = unshared;
13608 : 135 : mapper_clauses_p = &OMP_CLAUSE_CHAIN (unshared);
13609 : : }
13610 : :
13611 : 80 : return mapper_clauses_p;
13612 : 80 : }
13613 : :
13614 : : static int
13615 : 124993 : omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
13616 : : {
13617 : 124993 : tree decl = (tree) n->key;
13618 : 124993 : instantiate_mapper_info *im_info = (instantiate_mapper_info *) data;
13619 : 124993 : gimplify_omp_ctx *ctx = im_info->omp_ctx;
13620 : 124993 : tree *mapper_p = NULL;
13621 : 124993 : tree type = TREE_TYPE (decl);
13622 : 124993 : bool ref_p = false;
13623 : 124993 : unsigned flags = n->value;
13624 : :
13625 : 124993 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
13626 : : return 0;
13627 : 23043 : if ((flags & GOVD_SEEN) == 0)
13628 : : return 0;
13629 : : /* If we already have clauses pertaining to a struct variable, then we don't
13630 : : want to implicitly invoke a user-defined mapper. */
13631 : 19659 : if ((flags & GOVD_EXPLICIT) != 0 && AGGREGATE_TYPE_P (TREE_TYPE (decl)))
13632 : : return 0;
13633 : :
13634 : 19659 : if (TREE_CODE (type) == REFERENCE_TYPE)
13635 : : {
13636 : 900 : ref_p = true;
13637 : 900 : type = TREE_TYPE (type);
13638 : : }
13639 : :
13640 : 19659 : type = TYPE_MAIN_VARIANT (type);
13641 : :
13642 : 19659 : if (DECL_P (decl) && type && AGGREGATE_TYPE_P (type))
13643 : : {
13644 : 5263 : gcc_assert (ctx);
13645 : 5263 : mapper_p = ctx->implicit_mappers->get ({ NULL_TREE, type });
13646 : : }
13647 : :
13648 : 5263 : if (mapper_p)
13649 : : {
13650 : : /* If we have a reference, map the pointed-to object rather than the
13651 : : reference itself. */
13652 : 65 : if (ref_p)
13653 : 2 : decl = build_fold_indirect_ref (decl);
13654 : :
13655 : 65 : im_info->mapper_clauses_p
13656 : 65 : = omp_instantiate_mapper (im_info->pre_p, ctx->implicit_mappers,
13657 : : *mapper_p, decl, GOMP_MAP_TOFROM,
13658 : : im_info->mapper_clauses_p);
13659 : : /* Make sure we don't map the same variable implicitly in
13660 : : gimplify_adjust_omp_clauses_1 also. */
13661 : 65 : n->value |= GOVD_EXPLICIT;
13662 : : }
13663 : :
13664 : : return 0;
13665 : : }
13666 : :
13667 : : /* Scan the OMP clauses in *LIST_P, installing mappings into a new
13668 : : and previous omp contexts. */
13669 : :
13670 : : static void
13671 : 129126 : gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
13672 : : enum omp_region_type region_type,
13673 : : enum tree_code code,
13674 : : gimple_seq *loops_seq_p = NULL)
13675 : : {
13676 : 129126 : using namespace omp_addr_tokenizer;
13677 : 129126 : struct gimplify_omp_ctx *ctx, *outer_ctx;
13678 : 129126 : tree c;
13679 : 129126 : tree *orig_list_p = list_p;
13680 : 129126 : int handled_depend_iterators = -1;
13681 : 129126 : int nowait = -1;
13682 : :
13683 : 129126 : ctx = new_omp_context (region_type);
13684 : 129126 : ctx->code = code;
13685 : 129126 : outer_ctx = ctx->outer_context;
13686 : 129126 : if (code == OMP_TARGET)
13687 : : {
13688 : 12628 : if (!lang_GNU_Fortran ())
13689 : 10635 : ctx->defaultmap[GDMK_POINTER] = GOVD_MAP | GOVD_MAP_0LEN_ARRAY;
13690 : 12628 : ctx->defaultmap[GDMK_SCALAR] = GOVD_FIRSTPRIVATE;
13691 : 25256 : ctx->defaultmap[GDMK_SCALAR_TARGET] = (lang_GNU_Fortran ()
13692 : 12628 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
13693 : : }
13694 : 129126 : if (!lang_GNU_Fortran ())
13695 : 98540 : switch (code)
13696 : : {
13697 : 17966 : case OMP_TARGET:
13698 : 17966 : case OMP_TARGET_DATA:
13699 : 17966 : case OMP_TARGET_ENTER_DATA:
13700 : 17966 : case OMP_TARGET_EXIT_DATA:
13701 : 17966 : case OACC_DECLARE:
13702 : 17966 : case OACC_HOST_DATA:
13703 : 17966 : case OACC_PARALLEL:
13704 : 17966 : case OACC_KERNELS:
13705 : 17966 : ctx->target_firstprivatize_array_bases = true;
13706 : : default:
13707 : : break;
13708 : : }
13709 : :
13710 : 129126 : vec<omp_mapping_group> *groups = NULL;
13711 : 129126 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
13712 : 129126 : unsigned grpnum = 0;
13713 : 129126 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
13714 : :
13715 : 129126 : if (code == OMP_TARGET
13716 : 129126 : || code == OMP_TARGET_DATA
13717 : 129126 : || code == OMP_TARGET_ENTER_DATA
13718 : : || code == OMP_TARGET_EXIT_DATA
13719 : : || code == OACC_DATA
13720 : : || code == OACC_KERNELS
13721 : : || code == OACC_PARALLEL
13722 : : || code == OACC_SERIAL
13723 : : || code == OACC_ENTER_DATA
13724 : : || code == OACC_EXIT_DATA
13725 : : || code == OACC_UPDATE
13726 : : || code == OACC_DECLARE)
13727 : : {
13728 : 32668 : groups = omp_gather_mapping_groups (list_p);
13729 : :
13730 : 32668 : if (groups)
13731 : 17401 : grpmap = omp_index_mapping_groups (groups);
13732 : : }
13733 : :
13734 : 330922 : while ((c = *list_p) != NULL)
13735 : : {
13736 : 201796 : bool remove = false;
13737 : 201796 : bool notice_outer = true;
13738 : 201796 : bool map_descriptor;
13739 : 201796 : const char *check_non_private = NULL;
13740 : 201796 : unsigned int flags;
13741 : 201796 : tree decl;
13742 : 201796 : auto_vec<omp_addr_token *, 10> addr_tokens;
13743 : 201796 : tree op = NULL_TREE;
13744 : 201796 : location_t loc = OMP_CLAUSE_LOCATION (c);
13745 : :
13746 : 237299 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
13747 : : {
13748 : : grp_start_p = NULL;
13749 : : grp_end = NULL_TREE;
13750 : : }
13751 : :
13752 : 201796 : if (code == OMP_TARGET
13753 : : || code == OMP_TARGET_DATA
13754 : : || code == OMP_TARGET_ENTER_DATA
13755 : 171540 : || code == OMP_TARGET_EXIT_DATA)
13756 : : /* Do some target-specific type checks for map operands. */
13757 : 31802 : switch (OMP_CLAUSE_CODE (c))
13758 : : {
13759 : 22885 : case OMP_CLAUSE_MAP:
13760 : 22885 : op = OMP_CLAUSE_OPERAND (c, 0);
13761 : 22885 : verify_type_context (loc, TCTX_OMP_MAP, TREE_TYPE (op));
13762 : 22885 : break;
13763 : 129 : case OMP_CLAUSE_PRIVATE:
13764 : 129 : op = OMP_CLAUSE_OPERAND (c, 0);
13765 : 129 : verify_type_context (loc, TCTX_OMP_PRIVATE, TREE_TYPE (op));
13766 : 129 : break;
13767 : 1230 : case OMP_CLAUSE_FIRSTPRIVATE:
13768 : 1230 : op = OMP_CLAUSE_OPERAND (c, 0);
13769 : 1230 : verify_type_context (loc, TCTX_OMP_FIRSTPRIVATE, TREE_TYPE (op));
13770 : 1230 : break;
13771 : 2906 : case OMP_CLAUSE_IS_DEVICE_PTR:
13772 : 2906 : case OMP_CLAUSE_USE_DEVICE_ADDR:
13773 : 2906 : case OMP_CLAUSE_USE_DEVICE_PTR:
13774 : 2906 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
13775 : 2906 : op = OMP_CLAUSE_OPERAND (c, 0);
13776 : 2906 : verify_type_context (loc, TCTX_OMP_DEVICE_ADDR, TREE_TYPE (op));
13777 : 2906 : break;
13778 : : default:
13779 : : break;
13780 : : }
13781 : :
13782 : 201796 : switch (OMP_CLAUSE_CODE (c))
13783 : : {
13784 : 12156 : case OMP_CLAUSE_PRIVATE:
13785 : 12156 : flags = GOVD_PRIVATE | GOVD_EXPLICIT;
13786 : 12156 : if (lang_hooks.decls.omp_private_outer_ref (OMP_CLAUSE_DECL (c)))
13787 : : {
13788 : 165 : flags |= GOVD_PRIVATE_OUTER_REF;
13789 : 165 : OMP_CLAUSE_PRIVATE_OUTER_REF (c) = 1;
13790 : : }
13791 : : else
13792 : : notice_outer = false;
13793 : 12156 : goto do_add;
13794 : 5510 : case OMP_CLAUSE_SHARED:
13795 : 5510 : flags = GOVD_SHARED | GOVD_EXPLICIT;
13796 : 5510 : goto do_add;
13797 : 7837 : case OMP_CLAUSE_FIRSTPRIVATE:
13798 : 7837 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
13799 : 7837 : check_non_private = "firstprivate";
13800 : 7837 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
13801 : : {
13802 : 380 : gcc_assert (code == OMP_TARGET);
13803 : : flags |= GOVD_FIRSTPRIVATE_IMPLICIT;
13804 : : }
13805 : 7837 : goto do_add;
13806 : 7328 : case OMP_CLAUSE_LASTPRIVATE:
13807 : 7328 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13808 : 496 : switch (code)
13809 : : {
13810 : 25 : case OMP_DISTRIBUTE:
13811 : 25 : error_at (OMP_CLAUSE_LOCATION (c),
13812 : : "conditional %<lastprivate%> clause on "
13813 : : "%qs construct", "distribute");
13814 : 25 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13815 : 25 : break;
13816 : 13 : case OMP_TASKLOOP:
13817 : 13 : error_at (OMP_CLAUSE_LOCATION (c),
13818 : : "conditional %<lastprivate%> clause on "
13819 : : "%qs construct", "taskloop");
13820 : 13 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13821 : 13 : break;
13822 : : default:
13823 : : break;
13824 : : }
13825 : 7328 : flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
13826 : 7328 : if (code != OMP_LOOP)
13827 : 6977 : check_non_private = "lastprivate";
13828 : 7328 : decl = OMP_CLAUSE_DECL (c);
13829 : 7328 : if (error_operand_p (decl))
13830 : 0 : goto do_add;
13831 : 7328 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c)
13832 : 7328 : && !lang_hooks.decls.omp_scalar_p (decl, true))
13833 : : {
13834 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
13835 : : "non-scalar variable %qD in conditional "
13836 : : "%<lastprivate%> clause", decl);
13837 : 5 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
13838 : : }
13839 : 7328 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
13840 : 453 : flags |= GOVD_LASTPRIVATE_CONDITIONAL;
13841 : 7328 : omp_lastprivate_for_combined_outer_constructs (outer_ctx, decl,
13842 : : false);
13843 : 7328 : goto do_add;
13844 : 15211 : case OMP_CLAUSE_REDUCTION:
13845 : 15211 : if (OMP_CLAUSE_REDUCTION_TASK (c))
13846 : : {
13847 : 594 : if (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
13848 : : {
13849 : 408 : if (nowait == -1)
13850 : 293 : nowait = omp_find_clause (*list_p,
13851 : 293 : OMP_CLAUSE_NOWAIT) != NULL_TREE;
13852 : 408 : if (nowait
13853 : 15 : && (outer_ctx == NULL
13854 : 0 : || outer_ctx->region_type != ORT_COMBINED_PARALLEL))
13855 : : {
13856 : 15 : error_at (OMP_CLAUSE_LOCATION (c),
13857 : : "%<task%> reduction modifier on a construct "
13858 : : "with a %<nowait%> clause");
13859 : 15 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13860 : : }
13861 : : }
13862 : 186 : else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL)
13863 : : {
13864 : 40 : error_at (OMP_CLAUSE_LOCATION (c),
13865 : : "invalid %<task%> reduction modifier on construct "
13866 : : "other than %<parallel%>, %qs, %<sections%> or "
13867 : 20 : "%<scope%>", lang_GNU_Fortran () ? "do" : "for");
13868 : 20 : OMP_CLAUSE_REDUCTION_TASK (c) = 0;
13869 : : }
13870 : : }
13871 : 15211 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
13872 : 831 : switch (code)
13873 : : {
13874 : 4 : case OMP_SECTIONS:
13875 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
13876 : : "%<inscan%> %<reduction%> clause on "
13877 : : "%qs construct", "sections");
13878 : 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13879 : 4 : break;
13880 : 4 : case OMP_PARALLEL:
13881 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
13882 : : "%<inscan%> %<reduction%> clause on "
13883 : : "%qs construct", "parallel");
13884 : 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13885 : 4 : break;
13886 : 4 : case OMP_TEAMS:
13887 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
13888 : : "%<inscan%> %<reduction%> clause on "
13889 : : "%qs construct", "teams");
13890 : 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13891 : 4 : break;
13892 : 4 : case OMP_TASKLOOP:
13893 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
13894 : : "%<inscan%> %<reduction%> clause on "
13895 : : "%qs construct", "taskloop");
13896 : 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13897 : 4 : break;
13898 : 4 : case OMP_SCOPE:
13899 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
13900 : : "%<inscan%> %<reduction%> clause on "
13901 : : "%qs construct", "scope");
13902 : 4 : OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
13903 : 4 : break;
13904 : : default:
13905 : : break;
13906 : : }
13907 : : /* FALLTHRU */
13908 : 17811 : case OMP_CLAUSE_IN_REDUCTION:
13909 : 17811 : case OMP_CLAUSE_TASK_REDUCTION:
13910 : 17811 : flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
13911 : : /* OpenACC permits reductions on private variables. */
13912 : 17811 : if (!(region_type & ORT_ACC)
13913 : : /* taskgroup is actually not a worksharing region. */
13914 : 12292 : && code != OMP_TASKGROUP)
13915 : 11762 : check_non_private = omp_clause_code_name[OMP_CLAUSE_CODE (c)];
13916 : 17811 : decl = OMP_CLAUSE_DECL (c);
13917 : 17811 : if (TREE_CODE (decl) == MEM_REF)
13918 : : {
13919 : 2539 : tree type = TREE_TYPE (decl);
13920 : 2539 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
13921 : 2539 : gimplify_ctxp->into_ssa = false;
13922 : 2539 : if (gimplify_expr (&TYPE_MAX_VALUE (TYPE_DOMAIN (type)), pre_p,
13923 : : NULL, is_gimple_val, fb_rvalue, false)
13924 : : == GS_ERROR)
13925 : : {
13926 : 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13927 : 0 : remove = true;
13928 : 0 : break;
13929 : : }
13930 : 2539 : gimplify_ctxp->into_ssa = saved_into_ssa;
13931 : 2539 : tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
13932 : 2539 : if (DECL_P (v))
13933 : : {
13934 : 571 : omp_firstprivatize_variable (ctx, v);
13935 : 571 : omp_notice_variable (ctx, v, true);
13936 : : }
13937 : 2539 : decl = TREE_OPERAND (decl, 0);
13938 : 2539 : if (TREE_CODE (decl) == POINTER_PLUS_EXPR)
13939 : : {
13940 : 477 : gimplify_ctxp->into_ssa = false;
13941 : 477 : if (gimplify_expr (&TREE_OPERAND (decl, 1), pre_p,
13942 : : NULL, is_gimple_val, fb_rvalue, false)
13943 : : == GS_ERROR)
13944 : : {
13945 : 0 : gimplify_ctxp->into_ssa = saved_into_ssa;
13946 : 0 : remove = true;
13947 : 0 : break;
13948 : : }
13949 : 477 : gimplify_ctxp->into_ssa = saved_into_ssa;
13950 : 477 : v = TREE_OPERAND (decl, 1);
13951 : 477 : if (DECL_P (v))
13952 : : {
13953 : 477 : omp_firstprivatize_variable (ctx, v);
13954 : 477 : omp_notice_variable (ctx, v, true);
13955 : : }
13956 : 477 : decl = TREE_OPERAND (decl, 0);
13957 : : }
13958 : 2539 : if (TREE_CODE (decl) == ADDR_EXPR
13959 : 1352 : || TREE_CODE (decl) == INDIRECT_REF)
13960 : 1339 : decl = TREE_OPERAND (decl, 0);
13961 : : }
13962 : 17811 : goto do_add_decl;
13963 : 2668 : case OMP_CLAUSE_LINEAR:
13964 : 2668 : if (gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c), pre_p, NULL,
13965 : : is_gimple_val, fb_rvalue) == GS_ERROR)
13966 : : {
13967 : : remove = true;
13968 : : break;
13969 : : }
13970 : : else
13971 : : {
13972 : 2668 : if (code == OMP_SIMD
13973 : 2668 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
13974 : : {
13975 : 1154 : struct gimplify_omp_ctx *octx = outer_ctx;
13976 : 1154 : if (octx
13977 : 741 : && octx->region_type == ORT_WORKSHARE
13978 : 500 : && octx->combined_loop
13979 : 500 : && !octx->distribute)
13980 : : {
13981 : 492 : if (octx->outer_context
13982 : 430 : && (octx->outer_context->region_type
13983 : : == ORT_COMBINED_PARALLEL))
13984 : 393 : octx = octx->outer_context->outer_context;
13985 : : else
13986 : : octx = octx->outer_context;
13987 : : }
13988 : 905 : if (octx
13989 : 316 : && octx->region_type == ORT_WORKSHARE
13990 : 16 : && octx->combined_loop
13991 : 16 : && octx->distribute)
13992 : : {
13993 : 16 : error_at (OMP_CLAUSE_LOCATION (c),
13994 : : "%<linear%> clause for variable other than "
13995 : : "loop iterator specified on construct "
13996 : : "combined with %<distribute%>");
13997 : 16 : remove = true;
13998 : 16 : break;
13999 : : }
14000 : : }
14001 : : /* For combined #pragma omp parallel for simd, need to put
14002 : : lastprivate and perhaps firstprivate too on the
14003 : : parallel. Similarly for #pragma omp for simd. */
14004 : : struct gimplify_omp_ctx *octx = outer_ctx;
14005 : : bool taskloop_seen = false;
14006 : : decl = NULL_TREE;
14007 : 3443 : do
14008 : : {
14009 : 3443 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14010 : 3443 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14011 : : break;
14012 : 3383 : decl = OMP_CLAUSE_DECL (c);
14013 : 3383 : if (error_operand_p (decl))
14014 : : {
14015 : : decl = NULL_TREE;
14016 : : break;
14017 : : }
14018 : 3383 : flags = GOVD_SEEN;
14019 : 3383 : if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14020 : 1672 : flags |= GOVD_FIRSTPRIVATE;
14021 : 3383 : if (!OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14022 : 3383 : flags |= GOVD_LASTPRIVATE;
14023 : 3383 : if (octx
14024 : 2506 : && octx->region_type == ORT_WORKSHARE
14025 : 1213 : && octx->combined_loop)
14026 : : {
14027 : 1207 : if (octx->outer_context
14028 : 1037 : && (octx->outer_context->region_type
14029 : : == ORT_COMBINED_PARALLEL))
14030 : : octx = octx->outer_context;
14031 : 476 : else if (omp_check_private (octx, decl, false))
14032 : : break;
14033 : : }
14034 : : else if (octx
14035 : 1299 : && (octx->region_type & ORT_TASK) != 0
14036 : 307 : && octx->combined_loop)
14037 : : taskloop_seen = true;
14038 : : else if (octx
14039 : 996 : && octx->region_type == ORT_COMBINED_PARALLEL
14040 : 301 : && ((ctx->region_type == ORT_WORKSHARE
14041 : 201 : && octx == outer_ctx)
14042 : 100 : || taskloop_seen))
14043 : : flags = GOVD_SEEN | GOVD_SHARED;
14044 : : else if (octx
14045 : 695 : && ((octx->region_type & ORT_COMBINED_TEAMS)
14046 : : == ORT_COMBINED_TEAMS))
14047 : : flags = GOVD_SEEN | GOVD_SHARED;
14048 : 540 : else if (octx
14049 : 540 : && octx->region_type == ORT_COMBINED_TARGET)
14050 : : {
14051 : 195 : if (flags & GOVD_LASTPRIVATE)
14052 : 195 : flags = GOVD_SEEN | GOVD_MAP;
14053 : : }
14054 : : else
14055 : : break;
14056 : 2071 : splay_tree_node on
14057 : 2071 : = splay_tree_lookup (octx->variables,
14058 : : (splay_tree_key) decl);
14059 : 2071 : if (on && (on->value & GOVD_DATA_SHARE_CLASS) != 0)
14060 : : {
14061 : : octx = NULL;
14062 : : break;
14063 : : }
14064 : 2067 : omp_add_variable (octx, decl, flags);
14065 : 2067 : if (octx->outer_context == NULL)
14066 : : break;
14067 : : octx = octx->outer_context;
14068 : : }
14069 : : while (1);
14070 : 2652 : if (octx
14071 : 2652 : && decl
14072 : 2652 : && (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14073 : 728 : || !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
14074 : 1711 : omp_notice_variable (octx, decl, true);
14075 : : }
14076 : 2652 : flags = GOVD_LINEAR | GOVD_EXPLICIT;
14077 : 2652 : if (OMP_CLAUSE_LINEAR_NO_COPYIN (c)
14078 : 2652 : && OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
14079 : : {
14080 : : notice_outer = false;
14081 : : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
14082 : : }
14083 : 2652 : goto do_add;
14084 : :
14085 : 48456 : case OMP_CLAUSE_MAP:
14086 : 48456 : if (!grp_start_p)
14087 : : {
14088 : 29553 : grp_start_p = list_p;
14089 : 29553 : grp_end = (*groups)[grpnum].grp_end;
14090 : 29553 : grpnum++;
14091 : : }
14092 : 48456 : decl = OMP_CLAUSE_DECL (c);
14093 : :
14094 : 48456 : if (error_operand_p (decl))
14095 : : {
14096 : : remove = true;
14097 : : break;
14098 : : }
14099 : :
14100 : 48456 : if (!omp_parse_expr (addr_tokens, decl))
14101 : : {
14102 : : remove = true;
14103 : : break;
14104 : : }
14105 : :
14106 : 48456 : if (remove)
14107 : : break;
14108 : 48456 : if (DECL_P (decl) && outer_ctx && (region_type & ORT_ACC))
14109 : : {
14110 : : struct gimplify_omp_ctx *octx;
14111 : 1167 : for (octx = outer_ctx; octx; octx = octx->outer_context)
14112 : : {
14113 : 1167 : if (octx->region_type != ORT_ACC_HOST_DATA)
14114 : : break;
14115 : 12 : splay_tree_node n2
14116 : 12 : = splay_tree_lookup (octx->variables,
14117 : : (splay_tree_key) decl);
14118 : 12 : if (n2)
14119 : 4 : error_at (OMP_CLAUSE_LOCATION (c), "variable %qE "
14120 : : "declared in enclosing %<host_data%> region",
14121 : 4 : DECL_NAME (decl));
14122 : : }
14123 : : }
14124 : :
14125 : 48456 : map_descriptor = false;
14126 : :
14127 : : /* This condition checks if we're mapping an array descriptor that
14128 : : isn't inside a derived type -- these have special handling, and
14129 : : are not handled as structs in omp_build_struct_sibling_lists.
14130 : : See that function for further details. */
14131 : 48456 : if (*grp_start_p != grp_end
14132 : 32185 : && OMP_CLAUSE_CHAIN (*grp_start_p)
14133 : 80641 : && OMP_CLAUSE_CHAIN (*grp_start_p) != grp_end)
14134 : : {
14135 : 15475 : tree grp_mid = OMP_CLAUSE_CHAIN (*grp_start_p);
14136 : 15475 : if (omp_map_clause_descriptor_p (grp_mid)
14137 : 29183 : && DECL_P (OMP_CLAUSE_DECL (grp_mid)))
14138 : : map_descriptor = true;
14139 : : }
14140 : 32981 : else if (OMP_CLAUSE_CODE (grp_end) == OMP_CLAUSE_MAP
14141 : 32981 : && (OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_RELEASE
14142 : 32335 : || OMP_CLAUSE_MAP_KIND (grp_end) == GOMP_MAP_DELETE)
14143 : 33769 : && OMP_CLAUSE_RELEASE_DESCRIPTOR (grp_end))
14144 : : map_descriptor = true;
14145 : :
14146 : : /* Adding the decl for a struct access: we haven't created
14147 : : GOMP_MAP_STRUCT nodes yet, so this statement needs to predict
14148 : : whether they will be created in gimplify_adjust_omp_clauses.
14149 : : NOTE: Technically we should probably look through DECL_VALUE_EXPR
14150 : : here because something that looks like a DECL_P may actually be a
14151 : : struct access, e.g. variables in a lambda closure
14152 : : (__closure->__foo) or class members (this->foo). Currently in both
14153 : : those cases we map the whole of the containing object (directly in
14154 : : the C++ FE) though, so struct nodes are not created. */
14155 : 48456 : if (c == grp_end
14156 : 29553 : && addr_tokens[0]->type == STRUCTURE_BASE
14157 : 7619 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14158 : 56075 : && !map_descriptor)
14159 : : {
14160 : 4850 : gcc_assert (addr_tokens[1]->type == ACCESS_METHOD);
14161 : : /* If we got to this struct via a chain of pointers, maybe we
14162 : : want to map it implicitly instead. */
14163 : 4850 : if (omp_access_chain_p (addr_tokens, 1))
14164 : : break;
14165 : 4690 : omp_mapping_group *wholestruct;
14166 : 4690 : if (!(region_type & ORT_ACC)
14167 : 8109 : && omp_mapped_by_containing_struct (grpmap,
14168 : 3419 : OMP_CLAUSE_DECL (c),
14169 : : &wholestruct))
14170 : : break;
14171 : 4506 : decl = addr_tokens[1]->expr;
14172 : 4506 : if (splay_tree_lookup (ctx->variables, (splay_tree_key) decl))
14173 : : break;
14174 : : /* Standalone attach or detach clauses for a struct element
14175 : : should not inhibit implicit mapping of the whole struct. */
14176 : 2764 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
14177 : 2764 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)
14178 : : break;
14179 : 2614 : flags = GOVD_MAP | GOVD_EXPLICIT;
14180 : :
14181 : 2614 : gcc_assert (addr_tokens[1]->u.access_kind != ACCESS_DIRECT
14182 : : || TREE_ADDRESSABLE (decl));
14183 : 2614 : goto do_add_decl;
14184 : : }
14185 : :
14186 : 43606 : if (!DECL_P (decl))
14187 : : {
14188 : 19813 : tree d = decl, *pd;
14189 : 19813 : if (TREE_CODE (d) == ARRAY_REF)
14190 : : {
14191 : 4890 : while (TREE_CODE (d) == ARRAY_REF)
14192 : 2502 : d = TREE_OPERAND (d, 0);
14193 : 2388 : if (TREE_CODE (d) == COMPONENT_REF
14194 : 2388 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
14195 : : decl = d;
14196 : : }
14197 : 19813 : pd = &OMP_CLAUSE_DECL (c);
14198 : 19813 : if (d == decl
14199 : 17471 : && TREE_CODE (decl) == INDIRECT_REF
14200 : 13354 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
14201 : 1069 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
14202 : : == REFERENCE_TYPE)
14203 : 20464 : && (OMP_CLAUSE_MAP_KIND (c)
14204 : : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
14205 : : {
14206 : 647 : pd = &TREE_OPERAND (decl, 0);
14207 : 647 : decl = TREE_OPERAND (decl, 0);
14208 : : }
14209 : :
14210 : 19813 : if (addr_tokens[0]->type == STRUCTURE_BASE
14211 : 10275 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14212 : 10275 : && addr_tokens[1]->type == ACCESS_METHOD
14213 : 10275 : && (addr_tokens[1]->u.access_kind == ACCESS_POINTER
14214 : 9778 : || (addr_tokens[1]->u.access_kind
14215 : : == ACCESS_POINTER_OFFSET))
14216 : 20392 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)))
14217 : : {
14218 : 0 : tree base = addr_tokens[1]->expr;
14219 : 0 : splay_tree_node n
14220 : 0 : = splay_tree_lookup (ctx->variables,
14221 : : (splay_tree_key) base);
14222 : 0 : n->value |= GOVD_SEEN;
14223 : : }
14224 : :
14225 : 19813 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
14226 : : {
14227 : : /* Don't gimplify *pd fully at this point, as the base
14228 : : will need to be adjusted during omp lowering. */
14229 : 88 : auto_vec<tree, 10> expr_stack;
14230 : 88 : tree *p = pd;
14231 : 88 : while (handled_component_p (*p)
14232 : : || TREE_CODE (*p) == INDIRECT_REF
14233 : : || TREE_CODE (*p) == ADDR_EXPR
14234 : : || TREE_CODE (*p) == MEM_REF
14235 : 224 : || TREE_CODE (*p) == NON_LVALUE_EXPR)
14236 : : {
14237 : 136 : expr_stack.safe_push (*p);
14238 : 136 : p = &TREE_OPERAND (*p, 0);
14239 : : }
14240 : 312 : for (int i = expr_stack.length () - 1; i >= 0; i--)
14241 : : {
14242 : 136 : tree t = expr_stack[i];
14243 : 136 : if (TREE_CODE (t) == ARRAY_REF
14244 : 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14245 : : {
14246 : 56 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14247 : : {
14248 : 56 : tree low = unshare_expr (array_ref_low_bound (t));
14249 : 56 : if (!is_gimple_min_invariant (low))
14250 : : {
14251 : 0 : TREE_OPERAND (t, 2) = low;
14252 : 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14253 : : pre_p, NULL,
14254 : : is_gimple_reg,
14255 : : fb_rvalue) == GS_ERROR)
14256 : 0 : remove = true;
14257 : : }
14258 : : }
14259 : 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14260 : : NULL, is_gimple_reg,
14261 : : fb_rvalue) == GS_ERROR)
14262 : 0 : remove = true;
14263 : 56 : if (TREE_OPERAND (t, 3) == NULL_TREE)
14264 : : {
14265 : 56 : tree elmt_size = array_ref_element_size (t);
14266 : 56 : if (!is_gimple_min_invariant (elmt_size))
14267 : : {
14268 : 0 : elmt_size = unshare_expr (elmt_size);
14269 : 0 : tree elmt_type
14270 : 0 : = TREE_TYPE (TREE_TYPE (TREE_OPERAND (t,
14271 : : 0)));
14272 : 0 : tree factor
14273 : 0 : = size_int (TYPE_ALIGN_UNIT (elmt_type));
14274 : 0 : elmt_size
14275 : 0 : = size_binop (EXACT_DIV_EXPR, elmt_size,
14276 : : factor);
14277 : 0 : TREE_OPERAND (t, 3) = elmt_size;
14278 : 0 : if (gimplify_expr (&TREE_OPERAND (t, 3),
14279 : : pre_p, NULL,
14280 : : is_gimple_reg,
14281 : : fb_rvalue) == GS_ERROR)
14282 : 0 : remove = true;
14283 : : }
14284 : : }
14285 : 0 : else if (gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
14286 : : NULL, is_gimple_reg,
14287 : : fb_rvalue) == GS_ERROR)
14288 : 0 : remove = true;
14289 : : }
14290 : 80 : else if (TREE_CODE (t) == COMPONENT_REF)
14291 : : {
14292 : 0 : if (TREE_OPERAND (t, 2) == NULL_TREE)
14293 : : {
14294 : 0 : tree offset = component_ref_field_offset (t);
14295 : 0 : if (!is_gimple_min_invariant (offset))
14296 : : {
14297 : 0 : offset = unshare_expr (offset);
14298 : 0 : tree field = TREE_OPERAND (t, 1);
14299 : 0 : tree factor
14300 : 0 : = size_int (DECL_OFFSET_ALIGN (field)
14301 : : / BITS_PER_UNIT);
14302 : 0 : offset = size_binop (EXACT_DIV_EXPR, offset,
14303 : : factor);
14304 : 0 : TREE_OPERAND (t, 2) = offset;
14305 : 0 : if (gimplify_expr (&TREE_OPERAND (t, 2),
14306 : : pre_p, NULL,
14307 : : is_gimple_reg,
14308 : : fb_rvalue) == GS_ERROR)
14309 : 0 : remove = true;
14310 : : }
14311 : : }
14312 : 0 : else if (gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
14313 : : NULL, is_gimple_reg,
14314 : : fb_rvalue) == GS_ERROR)
14315 : 0 : remove = true;
14316 : : }
14317 : : }
14318 : 224 : for (; expr_stack.length () > 0; )
14319 : : {
14320 : 136 : tree t = expr_stack.pop ();
14321 : :
14322 : 136 : if (TREE_CODE (t) == ARRAY_REF
14323 : 136 : || TREE_CODE (t) == ARRAY_RANGE_REF)
14324 : : {
14325 : 56 : if (!is_gimple_min_invariant (TREE_OPERAND (t, 1))
14326 : 56 : && gimplify_expr (&TREE_OPERAND (t, 1), pre_p,
14327 : : NULL, is_gimple_val,
14328 : : fb_rvalue) == GS_ERROR)
14329 : 144 : remove = true;
14330 : : }
14331 : : }
14332 : 88 : }
14333 : : break;
14334 : : }
14335 : :
14336 : 23793 : if ((code == OMP_TARGET
14337 : : || code == OMP_TARGET_DATA
14338 : : || code == OMP_TARGET_ENTER_DATA
14339 : 14136 : || code == OMP_TARGET_EXIT_DATA)
14340 : 24351 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
14341 : : {
14342 : : /* If we have attach/detach but the decl we have is a pointer to
14343 : : pointer, we're probably mapping the "base level" array
14344 : : implicitly. Make sure we don't add the decl as if we mapped
14345 : : it explicitly. That is,
14346 : :
14347 : : int **arr;
14348 : : [...]
14349 : : #pragma omp target map(arr[a][b:c])
14350 : :
14351 : : should *not* map "arr" explicitly. That way we get a
14352 : : zero-length "alloc" mapping for it, and assuming it's been
14353 : : mapped by some previous directive, etc., things work as they
14354 : : should. */
14355 : :
14356 : 204 : tree basetype = TREE_TYPE (addr_tokens[0]->expr);
14357 : :
14358 : 204 : if (TREE_CODE (basetype) == REFERENCE_TYPE)
14359 : 34 : basetype = TREE_TYPE (basetype);
14360 : :
14361 : 204 : if (code == OMP_TARGET
14362 : 54 : && addr_tokens[0]->type == ARRAY_BASE
14363 : 54 : && addr_tokens[0]->u.structure_base_kind == BASE_DECL
14364 : 54 : && TREE_CODE (basetype) == POINTER_TYPE
14365 : 258 : && TREE_CODE (TREE_TYPE (basetype)) == POINTER_TYPE)
14366 : : break;
14367 : : }
14368 : :
14369 : 23771 : flags = GOVD_MAP | GOVD_EXPLICIT;
14370 : 23771 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TO
14371 : 23660 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_TOFROM
14372 : 23156 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TO
14373 : 46901 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_PRESENT_TOFROM)
14374 : : flags |= GOVD_MAP_ALWAYS_TO;
14375 : :
14376 : 23771 : goto do_add;
14377 : :
14378 : 374 : case OMP_CLAUSE_AFFINITY:
14379 : 374 : gimplify_omp_affinity (list_p, pre_p);
14380 : 374 : remove = true;
14381 : 374 : break;
14382 : 8 : case OMP_CLAUSE_DOACROSS:
14383 : 8 : if (OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
14384 : : {
14385 : 4 : tree deps = OMP_CLAUSE_DECL (c);
14386 : 8 : while (deps && TREE_CODE (deps) == TREE_LIST)
14387 : : {
14388 : 4 : if (TREE_CODE (TREE_PURPOSE (deps)) == TRUNC_DIV_EXPR
14389 : 4 : && DECL_P (TREE_OPERAND (TREE_PURPOSE (deps), 1)))
14390 : 0 : gimplify_expr (&TREE_OPERAND (TREE_PURPOSE (deps), 1),
14391 : : pre_p, NULL, is_gimple_val, fb_rvalue);
14392 : 4 : deps = TREE_CHAIN (deps);
14393 : : }
14394 : : }
14395 : : else
14396 : 4 : gcc_assert (OMP_CLAUSE_DOACROSS_KIND (c)
14397 : : == OMP_CLAUSE_DOACROSS_SOURCE);
14398 : : break;
14399 : 2200 : case OMP_CLAUSE_DEPEND:
14400 : 2200 : if (handled_depend_iterators == -1)
14401 : 1898 : handled_depend_iterators = gimplify_omp_depend (list_p, pre_p);
14402 : 2200 : if (handled_depend_iterators)
14403 : : {
14404 : 343 : if (handled_depend_iterators == 2)
14405 : 0 : remove = true;
14406 : : break;
14407 : : }
14408 : 1857 : if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPOUND_EXPR)
14409 : : {
14410 : 0 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (c), 0), pre_p,
14411 : : NULL, is_gimple_val, fb_rvalue);
14412 : 0 : OMP_CLAUSE_DECL (c) = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
14413 : : }
14414 : 1857 : if (error_operand_p (OMP_CLAUSE_DECL (c)))
14415 : : {
14416 : : remove = true;
14417 : : break;
14418 : : }
14419 : 1857 : if (OMP_CLAUSE_DECL (c) != null_pointer_node)
14420 : : {
14421 : 1826 : OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
14422 : 1826 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
14423 : : is_gimple_val, fb_rvalue) == GS_ERROR)
14424 : : {
14425 : : remove = true;
14426 : : break;
14427 : : }
14428 : : }
14429 : 1857 : if (code == OMP_TASK)
14430 : 1399 : ctx->has_depend = true;
14431 : : break;
14432 : :
14433 : 8207 : case OMP_CLAUSE_TO:
14434 : 8207 : case OMP_CLAUSE_FROM:
14435 : 8207 : case OMP_CLAUSE__CACHE_:
14436 : 8207 : decl = OMP_CLAUSE_DECL (c);
14437 : 8207 : if (error_operand_p (decl))
14438 : : {
14439 : : remove = true;
14440 : : break;
14441 : : }
14442 : 8207 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
14443 : 7435 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
14444 : 684 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
14445 : 8207 : gimple_seq *seq_p;
14446 : 8207 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
14447 : 8207 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
14448 : : is_gimple_val, fb_rvalue) == GS_ERROR)
14449 : : {
14450 : 0 : remove = true;
14451 : 0 : exit_omp_iterator_loop_context (c);
14452 : 0 : break;
14453 : : }
14454 : 8207 : if (!DECL_P (decl))
14455 : : {
14456 : 2020 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
14457 : : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
14458 : 0 : remove = true;
14459 : 2020 : exit_omp_iterator_loop_context (c);
14460 : 2020 : break;
14461 : : }
14462 : 6187 : exit_omp_iterator_loop_context (c);
14463 : 6187 : goto do_notice;
14464 : :
14465 : 125 : case OMP_CLAUSE__MAPPER_BINDING_:
14466 : 125 : {
14467 : 125 : tree name = OMP_CLAUSE__MAPPER_BINDING__ID (c);
14468 : 125 : tree var = OMP_CLAUSE__MAPPER_BINDING__DECL (c);
14469 : 125 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (var));
14470 : 125 : tree fndecl = OMP_CLAUSE__MAPPER_BINDING__MAPPER (c);
14471 : 125 : ctx->implicit_mappers->put ({ name, type }, fndecl);
14472 : 125 : remove = true;
14473 : 125 : break;
14474 : : }
14475 : :
14476 : 2118 : case OMP_CLAUSE_USE_DEVICE_PTR:
14477 : 2118 : case OMP_CLAUSE_USE_DEVICE_ADDR:
14478 : 2118 : flags = GOVD_EXPLICIT;
14479 : 2118 : goto do_add;
14480 : :
14481 : 543 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
14482 : 543 : decl = OMP_CLAUSE_DECL (c);
14483 : 543 : while (TREE_CODE (decl) == INDIRECT_REF
14484 : 592 : || TREE_CODE (decl) == ARRAY_REF)
14485 : 49 : decl = TREE_OPERAND (decl, 0);
14486 : 543 : flags = GOVD_EXPLICIT;
14487 : 543 : goto do_add_decl;
14488 : :
14489 : 498 : case OMP_CLAUSE_IS_DEVICE_PTR:
14490 : 498 : flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
14491 : 498 : goto do_add;
14492 : :
14493 : 62060 : do_add:
14494 : 62060 : decl = OMP_CLAUSE_DECL (c);
14495 : 83028 : do_add_decl:
14496 : 83028 : if (error_operand_p (decl))
14497 : : {
14498 : : remove = true;
14499 : : break;
14500 : : }
14501 : 83020 : if (DECL_NAME (decl) == NULL_TREE && (flags & GOVD_SHARED) == 0)
14502 : : {
14503 : 1765 : tree t = omp_member_access_dummy_var (decl);
14504 : 1765 : if (t)
14505 : : {
14506 : 668 : tree v = DECL_VALUE_EXPR (decl);
14507 : 668 : DECL_NAME (decl) = DECL_NAME (TREE_OPERAND (v, 1));
14508 : 668 : if (outer_ctx)
14509 : 140 : omp_notice_variable (outer_ctx, t, true);
14510 : : }
14511 : : }
14512 : 83020 : if (code == OACC_DATA
14513 : 2402 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14514 : 85422 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14515 : 307 : flags |= GOVD_MAP_0LEN_ARRAY;
14516 : 83020 : omp_add_variable (ctx, decl, flags);
14517 : 83020 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14518 : 67809 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION
14519 : 65739 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)
14520 : 85620 : && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
14521 : : {
14522 : 2087 : struct gimplify_omp_ctx *pctx
14523 : 2147 : = code == OMP_TARGET ? outer_ctx : ctx;
14524 : 2147 : if (pctx)
14525 : 2117 : omp_add_variable (pctx, OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
14526 : : GOVD_LOCAL | GOVD_SEEN);
14527 : 2117 : if (pctx
14528 : 2117 : && OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
14529 : 632 : && walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c),
14530 : : find_decl_expr,
14531 : : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14532 : : NULL) == NULL_TREE)
14533 : 208 : omp_add_variable (pctx,
14534 : 208 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
14535 : : GOVD_LOCAL | GOVD_SEEN);
14536 : 2147 : gimplify_omp_ctxp = pctx;
14537 : 2147 : push_gimplify_context ();
14538 : :
14539 : 2147 : OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
14540 : 2147 : OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
14541 : :
14542 : 2147 : gimplify_and_add (OMP_CLAUSE_REDUCTION_INIT (c),
14543 : 2147 : &OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c));
14544 : 2147 : pop_gimplify_context
14545 : 2147 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c)));
14546 : 2147 : push_gimplify_context ();
14547 : 4294 : gimplify_and_add (OMP_CLAUSE_REDUCTION_MERGE (c),
14548 : 2147 : &OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
14549 : 2147 : pop_gimplify_context
14550 : 2147 : (gimple_seq_first_stmt (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c)));
14551 : 2147 : OMP_CLAUSE_REDUCTION_INIT (c) = NULL_TREE;
14552 : 2147 : OMP_CLAUSE_REDUCTION_MERGE (c) = NULL_TREE;
14553 : :
14554 : 2147 : gimplify_omp_ctxp = outer_ctx;
14555 : : }
14556 : 80873 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
14557 : 80873 : && OMP_CLAUSE_LASTPRIVATE_STMT (c))
14558 : : {
14559 : 303 : gimplify_omp_ctxp = ctx;
14560 : 303 : push_gimplify_context ();
14561 : 303 : if (TREE_CODE (OMP_CLAUSE_LASTPRIVATE_STMT (c)) != BIND_EXPR)
14562 : : {
14563 : 303 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14564 : : NULL, NULL);
14565 : 303 : TREE_SIDE_EFFECTS (bind) = 1;
14566 : 303 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LASTPRIVATE_STMT (c);
14567 : 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = bind;
14568 : : }
14569 : 606 : gimplify_and_add (OMP_CLAUSE_LASTPRIVATE_STMT (c),
14570 : 303 : &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
14571 : 303 : pop_gimplify_context
14572 : 303 : (gimple_seq_first_stmt (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c)));
14573 : 303 : OMP_CLAUSE_LASTPRIVATE_STMT (c) = NULL_TREE;
14574 : :
14575 : 303 : gimplify_omp_ctxp = outer_ctx;
14576 : : }
14577 : 80570 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14578 : 80570 : && OMP_CLAUSE_LINEAR_STMT (c))
14579 : : {
14580 : 60 : gimplify_omp_ctxp = ctx;
14581 : 60 : push_gimplify_context ();
14582 : 60 : if (TREE_CODE (OMP_CLAUSE_LINEAR_STMT (c)) != BIND_EXPR)
14583 : : {
14584 : 60 : tree bind = build3 (BIND_EXPR, void_type_node, NULL,
14585 : : NULL, NULL);
14586 : 60 : TREE_SIDE_EFFECTS (bind) = 1;
14587 : 60 : BIND_EXPR_BODY (bind) = OMP_CLAUSE_LINEAR_STMT (c);
14588 : 60 : OMP_CLAUSE_LINEAR_STMT (c) = bind;
14589 : : }
14590 : 120 : gimplify_and_add (OMP_CLAUSE_LINEAR_STMT (c),
14591 : 60 : &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
14592 : 60 : pop_gimplify_context
14593 : 60 : (gimple_seq_first_stmt (OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c)));
14594 : 60 : OMP_CLAUSE_LINEAR_STMT (c) = NULL_TREE;
14595 : :
14596 : 60 : gimplify_omp_ctxp = outer_ctx;
14597 : : }
14598 : 83020 : if (notice_outer)
14599 : 70969 : goto do_notice;
14600 : : break;
14601 : :
14602 : 906 : case OMP_CLAUSE_COPYIN:
14603 : 906 : case OMP_CLAUSE_COPYPRIVATE:
14604 : 906 : decl = OMP_CLAUSE_DECL (c);
14605 : 906 : if (error_operand_p (decl))
14606 : : {
14607 : : remove = true;
14608 : : break;
14609 : : }
14610 : 906 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_COPYPRIVATE
14611 : : && !remove
14612 : 906 : && !omp_check_private (ctx, decl, true))
14613 : : {
14614 : 35 : remove = true;
14615 : 35 : if (is_global_var (decl))
14616 : : {
14617 : 30 : if (DECL_THREAD_LOCAL_P (decl))
14618 : : remove = false;
14619 : 10 : else if (DECL_HAS_VALUE_EXPR_P (decl))
14620 : : {
14621 : 2 : tree value = get_base_address (DECL_VALUE_EXPR (decl));
14622 : :
14623 : 2 : if (value
14624 : 2 : && DECL_P (value)
14625 : 4 : && DECL_THREAD_LOCAL_P (value))
14626 : : remove = false;
14627 : : }
14628 : : }
14629 : : if (remove)
14630 : 13 : error_at (OMP_CLAUSE_LOCATION (c),
14631 : : "copyprivate variable %qE is not threadprivate"
14632 : 13 : " or private in outer context", DECL_NAME (decl));
14633 : : }
14634 : 78062 : do_notice:
14635 : 78062 : if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14636 : 62851 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
14637 : 55014 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
14638 : 30376 : && outer_ctx
14639 : 17542 : && ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP
14640 : 16203 : || (region_type == ORT_WORKSHARE
14641 : 3884 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14642 : 1087 : && (OMP_CLAUSE_REDUCTION_INSCAN (c)
14643 : 912 : || code == OMP_LOOP)))
14644 : 80007 : && (outer_ctx->region_type == ORT_COMBINED_PARALLEL
14645 : 857 : || (code == OMP_LOOP
14646 : 138 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14647 : 138 : && ((outer_ctx->region_type & ORT_COMBINED_TEAMS)
14648 : : == ORT_COMBINED_TEAMS))))
14649 : : {
14650 : 1209 : splay_tree_node on
14651 : 1209 : = splay_tree_lookup (outer_ctx->variables,
14652 : : (splay_tree_key)decl);
14653 : 1209 : if (on == NULL || (on->value & GOVD_DATA_SHARE_CLASS) == 0)
14654 : : {
14655 : 891 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
14656 : 705 : && TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14657 : 1003 : && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
14658 : 56 : || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
14659 : 0 : && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl)))
14660 : : == POINTER_TYPE))))
14661 : 56 : omp_firstprivatize_variable (outer_ctx, decl);
14662 : : else
14663 : : {
14664 : 835 : omp_add_variable (outer_ctx, decl,
14665 : : GOVD_SEEN | GOVD_SHARED);
14666 : 835 : if (outer_ctx->outer_context)
14667 : 235 : omp_notice_variable (outer_ctx->outer_context, decl,
14668 : : true);
14669 : : }
14670 : : }
14671 : : }
14672 : 77462 : if (outer_ctx)
14673 : 29583 : omp_notice_variable (outer_ctx, decl, true);
14674 : 78062 : if (check_non_private
14675 : 26576 : && (region_type == ORT_WORKSHARE || code == OMP_SCOPE)
14676 : 4747 : && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
14677 : 1641 : || decl == OMP_CLAUSE_DECL (c)
14678 : 224 : || (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
14679 : 224 : && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14680 : : == ADDR_EXPR
14681 : 113 : || (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14682 : : == POINTER_PLUS_EXPR
14683 : 22 : && (TREE_CODE (TREE_OPERAND (TREE_OPERAND
14684 : : (OMP_CLAUSE_DECL (c), 0), 0))
14685 : : == ADDR_EXPR)))))
14686 : 82707 : && omp_check_private (ctx, decl, false))
14687 : : {
14688 : 58 : error ("%s variable %qE is private in outer context",
14689 : 29 : check_non_private, DECL_NAME (decl));
14690 : 29 : remove = true;
14691 : : }
14692 : : break;
14693 : :
14694 : 190 : case OMP_CLAUSE_DETACH:
14695 : 190 : flags = GOVD_FIRSTPRIVATE | GOVD_SEEN;
14696 : 190 : goto do_add;
14697 : :
14698 : 4092 : case OMP_CLAUSE_IF:
14699 : 4092 : if (OMP_CLAUSE_IF_MODIFIER (c) != ERROR_MARK
14700 : 4092 : && OMP_CLAUSE_IF_MODIFIER (c) != code)
14701 : : {
14702 : : const char *p[2];
14703 : 168 : for (int i = 0; i < 2; i++)
14704 : 112 : switch (i ? OMP_CLAUSE_IF_MODIFIER (c) : code)
14705 : : {
14706 : 8 : case VOID_CST: p[i] = "cancel"; break;
14707 : 24 : case OMP_PARALLEL: p[i] = "parallel"; break;
14708 : 4 : case OMP_SIMD: p[i] = "simd"; break;
14709 : 12 : case OMP_TASK: p[i] = "task"; break;
14710 : 12 : case OMP_TASKLOOP: p[i] = "taskloop"; break;
14711 : 8 : case OMP_TARGET_DATA: p[i] = "target data"; break;
14712 : 12 : case OMP_TARGET: p[i] = "target"; break;
14713 : 12 : case OMP_TARGET_UPDATE: p[i] = "target update"; break;
14714 : 8 : case OMP_TARGET_ENTER_DATA:
14715 : 8 : p[i] = "target enter data"; break;
14716 : 12 : case OMP_TARGET_EXIT_DATA: p[i] = "target exit data"; break;
14717 : 0 : default: gcc_unreachable ();
14718 : : }
14719 : 56 : error_at (OMP_CLAUSE_LOCATION (c),
14720 : : "expected %qs %<if%> clause modifier rather than %qs",
14721 : : p[0], p[1]);
14722 : 56 : remove = true;
14723 : : }
14724 : : /* Fall through. */
14725 : :
14726 : 4798 : case OMP_CLAUSE_SELF:
14727 : 4798 : case OMP_CLAUSE_FINAL:
14728 : 4798 : OMP_CLAUSE_OPERAND (c, 0)
14729 : 9596 : = gimple_boolify (OMP_CLAUSE_OPERAND (c, 0));
14730 : : /* Fall through. */
14731 : :
14732 : 5701 : case OMP_CLAUSE_NUM_TEAMS:
14733 : 5701 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
14734 : 903 : && OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14735 : 5946 : && !is_gimple_min_invariant (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14736 : : {
14737 : 208 : if (error_operand_p (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)))
14738 : : {
14739 : : remove = true;
14740 : : break;
14741 : : }
14742 : 208 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
14743 : 416 : = get_initialized_tmp_var (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c),
14744 : : pre_p, NULL, true);
14745 : : }
14746 : : /* Fall through. */
14747 : :
14748 : 21728 : case OMP_CLAUSE_SCHEDULE:
14749 : 21728 : case OMP_CLAUSE_NUM_THREADS:
14750 : 21728 : case OMP_CLAUSE_THREAD_LIMIT:
14751 : 21728 : case OMP_CLAUSE_DIST_SCHEDULE:
14752 : 21728 : case OMP_CLAUSE_DEVICE:
14753 : 21728 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14754 : 21728 : && OMP_CLAUSE_DEVICE_ANCESTOR (c))
14755 : : {
14756 : 125 : if (code != OMP_TARGET)
14757 : : {
14758 : 20 : error_at (OMP_CLAUSE_LOCATION (c),
14759 : : "%<device%> clause with %<ancestor%> is only "
14760 : : "allowed on %<target%> construct");
14761 : 20 : remove = true;
14762 : 20 : break;
14763 : : }
14764 : :
14765 : 105 : tree clauses = *orig_list_p;
14766 : 330 : for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
14767 : 236 : if (OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEVICE
14768 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_FIRSTPRIVATE
14769 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_PRIVATE
14770 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_DEFAULTMAP
14771 : : && OMP_CLAUSE_CODE (clauses) != OMP_CLAUSE_MAP
14772 : : )
14773 : : {
14774 : 11 : error_at (OMP_CLAUSE_LOCATION (c),
14775 : : "with %<ancestor%>, only the %<device%>, "
14776 : : "%<firstprivate%>, %<private%>, %<defaultmap%>, "
14777 : : "and %<map%> clauses may appear on the "
14778 : : "construct");
14779 : 11 : remove = true;
14780 : 11 : break;
14781 : : }
14782 : : }
14783 : 21603 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE
14784 : 21603 : && code == OMP_DISPATCH)
14785 : : {
14786 : 272 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
14787 : 272 : gimplify_ctxp->into_ssa = false;
14788 : 272 : if (gimplify_expr (&OMP_CLAUSE_DEVICE_ID (c), pre_p, NULL,
14789 : : is_gimple_val, fb_rvalue)
14790 : : == GS_ERROR)
14791 : : remove = true;
14792 : 272 : else if (DECL_P (OMP_CLAUSE_DEVICE_ID (c)))
14793 : 55 : omp_add_variable (ctx, OMP_CLAUSE_DEVICE_ID (c),
14794 : : GOVD_SHARED | GOVD_SEEN);
14795 : 272 : gimplify_ctxp->into_ssa = saved_into_ssa;
14796 : 272 : break;
14797 : : }
14798 : : /* Fall through. */
14799 : :
14800 : 31165 : case OMP_CLAUSE_PRIORITY:
14801 : 31165 : case OMP_CLAUSE_GRAINSIZE:
14802 : 31165 : case OMP_CLAUSE_NUM_TASKS:
14803 : 31165 : case OMP_CLAUSE_FILTER:
14804 : 31165 : case OMP_CLAUSE_HINT:
14805 : 31165 : case OMP_CLAUSE_ASYNC:
14806 : 31165 : case OMP_CLAUSE_WAIT:
14807 : 31165 : case OMP_CLAUSE_NUM_GANGS:
14808 : 31165 : case OMP_CLAUSE_NUM_WORKERS:
14809 : 31165 : case OMP_CLAUSE_VECTOR_LENGTH:
14810 : 31165 : case OMP_CLAUSE_WORKER:
14811 : 31165 : case OMP_CLAUSE_VECTOR:
14812 : 31165 : if (OMP_CLAUSE_OPERAND (c, 0)
14813 : 31165 : && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0)))
14814 : : {
14815 : 7722 : if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0)))
14816 : : {
14817 : : remove = true;
14818 : : break;
14819 : : }
14820 : : /* All these clauses care about value, not a particular decl,
14821 : : so try to force it into a SSA_NAME or fresh temporary. */
14822 : 7715 : OMP_CLAUSE_OPERAND (c, 0)
14823 : 15430 : = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0),
14824 : : pre_p, NULL, true);
14825 : : }
14826 : : break;
14827 : :
14828 : 2331 : case OMP_CLAUSE_GANG:
14829 : 2331 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
14830 : : is_gimple_val, fb_rvalue) == GS_ERROR)
14831 : 0 : remove = true;
14832 : 2331 : if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 1), pre_p, NULL,
14833 : : is_gimple_val, fb_rvalue) == GS_ERROR)
14834 : 0 : remove = true;
14835 : : break;
14836 : :
14837 : : case OMP_CLAUSE_NOWAIT:
14838 : 200397 : nowait = 1;
14839 : : break;
14840 : :
14841 : : case OMP_CLAUSE_ORDERED:
14842 : : case OMP_CLAUSE_UNTIED:
14843 : : case OMP_CLAUSE_COLLAPSE:
14844 : : case OMP_CLAUSE_TILE:
14845 : : case OMP_CLAUSE_AUTO:
14846 : : case OMP_CLAUSE_SEQ:
14847 : : case OMP_CLAUSE_INDEPENDENT:
14848 : : case OMP_CLAUSE_MERGEABLE:
14849 : : case OMP_CLAUSE_PROC_BIND:
14850 : : case OMP_CLAUSE_SAFELEN:
14851 : : case OMP_CLAUSE_SIMDLEN:
14852 : : case OMP_CLAUSE_NOGROUP:
14853 : : case OMP_CLAUSE_THREADS:
14854 : : case OMP_CLAUSE_SIMD:
14855 : : case OMP_CLAUSE_BIND:
14856 : : case OMP_CLAUSE_IF_PRESENT:
14857 : : case OMP_CLAUSE_FINALIZE:
14858 : : case OMP_CLAUSE_INTEROP:
14859 : : case OMP_CLAUSE_INIT:
14860 : : case OMP_CLAUSE_USE:
14861 : : case OMP_CLAUSE_DESTROY:
14862 : : break;
14863 : :
14864 : 3976 : case OMP_CLAUSE_ORDER:
14865 : 3976 : ctx->order_concurrent = true;
14866 : 3976 : break;
14867 : :
14868 : 1014 : case OMP_CLAUSE_DEFAULTMAP:
14869 : 1014 : enum gimplify_defaultmap_kind gdmkmin, gdmkmax;
14870 : 1014 : switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c))
14871 : : {
14872 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
14873 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
14874 : : gdmkmin = GDMK_SCALAR;
14875 : : gdmkmax = GDMK_POINTER;
14876 : : break;
14877 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
14878 : : gdmkmin = GDMK_SCALAR;
14879 : : gdmkmax = GDMK_SCALAR_TARGET;
14880 : : break;
14881 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
14882 : : gdmkmin = gdmkmax = GDMK_AGGREGATE;
14883 : : break;
14884 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE:
14885 : : gdmkmin = gdmkmax = GDMK_ALLOCATABLE;
14886 : : break;
14887 : : case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
14888 : : gdmkmin = gdmkmax = GDMK_POINTER;
14889 : : break;
14890 : 0 : default:
14891 : 0 : gcc_unreachable ();
14892 : : }
14893 : 4487 : for (int gdmk = gdmkmin; gdmk <= gdmkmax; gdmk++)
14894 : 3473 : switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (c))
14895 : : {
14896 : 91 : case OMP_CLAUSE_DEFAULTMAP_ALLOC:
14897 : 91 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_ALLOC_ONLY;
14898 : 91 : break;
14899 : 121 : case OMP_CLAUSE_DEFAULTMAP_TO:
14900 : 121 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_TO_ONLY;
14901 : 121 : break;
14902 : 28 : case OMP_CLAUSE_DEFAULTMAP_FROM:
14903 : 28 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FROM_ONLY;
14904 : 28 : break;
14905 : 671 : case OMP_CLAUSE_DEFAULTMAP_TOFROM:
14906 : 671 : ctx->defaultmap[gdmk] = GOVD_MAP;
14907 : 671 : break;
14908 : 380 : case OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE:
14909 : 380 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14910 : 380 : break;
14911 : 2079 : case OMP_CLAUSE_DEFAULTMAP_NONE:
14912 : 2079 : ctx->defaultmap[gdmk] = 0;
14913 : 2079 : break;
14914 : 45 : case OMP_CLAUSE_DEFAULTMAP_PRESENT:
14915 : 45 : ctx->defaultmap[gdmk] = GOVD_MAP | GOVD_MAP_FORCE_PRESENT;
14916 : 45 : break;
14917 : 58 : case OMP_CLAUSE_DEFAULTMAP_DEFAULT:
14918 : 58 : switch (gdmk)
14919 : : {
14920 : 11 : case GDMK_SCALAR:
14921 : 11 : ctx->defaultmap[gdmk] = GOVD_FIRSTPRIVATE;
14922 : 11 : break;
14923 : 11 : case GDMK_SCALAR_TARGET:
14924 : 11 : ctx->defaultmap[gdmk] = (lang_GNU_Fortran ()
14925 : 11 : ? GOVD_MAP : GOVD_FIRSTPRIVATE);
14926 : 11 : break;
14927 : 14 : case GDMK_AGGREGATE:
14928 : 14 : case GDMK_ALLOCATABLE:
14929 : 14 : ctx->defaultmap[gdmk] = GOVD_MAP;
14930 : 14 : break;
14931 : 22 : case GDMK_POINTER:
14932 : 22 : ctx->defaultmap[gdmk] = GOVD_MAP;
14933 : 22 : if (!lang_GNU_Fortran ())
14934 : 14 : ctx->defaultmap[gdmk] |= GOVD_MAP_0LEN_ARRAY;
14935 : : break;
14936 : : default:
14937 : : gcc_unreachable ();
14938 : : }
14939 : : break;
14940 : 0 : default:
14941 : 0 : gcc_unreachable ();
14942 : : }
14943 : : break;
14944 : :
14945 : 824 : case OMP_CLAUSE_ALIGNED:
14946 : 824 : decl = OMP_CLAUSE_DECL (c);
14947 : 824 : if (error_operand_p (decl))
14948 : : {
14949 : : remove = true;
14950 : : break;
14951 : : }
14952 : 824 : if (gimplify_expr (&OMP_CLAUSE_ALIGNED_ALIGNMENT (c), pre_p, NULL,
14953 : : is_gimple_val, fb_rvalue) == GS_ERROR)
14954 : : {
14955 : : remove = true;
14956 : : break;
14957 : : }
14958 : 824 : if (!is_global_var (decl)
14959 : 824 : && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
14960 : 592 : omp_add_variable (ctx, decl, GOVD_ALIGNED);
14961 : : break;
14962 : :
14963 : 489 : case OMP_CLAUSE_NONTEMPORAL:
14964 : 489 : decl = OMP_CLAUSE_DECL (c);
14965 : 489 : if (error_operand_p (decl))
14966 : : {
14967 : : remove = true;
14968 : : break;
14969 : : }
14970 : 489 : omp_add_variable (ctx, decl, GOVD_NONTEMPORAL);
14971 : 489 : break;
14972 : :
14973 : 3421 : case OMP_CLAUSE_ALLOCATE:
14974 : 3421 : decl = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
14975 : 3421 : if (decl
14976 : 1580 : && TREE_CODE (decl) == INTEGER_CST
14977 : 3450 : && wi::eq_p (wi::to_widest (decl), GOMP_OMP_PREDEF_ALLOC_THREADS)
14978 : 3450 : && (code == OMP_TARGET || code == OMP_TASK || code == OMP_TASKLOOP))
14979 : 35 : warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
14980 : : "allocator with access trait set to %<thread%> "
14981 : : "results in undefined behavior for %qs directive",
14982 : : code == OMP_TARGET ? "target"
14983 : : : (code == OMP_TASK
14984 : 15 : ? "task" : "taskloop"));
14985 : 3421 : decl = OMP_CLAUSE_DECL (c);
14986 : 3421 : if (error_operand_p (decl))
14987 : : {
14988 : : remove = true;
14989 : : break;
14990 : : }
14991 : 3421 : if (gimplify_expr (&OMP_CLAUSE_ALLOCATE_ALLOCATOR (c), pre_p, NULL,
14992 : : is_gimple_val, fb_rvalue) == GS_ERROR)
14993 : : {
14994 : : remove = true;
14995 : : break;
14996 : : }
14997 : 3421 : else if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) == NULL_TREE
14998 : 3421 : || (TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))
14999 : : == INTEGER_CST))
15000 : : ;
15001 : 491 : else if (code == OMP_TASKLOOP
15002 : 491 : || !DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
15003 : 66 : OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
15004 : 132 : = get_initialized_tmp_var (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
15005 : : pre_p, NULL, false);
15006 : : break;
15007 : :
15008 : 4349 : case OMP_CLAUSE_DEFAULT:
15009 : 4349 : ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
15010 : 4349 : break;
15011 : :
15012 : 640 : case OMP_CLAUSE_INCLUSIVE:
15013 : 640 : case OMP_CLAUSE_EXCLUSIVE:
15014 : 640 : decl = OMP_CLAUSE_DECL (c);
15015 : 640 : {
15016 : 640 : splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
15017 : : (splay_tree_key) decl);
15018 : 640 : if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
15019 : : {
15020 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
15021 : : "%qD specified in %qs clause but not in %<inscan%> "
15022 : : "%<reduction%> clause on the containing construct",
15023 : 5 : decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
15024 : 5 : remove = true;
15025 : : }
15026 : : else
15027 : : {
15028 : 635 : n->value |= GOVD_REDUCTION_INSCAN;
15029 : 635 : if (outer_ctx->region_type == ORT_SIMD
15030 : 520 : && outer_ctx->outer_context
15031 : 107 : && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
15032 : : {
15033 : 107 : n = splay_tree_lookup (outer_ctx->outer_context->variables,
15034 : : (splay_tree_key) decl);
15035 : 107 : if (n && (n->value & GOVD_REDUCTION) != 0)
15036 : 107 : n->value |= GOVD_REDUCTION_INSCAN;
15037 : : }
15038 : : }
15039 : : }
15040 : : break;
15041 : :
15042 : 97 : case OMP_CLAUSE_NOVARIANTS:
15043 : 97 : OMP_CLAUSE_NOVARIANTS_EXPR (c)
15044 : 97 : = gimple_boolify (OMP_CLAUSE_NOVARIANTS_EXPR (c));
15045 : 97 : break;
15046 : 115 : case OMP_CLAUSE_NOCONTEXT:
15047 : 115 : OMP_CLAUSE_NOCONTEXT_EXPR (c)
15048 : 115 : = gimple_boolify (OMP_CLAUSE_NOCONTEXT_EXPR (c));
15049 : 115 : break;
15050 : 0 : case OMP_CLAUSE_NOHOST:
15051 : 0 : default:
15052 : 0 : gcc_unreachable ();
15053 : : }
15054 : :
15055 : 1399 : if (code == OACC_DATA
15056 : 5123 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15057 : 205208 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15058 : 4504 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15059 : : remove = true;
15060 : 201489 : if (remove)
15061 : 971 : *list_p = OMP_CLAUSE_CHAIN (c);
15062 : : else
15063 : 200825 : list_p = &OMP_CLAUSE_CHAIN (c);
15064 : 201796 : }
15065 : :
15066 : 129126 : if (groups)
15067 : : {
15068 : 34802 : delete grpmap;
15069 : 17401 : delete groups;
15070 : : }
15071 : :
15072 : 129126 : ctx->clauses = *orig_list_p;
15073 : 129126 : gimplify_omp_ctxp = ctx;
15074 : 129126 : }
15075 : :
15076 : : /* Return true if DECL is a candidate for shared to firstprivate
15077 : : optimization. We only consider non-addressable scalars, not
15078 : : too big, and not references. */
15079 : :
15080 : : static bool
15081 : 404514 : omp_shared_to_firstprivate_optimizable_decl_p (tree decl)
15082 : : {
15083 : 404514 : if (TREE_ADDRESSABLE (decl))
15084 : : return false;
15085 : 355833 : tree type = TREE_TYPE (decl);
15086 : 355833 : if (!is_gimple_reg_type (type)
15087 : 331097 : || TREE_CODE (type) == REFERENCE_TYPE
15088 : 681354 : || TREE_ADDRESSABLE (type))
15089 : : return false;
15090 : : /* Don't optimize too large decls, as each thread/task will have
15091 : : its own. */
15092 : 325521 : HOST_WIDE_INT len = int_size_in_bytes (type);
15093 : 325521 : if (len == -1 || len > 4 * POINTER_SIZE / BITS_PER_UNIT)
15094 : : return false;
15095 : 325504 : if (omp_privatize_by_reference (decl))
15096 : : return false;
15097 : : return true;
15098 : : }
15099 : :
15100 : : /* Helper function of omp_find_stores_op and gimplify_adjust_omp_clauses*.
15101 : : For omp_shared_to_firstprivate_optimizable_decl_p decl mark it as
15102 : : GOVD_WRITTEN in outer contexts. */
15103 : :
15104 : : static void
15105 : 302635 : omp_mark_stores (struct gimplify_omp_ctx *ctx, tree decl)
15106 : : {
15107 : 464404 : for (; ctx; ctx = ctx->outer_context)
15108 : : {
15109 : 447428 : splay_tree_node n = splay_tree_lookup (ctx->variables,
15110 : : (splay_tree_key) decl);
15111 : 447428 : if (n == NULL)
15112 : 158190 : continue;
15113 : 289238 : else if (n->value & GOVD_SHARED)
15114 : : {
15115 : 9094 : n->value |= GOVD_WRITTEN;
15116 : 9094 : return;
15117 : : }
15118 : 280144 : else if (n->value & GOVD_DATA_SHARE_CLASS)
15119 : : return;
15120 : : }
15121 : : }
15122 : :
15123 : : /* Helper callback for walk_gimple_seq to discover possible stores
15124 : : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15125 : : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15126 : : for those. */
15127 : :
15128 : : static tree
15129 : 1124727 : omp_find_stores_op (tree *tp, int *walk_subtrees, void *data)
15130 : : {
15131 : 1124727 : struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15132 : :
15133 : 1124727 : *walk_subtrees = 0;
15134 : 1124727 : if (!wi->is_lhs)
15135 : : return NULL_TREE;
15136 : :
15137 : 321589 : tree op = *tp;
15138 : 400308 : do
15139 : : {
15140 : 400308 : if (handled_component_p (op))
15141 : 78719 : op = TREE_OPERAND (op, 0);
15142 : 321589 : else if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
15143 : 321589 : && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
15144 : 0 : op = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
15145 : : else
15146 : : break;
15147 : : }
15148 : : while (1);
15149 : 321589 : if (!DECL_P (op) || !omp_shared_to_firstprivate_optimizable_decl_p (op))
15150 : 59233 : return NULL_TREE;
15151 : :
15152 : 262356 : omp_mark_stores (gimplify_omp_ctxp, op);
15153 : 262356 : return NULL_TREE;
15154 : : }
15155 : :
15156 : : /* Helper callback for walk_gimple_seq to discover possible stores
15157 : : to omp_shared_to_firstprivate_optimizable_decl_p decls and set
15158 : : GOVD_WRITTEN if they are GOVD_SHARED in some outer context
15159 : : for those. */
15160 : :
15161 : : static tree
15162 : 624679 : omp_find_stores_stmt (gimple_stmt_iterator *gsi_p,
15163 : : bool *handled_ops_p,
15164 : : struct walk_stmt_info *wi)
15165 : : {
15166 : 624679 : gimple *stmt = gsi_stmt (*gsi_p);
15167 : 624679 : switch (gimple_code (stmt))
15168 : : {
15169 : : /* Don't recurse on OpenMP constructs for which
15170 : : gimplify_adjust_omp_clauses already handled the bodies,
15171 : : except handle gimple_omp_for_pre_body. */
15172 : 26682 : case GIMPLE_OMP_FOR:
15173 : 26682 : *handled_ops_p = true;
15174 : 26682 : if (gimple_omp_for_pre_body (stmt))
15175 : 1777 : walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15176 : : omp_find_stores_stmt, omp_find_stores_op, wi);
15177 : : break;
15178 : 8564 : case GIMPLE_OMP_PARALLEL:
15179 : 8564 : case GIMPLE_OMP_TASK:
15180 : 8564 : case GIMPLE_OMP_SECTIONS:
15181 : 8564 : case GIMPLE_OMP_SINGLE:
15182 : 8564 : case GIMPLE_OMP_SCOPE:
15183 : 8564 : case GIMPLE_OMP_TARGET:
15184 : 8564 : case GIMPLE_OMP_TEAMS:
15185 : 8564 : case GIMPLE_OMP_CRITICAL:
15186 : 8564 : *handled_ops_p = true;
15187 : 8564 : break;
15188 : : default:
15189 : : break;
15190 : : }
15191 : 624679 : return NULL_TREE;
15192 : : }
15193 : :
15194 : : struct gimplify_adjust_omp_clauses_data
15195 : : {
15196 : : tree *list_p;
15197 : : gimple_seq *pre_p;
15198 : : };
15199 : :
15200 : : /* For all variables that were not actually used within the context,
15201 : : remove PRIVATE, SHARED, and FIRSTPRIVATE clauses. */
15202 : :
15203 : : static int
15204 : 662740 : gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
15205 : : {
15206 : 662740 : tree *list_p = ((struct gimplify_adjust_omp_clauses_data *) data)->list_p;
15207 : 662740 : gimple_seq *pre_p
15208 : : = ((struct gimplify_adjust_omp_clauses_data *) data)->pre_p;
15209 : 662740 : tree decl = (tree) n->key;
15210 : 662740 : unsigned flags = n->value;
15211 : 662740 : enum omp_clause_code code;
15212 : 662740 : tree clause;
15213 : 662740 : bool private_debug;
15214 : :
15215 : 662740 : if (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
15216 : 132762 : && (flags & GOVD_LASTPRIVATE_CONDITIONAL) != 0)
15217 : : flags = GOVD_SHARED | GOVD_SEEN | GOVD_WRITTEN;
15218 : 662615 : if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
15219 : : return 0;
15220 : 177782 : if ((flags & GOVD_SEEN) == 0)
15221 : : return 0;
15222 : 156959 : if (flags & GOVD_DEBUG_PRIVATE)
15223 : : {
15224 : 256 : gcc_assert ((flags & GOVD_DATA_SHARE_CLASS) == GOVD_SHARED);
15225 : : private_debug = true;
15226 : : }
15227 : 156703 : else if (flags & GOVD_MAP)
15228 : : private_debug = false;
15229 : : else
15230 : 138684 : private_debug
15231 : 138684 : = lang_hooks.decls.omp_private_debug_clause (decl,
15232 : 138684 : !!(flags & GOVD_SHARED));
15233 : 138684 : if (private_debug)
15234 : : code = OMP_CLAUSE_PRIVATE;
15235 : 156581 : else if (flags & GOVD_MAP)
15236 : : {
15237 : 18019 : code = OMP_CLAUSE_MAP;
15238 : 18019 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15239 : 18019 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15240 : : {
15241 : 2 : error ("%<_Atomic%> %qD in implicit %<map%> clause", decl);
15242 : 2 : return 0;
15243 : : }
15244 : 18017 : if (VAR_P (decl)
15245 : 16079 : && DECL_IN_CONSTANT_POOL (decl)
15246 : 18018 : && !lookup_attribute ("omp declare target",
15247 : 1 : DECL_ATTRIBUTES (decl)))
15248 : : {
15249 : 1 : tree id = get_identifier ("omp declare target");
15250 : 1 : DECL_ATTRIBUTES (decl)
15251 : 1 : = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
15252 : 1 : varpool_node *node = varpool_node::get (decl);
15253 : 1 : if (node)
15254 : : {
15255 : 1 : node->offloadable = 1;
15256 : 1 : if (ENABLE_OFFLOADING)
15257 : : g->have_offload = true;
15258 : : }
15259 : : }
15260 : : }
15261 : 138562 : else if (flags & GOVD_SHARED)
15262 : : {
15263 : 49027 : if (is_global_var (decl))
15264 : : {
15265 : 16108 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15266 : 25288 : while (ctx != NULL)
15267 : : {
15268 : 17593 : splay_tree_node on
15269 : 17593 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15270 : 17593 : if (on && (on->value & (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE
15271 : : | GOVD_PRIVATE | GOVD_REDUCTION
15272 : : | GOVD_LINEAR | GOVD_MAP)) != 0)
15273 : : break;
15274 : 9180 : ctx = ctx->outer_context;
15275 : : }
15276 : 16108 : if (ctx == NULL)
15277 : : return 0;
15278 : : }
15279 : 41332 : code = OMP_CLAUSE_SHARED;
15280 : : /* Don't optimize shared into firstprivate for read-only vars
15281 : : on tasks with depend clause, we shouldn't try to copy them
15282 : : until the dependencies are satisfied. */
15283 : 41332 : if (gimplify_omp_ctxp->has_depend)
15284 : 350 : flags |= GOVD_WRITTEN;
15285 : : }
15286 : 89535 : else if (flags & GOVD_PRIVATE)
15287 : : code = OMP_CLAUSE_PRIVATE;
15288 : 31093 : else if (flags & GOVD_FIRSTPRIVATE)
15289 : : {
15290 : 21692 : code = OMP_CLAUSE_FIRSTPRIVATE;
15291 : 21692 : if ((gimplify_omp_ctxp->region_type & ORT_TARGET)
15292 : 13700 : && (gimplify_omp_ctxp->region_type & ORT_ACC) == 0
15293 : 31711 : && TYPE_ATOMIC (strip_array_types (TREE_TYPE (decl))))
15294 : : {
15295 : 1 : error ("%<_Atomic%> %qD in implicit %<firstprivate%> clause on "
15296 : : "%<target%> construct", decl);
15297 : 1 : return 0;
15298 : : }
15299 : : }
15300 : 9401 : else if (flags & GOVD_LASTPRIVATE)
15301 : : code = OMP_CLAUSE_LASTPRIVATE;
15302 : 241 : else if (flags & (GOVD_ALIGNED | GOVD_NONTEMPORAL))
15303 : : return 0;
15304 : 118 : else if (flags & GOVD_CONDTEMP)
15305 : : {
15306 : 118 : code = OMP_CLAUSE__CONDTEMP_;
15307 : 118 : gimple_add_tmp_var (decl);
15308 : : }
15309 : : else
15310 : 0 : gcc_unreachable ();
15311 : :
15312 : 139978 : if (((flags & GOVD_LASTPRIVATE)
15313 : 139288 : || (code == OMP_CLAUSE_SHARED && (flags & GOVD_WRITTEN)))
15314 : 155184 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15315 : 15192 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15316 : :
15317 : 149138 : tree chain = *list_p;
15318 : 149138 : clause = build_omp_clause (input_location, code);
15319 : 149138 : OMP_CLAUSE_DECL (clause) = decl;
15320 : 149138 : OMP_CLAUSE_CHAIN (clause) = chain;
15321 : 149138 : if (private_debug)
15322 : 378 : OMP_CLAUSE_PRIVATE_DEBUG (clause) = 1;
15323 : 148760 : else if (code == OMP_CLAUSE_PRIVATE && (flags & GOVD_PRIVATE_OUTER_REF))
15324 : 6 : OMP_CLAUSE_PRIVATE_OUTER_REF (clause) = 1;
15325 : 148754 : else if (code == OMP_CLAUSE_SHARED
15326 : 41332 : && (flags & GOVD_WRITTEN) == 0
15327 : 184040 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15328 : 21019 : OMP_CLAUSE_SHARED_READONLY (clause) = 1;
15329 : 127735 : else if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_EXPLICIT) == 0)
15330 : 21691 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clause) = 1;
15331 : 106044 : else if (code == OMP_CLAUSE_MAP && (flags & GOVD_MAP_0LEN_ARRAY) != 0)
15332 : : {
15333 : 644 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_MAP);
15334 : 644 : OMP_CLAUSE_DECL (nc) = decl;
15335 : 644 : if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
15336 : 644 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == POINTER_TYPE)
15337 : 15 : OMP_CLAUSE_DECL (clause)
15338 : 30 : = build_fold_indirect_ref_loc (input_location, decl);
15339 : 644 : OMP_CLAUSE_DECL (clause)
15340 : 644 : = build2 (MEM_REF, char_type_node, OMP_CLAUSE_DECL (clause),
15341 : : build_int_cst (build_pointer_type (char_type_node), 0));
15342 : 644 : OMP_CLAUSE_SIZE (clause) = size_zero_node;
15343 : 644 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15344 : 644 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_ALLOC);
15345 : 644 : OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (clause) = 1;
15346 : 644 : tree dtype = TREE_TYPE (decl);
15347 : 644 : if (TREE_CODE (dtype) == REFERENCE_TYPE)
15348 : 15 : dtype = TREE_TYPE (dtype);
15349 : : /* FIRSTPRIVATE_POINTER doesn't work well if we have a
15350 : : multiply-indirected pointer. If we have a reference to a pointer to
15351 : : a pointer, it's possible that this should really be
15352 : : GOMP_MAP_FIRSTPRIVATE_REFERENCE -- but that also doesn't work at the
15353 : : moment, so stick with this. (See PR113279 and testcases
15354 : : baseptrs-{4,6}.C:ref2ptrptr_offset_decl_member_slice). */
15355 : 644 : if (TREE_CODE (dtype) == POINTER_TYPE
15356 : 644 : && TREE_CODE (TREE_TYPE (dtype)) == POINTER_TYPE)
15357 : 19 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15358 : : else
15359 : 625 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15360 : 644 : OMP_CLAUSE_CHAIN (nc) = chain;
15361 : 644 : OMP_CLAUSE_CHAIN (clause) = nc;
15362 : 644 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15363 : 644 : gimplify_omp_ctxp = ctx->outer_context;
15364 : 644 : gimplify_expr (&TREE_OPERAND (OMP_CLAUSE_DECL (clause), 0),
15365 : : pre_p, NULL, is_gimple_val, fb_rvalue);
15366 : 644 : gimplify_omp_ctxp = ctx;
15367 : 644 : }
15368 : 17373 : else if (code == OMP_CLAUSE_MAP)
15369 : : {
15370 : 17373 : int kind;
15371 : : /* Not all combinations of these GOVD_MAP flags are actually valid. */
15372 : 17373 : switch (flags & (GOVD_MAP_TO_ONLY
15373 : : | GOVD_MAP_FORCE
15374 : : | GOVD_MAP_FORCE_PRESENT
15375 : : | GOVD_MAP_ALLOC_ONLY
15376 : : | GOVD_MAP_FROM_ONLY))
15377 : : {
15378 : : case 0:
15379 : : kind = GOMP_MAP_TOFROM;
15380 : : break;
15381 : 1042 : case GOVD_MAP_FORCE:
15382 : 1042 : kind = GOMP_MAP_TOFROM | GOMP_MAP_FLAG_FORCE;
15383 : 1042 : break;
15384 : 869 : case GOVD_MAP_TO_ONLY:
15385 : 869 : kind = GOMP_MAP_TO;
15386 : 869 : break;
15387 : 16 : case GOVD_MAP_FROM_ONLY:
15388 : 16 : kind = GOMP_MAP_FROM;
15389 : 16 : break;
15390 : 37 : case GOVD_MAP_ALLOC_ONLY:
15391 : 37 : kind = GOMP_MAP_ALLOC;
15392 : 37 : break;
15393 : 0 : case GOVD_MAP_TO_ONLY | GOVD_MAP_FORCE:
15394 : 0 : kind = GOMP_MAP_TO | GOMP_MAP_FLAG_FORCE;
15395 : 0 : break;
15396 : : case GOVD_MAP_FORCE_PRESENT:
15397 : 326 : kind = GOMP_MAP_FORCE_PRESENT;
15398 : : break;
15399 : : case GOVD_MAP_FORCE_PRESENT | GOVD_MAP_ALLOC_ONLY:
15400 : 326 : kind = GOMP_MAP_FORCE_PRESENT;
15401 : : break;
15402 : 0 : default:
15403 : 0 : gcc_unreachable ();
15404 : : }
15405 : 17373 : OMP_CLAUSE_SET_MAP_KIND (clause, kind);
15406 : : /* Setting of the implicit flag for the runtime is currently disabled for
15407 : : OpenACC. */
15408 : 17373 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
15409 : 9844 : OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause) = 1;
15410 : 17373 : if (DECL_SIZE (decl)
15411 : 17373 : && !poly_int_tree_p (DECL_SIZE (decl)))
15412 : : {
15413 : 535 : tree decl2 = DECL_VALUE_EXPR (decl);
15414 : 535 : gcc_assert (INDIRECT_REF_P (decl2));
15415 : 535 : decl2 = TREE_OPERAND (decl2, 0);
15416 : 535 : gcc_assert (DECL_P (decl2));
15417 : 535 : tree mem = build_simple_mem_ref (decl2);
15418 : 535 : OMP_CLAUSE_DECL (clause) = mem;
15419 : 535 : OMP_CLAUSE_SIZE (clause) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
15420 : 535 : if (gimplify_omp_ctxp->outer_context)
15421 : : {
15422 : 446 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp->outer_context;
15423 : 446 : omp_notice_variable (ctx, decl2, true);
15424 : 446 : omp_notice_variable (ctx, OMP_CLAUSE_SIZE (clause), true);
15425 : : }
15426 : 535 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15427 : : OMP_CLAUSE_MAP);
15428 : 535 : OMP_CLAUSE_DECL (nc) = decl;
15429 : 535 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15430 : 535 : if (gimplify_omp_ctxp->target_firstprivatize_array_bases)
15431 : 535 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_POINTER);
15432 : : else
15433 : 0 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
15434 : 535 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15435 : 535 : OMP_CLAUSE_CHAIN (clause) = nc;
15436 : : }
15437 : 16838 : else if (gimplify_omp_ctxp->target_firstprivatize_array_bases
15438 : 16838 : && omp_privatize_by_reference (decl))
15439 : : {
15440 : 29 : OMP_CLAUSE_DECL (clause) = build_simple_mem_ref (decl);
15441 : 29 : OMP_CLAUSE_SIZE (clause)
15442 : 29 : = unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (decl))));
15443 : 29 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15444 : 29 : gimplify_omp_ctxp = ctx->outer_context;
15445 : 29 : gimplify_expr (&OMP_CLAUSE_SIZE (clause),
15446 : : pre_p, NULL, is_gimple_val, fb_rvalue);
15447 : 29 : gimplify_omp_ctxp = ctx;
15448 : 29 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (clause),
15449 : : OMP_CLAUSE_MAP);
15450 : 29 : OMP_CLAUSE_DECL (nc) = decl;
15451 : 29 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
15452 : 29 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_FIRSTPRIVATE_REFERENCE);
15453 : 29 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (clause);
15454 : 29 : OMP_CLAUSE_CHAIN (clause) = nc;
15455 : : }
15456 : : else
15457 : 16809 : OMP_CLAUSE_SIZE (clause) = DECL_SIZE_UNIT (decl);
15458 : : }
15459 : 149138 : if (code == OMP_CLAUSE_FIRSTPRIVATE && (flags & GOVD_LASTPRIVATE) != 0)
15460 : : {
15461 : 690 : tree nc = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
15462 : 690 : OMP_CLAUSE_DECL (nc) = decl;
15463 : 690 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (nc) = 1;
15464 : 690 : OMP_CLAUSE_CHAIN (nc) = chain;
15465 : 690 : OMP_CLAUSE_CHAIN (clause) = nc;
15466 : 690 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15467 : 690 : gimplify_omp_ctxp = ctx->outer_context;
15468 : 690 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
15469 : 690 : (ctx->region_type & ORT_ACC) != 0);
15470 : 690 : gimplify_omp_ctxp = ctx;
15471 : : }
15472 : 149138 : *list_p = clause;
15473 : 149138 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15474 : 149138 : gimplify_omp_ctxp = ctx->outer_context;
15475 : : /* Don't call omp_finish_clause on implicitly added OMP_CLAUSE_PRIVATE
15476 : : in simd. Those are only added for the local vars inside of simd body
15477 : : and they don't need to be e.g. default constructible. */
15478 : 149138 : if (code != OMP_CLAUSE_PRIVATE || ctx->region_type != ORT_SIMD)
15479 : 141087 : lang_hooks.decls.omp_finish_clause (clause, pre_p,
15480 : 141087 : (ctx->region_type & ORT_ACC) != 0);
15481 : 149138 : if (gimplify_omp_ctxp)
15482 : 184159 : for (; clause != chain; clause = OMP_CLAUSE_CHAIN (clause))
15483 : 93492 : if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
15484 : 93492 : && DECL_P (OMP_CLAUSE_SIZE (clause)))
15485 : 1241 : omp_notice_variable (gimplify_omp_ctxp, OMP_CLAUSE_SIZE (clause),
15486 : : true);
15487 : 149138 : gimplify_omp_ctxp = ctx;
15488 : 149138 : return 0;
15489 : : }
15490 : :
15491 : : static void
15492 : 127668 : gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
15493 : : enum tree_code code,
15494 : : gimple_seq *loops_seq_p = NULL)
15495 : : {
15496 : 127668 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
15497 : 127668 : tree *orig_list_p = list_p;
15498 : 127668 : tree c, decl;
15499 : 127668 : bool has_inscan_reductions = false;
15500 : :
15501 : 127668 : if (body)
15502 : : {
15503 : : struct gimplify_omp_ctx *octx;
15504 : 222985 : for (octx = ctx; octx; octx = octx->outer_context)
15505 : 172571 : if ((octx->region_type & (ORT_PARALLEL | ORT_TASK | ORT_TEAMS)) != 0)
15506 : : break;
15507 : 110479 : if (octx)
15508 : : {
15509 : 60065 : struct walk_stmt_info wi;
15510 : 60065 : memset (&wi, 0, sizeof (wi));
15511 : 60065 : walk_gimple_seq (body, omp_find_stores_stmt,
15512 : : omp_find_stores_op, &wi);
15513 : : }
15514 : : }
15515 : :
15516 : 127668 : if (ctx->add_safelen1)
15517 : : {
15518 : : /* If there are VLAs in the body of simd loop, prevent
15519 : : vectorization. */
15520 : 2 : gcc_assert (ctx->region_type == ORT_SIMD);
15521 : 2 : c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
15522 : 2 : OMP_CLAUSE_SAFELEN_EXPR (c) = integer_one_node;
15523 : 2 : OMP_CLAUSE_CHAIN (c) = *list_p;
15524 : 2 : *list_p = c;
15525 : 2 : list_p = &OMP_CLAUSE_CHAIN (c);
15526 : : }
15527 : :
15528 : 127668 : if (ctx->region_type == ORT_WORKSHARE
15529 : 39258 : && ctx->outer_context
15530 : 27843 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL)
15531 : : {
15532 : 24872 : for (c = ctx->outer_context->clauses; c; c = OMP_CLAUSE_CHAIN (c))
15533 : 12535 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15534 : 12535 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
15535 : : {
15536 : 125 : decl = OMP_CLAUSE_DECL (c);
15537 : 125 : splay_tree_node n
15538 : 125 : = splay_tree_lookup (ctx->outer_context->variables,
15539 : : (splay_tree_key) decl);
15540 : 125 : gcc_checking_assert (!splay_tree_lookup (ctx->variables,
15541 : : (splay_tree_key) decl));
15542 : 125 : omp_add_variable (ctx, decl, n->value);
15543 : 125 : tree c2 = copy_node (c);
15544 : 125 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15545 : 125 : *list_p = c2;
15546 : 125 : if ((n->value & GOVD_FIRSTPRIVATE) == 0)
15547 : 103 : continue;
15548 : 22 : c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c),
15549 : : OMP_CLAUSE_FIRSTPRIVATE);
15550 : 22 : OMP_CLAUSE_DECL (c2) = decl;
15551 : 22 : OMP_CLAUSE_CHAIN (c2) = *list_p;
15552 : 22 : *list_p = c2;
15553 : : }
15554 : : }
15555 : :
15556 : 127668 : if (code == OMP_TARGET
15557 : 127668 : || code == OMP_TARGET_DATA
15558 : 127668 : || code == OMP_TARGET_ENTER_DATA
15559 : 112408 : || code == OMP_TARGET_EXIT_DATA)
15560 : : {
15561 : 15908 : tree mapper_clauses = NULL_TREE;
15562 : 15908 : instantiate_mapper_info im_info;
15563 : :
15564 : 15908 : im_info.mapper_clauses_p = &mapper_clauses;
15565 : 15908 : im_info.omp_ctx = ctx;
15566 : 15908 : im_info.pre_p = pre_p;
15567 : :
15568 : 15908 : splay_tree_foreach (ctx->variables,
15569 : : omp_instantiate_implicit_mappers,
15570 : : (void *) &im_info);
15571 : :
15572 : 15908 : if (mapper_clauses)
15573 : : {
15574 : 45 : mapper_clauses
15575 : 45 : = lang_hooks.decls.omp_finish_mapper_clauses (mapper_clauses);
15576 : :
15577 : : /* Stick the implicitly-expanded mapper clauses at the end of the
15578 : : clause list. */
15579 : 45 : tree *tail = list_p;
15580 : 139 : while (*tail)
15581 : 94 : tail = &OMP_CLAUSE_CHAIN (*tail);
15582 : 45 : *tail = mapper_clauses;
15583 : : }
15584 : :
15585 : 15908 : vec<omp_mapping_group> *groups;
15586 : 15908 : groups = omp_gather_mapping_groups (list_p);
15587 : 15908 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap = NULL;
15588 : :
15589 : 15908 : if (groups)
15590 : : {
15591 : 7735 : grpmap = omp_index_mapping_groups (groups);
15592 : :
15593 : 7735 : omp_resolve_clause_dependencies (code, groups, grpmap);
15594 : 7735 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15595 : : &grpmap, list_p);
15596 : :
15597 : 7735 : omp_mapping_group *outlist = NULL;
15598 : :
15599 : 15470 : delete grpmap;
15600 : 7735 : delete groups;
15601 : :
15602 : : /* Rebuild now we have struct sibling lists. */
15603 : 7735 : groups = omp_gather_mapping_groups (list_p);
15604 : 7735 : grpmap = omp_index_mapping_groups (groups);
15605 : :
15606 : 7735 : bool enter_exit = (code == OMP_TARGET_ENTER_DATA
15607 : 7735 : || code == OMP_TARGET_EXIT_DATA);
15608 : :
15609 : 7735 : outlist = omp_tsort_mapping_groups (groups, grpmap, enter_exit);
15610 : 7735 : outlist = omp_segregate_mapping_groups (outlist);
15611 : 7735 : list_p = omp_reorder_mapping_groups (groups, outlist, list_p);
15612 : :
15613 : 7735 : delete grpmap;
15614 : 7735 : delete groups;
15615 : : }
15616 : 15908 : }
15617 : 111760 : else if (ctx->region_type & ORT_ACC)
15618 : : {
15619 : 29839 : vec<omp_mapping_group> *groups;
15620 : 29839 : groups = omp_gather_mapping_groups (list_p);
15621 : 29839 : if (groups)
15622 : : {
15623 : 9457 : hash_map<tree_operand_hash_no_se, omp_mapping_group *> *grpmap;
15624 : 9457 : grpmap = omp_index_mapping_groups (groups);
15625 : :
15626 : 9457 : oacc_resolve_clause_dependencies (groups, grpmap);
15627 : 9457 : omp_build_struct_sibling_lists (code, ctx->region_type, groups,
15628 : : &grpmap, list_p);
15629 : :
15630 : 9457 : delete groups;
15631 : 18914 : delete grpmap;
15632 : : }
15633 : : }
15634 : :
15635 : 127668 : tree attach_list = NULL_TREE;
15636 : 127668 : tree *attach_tail = &attach_list;
15637 : :
15638 : 127668 : tree *grp_start_p = NULL, grp_end = NULL_TREE;
15639 : :
15640 : 370898 : while ((c = *list_p) != NULL)
15641 : : {
15642 : 243230 : splay_tree_node n;
15643 : 243230 : bool remove = false;
15644 : 243230 : bool move_attach = false;
15645 : :
15646 : 283453 : if (grp_end && c == OMP_CLAUSE_CHAIN (grp_end))
15647 : : grp_end = NULL_TREE;
15648 : :
15649 : 243230 : switch (OMP_CLAUSE_CODE (c))
15650 : : {
15651 : 7853 : case OMP_CLAUSE_FIRSTPRIVATE:
15652 : 7853 : if ((ctx->region_type & ORT_TARGET)
15653 : 1836 : && (ctx->region_type & ORT_ACC) == 0
15654 : 9083 : && TYPE_ATOMIC (strip_array_types
15655 : : (TREE_TYPE (OMP_CLAUSE_DECL (c)))))
15656 : : {
15657 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
15658 : : "%<_Atomic%> %qD in %<firstprivate%> clause on "
15659 : 2 : "%<target%> construct", OMP_CLAUSE_DECL (c));
15660 : 2 : remove = true;
15661 : 2 : break;
15662 : : }
15663 : 7851 : if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
15664 : : {
15665 : 380 : decl = OMP_CLAUSE_DECL (c);
15666 : 380 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15667 : 380 : if ((n->value & GOVD_MAP) != 0)
15668 : : {
15669 : : remove = true;
15670 : : break;
15671 : : }
15672 : 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) = 0;
15673 : 368 : OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 0;
15674 : : }
15675 : : /* FALLTHRU */
15676 : 36545 : case OMP_CLAUSE_PRIVATE:
15677 : 36545 : case OMP_CLAUSE_SHARED:
15678 : 36545 : case OMP_CLAUSE_LINEAR:
15679 : 36545 : decl = OMP_CLAUSE_DECL (c);
15680 : 36545 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15681 : 36545 : remove = !(n->value & GOVD_SEEN);
15682 : 36545 : if ((n->value & GOVD_LASTPRIVATE_CONDITIONAL) != 0
15683 : 48 : && code == OMP_PARALLEL
15684 : 36567 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15685 : : remove = true;
15686 : 36523 : if (! remove)
15687 : : {
15688 : 31948 : bool shared = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED;
15689 : 31948 : if ((n->value & GOVD_DEBUG_PRIVATE)
15690 : 31948 : || lang_hooks.decls.omp_private_debug_clause (decl, shared))
15691 : : {
15692 : 83 : gcc_assert ((n->value & GOVD_DEBUG_PRIVATE) == 0
15693 : : || ((n->value & GOVD_DATA_SHARE_CLASS)
15694 : : == GOVD_SHARED));
15695 : 83 : OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_PRIVATE);
15696 : 83 : OMP_CLAUSE_PRIVATE_DEBUG (c) = 1;
15697 : : }
15698 : 31948 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15699 : 4129 : && ctx->has_depend
15700 : 32506 : && DECL_P (decl))
15701 : 558 : n->value |= GOVD_WRITTEN;
15702 : 31948 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15703 : 4129 : && (n->value & GOVD_WRITTEN) == 0
15704 : 3018 : && DECL_P (decl)
15705 : 34966 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15706 : 526 : OMP_CLAUSE_SHARED_READONLY (c) = 1;
15707 : 31422 : else if (DECL_P (decl)
15708 : 31422 : && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
15709 : 3603 : && (n->value & GOVD_WRITTEN) != 0)
15710 : 30311 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15711 : 9025 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
15712 : 38452 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15713 : 5726 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15714 : : }
15715 : : else
15716 : 4597 : n->value &= ~GOVD_EXPLICIT;
15717 : : break;
15718 : :
15719 : 13000 : case OMP_CLAUSE_LASTPRIVATE:
15720 : : /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
15721 : : accurately reflect the presence of a FIRSTPRIVATE clause. */
15722 : 13000 : decl = OMP_CLAUSE_DECL (c);
15723 : 13000 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15724 : 13000 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
15725 : 13000 : = (n->value & GOVD_FIRSTPRIVATE) != 0;
15726 : 13000 : if (code == OMP_DISTRIBUTE
15727 : 13000 : && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
15728 : : {
15729 : 4 : remove = true;
15730 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
15731 : : "same variable used in %<firstprivate%> and "
15732 : : "%<lastprivate%> clauses on %<distribute%> "
15733 : : "construct");
15734 : : }
15735 : 13000 : if (!remove
15736 : 12996 : && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
15737 : 12996 : && DECL_P (decl)
15738 : 12996 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
15739 : 11403 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
15740 : 13000 : if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) && code == OMP_PARALLEL)
15741 : : remove = true;
15742 : : break;
15743 : :
15744 : 824 : case OMP_CLAUSE_ALIGNED:
15745 : 824 : decl = OMP_CLAUSE_DECL (c);
15746 : 824 : if (!is_global_var (decl))
15747 : : {
15748 : 738 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15749 : 738 : remove = n == NULL || !(n->value & GOVD_SEEN);
15750 : 88 : if (!remove && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
15751 : : {
15752 : 88 : struct gimplify_omp_ctx *octx;
15753 : 88 : if (n != NULL
15754 : 88 : && (n->value & (GOVD_DATA_SHARE_CLASS
15755 : : & ~GOVD_FIRSTPRIVATE)))
15756 : : remove = true;
15757 : : else
15758 : 100 : for (octx = ctx->outer_context; octx;
15759 : 12 : octx = octx->outer_context)
15760 : : {
15761 : 24 : n = splay_tree_lookup (octx->variables,
15762 : : (splay_tree_key) decl);
15763 : 24 : if (n == NULL)
15764 : 12 : continue;
15765 : 12 : if (n->value & GOVD_LOCAL)
15766 : : break;
15767 : : /* We have to avoid assigning a shared variable
15768 : : to itself when trying to add
15769 : : __builtin_assume_aligned. */
15770 : 12 : if (n->value & GOVD_SHARED)
15771 : : {
15772 : : remove = true;
15773 : : break;
15774 : : }
15775 : : }
15776 : : }
15777 : : }
15778 : 86 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
15779 : : {
15780 : 83 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15781 : 83 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
15782 : : remove = true;
15783 : : }
15784 : : break;
15785 : :
15786 : 538 : case OMP_CLAUSE_HAS_DEVICE_ADDR:
15787 : 538 : decl = OMP_CLAUSE_DECL (c);
15788 : 538 : while (INDIRECT_REF_P (decl)
15789 : 587 : || TREE_CODE (decl) == ARRAY_REF)
15790 : 49 : decl = TREE_OPERAND (decl, 0);
15791 : 538 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15792 : 538 : remove = n == NULL || !(n->value & GOVD_SEEN);
15793 : : break;
15794 : :
15795 : 898 : case OMP_CLAUSE_IS_DEVICE_PTR:
15796 : 898 : case OMP_CLAUSE_NONTEMPORAL:
15797 : 898 : decl = OMP_CLAUSE_DECL (c);
15798 : 898 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
15799 : 898 : remove = n == NULL || !(n->value & GOVD_SEEN);
15800 : : break;
15801 : :
15802 : 53524 : case OMP_CLAUSE_MAP:
15803 : 53524 : decl = OMP_CLAUSE_DECL (c);
15804 : 53524 : if (!grp_end)
15805 : : {
15806 : 30166 : grp_start_p = list_p;
15807 : 30166 : grp_end = *omp_group_last (grp_start_p);
15808 : : }
15809 : 53524 : switch (OMP_CLAUSE_MAP_KIND (c))
15810 : : {
15811 : 123 : case GOMP_MAP_PRESENT_ALLOC:
15812 : 123 : case GOMP_MAP_PRESENT_TO:
15813 : 123 : case GOMP_MAP_PRESENT_FROM:
15814 : 123 : case GOMP_MAP_PRESENT_TOFROM:
15815 : 123 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_PRESENT);
15816 : 123 : break;
15817 : : default:
15818 : : break;
15819 : : }
15820 : 53524 : switch (code)
15821 : : {
15822 : 4563 : case OACC_DATA:
15823 : 4563 : if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
15824 : : break;
15825 : : /* Fallthrough. */
15826 : 17116 : case OACC_HOST_DATA:
15827 : 17116 : case OACC_ENTER_DATA:
15828 : 17116 : case OACC_EXIT_DATA:
15829 : 17116 : case OMP_TARGET_DATA:
15830 : 17116 : case OMP_TARGET_ENTER_DATA:
15831 : 17116 : case OMP_TARGET_EXIT_DATA:
15832 : 17116 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15833 : 17116 : || (OMP_CLAUSE_MAP_KIND (c)
15834 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15835 : : /* For target {,enter ,exit }data only the array slice is
15836 : : mapped, but not the pointer to it. */
15837 : : remove = true;
15838 : 17116 : if (code == OMP_TARGET_EXIT_DATA
15839 : 17116 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER
15840 : 1790 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER))
15841 : : remove = true;
15842 : : break;
15843 : : case OMP_TARGET:
15844 : : break;
15845 : : default:
15846 : : break;
15847 : : }
15848 : 17114 : if (remove)
15849 : : break;
15850 : 53189 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
15851 : : {
15852 : : /* Sanity check: attach/detach map kinds use the size as a bias,
15853 : : and it's never right to use the decl size for such
15854 : : mappings. */
15855 : 16884 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH
15856 : : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_DETACH
15857 : : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DETACH
15858 : : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH
15859 : : && (OMP_CLAUSE_MAP_KIND (c)
15860 : : != GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION));
15861 : 20665 : OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
15862 : 3781 : : TYPE_SIZE_UNIT (TREE_TYPE (decl));
15863 : : }
15864 : 53189 : gimplify_omp_ctxp = ctx->outer_context;
15865 : 53189 : gimple_seq *seq_p;
15866 : 53189 : seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
15867 : 53189 : if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
15868 : : is_gimple_val, fb_rvalue) == GS_ERROR)
15869 : : {
15870 : 0 : gimplify_omp_ctxp = ctx;
15871 : 0 : remove = true;
15872 : 0 : goto end_adjust_omp_map_clause;
15873 : : }
15874 : 53189 : else if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15875 : 50390 : || (OMP_CLAUSE_MAP_KIND (c)
15876 : : == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15877 : 49981 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15878 : 59216 : && TREE_CODE (OMP_CLAUSE_SIZE (c)) != INTEGER_CST)
15879 : : {
15880 : 842 : OMP_CLAUSE_SIZE (c)
15881 : 842 : = get_initialized_tmp_var (OMP_CLAUSE_SIZE (c), seq_p, NULL,
15882 : : false);
15883 : 842 : if ((ctx->region_type & ORT_TARGET) != 0)
15884 : 643 : omp_add_variable (ctx, OMP_CLAUSE_SIZE (c),
15885 : : GOVD_FIRSTPRIVATE | GOVD_SEEN);
15886 : : }
15887 : 53189 : gimplify_omp_ctxp = ctx;
15888 : : /* Data clauses associated with reductions must be
15889 : : compatible with present_or_copy. Warn and adjust the clause
15890 : : if that is not the case. */
15891 : 53189 : if (ctx->region_type == ORT_ACC_PARALLEL
15892 : 44210 : || ctx->region_type == ORT_ACC_SERIAL)
15893 : : {
15894 : 9535 : tree t = DECL_P (decl) ? decl : TREE_OPERAND (decl, 0);
15895 : 9535 : n = NULL;
15896 : :
15897 : 9535 : if (DECL_P (t))
15898 : 7770 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) t);
15899 : :
15900 : 7770 : if (n && (n->value & GOVD_REDUCTION))
15901 : : {
15902 : 809 : enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c);
15903 : :
15904 : 809 : OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1;
15905 : 809 : if ((kind & GOMP_MAP_TOFROM) != GOMP_MAP_TOFROM
15906 : 159 : && kind != GOMP_MAP_FORCE_PRESENT
15907 : 159 : && kind != GOMP_MAP_POINTER)
15908 : : {
15909 : 120 : warning_at (OMP_CLAUSE_LOCATION (c), 0,
15910 : : "incompatible data clause with reduction "
15911 : : "on %qE; promoting to %<present_or_copy%>",
15912 : 120 : DECL_NAME (t));
15913 : 120 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM);
15914 : : }
15915 : : }
15916 : : }
15917 : 53189 : if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
15918 : 50593 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
15919 : 53297 : && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
15920 : : {
15921 : 412 : remove = true;
15922 : 412 : goto end_adjust_omp_map_clause;
15923 : : }
15924 : : /* If we have a DECL_VALUE_EXPR (e.g. this is a class member and/or
15925 : : a variable captured in a lambda closure), look through that now
15926 : : before the DECL_P check below. (A code other than COMPONENT_REF,
15927 : : i.e. INDIRECT_REF, will be a VLA/variable-length array
15928 : : section. A global var may be a variable in a common block. We
15929 : : don't want to do this here for either of those.) */
15930 : 52777 : if ((ctx->region_type & ORT_ACC) == 0
15931 : 26584 : && DECL_P (decl)
15932 : 11744 : && !is_global_var (decl)
15933 : 10453 : && DECL_HAS_VALUE_EXPR_P (decl)
15934 : 52967 : && TREE_CODE (DECL_VALUE_EXPR (decl)) == COMPONENT_REF)
15935 : 0 : decl = OMP_CLAUSE_DECL (c) = DECL_VALUE_EXPR (decl);
15936 : 52777 : if (TREE_CODE (decl) == TARGET_EXPR)
15937 : : {
15938 : 0 : if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
15939 : : is_gimple_lvalue, fb_lvalue) == GS_ERROR)
15940 : 25294 : remove = true;
15941 : : }
15942 : 52777 : else if (!DECL_P (decl))
15943 : : {
15944 : 27483 : if ((ctx->region_type & ORT_TARGET) != 0
15945 : 27483 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15946 : : {
15947 : 24 : if (INDIRECT_REF_P (decl)
15948 : 0 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
15949 : 24 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
15950 : : == REFERENCE_TYPE))
15951 : 0 : decl = TREE_OPERAND (decl, 0);
15952 : 24 : if (TREE_CODE (decl) == COMPONENT_REF)
15953 : : {
15954 : 0 : while (TREE_CODE (decl) == COMPONENT_REF)
15955 : 0 : decl = TREE_OPERAND (decl, 0);
15956 : 0 : if (DECL_P (decl))
15957 : : {
15958 : 0 : n = splay_tree_lookup (ctx->variables,
15959 : : (splay_tree_key) decl);
15960 : 0 : if (!(n->value & GOVD_SEEN))
15961 : 27483 : remove = true;
15962 : : }
15963 : : }
15964 : : }
15965 : :
15966 : 27483 : tree d = decl, *pd;
15967 : 27483 : if (TREE_CODE (d) == ARRAY_REF)
15968 : : {
15969 : 5594 : while (TREE_CODE (d) == ARRAY_REF)
15970 : 2857 : d = TREE_OPERAND (d, 0);
15971 : 2737 : if (TREE_CODE (d) == COMPONENT_REF
15972 : 2737 : && TREE_CODE (TREE_TYPE (d)) == ARRAY_TYPE)
15973 : : decl = d;
15974 : : }
15975 : 27483 : pd = &OMP_CLAUSE_DECL (c);
15976 : 27483 : if (d == decl
15977 : 25103 : && TREE_CODE (decl) == INDIRECT_REF
15978 : 14865 : && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
15979 : 1470 : && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
15980 : : == REFERENCE_TYPE)
15981 : 28283 : && (OMP_CLAUSE_MAP_KIND (c)
15982 : : != GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION))
15983 : : {
15984 : 796 : pd = &TREE_OPERAND (decl, 0);
15985 : 796 : decl = TREE_OPERAND (decl, 0);
15986 : : }
15987 : :
15988 : 27483 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
15989 : 2590 : switch (code)
15990 : : {
15991 : 427 : case OACC_ENTER_DATA:
15992 : 427 : case OACC_EXIT_DATA:
15993 : 427 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
15994 : : == ARRAY_TYPE)
15995 : : remove = true;
15996 : 417 : else if (code == OACC_ENTER_DATA)
15997 : 263 : goto change_to_attach;
15998 : : /* Fallthrough. */
15999 : 347 : case OMP_TARGET_EXIT_DATA:
16000 : 347 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DETACH);
16001 : 347 : break;
16002 : 71 : case OACC_UPDATE:
16003 : : /* An "attach/detach" operation on an update directive
16004 : : should behave as a GOMP_MAP_ALWAYS_POINTER. Note that
16005 : : both GOMP_MAP_ATTACH_DETACH and GOMP_MAP_ALWAYS_POINTER
16006 : : kinds depend on the previous mapping (for non-TARGET
16007 : : regions). */
16008 : 71 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER);
16009 : 71 : break;
16010 : 2172 : default:
16011 : 2172 : change_to_attach:
16012 : 2172 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ATTACH);
16013 : 2172 : if ((ctx->region_type & ORT_TARGET) != 0)
16014 : 1769 : move_attach = true;
16015 : : }
16016 : 24893 : else if ((ctx->region_type & ORT_TARGET) != 0
16017 : 24893 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16018 : 11494 : || (OMP_CLAUSE_MAP_KIND (c)
16019 : : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16020 : : move_attach = true;
16021 : :
16022 : : /* If we have e.g. map(struct: *var), don't gimplify the
16023 : : argument since omp-low.cc wants to see the decl itself. */
16024 : 27483 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT)
16025 : 1135 : goto end_adjust_omp_map_clause;
16026 : :
16027 : : /* We've already partly gimplified this in
16028 : : gimplify_scan_omp_clauses. Don't do any more. */
16029 : 26348 : if (code == OMP_TARGET && OMP_CLAUSE_MAP_IN_REDUCTION (c))
16030 : 88 : goto end_adjust_omp_map_clause;
16031 : :
16032 : 26260 : gimplify_omp_ctxp = ctx->outer_context;
16033 : 26260 : if (gimplify_expr (pd, seq_p, NULL, is_gimple_lvalue,
16034 : : fb_lvalue) == GS_ERROR)
16035 : 0 : remove = true;
16036 : 26260 : gimplify_omp_ctxp = ctx;
16037 : 26260 : goto end_adjust_omp_map_clause;
16038 : : }
16039 : :
16040 : 25294 : if ((code == OMP_TARGET
16041 : : || code == OMP_TARGET_DATA
16042 : : || code == OMP_TARGET_ENTER_DATA
16043 : 14360 : || code == OMP_TARGET_EXIT_DATA)
16044 : 25842 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16045 : : {
16046 : 229 : bool firstprivatize = false;
16047 : :
16048 : 234 : for (struct gimplify_omp_ctx *octx = ctx->outer_context; octx;
16049 : 5 : octx = octx->outer_context)
16050 : : {
16051 : 6 : splay_tree_node n
16052 : 12 : = splay_tree_lookup (octx->variables,
16053 : 6 : (splay_tree_key) OMP_CLAUSE_DECL (c));
16054 : : /* If this is contained in an outer OpenMP region as a
16055 : : firstprivate value, remove the attach/detach. */
16056 : 6 : if (n && (n->value & GOVD_FIRSTPRIVATE))
16057 : : {
16058 : : firstprivatize = true;
16059 : : break;
16060 : : }
16061 : : }
16062 : :
16063 : 229 : enum gomp_map_kind map_kind;
16064 : 229 : if (firstprivatize)
16065 : : map_kind = GOMP_MAP_FIRSTPRIVATE_POINTER;
16066 : 228 : else if (code == OMP_TARGET_EXIT_DATA)
16067 : : map_kind = GOMP_MAP_DETACH;
16068 : : else
16069 : 180 : map_kind = GOMP_MAP_ATTACH;
16070 : 229 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16071 : : }
16072 : 25065 : else if ((ctx->region_type & ORT_ACC) != 0
16073 : 25065 : && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)
16074 : : {
16075 : 0 : enum gomp_map_kind map_kind = (code == OACC_EXIT_DATA
16076 : 0 : ? GOMP_MAP_DETACH
16077 : : : GOMP_MAP_ATTACH);
16078 : 0 : OMP_CLAUSE_SET_MAP_KIND (c, map_kind);
16079 : : }
16080 : :
16081 : 25294 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16082 : 25294 : if ((ctx->region_type & ORT_TARGET) != 0
16083 : 15662 : && !(n->value & GOVD_SEEN)
16084 : 1445 : && GOMP_MAP_ALWAYS_P (OMP_CLAUSE_MAP_KIND (c)) == 0
16085 : 26496 : && (!is_global_var (decl)
16086 : 75 : || !lookup_attribute ("omp declare target link",
16087 : 75 : DECL_ATTRIBUTES (decl))))
16088 : : {
16089 : 1190 : remove = true;
16090 : : /* For struct element mapping, if struct is never referenced
16091 : : in target block and none of the mapping has always modifier,
16092 : : remove all the struct element mappings, which immediately
16093 : : follow the GOMP_MAP_STRUCT map clause. */
16094 : 1190 : if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT
16095 : 1190 : || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT_UNORD)
16096 : : {
16097 : 28 : HOST_WIDE_INT cnt = tree_to_shwi (OMP_CLAUSE_SIZE (c));
16098 : 76 : while (cnt--)
16099 : 48 : OMP_CLAUSE_CHAIN (c)
16100 : 48 : = OMP_CLAUSE_CHAIN (OMP_CLAUSE_CHAIN (c));
16101 : : }
16102 : : }
16103 : 24104 : else if (DECL_SIZE (decl)
16104 : 24080 : && !poly_int_tree_p (DECL_SIZE (decl))
16105 : 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_POINTER
16106 : 199 : && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
16107 : 24155 : && (OMP_CLAUSE_MAP_KIND (c)
16108 : : != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
16109 : : {
16110 : : /* For GOMP_MAP_FORCE_DEVICEPTR, we'll never enter here, because
16111 : : for these, TREE_CODE (DECL_SIZE (decl)) will always be
16112 : : INTEGER_CST. */
16113 : 51 : gcc_assert (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FORCE_DEVICEPTR);
16114 : :
16115 : 51 : tree decl2 = DECL_VALUE_EXPR (decl);
16116 : 51 : gcc_assert (INDIRECT_REF_P (decl2));
16117 : 51 : decl2 = TREE_OPERAND (decl2, 0);
16118 : 51 : gcc_assert (DECL_P (decl2));
16119 : 51 : tree mem = build_simple_mem_ref (decl2);
16120 : 51 : OMP_CLAUSE_DECL (c) = mem;
16121 : 51 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16122 : 51 : if (ctx->outer_context)
16123 : : {
16124 : 15 : omp_notice_variable (ctx->outer_context, decl2, true);
16125 : 30 : omp_notice_variable (ctx->outer_context,
16126 : 15 : OMP_CLAUSE_SIZE (c), true);
16127 : : }
16128 : 51 : if (((ctx->region_type & ORT_TARGET) != 0
16129 : 24 : || !ctx->target_firstprivatize_array_bases)
16130 : 34 : && ((n->value & GOVD_SEEN) == 0
16131 : 30 : || (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE)) == 0))
16132 : : {
16133 : 34 : tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
16134 : : OMP_CLAUSE_MAP);
16135 : 34 : OMP_CLAUSE_DECL (nc) = decl;
16136 : 34 : OMP_CLAUSE_SIZE (nc) = size_zero_node;
16137 : 34 : if (ctx->target_firstprivatize_array_bases)
16138 : 27 : OMP_CLAUSE_SET_MAP_KIND (nc,
16139 : : GOMP_MAP_FIRSTPRIVATE_POINTER);
16140 : : else
16141 : 7 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_POINTER);
16142 : 34 : OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
16143 : 34 : OMP_CLAUSE_CHAIN (c) = nc;
16144 : 34 : c = nc;
16145 : : }
16146 : : }
16147 : : else
16148 : : {
16149 : 24053 : if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16150 : 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16151 : 24053 : gcc_assert ((n->value & GOVD_SEEN) == 0
16152 : : || ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16153 : : == 0));
16154 : : }
16155 : :
16156 : : /* If we have a target region, we can push all the attaches to the
16157 : : end of the list (we may have standalone "attach" operations
16158 : : synthesized for GOMP_MAP_STRUCT nodes that must be processed after
16159 : : the attachment point AND the pointed-to block have been mapped).
16160 : : If we have something else, e.g. "enter data", we need to keep
16161 : : "attach" nodes together with the previous node they attach to so
16162 : : that separate "exit data" operations work properly (see
16163 : : libgomp/target.c). */
16164 : 25294 : if ((ctx->region_type & ORT_TARGET) != 0
16165 : 25294 : && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH
16166 : 15546 : || (OMP_CLAUSE_MAP_KIND (c)
16167 : : == GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION)))
16168 : : move_attach = true;
16169 : :
16170 : 53189 : end_adjust_omp_map_clause:
16171 : 53189 : exit_omp_iterator_loop_context (c);
16172 : 53189 : break;
16173 : :
16174 : 8207 : case OMP_CLAUSE_TO:
16175 : 8207 : case OMP_CLAUSE_FROM:
16176 : 8207 : case OMP_CLAUSE__CACHE_:
16177 : 8207 : decl = OMP_CLAUSE_DECL (c);
16178 : 8207 : if (!DECL_P (decl))
16179 : : break;
16180 : 6187 : if (DECL_SIZE (decl)
16181 : 6187 : && !poly_int_tree_p (DECL_SIZE (decl)))
16182 : : {
16183 : 4 : tree decl2 = DECL_VALUE_EXPR (decl);
16184 : 4 : gcc_assert (INDIRECT_REF_P (decl2));
16185 : 4 : decl2 = TREE_OPERAND (decl2, 0);
16186 : 4 : gcc_assert (DECL_P (decl2));
16187 : 4 : tree mem = build_simple_mem_ref (decl2);
16188 : 4 : OMP_CLAUSE_DECL (c) = mem;
16189 : 4 : OMP_CLAUSE_SIZE (c) = TYPE_SIZE_UNIT (TREE_TYPE (decl));
16190 : 4 : if (ctx->outer_context)
16191 : : {
16192 : 4 : omp_notice_variable (ctx->outer_context, decl2, true);
16193 : 4 : omp_notice_variable (ctx->outer_context,
16194 : 4 : OMP_CLAUSE_SIZE (c), true);
16195 : : }
16196 : : }
16197 : 6183 : else if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
16198 : 0 : OMP_CLAUSE_SIZE (c) = DECL_SIZE_UNIT (decl);
16199 : : break;
16200 : :
16201 : 15206 : case OMP_CLAUSE_REDUCTION:
16202 : 15206 : if (OMP_CLAUSE_REDUCTION_INSCAN (c))
16203 : : {
16204 : 811 : decl = OMP_CLAUSE_DECL (c);
16205 : 811 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16206 : 811 : if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
16207 : : {
16208 : 69 : remove = true;
16209 : 69 : error_at (OMP_CLAUSE_LOCATION (c),
16210 : : "%qD specified in %<inscan%> %<reduction%> clause "
16211 : : "but not in %<scan%> directive clause", decl);
16212 : 69 : break;
16213 : : }
16214 : : has_inscan_reductions = true;
16215 : : }
16216 : : /* FALLTHRU */
16217 : 17737 : case OMP_CLAUSE_IN_REDUCTION:
16218 : 17737 : case OMP_CLAUSE_TASK_REDUCTION:
16219 : 17737 : decl = OMP_CLAUSE_DECL (c);
16220 : : /* OpenACC reductions need a present_or_copy data clause.
16221 : : Add one if necessary. Emit error when the reduction is private. */
16222 : 17737 : if (ctx->region_type == ORT_ACC_PARALLEL
16223 : 17205 : || ctx->region_type == ORT_ACC_SERIAL)
16224 : : {
16225 : 803 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16226 : 803 : if (n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE))
16227 : : {
16228 : 13 : remove = true;
16229 : 13 : error_at (OMP_CLAUSE_LOCATION (c), "invalid private "
16230 : 13 : "reduction on %qE", DECL_NAME (decl));
16231 : : }
16232 : 790 : else if ((n->value & GOVD_MAP) == 0)
16233 : : {
16234 : 524 : tree next = OMP_CLAUSE_CHAIN (c);
16235 : 524 : tree nc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_MAP);
16236 : 524 : OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_TOFROM);
16237 : 524 : OMP_CLAUSE_DECL (nc) = decl;
16238 : 524 : OMP_CLAUSE_CHAIN (c) = nc;
16239 : 524 : lang_hooks.decls.omp_finish_clause (nc, pre_p,
16240 : 524 : (ctx->region_type
16241 : : & ORT_ACC) != 0);
16242 : 550 : while (1)
16243 : : {
16244 : 537 : OMP_CLAUSE_MAP_IN_REDUCTION (nc) = 1;
16245 : 537 : if (OMP_CLAUSE_CHAIN (nc) == NULL)
16246 : : break;
16247 : 13 : nc = OMP_CLAUSE_CHAIN (nc);
16248 : : }
16249 : 524 : OMP_CLAUSE_CHAIN (nc) = next;
16250 : 524 : n->value |= GOVD_MAP;
16251 : : }
16252 : : }
16253 : 17737 : if (DECL_P (decl)
16254 : 17737 : && omp_shared_to_firstprivate_optimizable_decl_p (decl))
16255 : 7958 : omp_mark_stores (gimplify_omp_ctxp->outer_context, decl);
16256 : : break;
16257 : :
16258 : 3421 : case OMP_CLAUSE_ALLOCATE:
16259 : 3421 : decl = OMP_CLAUSE_DECL (c);
16260 : 3421 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16261 : 3421 : if (n != NULL && !(n->value & GOVD_SEEN))
16262 : : {
16263 : 1176 : if ((n->value & (GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LINEAR))
16264 : : != 0
16265 : 1176 : && (n->value & (GOVD_REDUCTION | GOVD_LASTPRIVATE)) == 0)
16266 : : remove = true;
16267 : : }
16268 : : if (!remove
16269 : 2245 : && OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
16270 : 1153 : && TREE_CODE (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)) != INTEGER_CST
16271 : 471 : && ((ctx->region_type & (ORT_PARALLEL | ORT_TARGET)) != 0
16272 : 347 : || (ctx->region_type & ORT_TASKLOOP) == ORT_TASK
16273 : 287 : || (ctx->region_type & ORT_HOST_TEAMS) == ORT_HOST_TEAMS))
16274 : : {
16275 : 202 : tree allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
16276 : 202 : n = splay_tree_lookup (ctx->variables, (splay_tree_key) allocator);
16277 : 202 : if (n == NULL)
16278 : : {
16279 : 82 : enum omp_clause_default_kind default_kind
16280 : : = ctx->default_kind;
16281 : 82 : ctx->default_kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
16282 : 82 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16283 : : true);
16284 : 82 : ctx->default_kind = default_kind;
16285 : : }
16286 : : else
16287 : 120 : omp_notice_variable (ctx, OMP_CLAUSE_ALLOCATE_ALLOCATOR (c),
16288 : : true);
16289 : : }
16290 : : break;
16291 : :
16292 : : case OMP_CLAUSE_COPYIN:
16293 : : case OMP_CLAUSE_COPYPRIVATE:
16294 : : case OMP_CLAUSE_IF:
16295 : : case OMP_CLAUSE_SELF:
16296 : : case OMP_CLAUSE_NUM_THREADS:
16297 : : case OMP_CLAUSE_NUM_TEAMS:
16298 : : case OMP_CLAUSE_THREAD_LIMIT:
16299 : : case OMP_CLAUSE_DIST_SCHEDULE:
16300 : : case OMP_CLAUSE_DEVICE:
16301 : : case OMP_CLAUSE_SCHEDULE:
16302 : : case OMP_CLAUSE_NOWAIT:
16303 : : case OMP_CLAUSE_ORDERED:
16304 : : case OMP_CLAUSE_DEFAULT:
16305 : : case OMP_CLAUSE_UNTIED:
16306 : : case OMP_CLAUSE_COLLAPSE:
16307 : : case OMP_CLAUSE_FINAL:
16308 : : case OMP_CLAUSE_MERGEABLE:
16309 : : case OMP_CLAUSE_PROC_BIND:
16310 : : case OMP_CLAUSE_SAFELEN:
16311 : : case OMP_CLAUSE_SIMDLEN:
16312 : : case OMP_CLAUSE_DEPEND:
16313 : : case OMP_CLAUSE_DOACROSS:
16314 : : case OMP_CLAUSE_PRIORITY:
16315 : : case OMP_CLAUSE_GRAINSIZE:
16316 : : case OMP_CLAUSE_NUM_TASKS:
16317 : : case OMP_CLAUSE_NOGROUP:
16318 : : case OMP_CLAUSE_THREADS:
16319 : : case OMP_CLAUSE_SIMD:
16320 : : case OMP_CLAUSE_FILTER:
16321 : : case OMP_CLAUSE_HINT:
16322 : : case OMP_CLAUSE_DEFAULTMAP:
16323 : : case OMP_CLAUSE_ORDER:
16324 : : case OMP_CLAUSE_BIND:
16325 : : case OMP_CLAUSE_DETACH:
16326 : : case OMP_CLAUSE_USE_DEVICE_PTR:
16327 : : case OMP_CLAUSE_USE_DEVICE_ADDR:
16328 : : case OMP_CLAUSE_ASYNC:
16329 : : case OMP_CLAUSE_WAIT:
16330 : : case OMP_CLAUSE_INDEPENDENT:
16331 : : case OMP_CLAUSE_NUM_GANGS:
16332 : : case OMP_CLAUSE_NUM_WORKERS:
16333 : : case OMP_CLAUSE_VECTOR_LENGTH:
16334 : : case OMP_CLAUSE_GANG:
16335 : : case OMP_CLAUSE_WORKER:
16336 : : case OMP_CLAUSE_VECTOR:
16337 : : case OMP_CLAUSE_AUTO:
16338 : : case OMP_CLAUSE_SEQ:
16339 : : case OMP_CLAUSE_TILE:
16340 : : case OMP_CLAUSE_IF_PRESENT:
16341 : : case OMP_CLAUSE_FINALIZE:
16342 : : case OMP_CLAUSE_INCLUSIVE:
16343 : : case OMP_CLAUSE_EXCLUSIVE:
16344 : : break;
16345 : :
16346 : 0 : case OMP_CLAUSE_NOHOST:
16347 : 0 : default:
16348 : 0 : gcc_unreachable ();
16349 : : }
16350 : :
16351 : 126016 : if (remove)
16352 : 9634 : *list_p = OMP_CLAUSE_CHAIN (c);
16353 : 233596 : else if (move_attach)
16354 : : {
16355 : : /* Remove attach node from here, separate out into its own list. */
16356 : 2312 : *attach_tail = c;
16357 : 2312 : *list_p = OMP_CLAUSE_CHAIN (c);
16358 : 2312 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
16359 : 2312 : attach_tail = &OMP_CLAUSE_CHAIN (c);
16360 : : }
16361 : : else
16362 : 231284 : list_p = &OMP_CLAUSE_CHAIN (c);
16363 : : }
16364 : :
16365 : : /* Splice attach nodes at the end of the list. */
16366 : 127668 : if (attach_list)
16367 : : {
16368 : 1100 : *list_p = attach_list;
16369 : 1100 : list_p = attach_tail;
16370 : : }
16371 : :
16372 : : /* Add in any implicit data sharing. */
16373 : 127668 : struct gimplify_adjust_omp_clauses_data data;
16374 : 127668 : if ((gimplify_omp_ctxp->region_type & ORT_ACC) == 0)
16375 : : {
16376 : : /* OpenMP. Implicit clauses are added at the start of the clause list,
16377 : : but after any non-map clauses. */
16378 : : tree *implicit_add_list_p = orig_list_p;
16379 : 248658 : while (*implicit_add_list_p
16380 : 248658 : && OMP_CLAUSE_CODE (*implicit_add_list_p) != OMP_CLAUSE_MAP)
16381 : 150829 : implicit_add_list_p = &OMP_CLAUSE_CHAIN (*implicit_add_list_p);
16382 : 97829 : data.list_p = implicit_add_list_p;
16383 : : }
16384 : : else
16385 : : /* OpenACC. */
16386 : 29839 : data.list_p = list_p;
16387 : 127668 : data.pre_p = pre_p;
16388 : 127668 : splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
16389 : :
16390 : 127668 : if (has_inscan_reductions)
16391 : 2431 : for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
16392 : 1822 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
16393 : 1822 : && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
16394 : : {
16395 : 5 : error_at (OMP_CLAUSE_LOCATION (c),
16396 : : "%<inscan%> %<reduction%> clause used together with "
16397 : : "%<linear%> clause for a variable other than loop "
16398 : : "iterator");
16399 : 5 : break;
16400 : : }
16401 : :
16402 : 127668 : gimplify_omp_ctxp = ctx->outer_context;
16403 : 127668 : delete_omp_context (ctx);
16404 : 127668 : }
16405 : :
16406 : : /* Try to evaluate a novariants clause. Return 1 if true, 0 if false or absent,
16407 : : * -1 if run-time evaluation is needed. */
16408 : :
16409 : : int
16410 : 243002 : omp_has_novariants (void)
16411 : : {
16412 : 243002 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16413 : 243002 : if (ctx != NULL && ctx->code == OMP_DISPATCH && !ctx->in_call_args)
16414 : : {
16415 : 3278 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOVARIANTS);
16416 : 3278 : if (c != NULL_TREE)
16417 : : {
16418 : 287 : if (integer_nonzerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16419 : : return 1;
16420 : 171 : else if (integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
16421 : : return 0;
16422 : : else
16423 : : return -1;
16424 : : }
16425 : : return 0;
16426 : : }
16427 : : return 0;
16428 : : }
16429 : :
16430 : : /* Try to evaluate a nocontext clause. Return 1 if true, 0 if false or absent,
16431 : : * -1 if run-time evaluation is needed. */
16432 : :
16433 : : static int
16434 : 1891 : omp_has_nocontext (void)
16435 : : {
16436 : 1891 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16437 : 1891 : if (ctx != NULL && ctx->code == OMP_DISPATCH)
16438 : : {
16439 : 1891 : tree c = omp_find_clause (ctx->clauses, OMP_CLAUSE_NOCONTEXT);
16440 : 1891 : if (c != NULL_TREE)
16441 : : {
16442 : 256 : if (integer_nonzerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16443 : : return 1;
16444 : 94 : else if (integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
16445 : : return 0;
16446 : : else
16447 : : return -1;
16448 : : }
16449 : : return 0;
16450 : : }
16451 : : return 0;
16452 : : }
16453 : :
16454 : : /* Collect a list of traits for enclosing constructs in the current
16455 : : OpenMP context. The list is in the same format as the trait selector
16456 : : list of construct trait sets built by the front ends.
16457 : :
16458 : : Per the OpenMP specification, the construct trait set includes constructs
16459 : : up to an enclosing "target" construct. If there is no "target" construct,
16460 : : then additional things may be added to the construct trait set (simd for
16461 : : simd clones, additional constructs associated with "declare variant",
16462 : : the target trait for "declare target"); those are not handled here.
16463 : : In particular simd clones are not known during gimplification so
16464 : : matching/scoring of context selectors that might involve them needs
16465 : : to be deferred to the omp_device_lower pass. */
16466 : :
16467 : : tree
16468 : 2008 : omp_get_construct_context (void)
16469 : : {
16470 : 2008 : tree result = NULL_TREE;
16471 : 3966 : for (struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; ctx;)
16472 : : {
16473 : 2039 : if (((ctx->region_type & (ORT_TARGET | ORT_IMPLICIT_TARGET | ORT_ACC))
16474 : : == ORT_TARGET)
16475 : 81 : && ctx->code == OMP_TARGET)
16476 : : {
16477 : 81 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TARGET,
16478 : : NULL_TREE, NULL_TREE, result);
16479 : : /* We're not interested in any outer constructs. */
16480 : 81 : break;
16481 : : }
16482 : 1958 : else if ((ctx->region_type & ORT_PARALLEL) && ctx->code == OMP_PARALLEL)
16483 : 211 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_PARALLEL,
16484 : : NULL_TREE, NULL_TREE, result);
16485 : 1747 : else if ((ctx->region_type & ORT_TEAMS) && ctx->code == OMP_TEAMS)
16486 : 71 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_TEAMS,
16487 : : NULL_TREE, NULL_TREE, result);
16488 : 1676 : else if (ctx->region_type == ORT_WORKSHARE && ctx->code == OMP_FOR)
16489 : 164 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_FOR,
16490 : : NULL_TREE, NULL_TREE, result);
16491 : 1512 : else if (ctx->code == OMP_DISPATCH && omp_has_nocontext () != 1)
16492 : 1273 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_DISPATCH,
16493 : : NULL_TREE, NULL_TREE, result);
16494 : 239 : else if (ctx->region_type == ORT_SIMD
16495 : 32 : && ctx->code == OMP_SIMD
16496 : 271 : && !omp_find_clause (ctx->clauses, OMP_CLAUSE_BIND))
16497 : : {
16498 : 32 : tree props = NULL_TREE;
16499 : 32 : tree *last = &props;
16500 : 72 : for (tree c = ctx->clauses; c; c = OMP_CLAUSE_CHAIN (c))
16501 : 40 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMDLEN
16502 : 32 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INBRANCH
16503 : 72 : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOTINBRANCH)
16504 : : {
16505 : 8 : *last = unshare_expr (c);
16506 : 8 : last = &(OMP_CLAUSE_CHAIN (c));
16507 : : }
16508 : 32 : result = make_trait_selector (OMP_TRAIT_CONSTRUCT_SIMD,
16509 : : NULL_TREE, props, result);
16510 : : }
16511 : 207 : else if (ctx->region_type == ORT_WORKSHARE
16512 : 5 : && ctx->code == OMP_LOOP
16513 : 0 : && ctx->outer_context
16514 : 0 : && ctx->outer_context->region_type == ORT_COMBINED_PARALLEL
16515 : 0 : && ctx->outer_context->outer_context
16516 : 0 : && ctx->outer_context->outer_context->code == OMP_LOOP
16517 : 0 : && ctx->outer_context->outer_context->distribute)
16518 : 1958 : ctx = ctx->outer_context->outer_context;
16519 : 1958 : ctx = ctx->outer_context;
16520 : : }
16521 : :
16522 : 2008 : return result;
16523 : : }
16524 : :
16525 : : /* Gimplify OACC_CACHE. */
16526 : :
16527 : : static void
16528 : 665 : gimplify_oacc_cache (tree *expr_p, gimple_seq *pre_p)
16529 : : {
16530 : 665 : tree expr = *expr_p;
16531 : :
16532 : 665 : gimplify_scan_omp_clauses (&OACC_CACHE_CLAUSES (expr), pre_p, ORT_ACC,
16533 : : OACC_CACHE);
16534 : 665 : gimplify_adjust_omp_clauses (pre_p, NULL, &OACC_CACHE_CLAUSES (expr),
16535 : : OACC_CACHE);
16536 : :
16537 : : /* TODO: Do something sensible with this information. */
16538 : :
16539 : 665 : *expr_p = NULL_TREE;
16540 : 665 : }
16541 : :
16542 : : /* Helper function of gimplify_oacc_declare. The helper's purpose is to,
16543 : : if required, translate 'kind' in CLAUSE into an 'entry' kind and 'exit'
16544 : : kind. The entry kind will replace the one in CLAUSE, while the exit
16545 : : kind will be used in a new omp_clause and returned to the caller. */
16546 : :
16547 : : static tree
16548 : 190 : gimplify_oacc_declare_1 (tree clause)
16549 : : {
16550 : 190 : HOST_WIDE_INT kind, new_op;
16551 : 190 : bool ret = false;
16552 : 190 : tree c = NULL;
16553 : :
16554 : 190 : kind = OMP_CLAUSE_MAP_KIND (clause);
16555 : :
16556 : 190 : switch (kind)
16557 : : {
16558 : : case GOMP_MAP_ALLOC:
16559 : : new_op = GOMP_MAP_RELEASE;
16560 : : ret = true;
16561 : : break;
16562 : :
16563 : 29 : case GOMP_MAP_FROM:
16564 : 29 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_FORCE_ALLOC);
16565 : 29 : new_op = GOMP_MAP_FROM;
16566 : 29 : ret = true;
16567 : 29 : break;
16568 : :
16569 : 40 : case GOMP_MAP_TOFROM:
16570 : 40 : OMP_CLAUSE_SET_MAP_KIND (clause, GOMP_MAP_TO);
16571 : 40 : new_op = GOMP_MAP_FROM;
16572 : 40 : ret = true;
16573 : 40 : break;
16574 : :
16575 : : case GOMP_MAP_DEVICE_RESIDENT:
16576 : : case GOMP_MAP_FORCE_DEVICEPTR:
16577 : : case GOMP_MAP_FORCE_PRESENT:
16578 : : case GOMP_MAP_LINK:
16579 : : case GOMP_MAP_POINTER:
16580 : : case GOMP_MAP_TO:
16581 : : break;
16582 : :
16583 : 0 : default:
16584 : 0 : gcc_unreachable ();
16585 : 69 : break;
16586 : : }
16587 : :
16588 : 69 : if (ret)
16589 : : {
16590 : 116 : c = build_omp_clause (OMP_CLAUSE_LOCATION (clause), OMP_CLAUSE_MAP);
16591 : 116 : OMP_CLAUSE_SET_MAP_KIND (c, new_op);
16592 : 116 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clause);
16593 : : }
16594 : :
16595 : 190 : return c;
16596 : : }
16597 : :
16598 : : /* Gimplify OACC_DECLARE. */
16599 : :
16600 : : static void
16601 : 254 : gimplify_oacc_declare (tree *expr_p, gimple_seq *pre_p)
16602 : : {
16603 : 254 : tree expr = *expr_p;
16604 : 254 : gomp_target *stmt;
16605 : 254 : tree clauses, t, decl;
16606 : :
16607 : 254 : clauses = OACC_DECLARE_CLAUSES (expr);
16608 : :
16609 : 254 : gimplify_scan_omp_clauses (&clauses, pre_p, ORT_TARGET_DATA, OACC_DECLARE);
16610 : 254 : gimplify_adjust_omp_clauses (pre_p, NULL, &clauses, OACC_DECLARE);
16611 : :
16612 : 516 : for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16613 : : {
16614 : 262 : decl = OMP_CLAUSE_DECL (t);
16615 : :
16616 : 262 : if (TREE_CODE (decl) == MEM_REF)
16617 : 8 : decl = TREE_OPERAND (decl, 0);
16618 : :
16619 : 262 : if (VAR_P (decl) && !is_oacc_declared (decl))
16620 : : {
16621 : 262 : tree attr = get_identifier ("oacc declare target");
16622 : 262 : DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE,
16623 : 262 : DECL_ATTRIBUTES (decl));
16624 : : }
16625 : :
16626 : 262 : if (VAR_P (decl)
16627 : 262 : && !is_global_var (decl)
16628 : 452 : && DECL_CONTEXT (decl) == current_function_decl)
16629 : : {
16630 : 190 : tree c = gimplify_oacc_declare_1 (t);
16631 : 190 : if (c)
16632 : : {
16633 : 116 : if (oacc_declare_returns == NULL)
16634 : 40 : oacc_declare_returns = new hash_map<tree, tree>;
16635 : :
16636 : 116 : oacc_declare_returns->put (decl, c);
16637 : : }
16638 : : }
16639 : :
16640 : 262 : if (gimplify_omp_ctxp)
16641 : 72 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_SEEN);
16642 : : }
16643 : :
16644 : 254 : stmt = gimple_build_omp_target (NULL, GF_OMP_TARGET_KIND_OACC_DECLARE,
16645 : : clauses);
16646 : :
16647 : 254 : gimplify_seq_add_stmt (pre_p, stmt);
16648 : :
16649 : 254 : *expr_p = NULL_TREE;
16650 : 254 : }
16651 : :
16652 : : /* Gimplify the contents of an OMP_PARALLEL statement. This involves
16653 : : gimplification of the body, as well as scanning the body for used
16654 : : variables. We need to do this scan now, because variable-sized
16655 : : decls will be decomposed during gimplification. */
16656 : :
16657 : : static void
16658 : 18156 : gimplify_omp_parallel (tree *expr_p, gimple_seq *pre_p)
16659 : : {
16660 : 18156 : tree expr = *expr_p;
16661 : 18156 : gimple *g;
16662 : 18156 : gimple_seq body = NULL;
16663 : :
16664 : 36312 : gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p,
16665 : 18156 : OMP_PARALLEL_COMBINED (expr)
16666 : : ? ORT_COMBINED_PARALLEL
16667 : : : ORT_PARALLEL, OMP_PARALLEL);
16668 : :
16669 : 18156 : push_gimplify_context ();
16670 : :
16671 : 18156 : g = gimplify_and_return_first (OMP_PARALLEL_BODY (expr), &body);
16672 : 18156 : if (gimple_code (g) == GIMPLE_BIND)
16673 : 18156 : pop_gimplify_context (g);
16674 : : else
16675 : 0 : pop_gimplify_context (NULL);
16676 : :
16677 : 18156 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_PARALLEL_CLAUSES (expr),
16678 : : OMP_PARALLEL);
16679 : :
16680 : 36312 : g = gimple_build_omp_parallel (body,
16681 : 18156 : OMP_PARALLEL_CLAUSES (expr),
16682 : : NULL_TREE, NULL_TREE);
16683 : 18156 : if (OMP_PARALLEL_COMBINED (expr))
16684 : 12524 : gimple_omp_set_subcode (g, GF_OMP_PARALLEL_COMBINED);
16685 : 18156 : gimplify_seq_add_stmt (pre_p, g);
16686 : 18156 : *expr_p = NULL_TREE;
16687 : 18156 : }
16688 : :
16689 : : /* Gimplify the contents of an OMP_TASK statement. This involves
16690 : : gimplification of the body, as well as scanning the body for used
16691 : : variables. We need to do this scan now, because variable-sized
16692 : : decls will be decomposed during gimplification. */
16693 : :
16694 : : static void
16695 : 3846 : gimplify_omp_task (tree *expr_p, gimple_seq *pre_p)
16696 : : {
16697 : 3846 : tree expr = *expr_p;
16698 : 3846 : gimple *g;
16699 : 3846 : gimple_seq body = NULL;
16700 : 3846 : bool nowait = false;
16701 : 3846 : bool has_depend = false;
16702 : :
16703 : 3846 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16704 : : {
16705 : 236 : for (tree c = OMP_TASK_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
16706 : 150 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
16707 : : {
16708 : 108 : has_depend = true;
16709 : 108 : if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_MUTEXINOUTSET)
16710 : : {
16711 : 9 : error_at (OMP_CLAUSE_LOCATION (c),
16712 : : "%<mutexinoutset%> kind in %<depend%> clause on a "
16713 : : "%<taskwait%> construct");
16714 : 9 : break;
16715 : : }
16716 : : }
16717 : 42 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT)
16718 : 42 : nowait = true;
16719 : 95 : if (nowait && !has_depend)
16720 : : {
16721 : 5 : error_at (EXPR_LOCATION (expr),
16722 : : "%<taskwait%> construct with %<nowait%> clause but no "
16723 : : "%<depend%> clauses");
16724 : 5 : *expr_p = NULL_TREE;
16725 : 5 : return;
16726 : : }
16727 : : }
16728 : :
16729 : 11523 : gimplify_scan_omp_clauses (&OMP_TASK_CLAUSES (expr), pre_p,
16730 : 3841 : omp_find_clause (OMP_TASK_CLAUSES (expr),
16731 : : OMP_CLAUSE_UNTIED)
16732 : : ? ORT_UNTIED_TASK : ORT_TASK, OMP_TASK);
16733 : :
16734 : 3841 : if (OMP_TASK_BODY (expr))
16735 : : {
16736 : 3751 : push_gimplify_context ();
16737 : :
16738 : 3751 : g = gimplify_and_return_first (OMP_TASK_BODY (expr), &body);
16739 : 3751 : if (gimple_code (g) == GIMPLE_BIND)
16740 : 3751 : pop_gimplify_context (g);
16741 : : else
16742 : 0 : pop_gimplify_context (NULL);
16743 : : }
16744 : :
16745 : 3841 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_TASK_CLAUSES (expr),
16746 : : OMP_TASK);
16747 : :
16748 : 7682 : g = gimple_build_omp_task (body,
16749 : 3841 : OMP_TASK_CLAUSES (expr),
16750 : : NULL_TREE, NULL_TREE,
16751 : : NULL_TREE, NULL_TREE, NULL_TREE);
16752 : 3841 : if (OMP_TASK_BODY (expr) == NULL_TREE)
16753 : 90 : gimple_omp_task_set_taskwait_p (g, true);
16754 : 3841 : gimplify_seq_add_stmt (pre_p, g);
16755 : 3841 : *expr_p = NULL_TREE;
16756 : : }
16757 : :
16758 : : /* Helper function for gimplify_omp_for. If *TP is not a gimple constant,
16759 : : force it into a temporary initialized in PRE_P and add firstprivate clause
16760 : : to ORIG_FOR_STMT. */
16761 : :
16762 : : static void
16763 : 4391 : gimplify_omp_taskloop_expr (tree type, tree *tp, gimple_seq *pre_p,
16764 : : tree orig_for_stmt)
16765 : : {
16766 : 4391 : if (*tp == NULL || is_gimple_constant (*tp))
16767 : : return;
16768 : :
16769 : 779 : if (TREE_CODE (*tp) == SAVE_EXPR)
16770 : 135 : gimplify_save_expr (tp, pre_p, NULL);
16771 : : else
16772 : 644 : *tp = get_initialized_tmp_var (*tp, pre_p, NULL, false);
16773 : : /* Reference to pointer conversion is considered useless,
16774 : : but is significant for firstprivate clause. Force it
16775 : : here. */
16776 : 779 : if (type
16777 : 687 : && TREE_CODE (type) == POINTER_TYPE
16778 : 869 : && TREE_CODE (TREE_TYPE (*tp)) == REFERENCE_TYPE)
16779 : : {
16780 : 12 : tree v = create_tmp_var (TYPE_MAIN_VARIANT (type));
16781 : 12 : tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, *tp);
16782 : 12 : gimplify_and_add (m, pre_p);
16783 : 12 : *tp = v;
16784 : : }
16785 : :
16786 : 779 : tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE);
16787 : 779 : OMP_CLAUSE_DECL (c) = *tp;
16788 : 779 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (orig_for_stmt);
16789 : 779 : OMP_FOR_CLAUSES (orig_for_stmt) = c;
16790 : : }
16791 : :
16792 : : /* Helper function of gimplify_omp_for, find OMP_ORDERED with
16793 : : null OMP_ORDERED_BODY inside of OMP_FOR's body. */
16794 : :
16795 : : static tree
16796 : 16484 : find_standalone_omp_ordered (tree *tp, int *walk_subtrees, void *)
16797 : : {
16798 : 16484 : switch (TREE_CODE (*tp))
16799 : : {
16800 : 896 : case OMP_ORDERED:
16801 : 896 : if (OMP_ORDERED_BODY (*tp) == NULL_TREE)
16802 : : return *tp;
16803 : : break;
16804 : 23 : case OMP_SIMD:
16805 : 23 : case OMP_PARALLEL:
16806 : 23 : case OMP_TARGET:
16807 : 23 : *walk_subtrees = 0;
16808 : 23 : break;
16809 : : default:
16810 : : break;
16811 : : }
16812 : : return NULL_TREE;
16813 : : }
16814 : :
16815 : : /* Gimplify standalone loop transforming directive which has the
16816 : : transformations applied already. So, all that is needed is gimplify
16817 : : the remaining loops as normal loops. */
16818 : :
16819 : : static enum gimplify_status
16820 : 2264 : gimplify_omp_loop_xform (tree *expr_p, gimple_seq *pre_p)
16821 : : {
16822 : 2264 : tree for_stmt = *expr_p;
16823 : :
16824 : 2264 : if (OMP_FOR_PRE_BODY (for_stmt))
16825 : 759 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), pre_p);
16826 : :
16827 : 2264 : gimple_seq pre_body = NULL, post_body = NULL;
16828 : 5203 : for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
16829 : : {
16830 : 2939 : if (TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i) == NULL_TREE)
16831 : 1707 : continue;
16832 : 1283 : tree iters = NULL_TREE;
16833 : 1283 : if (i == 0
16834 : 826 : && TREE_CODE (for_stmt) == OMP_UNROLL
16835 : 1771 : && !omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_PARTIAL))
16836 : : {
16837 : 311 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_FULL))
16838 : 269 : iters = omp_loop_number_of_iterations (for_stmt, 0, NULL);
16839 : : else
16840 : 42 : iters = build_int_cst (integer_type_node, 8);
16841 : : }
16842 : 1283 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
16843 : 1283 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
16844 : 1283 : tree decl = TREE_OPERAND (t, 0);
16845 : 1283 : gcc_assert (DECL_P (decl));
16846 : 1283 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
16847 : : || POINTER_TYPE_P (TREE_TYPE (decl)));
16848 : 1283 : if (DECL_ARTIFICIAL (decl)
16849 : 876 : && TREE_PRIVATE (t)
16850 : 867 : && gimplify_omp_ctxp
16851 : 1613 : && gimplify_omp_ctxp->region_type != ORT_NONE)
16852 : : {
16853 : : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
16854 : 504 : do
16855 : : {
16856 : 504 : splay_tree_node n
16857 : 504 : = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
16858 : 504 : if (n != NULL)
16859 : : break;
16860 : 346 : else if (ctx->region_type != ORT_WORKSHARE
16861 : : && ctx->region_type != ORT_TASKGROUP
16862 : 62 : && ctx->region_type != ORT_SIMD
16863 : 38 : && ctx->region_type != ORT_ACC
16864 : 38 : && !(ctx->region_type & ORT_TARGET_DATA))
16865 : : {
16866 : 38 : omp_add_variable (ctx, decl, GOVD_PRIVATE);
16867 : 38 : break;
16868 : : }
16869 : 308 : ctx = ctx->outer_context;
16870 : : }
16871 : 308 : while (ctx);
16872 : : }
16873 : 1283 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16874 : : {
16875 : 23 : gcc_assert (seen_error ());
16876 : 23 : continue;
16877 : : }
16878 : 1260 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16879 : : fb_rvalue);
16880 : 1260 : gimplify_and_add (t, &pre_body);
16881 : 1260 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16882 : 1260 : gcc_assert (TREE_OPERAND (t, 0) == decl);
16883 : 1260 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
16884 : : {
16885 : 28 : gcc_assert (seen_error ());
16886 : 28 : continue;
16887 : : }
16888 : 1232 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16889 : : fb_rvalue);
16890 : 1232 : tree l1 = create_artificial_label (UNKNOWN_LOCATION);
16891 : 1232 : tree l2 = create_artificial_label (UNKNOWN_LOCATION);
16892 : 1232 : tree l3 = create_artificial_label (UNKNOWN_LOCATION);
16893 : 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_goto (l2));
16894 : 1232 : gimplify_seq_add_stmt (&pre_body, gimple_build_label (l1));
16895 : 1232 : gimple_seq this_post_body = NULL;
16896 : 1232 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
16897 : 1232 : if (TREE_CODE (t) == MODIFY_EXPR)
16898 : : {
16899 : 975 : t = TREE_OPERAND (t, 1);
16900 : 975 : if (TREE_CODE (t) == PLUS_EXPR
16901 : 975 : && TREE_OPERAND (t, 1) == decl)
16902 : : {
16903 : 0 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
16904 : 0 : TREE_OPERAND (t, 0) = decl;
16905 : : }
16906 : 975 : gimplify_expr (&TREE_OPERAND (t, 1), pre_p, NULL, is_gimple_val,
16907 : : fb_rvalue);
16908 : : }
16909 : 1232 : gimplify_and_add (TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i),
16910 : : &this_post_body);
16911 : 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l2));
16912 : 1232 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
16913 : 1232 : gcond *cond = NULL;
16914 : 1232 : tree d = decl;
16915 : 1232 : gimplify_expr (&d, &this_post_body, NULL, is_gimple_val, fb_rvalue);
16916 : 1232 : if (iters && tree_fits_uhwi_p (iters))
16917 : : {
16918 : 299 : unsigned HOST_WIDE_INT niters = tree_to_uhwi (iters);
16919 : 299 : if ((unsigned HOST_WIDE_INT) (int) niters == niters
16920 : 299 : && (int) niters > 0)
16921 : : {
16922 : 299 : t = build2 (TREE_CODE (t), boolean_type_node, d,
16923 : 299 : TREE_OPERAND (t, 1));
16924 : 299 : t = build3 (ANNOTATE_EXPR, TREE_TYPE (t), t,
16925 : : build_int_cst (integer_type_node,
16926 : : annot_expr_unroll_kind),
16927 : 299 : build_int_cst (integer_type_node, niters));
16928 : 299 : gimplify_expr (&t, &this_post_body, NULL, is_gimple_val,
16929 : : fb_rvalue);
16930 : 299 : cond = gimple_build_cond (NE_EXPR, t, boolean_false_node,
16931 : : l1, l3);
16932 : : }
16933 : : }
16934 : 299 : if (cond == NULL)
16935 : 933 : cond = gimple_build_cond (TREE_CODE (t), d, TREE_OPERAND (t, 1),
16936 : : l1, l3);
16937 : 1232 : gimplify_seq_add_stmt (&this_post_body, cond);
16938 : 1232 : gimplify_seq_add_stmt (&this_post_body, gimple_build_label (l3));
16939 : 1232 : gimplify_seq_add_seq (&this_post_body, post_body);
16940 : 1232 : post_body = this_post_body;
16941 : : }
16942 : 2264 : gimplify_seq_add_seq (pre_p, pre_body);
16943 : 2264 : gimplify_and_add (OMP_FOR_BODY (for_stmt), pre_p);
16944 : 2264 : gimplify_seq_add_seq (pre_p, post_body);
16945 : :
16946 : 2264 : *expr_p = NULL_TREE;
16947 : 2264 : return GS_ALL_DONE;
16948 : : }
16949 : :
16950 : : /* Gimplify the gross structure of an OMP_FOR statement. */
16951 : :
16952 : : static enum gimplify_status
16953 : 58061 : gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
16954 : : {
16955 : 58061 : tree for_stmt, orig_for_stmt, inner_for_stmt = NULL_TREE, decl, var, t;
16956 : 58061 : enum gimplify_status ret = GS_ALL_DONE;
16957 : 58061 : enum gimplify_status tret;
16958 : 58061 : gomp_for *gfor;
16959 : 58061 : gimple_seq for_body, for_pre_body;
16960 : 58061 : int i;
16961 : 58061 : bitmap has_decl_expr = NULL;
16962 : 58061 : enum omp_region_type ort = ORT_WORKSHARE;
16963 : 58061 : bool openacc = TREE_CODE (*expr_p) == OACC_LOOP;
16964 : :
16965 : 58061 : orig_for_stmt = for_stmt = *expr_p;
16966 : :
16967 : 58061 : bool loop_p = (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_BIND)
16968 : 58061 : != NULL_TREE);
16969 : 58132 : while (OMP_FOR_INIT (for_stmt) == NULL_TREE)
16970 : : {
16971 : 17752 : tree *data[4] = { NULL, NULL, NULL, NULL };
16972 : 17752 : gcc_assert (TREE_CODE (for_stmt) != OACC_LOOP);
16973 : 17752 : inner_for_stmt = walk_tree (&OMP_FOR_BODY (for_stmt),
16974 : : find_combined_omp_for, data, NULL);
16975 : 17752 : if (inner_for_stmt == NULL_TREE)
16976 : : {
16977 : 36 : gcc_assert (seen_error ());
16978 : 36 : *expr_p = NULL_TREE;
16979 : 3748 : return GS_ERROR;
16980 : : }
16981 : 17716 : gcc_assert (inner_for_stmt == *data[3]);
16982 : 17716 : omp_maybe_apply_loop_xforms (data[3],
16983 : 17716 : data[2]
16984 : 4279 : ? OMP_FOR_CLAUSES (*data[2])
16985 : 13437 : : TREE_CODE (for_stmt) == OMP_FOR
16986 : 13437 : ? OMP_FOR_CLAUSES (for_stmt)
16987 : : : NULL_TREE);
16988 : 17716 : if (inner_for_stmt != *data[3])
16989 : 71 : continue;
16990 : 17645 : if (data[2] && OMP_FOR_PRE_BODY (*data[2]))
16991 : : {
16992 : 2 : append_to_statement_list_force (OMP_FOR_PRE_BODY (*data[2]),
16993 : : &OMP_FOR_PRE_BODY (for_stmt));
16994 : 2 : OMP_FOR_PRE_BODY (*data[2]) = NULL_TREE;
16995 : : }
16996 : 17645 : if (OMP_FOR_PRE_BODY (inner_for_stmt))
16997 : : {
16998 : 7200 : append_to_statement_list_force (OMP_FOR_PRE_BODY (inner_for_stmt),
16999 : : &OMP_FOR_PRE_BODY (for_stmt));
17000 : 7200 : OMP_FOR_PRE_BODY (inner_for_stmt) = NULL_TREE;
17001 : : }
17002 : :
17003 : 17645 : if (data[0])
17004 : : {
17005 : : /* We have some statements or variable declarations in between
17006 : : the composite construct directives. Move them around the
17007 : : inner_for_stmt. */
17008 : 3712 : data[0] = expr_p;
17009 : 14848 : for (i = 0; i < 3; i++)
17010 : 11136 : if (data[i])
17011 : : {
17012 : 7042 : tree t = *data[i];
17013 : 7042 : if (i < 2 && data[i + 1] == &OMP_BODY (t))
17014 : 1002 : data[i + 1] = data[i];
17015 : 7042 : *data[i] = OMP_BODY (t);
17016 : 7042 : tree body = build3 (BIND_EXPR, void_type_node, NULL_TREE,
17017 : : NULL_TREE, make_node (BLOCK));
17018 : 7042 : OMP_BODY (t) = body;
17019 : 7042 : append_to_statement_list_force (inner_for_stmt,
17020 : : &BIND_EXPR_BODY (body));
17021 : 7042 : *data[3] = t;
17022 : 7042 : data[3] = tsi_stmt_ptr (tsi_start (BIND_EXPR_BODY (body)));
17023 : 7042 : gcc_assert (*data[3] == inner_for_stmt);
17024 : : }
17025 : : return GS_OK;
17026 : : }
17027 : :
17028 : 36745 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17029 : 22812 : if (!loop_p
17030 : 21931 : && OMP_FOR_ORIG_DECLS (inner_for_stmt)
17031 : 11102 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17032 : : i)) == TREE_LIST
17033 : 22880 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17034 : : i)))
17035 : : {
17036 : 40 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17037 : : /* Class iterators aren't allowed on OMP_SIMD, so the only
17038 : : case we need to solve is distribute parallel for. They are
17039 : : allowed on the loop construct, but that is already handled
17040 : : in gimplify_omp_loop. */
17041 : 40 : gcc_assert (TREE_CODE (inner_for_stmt) == OMP_FOR
17042 : : && TREE_CODE (for_stmt) == OMP_DISTRIBUTE
17043 : : && data[1]);
17044 : 40 : tree orig_decl = TREE_PURPOSE (orig);
17045 : 40 : tree last = TREE_VALUE (orig);
17046 : 40 : tree *pc;
17047 : 40 : for (pc = &OMP_FOR_CLAUSES (inner_for_stmt);
17048 : 74 : *pc; pc = &OMP_CLAUSE_CHAIN (*pc))
17049 : 42 : if ((OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE
17050 : 35 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LASTPRIVATE)
17051 : 43 : && OMP_CLAUSE_DECL (*pc) == orig_decl)
17052 : : break;
17053 : 40 : if (*pc == NULL_TREE)
17054 : : {
17055 : 32 : tree *spc;
17056 : 32 : for (spc = &OMP_PARALLEL_CLAUSES (*data[1]);
17057 : 98 : *spc; spc = &OMP_CLAUSE_CHAIN (*spc))
17058 : 67 : if (OMP_CLAUSE_CODE (*spc) == OMP_CLAUSE_PRIVATE
17059 : 67 : && OMP_CLAUSE_DECL (*spc) == orig_decl)
17060 : : break;
17061 : 32 : if (*spc)
17062 : : {
17063 : 1 : tree c = *spc;
17064 : 1 : *spc = OMP_CLAUSE_CHAIN (c);
17065 : 1 : OMP_CLAUSE_CHAIN (c) = NULL_TREE;
17066 : 1 : *pc = c;
17067 : : }
17068 : : }
17069 : 40 : if (*pc == NULL_TREE)
17070 : : ;
17071 : 9 : else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_PRIVATE)
17072 : : {
17073 : : /* private clause will appear only on inner_for_stmt.
17074 : : Change it into firstprivate, and add private clause
17075 : : on for_stmt. */
17076 : 8 : tree c = copy_node (*pc);
17077 : 8 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17078 : 8 : OMP_FOR_CLAUSES (for_stmt) = c;
17079 : 8 : OMP_CLAUSE_CODE (*pc) = OMP_CLAUSE_FIRSTPRIVATE;
17080 : 8 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17081 : : }
17082 : : else
17083 : : {
17084 : : /* lastprivate clause will appear on both inner_for_stmt
17085 : : and for_stmt. Add firstprivate clause to
17086 : : inner_for_stmt. */
17087 : 1 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (*pc),
17088 : : OMP_CLAUSE_FIRSTPRIVATE);
17089 : 1 : OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (*pc);
17090 : 1 : OMP_CLAUSE_CHAIN (c) = *pc;
17091 : 1 : *pc = c;
17092 : 1 : lang_hooks.decls.omp_finish_clause (*pc, pre_p, openacc);
17093 : : }
17094 : 40 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17095 : : OMP_CLAUSE_FIRSTPRIVATE);
17096 : 40 : OMP_CLAUSE_DECL (c) = last;
17097 : 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17098 : 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17099 : 40 : c = build_omp_clause (UNKNOWN_LOCATION,
17100 : 40 : *pc ? OMP_CLAUSE_SHARED
17101 : : : OMP_CLAUSE_FIRSTPRIVATE);
17102 : 40 : OMP_CLAUSE_DECL (c) = orig_decl;
17103 : 40 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17104 : 40 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17105 : : }
17106 : : /* Similarly, take care of C++ range for temporaries, those should
17107 : : be firstprivate on OMP_PARALLEL if any. */
17108 : 13933 : if (data[1])
17109 : 17514 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner_for_stmt)); i++)
17110 : 11112 : if (OMP_FOR_ORIG_DECLS (inner_for_stmt)
17111 : 5737 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17112 : : i)) == TREE_LIST
17113 : 11188 : && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt),
17114 : : i)))
17115 : : {
17116 : 49 : tree orig
17117 : 49 : = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner_for_stmt), i);
17118 : 49 : tree v = TREE_CHAIN (orig);
17119 : 49 : tree c = build_omp_clause (UNKNOWN_LOCATION,
17120 : : OMP_CLAUSE_FIRSTPRIVATE);
17121 : : /* First add firstprivate clause for the __for_end artificial
17122 : : decl. */
17123 : 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 1);
17124 : 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17125 : : == REFERENCE_TYPE)
17126 : 0 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17127 : 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17128 : 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17129 : 49 : if (TREE_VEC_ELT (v, 0))
17130 : : {
17131 : : /* And now the same for __for_range artificial decl if it
17132 : : exists. */
17133 : 49 : c = build_omp_clause (UNKNOWN_LOCATION,
17134 : : OMP_CLAUSE_FIRSTPRIVATE);
17135 : 49 : OMP_CLAUSE_DECL (c) = TREE_VEC_ELT (v, 0);
17136 : 49 : if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
17137 : : == REFERENCE_TYPE)
17138 : 49 : OMP_CLAUSE_FIRSTPRIVATE_NO_REFERENCE (c) = 1;
17139 : 49 : OMP_CLAUSE_CHAIN (c) = OMP_PARALLEL_CLAUSES (*data[1]);
17140 : 49 : OMP_PARALLEL_CLAUSES (*data[1]) = c;
17141 : : }
17142 : : }
17143 : 13933 : break;
17144 : : }
17145 : 54313 : if (OMP_FOR_INIT (for_stmt) != NULL_TREE)
17146 : : {
17147 : 40380 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
17148 : 40380 : if (*expr_p != for_stmt)
17149 : : return GS_OK;
17150 : : }
17151 : :
17152 : 53431 : switch (TREE_CODE (for_stmt))
17153 : : {
17154 : 18161 : case OMP_FOR:
17155 : 30353 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17156 : : {
17157 : 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17158 : : OMP_CLAUSE_SCHEDULE))
17159 : 47 : error_at (EXPR_LOCATION (for_stmt),
17160 : : "%qs clause may not appear on non-rectangular %qs",
17161 : 27 : "schedule", lang_GNU_Fortran () ? "do" : "for");
17162 : 458 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED))
17163 : 34 : error_at (EXPR_LOCATION (for_stmt),
17164 : : "%qs clause may not appear on non-rectangular %qs",
17165 : 18 : "ordered", lang_GNU_Fortran () ? "do" : "for");
17166 : : }
17167 : : break;
17168 : 8226 : case OMP_DISTRIBUTE:
17169 : 9137 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt)
17170 : 8226 : && omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17171 : : OMP_CLAUSE_DIST_SCHEDULE))
17172 : 29 : error_at (EXPR_LOCATION (for_stmt),
17173 : : "%qs clause may not appear on non-rectangular %qs",
17174 : : "dist_schedule", "distribute");
17175 : : break;
17176 : : case OACC_LOOP:
17177 : : ort = ORT_ACC;
17178 : : break;
17179 : 1582 : case OMP_TASKLOOP:
17180 : 2515 : if (OMP_FOR_NON_RECTANGULAR (inner_for_stmt ? inner_for_stmt : for_stmt))
17181 : : {
17182 : 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17183 : : OMP_CLAUSE_GRAINSIZE))
17184 : 11 : error_at (EXPR_LOCATION (for_stmt),
17185 : : "%qs clause may not appear on non-rectangular %qs",
17186 : : "grainsize", "taskloop");
17187 : 36 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17188 : : OMP_CLAUSE_NUM_TASKS))
17189 : 6 : error_at (EXPR_LOCATION (for_stmt),
17190 : : "%qs clause may not appear on non-rectangular %qs",
17191 : : "num_tasks", "taskloop");
17192 : : }
17193 : 1582 : if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED))
17194 : : ort = ORT_UNTIED_TASKLOOP;
17195 : : else
17196 : : ort = ORT_TASKLOOP;
17197 : : break;
17198 : 10648 : case OMP_SIMD:
17199 : 10648 : ort = ORT_SIMD;
17200 : 10648 : break;
17201 : 2264 : case OMP_TILE:
17202 : 2264 : case OMP_UNROLL:
17203 : 2264 : gcc_assert (inner_for_stmt == NULL_TREE);
17204 : 2264 : return gimplify_omp_loop_xform (expr_p, pre_p);
17205 : 0 : default:
17206 : 0 : gcc_unreachable ();
17207 : : }
17208 : :
17209 : : /* Set OMP_CLAUSE_LINEAR_NO_COPYIN flag on explicit linear
17210 : : clause for the IV. */
17211 : 10695 : if (ort == ORT_SIMD && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17212 : : {
17213 : 7820 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), 0);
17214 : 7820 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17215 : 7820 : decl = TREE_OPERAND (t, 0);
17216 : 18630 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
17217 : 11924 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17218 : 11924 : && OMP_CLAUSE_DECL (c) == decl)
17219 : : {
17220 : 1114 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17221 : 1114 : break;
17222 : : }
17223 : : }
17224 : :
17225 : 51167 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP)
17226 : 51495 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, ort,
17227 : 1910 : loop_p && TREE_CODE (for_stmt) != OMP_SIMD
17228 : : ? OMP_LOOP : TREE_CODE (for_stmt));
17229 : :
17230 : 51167 : if (TREE_CODE (for_stmt) == OMP_DISTRIBUTE)
17231 : 8226 : gimplify_omp_ctxp->distribute = true;
17232 : :
17233 : : /* Handle OMP_FOR_INIT. */
17234 : 51167 : for_pre_body = NULL;
17235 : 51167 : if ((ort == ORT_SIMD
17236 : 40519 : || (inner_for_stmt && TREE_CODE (inner_for_stmt) == OMP_SIMD))
17237 : 61907 : && OMP_FOR_PRE_BODY (for_stmt))
17238 : : {
17239 : 6781 : has_decl_expr = BITMAP_ALLOC (NULL);
17240 : 6781 : if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == DECL_EXPR
17241 : 6781 : && VAR_P (DECL_EXPR_DECL (OMP_FOR_PRE_BODY (for_stmt))))
17242 : : {
17243 : 18 : t = OMP_FOR_PRE_BODY (for_stmt);
17244 : 18 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17245 : : }
17246 : 6763 : else if (TREE_CODE (OMP_FOR_PRE_BODY (for_stmt)) == STATEMENT_LIST)
17247 : : {
17248 : 6761 : tree_stmt_iterator si;
17249 : 11228 : for (si = tsi_start (OMP_FOR_PRE_BODY (for_stmt)); !tsi_end_p (si);
17250 : 4467 : tsi_next (&si))
17251 : : {
17252 : 4467 : t = tsi_stmt (si);
17253 : 4467 : if (TREE_CODE (t) == DECL_EXPR
17254 : 4467 : && VAR_P (DECL_EXPR_DECL (t)))
17255 : 4394 : bitmap_set_bit (has_decl_expr, DECL_UID (DECL_EXPR_DECL (t)));
17256 : : }
17257 : : }
17258 : : }
17259 : 51167 : if (OMP_FOR_PRE_BODY (for_stmt))
17260 : : {
17261 : 20957 : if (TREE_CODE (for_stmt) != OMP_TASKLOOP || gimplify_omp_ctxp)
17262 : 20236 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17263 : : else
17264 : : {
17265 : 721 : struct gimplify_omp_ctx ctx;
17266 : 721 : memset (&ctx, 0, sizeof (ctx));
17267 : 721 : ctx.region_type = ORT_NONE;
17268 : 721 : gimplify_omp_ctxp = &ctx;
17269 : 721 : gimplify_and_add (OMP_FOR_PRE_BODY (for_stmt), &for_pre_body);
17270 : 721 : gimplify_omp_ctxp = NULL;
17271 : : }
17272 : : }
17273 : 51167 : OMP_FOR_PRE_BODY (for_stmt) = NULL_TREE;
17274 : :
17275 : 51167 : if (OMP_FOR_INIT (for_stmt) == NULL_TREE)
17276 : 13933 : for_stmt = inner_for_stmt;
17277 : :
17278 : : /* For taskloop, need to gimplify the start, end and step before the
17279 : : taskloop, outside of the taskloop omp context. */
17280 : 51167 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17281 : : {
17282 : 3450 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17283 : : {
17284 : 1868 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17285 : 1868 : gimple_seq *for_pre_p = (gimple_seq_empty_p (for_pre_body)
17286 : 1868 : ? pre_p : &for_pre_body);
17287 : 1868 : tree type = TREE_TYPE (TREE_OPERAND (t, 0));
17288 : 1868 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17289 : : {
17290 : 34 : tree v = TREE_OPERAND (t, 1);
17291 : 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17292 : : for_pre_p, orig_for_stmt);
17293 : 34 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17294 : : for_pre_p, orig_for_stmt);
17295 : : }
17296 : : else
17297 : 1834 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17298 : : orig_for_stmt);
17299 : :
17300 : : /* Handle OMP_FOR_COND. */
17301 : 1868 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17302 : 1868 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17303 : : {
17304 : 31 : tree v = TREE_OPERAND (t, 1);
17305 : 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 1),
17306 : : for_pre_p, orig_for_stmt);
17307 : 31 : gimplify_omp_taskloop_expr (type, &TREE_VEC_ELT (v, 2),
17308 : : for_pre_p, orig_for_stmt);
17309 : : }
17310 : : else
17311 : 1837 : gimplify_omp_taskloop_expr (type, &TREE_OPERAND (t, 1), for_pre_p,
17312 : : orig_for_stmt);
17313 : :
17314 : : /* Handle OMP_FOR_INCR. */
17315 : 1868 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17316 : 1868 : if (TREE_CODE (t) == MODIFY_EXPR)
17317 : : {
17318 : 590 : decl = TREE_OPERAND (t, 0);
17319 : 590 : t = TREE_OPERAND (t, 1);
17320 : 590 : tree *tp = &TREE_OPERAND (t, 1);
17321 : 590 : if (TREE_CODE (t) == PLUS_EXPR && *tp == decl)
17322 : 22 : tp = &TREE_OPERAND (t, 0);
17323 : :
17324 : 590 : gimplify_omp_taskloop_expr (NULL_TREE, tp, for_pre_p,
17325 : : orig_for_stmt);
17326 : : }
17327 : : }
17328 : :
17329 : 1582 : gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (orig_for_stmt), pre_p, ort,
17330 : : OMP_TASKLOOP);
17331 : : }
17332 : :
17333 : 51167 : if (orig_for_stmt != for_stmt)
17334 : 13933 : gimplify_omp_ctxp->combined_loop = true;
17335 : :
17336 : 51167 : for_body = NULL;
17337 : 51167 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17338 : : == TREE_VEC_LENGTH (OMP_FOR_COND (for_stmt)));
17339 : 51167 : gcc_assert (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17340 : : == TREE_VEC_LENGTH (OMP_FOR_INCR (for_stmt)));
17341 : :
17342 : 51167 : tree c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ORDERED);
17343 : 51167 : bool is_doacross = false;
17344 : 51167 : if (c && walk_tree_without_duplicates (&OMP_FOR_BODY (for_stmt),
17345 : : find_standalone_omp_ordered, NULL))
17346 : : {
17347 : 526 : OMP_CLAUSE_ORDERED_DOACROSS (c) = 1;
17348 : 526 : is_doacross = true;
17349 : 526 : int len = TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt));
17350 : 526 : gimplify_omp_ctxp->loop_iter_var.create (len * 2);
17351 : 2190 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
17352 : 1664 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
17353 : : {
17354 : 10 : error_at (OMP_CLAUSE_LOCATION (*pc),
17355 : : "%<linear%> clause may not be specified together "
17356 : : "with %<ordered%> clause if stand-alone %<ordered%> "
17357 : : "construct is nested in it");
17358 : 10 : *pc = OMP_CLAUSE_CHAIN (*pc);
17359 : : }
17360 : : else
17361 : 1654 : pc = &OMP_CLAUSE_CHAIN (*pc);
17362 : : }
17363 : 51167 : int collapse = 1, tile = 0;
17364 : 51167 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_COLLAPSE);
17365 : 51167 : if (c)
17366 : 13712 : collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c));
17367 : 51167 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_TILE);
17368 : 51167 : if (c)
17369 : 384 : tile = list_length (OMP_CLAUSE_TILE_LIST (c));
17370 : 51167 : c = omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_ALLOCATE);
17371 : 51167 : hash_set<tree> *allocate_uids = NULL;
17372 : 51167 : if (c)
17373 : : {
17374 : 275 : allocate_uids = new hash_set<tree>;
17375 : 1682 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17376 : 1132 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE)
17377 : 478 : allocate_uids->add (OMP_CLAUSE_DECL (c));
17378 : : }
17379 : 124065 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17380 : : {
17381 : 72898 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17382 : 72898 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17383 : 72898 : decl = TREE_OPERAND (t, 0);
17384 : 72898 : gcc_assert (DECL_P (decl));
17385 : 72898 : gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (decl))
17386 : : || POINTER_TYPE_P (TREE_TYPE (decl)));
17387 : 72898 : if (is_doacross)
17388 : : {
17389 : 1649 : if (TREE_CODE (for_stmt) == OMP_FOR && OMP_FOR_ORIG_DECLS (for_stmt))
17390 : : {
17391 : 956 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17392 : 956 : if (TREE_CODE (orig_decl) == TREE_LIST)
17393 : : {
17394 : 15 : orig_decl = TREE_PURPOSE (orig_decl);
17395 : 15 : if (!orig_decl)
17396 : 0 : orig_decl = decl;
17397 : : }
17398 : 956 : gimplify_omp_ctxp->loop_iter_var.quick_push (orig_decl);
17399 : : }
17400 : : else
17401 : 693 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17402 : 1649 : gimplify_omp_ctxp->loop_iter_var.quick_push (decl);
17403 : : }
17404 : :
17405 : 72898 : if (for_stmt == orig_for_stmt)
17406 : : {
17407 : 50086 : tree orig_decl = decl;
17408 : 50086 : if (OMP_FOR_ORIG_DECLS (for_stmt))
17409 : : {
17410 : 23895 : tree orig_decl = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17411 : 23895 : if (TREE_CODE (orig_decl) == TREE_LIST)
17412 : : {
17413 : : orig_decl = TREE_PURPOSE (orig_decl);
17414 : : if (!orig_decl)
17415 : : orig_decl = decl;
17416 : : }
17417 : : }
17418 : 50086 : if (is_global_var (orig_decl) && DECL_THREAD_LOCAL_P (orig_decl))
17419 : 36 : error_at (EXPR_LOCATION (for_stmt),
17420 : : "threadprivate iteration variable %qD", orig_decl);
17421 : : }
17422 : :
17423 : : /* Make sure the iteration variable is private. */
17424 : 72898 : tree c = NULL_TREE;
17425 : 72898 : tree c2 = NULL_TREE;
17426 : 72898 : if (orig_for_stmt != for_stmt)
17427 : : {
17428 : : /* Preserve this information until we gimplify the inner simd. */
17429 : 22812 : if (has_decl_expr
17430 : 22812 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17431 : 3413 : TREE_PRIVATE (t) = 1;
17432 : : }
17433 : 50086 : else if (ort == ORT_SIMD)
17434 : : {
17435 : 15721 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17436 : : (splay_tree_key) decl);
17437 : 15721 : omp_is_private (gimplify_omp_ctxp, decl,
17438 : 15721 : 1 + (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt))
17439 : : != 1));
17440 : 15721 : if (n != NULL && (n->value & GOVD_DATA_SHARE_CLASS) != 0)
17441 : : {
17442 : 2518 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17443 : 2518 : if (n->value & GOVD_LASTPRIVATE_CONDITIONAL)
17444 : 0 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17445 : : OMP_CLAUSE_LASTPRIVATE);
17446 : 0 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17447 : : OMP_CLAUSE_LASTPRIVATE))
17448 : 0 : if (OMP_CLAUSE_DECL (c3) == decl)
17449 : : {
17450 : 0 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17451 : : "conditional %<lastprivate%> on loop "
17452 : : "iterator %qD ignored", decl);
17453 : 0 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17454 : 0 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17455 : : }
17456 : : }
17457 : 13203 : else if (TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1 && !loop_p)
17458 : : {
17459 : 5632 : c = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17460 : 5632 : OMP_CLAUSE_LINEAR_NO_COPYIN (c) = 1;
17461 : 5632 : unsigned int flags = GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN;
17462 : 5632 : if ((has_decl_expr
17463 : 1306 : && bitmap_bit_p (has_decl_expr, DECL_UID (decl)))
17464 : 6316 : || TREE_PRIVATE (t))
17465 : : {
17466 : 2278 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17467 : 2278 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17468 : : }
17469 : 5632 : struct gimplify_omp_ctx *outer
17470 : 5632 : = gimplify_omp_ctxp->outer_context;
17471 : 5632 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17472 : : {
17473 : 2433 : if (outer->region_type == ORT_WORKSHARE
17474 : 2193 : && outer->combined_loop)
17475 : : {
17476 : 2142 : n = splay_tree_lookup (outer->variables,
17477 : : (splay_tree_key)decl);
17478 : 2142 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17479 : : {
17480 : 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17481 : 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17482 : : }
17483 : : else
17484 : : {
17485 : 2142 : struct gimplify_omp_ctx *octx = outer->outer_context;
17486 : 2142 : if (octx
17487 : 1714 : && octx->region_type == ORT_COMBINED_PARALLEL
17488 : 1476 : && octx->outer_context
17489 : 1209 : && (octx->outer_context->region_type
17490 : : == ORT_WORKSHARE)
17491 : 1079 : && octx->outer_context->combined_loop)
17492 : : {
17493 : 1079 : octx = octx->outer_context;
17494 : 1079 : n = splay_tree_lookup (octx->variables,
17495 : : (splay_tree_key)decl);
17496 : 1079 : if (n != NULL && (n->value & GOVD_LOCAL) != 0)
17497 : : {
17498 : 0 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c) = 1;
17499 : 0 : flags |= GOVD_LINEAR_LASTPRIVATE_NO_OUTER;
17500 : : }
17501 : : }
17502 : : }
17503 : : }
17504 : : }
17505 : :
17506 : 5632 : OMP_CLAUSE_DECL (c) = decl;
17507 : 5632 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17508 : 5632 : OMP_FOR_CLAUSES (for_stmt) = c;
17509 : 5632 : omp_add_variable (gimplify_omp_ctxp, decl, flags);
17510 : 5632 : if (outer && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
17511 : 2433 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17512 : : true);
17513 : : }
17514 : : else
17515 : : {
17516 : 7571 : bool lastprivate
17517 : : = (!has_decl_expr
17518 : 7571 : || !bitmap_bit_p (has_decl_expr, DECL_UID (decl)));
17519 : 7571 : if (TREE_PRIVATE (t))
17520 : 1787 : lastprivate = false;
17521 : 7571 : if (loop_p && OMP_FOR_ORIG_DECLS (for_stmt))
17522 : : {
17523 : 509 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
17524 : 509 : if (TREE_CODE (elt) == TREE_LIST && TREE_PURPOSE (elt))
17525 : : lastprivate = false;
17526 : : }
17527 : :
17528 : 7571 : struct gimplify_omp_ctx *outer
17529 : 7571 : = gimplify_omp_ctxp->outer_context;
17530 : 7571 : if (outer && lastprivate)
17531 : 4887 : omp_lastprivate_for_combined_outer_constructs (outer, decl,
17532 : : true);
17533 : :
17534 : 9577 : c = build_omp_clause (input_location,
17535 : : lastprivate ? OMP_CLAUSE_LASTPRIVATE
17536 : : : OMP_CLAUSE_PRIVATE);
17537 : 7571 : OMP_CLAUSE_DECL (c) = decl;
17538 : 7571 : OMP_CLAUSE_CHAIN (c) = OMP_FOR_CLAUSES (for_stmt);
17539 : 7571 : OMP_FOR_CLAUSES (for_stmt) = c;
17540 : 7571 : omp_add_variable (gimplify_omp_ctxp, decl,
17541 : : (lastprivate ? GOVD_LASTPRIVATE : GOVD_PRIVATE)
17542 : : | GOVD_EXPLICIT | GOVD_SEEN);
17543 : 7571 : c = NULL_TREE;
17544 : : }
17545 : : }
17546 : 34365 : else if (omp_is_private (gimplify_omp_ctxp, decl, 0))
17547 : : {
17548 : 8720 : omp_notice_variable (gimplify_omp_ctxp, decl, true);
17549 : 8720 : splay_tree_node n = splay_tree_lookup (gimplify_omp_ctxp->variables,
17550 : : (splay_tree_key) decl);
17551 : 8720 : if (n && (n->value & GOVD_LASTPRIVATE_CONDITIONAL))
17552 : 80 : for (tree c3 = omp_find_clause (OMP_FOR_CLAUSES (for_stmt),
17553 : : OMP_CLAUSE_LASTPRIVATE);
17554 : 80 : c3; c3 = omp_find_clause (OMP_CLAUSE_CHAIN (c3),
17555 : : OMP_CLAUSE_LASTPRIVATE))
17556 : 40 : if (OMP_CLAUSE_DECL (c3) == decl)
17557 : : {
17558 : 40 : warning_at (OMP_CLAUSE_LOCATION (c3), OPT_Wopenmp,
17559 : : "conditional %<lastprivate%> on loop "
17560 : : "iterator %qD ignored", decl);
17561 : 40 : OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c3) = 0;
17562 : 40 : n->value &= ~GOVD_LASTPRIVATE_CONDITIONAL;
17563 : : }
17564 : : }
17565 : : else
17566 : 25645 : omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
17567 : :
17568 : : /* If DECL is not a gimple register, create a temporary variable to act
17569 : : as an iteration counter. This is valid, since DECL cannot be
17570 : : modified in the body of the loop. Similarly for any iteration vars
17571 : : in simd with collapse > 1 where the iterator vars must be
17572 : : lastprivate. And similarly for vars mentioned in allocate clauses. */
17573 : 72898 : if (orig_for_stmt != for_stmt)
17574 : 22812 : var = decl;
17575 : 50086 : else if (!is_gimple_reg (decl)
17576 : 46818 : || (ort == ORT_SIMD
17577 : 14122 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) > 1)
17578 : 89834 : || (allocate_uids && allocate_uids->contains (decl)))
17579 : : {
17580 : 10370 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17581 : : /* Make sure omp_add_variable is not called on it prematurely.
17582 : : We call it ourselves a few lines later. */
17583 : 10370 : gimplify_omp_ctxp = NULL;
17584 : 10370 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17585 : 10370 : gimplify_omp_ctxp = ctx;
17586 : 10370 : TREE_OPERAND (t, 0) = var;
17587 : :
17588 : 10370 : gimplify_seq_add_stmt (&for_body, gimple_build_assign (decl, var));
17589 : :
17590 : 10370 : if (ort == ORT_SIMD
17591 : 10370 : && TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)) == 1)
17592 : : {
17593 : 768 : c2 = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
17594 : 768 : OMP_CLAUSE_LINEAR_NO_COPYIN (c2) = 1;
17595 : 768 : OMP_CLAUSE_LINEAR_NO_COPYOUT (c2) = 1;
17596 : 768 : OMP_CLAUSE_DECL (c2) = var;
17597 : 768 : OMP_CLAUSE_CHAIN (c2) = OMP_FOR_CLAUSES (for_stmt);
17598 : 768 : OMP_FOR_CLAUSES (for_stmt) = c2;
17599 : 768 : omp_add_variable (gimplify_omp_ctxp, var,
17600 : : GOVD_LINEAR | GOVD_EXPLICIT | GOVD_SEEN);
17601 : 768 : if (c == NULL_TREE)
17602 : : {
17603 : 518 : c = c2;
17604 : 518 : c2 = NULL_TREE;
17605 : : }
17606 : : }
17607 : : else
17608 : 9602 : omp_add_variable (gimplify_omp_ctxp, var,
17609 : : GOVD_PRIVATE | GOVD_SEEN);
17610 : : }
17611 : : else
17612 : : var = decl;
17613 : :
17614 : 72898 : gimplify_omp_ctxp->in_for_exprs = true;
17615 : 72898 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17616 : : {
17617 : 719 : tree lb = TREE_OPERAND (t, 1);
17618 : 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 1), &for_pre_body, NULL,
17619 : : is_gimple_val, fb_rvalue, false);
17620 : 719 : ret = MIN (ret, tret);
17621 : 719 : tret = gimplify_expr (&TREE_VEC_ELT (lb, 2), &for_pre_body, NULL,
17622 : : is_gimple_val, fb_rvalue, false);
17623 : : }
17624 : : else
17625 : 72179 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17626 : : is_gimple_val, fb_rvalue, false);
17627 : 72898 : gimplify_omp_ctxp->in_for_exprs = false;
17628 : 72898 : ret = MIN (ret, tret);
17629 : 72898 : if (ret == GS_ERROR)
17630 : : return ret;
17631 : :
17632 : : /* Handle OMP_FOR_COND. */
17633 : 72898 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17634 : 72898 : gcc_assert (COMPARISON_CLASS_P (t));
17635 : 72898 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17636 : :
17637 : 72898 : gimplify_omp_ctxp->in_for_exprs = true;
17638 : 72898 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC)
17639 : : {
17640 : 599 : tree ub = TREE_OPERAND (t, 1);
17641 : 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 1), &for_pre_body, NULL,
17642 : : is_gimple_val, fb_rvalue, false);
17643 : 599 : ret = MIN (ret, tret);
17644 : 599 : tret = gimplify_expr (&TREE_VEC_ELT (ub, 2), &for_pre_body, NULL,
17645 : : is_gimple_val, fb_rvalue, false);
17646 : : }
17647 : : else
17648 : 72299 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17649 : : is_gimple_val, fb_rvalue, false);
17650 : 72898 : gimplify_omp_ctxp->in_for_exprs = false;
17651 : 72898 : ret = MIN (ret, tret);
17652 : :
17653 : : /* Handle OMP_FOR_INCR. */
17654 : 72898 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17655 : 72898 : switch (TREE_CODE (t))
17656 : : {
17657 : 35661 : case PREINCREMENT_EXPR:
17658 : 35661 : case POSTINCREMENT_EXPR:
17659 : 35661 : {
17660 : 35661 : tree decl = TREE_OPERAND (t, 0);
17661 : : /* c_omp_for_incr_canonicalize_ptr() should have been
17662 : : called to massage things appropriately. */
17663 : 35661 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17664 : :
17665 : 35661 : if (orig_for_stmt != for_stmt)
17666 : : break;
17667 : 25272 : t = build_int_cst (TREE_TYPE (decl), 1);
17668 : 25272 : if (c)
17669 : 4467 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17670 : 25272 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17671 : 25272 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17672 : 25272 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17673 : 25272 : break;
17674 : : }
17675 : :
17676 : 3826 : case PREDECREMENT_EXPR:
17677 : 3826 : case POSTDECREMENT_EXPR:
17678 : : /* c_omp_for_incr_canonicalize_ptr() should have been
17679 : : called to massage things appropriately. */
17680 : 3826 : gcc_assert (!POINTER_TYPE_P (TREE_TYPE (decl)));
17681 : 3826 : if (orig_for_stmt != for_stmt)
17682 : : break;
17683 : 1988 : t = build_int_cst (TREE_TYPE (decl), -1);
17684 : 1988 : if (c)
17685 : 112 : OMP_CLAUSE_LINEAR_STEP (c) = t;
17686 : 1988 : t = build2 (PLUS_EXPR, TREE_TYPE (decl), var, t);
17687 : 1988 : t = build2 (MODIFY_EXPR, TREE_TYPE (var), var, t);
17688 : 1988 : TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i) = t;
17689 : 1988 : break;
17690 : :
17691 : 33411 : case MODIFY_EXPR:
17692 : 33411 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17693 : 33411 : TREE_OPERAND (t, 0) = var;
17694 : :
17695 : 33411 : t = TREE_OPERAND (t, 1);
17696 : 33411 : switch (TREE_CODE (t))
17697 : : {
17698 : 26486 : case PLUS_EXPR:
17699 : 26486 : if (TREE_OPERAND (t, 1) == decl)
17700 : : {
17701 : 215 : TREE_OPERAND (t, 1) = TREE_OPERAND (t, 0);
17702 : 215 : TREE_OPERAND (t, 0) = var;
17703 : 215 : break;
17704 : : }
17705 : :
17706 : : /* Fallthru. */
17707 : 33196 : case MINUS_EXPR:
17708 : 33196 : case POINTER_PLUS_EXPR:
17709 : 33196 : gcc_assert (TREE_OPERAND (t, 0) == decl);
17710 : 33196 : TREE_OPERAND (t, 0) = var;
17711 : 33196 : break;
17712 : 0 : default:
17713 : 0 : gcc_unreachable ();
17714 : : }
17715 : :
17716 : 33411 : gimplify_omp_ctxp->in_for_exprs = true;
17717 : 33411 : tret = gimplify_expr (&TREE_OPERAND (t, 1), &for_pre_body, NULL,
17718 : : is_gimple_val, fb_rvalue, false);
17719 : 33411 : ret = MIN (ret, tret);
17720 : 33411 : if (c)
17721 : : {
17722 : 1571 : tree step = TREE_OPERAND (t, 1);
17723 : 1571 : tree stept = TREE_TYPE (decl);
17724 : 1571 : if (POINTER_TYPE_P (stept))
17725 : 280 : stept = sizetype;
17726 : 1571 : step = fold_convert (stept, step);
17727 : 1571 : if (TREE_CODE (t) == MINUS_EXPR)
17728 : 295 : step = fold_build1 (NEGATE_EXPR, stept, step);
17729 : 1571 : OMP_CLAUSE_LINEAR_STEP (c) = step;
17730 : 1571 : if (step != TREE_OPERAND (t, 1))
17731 : : {
17732 : 295 : tret = gimplify_expr (&OMP_CLAUSE_LINEAR_STEP (c),
17733 : : &for_pre_body, NULL,
17734 : : is_gimple_val, fb_rvalue, false);
17735 : 295 : ret = MIN (ret, tret);
17736 : : }
17737 : : }
17738 : 33411 : gimplify_omp_ctxp->in_for_exprs = false;
17739 : 33411 : break;
17740 : :
17741 : 0 : default:
17742 : 0 : gcc_unreachable ();
17743 : : }
17744 : :
17745 : 72898 : if (c2)
17746 : : {
17747 : 250 : gcc_assert (c);
17748 : 250 : OMP_CLAUSE_LINEAR_STEP (c2) = OMP_CLAUSE_LINEAR_STEP (c);
17749 : : }
17750 : :
17751 : 72898 : if ((var != decl || collapse > 1 || tile) && orig_for_stmt == for_stmt)
17752 : : {
17753 : 86626 : for (c = OMP_FOR_CLAUSES (for_stmt); c ; c = OMP_CLAUSE_CHAIN (c))
17754 : 65083 : if (((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
17755 : 16218 : && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) == NULL)
17756 : 56074 : || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
17757 : 2155 : && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)
17758 : 1371 : && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) == NULL))
17759 : 75441 : && OMP_CLAUSE_DECL (c) == decl)
17760 : : {
17761 : 7533 : if (is_doacross && (collapse == 1 || i >= collapse))
17762 : : t = var;
17763 : : else
17764 : : {
17765 : 7460 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17766 : 7460 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17767 : 7460 : gcc_assert (TREE_OPERAND (t, 0) == var);
17768 : 7460 : t = TREE_OPERAND (t, 1);
17769 : 7460 : gcc_assert (TREE_CODE (t) == PLUS_EXPR
17770 : : || TREE_CODE (t) == MINUS_EXPR
17771 : : || TREE_CODE (t) == POINTER_PLUS_EXPR);
17772 : 7460 : gcc_assert (TREE_OPERAND (t, 0) == var);
17773 : 14818 : t = build2 (TREE_CODE (t), TREE_TYPE (decl),
17774 : : is_doacross ? var : decl,
17775 : 7460 : TREE_OPERAND (t, 1));
17776 : : }
17777 : 7533 : gimple_seq *seq;
17778 : 7533 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
17779 : 6939 : seq = &OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c);
17780 : : else
17781 : 594 : seq = &OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c);
17782 : 7533 : push_gimplify_context ();
17783 : 7533 : gimplify_assign (decl, t, seq);
17784 : 7533 : gimple *bind = NULL;
17785 : 7533 : if (gimplify_ctxp->temps)
17786 : : {
17787 : 2070 : bind = gimple_build_bind (NULL_TREE, *seq, NULL_TREE);
17788 : 2070 : *seq = NULL;
17789 : 2070 : gimplify_seq_add_stmt (seq, bind);
17790 : : }
17791 : 7533 : pop_gimplify_context (bind);
17792 : : }
17793 : : }
17794 : 72898 : if (OMP_FOR_NON_RECTANGULAR (for_stmt) && var != decl)
17795 : 2609 : for (int j = i + 1; j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17796 : : {
17797 : 1197 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17798 : 1197 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17799 : 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17800 : 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17801 : 336 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17802 : 1197 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17803 : 1197 : gcc_assert (COMPARISON_CLASS_P (t));
17804 : 1197 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17805 : 1197 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17806 : 343 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17807 : : }
17808 : : }
17809 : :
17810 : 51167 : BITMAP_FREE (has_decl_expr);
17811 : 51442 : delete allocate_uids;
17812 : :
17813 : 51167 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17814 : 49585 : || (loop_p && orig_for_stmt == for_stmt))
17815 : : {
17816 : 2638 : push_gimplify_context ();
17817 : 2638 : if (TREE_CODE (OMP_FOR_BODY (orig_for_stmt)) != BIND_EXPR)
17818 : : {
17819 : 1887 : OMP_FOR_BODY (orig_for_stmt)
17820 : 1887 : = build3 (BIND_EXPR, void_type_node, NULL,
17821 : 1887 : OMP_FOR_BODY (orig_for_stmt), NULL);
17822 : 1887 : TREE_SIDE_EFFECTS (OMP_FOR_BODY (orig_for_stmt)) = 1;
17823 : : }
17824 : : }
17825 : :
17826 : 51167 : gimple *g = gimplify_and_return_first (OMP_FOR_BODY (orig_for_stmt),
17827 : : &for_body);
17828 : :
17829 : 51167 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP
17830 : 49585 : || (loop_p && orig_for_stmt == for_stmt))
17831 : : {
17832 : 2638 : if (gimple_code (g) == GIMPLE_BIND)
17833 : 2638 : pop_gimplify_context (g);
17834 : : else
17835 : 0 : pop_gimplify_context (NULL);
17836 : : }
17837 : :
17838 : 51167 : if (orig_for_stmt != for_stmt)
17839 : 36745 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17840 : : {
17841 : 22812 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17842 : 22812 : decl = TREE_OPERAND (t, 0);
17843 : 22812 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
17844 : 22812 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17845 : 772 : gimplify_omp_ctxp = ctx->outer_context;
17846 : 22812 : var = create_tmp_var (TREE_TYPE (decl), get_name (decl));
17847 : 22812 : gimplify_omp_ctxp = ctx;
17848 : 22812 : omp_add_variable (gimplify_omp_ctxp, var, GOVD_PRIVATE | GOVD_SEEN);
17849 : 22812 : TREE_OPERAND (t, 0) = var;
17850 : 22812 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17851 : 22812 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17852 : 22812 : TREE_OPERAND (TREE_OPERAND (t, 1), 0) = var;
17853 : 22812 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
17854 : 791 : for (int j = i + 1;
17855 : 791 : j < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); j++)
17856 : : {
17857 : 377 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), j);
17858 : 377 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
17859 : 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17860 : 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17861 : : {
17862 : 133 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17863 : 133 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17864 : : }
17865 : 377 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), j);
17866 : 377 : gcc_assert (COMPARISON_CLASS_P (t));
17867 : 377 : if (TREE_CODE (TREE_OPERAND (t, 1)) == TREE_VEC
17868 : 377 : && TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) == decl)
17869 : : {
17870 : 67 : TREE_OPERAND (t, 1) = copy_node (TREE_OPERAND (t, 1));
17871 : 67 : TREE_VEC_ELT (TREE_OPERAND (t, 1), 0) = var;
17872 : : }
17873 : : }
17874 : : }
17875 : :
17876 : 51167 : gimplify_adjust_omp_clauses (pre_p, for_body,
17877 : : &OMP_FOR_CLAUSES (orig_for_stmt),
17878 : 51167 : TREE_CODE (orig_for_stmt));
17879 : :
17880 : 51167 : int kind;
17881 : 51167 : switch (TREE_CODE (orig_for_stmt))
17882 : : {
17883 : : case OMP_FOR: kind = GF_OMP_FOR_KIND_FOR; break;
17884 : 10648 : case OMP_SIMD: kind = GF_OMP_FOR_KIND_SIMD; break;
17885 : 8226 : case OMP_DISTRIBUTE: kind = GF_OMP_FOR_KIND_DISTRIBUTE; break;
17886 : 1582 : case OMP_TASKLOOP: kind = GF_OMP_FOR_KIND_TASKLOOP; break;
17887 : 12550 : case OACC_LOOP: kind = GF_OMP_FOR_KIND_OACC_LOOP; break;
17888 : 0 : default:
17889 : 0 : gcc_unreachable ();
17890 : : }
17891 : 51167 : if (loop_p && kind == GF_OMP_FOR_KIND_SIMD)
17892 : : {
17893 : 1056 : gimplify_seq_add_seq (pre_p, for_pre_body);
17894 : 1056 : for_pre_body = NULL;
17895 : : }
17896 : 51167 : gfor = gimple_build_omp_for (for_body, kind, OMP_FOR_CLAUSES (orig_for_stmt),
17897 : 51167 : TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)),
17898 : : for_pre_body);
17899 : 51167 : if (orig_for_stmt != for_stmt)
17900 : 13933 : gimple_omp_for_set_combined_p (gfor, true);
17901 : 51167 : if (gimplify_omp_ctxp
17902 : 42560 : && (gimplify_omp_ctxp->combined_loop
17903 : 35029 : || (gimplify_omp_ctxp->region_type == ORT_COMBINED_PARALLEL
17904 : 12287 : && gimplify_omp_ctxp->outer_context
17905 : 7865 : && gimplify_omp_ctxp->outer_context->combined_loop)))
17906 : : {
17907 : 13933 : gimple_omp_for_set_combined_into_p (gfor, true);
17908 : 13933 : if (gimplify_omp_ctxp->combined_loop)
17909 : 7531 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_SIMD);
17910 : : else
17911 : 6402 : gcc_assert (TREE_CODE (orig_for_stmt) == OMP_FOR);
17912 : : }
17913 : :
17914 : 124065 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
17915 : : {
17916 : 72898 : t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
17917 : 72898 : gimple_omp_for_set_index (gfor, i, TREE_OPERAND (t, 0));
17918 : 72898 : gimple_omp_for_set_initial (gfor, i, TREE_OPERAND (t, 1));
17919 : 72898 : t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i);
17920 : 72898 : gimple_omp_for_set_cond (gfor, i, TREE_CODE (t));
17921 : 72898 : gimple_omp_for_set_final (gfor, i, TREE_OPERAND (t, 1));
17922 : 72898 : t = TREE_VEC_ELT (OMP_FOR_INCR (for_stmt), i);
17923 : 72898 : gimple_omp_for_set_incr (gfor, i, TREE_OPERAND (t, 1));
17924 : : }
17925 : :
17926 : : /* OMP_TASKLOOP is gimplified as two GIMPLE_OMP_FOR taskloop
17927 : : constructs with GIMPLE_OMP_TASK sandwiched in between them.
17928 : : The outer taskloop stands for computing the number of iterations,
17929 : : counts for collapsed loops and holding taskloop specific clauses.
17930 : : The task construct stands for the effect of data sharing on the
17931 : : explicit task it creates and the inner taskloop stands for expansion
17932 : : of the static loop inside of the explicit task construct. */
17933 : 51167 : if (TREE_CODE (orig_for_stmt) == OMP_TASKLOOP)
17934 : : {
17935 : 1582 : tree *gfor_clauses_ptr = gimple_omp_for_clauses_ptr (gfor);
17936 : 1582 : tree task_clauses = NULL_TREE;
17937 : 1582 : tree c = *gfor_clauses_ptr;
17938 : 1582 : tree *gtask_clauses_ptr = &task_clauses;
17939 : 1582 : tree outer_for_clauses = NULL_TREE;
17940 : 1582 : tree *gforo_clauses_ptr = &outer_for_clauses;
17941 : 1582 : bitmap lastprivate_uids = NULL;
17942 : 1582 : if (omp_find_clause (c, OMP_CLAUSE_ALLOCATE))
17943 : : {
17944 : 36 : c = omp_find_clause (c, OMP_CLAUSE_LASTPRIVATE);
17945 : 36 : if (c)
17946 : : {
17947 : 18 : lastprivate_uids = BITMAP_ALLOC (NULL);
17948 : 54 : for (; c; c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
17949 : : OMP_CLAUSE_LASTPRIVATE))
17950 : 18 : bitmap_set_bit (lastprivate_uids,
17951 : 18 : DECL_UID (OMP_CLAUSE_DECL (c)));
17952 : : }
17953 : 36 : c = *gfor_clauses_ptr;
17954 : : }
17955 : 12200 : for (; c; c = OMP_CLAUSE_CHAIN (c))
17956 : 10618 : switch (OMP_CLAUSE_CODE (c))
17957 : : {
17958 : : /* These clauses are allowed on task, move them there. */
17959 : 6196 : case OMP_CLAUSE_SHARED:
17960 : 6196 : case OMP_CLAUSE_FIRSTPRIVATE:
17961 : 6196 : case OMP_CLAUSE_DEFAULT:
17962 : 6196 : case OMP_CLAUSE_IF:
17963 : 6196 : case OMP_CLAUSE_UNTIED:
17964 : 6196 : case OMP_CLAUSE_FINAL:
17965 : 6196 : case OMP_CLAUSE_MERGEABLE:
17966 : 6196 : case OMP_CLAUSE_PRIORITY:
17967 : 6196 : case OMP_CLAUSE_REDUCTION:
17968 : 6196 : case OMP_CLAUSE_IN_REDUCTION:
17969 : 6196 : *gtask_clauses_ptr = c;
17970 : 6196 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17971 : 6196 : break;
17972 : 2064 : case OMP_CLAUSE_PRIVATE:
17973 : 2064 : if (OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c))
17974 : : {
17975 : : /* We want private on outer for and firstprivate
17976 : : on task. */
17977 : 26 : *gtask_clauses_ptr
17978 : 26 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
17979 : : OMP_CLAUSE_FIRSTPRIVATE);
17980 : 26 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
17981 : 26 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
17982 : : openacc);
17983 : 26 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
17984 : 26 : *gforo_clauses_ptr = c;
17985 : 26 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17986 : : }
17987 : : else
17988 : : {
17989 : 2038 : *gtask_clauses_ptr = c;
17990 : 2038 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17991 : : }
17992 : : break;
17993 : : /* These clauses go into outer taskloop clauses. */
17994 : 529 : case OMP_CLAUSE_GRAINSIZE:
17995 : 529 : case OMP_CLAUSE_NUM_TASKS:
17996 : 529 : case OMP_CLAUSE_NOGROUP:
17997 : 529 : *gforo_clauses_ptr = c;
17998 : 529 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
17999 : 529 : break;
18000 : : /* Collapse clause we duplicate on both taskloops. */
18001 : 580 : case OMP_CLAUSE_COLLAPSE:
18002 : 580 : *gfor_clauses_ptr = c;
18003 : 580 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18004 : 580 : *gforo_clauses_ptr = copy_node (c);
18005 : 580 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18006 : 580 : break;
18007 : : /* For lastprivate, keep the clause on inner taskloop, and add
18008 : : a shared clause on task. If the same decl is also firstprivate,
18009 : : add also firstprivate clause on the inner taskloop. */
18010 : 1187 : case OMP_CLAUSE_LASTPRIVATE:
18011 : 1187 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18012 : : {
18013 : : /* For taskloop C++ lastprivate IVs, we want:
18014 : : 1) private on outer taskloop
18015 : : 2) firstprivate and shared on task
18016 : : 3) lastprivate on inner taskloop */
18017 : 38 : *gtask_clauses_ptr
18018 : 38 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18019 : : OMP_CLAUSE_FIRSTPRIVATE);
18020 : 38 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18021 : 38 : lang_hooks.decls.omp_finish_clause (*gtask_clauses_ptr, NULL,
18022 : : openacc);
18023 : 38 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18024 : 38 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c) = 1;
18025 : 38 : *gforo_clauses_ptr = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18026 : : OMP_CLAUSE_PRIVATE);
18027 : 38 : OMP_CLAUSE_DECL (*gforo_clauses_ptr) = OMP_CLAUSE_DECL (c);
18028 : 38 : OMP_CLAUSE_PRIVATE_TASKLOOP_IV (*gforo_clauses_ptr) = 1;
18029 : 38 : TREE_TYPE (*gforo_clauses_ptr) = TREE_TYPE (c);
18030 : 38 : gforo_clauses_ptr = &OMP_CLAUSE_CHAIN (*gforo_clauses_ptr);
18031 : : }
18032 : 1187 : *gfor_clauses_ptr = c;
18033 : 1187 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18034 : 1187 : *gtask_clauses_ptr
18035 : 1187 : = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_SHARED);
18036 : 1187 : OMP_CLAUSE_DECL (*gtask_clauses_ptr) = OMP_CLAUSE_DECL (c);
18037 : 1187 : if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
18038 : 312 : OMP_CLAUSE_SHARED_FIRSTPRIVATE (*gtask_clauses_ptr) = 1;
18039 : 1187 : gtask_clauses_ptr
18040 : 1187 : = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18041 : 1187 : break;
18042 : : /* Allocate clause we duplicate on task and inner taskloop
18043 : : if the decl is lastprivate, otherwise just put on task. */
18044 : 62 : case OMP_CLAUSE_ALLOCATE:
18045 : 62 : if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)
18046 : 62 : && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))
18047 : : {
18048 : : /* Additionally, put firstprivate clause on task
18049 : : for the allocator if it is not constant. */
18050 : 34 : *gtask_clauses_ptr
18051 : 34 : = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18052 : : OMP_CLAUSE_FIRSTPRIVATE);
18053 : 34 : OMP_CLAUSE_DECL (*gtask_clauses_ptr)
18054 : 34 : = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c);
18055 : 34 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18056 : : }
18057 : 62 : if (lastprivate_uids
18058 : 97 : && bitmap_bit_p (lastprivate_uids,
18059 : 35 : DECL_UID (OMP_CLAUSE_DECL (c))))
18060 : : {
18061 : 17 : *gfor_clauses_ptr = c;
18062 : 17 : gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18063 : 17 : *gtask_clauses_ptr = copy_node (c);
18064 : 17 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr);
18065 : : }
18066 : : else
18067 : : {
18068 : 45 : *gtask_clauses_ptr = c;
18069 : 45 : gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
18070 : : }
18071 : : break;
18072 : 0 : default:
18073 : 0 : gcc_unreachable ();
18074 : : }
18075 : 1582 : *gfor_clauses_ptr = NULL_TREE;
18076 : 1582 : *gtask_clauses_ptr = NULL_TREE;
18077 : 1582 : *gforo_clauses_ptr = NULL_TREE;
18078 : 1582 : BITMAP_FREE (lastprivate_uids);
18079 : 1582 : gimple_set_location (gfor, input_location);
18080 : 1582 : g = gimple_build_bind (NULL_TREE, gfor, NULL_TREE);
18081 : 1582 : g = gimple_build_omp_task (g, task_clauses, NULL_TREE, NULL_TREE,
18082 : : NULL_TREE, NULL_TREE, NULL_TREE);
18083 : 1582 : gimple_set_location (g, input_location);
18084 : 1582 : gimple_omp_task_set_taskloop_p (g, true);
18085 : 1582 : g = gimple_build_bind (NULL_TREE, g, NULL_TREE);
18086 : 1582 : gomp_for *gforo
18087 : 1582 : = gimple_build_omp_for (g, GF_OMP_FOR_KIND_TASKLOOP, outer_for_clauses,
18088 : : gimple_omp_for_collapse (gfor),
18089 : : gimple_omp_for_pre_body (gfor));
18090 : 1582 : gimple_omp_for_set_pre_body (gfor, NULL);
18091 : 1582 : gimple_omp_for_set_combined_p (gforo, true);
18092 : 1582 : gimple_omp_for_set_combined_into_p (gfor, true);
18093 : 3450 : for (i = 0; i < (int) gimple_omp_for_collapse (gfor); i++)
18094 : : {
18095 : 1868 : tree type = TREE_TYPE (gimple_omp_for_index (gfor, i));
18096 : 1868 : tree v = create_tmp_var (type);
18097 : 1868 : gimple_omp_for_set_index (gforo, i, v);
18098 : 1868 : t = unshare_expr (gimple_omp_for_initial (gfor, i));
18099 : 1868 : gimple_omp_for_set_initial (gforo, i, t);
18100 : 1868 : gimple_omp_for_set_cond (gforo, i,
18101 : : gimple_omp_for_cond (gfor, i));
18102 : 1868 : t = unshare_expr (gimple_omp_for_final (gfor, i));
18103 : 1868 : gimple_omp_for_set_final (gforo, i, t);
18104 : 1868 : t = unshare_expr (gimple_omp_for_incr (gfor, i));
18105 : 1868 : gcc_assert (TREE_OPERAND (t, 0) == gimple_omp_for_index (gfor, i));
18106 : 1868 : TREE_OPERAND (t, 0) = v;
18107 : 1868 : gimple_omp_for_set_incr (gforo, i, t);
18108 : 1868 : t = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
18109 : 1868 : OMP_CLAUSE_DECL (t) = v;
18110 : 1868 : OMP_CLAUSE_CHAIN (t) = gimple_omp_for_clauses (gforo);
18111 : 1868 : gimple_omp_for_set_clauses (gforo, t);
18112 : 1868 : if (OMP_FOR_NON_RECTANGULAR (for_stmt))
18113 : : {
18114 : 90 : tree *p1 = NULL, *p2 = NULL;
18115 : 90 : t = gimple_omp_for_initial (gforo, i);
18116 : 90 : if (TREE_CODE (t) == TREE_VEC)
18117 : 34 : p1 = &TREE_VEC_ELT (t, 0);
18118 : 90 : t = gimple_omp_for_final (gforo, i);
18119 : 90 : if (TREE_CODE (t) == TREE_VEC)
18120 : : {
18121 : 31 : if (p1)
18122 : 23 : p2 = &TREE_VEC_ELT (t, 0);
18123 : : else
18124 : 8 : p1 = &TREE_VEC_ELT (t, 0);
18125 : : }
18126 : 90 : if (p1)
18127 : : {
18128 : : int j;
18129 : 58 : for (j = 0; j < i; j++)
18130 : 58 : if (*p1 == gimple_omp_for_index (gfor, j))
18131 : : {
18132 : 42 : *p1 = gimple_omp_for_index (gforo, j);
18133 : 42 : if (p2)
18134 : 23 : *p2 = *p1;
18135 : : break;
18136 : : }
18137 : 42 : gcc_assert (j < i);
18138 : : }
18139 : : }
18140 : : }
18141 : 1582 : gimplify_seq_add_stmt (pre_p, gforo);
18142 : : }
18143 : : else
18144 : 49585 : gimplify_seq_add_stmt (pre_p, gfor);
18145 : :
18146 : 51167 : if (TREE_CODE (orig_for_stmt) == OMP_FOR)
18147 : : {
18148 : 18161 : struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
18149 : 18161 : unsigned lastprivate_conditional = 0;
18150 : 18161 : while (ctx
18151 : 18197 : && (ctx->region_type == ORT_TARGET_DATA
18152 : 14171 : || ctx->region_type == ORT_TASKGROUP))
18153 : 36 : ctx = ctx->outer_context;
18154 : 18161 : if (ctx && (ctx->region_type & ORT_PARALLEL) != 0)
18155 : 13911 : for (tree c = gimple_omp_for_clauses (gfor);
18156 : 63129 : c; c = OMP_CLAUSE_CHAIN (c))
18157 : 49218 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18158 : 49218 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18159 : 158 : ++lastprivate_conditional;
18160 : 13911 : if (lastprivate_conditional)
18161 : : {
18162 : 118 : struct omp_for_data fd;
18163 : 118 : omp_extract_for_data (gfor, &fd, NULL);
18164 : 118 : tree type = build_array_type_nelts (unsigned_type_for (fd.iter_type),
18165 : 118 : lastprivate_conditional);
18166 : 118 : tree var = create_tmp_var_raw (type);
18167 : 118 : tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
18168 : 118 : OMP_CLAUSE_DECL (c) = var;
18169 : 118 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18170 : 118 : gimple_omp_for_set_clauses (gfor, c);
18171 : 118 : omp_add_variable (ctx, var, GOVD_CONDTEMP | GOVD_SEEN);
18172 : : }
18173 : : }
18174 : 33006 : else if (TREE_CODE (orig_for_stmt) == OMP_SIMD)
18175 : : {
18176 : 10648 : unsigned lastprivate_conditional = 0;
18177 : 49148 : for (tree c = gimple_omp_for_clauses (gfor); c; c = OMP_CLAUSE_CHAIN (c))
18178 : 38500 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
18179 : 38500 : && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
18180 : 119 : ++lastprivate_conditional;
18181 : 10648 : if (lastprivate_conditional)
18182 : : {
18183 : 91 : struct omp_for_data fd;
18184 : 91 : omp_extract_for_data (gfor, &fd, NULL);
18185 : 91 : tree type = unsigned_type_for (fd.iter_type);
18186 : 301 : while (lastprivate_conditional--)
18187 : : {
18188 : 119 : tree c = build_omp_clause (UNKNOWN_LOCATION,
18189 : : OMP_CLAUSE__CONDTEMP_);
18190 : 119 : OMP_CLAUSE_DECL (c) = create_tmp_var (type);
18191 : 119 : OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (gfor);
18192 : 119 : gimple_omp_for_set_clauses (gfor, c);
18193 : : }
18194 : : }
18195 : : }
18196 : :
18197 : 51167 : if (ret != GS_ALL_DONE)
18198 : : return GS_ERROR;
18199 : 51167 : *expr_p = NULL_TREE;
18200 : 51167 : return GS_ALL_DONE;
18201 : : }
18202 : :
18203 : : /* Helper for gimplify_omp_loop, called through walk_tree. */
18204 : :
18205 : : static tree
18206 : 294 : note_no_context_vars (tree *tp, int *, void *data)
18207 : : {
18208 : 294 : if (VAR_P (*tp)
18209 : 56 : && DECL_CONTEXT (*tp) == NULL_TREE
18210 : 309 : && !is_global_var (*tp))
18211 : : {
18212 : 15 : vec<tree> *d = (vec<tree> *) data;
18213 : 15 : d->safe_push (*tp);
18214 : 15 : DECL_CONTEXT (*tp) = current_function_decl;
18215 : : }
18216 : 294 : return NULL_TREE;
18217 : : }
18218 : :
18219 : : /* Gimplify the gross structure of an OMP_LOOP statement. */
18220 : :
18221 : : static enum gimplify_status
18222 : 1056 : gimplify_omp_loop (tree *expr_p, gimple_seq *pre_p)
18223 : : {
18224 : 1056 : tree for_stmt = *expr_p;
18225 : 1056 : tree clauses = OMP_FOR_CLAUSES (for_stmt);
18226 : 1056 : struct gimplify_omp_ctx *octx = gimplify_omp_ctxp;
18227 : 1056 : enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
18228 : 1056 : int i;
18229 : :
18230 : 1056 : omp_maybe_apply_loop_xforms (expr_p, NULL_TREE);
18231 : 1056 : if (*expr_p != for_stmt)
18232 : : return GS_OK;
18233 : :
18234 : : /* If order is not present, the behavior is as if order(concurrent)
18235 : : appeared. */
18236 : 1056 : tree order = omp_find_clause (clauses, OMP_CLAUSE_ORDER);
18237 : 1056 : if (order == NULL_TREE)
18238 : : {
18239 : 799 : order = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_ORDER);
18240 : 799 : OMP_CLAUSE_CHAIN (order) = clauses;
18241 : 799 : OMP_FOR_CLAUSES (for_stmt) = clauses = order;
18242 : : }
18243 : :
18244 : 1056 : tree bind = omp_find_clause (clauses, OMP_CLAUSE_BIND);
18245 : 1056 : if (bind == NULL_TREE)
18246 : : {
18247 : 574 : if (!flag_openmp) /* flag_openmp_simd */
18248 : : ;
18249 : 557 : else if (octx && (octx->region_type & ORT_TEAMS) != 0)
18250 : : kind = OMP_CLAUSE_BIND_TEAMS;
18251 : 327 : else if (octx && (octx->region_type & ORT_PARALLEL) != 0)
18252 : : kind = OMP_CLAUSE_BIND_PARALLEL;
18253 : : else
18254 : : {
18255 : 187 : for (; octx; octx = octx->outer_context)
18256 : : {
18257 : 79 : if ((octx->region_type & ORT_ACC) != 0
18258 : 79 : || octx->region_type == ORT_NONE
18259 : 79 : || octx->region_type == ORT_IMPLICIT_TARGET)
18260 : 0 : continue;
18261 : : break;
18262 : : }
18263 : 187 : if (octx == NULL && !in_omp_construct)
18264 : 4 : error_at (EXPR_LOCATION (for_stmt),
18265 : : "%<bind%> clause not specified on a %<loop%> "
18266 : : "construct not nested inside another OpenMP construct");
18267 : : }
18268 : 574 : bind = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_BIND);
18269 : 574 : OMP_CLAUSE_CHAIN (bind) = clauses;
18270 : 574 : OMP_CLAUSE_BIND_KIND (bind) = kind;
18271 : 574 : OMP_FOR_CLAUSES (for_stmt) = bind;
18272 : : }
18273 : : else
18274 : 482 : switch (OMP_CLAUSE_BIND_KIND (bind))
18275 : : {
18276 : : case OMP_CLAUSE_BIND_THREAD:
18277 : : break;
18278 : 166 : case OMP_CLAUSE_BIND_PARALLEL:
18279 : 166 : if (!flag_openmp) /* flag_openmp_simd */
18280 : : {
18281 : 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18282 : 0 : break;
18283 : : }
18284 : 240 : for (; octx; octx = octx->outer_context)
18285 : 78 : if (octx->region_type == ORT_SIMD
18286 : 78 : && omp_find_clause (octx->clauses, OMP_CLAUSE_BIND) == NULL_TREE)
18287 : : {
18288 : 4 : error_at (EXPR_LOCATION (for_stmt),
18289 : : "%<bind(parallel)%> on a %<loop%> construct nested "
18290 : : "inside %<simd%> construct");
18291 : 4 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18292 : 4 : break;
18293 : : }
18294 : : kind = OMP_CLAUSE_BIND_PARALLEL;
18295 : : break;
18296 : 162 : case OMP_CLAUSE_BIND_TEAMS:
18297 : 162 : if (!flag_openmp) /* flag_openmp_simd */
18298 : : {
18299 : 0 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18300 : 0 : break;
18301 : : }
18302 : 162 : if ((octx
18303 : 128 : && octx->region_type != ORT_IMPLICIT_TARGET
18304 : 111 : && octx->region_type != ORT_NONE
18305 : 111 : && (octx->region_type & ORT_TEAMS) == 0)
18306 : 110 : || in_omp_construct)
18307 : : {
18308 : 64 : error_at (EXPR_LOCATION (for_stmt),
18309 : : "%<bind(teams)%> on a %<loop%> region not strictly "
18310 : : "nested inside of a %<teams%> region");
18311 : 64 : OMP_CLAUSE_BIND_KIND (bind) = OMP_CLAUSE_BIND_THREAD;
18312 : 64 : break;
18313 : : }
18314 : : kind = OMP_CLAUSE_BIND_TEAMS;
18315 : : break;
18316 : 0 : default:
18317 : 0 : gcc_unreachable ();
18318 : : }
18319 : :
18320 : 4280 : for (tree *pc = &OMP_FOR_CLAUSES (for_stmt); *pc; )
18321 : 3224 : switch (OMP_CLAUSE_CODE (*pc))
18322 : : {
18323 : 343 : case OMP_CLAUSE_REDUCTION:
18324 : 343 : if (OMP_CLAUSE_REDUCTION_INSCAN (*pc))
18325 : : {
18326 : 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18327 : : "%<inscan%> %<reduction%> clause on "
18328 : : "%qs construct", "loop");
18329 : 4 : OMP_CLAUSE_REDUCTION_INSCAN (*pc) = 0;
18330 : : }
18331 : 343 : if (OMP_CLAUSE_REDUCTION_TASK (*pc))
18332 : : {
18333 : 8 : error_at (OMP_CLAUSE_LOCATION (*pc),
18334 : : "invalid %<task%> reduction modifier on construct "
18335 : : "other than %<parallel%>, %qs or %<sections%>",
18336 : 4 : lang_GNU_Fortran () ? "do" : "for");
18337 : 4 : OMP_CLAUSE_REDUCTION_TASK (*pc) = 0;
18338 : : }
18339 : 343 : pc = &OMP_CLAUSE_CHAIN (*pc);
18340 : 343 : break;
18341 : : case OMP_CLAUSE_LASTPRIVATE:
18342 : 293 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18343 : : {
18344 : 289 : tree t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i);
18345 : 289 : gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
18346 : 289 : if (OMP_CLAUSE_DECL (*pc) == TREE_OPERAND (t, 0))
18347 : : break;
18348 : 26 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18349 : 25 : && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18350 : : i)) == TREE_LIST
18351 : 48 : && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt),
18352 : : i)))
18353 : : {
18354 : 22 : tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18355 : 22 : if (OMP_CLAUSE_DECL (*pc) == TREE_PURPOSE (orig))
18356 : : break;
18357 : : }
18358 : : }
18359 : 289 : if (i == TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)))
18360 : : {
18361 : 4 : error_at (OMP_CLAUSE_LOCATION (*pc),
18362 : : "%<lastprivate%> clause on a %<loop%> construct refers "
18363 : : "to a variable %qD which is not the loop iterator",
18364 : 4 : OMP_CLAUSE_DECL (*pc));
18365 : 4 : *pc = OMP_CLAUSE_CHAIN (*pc);
18366 : 4 : break;
18367 : : }
18368 : 285 : pc = &OMP_CLAUSE_CHAIN (*pc);
18369 : 285 : break;
18370 : 2592 : default:
18371 : 2592 : pc = &OMP_CLAUSE_CHAIN (*pc);
18372 : 2592 : break;
18373 : : }
18374 : :
18375 : 1056 : TREE_SET_CODE (for_stmt, OMP_SIMD);
18376 : :
18377 : 1056 : int last;
18378 : 1056 : switch (kind)
18379 : : {
18380 : : case OMP_CLAUSE_BIND_THREAD: last = 0; break;
18381 : 414 : case OMP_CLAUSE_BIND_PARALLEL: last = 1; break;
18382 : 220 : case OMP_CLAUSE_BIND_TEAMS: last = 2; break;
18383 : : }
18384 : 1910 : for (int pass = 1; pass <= last; pass++)
18385 : : {
18386 : 854 : if (pass == 2)
18387 : : {
18388 : 220 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, NULL,
18389 : : make_node (BLOCK));
18390 : 220 : append_to_statement_list (*expr_p, &BIND_EXPR_BODY (bind));
18391 : 220 : *expr_p = make_node (OMP_PARALLEL);
18392 : 220 : TREE_TYPE (*expr_p) = void_type_node;
18393 : 220 : OMP_PARALLEL_BODY (*expr_p) = bind;
18394 : 220 : OMP_PARALLEL_COMBINED (*expr_p) = 1;
18395 : 220 : SET_EXPR_LOCATION (*expr_p, EXPR_LOCATION (for_stmt));
18396 : 220 : tree *pc = &OMP_PARALLEL_CLAUSES (*expr_p);
18397 : 452 : for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (for_stmt)); i++)
18398 : 232 : if (OMP_FOR_ORIG_DECLS (for_stmt)
18399 : 232 : && (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i))
18400 : : == TREE_LIST))
18401 : : {
18402 : 16 : tree elt = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (for_stmt), i);
18403 : 16 : if (TREE_PURPOSE (elt) && TREE_VALUE (elt))
18404 : : {
18405 : 13 : *pc = build_omp_clause (UNKNOWN_LOCATION,
18406 : : OMP_CLAUSE_FIRSTPRIVATE);
18407 : 13 : OMP_CLAUSE_DECL (*pc) = TREE_VALUE (elt);
18408 : 13 : pc = &OMP_CLAUSE_CHAIN (*pc);
18409 : : }
18410 : : }
18411 : : }
18412 : 854 : tree t = make_node (pass == 2 ? OMP_DISTRIBUTE : OMP_FOR);
18413 : 854 : tree *pc = &OMP_FOR_CLAUSES (t);
18414 : 854 : TREE_TYPE (t) = void_type_node;
18415 : 854 : OMP_FOR_BODY (t) = *expr_p;
18416 : 854 : SET_EXPR_LOCATION (t, EXPR_LOCATION (for_stmt));
18417 : 3968 : for (tree c = OMP_FOR_CLAUSES (for_stmt); c; c = OMP_CLAUSE_CHAIN (c))
18418 : 3114 : switch (OMP_CLAUSE_CODE (c))
18419 : : {
18420 : 1992 : case OMP_CLAUSE_BIND:
18421 : 1992 : case OMP_CLAUSE_ORDER:
18422 : 1992 : case OMP_CLAUSE_COLLAPSE:
18423 : 1992 : *pc = copy_node (c);
18424 : 1992 : pc = &OMP_CLAUSE_CHAIN (*pc);
18425 : 1992 : break;
18426 : : case OMP_CLAUSE_PRIVATE:
18427 : : case OMP_CLAUSE_FIRSTPRIVATE:
18428 : : /* Only needed on innermost. */
18429 : : break;
18430 : 351 : case OMP_CLAUSE_LASTPRIVATE:
18431 : 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) && pass != last)
18432 : : {
18433 : 7 : *pc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
18434 : : OMP_CLAUSE_FIRSTPRIVATE);
18435 : 7 : OMP_CLAUSE_DECL (*pc) = OMP_CLAUSE_DECL (c);
18436 : 7 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18437 : 7 : pc = &OMP_CLAUSE_CHAIN (*pc);
18438 : : }
18439 : 351 : *pc = copy_node (c);
18440 : 351 : OMP_CLAUSE_LASTPRIVATE_STMT (*pc) = NULL_TREE;
18441 : 351 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18442 : 351 : if (OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c))
18443 : : {
18444 : 22 : if (pass != last)
18445 : 7 : OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (*pc) = 1;
18446 : : else
18447 : 15 : lang_hooks.decls.omp_finish_clause (*pc, NULL, false);
18448 : 22 : OMP_CLAUSE_LASTPRIVATE_LOOP_IV (*pc) = 0;
18449 : : }
18450 : 351 : pc = &OMP_CLAUSE_CHAIN (*pc);
18451 : 351 : break;
18452 : 463 : case OMP_CLAUSE_REDUCTION:
18453 : 463 : *pc = copy_node (c);
18454 : 463 : OMP_CLAUSE_DECL (*pc) = unshare_expr (OMP_CLAUSE_DECL (c));
18455 : 463 : TREE_TYPE (*pc) = unshare_expr (TREE_TYPE (c));
18456 : 463 : if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc))
18457 : : {
18458 : 15 : auto_vec<tree> no_context_vars;
18459 : 15 : int walk_subtrees = 0;
18460 : 15 : note_no_context_vars (&OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18461 : : &walk_subtrees, &no_context_vars);
18462 : 15 : if (tree p = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c))
18463 : 0 : note_no_context_vars (&p, &walk_subtrees, &no_context_vars);
18464 : 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_INIT (c),
18465 : : note_no_context_vars,
18466 : : &no_context_vars);
18467 : 15 : walk_tree_without_duplicates (&OMP_CLAUSE_REDUCTION_MERGE (c),
18468 : : note_no_context_vars,
18469 : : &no_context_vars);
18470 : :
18471 : 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc)
18472 : 15 : = copy_node (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
18473 : 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18474 : 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc)
18475 : 0 : = copy_node (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c));
18476 : :
18477 : 15 : hash_map<tree, tree> decl_map;
18478 : 15 : decl_map.put (OMP_CLAUSE_DECL (c), OMP_CLAUSE_DECL (c));
18479 : 15 : decl_map.put (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c),
18480 : 15 : OMP_CLAUSE_REDUCTION_PLACEHOLDER (*pc));
18481 : 15 : if (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc))
18482 : 0 : decl_map.put (OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c),
18483 : 0 : OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (*pc));
18484 : :
18485 : 15 : copy_body_data id;
18486 : 15 : memset (&id, 0, sizeof (id));
18487 : 15 : id.src_fn = current_function_decl;
18488 : 15 : id.dst_fn = current_function_decl;
18489 : 15 : id.src_cfun = cfun;
18490 : 15 : id.decl_map = &decl_map;
18491 : 15 : id.copy_decl = copy_decl_no_change;
18492 : 15 : id.transform_call_graph_edges = CB_CGE_DUPLICATE;
18493 : 15 : id.transform_new_cfg = true;
18494 : 15 : id.transform_return_to_modify = false;
18495 : 15 : id.eh_lp_nr = 0;
18496 : 15 : walk_tree (&OMP_CLAUSE_REDUCTION_INIT (*pc), copy_tree_body_r,
18497 : : &id, NULL);
18498 : 15 : walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (*pc), copy_tree_body_r,
18499 : : &id, NULL);
18500 : :
18501 : 60 : for (tree d : no_context_vars)
18502 : : {
18503 : 15 : DECL_CONTEXT (d) = NULL_TREE;
18504 : 15 : DECL_CONTEXT (*decl_map.get (d)) = NULL_TREE;
18505 : : }
18506 : 15 : }
18507 : : else
18508 : : {
18509 : 448 : OMP_CLAUSE_REDUCTION_INIT (*pc)
18510 : 448 : = unshare_expr (OMP_CLAUSE_REDUCTION_INIT (c));
18511 : 448 : OMP_CLAUSE_REDUCTION_MERGE (*pc)
18512 : 896 : = unshare_expr (OMP_CLAUSE_REDUCTION_MERGE (c));
18513 : : }
18514 : 463 : pc = &OMP_CLAUSE_CHAIN (*pc);
18515 : 463 : break;
18516 : 0 : default:
18517 : 0 : gcc_unreachable ();
18518 : : }
18519 : 854 : *pc = NULL_TREE;
18520 : 854 : *expr_p = t;
18521 : : }
18522 : 1056 : return gimplify_expr (expr_p, pre_p, NULL, is_gimple_stmt, fb_none);
18523 : : }
18524 : :
18525 : :
18526 : : /* Helper function of optimize_target_teams, find OMP_TEAMS inside
18527 : : of OMP_TARGET's body. */
18528 : :
18529 : : static tree
18530 : 80775 : find_omp_teams (tree *tp, int *walk_subtrees, void *)
18531 : : {
18532 : 80775 : *walk_subtrees = 0;
18533 : 80775 : switch (TREE_CODE (*tp))
18534 : : {
18535 : : case OMP_TEAMS:
18536 : : return *tp;
18537 : 23985 : case BIND_EXPR:
18538 : 23985 : case STATEMENT_LIST:
18539 : 23985 : *walk_subtrees = 1;
18540 : 23985 : break;
18541 : : default:
18542 : : break;
18543 : : }
18544 : : return NULL_TREE;
18545 : : }
18546 : :
18547 : : /* Helper function of optimize_target_teams, determine if the expression
18548 : : can be computed safely before the target construct on the host. */
18549 : :
18550 : : static tree
18551 : 1311 : computable_teams_clause (tree *tp, int *walk_subtrees, void *)
18552 : : {
18553 : 1831 : splay_tree_node n;
18554 : :
18555 : 1831 : if (TYPE_P (*tp))
18556 : : {
18557 : 0 : *walk_subtrees = 0;
18558 : 0 : return NULL_TREE;
18559 : : }
18560 : 1831 : switch (TREE_CODE (*tp))
18561 : : {
18562 : 990 : case VAR_DECL:
18563 : 990 : case PARM_DECL:
18564 : 990 : case RESULT_DECL:
18565 : 990 : *walk_subtrees = 0;
18566 : 990 : if (error_operand_p (*tp)
18567 : 990 : || !INTEGRAL_TYPE_P (TREE_TYPE (*tp))
18568 : 990 : || DECL_HAS_VALUE_EXPR_P (*tp)
18569 : 990 : || DECL_THREAD_LOCAL_P (*tp)
18570 : 990 : || TREE_SIDE_EFFECTS (*tp)
18571 : 1980 : || TREE_THIS_VOLATILE (*tp))
18572 : 0 : return *tp;
18573 : 990 : if (is_global_var (*tp)
18574 : 990 : && (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (*tp))
18575 : 0 : || lookup_attribute ("omp declare target link",
18576 : 0 : DECL_ATTRIBUTES (*tp))))
18577 : 16 : return *tp;
18578 : 974 : if (VAR_P (*tp)
18579 : 668 : && !DECL_SEEN_IN_BIND_EXPR_P (*tp)
18580 : 50 : && !is_global_var (*tp)
18581 : 1024 : && decl_function_context (*tp) == current_function_decl)
18582 : 50 : return *tp;
18583 : 1848 : n = splay_tree_lookup (gimplify_omp_ctxp->variables,
18584 : 924 : (splay_tree_key) *tp);
18585 : 924 : if (n == NULL)
18586 : : {
18587 : 292 : if (gimplify_omp_ctxp->defaultmap[GDMK_SCALAR] & GOVD_FIRSTPRIVATE)
18588 : : return NULL_TREE;
18589 : 24 : return *tp;
18590 : : }
18591 : 632 : else if (n->value & GOVD_LOCAL)
18592 : 0 : return *tp;
18593 : 632 : else if (n->value & GOVD_FIRSTPRIVATE)
18594 : : return NULL_TREE;
18595 : 112 : else if ((n->value & (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18596 : : == (GOVD_MAP | GOVD_MAP_ALWAYS_TO))
18597 : : return NULL_TREE;
18598 : 96 : return *tp;
18599 : 76 : case INTEGER_CST:
18600 : 76 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18601 : : return *tp;
18602 : : return NULL_TREE;
18603 : 520 : case TARGET_EXPR:
18604 : 520 : if (TARGET_EXPR_INITIAL (*tp)
18605 : 520 : || TREE_CODE (TARGET_EXPR_SLOT (*tp)) != VAR_DECL)
18606 : : return *tp;
18607 : 520 : return computable_teams_clause (&TARGET_EXPR_SLOT (*tp),
18608 : 520 : walk_subtrees, NULL);
18609 : : /* Allow some reasonable subset of integral arithmetics. */
18610 : 193 : case PLUS_EXPR:
18611 : 193 : case MINUS_EXPR:
18612 : 193 : case MULT_EXPR:
18613 : 193 : case TRUNC_DIV_EXPR:
18614 : 193 : case CEIL_DIV_EXPR:
18615 : 193 : case FLOOR_DIV_EXPR:
18616 : 193 : case ROUND_DIV_EXPR:
18617 : 193 : case TRUNC_MOD_EXPR:
18618 : 193 : case CEIL_MOD_EXPR:
18619 : 193 : case FLOOR_MOD_EXPR:
18620 : 193 : case ROUND_MOD_EXPR:
18621 : 193 : case RDIV_EXPR:
18622 : 193 : case EXACT_DIV_EXPR:
18623 : 193 : case MIN_EXPR:
18624 : 193 : case MAX_EXPR:
18625 : 193 : case LSHIFT_EXPR:
18626 : 193 : case RSHIFT_EXPR:
18627 : 193 : case BIT_IOR_EXPR:
18628 : 193 : case BIT_XOR_EXPR:
18629 : 193 : case BIT_AND_EXPR:
18630 : 193 : case NEGATE_EXPR:
18631 : 193 : case ABS_EXPR:
18632 : 193 : case BIT_NOT_EXPR:
18633 : 193 : case NON_LVALUE_EXPR:
18634 : 193 : CASE_CONVERT:
18635 : 193 : if (!INTEGRAL_TYPE_P (TREE_TYPE (*tp)))
18636 : : return *tp;
18637 : : return NULL_TREE;
18638 : : /* And disallow anything else, except for comparisons. */
18639 : 52 : default:
18640 : 52 : if (COMPARISON_CLASS_P (*tp))
18641 : : return NULL_TREE;
18642 : : return *tp;
18643 : : }
18644 : : }
18645 : :
18646 : : /* Try to determine if the num_teams and/or thread_limit expressions
18647 : : can have their values determined already before entering the
18648 : : target construct.
18649 : : INTEGER_CSTs trivially are,
18650 : : integral decls that are firstprivate (explicitly or implicitly)
18651 : : or explicitly map(always, to:) or map(always, tofrom:) on the target
18652 : : region too, and expressions involving simple arithmetics on those
18653 : : too, function calls are not ok, dereferencing something neither etc.
18654 : : Add NUM_TEAMS and THREAD_LIMIT clauses to the OMP_CLAUSES of
18655 : : EXPR based on what we find:
18656 : : 0 stands for clause not specified at all, use implementation default
18657 : : -1 stands for value that can't be determined easily before entering
18658 : : the target construct.
18659 : : -2 means that no explicit teams construct was specified
18660 : : If teams construct is not present at all, use 1 for num_teams
18661 : : and 0 for thread_limit (only one team is involved, and the thread
18662 : : limit is implementation defined. */
18663 : :
18664 : : static void
18665 : 12628 : optimize_target_teams (tree target, gimple_seq *pre_p)
18666 : : {
18667 : 12628 : tree body = OMP_BODY (target);
18668 : 12628 : tree teams = walk_tree (&body, find_omp_teams, NULL, NULL);
18669 : 12628 : tree num_teams_lower = NULL_TREE;
18670 : 12628 : tree num_teams_upper = integer_zero_node;
18671 : 12628 : tree thread_limit = integer_zero_node;
18672 : 12628 : location_t num_teams_loc = EXPR_LOCATION (target);
18673 : 12628 : location_t thread_limit_loc = EXPR_LOCATION (target);
18674 : 12628 : tree c, *p, expr;
18675 : 12628 : struct gimplify_omp_ctx *target_ctx = gimplify_omp_ctxp;
18676 : :
18677 : 12628 : if (teams == NULL_TREE)
18678 : 6519 : num_teams_upper = build_int_cst (integer_type_node, -2);
18679 : : else
18680 : 10580 : for (c = OMP_TEAMS_CLAUSES (teams); c; c = OMP_CLAUSE_CHAIN (c))
18681 : : {
18682 : 4471 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS)
18683 : : {
18684 : 617 : p = &num_teams_upper;
18685 : 617 : num_teams_loc = OMP_CLAUSE_LOCATION (c);
18686 : 617 : if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c))
18687 : : {
18688 : 148 : expr = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c);
18689 : 148 : if (TREE_CODE (expr) == INTEGER_CST)
18690 : 21 : num_teams_lower = expr;
18691 : 127 : else if (walk_tree (&expr, computable_teams_clause,
18692 : : NULL, NULL))
18693 : 19 : num_teams_lower = integer_minus_one_node;
18694 : : else
18695 : : {
18696 : 108 : num_teams_lower = expr;
18697 : 108 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18698 : 108 : if (gimplify_expr (&num_teams_lower, pre_p, NULL,
18699 : : is_gimple_val, fb_rvalue, false)
18700 : : == GS_ERROR)
18701 : : {
18702 : 0 : gimplify_omp_ctxp = target_ctx;
18703 : 0 : num_teams_lower = integer_minus_one_node;
18704 : : }
18705 : : else
18706 : : {
18707 : 108 : gimplify_omp_ctxp = target_ctx;
18708 : 108 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18709 : 28 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c)
18710 : 56 : = num_teams_lower;
18711 : : }
18712 : : }
18713 : : }
18714 : : }
18715 : 3854 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
18716 : : {
18717 : 471 : p = &thread_limit;
18718 : 471 : thread_limit_loc = OMP_CLAUSE_LOCATION (c);
18719 : : }
18720 : : else
18721 : 3383 : continue;
18722 : 1088 : expr = OMP_CLAUSE_OPERAND (c, 0);
18723 : 1088 : if (TREE_CODE (expr) == INTEGER_CST)
18724 : : {
18725 : 173 : *p = expr;
18726 : 173 : continue;
18727 : : }
18728 : 915 : if (walk_tree (&expr, computable_teams_clause, NULL, NULL))
18729 : : {
18730 : 219 : *p = integer_minus_one_node;
18731 : 219 : continue;
18732 : : }
18733 : 696 : *p = expr;
18734 : 696 : gimplify_omp_ctxp = gimplify_omp_ctxp->outer_context;
18735 : 696 : if (gimplify_expr (p, pre_p, NULL, is_gimple_val, fb_rvalue, false)
18736 : : == GS_ERROR)
18737 : : {
18738 : 0 : gimplify_omp_ctxp = target_ctx;
18739 : 0 : *p = integer_minus_one_node;
18740 : 0 : continue;
18741 : : }
18742 : 696 : gimplify_omp_ctxp = target_ctx;
18743 : 696 : if (!DECL_P (expr) && TREE_CODE (expr) != TARGET_EXPR)
18744 : 48 : OMP_CLAUSE_OPERAND (c, 0) = *p;
18745 : : }
18746 : 12628 : if (!omp_find_clause (OMP_TARGET_CLAUSES (target), OMP_CLAUSE_THREAD_LIMIT))
18747 : : {
18748 : 12360 : c = build_omp_clause (thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
18749 : 12360 : OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
18750 : 12360 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18751 : 12360 : OMP_TARGET_CLAUSES (target) = c;
18752 : : }
18753 : 12628 : c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
18754 : 12628 : OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = num_teams_upper;
18755 : 12628 : OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = num_teams_lower;
18756 : 12628 : OMP_CLAUSE_CHAIN (c) = OMP_TARGET_CLAUSES (target);
18757 : 12628 : OMP_TARGET_CLAUSES (target) = c;
18758 : 12628 : }
18759 : :
18760 : : /* Gimplify the gross structure of several OMP constructs. */
18761 : :
18762 : : static void
18763 : 38929 : gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
18764 : : {
18765 : 38929 : tree expr = *expr_p;
18766 : 38929 : gimple *stmt;
18767 : 38929 : gimple_seq body = NULL;
18768 : 38929 : enum omp_region_type ort;
18769 : :
18770 : 38929 : switch (TREE_CODE (expr))
18771 : : {
18772 : : case OMP_SECTIONS:
18773 : : case OMP_SINGLE:
18774 : : ort = ORT_WORKSHARE;
18775 : : break;
18776 : 214 : case OMP_SCOPE:
18777 : 214 : ort = ORT_TASKGROUP;
18778 : 214 : break;
18779 : 12628 : case OMP_TARGET:
18780 : 12628 : ort = OMP_TARGET_COMBINED (expr) ? ORT_COMBINED_TARGET : ORT_TARGET;
18781 : : break;
18782 : 2541 : case OACC_KERNELS:
18783 : 2541 : ort = ORT_ACC_KERNELS;
18784 : 2541 : break;
18785 : 7901 : case OACC_PARALLEL:
18786 : 7901 : ort = ORT_ACC_PARALLEL;
18787 : 7901 : break;
18788 : 1040 : case OACC_SERIAL:
18789 : 1040 : ort = ORT_ACC_SERIAL;
18790 : 1040 : break;
18791 : 1950 : case OACC_DATA:
18792 : 1950 : ort = ORT_ACC_DATA;
18793 : 1950 : break;
18794 : 1863 : case OMP_TARGET_DATA:
18795 : 1863 : ort = ORT_TARGET_DATA;
18796 : 1863 : break;
18797 : 8774 : case OMP_TEAMS:
18798 : 8774 : ort = OMP_TEAMS_COMBINED (expr) ? ORT_COMBINED_TEAMS : ORT_TEAMS;
18799 : 8774 : if (gimplify_omp_ctxp == NULL
18800 : 6149 : || gimplify_omp_ctxp->region_type == ORT_IMPLICIT_TARGET)
18801 : 2625 : ort = (enum omp_region_type) (ort | ORT_HOST_TEAMS);
18802 : : break;
18803 : 118 : case OACC_HOST_DATA:
18804 : 118 : ort = ORT_ACC_HOST_DATA;
18805 : 118 : break;
18806 : 0 : default:
18807 : 0 : gcc_unreachable ();
18808 : : }
18809 : :
18810 : 38929 : gimple_seq iterator_loops_seq = NULL;
18811 : 38929 : if (TREE_CODE (expr) == OMP_TARGET)
18812 : : {
18813 : 12628 : remove_unused_omp_iterator_vars (&OMP_CLAUSES (expr));
18814 : 12628 : build_omp_iterators_loops (&OMP_CLAUSES (expr), &iterator_loops_seq);
18815 : : }
18816 : :
18817 : 38929 : bool save_in_omp_construct = in_omp_construct;
18818 : 38929 : if ((ort & ORT_ACC) == 0)
18819 : 25379 : in_omp_construct = false;
18820 : 38929 : gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
18821 : 38929 : TREE_CODE (expr), &iterator_loops_seq);
18822 : 38929 : if (TREE_CODE (expr) == OMP_TARGET)
18823 : 12628 : optimize_target_teams (expr, pre_p);
18824 : 38929 : if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
18825 : 10888 : || (ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18826 : : {
18827 : 30666 : push_gimplify_context ();
18828 : 30666 : gimple *g = gimplify_and_return_first (OMP_BODY (expr), &body);
18829 : 30666 : if (gimple_code (g) == GIMPLE_BIND)
18830 : 30666 : pop_gimplify_context (g);
18831 : : else
18832 : 0 : pop_gimplify_context (NULL);
18833 : 30666 : if ((ort & ORT_TARGET_DATA) != 0)
18834 : : {
18835 : 3931 : enum built_in_function end_ix;
18836 : 3931 : switch (TREE_CODE (expr))
18837 : : {
18838 : : case OACC_DATA:
18839 : : case OACC_HOST_DATA:
18840 : : end_ix = BUILT_IN_GOACC_DATA_END;
18841 : : break;
18842 : 1863 : case OMP_TARGET_DATA:
18843 : 1863 : end_ix = BUILT_IN_GOMP_TARGET_END_DATA;
18844 : 1863 : break;
18845 : 0 : default:
18846 : 0 : gcc_unreachable ();
18847 : : }
18848 : 3931 : tree fn = builtin_decl_explicit (end_ix);
18849 : 3931 : g = gimple_build_call (fn, 0);
18850 : 3931 : gimple_seq cleanup = NULL;
18851 : 3931 : gimple_seq_add_stmt (&cleanup, g);
18852 : 3931 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
18853 : 3931 : body = NULL;
18854 : 3931 : gimple_seq_add_stmt (&body, g);
18855 : : }
18856 : : }
18857 : : else
18858 : 8263 : gimplify_and_add (OMP_BODY (expr), &body);
18859 : 38929 : gimplify_adjust_omp_clauses (pre_p, body, &OMP_CLAUSES (expr),
18860 : 38929 : TREE_CODE (expr), &iterator_loops_seq);
18861 : 38929 : in_omp_construct = save_in_omp_construct;
18862 : :
18863 : 38929 : switch (TREE_CODE (expr))
18864 : : {
18865 : 1950 : case OACC_DATA:
18866 : 3900 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_DATA,
18867 : 1950 : OMP_CLAUSES (expr));
18868 : 1950 : break;
18869 : 118 : case OACC_HOST_DATA:
18870 : 118 : if (omp_find_clause (OMP_CLAUSES (expr), OMP_CLAUSE_IF_PRESENT))
18871 : : {
18872 : 128 : for (tree c = OMP_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18873 : 95 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
18874 : 57 : OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (c) = 1;
18875 : : }
18876 : :
18877 : 236 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_HOST_DATA,
18878 : 118 : OMP_CLAUSES (expr));
18879 : 118 : break;
18880 : 2541 : case OACC_KERNELS:
18881 : 5082 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_KERNELS,
18882 : 2541 : OMP_CLAUSES (expr));
18883 : 2541 : break;
18884 : 7901 : case OACC_PARALLEL:
18885 : 15802 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_PARALLEL,
18886 : 7901 : OMP_CLAUSES (expr));
18887 : 7901 : break;
18888 : 1040 : case OACC_SERIAL:
18889 : 2080 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_OACC_SERIAL,
18890 : 1040 : OMP_CLAUSES (expr));
18891 : 1040 : break;
18892 : 626 : case OMP_SECTIONS:
18893 : 626 : stmt = gimple_build_omp_sections (body, OMP_CLAUSES (expr));
18894 : 626 : break;
18895 : 1274 : case OMP_SINGLE:
18896 : 1274 : stmt = gimple_build_omp_single (body, OMP_CLAUSES (expr));
18897 : 1274 : break;
18898 : 214 : case OMP_SCOPE:
18899 : 214 : stmt = gimple_build_omp_scope (body, OMP_CLAUSES (expr));
18900 : 214 : break;
18901 : 12628 : case OMP_TARGET:
18902 : 25256 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_REGION,
18903 : 12628 : OMP_CLAUSES (expr), iterator_loops_seq);
18904 : 12628 : break;
18905 : 1863 : case OMP_TARGET_DATA:
18906 : : /* Put use_device_{ptr,addr} clauses last, as map clauses are supposed
18907 : : to be evaluated before the use_device_{ptr,addr} clauses if they
18908 : : refer to the same variables. */
18909 : 1863 : {
18910 : 1863 : tree use_device_clauses;
18911 : 1863 : tree *pc, *uc = &use_device_clauses;
18912 : 9916 : for (pc = &OMP_CLAUSES (expr); *pc; )
18913 : 8053 : if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
18914 : 8053 : || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
18915 : : {
18916 : 1959 : *uc = *pc;
18917 : 1959 : *pc = OMP_CLAUSE_CHAIN (*pc);
18918 : 1959 : uc = &OMP_CLAUSE_CHAIN (*uc);
18919 : : }
18920 : : else
18921 : 6094 : pc = &OMP_CLAUSE_CHAIN (*pc);
18922 : 1863 : *uc = NULL_TREE;
18923 : 1863 : *pc = use_device_clauses;
18924 : 1863 : stmt = gimple_build_omp_target (body, GF_OMP_TARGET_KIND_DATA,
18925 : 1863 : OMP_CLAUSES (expr));
18926 : : }
18927 : 1863 : break;
18928 : 8774 : case OMP_TEAMS:
18929 : 8774 : stmt = gimple_build_omp_teams (body, OMP_CLAUSES (expr));
18930 : 8774 : if ((ort & ORT_HOST_TEAMS) == ORT_HOST_TEAMS)
18931 : 2625 : gimple_omp_teams_set_host (as_a <gomp_teams *> (stmt), true);
18932 : : break;
18933 : 0 : default:
18934 : 0 : gcc_unreachable ();
18935 : : }
18936 : :
18937 : 38929 : gimplify_seq_add_stmt (pre_p, stmt);
18938 : 38929 : *expr_p = NULL_TREE;
18939 : 38929 : }
18940 : :
18941 : : /* Gimplify the gross structure of OpenACC enter/exit data, update, and OpenMP
18942 : : target update constructs. */
18943 : :
18944 : : static void
18945 : 11935 : gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
18946 : : {
18947 : 11935 : tree expr = *expr_p;
18948 : 11935 : int kind;
18949 : 11935 : gomp_target *stmt;
18950 : 11935 : enum omp_region_type ort = ORT_WORKSHARE;
18951 : :
18952 : 11935 : switch (TREE_CODE (expr))
18953 : : {
18954 : : case OACC_ENTER_DATA:
18955 : : kind = GF_OMP_TARGET_KIND_OACC_ENTER_DATA;
18956 : : ort = ORT_ACC;
18957 : : break;
18958 : : case OACC_EXIT_DATA:
18959 : : kind = GF_OMP_TARGET_KIND_OACC_EXIT_DATA;
18960 : : ort = ORT_ACC;
18961 : : break;
18962 : : case OACC_UPDATE:
18963 : : kind = GF_OMP_TARGET_KIND_OACC_UPDATE;
18964 : : ort = ORT_ACC;
18965 : : break;
18966 : : case OMP_TARGET_UPDATE:
18967 : : kind = GF_OMP_TARGET_KIND_UPDATE;
18968 : : break;
18969 : : case OMP_TARGET_ENTER_DATA:
18970 : : kind = GF_OMP_TARGET_KIND_ENTER_DATA;
18971 : : break;
18972 : : case OMP_TARGET_EXIT_DATA:
18973 : : kind = GF_OMP_TARGET_KIND_EXIT_DATA;
18974 : : break;
18975 : 0 : default:
18976 : 0 : gcc_unreachable ();
18977 : : }
18978 : :
18979 : 11935 : gimple_seq iterator_loops_seq = NULL;
18980 : 11935 : remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr));
18981 : 11935 : build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr),
18982 : : &iterator_loops_seq);
18983 : :
18984 : 11935 : gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
18985 : 11935 : ort, TREE_CODE (expr), &iterator_loops_seq);
18986 : 11935 : gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
18987 : 11935 : TREE_CODE (expr), &iterator_loops_seq);
18988 : 11935 : if (TREE_CODE (expr) == OACC_UPDATE
18989 : 11935 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
18990 : : OMP_CLAUSE_IF_PRESENT))
18991 : : {
18992 : : /* The runtime uses GOMP_MAP_{TO,FROM} to denote the if_present
18993 : : clause. */
18994 : 123 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
18995 : 97 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
18996 : 47 : switch (OMP_CLAUSE_MAP_KIND (c))
18997 : : {
18998 : 14 : case GOMP_MAP_FORCE_TO:
18999 : 14 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO);
19000 : 14 : break;
19001 : 24 : case GOMP_MAP_FORCE_FROM:
19002 : 24 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FROM);
19003 : 24 : break;
19004 : : default:
19005 : : break;
19006 : : }
19007 : : }
19008 : 11909 : else if (TREE_CODE (expr) == OACC_EXIT_DATA
19009 : 11909 : && omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
19010 : : OMP_CLAUSE_FINALIZE))
19011 : : {
19012 : : /* Use GOMP_MAP_DELETE/GOMP_MAP_FORCE_FROM to denote "finalize"
19013 : : semantics. */
19014 : 75 : bool have_clause = false;
19015 : 275 : for (tree c = OMP_STANDALONE_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19016 : 200 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP)
19017 : 117 : switch (OMP_CLAUSE_MAP_KIND (c))
19018 : : {
19019 : 45 : case GOMP_MAP_FROM:
19020 : 45 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_FROM);
19021 : 45 : have_clause = true;
19022 : 45 : break;
19023 : 47 : case GOMP_MAP_RELEASE:
19024 : 47 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_DELETE);
19025 : 47 : have_clause = true;
19026 : 47 : break;
19027 : : case GOMP_MAP_TO_PSET:
19028 : : /* Fortran arrays with descriptors must map that descriptor when
19029 : : doing standalone "attach" operations (in OpenACC). In that
19030 : : case GOMP_MAP_TO_PSET appears by itself with no preceding
19031 : : clause (see trans-openmp.cc:gfc_trans_omp_clauses). */
19032 : : break;
19033 : 2 : case GOMP_MAP_POINTER:
19034 : : /* TODO PR92929: we may see these here, but they'll always follow
19035 : : one of the clauses above, and will be handled by libgomp as
19036 : : one group, so no handling required here. */
19037 : 2 : gcc_assert (have_clause);
19038 : : break;
19039 : 22 : case GOMP_MAP_DETACH:
19040 : 22 : OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_FORCE_DETACH);
19041 : 22 : have_clause = false;
19042 : 22 : break;
19043 : : case GOMP_MAP_STRUCT:
19044 : : case GOMP_MAP_STRUCT_UNORD:
19045 : 22 : have_clause = false;
19046 : : break;
19047 : 0 : default:
19048 : 0 : gcc_unreachable ();
19049 : : }
19050 : : }
19051 : 11935 : stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr),
19052 : : iterator_loops_seq);
19053 : :
19054 : 11935 : gimplify_seq_add_stmt (pre_p, stmt);
19055 : 11935 : *expr_p = NULL_TREE;
19056 : 11935 : }
19057 : :
19058 : : /* A subroutine of gimplify_omp_atomic. The front end is supposed to have
19059 : : stabilized the lhs of the atomic operation as *ADDR. Return true if
19060 : : EXPR is this stabilized form. */
19061 : :
19062 : : static bool
19063 : 36797 : goa_lhs_expr_p (tree expr, tree addr)
19064 : : {
19065 : : /* Also include casts to other type variants. The C front end is fond
19066 : : of adding these for e.g. volatile variables. This is like
19067 : : STRIP_TYPE_NOPS but includes the main variant lookup. */
19068 : 36797 : STRIP_USELESS_TYPE_CONVERSION (expr);
19069 : :
19070 : 36797 : if (INDIRECT_REF_P (expr))
19071 : : {
19072 : 5013 : expr = TREE_OPERAND (expr, 0);
19073 : 5013 : while (expr != addr
19074 : 92 : && (CONVERT_EXPR_P (expr)
19075 : 92 : || TREE_CODE (expr) == NON_LVALUE_EXPR)
19076 : 0 : && TREE_CODE (expr) == TREE_CODE (addr)
19077 : 5013 : && types_compatible_p (TREE_TYPE (expr), TREE_TYPE (addr)))
19078 : : {
19079 : 0 : expr = TREE_OPERAND (expr, 0);
19080 : 0 : addr = TREE_OPERAND (addr, 0);
19081 : : }
19082 : 5013 : if (expr == addr)
19083 : : return true;
19084 : 92 : return (TREE_CODE (addr) == ADDR_EXPR
19085 : 62 : && TREE_CODE (expr) == ADDR_EXPR
19086 : 92 : && TREE_OPERAND (addr, 0) == TREE_OPERAND (expr, 0));
19087 : : }
19088 : 31784 : if (TREE_CODE (addr) == ADDR_EXPR && expr == TREE_OPERAND (addr, 0))
19089 : : return true;
19090 : : return false;
19091 : : }
19092 : :
19093 : : /* Walk *EXPR_P and replace appearances of *LHS_ADDR with LHS_VAR. If an
19094 : : expression does not involve the lhs, evaluate it into a temporary.
19095 : : Return 1 if the lhs appeared as a subexpression, 0 if it did not,
19096 : : or -1 if an error was encountered. */
19097 : :
19098 : : static int
19099 : 36797 : goa_stabilize_expr (tree *expr_p, gimple_seq *pre_p, tree lhs_addr,
19100 : : tree lhs_var, tree &target_expr, bool rhs, int depth)
19101 : : {
19102 : 36797 : tree expr = *expr_p;
19103 : 36797 : int saw_lhs = 0;
19104 : :
19105 : 36797 : if (goa_lhs_expr_p (expr, lhs_addr))
19106 : : {
19107 : 9185 : if (pre_p)
19108 : 8527 : *expr_p = lhs_var;
19109 : 9185 : return 1;
19110 : : }
19111 : 27612 : if (is_gimple_val (expr))
19112 : : return 0;
19113 : :
19114 : : /* Maximum depth of lhs in expression is for the
19115 : : __builtin_clear_padding (...), __builtin_clear_padding (...),
19116 : : __builtin_memcmp (&TARGET_EXPR <lhs, >, ...) == 0 ? ... : lhs; */
19117 : 17284 : if (++depth > 7)
19118 : 16 : goto finish;
19119 : :
19120 : 17268 : switch (TREE_CODE_CLASS (TREE_CODE (expr)))
19121 : : {
19122 : 9654 : case tcc_binary:
19123 : 9654 : case tcc_comparison:
19124 : 9654 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p, lhs_addr,
19125 : : lhs_var, target_expr, true, depth);
19126 : : /* FALLTHRU */
19127 : 11701 : case tcc_unary:
19128 : 11701 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p, lhs_addr,
19129 : : lhs_var, target_expr, true, depth);
19130 : 11701 : break;
19131 : 2982 : case tcc_expression:
19132 : 2982 : switch (TREE_CODE (expr))
19133 : : {
19134 : 836 : case TRUTH_ANDIF_EXPR:
19135 : 836 : case TRUTH_ORIF_EXPR:
19136 : 836 : case TRUTH_AND_EXPR:
19137 : 836 : case TRUTH_OR_EXPR:
19138 : 836 : case TRUTH_XOR_EXPR:
19139 : 836 : case BIT_INSERT_EXPR:
19140 : 836 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19141 : : lhs_addr, lhs_var, target_expr, true,
19142 : : depth);
19143 : : /* FALLTHRU */
19144 : 888 : case TRUTH_NOT_EXPR:
19145 : 888 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19146 : : lhs_addr, lhs_var, target_expr, true,
19147 : : depth);
19148 : 888 : break;
19149 : 550 : case MODIFY_EXPR:
19150 : 550 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19151 : : target_expr, true, depth))
19152 : : break;
19153 : 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19154 : : lhs_addr, lhs_var, target_expr, true,
19155 : : depth);
19156 : 544 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19157 : : lhs_addr, lhs_var, target_expr, false,
19158 : : depth);
19159 : 544 : break;
19160 : : /* FALLTHRU */
19161 : 164 : case ADDR_EXPR:
19162 : 164 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr, lhs_var,
19163 : : target_expr, true, depth))
19164 : : break;
19165 : 138 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19166 : : lhs_addr, lhs_var, target_expr, false,
19167 : : depth);
19168 : 138 : break;
19169 : : case COMPOUND_EXPR:
19170 : : /* Break out any preevaluations from cp_build_modify_expr. */
19171 : 76 : for (; TREE_CODE (expr) == COMPOUND_EXPR;
19172 : 38 : expr = TREE_OPERAND (expr, 1))
19173 : : {
19174 : : /* Special-case __builtin_clear_padding call before
19175 : : __builtin_memcmp. */
19176 : 38 : if (TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
19177 : : {
19178 : 2 : tree fndecl = get_callee_fndecl (TREE_OPERAND (expr, 0));
19179 : 2 : if (fndecl
19180 : 2 : && fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)
19181 : 0 : && VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)))
19182 : 2 : && (!pre_p
19183 : 0 : || goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL,
19184 : : lhs_addr, lhs_var,
19185 : : target_expr, true, depth)))
19186 : : {
19187 : 0 : if (pre_p)
19188 : 0 : *expr_p = expr;
19189 : 0 : saw_lhs = goa_stabilize_expr (&TREE_OPERAND (expr, 0),
19190 : : pre_p, lhs_addr, lhs_var,
19191 : : target_expr, true, depth);
19192 : 0 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1),
19193 : : pre_p, lhs_addr, lhs_var,
19194 : : target_expr, rhs, depth);
19195 : 0 : return saw_lhs;
19196 : : }
19197 : : }
19198 : :
19199 : 38 : if (pre_p)
19200 : 35 : gimplify_stmt (&TREE_OPERAND (expr, 0), pre_p);
19201 : : }
19202 : 38 : if (!pre_p)
19203 : 3 : return goa_stabilize_expr (&expr, pre_p, lhs_addr, lhs_var,
19204 : 3 : target_expr, rhs, depth);
19205 : 35 : *expr_p = expr;
19206 : 35 : return goa_stabilize_expr (expr_p, pre_p, lhs_addr, lhs_var,
19207 : 35 : target_expr, rhs, depth);
19208 : 441 : case COND_EXPR:
19209 : 441 : if (!goa_stabilize_expr (&TREE_OPERAND (expr, 0), NULL, lhs_addr,
19210 : : lhs_var, target_expr, true, depth))
19211 : : break;
19212 : 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19213 : : lhs_addr, lhs_var, target_expr, true,
19214 : : depth);
19215 : 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 1), pre_p,
19216 : : lhs_addr, lhs_var, target_expr, true,
19217 : : depth);
19218 : 428 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 2), pre_p,
19219 : : lhs_addr, lhs_var, target_expr, true,
19220 : : depth);
19221 : 428 : break;
19222 : 880 : case TARGET_EXPR:
19223 : 880 : if (TARGET_EXPR_INITIAL (expr))
19224 : : {
19225 : 880 : if (pre_p && !goa_stabilize_expr (expr_p, NULL, lhs_addr,
19226 : : lhs_var, target_expr, true,
19227 : : depth))
19228 : : break;
19229 : 702 : if (expr == target_expr)
19230 : : saw_lhs = 1;
19231 : : else
19232 : : {
19233 : 702 : saw_lhs = goa_stabilize_expr (&TARGET_EXPR_INITIAL (expr),
19234 : : pre_p, lhs_addr, lhs_var,
19235 : : target_expr, true, depth);
19236 : 702 : if (saw_lhs && target_expr == NULL_TREE && pre_p)
19237 : 26 : target_expr = expr;
19238 : : }
19239 : : }
19240 : : break;
19241 : : default:
19242 : : break;
19243 : : }
19244 : : break;
19245 : 556 : case tcc_reference:
19246 : 556 : if (TREE_CODE (expr) == BIT_FIELD_REF
19247 : 490 : || TREE_CODE (expr) == VIEW_CONVERT_EXPR)
19248 : 362 : saw_lhs |= goa_stabilize_expr (&TREE_OPERAND (expr, 0), pre_p,
19249 : : lhs_addr, lhs_var, target_expr, true,
19250 : : depth);
19251 : : break;
19252 : 58 : case tcc_vl_exp:
19253 : 58 : if (TREE_CODE (expr) == CALL_EXPR)
19254 : : {
19255 : 58 : if (tree fndecl = get_callee_fndecl (expr))
19256 : 58 : if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING,
19257 : : BUILT_IN_MEMCMP))
19258 : : {
19259 : 56 : int nargs = call_expr_nargs (expr);
19260 : 224 : for (int i = 0; i < nargs; i++)
19261 : 168 : saw_lhs |= goa_stabilize_expr (&CALL_EXPR_ARG (expr, i),
19262 : : pre_p, lhs_addr, lhs_var,
19263 : : target_expr, true, depth);
19264 : : }
19265 : : }
19266 : : break;
19267 : : default:
19268 : : break;
19269 : : }
19270 : :
19271 : 17246 : finish:
19272 : 17246 : if (saw_lhs == 0 && pre_p)
19273 : : {
19274 : 3491 : enum gimplify_status gs;
19275 : 3491 : if (TREE_CODE (expr) == CALL_EXPR && VOID_TYPE_P (TREE_TYPE (expr)))
19276 : : {
19277 : 0 : gimplify_stmt (&expr, pre_p);
19278 : 0 : return saw_lhs;
19279 : : }
19280 : 3491 : else if (rhs)
19281 : 3313 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_val, fb_rvalue);
19282 : : else
19283 : 178 : gs = gimplify_expr (expr_p, pre_p, NULL, is_gimple_lvalue, fb_lvalue);
19284 : 3491 : if (gs != GS_ALL_DONE)
19285 : 36797 : saw_lhs = -1;
19286 : : }
19287 : :
19288 : : return saw_lhs;
19289 : : }
19290 : :
19291 : : /* Gimplify an OMP_ATOMIC statement. */
19292 : :
19293 : : static enum gimplify_status
19294 : 10238 : gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p)
19295 : : {
19296 : 10238 : tree addr = TREE_OPERAND (*expr_p, 0);
19297 : 10238 : tree rhs = TREE_CODE (*expr_p) == OMP_ATOMIC_READ
19298 : 10238 : ? NULL : TREE_OPERAND (*expr_p, 1);
19299 : 10238 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
19300 : 10238 : tree tmp_load;
19301 : 10238 : gomp_atomic_load *loadstmt;
19302 : 10238 : gomp_atomic_store *storestmt;
19303 : 10238 : tree target_expr = NULL_TREE;
19304 : :
19305 : 10238 : tmp_load = create_tmp_reg (type);
19306 : 10238 : if (rhs
19307 : 10238 : && goa_stabilize_expr (&rhs, pre_p, addr, tmp_load, target_expr,
19308 : : true, 0) < 0)
19309 : : return GS_ERROR;
19310 : :
19311 : 10238 : if (gimplify_expr (&addr, pre_p, NULL, is_gimple_val, fb_rvalue)
19312 : : != GS_ALL_DONE)
19313 : : return GS_ERROR;
19314 : :
19315 : 10238 : loadstmt = gimple_build_omp_atomic_load (tmp_load, addr,
19316 : 10238 : OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19317 : 10238 : gimplify_seq_add_stmt (pre_p, loadstmt);
19318 : 10238 : if (rhs)
19319 : : {
19320 : : /* BIT_INSERT_EXPR is not valid for non-integral bitfield
19321 : : representatives. Use BIT_FIELD_REF on the lhs instead. */
19322 : 9057 : tree rhsarg = rhs;
19323 : 9057 : if (TREE_CODE (rhs) == COND_EXPR)
19324 : 428 : rhsarg = TREE_OPERAND (rhs, 1);
19325 : 9057 : if (TREE_CODE (rhsarg) == BIT_INSERT_EXPR
19326 : 9057 : && !INTEGRAL_TYPE_P (TREE_TYPE (tmp_load)))
19327 : : {
19328 : 32 : tree bitpos = TREE_OPERAND (rhsarg, 2);
19329 : 32 : tree op1 = TREE_OPERAND (rhsarg, 1);
19330 : 32 : tree bitsize;
19331 : 32 : tree tmp_store = tmp_load;
19332 : 32 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_CAPTURE_OLD)
19333 : 12 : tmp_store = get_initialized_tmp_var (tmp_load, pre_p);
19334 : 32 : if (INTEGRAL_TYPE_P (TREE_TYPE (op1)))
19335 : 32 : bitsize = bitsize_int (TYPE_PRECISION (TREE_TYPE (op1)));
19336 : : else
19337 : 0 : bitsize = TYPE_SIZE (TREE_TYPE (op1));
19338 : 32 : gcc_assert (TREE_OPERAND (rhsarg, 0) == tmp_load);
19339 : 32 : tree t = build2_loc (EXPR_LOCATION (rhsarg),
19340 : : MODIFY_EXPR, void_type_node,
19341 : 32 : build3_loc (EXPR_LOCATION (rhsarg),
19342 : 32 : BIT_FIELD_REF, TREE_TYPE (op1),
19343 : : tmp_store, bitsize, bitpos), op1);
19344 : 32 : if (TREE_CODE (rhs) == COND_EXPR)
19345 : 16 : t = build3_loc (EXPR_LOCATION (rhs), COND_EXPR, void_type_node,
19346 : 16 : TREE_OPERAND (rhs, 0), t, void_node);
19347 : 32 : gimplify_and_add (t, pre_p);
19348 : 32 : rhs = tmp_store;
19349 : : }
19350 : 9057 : bool save_allow_rhs_cond_expr = gimplify_ctxp->allow_rhs_cond_expr;
19351 : 9057 : if (TREE_CODE (rhs) == COND_EXPR)
19352 : 412 : gimplify_ctxp->allow_rhs_cond_expr = true;
19353 : 9057 : enum gimplify_status gs = gimplify_expr (&rhs, pre_p, NULL,
19354 : : is_gimple_val, fb_rvalue);
19355 : 9057 : gimplify_ctxp->allow_rhs_cond_expr = save_allow_rhs_cond_expr;
19356 : 9057 : if (gs != GS_ALL_DONE)
19357 : : return GS_ERROR;
19358 : : }
19359 : :
19360 : 10238 : if (TREE_CODE (*expr_p) == OMP_ATOMIC_READ)
19361 : 1181 : rhs = tmp_load;
19362 : 10238 : storestmt
19363 : 10238 : = gimple_build_omp_atomic_store (rhs, OMP_ATOMIC_MEMORY_ORDER (*expr_p));
19364 : 10238 : if (TREE_CODE (*expr_p) != OMP_ATOMIC_READ && OMP_ATOMIC_WEAK (*expr_p))
19365 : : {
19366 : 37 : gimple_omp_atomic_set_weak (loadstmt);
19367 : 37 : gimple_omp_atomic_set_weak (storestmt);
19368 : : }
19369 : 10238 : gimplify_seq_add_stmt (pre_p, storestmt);
19370 : 10238 : switch (TREE_CODE (*expr_p))
19371 : : {
19372 : 2065 : case OMP_ATOMIC_READ:
19373 : 2065 : case OMP_ATOMIC_CAPTURE_OLD:
19374 : 2065 : *expr_p = tmp_load;
19375 : 2065 : gimple_omp_atomic_set_need_value (loadstmt);
19376 : 2065 : break;
19377 : 868 : case OMP_ATOMIC_CAPTURE_NEW:
19378 : 868 : *expr_p = rhs;
19379 : 868 : gimple_omp_atomic_set_need_value (storestmt);
19380 : 868 : break;
19381 : 7305 : default:
19382 : 7305 : *expr_p = NULL;
19383 : 7305 : break;
19384 : : }
19385 : :
19386 : : return GS_ALL_DONE;
19387 : : }
19388 : :
19389 : : /* Gimplify a TRANSACTION_EXPR. This involves gimplification of the
19390 : : body, and adding some EH bits. */
19391 : :
19392 : : static enum gimplify_status
19393 : 478 : gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
19394 : : {
19395 : 478 : tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
19396 : 478 : gimple *body_stmt;
19397 : 478 : gtransaction *trans_stmt;
19398 : 478 : gimple_seq body = NULL;
19399 : 478 : int subcode = 0;
19400 : :
19401 : : /* Wrap the transaction body in a BIND_EXPR so we have a context
19402 : : where to put decls for OMP. */
19403 : 478 : if (TREE_CODE (tbody) != BIND_EXPR)
19404 : : {
19405 : 439 : tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
19406 : 439 : TREE_SIDE_EFFECTS (bind) = 1;
19407 : 439 : SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
19408 : 439 : TRANSACTION_EXPR_BODY (expr) = bind;
19409 : : }
19410 : :
19411 : 478 : push_gimplify_context ();
19412 : 478 : temp = voidify_wrapper_expr (*expr_p, NULL);
19413 : :
19414 : 478 : body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
19415 : 478 : pop_gimplify_context (body_stmt);
19416 : :
19417 : 478 : trans_stmt = gimple_build_transaction (body);
19418 : 478 : if (TRANSACTION_EXPR_OUTER (expr))
19419 : : subcode = GTMA_IS_OUTER;
19420 : 447 : else if (TRANSACTION_EXPR_RELAXED (expr))
19421 : 81 : subcode = GTMA_IS_RELAXED;
19422 : 478 : gimple_transaction_set_subcode (trans_stmt, subcode);
19423 : :
19424 : 478 : gimplify_seq_add_stmt (pre_p, trans_stmt);
19425 : :
19426 : 478 : if (temp)
19427 : : {
19428 : 76 : *expr_p = temp;
19429 : 76 : return GS_OK;
19430 : : }
19431 : :
19432 : 402 : *expr_p = NULL_TREE;
19433 : 402 : return GS_ALL_DONE;
19434 : : }
19435 : :
19436 : : /* Gimplify an OMP_ORDERED construct. EXPR is the tree version. BODY
19437 : : is the OMP_BODY of the original EXPR (which has already been
19438 : : gimplified so it's not present in the EXPR).
19439 : :
19440 : : Return the gimplified GIMPLE_OMP_ORDERED tuple. */
19441 : :
19442 : : static gimple *
19443 : 1940 : gimplify_omp_ordered (tree expr, gimple_seq body)
19444 : : {
19445 : 1940 : tree c, decls;
19446 : 1940 : int failures = 0;
19447 : 1940 : unsigned int i;
19448 : 1940 : tree source_c = NULL_TREE;
19449 : 1940 : tree sink_c = NULL_TREE;
19450 : :
19451 : 1940 : if (gimplify_omp_ctxp)
19452 : : {
19453 : 3271 : for (c = OMP_ORDERED_CLAUSES (expr); c; c = OMP_CLAUSE_CHAIN (c))
19454 : 1505 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19455 : 1505 : && gimplify_omp_ctxp->loop_iter_var.is_empty ())
19456 : : {
19457 : 74 : error_at (OMP_CLAUSE_LOCATION (c),
19458 : : "%<ordered%> construct with %qs clause must be "
19459 : : "closely nested inside a loop with %<ordered%> clause",
19460 : 74 : OMP_CLAUSE_DOACROSS_DEPEND (c) ? "depend" : "doacross");
19461 : 74 : failures++;
19462 : : }
19463 : 1431 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19464 : 1431 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SINK)
19465 : : {
19466 : 637 : bool fail = false;
19467 : 637 : sink_c = c;
19468 : 637 : if (OMP_CLAUSE_DECL (c) == NULL_TREE)
19469 : 72 : continue; /* omp_cur_iteration - 1 */
19470 : 565 : for (decls = OMP_CLAUSE_DECL (c), i = 0;
19471 : 3191 : decls && TREE_CODE (decls) == TREE_LIST;
19472 : 2626 : decls = TREE_CHAIN (decls), ++i)
19473 : 2626 : if (i >= gimplify_omp_ctxp->loop_iter_var.length () / 2)
19474 : 4 : continue;
19475 : 5244 : else if (TREE_VALUE (decls)
19476 : 2622 : != gimplify_omp_ctxp->loop_iter_var[2 * i])
19477 : : {
19478 : 8 : error_at (OMP_CLAUSE_LOCATION (c),
19479 : : "variable %qE is not an iteration "
19480 : : "of outermost loop %d, expected %qE",
19481 : 8 : TREE_VALUE (decls), i + 1,
19482 : 8 : gimplify_omp_ctxp->loop_iter_var[2 * i]);
19483 : 8 : fail = true;
19484 : 8 : failures++;
19485 : : }
19486 : : else
19487 : 5228 : TREE_VALUE (decls)
19488 : 2614 : = gimplify_omp_ctxp->loop_iter_var[2 * i + 1];
19489 : 1126 : if (!fail && i != gimplify_omp_ctxp->loop_iter_var.length () / 2)
19490 : : {
19491 : 16 : error_at (OMP_CLAUSE_LOCATION (c),
19492 : : "number of variables in %qs clause with "
19493 : : "%<sink%> modifier does not match number of "
19494 : : "iteration variables",
19495 : 16 : OMP_CLAUSE_DOACROSS_DEPEND (c)
19496 : : ? "depend" : "doacross");
19497 : 16 : failures++;
19498 : : }
19499 : : }
19500 : 794 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DOACROSS
19501 : 794 : && OMP_CLAUSE_DOACROSS_KIND (c) == OMP_CLAUSE_DOACROSS_SOURCE)
19502 : : {
19503 : 470 : if (source_c)
19504 : : {
19505 : 4 : error_at (OMP_CLAUSE_LOCATION (c),
19506 : : "more than one %qs clause with %<source%> "
19507 : : "modifier on an %<ordered%> construct",
19508 : 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c)
19509 : : ? "depend" : "doacross");
19510 : 4 : failures++;
19511 : : }
19512 : : else
19513 : : source_c = c;
19514 : : }
19515 : : }
19516 : 1940 : if (source_c && sink_c)
19517 : : {
19518 : 4 : error_at (OMP_CLAUSE_LOCATION (source_c),
19519 : : "%qs clause with %<source%> modifier specified "
19520 : : "together with %qs clauses with %<sink%> modifier "
19521 : : "on the same construct",
19522 : 4 : OMP_CLAUSE_DOACROSS_DEPEND (source_c) ? "depend" : "doacross",
19523 : 4 : OMP_CLAUSE_DOACROSS_DEPEND (sink_c) ? "depend" : "doacross");
19524 : 4 : failures++;
19525 : : }
19526 : :
19527 : 1940 : if (failures)
19528 : 102 : return gimple_build_nop ();
19529 : 1838 : return gimple_build_omp_ordered (body, OMP_ORDERED_CLAUSES (expr));
19530 : : }
19531 : :
19532 : : /* Gimplify an OMP_INTEROP statement. */
19533 : :
19534 : : static enum gimplify_status
19535 : 612 : gimplify_omp_interop (tree *expr_p, gimple_seq *pre_p)
19536 : : {
19537 : 612 : tree expr = *expr_p;
19538 : :
19539 : 612 : gimplify_scan_omp_clauses (&OMP_INTEROP_CLAUSES (expr), pre_p, ORT_TASK,
19540 : : OMP_INTEROP);
19541 : 612 : gimple *stmt = gimple_build_omp_interop (OMP_INTEROP_CLAUSES (expr));
19542 : 612 : gimplify_seq_add_stmt (pre_p, stmt);
19543 : 612 : *expr_p = NULL_TREE;
19544 : 612 : return GS_ALL_DONE;
19545 : : }
19546 : :
19547 : : /* Callback for walk_tree to find an IFN_GOMP_DISPATCH. */
19548 : :
19549 : : static tree
19550 : 3082 : find_ifn_gomp_dispatch (tree *tp, int *, void *modify)
19551 : : {
19552 : 3082 : tree t = *tp;
19553 : :
19554 : 3082 : if (TREE_CODE (t) == CALL_EXPR && CALL_EXPR_IFN (t) == IFN_GOMP_DISPATCH)
19555 : 1408 : return *(tree *) modify ? *(tree *) modify : *tp;
19556 : :
19557 : 2236 : if (TREE_CODE (t) == MODIFY_EXPR)
19558 : 507 : *(tree *) modify = *tp;
19559 : :
19560 : : return NULL_TREE;
19561 : : }
19562 : :
19563 : : /* Gimplify an OMP_DISPATCH construct. */
19564 : :
19565 : : static enum gimplify_status
19566 : 846 : gimplify_omp_dispatch (tree *expr_p, gimple_seq *pre_p)
19567 : : {
19568 : 846 : tree expr = *expr_p;
19569 : 846 : gimple_seq body = NULL;
19570 : :
19571 : 846 : gimplify_scan_omp_clauses (&OMP_DISPATCH_CLAUSES (expr), pre_p, ORT_DISPATCH,
19572 : : OMP_DISPATCH);
19573 : 846 : push_gimplify_context ();
19574 : :
19575 : : // If device clause, adjust ICV
19576 : 846 : tree device
19577 : 846 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_DEVICE);
19578 : : // If no device clause exists but an interop clause with a single list
19579 : : // item, use it to obtain the device number.
19580 : 846 : if (device)
19581 : 272 : device = OMP_CLAUSE_DEVICE_ID (device);
19582 : : else
19583 : : {
19584 : 574 : tree first_interop_obj
19585 : 574 : = omp_find_clause (OMP_DISPATCH_CLAUSES (expr), OMP_CLAUSE_INTEROP);
19586 : 574 : if (first_interop_obj)
19587 : 96 : for (tree c = TREE_CHAIN (first_interop_obj); c; c = TREE_CHAIN (c))
19588 : 8 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_INTEROP)
19589 : : {
19590 : : first_interop_obj = NULL_TREE;
19591 : : break;
19592 : : }
19593 : 95 : if (first_interop_obj)
19594 : : {
19595 : 88 : device = create_tmp_var (integer_type_node);
19596 : 88 : tree c = build_omp_clause (OMP_CLAUSE_LOCATION (first_interop_obj),
19597 : : OMP_CLAUSE_DEVICE);
19598 : 88 : OMP_CLAUSE_DEVICE_ID (c) = device;
19599 : 88 : TREE_CHAIN (c) = TREE_CHAIN (first_interop_obj);
19600 : 88 : TREE_CHAIN (first_interop_obj) = c;
19601 : 88 : first_interop_obj = OMP_CLAUSE_DECL (first_interop_obj);
19602 : : /* device = omp_get_interop_int (obj, omp_ipr_device_num, NULL); */
19603 : 88 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_INTEROP_INT);
19604 : 88 : fn = build_call_expr (fn, 3, first_interop_obj,
19605 : : build_int_cst (integer_type_node, -5),
19606 : : null_pointer_node);
19607 : 88 : gimplify_assign (device, fold_convert (integer_type_node, fn), &body);
19608 : : }
19609 : : }
19610 : 846 : tree saved_device_icv = NULL_TREE;
19611 : 846 : if (device
19612 : 846 : && (TREE_CODE (device) != INTEGER_CST
19613 : 703 : || !wi::eq_p (wi::to_wide (device), -1 /* omp_initial_device */)))
19614 : : {
19615 : : // Save current default-device-var ICV
19616 : 360 : saved_device_icv = create_tmp_var (integer_type_node);
19617 : 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_GET_DEFAULT_DEVICE);
19618 : 360 : gcall *call = gimple_build_call (fn, 0);
19619 : 360 : gimple_call_set_lhs (call, saved_device_icv);
19620 : 360 : gimplify_seq_add_stmt (&body, call);
19621 : :
19622 : : // Set default device
19623 : 360 : fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19624 : 360 : call = gimple_build_call (fn, 1, device);
19625 : 360 : gimplify_seq_add_stmt (&body, call);
19626 : : }
19627 : :
19628 : : // If the novariants and nocontext clauses are not compile-time constants,
19629 : : // we need to generate code for all possible cases:
19630 : : // if (novariants) // implies nocontext
19631 : : // base()
19632 : : // else if (nocontext)
19633 : : // variant1()
19634 : : // else
19635 : : // variant2()
19636 : 846 : tree *dispatch_body_p = &OMP_DISPATCH_BODY (expr);
19637 : 846 : if (TREE_CODE (*dispatch_body_p) == BIND_EXPR)
19638 : 28 : dispatch_body_p = &BIND_EXPR_BODY (*dispatch_body_p);
19639 : 846 : tree dispatch_body = *dispatch_body_p;
19640 : :
19641 : : // Look for IFN_GOMP_DISPATCH and extract the base function call
19642 : 846 : tree base_call_expr = NULL_TREE;
19643 : 846 : if (TREE_CODE (dispatch_body) == STATEMENT_LIST)
19644 : 243 : for (tree_stmt_iterator tsi = tsi_start (dispatch_body); !tsi_end_p (tsi);
19645 : 187 : tsi_next (&tsi))
19646 : : {
19647 : 243 : tree modify = NULL_TREE;
19648 : 243 : tree stmt = tsi_stmt (tsi);
19649 : 243 : base_call_expr
19650 : 243 : = walk_tree (&stmt, find_ifn_gomp_dispatch, &modify, NULL);
19651 : 243 : if (base_call_expr != NULL_TREE)
19652 : : break;
19653 : : }
19654 : : else
19655 : : {
19656 : 790 : tree modify = NULL_TREE;
19657 : 790 : base_call_expr
19658 : 790 : = walk_tree (dispatch_body_p, find_ifn_gomp_dispatch, &modify, NULL);
19659 : : }
19660 : 846 : gcc_assert (base_call_expr != NULL_TREE);
19661 : :
19662 : 846 : tree dst = NULL_TREE;
19663 : 846 : if (TREE_CODE (base_call_expr) == MODIFY_EXPR)
19664 : : {
19665 : 284 : dst = TREE_OPERAND (base_call_expr, 0);
19666 : 284 : base_call_expr = TREE_OPERAND (base_call_expr, 1);
19667 : : }
19668 : :
19669 : 874 : while (TREE_CODE (base_call_expr) == FLOAT_EXPR
19670 : : || TREE_CODE (base_call_expr) == CONVERT_EXPR
19671 : : || TREE_CODE (base_call_expr) == COMPLEX_EXPR
19672 : : || TREE_CODE (base_call_expr) == INDIRECT_REF
19673 : 874 : || TREE_CODE (base_call_expr) == NOP_EXPR)
19674 : 28 : base_call_expr = TREE_OPERAND (base_call_expr, 0);
19675 : :
19676 : 846 : gcc_assert (CALL_EXPR_IFN (base_call_expr) == IFN_GOMP_DISPATCH);
19677 : 846 : base_call_expr = CALL_EXPR_ARG (base_call_expr, 0);
19678 : :
19679 : 846 : tree base_fndecl = get_callee_fndecl (base_call_expr);
19680 : 846 : if (base_fndecl != NULL_TREE)
19681 : : {
19682 : 838 : if (DECL_VIRTUAL_P (base_fndecl))
19683 : : {
19684 : 6 : error_at (
19685 : 3 : EXPR_LOCATION (base_call_expr),
19686 : : "%qD is a virtual function but only a direct call is allowed "
19687 : : "in a dispatch construct",
19688 : 3 : DECL_NAME (base_fndecl));
19689 : : }
19690 : :
19691 : : /* We are not actually going to expand the variant call or use
19692 : : the result of omp_get_dynamic candidates here; only check that
19693 : : it does not trivially resolve to a call to the base function
19694 : : so that we can avoid some extra work in building code that's
19695 : : not needed in that case. */
19696 : 838 : tree construct_context = omp_get_construct_context ();
19697 : 838 : vec<struct omp_variant> all_candidates
19698 : 838 : = omp_declare_variant_candidates (base_fndecl, construct_context);
19699 : 838 : gcc_assert (!all_candidates.is_empty ());
19700 : 838 : vec<struct omp_variant> candidates
19701 : 838 : = omp_get_dynamic_candidates (all_candidates, construct_context);
19702 : 838 : tree variant_fndecl
19703 : 1664 : = (candidates.length () == 1 ? candidates[0].alternative : NULL_TREE);
19704 : :
19705 : 838 : if (base_fndecl != variant_fndecl
19706 : 838 : && (omp_has_novariants () == -1 || omp_has_nocontext () == -1))
19707 : : {
19708 : 22 : tree novariants_clause = NULL_TREE, nocontext_clause = NULL_TREE,
19709 : 22 : novariants_cond = NULL_TREE, nocontext_cond = NULL_TREE;
19710 : 59 : for (tree c = OMP_DISPATCH_CLAUSES (expr); c; c = TREE_CHAIN (c))
19711 : : {
19712 : 37 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOVARIANTS
19713 : 37 : && !integer_zerop (OMP_CLAUSE_NOVARIANTS_EXPR (c)))
19714 : : {
19715 : 16 : gcc_assert (novariants_cond == NULL_TREE);
19716 : 16 : novariants_clause = c;
19717 : 16 : novariants_cond = OMP_CLAUSE_NOVARIANTS_EXPR (c);
19718 : : }
19719 : 21 : else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOCONTEXT
19720 : 21 : && !integer_zerop (OMP_CLAUSE_NOCONTEXT_EXPR (c)))
19721 : : {
19722 : 16 : gcc_assert (nocontext_cond == NULL_TREE);
19723 : 16 : nocontext_clause = c;
19724 : 16 : nocontext_cond = OMP_CLAUSE_NOCONTEXT_EXPR (c);
19725 : : }
19726 : : }
19727 : 22 : gcc_assert (novariants_cond != NULL_TREE
19728 : : || nocontext_cond != NULL_TREE);
19729 : :
19730 : 22 : enum gimplify_status ret
19731 : 22 : = gimplify_expr (&novariants_cond, &body, NULL, is_gimple_val,
19732 : : fb_rvalue);
19733 : 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19734 : 0 : return ret;
19735 : 22 : ret = gimplify_expr (&nocontext_cond, &body, NULL, is_gimple_val,
19736 : : fb_rvalue);
19737 : 22 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19738 : : return ret;
19739 : :
19740 : 22 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19741 : :
19742 : 22 : if (novariants_cond != NULL_TREE)
19743 : : {
19744 : 16 : tree base_label = create_artificial_label (UNKNOWN_LOCATION);
19745 : 16 : tree cond_label = create_artificial_label (UNKNOWN_LOCATION);
19746 : 16 : gcond *novariants_cond_stmt
19747 : 16 : = gimple_build_cond_from_tree (novariants_cond, base_label,
19748 : : cond_label);
19749 : 16 : gimplify_seq_add_stmt (&body, novariants_cond_stmt);
19750 : :
19751 : 16 : gimplify_seq_add_stmt (&body, gimple_build_label (base_label));
19752 : 16 : tree base_call_expr2 = copy_node (base_call_expr);
19753 : 16 : base_call_expr2
19754 : 16 : = build_call_expr_internal_loc (EXPR_LOCATION (base_call_expr2),
19755 : : IFN_GOMP_DISPATCH,
19756 : 16 : TREE_TYPE (base_call_expr2), 1,
19757 : : base_call_expr2);
19758 : 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19759 : : {
19760 : 16 : base_call_expr2 = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19761 : : base_call_expr2);
19762 : : }
19763 : 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19764 : 16 : = boolean_true_node;
19765 : 16 : gimplify_and_add (base_call_expr2, &body);
19766 : 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19767 : :
19768 : 16 : OMP_CLAUSE_NOVARIANTS_EXPR (novariants_clause)
19769 : 16 : = boolean_false_node;
19770 : 16 : gimplify_seq_add_stmt (&body, gimple_build_label (cond_label));
19771 : : }
19772 : :
19773 : 22 : if (nocontext_cond != NULL_TREE)
19774 : : {
19775 : 16 : tree variant1_label = create_artificial_label (UNKNOWN_LOCATION);
19776 : 16 : tree variant2_label = create_artificial_label (UNKNOWN_LOCATION);
19777 : 16 : gcond *nocontext_cond_stmt
19778 : 16 : = gimple_build_cond_from_tree (nocontext_cond, variant1_label,
19779 : : variant2_label);
19780 : 16 : gimplify_seq_add_stmt (&body, nocontext_cond_stmt);
19781 : :
19782 : 32 : gimplify_seq_add_stmt (&body,
19783 : 16 : gimple_build_label (variant1_label));
19784 : 16 : tree variant_call_expr = copy_node (base_call_expr);
19785 : 32 : variant_call_expr = build_call_expr_internal_loc (
19786 : 16 : EXPR_LOCATION (variant_call_expr), IFN_GOMP_DISPATCH,
19787 : 16 : TREE_TYPE (variant_call_expr), 1, variant_call_expr);
19788 : 16 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19789 : : {
19790 : 16 : variant_call_expr = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst,
19791 : : variant_call_expr);
19792 : : }
19793 : 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_true_node;
19794 : 16 : gimplify_and_add (variant_call_expr, &body);
19795 : 16 : gimplify_seq_add_stmt (&body, gimple_build_goto (end_label));
19796 : 16 : OMP_CLAUSE_NOCONTEXT_EXPR (nocontext_clause) = boolean_false_node;
19797 : 32 : gimplify_seq_add_stmt (&body,
19798 : 16 : gimple_build_label (variant2_label));
19799 : : }
19800 : :
19801 : 22 : tree variant_call_expr = base_call_expr;
19802 : 22 : variant_call_expr
19803 : 22 : = build_call_expr_internal_loc (EXPR_LOCATION (variant_call_expr),
19804 : : IFN_GOMP_DISPATCH,
19805 : 22 : TREE_TYPE (variant_call_expr), 1,
19806 : : variant_call_expr);
19807 : 22 : if (TREE_CODE (dispatch_body) == MODIFY_EXPR)
19808 : : {
19809 : 22 : variant_call_expr
19810 : 22 : = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, variant_call_expr);
19811 : : }
19812 : 22 : gimplify_and_add (variant_call_expr, &body);
19813 : 22 : gimplify_seq_add_stmt (&body, gimple_build_label (end_label));
19814 : : }
19815 : : else
19816 : 816 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19817 : : }
19818 : : else
19819 : 8 : gimplify_and_add (OMP_DISPATCH_BODY (expr), &body);
19820 : :
19821 : : // Restore default-device-var ICV
19822 : 846 : if (saved_device_icv != NULL_TREE)
19823 : : {
19824 : 360 : tree fn = builtin_decl_explicit (BUILT_IN_OMP_SET_DEFAULT_DEVICE);
19825 : 360 : gcall *call = gimple_build_call (fn, 1, saved_device_icv);
19826 : 360 : gimplify_seq_add_stmt (&body, call);
19827 : : }
19828 : :
19829 : : // Wrap dispatch body into a bind
19830 : 846 : gimple *bind = gimple_build_bind (NULL_TREE, body, NULL_TREE);
19831 : 846 : pop_gimplify_context (bind);
19832 : :
19833 : : // Manually tear down context created by gimplify_scan_omp_clauses to avoid a
19834 : : // call to gimplify_adjust_omp_clauses
19835 : 846 : gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
19836 : 846 : if (ctx != NULL)
19837 : : {
19838 : 846 : gcc_assert (ctx->code == OMP_DISPATCH);
19839 : 846 : gimplify_omp_ctxp = ctx->outer_context;
19840 : 846 : delete_omp_context (ctx);
19841 : : }
19842 : :
19843 : : // Remove nowait as it has no effect on dispatch (OpenMP 5.2), device as it
19844 : : // has been handled above, and depend as the front end handled it by inserting
19845 : : // taskwait.
19846 : 846 : tree *dispatch_clauses_ptr = &OMP_DISPATCH_CLAUSES (expr);
19847 : 1433 : for (tree c = *dispatch_clauses_ptr; c; c = *dispatch_clauses_ptr)
19848 : : {
19849 : 985 : if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NOWAIT
19850 : : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
19851 : : || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE)
19852 : : {
19853 : 398 : *dispatch_clauses_ptr = OMP_CLAUSE_CHAIN (c);
19854 : 398 : break;
19855 : : }
19856 : : else
19857 : 587 : dispatch_clauses_ptr = &OMP_CLAUSE_CHAIN (c);
19858 : : }
19859 : :
19860 : 846 : gimple *stmt = gimple_build_omp_dispatch (bind, OMP_DISPATCH_CLAUSES (expr));
19861 : 846 : gimplify_seq_add_stmt (pre_p, stmt);
19862 : 846 : *expr_p = NULL_TREE;
19863 : 846 : return GS_ALL_DONE;
19864 : : }
19865 : :
19866 : : /* Expand a metadirective that has been resolved at gimplification time
19867 : : into the candidate directive variants in CANDIDATES. */
19868 : :
19869 : : static enum gimplify_status
19870 : 170 : expand_omp_metadirective (vec<struct omp_variant> &candidates,
19871 : : gimple_seq *pre_p)
19872 : : {
19873 : 170 : auto_vec<tree> selectors;
19874 : 170 : auto_vec<tree> directive_labels;
19875 : 170 : auto_vec<gimple_seq> directive_bodies;
19876 : 170 : tree body_label = NULL_TREE;
19877 : 170 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19878 : :
19879 : : /* Construct bodies for each candidate. */
19880 : 415 : for (unsigned i = 0; i < candidates.length(); i++)
19881 : : {
19882 : 245 : struct omp_variant &candidate = candidates[i];
19883 : 245 : gimple_seq body = NULL;
19884 : :
19885 : 245 : selectors.safe_push (omp_dynamic_cond (candidate.selector,
19886 : : find_supercontext ()));
19887 : 245 : directive_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
19888 : :
19889 : 245 : gimplify_seq_add_stmt (&body,
19890 : 245 : gimple_build_label (directive_labels.last ()));
19891 : 245 : if (candidate.alternative != NULL_TREE)
19892 : 245 : gimplify_stmt (&candidate.alternative, &body);
19893 : 245 : if (candidate.body != NULL_TREE)
19894 : : {
19895 : 35 : if (body_label != NULL_TREE)
19896 : 0 : gimplify_seq_add_stmt (&body, gimple_build_goto (body_label));
19897 : : else
19898 : : {
19899 : 35 : body_label = create_artificial_label (UNKNOWN_LOCATION);
19900 : 35 : gimplify_seq_add_stmt (&body, gimple_build_label (body_label));
19901 : 35 : gimplify_stmt (&candidate.body, &body);
19902 : : }
19903 : : }
19904 : :
19905 : 245 : directive_bodies.safe_push (body);
19906 : : }
19907 : :
19908 : 170 : auto_vec<tree> cond_labels;
19909 : :
19910 : 170 : cond_labels.safe_push (NULL_TREE);
19911 : 376 : for (unsigned i = 1; i < candidates.length () - 1; i++)
19912 : 18 : cond_labels.safe_push (create_artificial_label (UNKNOWN_LOCATION));
19913 : 170 : if (candidates.length () > 1)
19914 : 57 : cond_labels.safe_push (directive_labels.last ());
19915 : :
19916 : : /* Generate conditionals to test each dynamic selector in turn, executing
19917 : : the directive candidate if successful. */
19918 : 490 : for (unsigned i = 0; i < candidates.length () - 1; i++)
19919 : : {
19920 : 75 : if (i != 0)
19921 : 18 : gimplify_seq_add_stmt (pre_p, gimple_build_label (cond_labels [i]));
19922 : :
19923 : 75 : enum gimplify_status ret = gimplify_expr (&selectors[i], pre_p, NULL,
19924 : : is_gimple_val, fb_rvalue);
19925 : 75 : if (ret == GS_ERROR || ret == GS_UNHANDLED)
19926 : : return ret;
19927 : :
19928 : 75 : gcond *cond_stmt
19929 : 75 : = gimple_build_cond_from_tree (selectors[i], directive_labels[i],
19930 : 75 : cond_labels[i + 1]);
19931 : :
19932 : 75 : gimplify_seq_add_stmt (pre_p, cond_stmt);
19933 : 75 : gimplify_seq_add_seq (pre_p, directive_bodies[i]);
19934 : 75 : gimplify_seq_add_stmt (pre_p, gimple_build_goto (end_label));
19935 : : }
19936 : :
19937 : 170 : gimplify_seq_add_seq (pre_p, directive_bodies.last ());
19938 : 170 : gimplify_seq_add_stmt (pre_p, gimple_build_label (end_label));
19939 : :
19940 : 170 : return GS_ALL_DONE;
19941 : 170 : }
19942 : :
19943 : : /* Expand a variant construct that requires late resolution in the ompdevlow
19944 : : pass. It's a bit easier to do this in tree form and then gimplify that,
19945 : : than to emit gimple. The output is going to look something like:
19946 : :
19947 : : switch_var = OMP_NEXT_VARIANT (0, state);
19948 : : loop_label:
19949 : : switch (switch_var)
19950 : : {
19951 : : case 1:
19952 : : if (dynamic_selector_predicate_1)
19953 : : {
19954 : : alternative_1;
19955 : : goto end_label;
19956 : : }
19957 : : else
19958 : : {
19959 : : switch_var = OMP_NEXT_VARIANT (1, state);
19960 : : goto loop_label;
19961 : : }
19962 : : case 2:
19963 : : ...
19964 : : }
19965 : : end_label:
19966 : :
19967 : : OMP_NEXT_VARIANT is a magic cookie that is replaced with the switch variable
19968 : : index of the next variant to try, after late resolution. */
19969 : :
19970 : : static tree
19971 : 16 : expand_late_variant_directive (vec<struct omp_variant> all_candidates,
19972 : : tree construct_context)
19973 : : {
19974 : 16 : tree body_label = NULL_TREE;
19975 : 16 : tree standalone_body = NULL_TREE;
19976 : 16 : tree loop_label = create_artificial_label (UNKNOWN_LOCATION);
19977 : 16 : tree end_label = create_artificial_label (UNKNOWN_LOCATION);
19978 : 32 : tree selectors = make_tree_vec (all_candidates.length ());
19979 : 16 : tree switch_body = NULL_TREE;
19980 : 16 : tree switch_var = create_tmp_var (integer_type_node, "variant");
19981 : 16 : tree state = tree_cons (NULL_TREE, construct_context, selectors);
19982 : :
19983 : 92 : for (unsigned int i = 0; i < all_candidates.length (); i++)
19984 : : {
19985 : 76 : tree selector = all_candidates[i].selector;
19986 : 76 : tree alternative = all_candidates[i].alternative;
19987 : 76 : tree body = all_candidates[i].body;
19988 : 76 : TREE_VEC_ELT (selectors, i) = selector;
19989 : :
19990 : : /* Case label. Numbering is 1-based. */
19991 : 76 : tree case_val = build_int_cst (integer_type_node, i + 1);
19992 : 76 : tree case_label
19993 : 76 : = build_case_label (case_val, NULL_TREE,
19994 : : create_artificial_label (UNKNOWN_LOCATION));
19995 : 76 : append_to_statement_list (case_label, &switch_body);
19996 : :
19997 : : /* The actual body of the variant. */
19998 : 76 : tree variant_body = NULL_TREE;
19999 : 76 : append_to_statement_list (alternative, &variant_body);
20000 : :
20001 : 76 : if (body != NULL_TREE)
20002 : : {
20003 : 0 : if (standalone_body == NULL)
20004 : : {
20005 : 0 : standalone_body = body;
20006 : 0 : body_label = create_artificial_label (UNKNOWN_LOCATION);
20007 : : }
20008 : 0 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20009 : : body_label),
20010 : : &variant_body);
20011 : : }
20012 : : else
20013 : 76 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20014 : : end_label),
20015 : : &variant_body);
20016 : :
20017 : : /* If this is a dynamic selector, wrap variant_body with a conditional.
20018 : : If the predicate doesn't match, the else clause sets switch_var and
20019 : : jumps to loop_var to try again. */
20020 : 76 : tree dynamic_selector = omp_dynamic_cond (selector, find_supercontext ());
20021 : 76 : if (dynamic_selector)
20022 : : {
20023 : 20 : tree else_stmt = NULL_TREE;
20024 : 20 : tree next = build2 (OMP_NEXT_VARIANT, integer_type_node,
20025 : : case_val, state);
20026 : 20 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20027 : : switch_var, next),
20028 : : &else_stmt);
20029 : 20 : append_to_statement_list (build1 (GOTO_EXPR, void_type_node,
20030 : : loop_label),
20031 : : &else_stmt);
20032 : 20 : variant_body = build3 (COND_EXPR, void_type_node, dynamic_selector,
20033 : : variant_body, else_stmt);
20034 : : }
20035 : 76 : append_to_statement_list (variant_body, &switch_body);
20036 : : }
20037 : :
20038 : : /* Put it all together. */
20039 : 16 : tree result = NULL_TREE;
20040 : 16 : tree first = build2 (OMP_NEXT_VARIANT, integer_type_node, integer_zero_node,
20041 : : state);
20042 : 16 : append_to_statement_list (build2 (MODIFY_EXPR, integer_type_node,
20043 : : switch_var, first),
20044 : : &result);
20045 : 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, loop_label),
20046 : : &result);
20047 : 16 : append_to_statement_list (build2 (SWITCH_EXPR, integer_type_node,
20048 : : switch_var, switch_body),
20049 : : &result);
20050 : 16 : if (standalone_body)
20051 : : {
20052 : 0 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node,
20053 : : body_label),
20054 : : &result);
20055 : 0 : append_to_statement_list (standalone_body, &result);
20056 : : }
20057 : 16 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, end_label),
20058 : : &result);
20059 : 16 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
20060 : 16 : return result;
20061 : : }
20062 : :
20063 : :
20064 : : /* Gimplify an OMP_METADIRECTIVE construct. EXPR is the tree version.
20065 : : The metadirective will be resolved at this point if possible, otherwise
20066 : : a GIMPLE_OMP_VARIANT_CONSTRUCT is created. */
20067 : :
20068 : : static enum gimplify_status
20069 : 174 : gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *,
20070 : : bool (*) (tree), fallback_t)
20071 : : {
20072 : : /* Try to resolve the metadirective. */
20073 : 174 : tree construct_context = omp_get_construct_context ();
20074 : 174 : vec<struct omp_variant> all_candidates
20075 : 174 : = omp_metadirective_candidates (*expr_p, construct_context);
20076 : 174 : vec<struct omp_variant> candidates
20077 : 174 : = omp_get_dynamic_candidates (all_candidates, construct_context);
20078 : 174 : if (!candidates.is_empty ())
20079 : 170 : return expand_omp_metadirective (candidates, pre_p);
20080 : :
20081 : : /* The metadirective cannot be resolved yet. Turn it into a loop with
20082 : : a nested switch statement, using OMP_NEXT_VARIANT to set the control
20083 : : variable for the switch. */
20084 : 4 : *expr_p = expand_late_variant_directive (all_candidates, construct_context);
20085 : 4 : return GS_OK;
20086 : : }
20087 : :
20088 : : /* Gimplify an OMP_DECLARE_MAPPER node (by just removing it). */
20089 : :
20090 : : static enum gimplify_status
20091 : 0 : gimplify_omp_declare_mapper (tree *expr_p)
20092 : : {
20093 : 0 : *expr_p = NULL_TREE;
20094 : 0 : return GS_ALL_DONE;
20095 : : }
20096 : :
20097 : : /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the
20098 : : expression produces a value to be used as an operand inside a GIMPLE
20099 : : statement, the value will be stored back in *EXPR_P. This value will
20100 : : be a tree of class tcc_declaration, tcc_constant, tcc_reference or
20101 : : an SSA_NAME. The corresponding sequence of GIMPLE statements is
20102 : : emitted in PRE_P and POST_P.
20103 : :
20104 : : Additionally, this process may overwrite parts of the input
20105 : : expression during gimplification. Ideally, it should be
20106 : : possible to do non-destructive gimplification.
20107 : :
20108 : : EXPR_P points to the GENERIC expression to convert to GIMPLE. If
20109 : : the expression needs to evaluate to a value to be used as
20110 : : an operand in a GIMPLE statement, this value will be stored in
20111 : : *EXPR_P on exit. This happens when the caller specifies one
20112 : : of fb_lvalue or fb_rvalue fallback flags.
20113 : :
20114 : : PRE_P will contain the sequence of GIMPLE statements corresponding
20115 : : to the evaluation of EXPR and all the side-effects that must
20116 : : be executed before the main expression. On exit, the last
20117 : : statement of PRE_P is the core statement being gimplified. For
20118 : : instance, when gimplifying 'if (++a)' the last statement in
20119 : : PRE_P will be 'if (t.1)' where t.1 is the result of
20120 : : pre-incrementing 'a'.
20121 : :
20122 : : POST_P will contain the sequence of GIMPLE statements corresponding
20123 : : to the evaluation of all the side-effects that must be executed
20124 : : after the main expression. If this is NULL, the post
20125 : : side-effects are stored at the end of PRE_P.
20126 : :
20127 : : The reason why the output is split in two is to handle post
20128 : : side-effects explicitly. In some cases, an expression may have
20129 : : inner and outer post side-effects which need to be emitted in
20130 : : an order different from the one given by the recursive
20131 : : traversal. For instance, for the expression (*p--)++ the post
20132 : : side-effects of '--' must actually occur *after* the post
20133 : : side-effects of '++'. However, gimplification will first visit
20134 : : the inner expression, so if a separate POST sequence was not
20135 : : used, the resulting sequence would be:
20136 : :
20137 : : 1 t.1 = *p
20138 : : 2 p = p - 1
20139 : : 3 t.2 = t.1 + 1
20140 : : 4 *p = t.2
20141 : :
20142 : : However, the post-decrement operation in line #2 must not be
20143 : : evaluated until after the store to *p at line #4, so the
20144 : : correct sequence should be:
20145 : :
20146 : : 1 t.1 = *p
20147 : : 2 t.2 = t.1 + 1
20148 : : 3 *p = t.2
20149 : : 4 p = p - 1
20150 : :
20151 : : So, by specifying a separate post queue, it is possible
20152 : : to emit the post side-effects in the correct order.
20153 : : If POST_P is NULL, an internal queue will be used. Before
20154 : : returning to the caller, the sequence POST_P is appended to
20155 : : the main output sequence PRE_P.
20156 : :
20157 : : GIMPLE_TEST_F points to a function that takes a tree T and
20158 : : returns nonzero if T is in the GIMPLE form requested by the
20159 : : caller. The GIMPLE predicates are in gimple.cc.
20160 : :
20161 : : FALLBACK tells the function what sort of a temporary we want if
20162 : : gimplification cannot produce an expression that complies with
20163 : : GIMPLE_TEST_F.
20164 : :
20165 : : fb_none means that no temporary should be generated
20166 : : fb_rvalue means that an rvalue is OK to generate
20167 : : fb_lvalue means that an lvalue is OK to generate
20168 : : fb_either means that either is OK, but an lvalue is preferable.
20169 : : fb_mayfail means that gimplification may fail (in which case
20170 : : GS_ERROR will be returned)
20171 : :
20172 : : The return value is either GS_ERROR or GS_ALL_DONE, since this
20173 : : function iterates until EXPR is completely gimplified or an error
20174 : : occurs. */
20175 : :
20176 : : enum gimplify_status
20177 : 517489992 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
20178 : : bool (*gimple_test_f) (tree), fallback_t fallback)
20179 : : {
20180 : 517489992 : tree tmp;
20181 : 517489992 : gimple_seq internal_pre = NULL;
20182 : 517489992 : gimple_seq internal_post = NULL;
20183 : 517489992 : tree save_expr;
20184 : 517489992 : bool is_statement;
20185 : 517489992 : location_t saved_location;
20186 : 517489992 : enum gimplify_status ret;
20187 : 517489992 : gimple_stmt_iterator pre_last_gsi, post_last_gsi;
20188 : 517489992 : tree label;
20189 : :
20190 : 517489992 : save_expr = *expr_p;
20191 : 517489992 : if (save_expr == NULL_TREE)
20192 : : return GS_ALL_DONE;
20193 : :
20194 : : /* If we are gimplifying a top-level statement, PRE_P must be valid. */
20195 : 465940588 : is_statement = gimple_test_f == is_gimple_stmt;
20196 : 465940588 : if (is_statement)
20197 : 101119288 : gcc_assert (pre_p);
20198 : :
20199 : : /* Consistency checks. */
20200 : 465940588 : if (gimple_test_f == is_gimple_reg)
20201 : 6386251 : gcc_assert (fallback & (fb_rvalue | fb_lvalue));
20202 : 459554337 : else if (gimple_test_f == is_gimple_val
20203 : 339343149 : || gimple_test_f == is_gimple_call_addr
20204 : 322887492 : || gimple_test_f == is_gimple_condexpr_for_cond
20205 : 317310649 : || gimple_test_f == is_gimple_mem_rhs
20206 : 317167834 : || gimple_test_f == is_gimple_mem_rhs_or_call
20207 : 305843304 : || gimple_test_f == is_gimple_reg_rhs
20208 : 305236984 : || gimple_test_f == is_gimple_reg_rhs_or_call
20209 : 233602531 : || gimple_test_f == is_gimple_asm_val
20210 : 233563636 : || gimple_test_f == is_gimple_mem_ref_addr)
20211 : 241558239 : gcc_assert (fallback & fb_rvalue);
20212 : 217996098 : else if (gimple_test_f == is_gimple_min_lval
20213 : 187947537 : || gimple_test_f == is_gimple_lvalue)
20214 : 83479297 : gcc_assert (fallback & fb_lvalue);
20215 : 134516801 : else if (gimple_test_f == is_gimple_addressable)
20216 : 33397513 : gcc_assert (fallback & fb_either);
20217 : 101119288 : else if (gimple_test_f == is_gimple_stmt)
20218 : 101119288 : gcc_assert (fallback == fb_none);
20219 : : else
20220 : : {
20221 : : /* We should have recognized the GIMPLE_TEST_F predicate to
20222 : : know what kind of fallback to use in case a temporary is
20223 : : needed to hold the value or address of *EXPR_P. */
20224 : 0 : gcc_unreachable ();
20225 : : }
20226 : :
20227 : : /* We used to check the predicate here and return immediately if it
20228 : : succeeds. This is wrong; the design is for gimplification to be
20229 : : idempotent, and for the predicates to only test for valid forms, not
20230 : : whether they are fully simplified. */
20231 : 465940588 : if (pre_p == NULL)
20232 : 0 : pre_p = &internal_pre;
20233 : :
20234 : 465940588 : if (post_p == NULL)
20235 : 187853205 : post_p = &internal_post;
20236 : :
20237 : : /* Remember the last statements added to PRE_P and POST_P. Every
20238 : : new statement added by the gimplification helpers needs to be
20239 : : annotated with location information. To centralize the
20240 : : responsibility, we remember the last statement that had been
20241 : : added to both queues before gimplifying *EXPR_P. If
20242 : : gimplification produces new statements in PRE_P and POST_P, those
20243 : : statements will be annotated with the same location information
20244 : : as *EXPR_P. */
20245 : 465940588 : pre_last_gsi = gsi_last (*pre_p);
20246 : 465940588 : post_last_gsi = gsi_last (*post_p);
20247 : :
20248 : 465940588 : saved_location = input_location;
20249 : 465940588 : if (save_expr != error_mark_node
20250 : 465940588 : && EXPR_HAS_LOCATION (*expr_p))
20251 : 174444658 : input_location = EXPR_LOCATION (*expr_p);
20252 : :
20253 : : /* Loop over the specific gimplifiers until the toplevel node
20254 : : remains the same. */
20255 : 484434000 : do
20256 : : {
20257 : : /* Strip away as many useless type conversions as possible
20258 : : at the toplevel. */
20259 : 484434000 : STRIP_USELESS_TYPE_CONVERSION (*expr_p);
20260 : :
20261 : : /* Remember the expr. */
20262 : 484434000 : save_expr = *expr_p;
20263 : :
20264 : : /* Die, die, die, my darling. */
20265 : 484434000 : if (error_operand_p (save_expr))
20266 : : {
20267 : : ret = GS_ERROR;
20268 : : break;
20269 : : }
20270 : :
20271 : : /* Do any language-specific gimplification. */
20272 : 484430306 : ret = ((enum gimplify_status)
20273 : 484430306 : lang_hooks.gimplify_expr (expr_p, pre_p, post_p));
20274 : 484430306 : if (ret == GS_OK)
20275 : : {
20276 : 29145659 : if (*expr_p == NULL_TREE)
20277 : : break;
20278 : 29145659 : if (*expr_p != save_expr)
20279 : 4822693 : continue;
20280 : : }
20281 : 455284647 : else if (ret != GS_UNHANDLED)
20282 : : break;
20283 : :
20284 : : /* Make sure that all the cases set 'ret' appropriately. */
20285 : 478976976 : ret = GS_UNHANDLED;
20286 : 478976976 : switch (TREE_CODE (*expr_p))
20287 : : {
20288 : : /* First deal with the special cases. */
20289 : :
20290 : 1136047 : case POSTINCREMENT_EXPR:
20291 : 1136047 : case POSTDECREMENT_EXPR:
20292 : 1136047 : case PREINCREMENT_EXPR:
20293 : 1136047 : case PREDECREMENT_EXPR:
20294 : 2272094 : ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
20295 : : fallback != fb_none,
20296 : 1136047 : TREE_TYPE (*expr_p));
20297 : 1136047 : break;
20298 : :
20299 : 652774 : case VIEW_CONVERT_EXPR:
20300 : 652774 : if ((fallback & fb_rvalue)
20301 : 652657 : && is_gimple_reg_type (TREE_TYPE (*expr_p))
20302 : 1127180 : && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
20303 : : {
20304 : 462594 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20305 : : post_p, is_gimple_val, fb_rvalue);
20306 : 462594 : recalculate_side_effects (*expr_p);
20307 : 462594 : break;
20308 : : }
20309 : : /* Fallthru. */
20310 : :
20311 : 29986119 : case ARRAY_REF:
20312 : 29986119 : case ARRAY_RANGE_REF:
20313 : 29986119 : case REALPART_EXPR:
20314 : 29986119 : case IMAGPART_EXPR:
20315 : 29986119 : case COMPONENT_REF:
20316 : 29986119 : ret = gimplify_compound_lval (expr_p, pre_p, post_p,
20317 : : fallback ? fallback : fb_rvalue);
20318 : 29986119 : break;
20319 : :
20320 : 6193480 : case COND_EXPR:
20321 : 6193480 : ret = gimplify_cond_expr (expr_p, pre_p, fallback);
20322 : :
20323 : : /* C99 code may assign to an array in a structure value of a
20324 : : conditional expression, and this has undefined behavior
20325 : : only on execution, so create a temporary if an lvalue is
20326 : : required. */
20327 : 6193480 : if (fallback == fb_lvalue)
20328 : : {
20329 : 7 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20330 : 7 : mark_addressable (*expr_p);
20331 : 7 : ret = GS_OK;
20332 : : }
20333 : : break;
20334 : :
20335 : 17023038 : case CALL_EXPR:
20336 : 17023038 : ret = gimplify_call_expr (expr_p, pre_p, fallback);
20337 : :
20338 : : /* C99 code may assign to an array in a structure returned
20339 : : from a function, and this has undefined behavior only on
20340 : : execution, so create a temporary if an lvalue is
20341 : : required. */
20342 : 17023038 : if (fallback == fb_lvalue)
20343 : : {
20344 : 17913 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20345 : 17913 : mark_addressable (*expr_p);
20346 : 17913 : ret = GS_OK;
20347 : : }
20348 : : break;
20349 : :
20350 : 0 : case TREE_LIST:
20351 : 0 : gcc_unreachable ();
20352 : :
20353 : 0 : case OMP_ARRAY_SECTION:
20354 : 0 : gcc_unreachable ();
20355 : :
20356 : 483668 : case COMPOUND_EXPR:
20357 : 483668 : ret = gimplify_compound_expr (expr_p, pre_p, fallback != fb_none);
20358 : 483668 : break;
20359 : :
20360 : 36832 : case COMPOUND_LITERAL_EXPR:
20361 : 36832 : ret = gimplify_compound_literal_expr (expr_p, pre_p,
20362 : : gimple_test_f, fallback);
20363 : 36832 : break;
20364 : :
20365 : 50060173 : case MODIFY_EXPR:
20366 : 50060173 : case INIT_EXPR:
20367 : 50060173 : ret = gimplify_modify_expr (expr_p, pre_p, post_p,
20368 : : fallback != fb_none);
20369 : 50060173 : break;
20370 : :
20371 : 115305 : case TRUTH_ANDIF_EXPR:
20372 : 115305 : case TRUTH_ORIF_EXPR:
20373 : 115305 : {
20374 : : /* Preserve the original type of the expression and the
20375 : : source location of the outer expression. */
20376 : 115305 : tree org_type = TREE_TYPE (*expr_p);
20377 : 115305 : *expr_p = gimple_boolify (*expr_p);
20378 : 115305 : *expr_p = build3_loc (input_location, COND_EXPR,
20379 : : org_type, *expr_p,
20380 : : fold_convert_loc
20381 : : (input_location,
20382 : : org_type, boolean_true_node),
20383 : : fold_convert_loc
20384 : : (input_location,
20385 : : org_type, boolean_false_node));
20386 : 115305 : ret = GS_OK;
20387 : 115305 : break;
20388 : : }
20389 : :
20390 : 228906 : case TRUTH_NOT_EXPR:
20391 : 228906 : {
20392 : 228906 : tree type = TREE_TYPE (*expr_p);
20393 : : /* The parsers are careful to generate TRUTH_NOT_EXPR
20394 : : only with operands that are always zero or one.
20395 : : We do not fold here but handle the only interesting case
20396 : : manually, as fold may re-introduce the TRUTH_NOT_EXPR. */
20397 : 228906 : *expr_p = gimple_boolify (*expr_p);
20398 : 228906 : if (TYPE_PRECISION (TREE_TYPE (*expr_p)) == 1)
20399 : 228906 : *expr_p = build1_loc (input_location, BIT_NOT_EXPR,
20400 : 228906 : TREE_TYPE (*expr_p),
20401 : 228906 : TREE_OPERAND (*expr_p, 0));
20402 : : else
20403 : 0 : *expr_p = build2_loc (input_location, BIT_XOR_EXPR,
20404 : 0 : TREE_TYPE (*expr_p),
20405 : 0 : TREE_OPERAND (*expr_p, 0),
20406 : 0 : build_int_cst (TREE_TYPE (*expr_p), 1));
20407 : 228906 : if (!useless_type_conversion_p (type, TREE_TYPE (*expr_p)))
20408 : 6542 : *expr_p = fold_convert_loc (input_location, type, *expr_p);
20409 : : ret = GS_OK;
20410 : : break;
20411 : : }
20412 : :
20413 : 33478391 : case ADDR_EXPR:
20414 : 33478391 : ret = gimplify_addr_expr (expr_p, pre_p, post_p);
20415 : 33478391 : break;
20416 : :
20417 : 5476 : case ANNOTATE_EXPR:
20418 : 5476 : {
20419 : 5476 : tree cond = TREE_OPERAND (*expr_p, 0);
20420 : 5476 : tree kind = TREE_OPERAND (*expr_p, 1);
20421 : 5476 : tree data = TREE_OPERAND (*expr_p, 2);
20422 : 5476 : tree type = TREE_TYPE (cond);
20423 : 5476 : if (!INTEGRAL_TYPE_P (type))
20424 : : {
20425 : 0 : *expr_p = cond;
20426 : 0 : ret = GS_OK;
20427 : 0 : break;
20428 : : }
20429 : 5476 : tree tmp = create_tmp_var (type);
20430 : 5476 : gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
20431 : 5476 : gcall *call
20432 : 5476 : = gimple_build_call_internal (IFN_ANNOTATE, 3, cond, kind, data);
20433 : 5476 : gimple_call_set_lhs (call, tmp);
20434 : 5476 : gimplify_seq_add_stmt (pre_p, call);
20435 : 5476 : *expr_p = tmp;
20436 : 5476 : ret = GS_ALL_DONE;
20437 : 5476 : break;
20438 : : }
20439 : :
20440 : 50935 : case VA_ARG_EXPR:
20441 : 50935 : ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
20442 : 50935 : break;
20443 : :
20444 : 17173012 : CASE_CONVERT:
20445 : 17173012 : if (IS_EMPTY_STMT (*expr_p))
20446 : : {
20447 : : ret = GS_ALL_DONE;
20448 : : break;
20449 : : }
20450 : :
20451 : 15468240 : if (VOID_TYPE_P (TREE_TYPE (*expr_p))
20452 : 15468240 : || fallback == fb_none)
20453 : : {
20454 : : /* Just strip a conversion to void (or in void context) and
20455 : : try again. */
20456 : 2730576 : *expr_p = TREE_OPERAND (*expr_p, 0);
20457 : 2730576 : ret = GS_OK;
20458 : 2730576 : break;
20459 : : }
20460 : :
20461 : 12737664 : ret = gimplify_conversion (expr_p);
20462 : 12737664 : if (ret == GS_ERROR)
20463 : : break;
20464 : 12737664 : if (*expr_p != save_expr)
20465 : : break;
20466 : : /* FALLTHRU */
20467 : :
20468 : 12863472 : case FIX_TRUNC_EXPR:
20469 : : /* unary_expr: ... | '(' cast ')' val | ... */
20470 : 12863472 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20471 : : is_gimple_val, fb_rvalue);
20472 : 12863472 : recalculate_side_effects (*expr_p);
20473 : 12863472 : break;
20474 : :
20475 : 6315142 : case INDIRECT_REF:
20476 : 6315142 : {
20477 : 6315142 : bool volatilep = TREE_THIS_VOLATILE (*expr_p);
20478 : 6315142 : bool notrap = TREE_THIS_NOTRAP (*expr_p);
20479 : 6315142 : tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
20480 : :
20481 : 6315142 : *expr_p = fold_indirect_ref_loc (input_location, *expr_p);
20482 : 6315142 : if (*expr_p != save_expr)
20483 : : {
20484 : : ret = GS_OK;
20485 : : break;
20486 : : }
20487 : :
20488 : 6296012 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20489 : : is_gimple_reg, fb_rvalue);
20490 : 6296012 : if (ret == GS_ERROR)
20491 : : break;
20492 : :
20493 : 6296011 : recalculate_side_effects (*expr_p);
20494 : 12592022 : *expr_p = fold_build2_loc (input_location, MEM_REF,
20495 : 6296011 : TREE_TYPE (*expr_p),
20496 : 6296011 : TREE_OPERAND (*expr_p, 0),
20497 : : build_int_cst (saved_ptr_type, 0));
20498 : 6296011 : TREE_THIS_VOLATILE (*expr_p) = volatilep;
20499 : 6296011 : TREE_THIS_NOTRAP (*expr_p) = notrap;
20500 : 6296011 : ret = GS_OK;
20501 : 6296011 : break;
20502 : : }
20503 : :
20504 : : /* We arrive here through the various re-gimplifcation paths. */
20505 : 16118563 : case MEM_REF:
20506 : : /* First try re-folding the whole thing. */
20507 : 16118563 : tmp = fold_binary (MEM_REF, TREE_TYPE (*expr_p),
20508 : : TREE_OPERAND (*expr_p, 0),
20509 : : TREE_OPERAND (*expr_p, 1));
20510 : 16118563 : if (tmp)
20511 : : {
20512 : 6566 : REF_REVERSE_STORAGE_ORDER (tmp)
20513 : 3283 : = REF_REVERSE_STORAGE_ORDER (*expr_p);
20514 : 3283 : *expr_p = tmp;
20515 : 3283 : recalculate_side_effects (*expr_p);
20516 : 3283 : ret = GS_OK;
20517 : 3283 : break;
20518 : : }
20519 : : /* Avoid re-gimplifying the address operand if it is already
20520 : : in suitable form. Re-gimplifying would mark the address
20521 : : operand addressable. Always gimplify when not in SSA form
20522 : : as we still may have to gimplify decls with value-exprs. */
20523 : 16115280 : if (!gimplify_ctxp || !gimple_in_ssa_p (cfun)
20524 : 17203820 : || !is_gimple_mem_ref_addr (TREE_OPERAND (*expr_p, 0)))
20525 : : {
20526 : 15081656 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
20527 : : is_gimple_mem_ref_addr, fb_rvalue);
20528 : 15081656 : if (ret == GS_ERROR)
20529 : : break;
20530 : : }
20531 : 16115280 : recalculate_side_effects (*expr_p);
20532 : 16115280 : ret = GS_ALL_DONE;
20533 : 16115280 : break;
20534 : :
20535 : : /* Constants need not be gimplified. */
20536 : 43875638 : case INTEGER_CST:
20537 : 43875638 : case REAL_CST:
20538 : 43875638 : case FIXED_CST:
20539 : 43875638 : case STRING_CST:
20540 : 43875638 : case COMPLEX_CST:
20541 : 43875638 : case VECTOR_CST:
20542 : : /* Drop the overflow flag on constants, we do not want
20543 : : that in the GIMPLE IL. */
20544 : 43875638 : if (TREE_OVERFLOW_P (*expr_p))
20545 : 1159 : *expr_p = drop_tree_overflow (*expr_p);
20546 : : ret = GS_ALL_DONE;
20547 : : break;
20548 : :
20549 : 116487 : case CONST_DECL:
20550 : : /* If we require an lvalue, such as for ADDR_EXPR, retain the
20551 : : CONST_DECL node. Otherwise the decl is replaceable by its
20552 : : value. */
20553 : : /* ??? Should be == fb_lvalue, but ADDR_EXPR passes fb_either. */
20554 : 116487 : if (fallback & fb_lvalue)
20555 : : ret = GS_ALL_DONE;
20556 : : else
20557 : : {
20558 : 3780 : *expr_p = DECL_INITIAL (*expr_p);
20559 : 3780 : ret = GS_OK;
20560 : : }
20561 : : break;
20562 : :
20563 : 6533668 : case DECL_EXPR:
20564 : 6533668 : ret = gimplify_decl_expr (expr_p, pre_p);
20565 : 6533668 : break;
20566 : :
20567 : 5989850 : case BIND_EXPR:
20568 : 5989850 : ret = gimplify_bind_expr (expr_p, pre_p);
20569 : 5989850 : break;
20570 : :
20571 : 196194 : case LOOP_EXPR:
20572 : 196194 : ret = gimplify_loop_expr (expr_p, pre_p);
20573 : 196194 : break;
20574 : :
20575 : 52188 : case SWITCH_EXPR:
20576 : 52188 : ret = gimplify_switch_expr (expr_p, pre_p);
20577 : 52188 : break;
20578 : :
20579 : 3097 : case EXIT_EXPR:
20580 : 3097 : ret = gimplify_exit_expr (expr_p);
20581 : 3097 : break;
20582 : :
20583 : 1109880 : case GOTO_EXPR:
20584 : : /* If the target is not LABEL, then it is a computed jump
20585 : : and the target needs to be gimplified. */
20586 : 1109880 : if (TREE_CODE (GOTO_DESTINATION (*expr_p)) != LABEL_DECL)
20587 : : {
20588 : 1101 : ret = gimplify_expr (&GOTO_DESTINATION (*expr_p), pre_p,
20589 : : NULL, is_gimple_val, fb_rvalue);
20590 : 1101 : if (ret == GS_ERROR)
20591 : : break;
20592 : : }
20593 : 2219758 : gimplify_seq_add_stmt (pre_p,
20594 : 1109879 : gimple_build_goto (GOTO_DESTINATION (*expr_p)));
20595 : 1109879 : ret = GS_ALL_DONE;
20596 : 1109879 : break;
20597 : :
20598 : 106819 : case PREDICT_EXPR:
20599 : 427276 : gimplify_seq_add_stmt (pre_p,
20600 : 106819 : gimple_build_predict (PREDICT_EXPR_PREDICTOR (*expr_p),
20601 : 106819 : PREDICT_EXPR_OUTCOME (*expr_p)));
20602 : 106819 : ret = GS_ALL_DONE;
20603 : 106819 : break;
20604 : :
20605 : 2537957 : case LABEL_EXPR:
20606 : 2537957 : ret = gimplify_label_expr (expr_p, pre_p);
20607 : 2537957 : label = LABEL_EXPR_LABEL (*expr_p);
20608 : 2537957 : gcc_assert (decl_function_context (label) == current_function_decl);
20609 : :
20610 : : /* If the label is used in a goto statement, or address of the label
20611 : : is taken, we need to unpoison all variables that were seen so far.
20612 : : Doing so would prevent us from reporting a false positives. */
20613 : 2537957 : if (asan_poisoned_variables
20614 : 3807 : && asan_used_labels != NULL
20615 : 1213 : && asan_used_labels->contains (label)
20616 : 2538771 : && !gimplify_omp_ctxp)
20617 : 806 : asan_poison_variables (asan_poisoned_variables, false, pre_p);
20618 : : break;
20619 : :
20620 : 1065416 : case CASE_LABEL_EXPR:
20621 : 1065416 : ret = gimplify_case_label_expr (expr_p, pre_p);
20622 : :
20623 : 1065416 : if (gimplify_ctxp->live_switch_vars)
20624 : 1065229 : asan_poison_variables (gimplify_ctxp->live_switch_vars, false,
20625 : : pre_p);
20626 : : break;
20627 : :
20628 : 2263963 : case RETURN_EXPR:
20629 : 2263963 : ret = gimplify_return_expr (*expr_p, pre_p);
20630 : 2263963 : break;
20631 : :
20632 : 951134 : case CONSTRUCTOR:
20633 : : /* Don't reduce this in place; let gimplify_init_constructor work its
20634 : : magic. Buf if we're just elaborating this for side effects, just
20635 : : gimplify any element that has side-effects. */
20636 : 951134 : if (fallback == fb_none)
20637 : : {
20638 : 356 : unsigned HOST_WIDE_INT ix;
20639 : 356 : tree val;
20640 : 356 : tree temp = NULL_TREE;
20641 : 373 : FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (*expr_p), ix, val)
20642 : 17 : if (TREE_SIDE_EFFECTS (val))
20643 : 4 : append_to_statement_list (val, &temp);
20644 : :
20645 : 356 : *expr_p = temp;
20646 : 356 : ret = temp ? GS_OK : GS_ALL_DONE;
20647 : : }
20648 : : /* C99 code may assign to an array in a constructed
20649 : : structure or union, and this has undefined behavior only
20650 : : on execution, so create a temporary if an lvalue is
20651 : : required. */
20652 : 950778 : else if (fallback == fb_lvalue)
20653 : : {
20654 : 12 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, post_p, false);
20655 : 12 : mark_addressable (*expr_p);
20656 : 12 : ret = GS_OK;
20657 : : }
20658 : : else
20659 : : ret = GS_ALL_DONE;
20660 : : break;
20661 : :
20662 : : /* The following are special cases that are not handled by the
20663 : : original GIMPLE grammar. */
20664 : :
20665 : : /* SAVE_EXPR nodes are converted into a GIMPLE identifier and
20666 : : eliminated. */
20667 : 425682 : case SAVE_EXPR:
20668 : 425682 : ret = gimplify_save_expr (expr_p, pre_p, post_p);
20669 : 425682 : break;
20670 : :
20671 : 417067 : case BIT_FIELD_REF:
20672 : 417067 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20673 : : post_p, is_gimple_lvalue, fb_either);
20674 : 417067 : recalculate_side_effects (*expr_p);
20675 : 417067 : break;
20676 : :
20677 : 1698 : case TARGET_MEM_REF:
20678 : 1698 : {
20679 : 1698 : enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
20680 : :
20681 : 1698 : if (TMR_BASE (*expr_p))
20682 : 1698 : r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
20683 : : post_p, is_gimple_mem_ref_addr, fb_either);
20684 : 1698 : if (TMR_INDEX (*expr_p))
20685 : 1176 : r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
20686 : : post_p, is_gimple_val, fb_rvalue);
20687 : 1698 : if (TMR_INDEX2 (*expr_p))
20688 : 60 : r1 = gimplify_expr (&TMR_INDEX2 (*expr_p), pre_p,
20689 : : post_p, is_gimple_val, fb_rvalue);
20690 : : /* TMR_STEP and TMR_OFFSET are always integer constants. */
20691 : 1698 : ret = MIN (r0, r1);
20692 : : }
20693 : : break;
20694 : :
20695 : 0 : case NON_LVALUE_EXPR:
20696 : : /* This should have been stripped above. */
20697 : 0 : gcc_unreachable ();
20698 : :
20699 : 96525 : case ASM_EXPR:
20700 : 96525 : ret = gimplify_asm_expr (expr_p, pre_p, post_p);
20701 : 96525 : break;
20702 : :
20703 : 522955 : case TRY_FINALLY_EXPR:
20704 : 522955 : case TRY_CATCH_EXPR:
20705 : 522955 : {
20706 : 522955 : gimple_seq eval, cleanup;
20707 : 522955 : gtry *try_;
20708 : :
20709 : : /* Calls to destructors are generated automatically in FINALLY/CATCH
20710 : : block. They should have location as UNKNOWN_LOCATION. However,
20711 : : gimplify_call_expr will reset these call stmts to input_location
20712 : : if it finds stmt's location is unknown. To prevent resetting for
20713 : : destructors, we set the input_location to unknown.
20714 : : Note that this only affects the destructor calls in FINALLY/CATCH
20715 : : block, and will automatically reset to its original value by the
20716 : : end of gimplify_expr. */
20717 : 522955 : input_location = UNKNOWN_LOCATION;
20718 : 522955 : eval = cleanup = NULL;
20719 : 522955 : gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
20720 : 522955 : bool save_in_handler_expr = gimplify_ctxp->in_handler_expr;
20721 : 522955 : if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20722 : 522955 : && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR)
20723 : : {
20724 : 86 : gimple_seq n = NULL, e = NULL;
20725 : 86 : gimplify_ctxp->in_handler_expr = true;
20726 : 86 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20727 : : 0), &n);
20728 : 86 : gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
20729 : : 1), &e);
20730 : 86 : if (!gimple_seq_empty_p (n) || !gimple_seq_empty_p (e))
20731 : : {
20732 : 85 : geh_else *stmt = gimple_build_eh_else (n, e);
20733 : 85 : gimple_seq_add_stmt (&cleanup, stmt);
20734 : : }
20735 : : }
20736 : : else
20737 : : {
20738 : 522869 : gimplify_ctxp->in_handler_expr = true;
20739 : 522869 : gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
20740 : : }
20741 : 522955 : gimplify_ctxp->in_handler_expr = save_in_handler_expr;
20742 : : /* Don't create bogus GIMPLE_TRY with empty cleanup. */
20743 : 522955 : if (gimple_seq_empty_p (cleanup))
20744 : : {
20745 : 27407 : gimple_seq_add_seq (pre_p, eval);
20746 : 27407 : ret = GS_ALL_DONE;
20747 : 27407 : break;
20748 : : }
20749 : 495548 : try_ = gimple_build_try (eval, cleanup,
20750 : 495548 : TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
20751 : : ? GIMPLE_TRY_FINALLY
20752 : : : GIMPLE_TRY_CATCH);
20753 : 495548 : if (EXPR_HAS_LOCATION (save_expr))
20754 : 913824 : gimple_set_location (try_, EXPR_LOCATION (save_expr));
20755 : 38636 : else if (LOCATION_LOCUS (saved_location) != UNKNOWN_LOCATION)
20756 : 28342 : gimple_set_location (try_, saved_location);
20757 : 495548 : if (TREE_CODE (*expr_p) == TRY_CATCH_EXPR)
20758 : 183969 : gimple_try_set_catch_is_cleanup (try_,
20759 : 183969 : TRY_CATCH_IS_CLEANUP (*expr_p));
20760 : 495548 : gimplify_seq_add_stmt (pre_p, try_);
20761 : 495548 : ret = GS_ALL_DONE;
20762 : 495548 : break;
20763 : : }
20764 : :
20765 : 5283883 : case CLEANUP_POINT_EXPR:
20766 : 5283883 : ret = gimplify_cleanup_point_expr (expr_p, pre_p);
20767 : 5283883 : break;
20768 : :
20769 : 813932 : case TARGET_EXPR:
20770 : 813932 : ret = gimplify_target_expr (expr_p, pre_p, post_p);
20771 : 813932 : break;
20772 : :
20773 : 39603 : case CATCH_EXPR:
20774 : 39603 : {
20775 : 39603 : gimple *c;
20776 : 39603 : gimple_seq handler = NULL;
20777 : 39603 : gimplify_and_add (CATCH_BODY (*expr_p), &handler);
20778 : 39603 : c = gimple_build_catch (CATCH_TYPES (*expr_p), handler);
20779 : 39603 : gimplify_seq_add_stmt (pre_p, c);
20780 : 39603 : ret = GS_ALL_DONE;
20781 : 39603 : break;
20782 : : }
20783 : :
20784 : 4632 : case EH_FILTER_EXPR:
20785 : 4632 : {
20786 : 4632 : gimple *ehf;
20787 : 4632 : gimple_seq failure = NULL;
20788 : :
20789 : 4632 : gimplify_and_add (EH_FILTER_FAILURE (*expr_p), &failure);
20790 : 4632 : ehf = gimple_build_eh_filter (EH_FILTER_TYPES (*expr_p), failure);
20791 : 4632 : copy_warning (ehf, *expr_p);
20792 : 4632 : gimplify_seq_add_stmt (pre_p, ehf);
20793 : 4632 : ret = GS_ALL_DONE;
20794 : 4632 : break;
20795 : : }
20796 : :
20797 : 51289 : case OBJ_TYPE_REF:
20798 : 51289 : {
20799 : 51289 : enum gimplify_status r0, r1;
20800 : 51289 : r0 = gimplify_expr (&OBJ_TYPE_REF_OBJECT (*expr_p), pre_p,
20801 : : post_p, is_gimple_val, fb_rvalue);
20802 : 51289 : r1 = gimplify_expr (&OBJ_TYPE_REF_EXPR (*expr_p), pre_p,
20803 : : post_p, is_gimple_val, fb_rvalue);
20804 : 51289 : TREE_SIDE_EFFECTS (*expr_p) = 0;
20805 : 51289 : ret = MIN (r0, r1);
20806 : : }
20807 : : break;
20808 : :
20809 : 40494 : case LABEL_DECL:
20810 : : /* We get here when taking the address of a label. We mark
20811 : : the label as "forced"; meaning it can never be removed and
20812 : : it is a potential target for any computed goto. */
20813 : 40494 : FORCED_LABEL (*expr_p) = 1;
20814 : 40494 : ret = GS_ALL_DONE;
20815 : 40494 : break;
20816 : :
20817 : 8516084 : case STATEMENT_LIST:
20818 : 8516084 : ret = gimplify_statement_list (expr_p, pre_p);
20819 : 8516084 : break;
20820 : :
20821 : 1695 : case WITH_SIZE_EXPR:
20822 : 1695 : {
20823 : 1977 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
20824 : : post_p == &internal_post ? NULL : post_p,
20825 : : gimple_test_f, fallback);
20826 : 1695 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
20827 : : is_gimple_val, fb_rvalue);
20828 : 1695 : ret = GS_ALL_DONE;
20829 : : }
20830 : 1695 : break;
20831 : :
20832 : 108672652 : case VAR_DECL:
20833 : 108672652 : case PARM_DECL:
20834 : 108672652 : ret = gimplify_var_or_parm_decl (expr_p);
20835 : 108672652 : break;
20836 : :
20837 : 345073 : case RESULT_DECL:
20838 : : /* When within an OMP context, notice uses of variables. */
20839 : 345073 : if (gimplify_omp_ctxp)
20840 : 1357 : omp_notice_variable (gimplify_omp_ctxp, *expr_p, true);
20841 : : /* Handlers can refer to the function result; if that has been
20842 : : moved, we need to track it. */
20843 : 345073 : if (gimplify_ctxp->in_handler_expr && gimplify_ctxp->return_temp)
20844 : 48 : *expr_p = gimplify_ctxp->return_temp;
20845 : : ret = GS_ALL_DONE;
20846 : : break;
20847 : :
20848 : 0 : case DEBUG_EXPR_DECL:
20849 : 0 : gcc_unreachable ();
20850 : :
20851 : 2428491 : case DEBUG_BEGIN_STMT:
20852 : 4856982 : gimplify_seq_add_stmt (pre_p,
20853 : : gimple_build_debug_begin_stmt
20854 : 2428491 : (TREE_BLOCK (*expr_p),
20855 : 2428491 : EXPR_LOCATION (*expr_p)));
20856 : 2428491 : ret = GS_ALL_DONE;
20857 : 2428491 : *expr_p = NULL;
20858 : 2428491 : break;
20859 : :
20860 : : case SSA_NAME:
20861 : : /* Allow callbacks into the gimplifier during optimization. */
20862 : : ret = GS_ALL_DONE;
20863 : : break;
20864 : :
20865 : 18156 : case OMP_PARALLEL:
20866 : 18156 : gimplify_omp_parallel (expr_p, pre_p);
20867 : 18156 : ret = GS_ALL_DONE;
20868 : 18156 : break;
20869 : :
20870 : 3846 : case OMP_TASK:
20871 : 3846 : gimplify_omp_task (expr_p, pre_p);
20872 : 3846 : ret = GS_ALL_DONE;
20873 : 3846 : break;
20874 : :
20875 : 10678 : case OMP_SIMD:
20876 : 10678 : {
20877 : : /* Temporarily disable into_ssa, as scan_omp_simd
20878 : : which calls copy_gimple_seq_and_replace_locals can't deal
20879 : : with SSA_NAMEs defined outside of the body properly. */
20880 : 10678 : bool saved_into_ssa = gimplify_ctxp->into_ssa;
20881 : 10678 : gimplify_ctxp->into_ssa = false;
20882 : 10678 : ret = gimplify_omp_for (expr_p, pre_p);
20883 : 10678 : gimplify_ctxp->into_ssa = saved_into_ssa;
20884 : 10678 : break;
20885 : : }
20886 : :
20887 : 47383 : case OMP_FOR:
20888 : 47383 : case OMP_DISTRIBUTE:
20889 : 47383 : case OMP_TASKLOOP:
20890 : 47383 : case OMP_TILE:
20891 : 47383 : case OMP_UNROLL:
20892 : 47383 : case OACC_LOOP:
20893 : 47383 : ret = gimplify_omp_for (expr_p, pre_p);
20894 : 47383 : break;
20895 : :
20896 : 1056 : case OMP_LOOP:
20897 : 1056 : ret = gimplify_omp_loop (expr_p, pre_p);
20898 : 1056 : break;
20899 : :
20900 : 665 : case OACC_CACHE:
20901 : 665 : gimplify_oacc_cache (expr_p, pre_p);
20902 : 665 : ret = GS_ALL_DONE;
20903 : 665 : break;
20904 : :
20905 : 254 : case OACC_DECLARE:
20906 : 254 : gimplify_oacc_declare (expr_p, pre_p);
20907 : 254 : ret = GS_ALL_DONE;
20908 : 254 : break;
20909 : :
20910 : 38929 : case OACC_HOST_DATA:
20911 : 38929 : case OACC_DATA:
20912 : 38929 : case OACC_KERNELS:
20913 : 38929 : case OACC_PARALLEL:
20914 : 38929 : case OACC_SERIAL:
20915 : 38929 : case OMP_SCOPE:
20916 : 38929 : case OMP_SECTIONS:
20917 : 38929 : case OMP_SINGLE:
20918 : 38929 : case OMP_TARGET:
20919 : 38929 : case OMP_TARGET_DATA:
20920 : 38929 : case OMP_TEAMS:
20921 : 38929 : gimplify_omp_workshare (expr_p, pre_p);
20922 : 38929 : ret = GS_ALL_DONE;
20923 : 38929 : break;
20924 : :
20925 : 11935 : case OACC_ENTER_DATA:
20926 : 11935 : case OACC_EXIT_DATA:
20927 : 11935 : case OACC_UPDATE:
20928 : 11935 : case OMP_TARGET_UPDATE:
20929 : 11935 : case OMP_TARGET_ENTER_DATA:
20930 : 11935 : case OMP_TARGET_EXIT_DATA:
20931 : 11935 : gimplify_omp_target_update (expr_p, pre_p);
20932 : 11935 : ret = GS_ALL_DONE;
20933 : 11935 : break;
20934 : :
20935 : 6998 : case OMP_SECTION:
20936 : 6998 : case OMP_STRUCTURED_BLOCK:
20937 : 6998 : case OMP_MASTER:
20938 : 6998 : case OMP_MASKED:
20939 : 6998 : case OMP_ORDERED:
20940 : 6998 : case OMP_CRITICAL:
20941 : 6998 : case OMP_SCAN:
20942 : 6998 : {
20943 : 6998 : gimple_seq body = NULL;
20944 : 6998 : gimple *g;
20945 : 6998 : bool saved_in_omp_construct = in_omp_construct;
20946 : :
20947 : 6998 : in_omp_construct = true;
20948 : 6998 : gimplify_and_add (OMP_BODY (*expr_p), &body);
20949 : 6998 : in_omp_construct = saved_in_omp_construct;
20950 : 6998 : switch (TREE_CODE (*expr_p))
20951 : : {
20952 : 1271 : case OMP_SECTION:
20953 : 1271 : g = gimple_build_omp_section (body);
20954 : 1271 : break;
20955 : 791 : case OMP_STRUCTURED_BLOCK:
20956 : 791 : g = gimple_build_omp_structured_block (body);
20957 : 791 : break;
20958 : 886 : case OMP_MASTER:
20959 : 886 : g = gimple_build_omp_master (body);
20960 : 886 : break;
20961 : 1940 : case OMP_ORDERED:
20962 : 1940 : g = gimplify_omp_ordered (*expr_p, body);
20963 : 1940 : if (OMP_BODY (*expr_p) == NULL_TREE
20964 : 1940 : && gimple_code (g) == GIMPLE_OMP_ORDERED)
20965 : 1015 : gimple_omp_ordered_standalone (g);
20966 : : break;
20967 : 446 : case OMP_MASKED:
20968 : 446 : gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p),
20969 : : pre_p, ORT_WORKSHARE, OMP_MASKED);
20970 : 446 : gimplify_adjust_omp_clauses (pre_p, body,
20971 : : &OMP_MASKED_CLAUSES (*expr_p),
20972 : : OMP_MASKED);
20973 : 892 : g = gimple_build_omp_masked (body,
20974 : 446 : OMP_MASKED_CLAUSES (*expr_p));
20975 : 446 : break;
20976 : 546 : case OMP_CRITICAL:
20977 : 546 : gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
20978 : : pre_p, ORT_WORKSHARE, OMP_CRITICAL);
20979 : 546 : gimplify_adjust_omp_clauses (pre_p, body,
20980 : : &OMP_CRITICAL_CLAUSES (*expr_p),
20981 : : OMP_CRITICAL);
20982 : 1638 : g = gimple_build_omp_critical (body,
20983 : 546 : OMP_CRITICAL_NAME (*expr_p),
20984 : 546 : OMP_CRITICAL_CLAUSES (*expr_p));
20985 : 546 : break;
20986 : 1118 : case OMP_SCAN:
20987 : 1118 : gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
20988 : : pre_p, ORT_WORKSHARE, OMP_SCAN);
20989 : 1118 : gimplify_adjust_omp_clauses (pre_p, body,
20990 : : &OMP_SCAN_CLAUSES (*expr_p),
20991 : : OMP_SCAN);
20992 : 1118 : g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
20993 : 1118 : break;
20994 : 0 : default:
20995 : 0 : gcc_unreachable ();
20996 : : }
20997 : 6998 : gimplify_seq_add_stmt (pre_p, g);
20998 : 6998 : ret = GS_ALL_DONE;
20999 : 6998 : break;
21000 : : }
21001 : :
21002 : 611 : case OMP_TASKGROUP:
21003 : 611 : {
21004 : 611 : gimple_seq body = NULL;
21005 : :
21006 : 611 : tree *pclauses = &OMP_TASKGROUP_CLAUSES (*expr_p);
21007 : 611 : bool saved_in_omp_construct = in_omp_construct;
21008 : 611 : gimplify_scan_omp_clauses (pclauses, pre_p, ORT_TASKGROUP,
21009 : : OMP_TASKGROUP);
21010 : 611 : gimplify_adjust_omp_clauses (pre_p, NULL, pclauses, OMP_TASKGROUP);
21011 : :
21012 : 611 : in_omp_construct = true;
21013 : 611 : gimplify_and_add (OMP_BODY (*expr_p), &body);
21014 : 611 : in_omp_construct = saved_in_omp_construct;
21015 : 611 : gimple_seq cleanup = NULL;
21016 : 611 : tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_END);
21017 : 611 : gimple *g = gimple_build_call (fn, 0);
21018 : 611 : gimple_seq_add_stmt (&cleanup, g);
21019 : 611 : g = gimple_build_try (body, cleanup, GIMPLE_TRY_FINALLY);
21020 : 611 : body = NULL;
21021 : 611 : gimple_seq_add_stmt (&body, g);
21022 : 611 : g = gimple_build_omp_taskgroup (body, *pclauses);
21023 : 611 : gimplify_seq_add_stmt (pre_p, g);
21024 : 611 : ret = GS_ALL_DONE;
21025 : 611 : break;
21026 : : }
21027 : :
21028 : 612 : case OMP_INTEROP:
21029 : 612 : ret = gimplify_omp_interop (expr_p, pre_p);
21030 : 612 : break;
21031 : 10238 : case OMP_ATOMIC:
21032 : 10238 : case OMP_ATOMIC_READ:
21033 : 10238 : case OMP_ATOMIC_CAPTURE_OLD:
21034 : 10238 : case OMP_ATOMIC_CAPTURE_NEW:
21035 : 10238 : ret = gimplify_omp_atomic (expr_p, pre_p);
21036 : 10238 : break;
21037 : :
21038 : 846 : case OMP_DISPATCH:
21039 : 846 : ret = gimplify_omp_dispatch (expr_p, pre_p);
21040 : 846 : break;
21041 : :
21042 : 174 : case OMP_METADIRECTIVE:
21043 : 174 : ret = gimplify_omp_metadirective (expr_p, pre_p, post_p,
21044 : : gimple_test_f, fallback);
21045 : 174 : break;
21046 : :
21047 : 36 : case OMP_NEXT_VARIANT:
21048 : 36 : case OMP_TARGET_DEVICE_MATCHES:
21049 : : /* These are placeholders for constants. There's nothing to do with
21050 : : them here but we must mark the containing function as needing
21051 : : to run the ompdevlow pass to resolve them. Note that
21052 : : OMP_TARGET_DEVICE_MATCHES, in particular, may be inserted by
21053 : : the front ends. */
21054 : 36 : cgraph_node::get (cfun->decl)->has_omp_variant_constructs = 1;
21055 : 36 : ret = GS_ALL_DONE;
21056 : 36 : break;
21057 : :
21058 : 0 : case OMP_DECLARE_MAPPER:
21059 : 0 : ret = gimplify_omp_declare_mapper (expr_p);
21060 : 0 : break;
21061 : :
21062 : 478 : case TRANSACTION_EXPR:
21063 : 478 : ret = gimplify_transaction (expr_p, pre_p);
21064 : 478 : break;
21065 : :
21066 : 299028 : case TRUTH_AND_EXPR:
21067 : 299028 : case TRUTH_OR_EXPR:
21068 : 299028 : case TRUTH_XOR_EXPR:
21069 : 299028 : {
21070 : 299028 : tree orig_type = TREE_TYPE (*expr_p);
21071 : 299028 : tree new_type, xop0, xop1;
21072 : 299028 : *expr_p = gimple_boolify (*expr_p);
21073 : 299028 : new_type = TREE_TYPE (*expr_p);
21074 : 299028 : if (!useless_type_conversion_p (orig_type, new_type))
21075 : : {
21076 : 1134 : *expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
21077 : 1134 : ret = GS_OK;
21078 : 1134 : break;
21079 : : }
21080 : :
21081 : : /* Boolified binary truth expressions are semantically equivalent
21082 : : to bitwise binary expressions. Canonicalize them to the
21083 : : bitwise variant. */
21084 : 297894 : switch (TREE_CODE (*expr_p))
21085 : : {
21086 : 177389 : case TRUTH_AND_EXPR:
21087 : 177389 : TREE_SET_CODE (*expr_p, BIT_AND_EXPR);
21088 : 177389 : break;
21089 : 119917 : case TRUTH_OR_EXPR:
21090 : 119917 : TREE_SET_CODE (*expr_p, BIT_IOR_EXPR);
21091 : 119917 : break;
21092 : 588 : case TRUTH_XOR_EXPR:
21093 : 588 : TREE_SET_CODE (*expr_p, BIT_XOR_EXPR);
21094 : 588 : break;
21095 : : default:
21096 : : break;
21097 : : }
21098 : : /* Now make sure that operands have compatible type to
21099 : : expression's new_type. */
21100 : 297894 : xop0 = TREE_OPERAND (*expr_p, 0);
21101 : 297894 : xop1 = TREE_OPERAND (*expr_p, 1);
21102 : 297894 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
21103 : 326 : TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
21104 : : new_type,
21105 : : xop0);
21106 : 297894 : if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
21107 : 366 : TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
21108 : : new_type,
21109 : : xop1);
21110 : : /* Continue classified as tcc_binary. */
21111 : 297894 : goto expr_2;
21112 : : }
21113 : :
21114 : 9467 : case VEC_COND_EXPR:
21115 : 9467 : goto expr_3;
21116 : :
21117 : 132624 : case VEC_PERM_EXPR:
21118 : : /* Classified as tcc_expression. */
21119 : 132624 : goto expr_3;
21120 : :
21121 : 48 : case BIT_INSERT_EXPR:
21122 : : /* Argument 3 is a constant. */
21123 : 48 : goto expr_2;
21124 : :
21125 : 3837910 : case POINTER_PLUS_EXPR:
21126 : 3837910 : {
21127 : 3837910 : enum gimplify_status r0, r1;
21128 : 3837910 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21129 : : post_p, is_gimple_val, fb_rvalue);
21130 : 3837910 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21131 : : post_p, is_gimple_val, fb_rvalue);
21132 : 3837910 : recalculate_side_effects (*expr_p);
21133 : 3837910 : ret = MIN (r0, r1);
21134 : : break;
21135 : : }
21136 : :
21137 : 44185734 : default:
21138 : 44185734 : switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
21139 : : {
21140 : 6971895 : case tcc_comparison:
21141 : : /* Handle comparison of objects of non scalar mode aggregates
21142 : : with a call to memcmp. It would be nice to only have to do
21143 : : this for variable-sized objects, but then we'd have to allow
21144 : : the same nest of reference nodes we allow for MODIFY_EXPR and
21145 : : that's too complex.
21146 : :
21147 : : Compare scalar mode aggregates as scalar mode values. Using
21148 : : memcmp for them would be very inefficient at best, and is
21149 : : plain wrong if bitfields are involved. */
21150 : 6971895 : if (error_operand_p (TREE_OPERAND (*expr_p, 1)))
21151 : : ret = GS_ERROR;
21152 : : else
21153 : : {
21154 : 6971895 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 1));
21155 : :
21156 : : /* Vector comparisons need no boolification. */
21157 : 6971895 : if (TREE_CODE (type) == VECTOR_TYPE)
21158 : 11556 : goto expr_2;
21159 : 6960339 : else if (!AGGREGATE_TYPE_P (type))
21160 : : {
21161 : 6960323 : tree org_type = TREE_TYPE (*expr_p);
21162 : 6960323 : *expr_p = gimple_boolify (*expr_p);
21163 : 6960323 : if (!useless_type_conversion_p (org_type,
21164 : 6960323 : TREE_TYPE (*expr_p)))
21165 : : {
21166 : 55402 : *expr_p = fold_convert_loc (input_location,
21167 : : org_type, *expr_p);
21168 : 55402 : ret = GS_OK;
21169 : : }
21170 : : else
21171 : 6904921 : goto expr_2;
21172 : : }
21173 : 16 : else if (SCALAR_INT_MODE_P (TYPE_MODE (type)))
21174 : 16 : ret = gimplify_scalar_mode_aggregate_compare (expr_p);
21175 : : else
21176 : 0 : ret = gimplify_variable_sized_compare (expr_p);
21177 : : }
21178 : : break;
21179 : :
21180 : : /* If *EXPR_P does not need to be special-cased, handle it
21181 : : according to its class. */
21182 : 1594320 : case tcc_unary:
21183 : 1594320 : ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21184 : : post_p, is_gimple_val, fb_rvalue);
21185 : 1594320 : break;
21186 : :
21187 : 26124398 : case tcc_binary:
21188 : 26124398 : expr_2:
21189 : 26124398 : {
21190 : 26124398 : enum gimplify_status r0, r1;
21191 : :
21192 : 26124398 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21193 : : post_p, is_gimple_val, fb_rvalue);
21194 : 26124398 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21195 : : post_p, is_gimple_val, fb_rvalue);
21196 : :
21197 : 26124398 : ret = MIN (r0, r1);
21198 : : break;
21199 : : }
21200 : :
21201 : 142091 : expr_3:
21202 : 142091 : {
21203 : 142091 : enum gimplify_status r0, r1, r2;
21204 : :
21205 : 142091 : r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
21206 : : post_p, is_gimple_val, fb_rvalue);
21207 : 142091 : r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
21208 : : post_p, is_gimple_val, fb_rvalue);
21209 : 142091 : r2 = gimplify_expr (&TREE_OPERAND (*expr_p, 2), pre_p,
21210 : : post_p, is_gimple_val, fb_rvalue);
21211 : :
21212 : 142091 : ret = MIN (MIN (r0, r1), r2);
21213 : : break;
21214 : : }
21215 : :
21216 : 16709540 : case tcc_declaration:
21217 : 16709540 : case tcc_constant:
21218 : 16709540 : ret = GS_ALL_DONE;
21219 : 16709540 : goto dont_recalculate;
21220 : :
21221 : 0 : default:
21222 : 0 : gcc_unreachable ();
21223 : : }
21224 : :
21225 : 27916227 : recalculate_side_effects (*expr_p);
21226 : :
21227 : 478976976 : dont_recalculate:
21228 : : break;
21229 : : }
21230 : :
21231 : 478976976 : gcc_assert (*expr_p || ret != GS_OK);
21232 : : }
21233 : 483799669 : while (ret == GS_OK);
21234 : :
21235 : : /* If we encountered an error_mark somewhere nested inside, either
21236 : : stub out the statement or propagate the error back out. */
21237 : 465940588 : if (ret == GS_ERROR)
21238 : : {
21239 : 5557 : if (is_statement)
21240 : 4077 : *expr_p = NULL;
21241 : 5557 : goto out;
21242 : : }
21243 : :
21244 : : /* This was only valid as a return value from the langhook, which
21245 : : we handled. Make sure it doesn't escape from any other context. */
21246 : 465935031 : gcc_assert (ret != GS_UNHANDLED);
21247 : :
21248 : 465935031 : if (fallback == fb_none && *expr_p && !is_gimple_stmt (*expr_p))
21249 : : {
21250 : : /* We aren't looking for a value, and we don't have a valid
21251 : : statement. If it doesn't have side-effects, throw it away.
21252 : : We can also get here with code such as "*&&L;", where L is
21253 : : a LABEL_DECL that is marked as FORCED_LABEL. */
21254 : 1164463 : if (TREE_CODE (*expr_p) == LABEL_DECL
21255 : 1164463 : || !TREE_SIDE_EFFECTS (*expr_p))
21256 : 1163442 : *expr_p = NULL;
21257 : 1021 : else if (!TREE_THIS_VOLATILE (*expr_p))
21258 : : {
21259 : : /* This is probably a _REF that contains something nested that
21260 : : has side effects. Recurse through the operands to find it. */
21261 : 0 : enum tree_code code = TREE_CODE (*expr_p);
21262 : :
21263 : 0 : switch (code)
21264 : : {
21265 : 0 : case COMPONENT_REF:
21266 : 0 : case REALPART_EXPR:
21267 : 0 : case IMAGPART_EXPR:
21268 : 0 : case VIEW_CONVERT_EXPR:
21269 : 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21270 : : gimple_test_f, fallback);
21271 : 0 : break;
21272 : :
21273 : 0 : case ARRAY_REF:
21274 : 0 : case ARRAY_RANGE_REF:
21275 : 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
21276 : : gimple_test_f, fallback);
21277 : 0 : gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
21278 : : gimple_test_f, fallback);
21279 : 0 : break;
21280 : :
21281 : 0 : default:
21282 : : /* Anything else with side-effects must be converted to
21283 : : a valid statement before we get here. */
21284 : 0 : gcc_unreachable ();
21285 : : }
21286 : :
21287 : 0 : *expr_p = NULL;
21288 : : }
21289 : 1021 : else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
21290 : 971 : && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode
21291 : 1980 : && !is_empty_type (TREE_TYPE (*expr_p)))
21292 : : {
21293 : : /* Historically, the compiler has treated a bare reference
21294 : : to a non-BLKmode volatile lvalue as forcing a load. */
21295 : 893 : tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
21296 : :
21297 : : /* Normally, we do not want to create a temporary for a
21298 : : TREE_ADDRESSABLE type because such a type should not be
21299 : : copied by bitwise-assignment. However, we make an
21300 : : exception here, as all we are doing here is ensuring that
21301 : : we read the bytes that make up the type. We use
21302 : : create_tmp_var_raw because create_tmp_var will abort when
21303 : : given a TREE_ADDRESSABLE type. */
21304 : 893 : tree tmp = create_tmp_var_raw (type, "vol");
21305 : 893 : gimple_add_tmp_var (tmp);
21306 : 893 : gimplify_assign (tmp, *expr_p, pre_p);
21307 : 893 : *expr_p = NULL;
21308 : : }
21309 : : else
21310 : : /* We can't do anything useful with a volatile reference to
21311 : : an incomplete type, so just throw it away. Likewise for
21312 : : a BLKmode type, since any implicit inner load should
21313 : : already have been turned into an explicit one by the
21314 : : gimplification process. */
21315 : 128 : *expr_p = NULL;
21316 : : }
21317 : :
21318 : : /* If we are gimplifying at the statement level, we're done. Tack
21319 : : everything together and return. */
21320 : 465935031 : if (fallback == fb_none || is_statement)
21321 : : {
21322 : : /* Since *EXPR_P has been converted into a GIMPLE tuple, clear
21323 : : it out for GC to reclaim it. */
21324 : 101115211 : *expr_p = NULL_TREE;
21325 : :
21326 : 101115211 : if (!gimple_seq_empty_p (internal_pre)
21327 : 101115211 : || !gimple_seq_empty_p (internal_post))
21328 : : {
21329 : 19 : gimplify_seq_add_seq (&internal_pre, internal_post);
21330 : 19 : gimplify_seq_add_seq (pre_p, internal_pre);
21331 : : }
21332 : :
21333 : : /* The result of gimplifying *EXPR_P is going to be the last few
21334 : : statements in *PRE_P and *POST_P. Add location information
21335 : : to all the statements that were added by the gimplification
21336 : : helpers. */
21337 : 101115211 : if (!gimple_seq_empty_p (*pre_p))
21338 : 98653913 : annotate_all_with_location_after (*pre_p, pre_last_gsi, input_location);
21339 : :
21340 : 101115211 : if (!gimple_seq_empty_p (*post_p))
21341 : 19 : annotate_all_with_location_after (*post_p, post_last_gsi,
21342 : : input_location);
21343 : :
21344 : 101115211 : goto out;
21345 : : }
21346 : :
21347 : : #ifdef ENABLE_GIMPLE_CHECKING
21348 : 364819820 : if (*expr_p)
21349 : : {
21350 : 364819820 : enum tree_code code = TREE_CODE (*expr_p);
21351 : : /* These expressions should already be in gimple IR form. */
21352 : 364819820 : gcc_assert (code != MODIFY_EXPR
21353 : : && code != ASM_EXPR
21354 : : && code != BIND_EXPR
21355 : : && code != CATCH_EXPR
21356 : : && (code != COND_EXPR || gimplify_ctxp->allow_rhs_cond_expr)
21357 : : && code != EH_FILTER_EXPR
21358 : : && code != GOTO_EXPR
21359 : : && code != LABEL_EXPR
21360 : : && code != LOOP_EXPR
21361 : : && code != SWITCH_EXPR
21362 : : && code != TRY_FINALLY_EXPR
21363 : : && code != EH_ELSE_EXPR
21364 : : && code != OACC_PARALLEL
21365 : : && code != OACC_KERNELS
21366 : : && code != OACC_SERIAL
21367 : : && code != OACC_DATA
21368 : : && code != OACC_HOST_DATA
21369 : : && code != OACC_DECLARE
21370 : : && code != OACC_UPDATE
21371 : : && code != OACC_ENTER_DATA
21372 : : && code != OACC_EXIT_DATA
21373 : : && code != OACC_CACHE
21374 : : && code != OMP_CRITICAL
21375 : : && code != OMP_FOR
21376 : : && code != OACC_LOOP
21377 : : && code != OMP_MASTER
21378 : : && code != OMP_MASKED
21379 : : && code != OMP_TASKGROUP
21380 : : && code != OMP_ORDERED
21381 : : && code != OMP_PARALLEL
21382 : : && code != OMP_SCAN
21383 : : && code != OMP_SECTIONS
21384 : : && code != OMP_SECTION
21385 : : && code != OMP_STRUCTURED_BLOCK
21386 : : && code != OMP_SINGLE
21387 : : && code != OMP_SCOPE
21388 : : && code != OMP_DISPATCH);
21389 : : }
21390 : : #endif
21391 : :
21392 : : /* Otherwise we're gimplifying a subexpression, so the resulting
21393 : : value is interesting. If it's a valid operand that matches
21394 : : GIMPLE_TEST_F, we're done. Unless we are handling some
21395 : : post-effects internally; if that's the case, we need to copy into
21396 : : a temporary before adding the post-effects to POST_P. */
21397 : 364819820 : if (gimple_seq_empty_p (internal_post) && (*gimple_test_f) (*expr_p))
21398 : 338870110 : goto out;
21399 : :
21400 : : /* Otherwise, we need to create a new temporary for the gimplified
21401 : : expression. */
21402 : :
21403 : : /* We can't return an lvalue if we have an internal postqueue. The
21404 : : object the lvalue refers to would (probably) be modified by the
21405 : : postqueue; we need to copy the value out first, which means an
21406 : : rvalue. */
21407 : 25949710 : if ((fallback & fb_lvalue)
21408 : 588576 : && gimple_seq_empty_p (internal_post)
21409 : 26538286 : && is_gimple_addressable (*expr_p))
21410 : : {
21411 : : /* An lvalue will do. Take the address of the expression, store it
21412 : : in a temporary, and replace the expression with an INDIRECT_REF of
21413 : : that temporary. */
21414 : 15 : tree ref_alias_type = reference_alias_ptr_type (*expr_p);
21415 : 15 : unsigned int ref_align = get_object_alignment (*expr_p);
21416 : 15 : tree ref_type = TREE_TYPE (*expr_p);
21417 : 15 : tmp = build_fold_addr_expr_loc (input_location, *expr_p);
21418 : 15 : gimplify_expr (&tmp, pre_p, post_p, is_gimple_reg, fb_rvalue);
21419 : 15 : if (TYPE_ALIGN (ref_type) != ref_align)
21420 : 1 : ref_type = build_aligned_type (ref_type, ref_align);
21421 : 15 : *expr_p = build2 (MEM_REF, ref_type,
21422 : : tmp, build_zero_cst (ref_alias_type));
21423 : : }
21424 : 25949695 : else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p))
21425 : : {
21426 : : /* An rvalue will do. Assign the gimplified expression into a
21427 : : new temporary TMP and replace the original expression with
21428 : : TMP. First, make sure that the expression has a type so that
21429 : : it can be assigned into a temporary. */
21430 : 25949687 : gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p)));
21431 : 25949687 : *expr_p = get_formal_tmp_var (*expr_p, pre_p);
21432 : : }
21433 : : else
21434 : : {
21435 : : #ifdef ENABLE_GIMPLE_CHECKING
21436 : 8 : if (!(fallback & fb_mayfail))
21437 : : {
21438 : 0 : fprintf (stderr, "gimplification failed:\n");
21439 : 0 : print_generic_expr (stderr, *expr_p);
21440 : 0 : debug_tree (*expr_p);
21441 : 0 : internal_error ("gimplification failed");
21442 : : }
21443 : : #endif
21444 : 8 : gcc_assert (fallback & fb_mayfail);
21445 : :
21446 : : /* If this is an asm statement, and the user asked for the
21447 : : impossible, don't die. Fail and let gimplify_asm_expr
21448 : : issue an error. */
21449 : 8 : ret = GS_ERROR;
21450 : 8 : goto out;
21451 : : }
21452 : :
21453 : : /* Make sure the temporary matches our predicate. */
21454 : 25949702 : gcc_assert ((*gimple_test_f) (*expr_p));
21455 : :
21456 : 25949702 : if (!gimple_seq_empty_p (internal_post))
21457 : : {
21458 : 0 : annotate_all_with_location (internal_post, input_location);
21459 : 0 : gimplify_seq_add_seq (pre_p, internal_post);
21460 : : }
21461 : :
21462 : 25949702 : out:
21463 : 465940588 : input_location = saved_location;
21464 : 465940588 : return ret;
21465 : : }
21466 : :
21467 : : /* Like gimplify_expr but make sure the gimplified result is not itself
21468 : : a SSA name (but a decl if it were). Temporaries required by
21469 : : evaluating *EXPR_P may be still SSA names. */
21470 : :
21471 : : static enum gimplify_status
21472 : 34147900 : gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
21473 : : bool (*gimple_test_f) (tree), fallback_t fallback,
21474 : : bool allow_ssa)
21475 : : {
21476 : 34147900 : enum gimplify_status ret = gimplify_expr (expr_p, pre_p, post_p,
21477 : : gimple_test_f, fallback);
21478 : 34147900 : if (! allow_ssa
21479 : 265360 : && TREE_CODE (*expr_p) == SSA_NAME)
21480 : 68022 : *expr_p = get_initialized_tmp_var (*expr_p, pre_p, NULL, false);
21481 : 34147900 : return ret;
21482 : : }
21483 : :
21484 : : /* Look through TYPE for variable-sized objects and gimplify each such
21485 : : size that we find. Add to LIST_P any statements generated. */
21486 : :
21487 : : void
21488 : 8220619 : gimplify_type_sizes (tree type, gimple_seq *list_p)
21489 : : {
21490 : 8220619 : if (type == NULL || type == error_mark_node)
21491 : : return;
21492 : :
21493 : 8220373 : const bool ignored_p
21494 : 8220373 : = TYPE_NAME (type)
21495 : 4049760 : && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
21496 : 12049245 : && DECL_IGNORED_P (TYPE_NAME (type));
21497 : 8220373 : tree t;
21498 : :
21499 : : /* We first do the main variant, then copy into any other variants. */
21500 : 8220373 : type = TYPE_MAIN_VARIANT (type);
21501 : :
21502 : : /* Avoid infinite recursion. */
21503 : 8220373 : if (TYPE_SIZES_GIMPLIFIED (type))
21504 : : return;
21505 : :
21506 : 2463225 : TYPE_SIZES_GIMPLIFIED (type) = 1;
21507 : :
21508 : 2463225 : switch (TREE_CODE (type))
21509 : : {
21510 : 486775 : case INTEGER_TYPE:
21511 : 486775 : case ENUMERAL_TYPE:
21512 : 486775 : case BOOLEAN_TYPE:
21513 : 486775 : case REAL_TYPE:
21514 : 486775 : case FIXED_POINT_TYPE:
21515 : 486775 : gimplify_one_sizepos (&TYPE_MIN_VALUE (type), list_p);
21516 : 486775 : gimplify_one_sizepos (&TYPE_MAX_VALUE (type), list_p);
21517 : :
21518 : 8636116 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21519 : : {
21520 : 8149341 : TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (type);
21521 : 8149341 : TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (type);
21522 : : }
21523 : : break;
21524 : :
21525 : 181374 : case ARRAY_TYPE:
21526 : : /* These types may not have declarations, so handle them here. */
21527 : 181374 : gimplify_type_sizes (TREE_TYPE (type), list_p);
21528 : 181374 : gimplify_type_sizes (TYPE_DOMAIN (type), list_p);
21529 : : /* Ensure VLA bounds aren't removed, for -O0 they should be variables
21530 : : with assigned stack slots, for -O1+ -g they should be tracked
21531 : : by VTA. */
21532 : 181374 : if (!ignored_p
21533 : 181374 : && TYPE_DOMAIN (type)
21534 : 362523 : && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
21535 : : {
21536 : 181149 : t = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
21537 : 181149 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21538 : 0 : DECL_IGNORED_P (t) = 0;
21539 : 181149 : t = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
21540 : 181149 : if (t && VAR_P (t) && DECL_ARTIFICIAL (t))
21541 : 18837 : DECL_IGNORED_P (t) = 0;
21542 : : }
21543 : : break;
21544 : :
21545 : 494539 : case RECORD_TYPE:
21546 : 494539 : case UNION_TYPE:
21547 : 494539 : case QUAL_UNION_TYPE:
21548 : 10695197 : for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
21549 : 10200658 : if (TREE_CODE (field) == FIELD_DECL)
21550 : : {
21551 : 1078720 : gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
21552 : : /* Likewise, ensure variable offsets aren't removed. */
21553 : 1078720 : if (!ignored_p
21554 : 1078720 : && (t = DECL_FIELD_OFFSET (field))
21555 : 1078708 : && VAR_P (t)
21556 : 1078882 : && DECL_ARTIFICIAL (t))
21557 : 162 : DECL_IGNORED_P (t) = 0;
21558 : 1078720 : gimplify_one_sizepos (&DECL_SIZE (field), list_p);
21559 : 1078720 : gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
21560 : 1078720 : gimplify_type_sizes (TREE_TYPE (field), list_p);
21561 : : }
21562 : : break;
21563 : :
21564 : : case POINTER_TYPE:
21565 : : case REFERENCE_TYPE:
21566 : : /* We used to recurse on the pointed-to type here, which turned out to
21567 : : be incorrect because its definition might refer to variables not
21568 : : yet initialized at this point if a forward declaration is involved.
21569 : :
21570 : : It was actually useful for anonymous pointed-to types to ensure
21571 : : that the sizes evaluation dominates every possible later use of the
21572 : : values. Restricting to such types here would be safe since there
21573 : : is no possible forward declaration around, but would introduce an
21574 : : undesirable middle-end semantic to anonymity. We then defer to
21575 : : front-ends the responsibility of ensuring that the sizes are
21576 : : evaluated both early and late enough, e.g. by attaching artificial
21577 : : type declarations to the tree. */
21578 : : break;
21579 : :
21580 : : default:
21581 : : break;
21582 : : }
21583 : :
21584 : 2463225 : gimplify_one_sizepos (&TYPE_SIZE (type), list_p);
21585 : 2463225 : gimplify_one_sizepos (&TYPE_SIZE_UNIT (type), list_p);
21586 : :
21587 : 14753729 : for (t = TYPE_NEXT_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
21588 : : {
21589 : 12290504 : TYPE_SIZE (t) = TYPE_SIZE (type);
21590 : 12290504 : TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (type);
21591 : 12290504 : TYPE_SIZES_GIMPLIFIED (t) = 1;
21592 : : }
21593 : : }
21594 : :
21595 : : /* A subroutine of gimplify_type_sizes to make sure that *EXPR_P,
21596 : : a size or position, has had all of its SAVE_EXPRs evaluated.
21597 : : We add any required statements to *STMT_P. */
21598 : :
21599 : : void
21600 : 9154132 : gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
21601 : : {
21602 : 9154132 : tree expr = *expr_p;
21603 : :
21604 : : /* We don't do anything if the value isn't there, is constant, or contains
21605 : : A PLACEHOLDER_EXPR. We also don't want to do anything if it's already
21606 : : a VAR_DECL. If it's a VAR_DECL from another function, the gimplifier
21607 : : will want to replace it with a new variable, but that will cause problems
21608 : : if this type is from outside the function. It's OK to have that here. */
21609 : 9154132 : if (expr == NULL_TREE
21610 : 9157982 : || is_gimple_constant (expr)
21611 : 80162 : || VAR_P (expr)
21612 : 9230444 : || CONTAINS_PLACEHOLDER_P (expr))
21613 : 9077820 : return;
21614 : :
21615 : 76312 : *expr_p = unshare_expr (expr);
21616 : :
21617 : : /* SSA names in decl/type fields are a bad idea - they'll get reclaimed
21618 : : if the def vanishes. */
21619 : 76312 : gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false);
21620 : :
21621 : : /* If expr wasn't already is_gimple_sizepos or is_gimple_constant from the
21622 : : FE, ensure that it is a VAR_DECL, otherwise we might handle some decls
21623 : : as gimplify_vla_decl even when they would have all sizes INTEGER_CSTs. */
21624 : 76312 : if (is_gimple_constant (*expr_p))
21625 : 548 : *expr_p = get_initialized_tmp_var (*expr_p, stmt_p, NULL, false);
21626 : : }
21627 : :
21628 : : /* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
21629 : : containing the sequence of corresponding GIMPLE statements. If DO_PARMS
21630 : : is true, also gimplify the parameters. */
21631 : :
21632 : : gbind *
21633 : 2946372 : gimplify_body (tree fndecl, bool do_parms)
21634 : : {
21635 : 2946372 : location_t saved_location = input_location;
21636 : 2946372 : gimple_seq parm_stmts, parm_cleanup = NULL, seq;
21637 : 2946372 : gimple *outer_stmt;
21638 : 2946372 : gbind *outer_bind;
21639 : :
21640 : 2946372 : timevar_push (TV_TREE_GIMPLIFY);
21641 : :
21642 : 2946372 : init_tree_ssa (cfun);
21643 : :
21644 : : /* Initialize for optimize_insn_for_s{ize,peed}_p possibly called during
21645 : : gimplification. */
21646 : 2946372 : default_rtl_profile ();
21647 : :
21648 : 2946372 : gcc_assert (gimplify_ctxp == NULL);
21649 : 2946372 : push_gimplify_context (true);
21650 : :
21651 : 2946372 : if (flag_openacc || flag_openmp)
21652 : : {
21653 : 53823 : gcc_assert (gimplify_omp_ctxp == NULL);
21654 : 53823 : if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)))
21655 : 9840 : gimplify_omp_ctxp = new_omp_context (ORT_IMPLICIT_TARGET);
21656 : : }
21657 : :
21658 : : /* Unshare most shared trees in the body and in that of any nested functions.
21659 : : It would seem we don't have to do this for nested functions because
21660 : : they are supposed to be output and then the outer function gimplified
21661 : : first, but the g++ front end doesn't always do it that way. */
21662 : 2946372 : unshare_body (fndecl);
21663 : 2946372 : unvisit_body (fndecl);
21664 : :
21665 : : /* Make sure input_location isn't set to something weird. */
21666 : 2946372 : input_location = DECL_SOURCE_LOCATION (fndecl);
21667 : :
21668 : : /* Resolve callee-copies. This has to be done before processing
21669 : : the body so that DECL_VALUE_EXPR gets processed correctly. */
21670 : 2946372 : parm_stmts = do_parms ? gimplify_parameters (&parm_cleanup) : NULL;
21671 : :
21672 : : /* Gimplify the function's body. */
21673 : 2946372 : seq = NULL;
21674 : 2946372 : gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
21675 : 2946372 : outer_stmt = gimple_seq_first_nondebug_stmt (seq);
21676 : 2946372 : if (!outer_stmt)
21677 : : {
21678 : 25487 : outer_stmt = gimple_build_nop ();
21679 : 25487 : gimplify_seq_add_stmt (&seq, outer_stmt);
21680 : : }
21681 : :
21682 : : /* The body must contain exactly one statement, a GIMPLE_BIND. If this is
21683 : : not the case, wrap everything in a GIMPLE_BIND to make it so. */
21684 : 2946372 : if (gimple_code (outer_stmt) == GIMPLE_BIND
21685 : 2946372 : && (gimple_seq_first_nondebug_stmt (seq)
21686 : 1695113 : == gimple_seq_last_nondebug_stmt (seq)))
21687 : : {
21688 : 1630783 : outer_bind = as_a <gbind *> (outer_stmt);
21689 : 1630783 : if (gimple_seq_first_stmt (seq) != outer_stmt
21690 : 1630783 : || gimple_seq_last_stmt (seq) != outer_stmt)
21691 : : {
21692 : : /* If there are debug stmts before or after outer_stmt, move them
21693 : : inside of outer_bind body. */
21694 : 1 : gimple_stmt_iterator gsi = gsi_for_stmt (outer_stmt, &seq);
21695 : 1 : gimple_seq second_seq = NULL;
21696 : 1 : if (gimple_seq_first_stmt (seq) != outer_stmt
21697 : 2 : && gimple_seq_last_stmt (seq) != outer_stmt)
21698 : : {
21699 : 0 : second_seq = gsi_split_seq_after (gsi);
21700 : 0 : gsi_remove (&gsi, false);
21701 : : }
21702 : 1 : else if (gimple_seq_first_stmt (seq) != outer_stmt)
21703 : 1 : gsi_remove (&gsi, false);
21704 : : else
21705 : : {
21706 : 0 : gsi_remove (&gsi, false);
21707 : 0 : second_seq = seq;
21708 : 0 : seq = NULL;
21709 : : }
21710 : 1 : gimple_seq_add_seq_without_update (&seq,
21711 : : gimple_bind_body (outer_bind));
21712 : 1 : gimple_seq_add_seq_without_update (&seq, second_seq);
21713 : 1 : gimple_bind_set_body (outer_bind, seq);
21714 : : }
21715 : : }
21716 : : else
21717 : 1315589 : outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
21718 : :
21719 : 2946372 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
21720 : :
21721 : : /* If we had callee-copies statements, insert them at the beginning
21722 : : of the function and clear DECL_HAS_VALUE_EXPR_P on the parameters. */
21723 : 2946372 : if (!gimple_seq_empty_p (parm_stmts))
21724 : : {
21725 : 41 : tree parm;
21726 : :
21727 : 41 : gimplify_seq_add_seq (&parm_stmts, gimple_bind_body (outer_bind));
21728 : 41 : if (parm_cleanup)
21729 : : {
21730 : 0 : gtry *g = gimple_build_try (parm_stmts, parm_cleanup,
21731 : : GIMPLE_TRY_FINALLY);
21732 : 0 : parm_stmts = NULL;
21733 : 0 : gimple_seq_add_stmt (&parm_stmts, g);
21734 : : }
21735 : 41 : gimple_bind_set_body (outer_bind, parm_stmts);
21736 : :
21737 : 41 : for (parm = DECL_ARGUMENTS (current_function_decl);
21738 : 101 : parm; parm = DECL_CHAIN (parm))
21739 : 60 : if (DECL_HAS_VALUE_EXPR_P (parm))
21740 : : {
21741 : 0 : DECL_HAS_VALUE_EXPR_P (parm) = 0;
21742 : 0 : DECL_IGNORED_P (parm) = 0;
21743 : : }
21744 : : }
21745 : :
21746 : 2946372 : if ((flag_openacc || flag_openmp || flag_openmp_simd)
21747 : 56076 : && gimplify_omp_ctxp)
21748 : : {
21749 : 9893 : delete_omp_context (gimplify_omp_ctxp);
21750 : 9893 : gimplify_omp_ctxp = NULL;
21751 : : }
21752 : :
21753 : 2946372 : pop_gimplify_context (outer_bind);
21754 : 2946372 : gcc_assert (gimplify_ctxp == NULL);
21755 : :
21756 : 2946372 : if (flag_checking && !seen_error ())
21757 : 2895331 : verify_gimple_in_seq (gimple_bind_body (outer_bind));
21758 : :
21759 : 2946372 : timevar_pop (TV_TREE_GIMPLIFY);
21760 : 2946372 : input_location = saved_location;
21761 : :
21762 : 2946372 : return outer_bind;
21763 : : }
21764 : :
21765 : : typedef char *char_p; /* For DEF_VEC_P. */
21766 : :
21767 : : /* Return whether we should exclude FNDECL from instrumentation. */
21768 : :
21769 : : static bool
21770 : 39 : flag_instrument_functions_exclude_p (tree fndecl)
21771 : : {
21772 : 39 : vec<char_p> *v;
21773 : :
21774 : 39 : v = (vec<char_p> *) flag_instrument_functions_exclude_functions;
21775 : 40 : if (v && v->length () > 0)
21776 : : {
21777 : 1 : const char *name;
21778 : 1 : int i;
21779 : 1 : char *s;
21780 : :
21781 : 1 : name = lang_hooks.decl_printable_name (fndecl, 1);
21782 : 2 : FOR_EACH_VEC_ELT (*v, i, s)
21783 : 1 : if (strstr (name, s) != NULL)
21784 : 2 : return true;
21785 : : }
21786 : :
21787 : 38 : v = (vec<char_p> *) flag_instrument_functions_exclude_files;
21788 : 39 : if (v && v->length () > 0)
21789 : : {
21790 : 1 : const char *name;
21791 : 1 : int i;
21792 : 1 : char *s;
21793 : :
21794 : 1 : name = DECL_SOURCE_FILE (fndecl);
21795 : 1 : FOR_EACH_VEC_ELT (*v, i, s)
21796 : 1 : if (strstr (name, s) != NULL)
21797 : 2 : return true;
21798 : : }
21799 : :
21800 : : return false;
21801 : : }
21802 : :
21803 : : /* Build a call to the instrumentation function FNCODE and add it to SEQ.
21804 : : If COND_VAR is not NULL, it is a boolean variable guarding the call to
21805 : : the instrumentation function. IF STMT is not NULL, it is a statement
21806 : : to be executed just before the call to the instrumentation function. */
21807 : :
21808 : : static void
21809 : 74 : build_instrumentation_call (gimple_seq *seq, enum built_in_function fncode,
21810 : : tree cond_var, gimple *stmt)
21811 : : {
21812 : : /* The instrumentation hooks aren't going to call the instrumented
21813 : : function and the address they receive is expected to be matchable
21814 : : against symbol addresses. Make sure we don't create a trampoline,
21815 : : in case the current function is nested. */
21816 : 74 : tree this_fn_addr = build_fold_addr_expr (current_function_decl);
21817 : 74 : TREE_NO_TRAMPOLINE (this_fn_addr) = 1;
21818 : :
21819 : 74 : tree label_true, label_false;
21820 : 74 : if (cond_var)
21821 : : {
21822 : 16 : label_true = create_artificial_label (UNKNOWN_LOCATION);
21823 : 16 : label_false = create_artificial_label (UNKNOWN_LOCATION);
21824 : 16 : gcond *cond = gimple_build_cond (EQ_EXPR, cond_var, boolean_false_node,
21825 : : label_true, label_false);
21826 : 16 : gimplify_seq_add_stmt (seq, cond);
21827 : 16 : gimplify_seq_add_stmt (seq, gimple_build_label (label_true));
21828 : 16 : gimplify_seq_add_stmt (seq, gimple_build_predict (PRED_COLD_LABEL,
21829 : : NOT_TAKEN));
21830 : : }
21831 : :
21832 : 74 : if (stmt)
21833 : 8 : gimplify_seq_add_stmt (seq, stmt);
21834 : :
21835 : 74 : tree x = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
21836 : 74 : gcall *call = gimple_build_call (x, 1, integer_zero_node);
21837 : 74 : tree tmp_var = create_tmp_var (ptr_type_node, "return_addr");
21838 : 74 : gimple_call_set_lhs (call, tmp_var);
21839 : 74 : gimplify_seq_add_stmt (seq, call);
21840 : 74 : x = builtin_decl_implicit (fncode);
21841 : 74 : call = gimple_build_call (x, 2, this_fn_addr, tmp_var);
21842 : 74 : gimplify_seq_add_stmt (seq, call);
21843 : :
21844 : 74 : if (cond_var)
21845 : 16 : gimplify_seq_add_stmt (seq, gimple_build_label (label_false));
21846 : 74 : }
21847 : :
21848 : : /* Entry point to the gimplification pass. FNDECL is the FUNCTION_DECL
21849 : : node for the function we want to gimplify.
21850 : :
21851 : : Return the sequence of GIMPLE statements corresponding to the body
21852 : : of FNDECL. */
21853 : :
21854 : : void
21855 : 2945853 : gimplify_function_tree (tree fndecl)
21856 : : {
21857 : 2945853 : gimple_seq seq;
21858 : 2945853 : gbind *bind;
21859 : :
21860 : 2945853 : gcc_assert (!gimple_body (fndecl));
21861 : :
21862 : 2945853 : if (DECL_STRUCT_FUNCTION (fndecl))
21863 : 2942307 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
21864 : : else
21865 : 3546 : push_struct_function (fndecl);
21866 : :
21867 : 2945853 : reset_cond_uid ();
21868 : 2945853 : if (cond_uids)
21869 : : {
21870 : 65 : delete cond_uids;
21871 : 65 : cond_uids = NULL;
21872 : : }
21873 : :
21874 : : /* Tentatively set PROP_gimple_lva here, and reset it in gimplify_va_arg_expr
21875 : : if necessary. */
21876 : 2945853 : cfun->curr_properties |= PROP_gimple_lva;
21877 : :
21878 : 2945853 : if (asan_sanitize_use_after_scope ())
21879 : 8241 : asan_poisoned_variables = new hash_set<tree> ();
21880 : 2945853 : if (flag_openmp)
21881 : 46154 : omp_resolved_variant_calls = new hash_set<tree> ();
21882 : :
21883 : 2945853 : bind = gimplify_body (fndecl, true);
21884 : :
21885 : 2945853 : if (omp_resolved_variant_calls)
21886 : : {
21887 : 46154 : delete omp_resolved_variant_calls;
21888 : 46154 : omp_resolved_variant_calls = NULL;
21889 : : }
21890 : 2945853 : if (asan_poisoned_variables)
21891 : : {
21892 : 8241 : delete asan_poisoned_variables;
21893 : 8241 : asan_poisoned_variables = NULL;
21894 : : }
21895 : :
21896 : : /* The tree body of the function is no longer needed, replace it
21897 : : with the new GIMPLE body. */
21898 : 2945853 : seq = NULL;
21899 : 2945853 : gimple_seq_add_stmt (&seq, bind);
21900 : 2945853 : gimple_set_body (fndecl, seq);
21901 : :
21902 : : /* If we're instrumenting function entry/exit, then prepend the call to
21903 : : the entry hook and wrap the whole function in a TRY_FINALLY_EXPR to
21904 : : catch the exit hook. */
21905 : : /* ??? Add some way to ignore exceptions for this TFE. */
21906 : 2945853 : if (flag_instrument_function_entry_exit
21907 : 91 : && !DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (fndecl)
21908 : : /* Do not instrument extern inline functions. */
21909 : 40 : && !(DECL_DECLARED_INLINE_P (fndecl)
21910 : 5 : && DECL_EXTERNAL (fndecl)
21911 : 1 : && DECL_DISREGARD_INLINE_LIMITS (fndecl))
21912 : 2945892 : && !flag_instrument_functions_exclude_p (fndecl))
21913 : : {
21914 : 37 : gimple_seq body = NULL, cleanup = NULL;
21915 : 37 : gassign *assign;
21916 : 37 : tree cond_var;
21917 : :
21918 : : /* If -finstrument-functions-once is specified, generate:
21919 : :
21920 : : static volatile bool C.0 = false;
21921 : : bool tmp_called;
21922 : :
21923 : : tmp_called = C.0;
21924 : : if (!tmp_called)
21925 : : {
21926 : : C.0 = true;
21927 : : [call profiling enter function]
21928 : : }
21929 : :
21930 : : without specific protection for data races. */
21931 : 37 : if (flag_instrument_function_entry_exit > 1)
21932 : : {
21933 : 8 : tree first_var
21934 : 8 : = build_decl (DECL_SOURCE_LOCATION (current_function_decl),
21935 : : VAR_DECL,
21936 : : create_tmp_var_name ("C"),
21937 : : boolean_type_node);
21938 : 8 : DECL_ARTIFICIAL (first_var) = 1;
21939 : 8 : DECL_IGNORED_P (first_var) = 1;
21940 : 8 : TREE_STATIC (first_var) = 1;
21941 : 8 : TREE_THIS_VOLATILE (first_var) = 1;
21942 : 8 : TREE_USED (first_var) = 1;
21943 : 8 : DECL_INITIAL (first_var) = boolean_false_node;
21944 : 8 : varpool_node::add (first_var);
21945 : :
21946 : 8 : cond_var = create_tmp_var (boolean_type_node, "tmp_called");
21947 : 8 : assign = gimple_build_assign (cond_var, first_var);
21948 : 8 : gimplify_seq_add_stmt (&body, assign);
21949 : :
21950 : 8 : assign = gimple_build_assign (first_var, boolean_true_node);
21951 : : }
21952 : :
21953 : : else
21954 : : {
21955 : : cond_var = NULL_TREE;
21956 : : assign = NULL;
21957 : : }
21958 : :
21959 : 37 : build_instrumentation_call (&body, BUILT_IN_PROFILE_FUNC_ENTER,
21960 : : cond_var, assign);
21961 : :
21962 : : /* If -finstrument-functions-once is specified, generate:
21963 : :
21964 : : if (!tmp_called)
21965 : : [call profiling exit function]
21966 : :
21967 : : without specific protection for data races. */
21968 : 37 : build_instrumentation_call (&cleanup, BUILT_IN_PROFILE_FUNC_EXIT,
21969 : : cond_var, NULL);
21970 : :
21971 : 37 : gimple *tf = gimple_build_try (seq, cleanup, GIMPLE_TRY_FINALLY);
21972 : 37 : gimplify_seq_add_stmt (&body, tf);
21973 : 37 : gbind *new_bind = gimple_build_bind (NULL, body, NULL);
21974 : :
21975 : : /* Replace the current function body with the body
21976 : : wrapped in the try/finally TF. */
21977 : 37 : seq = NULL;
21978 : 37 : gimple_seq_add_stmt (&seq, new_bind);
21979 : 37 : gimple_set_body (fndecl, seq);
21980 : 37 : bind = new_bind;
21981 : : }
21982 : :
21983 : 2945853 : if (sanitize_flags_p (SANITIZE_THREAD)
21984 : 2945853 : && param_tsan_instrument_func_entry_exit)
21985 : : {
21986 : 1057 : gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
21987 : 1057 : gimple *tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
21988 : 1057 : gbind *new_bind = gimple_build_bind (NULL, tf, NULL);
21989 : : /* Replace the current function body with the body
21990 : : wrapped in the try/finally TF. */
21991 : 1057 : seq = NULL;
21992 : 1057 : gimple_seq_add_stmt (&seq, new_bind);
21993 : 1057 : gimple_set_body (fndecl, seq);
21994 : : }
21995 : :
21996 : 2945853 : DECL_SAVED_TREE (fndecl) = NULL_TREE;
21997 : 2945853 : cfun->curr_properties |= PROP_gimple_any;
21998 : :
21999 : 2945853 : pop_cfun ();
22000 : :
22001 : 2945853 : dump_function (TDI_gimple, fndecl);
22002 : 2945853 : }
22003 : :
22004 : : /* Return a dummy expression of type TYPE in order to keep going after an
22005 : : error. */
22006 : :
22007 : : static tree
22008 : 30 : dummy_object (tree type)
22009 : : {
22010 : 30 : tree t = build_int_cst (build_pointer_type (type), 0);
22011 : 30 : return build2 (MEM_REF, type, t, t);
22012 : : }
22013 : :
22014 : : /* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a
22015 : : builtin function, but a very special sort of operator. */
22016 : :
22017 : : enum gimplify_status
22018 : 50935 : gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p,
22019 : : gimple_seq *post_p ATTRIBUTE_UNUSED)
22020 : : {
22021 : 50935 : tree promoted_type, have_va_type;
22022 : 50935 : tree valist = TREE_OPERAND (*expr_p, 0);
22023 : 50935 : tree type = TREE_TYPE (*expr_p);
22024 : 50935 : tree t, tag, aptag;
22025 : 50935 : location_t loc = EXPR_LOCATION (*expr_p);
22026 : :
22027 : : /* Verify that valist is of the proper type. */
22028 : 50935 : have_va_type = TREE_TYPE (valist);
22029 : 50935 : if (have_va_type == error_mark_node)
22030 : : return GS_ERROR;
22031 : 50916 : have_va_type = targetm.canonical_va_list_type (have_va_type);
22032 : 50916 : if (have_va_type == NULL_TREE
22033 : 50916 : && POINTER_TYPE_P (TREE_TYPE (valist)))
22034 : : /* Handle 'Case 1: Not an array type' from c-common.cc/build_va_arg. */
22035 : 258 : have_va_type
22036 : 258 : = targetm.canonical_va_list_type (TREE_TYPE (TREE_TYPE (valist)));
22037 : 50916 : gcc_assert (have_va_type != NULL_TREE);
22038 : :
22039 : : /* Generate a diagnostic for requesting data of a type that cannot
22040 : : be passed through `...' due to type promotion at the call site. */
22041 : 50916 : if ((promoted_type = lang_hooks.types.type_promotes_to (type))
22042 : : != type)
22043 : : {
22044 : 30 : static bool gave_help;
22045 : 30 : bool warned;
22046 : : /* Use the expansion point to handle cases such as passing bool (defined
22047 : : in a system header) through `...'. */
22048 : 30 : location_t xloc
22049 : 30 : = expansion_point_location_if_in_system_header (loc);
22050 : :
22051 : : /* Unfortunately, this is merely undefined, rather than a constraint
22052 : : violation, so we cannot make this an error. If this call is never
22053 : : executed, the program is still strictly conforming. */
22054 : 30 : auto_diagnostic_group d;
22055 : 30 : warned = warning_at (xloc, 0,
22056 : : "%qT is promoted to %qT when passed through %<...%>",
22057 : : type, promoted_type);
22058 : 30 : if (!gave_help && warned)
22059 : : {
22060 : 15 : gave_help = true;
22061 : 15 : inform (xloc, "(so you should pass %qT not %qT to %<va_arg%>)",
22062 : : promoted_type, type);
22063 : : }
22064 : :
22065 : : /* We can, however, treat "undefined" any way we please.
22066 : : Call abort to encourage the user to fix the program. */
22067 : 23 : if (warned)
22068 : 23 : inform (xloc, "if this code is reached, the program will abort");
22069 : : /* Before the abort, allow the evaluation of the va_list
22070 : : expression to exit or longjmp. */
22071 : 30 : gimplify_and_add (valist, pre_p);
22072 : 60 : t = build_call_expr_loc (loc,
22073 : : builtin_decl_implicit (BUILT_IN_TRAP), 0);
22074 : 30 : gimplify_and_add (t, pre_p);
22075 : :
22076 : : /* This is dead code, but go ahead and finish so that the
22077 : : mode of the result comes out right. */
22078 : 30 : *expr_p = dummy_object (type);
22079 : 30 : return GS_ALL_DONE;
22080 : 30 : }
22081 : :
22082 : 50886 : tag = build_int_cst (build_pointer_type (type), 0);
22083 : 50886 : aptag = build_int_cst (TREE_TYPE (valist), 0);
22084 : :
22085 : 50886 : *expr_p = build_call_expr_internal_loc (loc, IFN_VA_ARG, type, 3,
22086 : : valist, tag, aptag);
22087 : :
22088 : : /* Clear the tentatively set PROP_gimple_lva, to indicate that IFN_VA_ARG
22089 : : needs to be expanded. */
22090 : 50886 : cfun->curr_properties &= ~PROP_gimple_lva;
22091 : :
22092 : 50886 : return GS_OK;
22093 : : }
22094 : :
22095 : : /* Build a new GIMPLE_ASSIGN tuple and append it to the end of *SEQ_P.
22096 : :
22097 : : DST/SRC are the destination and source respectively. You can pass
22098 : : ungimplified trees in DST or SRC, in which case they will be
22099 : : converted to a gimple operand if necessary.
22100 : :
22101 : : This function returns the newly created GIMPLE_ASSIGN tuple. */
22102 : :
22103 : : gimple *
22104 : 904823 : gimplify_assign (tree dst, tree src, gimple_seq *seq_p)
22105 : : {
22106 : 904823 : tree t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
22107 : 904823 : gimplify_and_add (t, seq_p);
22108 : 904823 : ggc_free (t);
22109 : 904823 : return gimple_seq_last_stmt (*seq_p);
22110 : : }
22111 : :
22112 : : inline hashval_t
22113 : 1564505 : gimplify_hasher::hash (const elt_t *p)
22114 : : {
22115 : 1564505 : tree t = p->val;
22116 : 1564505 : return iterative_hash_expr (t, 0);
22117 : : }
22118 : :
22119 : : inline bool
22120 : 583754 : gimplify_hasher::equal (const elt_t *p1, const elt_t *p2)
22121 : : {
22122 : 583754 : tree t1 = p1->val;
22123 : 583754 : tree t2 = p2->val;
22124 : 583754 : enum tree_code code = TREE_CODE (t1);
22125 : :
22126 : 583754 : if (TREE_CODE (t2) != code
22127 : 583754 : || TREE_TYPE (t1) != TREE_TYPE (t2))
22128 : : return false;
22129 : :
22130 : 358435 : if (!operand_equal_p (t1, t2, 0))
22131 : : return false;
22132 : :
22133 : : return true;
22134 : : }
|