]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/omp-low.c
2015-10-29 Andrew MacLeod <amacleod@redhat.com>
[thirdparty/gcc.git] / gcc / omp-low.c
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
4
5 Contributed by Diego Novillo <dnovillo@redhat.com>
6
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
8
9 This file is part of GCC.
10
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
15
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
24
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "cfghooks.h"
34 #include "alloc-pool.h"
35 #include "tree-pass.h"
36 #include "ssa.h"
37 #include "expmed.h"
38 #include "optabs.h"
39 #include "emit-rtl.h"
40 #include "cgraph.h"
41 #include "pretty-print.h"
42 #include "diagnostic-core.h"
43 #include "alias.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
46 #include "cfganal.h"
47 #include "internal-fn.h"
48 #include "gimple-fold.h"
49 #include "gimplify.h"
50 #include "gimple-iterator.h"
51 #include "gimplify-me.h"
52 #include "gimple-walk.h"
53 #include "tree-iterator.h"
54 #include "tree-inline.h"
55 #include "langhooks.h"
56 #include "tree-cfg.h"
57 #include "tree-into-ssa.h"
58 #include "flags.h"
59 #include "dojump.h"
60 #include "explow.h"
61 #include "calls.h"
62 #include "varasm.h"
63 #include "stmt.h"
64 #include "expr.h"
65 #include "tree-dfa.h"
66 #include "tree-ssa.h"
67 #include "except.h"
68 #include "splay-tree.h"
69 #include "cfgloop.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "symbol-summary.h"
75 #include "ipa-prop.h"
76 #include "tree-nested.h"
77 #include "tree-eh.h"
78 #include "cilk.h"
79 #include "context.h"
80 #include "lto-section-names.h"
81 #include "gomp-constants.h"
82 #include "gimple-pretty-print.h"
83
84 /* Lowering of OMP parallel and workshare constructs proceeds in two
85 phases. The first phase scans the function looking for OMP statements
86 and then for variables that must be replaced to satisfy data sharing
87 clauses. The second phase expands code for the constructs, as well as
88 re-gimplifying things when variables have been replaced with complex
89 expressions.
90
91 Final code generation is done by pass_expand_omp. The flowgraph is
92 scanned for regions which are then moved to a new
93 function, to be invoked by the thread library, or offloaded. */
94
95 /* OMP region information. Every parallel and workshare
96 directive is enclosed between two markers, the OMP_* directive
97 and a corresponding GIMPLE_OMP_RETURN statement. */
98
99 struct omp_region
100 {
101 /* The enclosing region. */
102 struct omp_region *outer;
103
104 /* First child region. */
105 struct omp_region *inner;
106
107 /* Next peer region. */
108 struct omp_region *next;
109
110 /* Block containing the omp directive as its last stmt. */
111 basic_block entry;
112
113 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
114 basic_block exit;
115
116 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
117 basic_block cont;
118
119 /* If this is a combined parallel+workshare region, this is a list
120 of additional arguments needed by the combined parallel+workshare
121 library call. */
122 vec<tree, va_gc> *ws_args;
123
124 /* The code for the omp directive of this region. */
125 enum gimple_code type;
126
127 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
128 enum omp_clause_schedule_kind sched_kind;
129
130 /* True if this is a combined parallel+workshare region. */
131 bool is_combined_parallel;
132
133 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
134 a depend clause. */
135 gomp_ordered *ord_stmt;
136 };
137
138 /* Context structure. Used to store information about each parallel
139 directive in the code. */
140
141 struct omp_context
142 {
143 /* This field must be at the beginning, as we do "inheritance": Some
144 callback functions for tree-inline.c (e.g., omp_copy_decl)
145 receive a copy_body_data pointer that is up-casted to an
146 omp_context pointer. */
147 copy_body_data cb;
148
149 /* The tree of contexts corresponding to the encountered constructs. */
150 struct omp_context *outer;
151 gimple *stmt;
152
153 /* Map variables to fields in a structure that allows communication
154 between sending and receiving threads. */
155 splay_tree field_map;
156 tree record_type;
157 tree sender_decl;
158 tree receiver_decl;
159
160 /* These are used just by task contexts, if task firstprivate fn is
161 needed. srecord_type is used to communicate from the thread
162 that encountered the task construct to task firstprivate fn,
163 record_type is allocated by GOMP_task, initialized by task firstprivate
164 fn and passed to the task body fn. */
165 splay_tree sfield_map;
166 tree srecord_type;
167
168 /* A chain of variables to add to the top-level block surrounding the
169 construct. In the case of a parallel, this is in the child function. */
170 tree block_vars;
171
172 /* A map of reduction pointer variables. For accelerators, each
173 reduction variable is replaced with an array. Each thread, in turn,
174 is assigned to a slot on that array. */
175 splay_tree reduction_map;
176
177 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
178 barriers should jump to during omplower pass. */
179 tree cancel_label;
180
181 /* What to do with variables with implicitly determined sharing
182 attributes. */
183 enum omp_clause_default_kind default_kind;
184
185 /* Nesting depth of this context. Used to beautify error messages re
186 invalid gotos. The outermost ctx is depth 1, with depth 0 being
187 reserved for the main body of the function. */
188 int depth;
189
190 /* True if this parallel directive is nested within another. */
191 bool is_nested;
192
193 /* True if this construct can be cancelled. */
194 bool cancellable;
195 };
196
197 /* A structure holding the elements of:
198 for (V = N1; V cond N2; V += STEP) [...] */
199
200 struct omp_for_data_loop
201 {
202 tree v, n1, n2, step;
203 enum tree_code cond_code;
204 };
205
206 /* A structure describing the main elements of a parallel loop. */
207
208 struct omp_for_data
209 {
210 struct omp_for_data_loop loop;
211 tree chunk_size;
212 gomp_for *for_stmt;
213 tree pre, iter_type;
214 int collapse;
215 int ordered;
216 bool have_nowait, have_ordered, simd_schedule;
217 enum omp_clause_schedule_kind sched_kind;
218 struct omp_for_data_loop *loops;
219 };
220
221 /* Describe the OpenACC looping structure of a function. The entire
222 function is held in a 'NULL' loop. */
223
224 struct oacc_loop
225 {
226 oacc_loop *parent; /* Containing loop. */
227
228 oacc_loop *child; /* First inner loop. */
229
230 oacc_loop *sibling; /* Next loop within same parent. */
231
232 location_t loc; /* Location of the loop start. */
233
234 gcall *marker; /* Initial head marker. */
235
236 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
237 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
238
239 tree routine; /* Pseudo-loop enclosing a routine. */
240
241 unsigned mask; /* Partitioning mask. */
242 unsigned flags; /* Partitioning flags. */
243 tree chunk_size; /* Chunk size. */
244 gcall *head_end; /* Final marker of head sequence. */
245 };
246
247 /* Flags for an OpenACC loop. */
248
249 enum oacc_loop_flags {
250 OLF_SEQ = 1u << 0, /* Explicitly sequential */
251 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
252 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
253 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
254
255 /* Explicitly specified loop axes. */
256 OLF_DIM_BASE = 4,
257 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
258 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
259 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
260
261 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
262 };
263
264
265 static splay_tree all_contexts;
266 static int taskreg_nesting_level;
267 static int target_nesting_level;
268 static struct omp_region *root_omp_region;
269 static bitmap task_shared_vars;
270 static vec<omp_context *> taskreg_contexts;
271
272 static void scan_omp (gimple_seq *, omp_context *);
273 static tree scan_omp_1_op (tree *, int *, void *);
274 static gphi *find_phi_with_arg_on_edge (tree, edge);
275
276 #define WALK_SUBSTMTS \
277 case GIMPLE_BIND: \
278 case GIMPLE_TRY: \
279 case GIMPLE_CATCH: \
280 case GIMPLE_EH_FILTER: \
281 case GIMPLE_TRANSACTION: \
282 /* The sub-statements for these should be walked. */ \
283 *handled_ops_p = false; \
284 break;
285
286 /* Return true if CTX corresponds to an oacc parallel region. */
287
288 static bool
289 is_oacc_parallel (omp_context *ctx)
290 {
291 enum gimple_code outer_type = gimple_code (ctx->stmt);
292 return ((outer_type == GIMPLE_OMP_TARGET)
293 && (gimple_omp_target_kind (ctx->stmt)
294 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
295 }
296
297 /* Return true if CTX corresponds to an oacc kernels region. */
298
299 static bool
300 is_oacc_kernels (omp_context *ctx)
301 {
302 enum gimple_code outer_type = gimple_code (ctx->stmt);
303 return ((outer_type == GIMPLE_OMP_TARGET)
304 && (gimple_omp_target_kind (ctx->stmt)
305 == GF_OMP_TARGET_KIND_OACC_KERNELS));
306 }
307
308 /* Helper function to get the name of the array containing the partial
309 reductions for OpenACC reductions. */
310 static const char *
311 oacc_get_reduction_array_id (tree node)
312 {
313 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
314 int len = strlen ("OACC") + strlen (id);
315 char *temp_name = XALLOCAVEC (char, len + 1);
316 snprintf (temp_name, len + 1, "OACC%s", id);
317 return IDENTIFIER_POINTER (get_identifier (temp_name));
318 }
319
320 /* Determine the number of threads OpenACC threads used to determine the
321 size of the array of partial reductions. Currently, this is num_gangs
322 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
323 because it is independed of the device used. */
324
325 static tree
326 oacc_max_threads (omp_context *ctx)
327 {
328 tree nthreads, vector_length, gangs, clauses;
329
330 gangs = fold_convert (sizetype, integer_one_node);
331 vector_length = gangs;
332
333 /* The reduction clause may be nested inside a loop directive.
334 Scan for the innermost vector_length clause. */
335 for (omp_context *oc = ctx; oc; oc = oc->outer)
336 {
337 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
338 || (gimple_omp_target_kind (oc->stmt)
339 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
340 continue;
341
342 clauses = gimple_omp_target_clauses (oc->stmt);
343
344 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
345 if (vector_length)
346 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
347 sizetype,
348 OMP_CLAUSE_VECTOR_LENGTH_EXPR
349 (vector_length));
350 else
351 vector_length = fold_convert (sizetype, integer_one_node);
352
353 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
354 if (gangs)
355 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
356 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
357 else
358 gangs = fold_convert (sizetype, integer_one_node);
359
360 break;
361 }
362
363 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
364
365 return nthreads;
366 }
367
368 /* If DECL is the artificial dummy VAR_DECL created for non-static
369 data member privatization, return the underlying "this" parameter,
370 otherwise return NULL. */
371
372 tree
373 omp_member_access_dummy_var (tree decl)
374 {
375 if (!VAR_P (decl)
376 || !DECL_ARTIFICIAL (decl)
377 || !DECL_IGNORED_P (decl)
378 || !DECL_HAS_VALUE_EXPR_P (decl)
379 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
380 return NULL_TREE;
381
382 tree v = DECL_VALUE_EXPR (decl);
383 if (TREE_CODE (v) != COMPONENT_REF)
384 return NULL_TREE;
385
386 while (1)
387 switch (TREE_CODE (v))
388 {
389 case COMPONENT_REF:
390 case MEM_REF:
391 case INDIRECT_REF:
392 CASE_CONVERT:
393 case POINTER_PLUS_EXPR:
394 v = TREE_OPERAND (v, 0);
395 continue;
396 case PARM_DECL:
397 if (DECL_CONTEXT (v) == current_function_decl
398 && DECL_ARTIFICIAL (v)
399 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
400 return v;
401 return NULL_TREE;
402 default:
403 return NULL_TREE;
404 }
405 }
406
407 /* Helper for unshare_and_remap, called through walk_tree. */
408
409 static tree
410 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
411 {
412 tree *pair = (tree *) data;
413 if (*tp == pair[0])
414 {
415 *tp = unshare_expr (pair[1]);
416 *walk_subtrees = 0;
417 }
418 else if (IS_TYPE_OR_DECL_P (*tp))
419 *walk_subtrees = 0;
420 return NULL_TREE;
421 }
422
423 /* Return unshare_expr (X) with all occurrences of FROM
424 replaced with TO. */
425
426 static tree
427 unshare_and_remap (tree x, tree from, tree to)
428 {
429 tree pair[2] = { from, to };
430 x = unshare_expr (x);
431 walk_tree (&x, unshare_and_remap_1, pair, NULL);
432 return x;
433 }
434
435 /* Holds offload tables with decls. */
436 vec<tree, va_gc> *offload_funcs, *offload_vars;
437
438 /* Convenience function for calling scan_omp_1_op on tree operands. */
439
440 static inline tree
441 scan_omp_op (tree *tp, omp_context *ctx)
442 {
443 struct walk_stmt_info wi;
444
445 memset (&wi, 0, sizeof (wi));
446 wi.info = ctx;
447 wi.want_locations = true;
448
449 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
450 }
451
452 static void lower_omp (gimple_seq *, omp_context *);
453 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
454 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
455
456 /* Find an OMP clause of type KIND within CLAUSES. */
457
458 tree
459 find_omp_clause (tree clauses, enum omp_clause_code kind)
460 {
461 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
462 if (OMP_CLAUSE_CODE (clauses) == kind)
463 return clauses;
464
465 return NULL_TREE;
466 }
467
468 /* Return true if CTX is for an omp parallel. */
469
470 static inline bool
471 is_parallel_ctx (omp_context *ctx)
472 {
473 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
474 }
475
476
477 /* Return true if CTX is for an omp task. */
478
479 static inline bool
480 is_task_ctx (omp_context *ctx)
481 {
482 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
483 }
484
485
486 /* Return true if CTX is for an omp taskloop. */
487
488 static inline bool
489 is_taskloop_ctx (omp_context *ctx)
490 {
491 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
492 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
493 }
494
495
496 /* Return true if CTX is for an omp parallel or omp task. */
497
498 static inline bool
499 is_taskreg_ctx (omp_context *ctx)
500 {
501 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
502 }
503
504
505 /* Return true if REGION is a combined parallel+workshare region. */
506
507 static inline bool
508 is_combined_parallel (struct omp_region *region)
509 {
510 return region->is_combined_parallel;
511 }
512
513
514 /* Extract the header elements of parallel loop FOR_STMT and store
515 them into *FD. */
516
517 static void
518 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
519 struct omp_for_data_loop *loops)
520 {
521 tree t, var, *collapse_iter, *collapse_count;
522 tree count = NULL_TREE, iter_type = long_integer_type_node;
523 struct omp_for_data_loop *loop;
524 int i;
525 struct omp_for_data_loop dummy_loop;
526 location_t loc = gimple_location (for_stmt);
527 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
528 bool distribute = gimple_omp_for_kind (for_stmt)
529 == GF_OMP_FOR_KIND_DISTRIBUTE;
530 bool taskloop = gimple_omp_for_kind (for_stmt)
531 == GF_OMP_FOR_KIND_TASKLOOP;
532 tree iterv, countv;
533
534 fd->for_stmt = for_stmt;
535 fd->pre = NULL;
536 if (gimple_omp_for_collapse (for_stmt) > 1)
537 fd->loops = loops;
538 else
539 fd->loops = &fd->loop;
540
541 fd->have_nowait = distribute || simd;
542 fd->have_ordered = false;
543 fd->collapse = 1;
544 fd->ordered = 0;
545 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
546 fd->chunk_size = NULL_TREE;
547 fd->simd_schedule = false;
548 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
549 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
550 collapse_iter = NULL;
551 collapse_count = NULL;
552
553 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
554 switch (OMP_CLAUSE_CODE (t))
555 {
556 case OMP_CLAUSE_NOWAIT:
557 fd->have_nowait = true;
558 break;
559 case OMP_CLAUSE_ORDERED:
560 fd->have_ordered = true;
561 if (OMP_CLAUSE_ORDERED_EXPR (t))
562 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
563 break;
564 case OMP_CLAUSE_SCHEDULE:
565 gcc_assert (!distribute && !taskloop);
566 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
567 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
568 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
569 break;
570 case OMP_CLAUSE_DIST_SCHEDULE:
571 gcc_assert (distribute);
572 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
573 break;
574 case OMP_CLAUSE_COLLAPSE:
575 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
576 if (fd->collapse > 1)
577 {
578 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
579 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
580 }
581 break;
582 default:
583 break;
584 }
585 if (fd->ordered && fd->collapse == 1 && loops != NULL)
586 {
587 fd->loops = loops;
588 iterv = NULL_TREE;
589 countv = NULL_TREE;
590 collapse_iter = &iterv;
591 collapse_count = &countv;
592 }
593
594 /* FIXME: for now map schedule(auto) to schedule(static).
595 There should be analysis to determine whether all iterations
596 are approximately the same amount of work (then schedule(static)
597 is best) or if it varies (then schedule(dynamic,N) is better). */
598 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
599 {
600 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
601 gcc_assert (fd->chunk_size == NULL);
602 }
603 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
604 if (taskloop)
605 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
606 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
607 gcc_assert (fd->chunk_size == NULL);
608 else if (fd->chunk_size == NULL)
609 {
610 /* We only need to compute a default chunk size for ordered
611 static loops and dynamic loops. */
612 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
613 || fd->have_ordered)
614 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
615 ? integer_zero_node : integer_one_node;
616 }
617
618 int cnt = fd->ordered ? fd->ordered : fd->collapse;
619 for (i = 0; i < cnt; i++)
620 {
621 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
622 loop = &fd->loop;
623 else if (loops != NULL)
624 loop = loops + i;
625 else
626 loop = &dummy_loop;
627
628 loop->v = gimple_omp_for_index (for_stmt, i);
629 gcc_assert (SSA_VAR_P (loop->v));
630 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
631 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
632 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
633 loop->n1 = gimple_omp_for_initial (for_stmt, i);
634
635 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
636 loop->n2 = gimple_omp_for_final (for_stmt, i);
637 switch (loop->cond_code)
638 {
639 case LT_EXPR:
640 case GT_EXPR:
641 break;
642 case NE_EXPR:
643 gcc_assert (gimple_omp_for_kind (for_stmt)
644 == GF_OMP_FOR_KIND_CILKSIMD
645 || (gimple_omp_for_kind (for_stmt)
646 == GF_OMP_FOR_KIND_CILKFOR));
647 break;
648 case LE_EXPR:
649 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
650 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
651 else
652 loop->n2 = fold_build2_loc (loc,
653 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
654 build_int_cst (TREE_TYPE (loop->n2), 1));
655 loop->cond_code = LT_EXPR;
656 break;
657 case GE_EXPR:
658 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
659 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
660 else
661 loop->n2 = fold_build2_loc (loc,
662 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
663 build_int_cst (TREE_TYPE (loop->n2), 1));
664 loop->cond_code = GT_EXPR;
665 break;
666 default:
667 gcc_unreachable ();
668 }
669
670 t = gimple_omp_for_incr (for_stmt, i);
671 gcc_assert (TREE_OPERAND (t, 0) == var);
672 switch (TREE_CODE (t))
673 {
674 case PLUS_EXPR:
675 loop->step = TREE_OPERAND (t, 1);
676 break;
677 case POINTER_PLUS_EXPR:
678 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
679 break;
680 case MINUS_EXPR:
681 loop->step = TREE_OPERAND (t, 1);
682 loop->step = fold_build1_loc (loc,
683 NEGATE_EXPR, TREE_TYPE (loop->step),
684 loop->step);
685 break;
686 default:
687 gcc_unreachable ();
688 }
689
690 if (simd
691 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
692 && !fd->have_ordered))
693 {
694 if (fd->collapse == 1)
695 iter_type = TREE_TYPE (loop->v);
696 else if (i == 0
697 || TYPE_PRECISION (iter_type)
698 < TYPE_PRECISION (TREE_TYPE (loop->v)))
699 iter_type
700 = build_nonstandard_integer_type
701 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
702 }
703 else if (iter_type != long_long_unsigned_type_node)
704 {
705 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
706 iter_type = long_long_unsigned_type_node;
707 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
708 && TYPE_PRECISION (TREE_TYPE (loop->v))
709 >= TYPE_PRECISION (iter_type))
710 {
711 tree n;
712
713 if (loop->cond_code == LT_EXPR)
714 n = fold_build2_loc (loc,
715 PLUS_EXPR, TREE_TYPE (loop->v),
716 loop->n2, loop->step);
717 else
718 n = loop->n1;
719 if (TREE_CODE (n) != INTEGER_CST
720 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
721 iter_type = long_long_unsigned_type_node;
722 }
723 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
724 > TYPE_PRECISION (iter_type))
725 {
726 tree n1, n2;
727
728 if (loop->cond_code == LT_EXPR)
729 {
730 n1 = loop->n1;
731 n2 = fold_build2_loc (loc,
732 PLUS_EXPR, TREE_TYPE (loop->v),
733 loop->n2, loop->step);
734 }
735 else
736 {
737 n1 = fold_build2_loc (loc,
738 MINUS_EXPR, TREE_TYPE (loop->v),
739 loop->n2, loop->step);
740 n2 = loop->n1;
741 }
742 if (TREE_CODE (n1) != INTEGER_CST
743 || TREE_CODE (n2) != INTEGER_CST
744 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
745 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
746 iter_type = long_long_unsigned_type_node;
747 }
748 }
749
750 if (i >= fd->collapse)
751 continue;
752
753 if (collapse_count && *collapse_count == NULL)
754 {
755 t = fold_binary (loop->cond_code, boolean_type_node,
756 fold_convert (TREE_TYPE (loop->v), loop->n1),
757 fold_convert (TREE_TYPE (loop->v), loop->n2));
758 if (t && integer_zerop (t))
759 count = build_zero_cst (long_long_unsigned_type_node);
760 else if ((i == 0 || count != NULL_TREE)
761 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
762 && TREE_CONSTANT (loop->n1)
763 && TREE_CONSTANT (loop->n2)
764 && TREE_CODE (loop->step) == INTEGER_CST)
765 {
766 tree itype = TREE_TYPE (loop->v);
767
768 if (POINTER_TYPE_P (itype))
769 itype = signed_type_for (itype);
770 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
771 t = fold_build2_loc (loc,
772 PLUS_EXPR, itype,
773 fold_convert_loc (loc, itype, loop->step), t);
774 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
775 fold_convert_loc (loc, itype, loop->n2));
776 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
777 fold_convert_loc (loc, itype, loop->n1));
778 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
779 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
780 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
781 fold_build1_loc (loc, NEGATE_EXPR, itype,
782 fold_convert_loc (loc, itype,
783 loop->step)));
784 else
785 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
786 fold_convert_loc (loc, itype, loop->step));
787 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
788 if (count != NULL_TREE)
789 count = fold_build2_loc (loc,
790 MULT_EXPR, long_long_unsigned_type_node,
791 count, t);
792 else
793 count = t;
794 if (TREE_CODE (count) != INTEGER_CST)
795 count = NULL_TREE;
796 }
797 else if (count && !integer_zerop (count))
798 count = NULL_TREE;
799 }
800 }
801
802 if (count
803 && !simd
804 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
805 || fd->have_ordered))
806 {
807 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
808 iter_type = long_long_unsigned_type_node;
809 else
810 iter_type = long_integer_type_node;
811 }
812 else if (collapse_iter && *collapse_iter != NULL)
813 iter_type = TREE_TYPE (*collapse_iter);
814 fd->iter_type = iter_type;
815 if (collapse_iter && *collapse_iter == NULL)
816 *collapse_iter = create_tmp_var (iter_type, ".iter");
817 if (collapse_count && *collapse_count == NULL)
818 {
819 if (count)
820 *collapse_count = fold_convert_loc (loc, iter_type, count);
821 else
822 *collapse_count = create_tmp_var (iter_type, ".count");
823 }
824
825 if (fd->collapse > 1 || (fd->ordered && loops))
826 {
827 fd->loop.v = *collapse_iter;
828 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
829 fd->loop.n2 = *collapse_count;
830 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
831 fd->loop.cond_code = LT_EXPR;
832 }
833 else if (loops)
834 loops[0] = fd->loop;
835 }
836
837
838 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
839 is the immediate dominator of PAR_ENTRY_BB, return true if there
840 are no data dependencies that would prevent expanding the parallel
841 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
842
843 When expanding a combined parallel+workshare region, the call to
844 the child function may need additional arguments in the case of
845 GIMPLE_OMP_FOR regions. In some cases, these arguments are
846 computed out of variables passed in from the parent to the child
847 via 'struct .omp_data_s'. For instance:
848
849 #pragma omp parallel for schedule (guided, i * 4)
850 for (j ...)
851
852 Is lowered into:
853
854 # BLOCK 2 (PAR_ENTRY_BB)
855 .omp_data_o.i = i;
856 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
857
858 # BLOCK 3 (WS_ENTRY_BB)
859 .omp_data_i = &.omp_data_o;
860 D.1667 = .omp_data_i->i;
861 D.1598 = D.1667 * 4;
862 #pragma omp for schedule (guided, D.1598)
863
864 When we outline the parallel region, the call to the child function
865 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
866 that value is computed *after* the call site. So, in principle we
867 cannot do the transformation.
868
869 To see whether the code in WS_ENTRY_BB blocks the combined
870 parallel+workshare call, we collect all the variables used in the
871 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
872 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
873 call.
874
875 FIXME. If we had the SSA form built at this point, we could merely
876 hoist the code in block 3 into block 2 and be done with it. But at
877 this point we don't have dataflow information and though we could
878 hack something up here, it is really not worth the aggravation. */
879
880 static bool
881 workshare_safe_to_combine_p (basic_block ws_entry_bb)
882 {
883 struct omp_for_data fd;
884 gimple *ws_stmt = last_stmt (ws_entry_bb);
885
886 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
887 return true;
888
889 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
890
891 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
892
893 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
894 return false;
895 if (fd.iter_type != long_integer_type_node)
896 return false;
897
898 /* FIXME. We give up too easily here. If any of these arguments
899 are not constants, they will likely involve variables that have
900 been mapped into fields of .omp_data_s for sharing with the child
901 function. With appropriate data flow, it would be possible to
902 see through this. */
903 if (!is_gimple_min_invariant (fd.loop.n1)
904 || !is_gimple_min_invariant (fd.loop.n2)
905 || !is_gimple_min_invariant (fd.loop.step)
906 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
907 return false;
908
909 return true;
910 }
911
912
913 static int omp_max_vf (void);
914
915 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
916 presence (SIMD_SCHEDULE). */
917
918 static tree
919 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
920 {
921 if (!simd_schedule)
922 return chunk_size;
923
924 int vf = omp_max_vf ();
925 if (vf == 1)
926 return chunk_size;
927
928 tree type = TREE_TYPE (chunk_size);
929 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
930 build_int_cst (type, vf - 1));
931 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
932 build_int_cst (type, -vf));
933 }
934
935
936 /* Collect additional arguments needed to emit a combined
937 parallel+workshare call. WS_STMT is the workshare directive being
938 expanded. */
939
940 static vec<tree, va_gc> *
941 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
942 {
943 tree t;
944 location_t loc = gimple_location (ws_stmt);
945 vec<tree, va_gc> *ws_args;
946
947 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
948 {
949 struct omp_for_data fd;
950 tree n1, n2;
951
952 extract_omp_for_data (for_stmt, &fd, NULL);
953 n1 = fd.loop.n1;
954 n2 = fd.loop.n2;
955
956 if (gimple_omp_for_combined_into_p (for_stmt))
957 {
958 tree innerc
959 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
960 OMP_CLAUSE__LOOPTEMP_);
961 gcc_assert (innerc);
962 n1 = OMP_CLAUSE_DECL (innerc);
963 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
964 OMP_CLAUSE__LOOPTEMP_);
965 gcc_assert (innerc);
966 n2 = OMP_CLAUSE_DECL (innerc);
967 }
968
969 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
970
971 t = fold_convert_loc (loc, long_integer_type_node, n1);
972 ws_args->quick_push (t);
973
974 t = fold_convert_loc (loc, long_integer_type_node, n2);
975 ws_args->quick_push (t);
976
977 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
978 ws_args->quick_push (t);
979
980 if (fd.chunk_size)
981 {
982 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
983 t = omp_adjust_chunk_size (t, fd.simd_schedule);
984 ws_args->quick_push (t);
985 }
986
987 return ws_args;
988 }
989 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
990 {
991 /* Number of sections is equal to the number of edges from the
992 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
993 the exit of the sections region. */
994 basic_block bb = single_succ (gimple_bb (ws_stmt));
995 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
996 vec_alloc (ws_args, 1);
997 ws_args->quick_push (t);
998 return ws_args;
999 }
1000
1001 gcc_unreachable ();
1002 }
1003
1004
1005 /* Discover whether REGION is a combined parallel+workshare region. */
1006
1007 static void
1008 determine_parallel_type (struct omp_region *region)
1009 {
1010 basic_block par_entry_bb, par_exit_bb;
1011 basic_block ws_entry_bb, ws_exit_bb;
1012
1013 if (region == NULL || region->inner == NULL
1014 || region->exit == NULL || region->inner->exit == NULL
1015 || region->inner->cont == NULL)
1016 return;
1017
1018 /* We only support parallel+for and parallel+sections. */
1019 if (region->type != GIMPLE_OMP_PARALLEL
1020 || (region->inner->type != GIMPLE_OMP_FOR
1021 && region->inner->type != GIMPLE_OMP_SECTIONS))
1022 return;
1023
1024 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
1025 WS_EXIT_BB -> PAR_EXIT_BB. */
1026 par_entry_bb = region->entry;
1027 par_exit_bb = region->exit;
1028 ws_entry_bb = region->inner->entry;
1029 ws_exit_bb = region->inner->exit;
1030
1031 if (single_succ (par_entry_bb) == ws_entry_bb
1032 && single_succ (ws_exit_bb) == par_exit_bb
1033 && workshare_safe_to_combine_p (ws_entry_bb)
1034 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
1035 || (last_and_only_stmt (ws_entry_bb)
1036 && last_and_only_stmt (par_exit_bb))))
1037 {
1038 gimple *par_stmt = last_stmt (par_entry_bb);
1039 gimple *ws_stmt = last_stmt (ws_entry_bb);
1040
1041 if (region->inner->type == GIMPLE_OMP_FOR)
1042 {
1043 /* If this is a combined parallel loop, we need to determine
1044 whether or not to use the combined library calls. There
1045 are two cases where we do not apply the transformation:
1046 static loops and any kind of ordered loop. In the first
1047 case, we already open code the loop so there is no need
1048 to do anything else. In the latter case, the combined
1049 parallel loop call would still need extra synchronization
1050 to implement ordered semantics, so there would not be any
1051 gain in using the combined call. */
1052 tree clauses = gimple_omp_for_clauses (ws_stmt);
1053 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1054 if (c == NULL
1055 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
1056 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1057 {
1058 region->is_combined_parallel = false;
1059 region->inner->is_combined_parallel = false;
1060 return;
1061 }
1062 }
1063
1064 region->is_combined_parallel = true;
1065 region->inner->is_combined_parallel = true;
1066 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1067 }
1068 }
1069
1070
1071 /* Return true if EXPR is variable sized. */
1072
1073 static inline bool
1074 is_variable_sized (const_tree expr)
1075 {
1076 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1077 }
1078
1079 /* Return true if DECL is a reference type. */
1080
1081 static inline bool
1082 is_reference (tree decl)
1083 {
1084 return lang_hooks.decls.omp_privatize_by_reference (decl);
1085 }
1086
1087 /* Return the type of a decl. If the decl is reference type,
1088 return its base type. */
1089 static inline tree
1090 get_base_type (tree decl)
1091 {
1092 tree type = TREE_TYPE (decl);
1093 if (is_reference (decl))
1094 type = TREE_TYPE (type);
1095 return type;
1096 }
1097
1098 /* Lookup variables. The "maybe" form
1099 allows for the variable form to not have been entered, otherwise we
1100 assert that the variable must have been entered. */
1101
1102 static inline tree
1103 lookup_decl (tree var, omp_context *ctx)
1104 {
1105 tree *n = ctx->cb.decl_map->get (var);
1106 return *n;
1107 }
1108
1109 static inline tree
1110 maybe_lookup_decl (const_tree var, omp_context *ctx)
1111 {
1112 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1113 return n ? *n : NULL_TREE;
1114 }
1115
1116 static inline tree
1117 lookup_field (tree var, omp_context *ctx)
1118 {
1119 splay_tree_node n;
1120 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1121 return (tree) n->value;
1122 }
1123
1124 static inline tree
1125 lookup_sfield (splay_tree_key key, omp_context *ctx)
1126 {
1127 splay_tree_node n;
1128 n = splay_tree_lookup (ctx->sfield_map
1129 ? ctx->sfield_map : ctx->field_map, key);
1130 return (tree) n->value;
1131 }
1132
1133 static inline tree
1134 lookup_sfield (tree var, omp_context *ctx)
1135 {
1136 return lookup_sfield ((splay_tree_key) var, ctx);
1137 }
1138
1139 static inline tree
1140 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1141 {
1142 splay_tree_node n;
1143 n = splay_tree_lookup (ctx->field_map, key);
1144 return n ? (tree) n->value : NULL_TREE;
1145 }
1146
1147 static inline tree
1148 maybe_lookup_field (tree var, omp_context *ctx)
1149 {
1150 return maybe_lookup_field ((splay_tree_key) var, ctx);
1151 }
1152
1153 static inline tree
1154 lookup_oacc_reduction (const char *id, omp_context *ctx)
1155 {
1156 splay_tree_node n;
1157 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1158 return (tree) n->value;
1159 }
1160
1161 static inline tree
1162 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1163 {
1164 splay_tree_node n = NULL;
1165 if (ctx->reduction_map)
1166 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1167 return n ? (tree) n->value : NULL_TREE;
1168 }
1169
1170 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1171 the parallel context if DECL is to be shared. */
1172
1173 static bool
1174 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1175 {
1176 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1177 return true;
1178
1179 /* We can only use copy-in/copy-out semantics for shared variables
1180 when we know the value is not accessible from an outer scope. */
1181 if (shared_ctx)
1182 {
1183 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1184
1185 /* ??? Trivially accessible from anywhere. But why would we even
1186 be passing an address in this case? Should we simply assert
1187 this to be false, or should we have a cleanup pass that removes
1188 these from the list of mappings? */
1189 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1190 return true;
1191
1192 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1193 without analyzing the expression whether or not its location
1194 is accessible to anyone else. In the case of nested parallel
1195 regions it certainly may be. */
1196 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1197 return true;
1198
1199 /* Do not use copy-in/copy-out for variables that have their
1200 address taken. */
1201 if (TREE_ADDRESSABLE (decl))
1202 return true;
1203
1204 /* lower_send_shared_vars only uses copy-in, but not copy-out
1205 for these. */
1206 if (TREE_READONLY (decl)
1207 || ((TREE_CODE (decl) == RESULT_DECL
1208 || TREE_CODE (decl) == PARM_DECL)
1209 && DECL_BY_REFERENCE (decl)))
1210 return false;
1211
1212 /* Disallow copy-in/out in nested parallel if
1213 decl is shared in outer parallel, otherwise
1214 each thread could store the shared variable
1215 in its own copy-in location, making the
1216 variable no longer really shared. */
1217 if (shared_ctx->is_nested)
1218 {
1219 omp_context *up;
1220
1221 for (up = shared_ctx->outer; up; up = up->outer)
1222 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1223 break;
1224
1225 if (up)
1226 {
1227 tree c;
1228
1229 for (c = gimple_omp_taskreg_clauses (up->stmt);
1230 c; c = OMP_CLAUSE_CHAIN (c))
1231 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1232 && OMP_CLAUSE_DECL (c) == decl)
1233 break;
1234
1235 if (c)
1236 goto maybe_mark_addressable_and_ret;
1237 }
1238 }
1239
1240 /* For tasks avoid using copy-in/out. As tasks can be
1241 deferred or executed in different thread, when GOMP_task
1242 returns, the task hasn't necessarily terminated. */
1243 if (is_task_ctx (shared_ctx))
1244 {
1245 tree outer;
1246 maybe_mark_addressable_and_ret:
1247 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1248 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1249 {
1250 /* Taking address of OUTER in lower_send_shared_vars
1251 might need regimplification of everything that uses the
1252 variable. */
1253 if (!task_shared_vars)
1254 task_shared_vars = BITMAP_ALLOC (NULL);
1255 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1256 TREE_ADDRESSABLE (outer) = 1;
1257 }
1258 return true;
1259 }
1260 }
1261
1262 return false;
1263 }
1264
1265 /* Construct a new automatic decl similar to VAR. */
1266
1267 static tree
1268 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1269 {
1270 tree copy = copy_var_decl (var, name, type);
1271
1272 DECL_CONTEXT (copy) = current_function_decl;
1273 DECL_CHAIN (copy) = ctx->block_vars;
1274 /* If VAR is listed in task_shared_vars, it means it wasn't
1275 originally addressable and is just because task needs to take
1276 it's address. But we don't need to take address of privatizations
1277 from that var. */
1278 if (TREE_ADDRESSABLE (var)
1279 && task_shared_vars
1280 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1281 TREE_ADDRESSABLE (copy) = 0;
1282 ctx->block_vars = copy;
1283
1284 return copy;
1285 }
1286
1287 static tree
1288 omp_copy_decl_1 (tree var, omp_context *ctx)
1289 {
1290 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1291 }
1292
1293 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1294 as appropriate. */
1295 static tree
1296 omp_build_component_ref (tree obj, tree field)
1297 {
1298 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1299 if (TREE_THIS_VOLATILE (field))
1300 TREE_THIS_VOLATILE (ret) |= 1;
1301 if (TREE_READONLY (field))
1302 TREE_READONLY (ret) |= 1;
1303 return ret;
1304 }
1305
1306 /* Build tree nodes to access the field for VAR on the receiver side. */
1307
1308 static tree
1309 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1310 {
1311 tree x, field = lookup_field (var, ctx);
1312
1313 /* If the receiver record type was remapped in the child function,
1314 remap the field into the new record type. */
1315 x = maybe_lookup_field (field, ctx);
1316 if (x != NULL)
1317 field = x;
1318
1319 x = build_simple_mem_ref (ctx->receiver_decl);
1320 TREE_THIS_NOTRAP (x) = 1;
1321 x = omp_build_component_ref (x, field);
1322 if (by_ref)
1323 x = build_simple_mem_ref (x);
1324
1325 return x;
1326 }
1327
1328 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1329 of a parallel, this is a component reference; for workshare constructs
1330 this is some variable. */
1331
1332 static tree
1333 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1334 {
1335 tree x;
1336
1337 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1338 x = var;
1339 else if (is_variable_sized (var))
1340 {
1341 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1342 x = build_outer_var_ref (x, ctx, lastprivate);
1343 x = build_simple_mem_ref (x);
1344 }
1345 else if (is_taskreg_ctx (ctx))
1346 {
1347 bool by_ref = use_pointer_for_field (var, NULL);
1348 x = build_receiver_ref (var, by_ref, ctx);
1349 }
1350 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1351 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1352 {
1353 /* #pragma omp simd isn't a worksharing construct, and can reference even
1354 private vars in its linear etc. clauses. */
1355 x = NULL_TREE;
1356 if (ctx->outer && is_taskreg_ctx (ctx))
1357 x = lookup_decl (var, ctx->outer);
1358 else if (ctx->outer)
1359 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1360 if (x == NULL_TREE)
1361 x = var;
1362 }
1363 else if (lastprivate && is_taskloop_ctx (ctx))
1364 {
1365 gcc_assert (ctx->outer);
1366 splay_tree_node n
1367 = splay_tree_lookup (ctx->outer->field_map,
1368 (splay_tree_key) &DECL_UID (var));
1369 if (n == NULL)
1370 {
1371 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1372 x = var;
1373 else
1374 x = lookup_decl (var, ctx->outer);
1375 }
1376 else
1377 {
1378 tree field = (tree) n->value;
1379 /* If the receiver record type was remapped in the child function,
1380 remap the field into the new record type. */
1381 x = maybe_lookup_field (field, ctx->outer);
1382 if (x != NULL)
1383 field = x;
1384
1385 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1386 x = omp_build_component_ref (x, field);
1387 if (use_pointer_for_field (var, ctx->outer))
1388 x = build_simple_mem_ref (x);
1389 }
1390 }
1391 else if (ctx->outer)
1392 x = lookup_decl (var, ctx->outer);
1393 else if (is_reference (var))
1394 /* This can happen with orphaned constructs. If var is reference, it is
1395 possible it is shared and as such valid. */
1396 x = var;
1397 else if (omp_member_access_dummy_var (var))
1398 x = var;
1399 else
1400 gcc_unreachable ();
1401
1402 if (x == var)
1403 {
1404 tree t = omp_member_access_dummy_var (var);
1405 if (t)
1406 {
1407 x = DECL_VALUE_EXPR (var);
1408 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1409 if (o != t)
1410 x = unshare_and_remap (x, t, o);
1411 else
1412 x = unshare_expr (x);
1413 }
1414 }
1415
1416 if (is_reference (var))
1417 x = build_simple_mem_ref (x);
1418
1419 return x;
1420 }
1421
1422 /* Build tree nodes to access the field for VAR on the sender side. */
1423
1424 static tree
1425 build_sender_ref (splay_tree_key key, omp_context *ctx)
1426 {
1427 tree field = lookup_sfield (key, ctx);
1428 return omp_build_component_ref (ctx->sender_decl, field);
1429 }
1430
1431 static tree
1432 build_sender_ref (tree var, omp_context *ctx)
1433 {
1434 return build_sender_ref ((splay_tree_key) var, ctx);
1435 }
1436
1437 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1438
1439 static void
1440 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1441 {
1442 tree field, type, sfield = NULL_TREE;
1443 splay_tree_key key = (splay_tree_key) var;
1444
1445 if ((mask & 8) != 0)
1446 {
1447 key = (splay_tree_key) &DECL_UID (var);
1448 gcc_checking_assert (key != (splay_tree_key) var);
1449 }
1450 gcc_assert ((mask & 1) == 0
1451 || !splay_tree_lookup (ctx->field_map, key));
1452 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1453 || !splay_tree_lookup (ctx->sfield_map, key));
1454 gcc_assert ((mask & 3) == 3
1455 || !is_gimple_omp_oacc (ctx->stmt));
1456
1457 type = TREE_TYPE (var);
1458 if (mask & 4)
1459 {
1460 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1461 type = build_pointer_type (build_pointer_type (type));
1462 }
1463 else if (by_ref)
1464 type = build_pointer_type (type);
1465 else if ((mask & 3) == 1 && is_reference (var))
1466 type = TREE_TYPE (type);
1467
1468 field = build_decl (DECL_SOURCE_LOCATION (var),
1469 FIELD_DECL, DECL_NAME (var), type);
1470
1471 /* Remember what variable this field was created for. This does have a
1472 side effect of making dwarf2out ignore this member, so for helpful
1473 debugging we clear it later in delete_omp_context. */
1474 DECL_ABSTRACT_ORIGIN (field) = var;
1475 if (type == TREE_TYPE (var))
1476 {
1477 DECL_ALIGN (field) = DECL_ALIGN (var);
1478 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1479 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1480 }
1481 else
1482 DECL_ALIGN (field) = TYPE_ALIGN (type);
1483
1484 if ((mask & 3) == 3)
1485 {
1486 insert_field_into_struct (ctx->record_type, field);
1487 if (ctx->srecord_type)
1488 {
1489 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1490 FIELD_DECL, DECL_NAME (var), type);
1491 DECL_ABSTRACT_ORIGIN (sfield) = var;
1492 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1493 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1494 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1495 insert_field_into_struct (ctx->srecord_type, sfield);
1496 }
1497 }
1498 else
1499 {
1500 if (ctx->srecord_type == NULL_TREE)
1501 {
1502 tree t;
1503
1504 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1505 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1506 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1507 {
1508 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1509 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1510 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1511 insert_field_into_struct (ctx->srecord_type, sfield);
1512 splay_tree_insert (ctx->sfield_map,
1513 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1514 (splay_tree_value) sfield);
1515 }
1516 }
1517 sfield = field;
1518 insert_field_into_struct ((mask & 1) ? ctx->record_type
1519 : ctx->srecord_type, field);
1520 }
1521
1522 if (mask & 1)
1523 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1524 if ((mask & 2) && ctx->sfield_map)
1525 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1526 }
1527
1528 static tree
1529 install_var_local (tree var, omp_context *ctx)
1530 {
1531 tree new_var = omp_copy_decl_1 (var, ctx);
1532 insert_decl_map (&ctx->cb, var, new_var);
1533 return new_var;
1534 }
1535
1536 /* Adjust the replacement for DECL in CTX for the new context. This means
1537 copying the DECL_VALUE_EXPR, and fixing up the type. */
1538
1539 static void
1540 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1541 {
1542 tree new_decl, size;
1543
1544 new_decl = lookup_decl (decl, ctx);
1545
1546 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1547
1548 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1549 && DECL_HAS_VALUE_EXPR_P (decl))
1550 {
1551 tree ve = DECL_VALUE_EXPR (decl);
1552 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1553 SET_DECL_VALUE_EXPR (new_decl, ve);
1554 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1555 }
1556
1557 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1558 {
1559 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1560 if (size == error_mark_node)
1561 size = TYPE_SIZE (TREE_TYPE (new_decl));
1562 DECL_SIZE (new_decl) = size;
1563
1564 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1565 if (size == error_mark_node)
1566 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1567 DECL_SIZE_UNIT (new_decl) = size;
1568 }
1569 }
1570
1571 /* The callback for remap_decl. Search all containing contexts for a
1572 mapping of the variable; this avoids having to duplicate the splay
1573 tree ahead of time. We know a mapping doesn't already exist in the
1574 given context. Create new mappings to implement default semantics. */
1575
1576 static tree
1577 omp_copy_decl (tree var, copy_body_data *cb)
1578 {
1579 omp_context *ctx = (omp_context *) cb;
1580 tree new_var;
1581
1582 if (TREE_CODE (var) == LABEL_DECL)
1583 {
1584 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1585 DECL_CONTEXT (new_var) = current_function_decl;
1586 insert_decl_map (&ctx->cb, var, new_var);
1587 return new_var;
1588 }
1589
1590 while (!is_taskreg_ctx (ctx))
1591 {
1592 ctx = ctx->outer;
1593 if (ctx == NULL)
1594 return var;
1595 new_var = maybe_lookup_decl (var, ctx);
1596 if (new_var)
1597 return new_var;
1598 }
1599
1600 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1601 return var;
1602
1603 return error_mark_node;
1604 }
1605
1606
1607 /* Debugging dumps for parallel regions. */
1608 void dump_omp_region (FILE *, struct omp_region *, int);
1609 void debug_omp_region (struct omp_region *);
1610 void debug_all_omp_regions (void);
1611
1612 /* Dump the parallel region tree rooted at REGION. */
1613
1614 void
1615 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1616 {
1617 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1618 gimple_code_name[region->type]);
1619
1620 if (region->inner)
1621 dump_omp_region (file, region->inner, indent + 4);
1622
1623 if (region->cont)
1624 {
1625 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1626 region->cont->index);
1627 }
1628
1629 if (region->exit)
1630 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1631 region->exit->index);
1632 else
1633 fprintf (file, "%*s[no exit marker]\n", indent, "");
1634
1635 if (region->next)
1636 dump_omp_region (file, region->next, indent);
1637 }
1638
1639 DEBUG_FUNCTION void
1640 debug_omp_region (struct omp_region *region)
1641 {
1642 dump_omp_region (stderr, region, 0);
1643 }
1644
1645 DEBUG_FUNCTION void
1646 debug_all_omp_regions (void)
1647 {
1648 dump_omp_region (stderr, root_omp_region, 0);
1649 }
1650
1651
1652 /* Create a new parallel region starting at STMT inside region PARENT. */
1653
1654 static struct omp_region *
1655 new_omp_region (basic_block bb, enum gimple_code type,
1656 struct omp_region *parent)
1657 {
1658 struct omp_region *region = XCNEW (struct omp_region);
1659
1660 region->outer = parent;
1661 region->entry = bb;
1662 region->type = type;
1663
1664 if (parent)
1665 {
1666 /* This is a nested region. Add it to the list of inner
1667 regions in PARENT. */
1668 region->next = parent->inner;
1669 parent->inner = region;
1670 }
1671 else
1672 {
1673 /* This is a toplevel region. Add it to the list of toplevel
1674 regions in ROOT_OMP_REGION. */
1675 region->next = root_omp_region;
1676 root_omp_region = region;
1677 }
1678
1679 return region;
1680 }
1681
1682 /* Release the memory associated with the region tree rooted at REGION. */
1683
1684 static void
1685 free_omp_region_1 (struct omp_region *region)
1686 {
1687 struct omp_region *i, *n;
1688
1689 for (i = region->inner; i ; i = n)
1690 {
1691 n = i->next;
1692 free_omp_region_1 (i);
1693 }
1694
1695 free (region);
1696 }
1697
1698 /* Release the memory for the entire omp region tree. */
1699
1700 void
1701 free_omp_regions (void)
1702 {
1703 struct omp_region *r, *n;
1704 for (r = root_omp_region; r ; r = n)
1705 {
1706 n = r->next;
1707 free_omp_region_1 (r);
1708 }
1709 root_omp_region = NULL;
1710 }
1711
1712
1713 /* Create a new context, with OUTER_CTX being the surrounding context. */
1714
1715 static omp_context *
1716 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1717 {
1718 omp_context *ctx = XCNEW (omp_context);
1719
1720 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1721 (splay_tree_value) ctx);
1722 ctx->stmt = stmt;
1723
1724 if (outer_ctx)
1725 {
1726 ctx->outer = outer_ctx;
1727 ctx->cb = outer_ctx->cb;
1728 ctx->cb.block = NULL;
1729 ctx->depth = outer_ctx->depth + 1;
1730 ctx->reduction_map = outer_ctx->reduction_map;
1731 }
1732 else
1733 {
1734 ctx->cb.src_fn = current_function_decl;
1735 ctx->cb.dst_fn = current_function_decl;
1736 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1737 gcc_checking_assert (ctx->cb.src_node);
1738 ctx->cb.dst_node = ctx->cb.src_node;
1739 ctx->cb.src_cfun = cfun;
1740 ctx->cb.copy_decl = omp_copy_decl;
1741 ctx->cb.eh_lp_nr = 0;
1742 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1743 ctx->depth = 1;
1744 }
1745
1746 ctx->cb.decl_map = new hash_map<tree, tree>;
1747
1748 return ctx;
1749 }
1750
1751 static gimple_seq maybe_catch_exception (gimple_seq);
1752
1753 /* Finalize task copyfn. */
1754
1755 static void
1756 finalize_task_copyfn (gomp_task *task_stmt)
1757 {
1758 struct function *child_cfun;
1759 tree child_fn;
1760 gimple_seq seq = NULL, new_seq;
1761 gbind *bind;
1762
1763 child_fn = gimple_omp_task_copy_fn (task_stmt);
1764 if (child_fn == NULL_TREE)
1765 return;
1766
1767 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1768 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1769
1770 push_cfun (child_cfun);
1771 bind = gimplify_body (child_fn, false);
1772 gimple_seq_add_stmt (&seq, bind);
1773 new_seq = maybe_catch_exception (seq);
1774 if (new_seq != seq)
1775 {
1776 bind = gimple_build_bind (NULL, new_seq, NULL);
1777 seq = NULL;
1778 gimple_seq_add_stmt (&seq, bind);
1779 }
1780 gimple_set_body (child_fn, seq);
1781 pop_cfun ();
1782
1783 /* Inform the callgraph about the new function. */
1784 cgraph_node *node = cgraph_node::get_create (child_fn);
1785 node->parallelized_function = 1;
1786 cgraph_node::add_new_function (child_fn, false);
1787 }
1788
1789 /* Destroy a omp_context data structures. Called through the splay tree
1790 value delete callback. */
1791
1792 static void
1793 delete_omp_context (splay_tree_value value)
1794 {
1795 omp_context *ctx = (omp_context *) value;
1796
1797 delete ctx->cb.decl_map;
1798
1799 if (ctx->field_map)
1800 splay_tree_delete (ctx->field_map);
1801 if (ctx->sfield_map)
1802 splay_tree_delete (ctx->sfield_map);
1803 /* Reduction map is copied to nested contexts, so only delete it in the
1804 owner. */
1805 if (ctx->reduction_map
1806 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1807 && is_gimple_omp_offloaded (ctx->stmt)
1808 && is_gimple_omp_oacc (ctx->stmt))
1809 splay_tree_delete (ctx->reduction_map);
1810
1811 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1812 it produces corrupt debug information. */
1813 if (ctx->record_type)
1814 {
1815 tree t;
1816 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1817 DECL_ABSTRACT_ORIGIN (t) = NULL;
1818 }
1819 if (ctx->srecord_type)
1820 {
1821 tree t;
1822 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1823 DECL_ABSTRACT_ORIGIN (t) = NULL;
1824 }
1825
1826 if (is_task_ctx (ctx))
1827 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1828
1829 XDELETE (ctx);
1830 }
1831
1832 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1833 context. */
1834
1835 static void
1836 fixup_child_record_type (omp_context *ctx)
1837 {
1838 tree f, type = ctx->record_type;
1839
1840 /* ??? It isn't sufficient to just call remap_type here, because
1841 variably_modified_type_p doesn't work the way we expect for
1842 record types. Testing each field for whether it needs remapping
1843 and creating a new record by hand works, however. */
1844 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1845 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1846 break;
1847 if (f)
1848 {
1849 tree name, new_fields = NULL;
1850
1851 type = lang_hooks.types.make_type (RECORD_TYPE);
1852 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1853 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1854 TYPE_DECL, name, type);
1855 TYPE_NAME (type) = name;
1856
1857 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1858 {
1859 tree new_f = copy_node (f);
1860 DECL_CONTEXT (new_f) = type;
1861 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1862 DECL_CHAIN (new_f) = new_fields;
1863 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1864 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1865 &ctx->cb, NULL);
1866 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1867 &ctx->cb, NULL);
1868 new_fields = new_f;
1869
1870 /* Arrange to be able to look up the receiver field
1871 given the sender field. */
1872 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1873 (splay_tree_value) new_f);
1874 }
1875 TYPE_FIELDS (type) = nreverse (new_fields);
1876 layout_type (type);
1877 }
1878
1879 /* In a target region we never modify any of the pointers in *.omp_data_i,
1880 so attempt to help the optimizers. */
1881 if (is_gimple_omp_offloaded (ctx->stmt))
1882 type = build_qualified_type (type, TYPE_QUAL_CONST);
1883
1884 TREE_TYPE (ctx->receiver_decl)
1885 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1886 }
1887
1888 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1889 specified by CLAUSES. */
1890
1891 static void
1892 scan_sharing_clauses (tree clauses, omp_context *ctx)
1893 {
1894 tree c, decl;
1895 bool scan_array_reductions = false;
1896
1897 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1898 {
1899 bool by_ref;
1900
1901 switch (OMP_CLAUSE_CODE (c))
1902 {
1903 case OMP_CLAUSE_PRIVATE:
1904 decl = OMP_CLAUSE_DECL (c);
1905 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1906 goto do_private;
1907 else if (!is_variable_sized (decl))
1908 install_var_local (decl, ctx);
1909 break;
1910
1911 case OMP_CLAUSE_SHARED:
1912 decl = OMP_CLAUSE_DECL (c);
1913 /* Ignore shared directives in teams construct. */
1914 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1915 {
1916 /* Global variables don't need to be copied,
1917 the receiver side will use them directly. */
1918 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1919 if (is_global_var (odecl))
1920 break;
1921 insert_decl_map (&ctx->cb, decl, odecl);
1922 break;
1923 }
1924 gcc_assert (is_taskreg_ctx (ctx));
1925 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1926 || !is_variable_sized (decl));
1927 /* Global variables don't need to be copied,
1928 the receiver side will use them directly. */
1929 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1930 break;
1931 by_ref = use_pointer_for_field (decl, ctx);
1932 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1933 break;
1934 if (! TREE_READONLY (decl)
1935 || TREE_ADDRESSABLE (decl)
1936 || by_ref
1937 || is_reference (decl))
1938 {
1939 install_var_field (decl, by_ref, 3, ctx);
1940 install_var_local (decl, ctx);
1941 break;
1942 }
1943 /* We don't need to copy const scalar vars back. */
1944 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1945 goto do_private;
1946
1947 case OMP_CLAUSE_REDUCTION:
1948 decl = OMP_CLAUSE_DECL (c);
1949 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1950 && TREE_CODE (decl) == MEM_REF)
1951 {
1952 tree t = TREE_OPERAND (decl, 0);
1953 if (TREE_CODE (t) == INDIRECT_REF
1954 || TREE_CODE (t) == ADDR_EXPR)
1955 t = TREE_OPERAND (t, 0);
1956 install_var_local (t, ctx);
1957 if (is_taskreg_ctx (ctx)
1958 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1959 && !is_variable_sized (t))
1960 {
1961 by_ref = use_pointer_for_field (t, ctx);
1962 install_var_field (t, by_ref, 3, ctx);
1963 }
1964 break;
1965 }
1966 goto do_private;
1967
1968 case OMP_CLAUSE_LASTPRIVATE:
1969 /* Let the corresponding firstprivate clause create
1970 the variable. */
1971 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1972 break;
1973 /* FALLTHRU */
1974
1975 case OMP_CLAUSE_FIRSTPRIVATE:
1976 if (is_gimple_omp_oacc (ctx->stmt))
1977 {
1978 sorry ("clause not supported yet");
1979 break;
1980 }
1981 /* FALLTHRU */
1982 case OMP_CLAUSE_LINEAR:
1983 decl = OMP_CLAUSE_DECL (c);
1984 do_private:
1985 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1986 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1987 && is_gimple_omp_offloaded (ctx->stmt))
1988 {
1989 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1990 install_var_field (decl, !is_reference (decl), 3, ctx);
1991 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1992 install_var_field (decl, true, 3, ctx);
1993 else
1994 install_var_field (decl, false, 3, ctx);
1995 }
1996 if (is_variable_sized (decl))
1997 {
1998 if (is_task_ctx (ctx))
1999 install_var_field (decl, false, 1, ctx);
2000 break;
2001 }
2002 else if (is_taskreg_ctx (ctx))
2003 {
2004 bool global
2005 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
2006 by_ref = use_pointer_for_field (decl, NULL);
2007
2008 if (is_task_ctx (ctx)
2009 && (global || by_ref || is_reference (decl)))
2010 {
2011 install_var_field (decl, false, 1, ctx);
2012 if (!global)
2013 install_var_field (decl, by_ref, 2, ctx);
2014 }
2015 else if (!global)
2016 install_var_field (decl, by_ref, 3, ctx);
2017 }
2018 install_var_local (decl, ctx);
2019 if (is_gimple_omp_oacc (ctx->stmt)
2020 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
2021 {
2022 /* Create a decl for the reduction array. */
2023 tree var = OMP_CLAUSE_DECL (c);
2024 tree type = get_base_type (var);
2025 tree ptype = build_pointer_type (type);
2026 tree array = create_tmp_var (ptype,
2027 oacc_get_reduction_array_id (var));
2028 omp_context *octx = (ctx->field_map ? ctx : ctx->outer);
2029 install_var_field (array, true, 3, octx);
2030 install_var_local (array, octx);
2031
2032 /* Insert it into the current context. */
2033 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
2034 oacc_get_reduction_array_id (var),
2035 (splay_tree_value) array);
2036 splay_tree_insert (ctx->reduction_map,
2037 (splay_tree_key) array,
2038 (splay_tree_value) array);
2039 }
2040 break;
2041
2042 case OMP_CLAUSE_USE_DEVICE_PTR:
2043 decl = OMP_CLAUSE_DECL (c);
2044 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2045 install_var_field (decl, true, 3, ctx);
2046 else
2047 install_var_field (decl, false, 3, ctx);
2048 if (DECL_SIZE (decl)
2049 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2050 {
2051 tree decl2 = DECL_VALUE_EXPR (decl);
2052 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2053 decl2 = TREE_OPERAND (decl2, 0);
2054 gcc_assert (DECL_P (decl2));
2055 install_var_local (decl2, ctx);
2056 }
2057 install_var_local (decl, ctx);
2058 break;
2059
2060 case OMP_CLAUSE_IS_DEVICE_PTR:
2061 decl = OMP_CLAUSE_DECL (c);
2062 goto do_private;
2063
2064 case OMP_CLAUSE__LOOPTEMP_:
2065 gcc_assert (is_taskreg_ctx (ctx));
2066 decl = OMP_CLAUSE_DECL (c);
2067 install_var_field (decl, false, 3, ctx);
2068 install_var_local (decl, ctx);
2069 break;
2070
2071 case OMP_CLAUSE_COPYPRIVATE:
2072 case OMP_CLAUSE_COPYIN:
2073 decl = OMP_CLAUSE_DECL (c);
2074 by_ref = use_pointer_for_field (decl, NULL);
2075 install_var_field (decl, by_ref, 3, ctx);
2076 break;
2077
2078 case OMP_CLAUSE_DEFAULT:
2079 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2080 break;
2081
2082 case OMP_CLAUSE_FINAL:
2083 case OMP_CLAUSE_IF:
2084 case OMP_CLAUSE_NUM_THREADS:
2085 case OMP_CLAUSE_NUM_TEAMS:
2086 case OMP_CLAUSE_THREAD_LIMIT:
2087 case OMP_CLAUSE_DEVICE:
2088 case OMP_CLAUSE_SCHEDULE:
2089 case OMP_CLAUSE_DIST_SCHEDULE:
2090 case OMP_CLAUSE_DEPEND:
2091 case OMP_CLAUSE_PRIORITY:
2092 case OMP_CLAUSE_GRAINSIZE:
2093 case OMP_CLAUSE_NUM_TASKS:
2094 case OMP_CLAUSE__CILK_FOR_COUNT_:
2095 case OMP_CLAUSE_NUM_GANGS:
2096 case OMP_CLAUSE_NUM_WORKERS:
2097 case OMP_CLAUSE_VECTOR_LENGTH:
2098 if (ctx->outer)
2099 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2100 break;
2101
2102 case OMP_CLAUSE_TO:
2103 case OMP_CLAUSE_FROM:
2104 case OMP_CLAUSE_MAP:
2105 if (ctx->outer)
2106 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2107 decl = OMP_CLAUSE_DECL (c);
2108 /* Global variables with "omp declare target" attribute
2109 don't need to be copied, the receiver side will use them
2110 directly. */
2111 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2112 && DECL_P (decl)
2113 && (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2114 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2115 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2116 && varpool_node::get_create (decl)->offloadable)
2117 break;
2118 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2119 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2120 {
2121 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2122 not offloaded; there is nothing to map for those. */
2123 if (!is_gimple_omp_offloaded (ctx->stmt)
2124 && !POINTER_TYPE_P (TREE_TYPE (decl))
2125 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2126 break;
2127 }
2128 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2129 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2130 {
2131 if (TREE_CODE (decl) == COMPONENT_REF
2132 || (TREE_CODE (decl) == INDIRECT_REF
2133 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2134 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2135 == REFERENCE_TYPE)))
2136 break;
2137 if (DECL_SIZE (decl)
2138 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2139 {
2140 tree decl2 = DECL_VALUE_EXPR (decl);
2141 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2142 decl2 = TREE_OPERAND (decl2, 0);
2143 gcc_assert (DECL_P (decl2));
2144 install_var_local (decl2, ctx);
2145 }
2146 install_var_local (decl, ctx);
2147 break;
2148 }
2149 if (DECL_P (decl))
2150 {
2151 if (DECL_SIZE (decl)
2152 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2153 {
2154 tree decl2 = DECL_VALUE_EXPR (decl);
2155 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2156 decl2 = TREE_OPERAND (decl2, 0);
2157 gcc_assert (DECL_P (decl2));
2158 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2159 && OMP_CLAUSE_MAP_PRIVATE (c))
2160 install_var_field (decl2, true, 11, ctx);
2161 else
2162 install_var_field (decl2, true, 3, ctx);
2163 install_var_local (decl2, ctx);
2164 install_var_local (decl, ctx);
2165 }
2166 else
2167 {
2168 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2169 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2170 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2171 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2172 install_var_field (decl, true, 7, ctx);
2173 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2174 && OMP_CLAUSE_MAP_PRIVATE (c))
2175 install_var_field (decl, true, 11, ctx);
2176 else
2177 install_var_field (decl, true, 3, ctx);
2178 if (is_gimple_omp_offloaded (ctx->stmt))
2179 install_var_local (decl, ctx);
2180 }
2181 }
2182 else
2183 {
2184 tree base = get_base_address (decl);
2185 tree nc = OMP_CLAUSE_CHAIN (c);
2186 if (DECL_P (base)
2187 && nc != NULL_TREE
2188 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2189 && OMP_CLAUSE_DECL (nc) == base
2190 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2191 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2192 {
2193 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2194 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2195 }
2196 else
2197 {
2198 if (ctx->outer)
2199 {
2200 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2201 decl = OMP_CLAUSE_DECL (c);
2202 }
2203 gcc_assert (!splay_tree_lookup (ctx->field_map,
2204 (splay_tree_key) decl));
2205 tree field
2206 = build_decl (OMP_CLAUSE_LOCATION (c),
2207 FIELD_DECL, NULL_TREE, ptr_type_node);
2208 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2209 insert_field_into_struct (ctx->record_type, field);
2210 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2211 (splay_tree_value) field);
2212 }
2213 }
2214 break;
2215
2216 case OMP_CLAUSE_NOWAIT:
2217 case OMP_CLAUSE_ORDERED:
2218 case OMP_CLAUSE_COLLAPSE:
2219 case OMP_CLAUSE_UNTIED:
2220 case OMP_CLAUSE_MERGEABLE:
2221 case OMP_CLAUSE_PROC_BIND:
2222 case OMP_CLAUSE_SAFELEN:
2223 case OMP_CLAUSE_SIMDLEN:
2224 case OMP_CLAUSE_THREADS:
2225 case OMP_CLAUSE_SIMD:
2226 case OMP_CLAUSE_NOGROUP:
2227 case OMP_CLAUSE_DEFAULTMAP:
2228 case OMP_CLAUSE_ASYNC:
2229 case OMP_CLAUSE_WAIT:
2230 case OMP_CLAUSE_GANG:
2231 case OMP_CLAUSE_WORKER:
2232 case OMP_CLAUSE_VECTOR:
2233 break;
2234
2235 case OMP_CLAUSE_ALIGNED:
2236 decl = OMP_CLAUSE_DECL (c);
2237 if (is_global_var (decl)
2238 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2239 install_var_local (decl, ctx);
2240 break;
2241
2242 case OMP_CLAUSE_DEVICE_RESIDENT:
2243 case OMP_CLAUSE_USE_DEVICE:
2244 case OMP_CLAUSE__CACHE_:
2245 case OMP_CLAUSE_INDEPENDENT:
2246 case OMP_CLAUSE_AUTO:
2247 case OMP_CLAUSE_SEQ:
2248 sorry ("Clause not supported yet");
2249 break;
2250
2251 default:
2252 gcc_unreachable ();
2253 }
2254 }
2255
2256 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2257 {
2258 switch (OMP_CLAUSE_CODE (c))
2259 {
2260 case OMP_CLAUSE_LASTPRIVATE:
2261 /* Let the corresponding firstprivate clause create
2262 the variable. */
2263 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2264 scan_array_reductions = true;
2265 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2266 break;
2267 /* FALLTHRU */
2268
2269 case OMP_CLAUSE_FIRSTPRIVATE:
2270 if (is_gimple_omp_oacc (ctx->stmt))
2271 {
2272 sorry ("clause not supported yet");
2273 break;
2274 }
2275 /* FALLTHRU */
2276 case OMP_CLAUSE_PRIVATE:
2277 case OMP_CLAUSE_LINEAR:
2278 case OMP_CLAUSE_IS_DEVICE_PTR:
2279 decl = OMP_CLAUSE_DECL (c);
2280 if (is_variable_sized (decl))
2281 {
2282 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2283 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2284 && is_gimple_omp_offloaded (ctx->stmt))
2285 {
2286 tree decl2 = DECL_VALUE_EXPR (decl);
2287 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2288 decl2 = TREE_OPERAND (decl2, 0);
2289 gcc_assert (DECL_P (decl2));
2290 install_var_local (decl2, ctx);
2291 fixup_remapped_decl (decl2, ctx, false);
2292 }
2293 install_var_local (decl, ctx);
2294 }
2295 fixup_remapped_decl (decl, ctx,
2296 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2297 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2298 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2299 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2300 scan_array_reductions = true;
2301 break;
2302
2303 case OMP_CLAUSE_REDUCTION:
2304 decl = OMP_CLAUSE_DECL (c);
2305 if (TREE_CODE (decl) != MEM_REF)
2306 {
2307 if (is_variable_sized (decl))
2308 install_var_local (decl, ctx);
2309 fixup_remapped_decl (decl, ctx, false);
2310 }
2311 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2312 scan_array_reductions = true;
2313 break;
2314
2315 case OMP_CLAUSE_SHARED:
2316 /* Ignore shared directives in teams construct. */
2317 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2318 break;
2319 decl = OMP_CLAUSE_DECL (c);
2320 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2321 break;
2322 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2323 {
2324 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2325 ctx->outer)))
2326 break;
2327 bool by_ref = use_pointer_for_field (decl, ctx);
2328 install_var_field (decl, by_ref, 11, ctx);
2329 break;
2330 }
2331 fixup_remapped_decl (decl, ctx, false);
2332 break;
2333
2334 case OMP_CLAUSE_MAP:
2335 if (!is_gimple_omp_offloaded (ctx->stmt))
2336 break;
2337 decl = OMP_CLAUSE_DECL (c);
2338 if (DECL_P (decl)
2339 && (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2340 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2341 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2342 && varpool_node::get_create (decl)->offloadable)
2343 break;
2344 if (DECL_P (decl))
2345 {
2346 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2347 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2348 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2349 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2350 {
2351 tree new_decl = lookup_decl (decl, ctx);
2352 TREE_TYPE (new_decl)
2353 = remap_type (TREE_TYPE (decl), &ctx->cb);
2354 }
2355 else if (DECL_SIZE (decl)
2356 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2357 {
2358 tree decl2 = DECL_VALUE_EXPR (decl);
2359 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2360 decl2 = TREE_OPERAND (decl2, 0);
2361 gcc_assert (DECL_P (decl2));
2362 fixup_remapped_decl (decl2, ctx, false);
2363 fixup_remapped_decl (decl, ctx, true);
2364 }
2365 else
2366 fixup_remapped_decl (decl, ctx, false);
2367 }
2368 break;
2369
2370 case OMP_CLAUSE_COPYPRIVATE:
2371 case OMP_CLAUSE_COPYIN:
2372 case OMP_CLAUSE_DEFAULT:
2373 case OMP_CLAUSE_IF:
2374 case OMP_CLAUSE_NUM_THREADS:
2375 case OMP_CLAUSE_NUM_TEAMS:
2376 case OMP_CLAUSE_THREAD_LIMIT:
2377 case OMP_CLAUSE_DEVICE:
2378 case OMP_CLAUSE_SCHEDULE:
2379 case OMP_CLAUSE_DIST_SCHEDULE:
2380 case OMP_CLAUSE_NOWAIT:
2381 case OMP_CLAUSE_ORDERED:
2382 case OMP_CLAUSE_COLLAPSE:
2383 case OMP_CLAUSE_UNTIED:
2384 case OMP_CLAUSE_FINAL:
2385 case OMP_CLAUSE_MERGEABLE:
2386 case OMP_CLAUSE_PROC_BIND:
2387 case OMP_CLAUSE_SAFELEN:
2388 case OMP_CLAUSE_SIMDLEN:
2389 case OMP_CLAUSE_ALIGNED:
2390 case OMP_CLAUSE_DEPEND:
2391 case OMP_CLAUSE__LOOPTEMP_:
2392 case OMP_CLAUSE_TO:
2393 case OMP_CLAUSE_FROM:
2394 case OMP_CLAUSE_PRIORITY:
2395 case OMP_CLAUSE_GRAINSIZE:
2396 case OMP_CLAUSE_NUM_TASKS:
2397 case OMP_CLAUSE_THREADS:
2398 case OMP_CLAUSE_SIMD:
2399 case OMP_CLAUSE_NOGROUP:
2400 case OMP_CLAUSE_DEFAULTMAP:
2401 case OMP_CLAUSE_USE_DEVICE_PTR:
2402 case OMP_CLAUSE__CILK_FOR_COUNT_:
2403 case OMP_CLAUSE_ASYNC:
2404 case OMP_CLAUSE_WAIT:
2405 case OMP_CLAUSE_NUM_GANGS:
2406 case OMP_CLAUSE_NUM_WORKERS:
2407 case OMP_CLAUSE_VECTOR_LENGTH:
2408 case OMP_CLAUSE_GANG:
2409 case OMP_CLAUSE_WORKER:
2410 case OMP_CLAUSE_VECTOR:
2411 break;
2412
2413 case OMP_CLAUSE_DEVICE_RESIDENT:
2414 case OMP_CLAUSE_USE_DEVICE:
2415 case OMP_CLAUSE__CACHE_:
2416 case OMP_CLAUSE_INDEPENDENT:
2417 case OMP_CLAUSE_AUTO:
2418 case OMP_CLAUSE_SEQ:
2419 sorry ("Clause not supported yet");
2420 break;
2421
2422 default:
2423 gcc_unreachable ();
2424 }
2425 }
2426
2427 gcc_checking_assert (!scan_array_reductions
2428 || !is_gimple_omp_oacc (ctx->stmt));
2429 if (scan_array_reductions)
2430 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2431 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2432 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2433 {
2434 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2435 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2436 }
2437 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2438 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2439 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2440 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2441 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2442 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2443 }
2444
2445 /* Create a new name for omp child function. Returns an identifier. If
2446 IS_CILK_FOR is true then the suffix for the child function is
2447 "_cilk_for_fn." */
2448
2449 static tree
2450 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2451 {
2452 if (is_cilk_for)
2453 return clone_function_name (current_function_decl, "_cilk_for_fn");
2454 return clone_function_name (current_function_decl,
2455 task_copy ? "_omp_cpyfn" : "_omp_fn");
2456 }
2457
2458 /* Returns the type of the induction variable for the child function for
2459 _Cilk_for and the types for _high and _low variables based on TYPE. */
2460
2461 static tree
2462 cilk_for_check_loop_diff_type (tree type)
2463 {
2464 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2465 {
2466 if (TYPE_UNSIGNED (type))
2467 return uint32_type_node;
2468 else
2469 return integer_type_node;
2470 }
2471 else
2472 {
2473 if (TYPE_UNSIGNED (type))
2474 return uint64_type_node;
2475 else
2476 return long_long_integer_type_node;
2477 }
2478 }
2479
2480 /* Build a decl for the omp child function. It'll not contain a body
2481 yet, just the bare decl. */
2482
2483 static void
2484 create_omp_child_function (omp_context *ctx, bool task_copy)
2485 {
2486 tree decl, type, name, t;
2487
2488 tree cilk_for_count
2489 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2490 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2491 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2492 tree cilk_var_type = NULL_TREE;
2493
2494 name = create_omp_child_function_name (task_copy,
2495 cilk_for_count != NULL_TREE);
2496 if (task_copy)
2497 type = build_function_type_list (void_type_node, ptr_type_node,
2498 ptr_type_node, NULL_TREE);
2499 else if (cilk_for_count)
2500 {
2501 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2502 cilk_var_type = cilk_for_check_loop_diff_type (type);
2503 type = build_function_type_list (void_type_node, ptr_type_node,
2504 cilk_var_type, cilk_var_type, NULL_TREE);
2505 }
2506 else
2507 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2508
2509 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2510
2511 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2512 || !task_copy);
2513 if (!task_copy)
2514 ctx->cb.dst_fn = decl;
2515 else
2516 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2517
2518 TREE_STATIC (decl) = 1;
2519 TREE_USED (decl) = 1;
2520 DECL_ARTIFICIAL (decl) = 1;
2521 DECL_IGNORED_P (decl) = 0;
2522 TREE_PUBLIC (decl) = 0;
2523 DECL_UNINLINABLE (decl) = 1;
2524 DECL_EXTERNAL (decl) = 0;
2525 DECL_CONTEXT (decl) = NULL_TREE;
2526 DECL_INITIAL (decl) = make_node (BLOCK);
2527 if (cgraph_node::get (current_function_decl)->offloadable)
2528 cgraph_node::get_create (decl)->offloadable = 1;
2529 else
2530 {
2531 omp_context *octx;
2532 for (octx = ctx; octx; octx = octx->outer)
2533 if (is_gimple_omp_offloaded (octx->stmt))
2534 {
2535 cgraph_node::get_create (decl)->offloadable = 1;
2536 #ifdef ENABLE_OFFLOADING
2537 g->have_offload = true;
2538 #endif
2539 break;
2540 }
2541 }
2542
2543 if (cgraph_node::get_create (decl)->offloadable
2544 && !lookup_attribute ("omp declare target",
2545 DECL_ATTRIBUTES (current_function_decl)))
2546 DECL_ATTRIBUTES (decl)
2547 = tree_cons (get_identifier ("omp target entrypoint"),
2548 NULL_TREE, DECL_ATTRIBUTES (decl));
2549
2550 t = build_decl (DECL_SOURCE_LOCATION (decl),
2551 RESULT_DECL, NULL_TREE, void_type_node);
2552 DECL_ARTIFICIAL (t) = 1;
2553 DECL_IGNORED_P (t) = 1;
2554 DECL_CONTEXT (t) = decl;
2555 DECL_RESULT (decl) = t;
2556
2557 /* _Cilk_for's child function requires two extra parameters called
2558 __low and __high that are set the by Cilk runtime when it calls this
2559 function. */
2560 if (cilk_for_count)
2561 {
2562 t = build_decl (DECL_SOURCE_LOCATION (decl),
2563 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2564 DECL_ARTIFICIAL (t) = 1;
2565 DECL_NAMELESS (t) = 1;
2566 DECL_ARG_TYPE (t) = ptr_type_node;
2567 DECL_CONTEXT (t) = current_function_decl;
2568 TREE_USED (t) = 1;
2569 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2570 DECL_ARGUMENTS (decl) = t;
2571
2572 t = build_decl (DECL_SOURCE_LOCATION (decl),
2573 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2574 DECL_ARTIFICIAL (t) = 1;
2575 DECL_NAMELESS (t) = 1;
2576 DECL_ARG_TYPE (t) = ptr_type_node;
2577 DECL_CONTEXT (t) = current_function_decl;
2578 TREE_USED (t) = 1;
2579 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2580 DECL_ARGUMENTS (decl) = t;
2581 }
2582
2583 tree data_name = get_identifier (".omp_data_i");
2584 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2585 ptr_type_node);
2586 DECL_ARTIFICIAL (t) = 1;
2587 DECL_NAMELESS (t) = 1;
2588 DECL_ARG_TYPE (t) = ptr_type_node;
2589 DECL_CONTEXT (t) = current_function_decl;
2590 TREE_USED (t) = 1;
2591 TREE_READONLY (t) = 1;
2592 if (cilk_for_count)
2593 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2594 DECL_ARGUMENTS (decl) = t;
2595 if (!task_copy)
2596 ctx->receiver_decl = t;
2597 else
2598 {
2599 t = build_decl (DECL_SOURCE_LOCATION (decl),
2600 PARM_DECL, get_identifier (".omp_data_o"),
2601 ptr_type_node);
2602 DECL_ARTIFICIAL (t) = 1;
2603 DECL_NAMELESS (t) = 1;
2604 DECL_ARG_TYPE (t) = ptr_type_node;
2605 DECL_CONTEXT (t) = current_function_decl;
2606 TREE_USED (t) = 1;
2607 TREE_ADDRESSABLE (t) = 1;
2608 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2609 DECL_ARGUMENTS (decl) = t;
2610 }
2611
2612 /* Allocate memory for the function structure. The call to
2613 allocate_struct_function clobbers CFUN, so we need to restore
2614 it afterward. */
2615 push_struct_function (decl);
2616 cfun->function_end_locus = gimple_location (ctx->stmt);
2617 pop_cfun ();
2618 }
2619
2620 /* Callback for walk_gimple_seq. Check if combined parallel
2621 contains gimple_omp_for_combined_into_p OMP_FOR. */
2622
2623 static tree
2624 find_combined_for (gimple_stmt_iterator *gsi_p,
2625 bool *handled_ops_p,
2626 struct walk_stmt_info *wi)
2627 {
2628 gimple *stmt = gsi_stmt (*gsi_p);
2629
2630 *handled_ops_p = true;
2631 switch (gimple_code (stmt))
2632 {
2633 WALK_SUBSTMTS;
2634
2635 case GIMPLE_OMP_FOR:
2636 if (gimple_omp_for_combined_into_p (stmt)
2637 && gimple_omp_for_kind (stmt)
2638 == *(const enum gf_mask *) (wi->info))
2639 {
2640 wi->info = stmt;
2641 return integer_zero_node;
2642 }
2643 break;
2644 default:
2645 break;
2646 }
2647 return NULL;
2648 }
2649
2650 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2651
2652 static void
2653 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2654 omp_context *outer_ctx)
2655 {
2656 struct walk_stmt_info wi;
2657
2658 memset (&wi, 0, sizeof (wi));
2659 wi.val_only = true;
2660 wi.info = (void *) &msk;
2661 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2662 if (wi.info != (void *) &msk)
2663 {
2664 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2665 struct omp_for_data fd;
2666 extract_omp_for_data (for_stmt, &fd, NULL);
2667 /* We need two temporaries with fd.loop.v type (istart/iend)
2668 and then (fd.collapse - 1) temporaries with the same
2669 type for count2 ... countN-1 vars if not constant. */
2670 size_t count = 2, i;
2671 tree type = fd.iter_type;
2672 if (fd.collapse > 1
2673 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2674 {
2675 count += fd.collapse - 1;
2676 /* For taskloop, if there are lastprivate clauses on the inner
2677 GIMPLE_OMP_FOR, add one more temporaries for the total number
2678 of iterations (product of count1 ... countN-1). */
2679 if (msk == GF_OMP_FOR_KIND_TASKLOOP
2680 && find_omp_clause (gimple_omp_for_clauses (for_stmt),
2681 OMP_CLAUSE_LASTPRIVATE))
2682 count++;
2683 }
2684 for (i = 0; i < count; i++)
2685 {
2686 tree temp = create_tmp_var (type);
2687 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2688 insert_decl_map (&outer_ctx->cb, temp, temp);
2689 OMP_CLAUSE_DECL (c) = temp;
2690 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2691 gimple_omp_taskreg_set_clauses (stmt, c);
2692 }
2693 }
2694 }
2695
2696 /* Scan an OpenMP parallel directive. */
2697
2698 static void
2699 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2700 {
2701 omp_context *ctx;
2702 tree name;
2703 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2704
2705 /* Ignore parallel directives with empty bodies, unless there
2706 are copyin clauses. */
2707 if (optimize > 0
2708 && empty_body_p (gimple_omp_body (stmt))
2709 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2710 OMP_CLAUSE_COPYIN) == NULL)
2711 {
2712 gsi_replace (gsi, gimple_build_nop (), false);
2713 return;
2714 }
2715
2716 if (gimple_omp_parallel_combined_p (stmt))
2717 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2718
2719 ctx = new_omp_context (stmt, outer_ctx);
2720 taskreg_contexts.safe_push (ctx);
2721 if (taskreg_nesting_level > 1)
2722 ctx->is_nested = true;
2723 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2724 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2725 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2726 name = create_tmp_var_name (".omp_data_s");
2727 name = build_decl (gimple_location (stmt),
2728 TYPE_DECL, name, ctx->record_type);
2729 DECL_ARTIFICIAL (name) = 1;
2730 DECL_NAMELESS (name) = 1;
2731 TYPE_NAME (ctx->record_type) = name;
2732 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2733 create_omp_child_function (ctx, false);
2734 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2735
2736 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2737 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2738
2739 if (TYPE_FIELDS (ctx->record_type) == NULL)
2740 ctx->record_type = ctx->receiver_decl = NULL;
2741 }
2742
2743 /* Scan an OpenMP task directive. */
2744
2745 static void
2746 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2747 {
2748 omp_context *ctx;
2749 tree name, t;
2750 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2751
2752 /* Ignore task directives with empty bodies. */
2753 if (optimize > 0
2754 && empty_body_p (gimple_omp_body (stmt)))
2755 {
2756 gsi_replace (gsi, gimple_build_nop (), false);
2757 return;
2758 }
2759
2760 if (gimple_omp_task_taskloop_p (stmt))
2761 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2762
2763 ctx = new_omp_context (stmt, outer_ctx);
2764 taskreg_contexts.safe_push (ctx);
2765 if (taskreg_nesting_level > 1)
2766 ctx->is_nested = true;
2767 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2768 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2769 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2770 name = create_tmp_var_name (".omp_data_s");
2771 name = build_decl (gimple_location (stmt),
2772 TYPE_DECL, name, ctx->record_type);
2773 DECL_ARTIFICIAL (name) = 1;
2774 DECL_NAMELESS (name) = 1;
2775 TYPE_NAME (ctx->record_type) = name;
2776 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2777 create_omp_child_function (ctx, false);
2778 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2779
2780 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2781
2782 if (ctx->srecord_type)
2783 {
2784 name = create_tmp_var_name (".omp_data_a");
2785 name = build_decl (gimple_location (stmt),
2786 TYPE_DECL, name, ctx->srecord_type);
2787 DECL_ARTIFICIAL (name) = 1;
2788 DECL_NAMELESS (name) = 1;
2789 TYPE_NAME (ctx->srecord_type) = name;
2790 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2791 create_omp_child_function (ctx, true);
2792 }
2793
2794 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2795
2796 if (TYPE_FIELDS (ctx->record_type) == NULL)
2797 {
2798 ctx->record_type = ctx->receiver_decl = NULL;
2799 t = build_int_cst (long_integer_type_node, 0);
2800 gimple_omp_task_set_arg_size (stmt, t);
2801 t = build_int_cst (long_integer_type_node, 1);
2802 gimple_omp_task_set_arg_align (stmt, t);
2803 }
2804 }
2805
2806
2807 /* If any decls have been made addressable during scan_omp,
2808 adjust their fields if needed, and layout record types
2809 of parallel/task constructs. */
2810
2811 static void
2812 finish_taskreg_scan (omp_context *ctx)
2813 {
2814 if (ctx->record_type == NULL_TREE)
2815 return;
2816
2817 /* If any task_shared_vars were needed, verify all
2818 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2819 statements if use_pointer_for_field hasn't changed
2820 because of that. If it did, update field types now. */
2821 if (task_shared_vars)
2822 {
2823 tree c;
2824
2825 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2826 c; c = OMP_CLAUSE_CHAIN (c))
2827 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2828 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2829 {
2830 tree decl = OMP_CLAUSE_DECL (c);
2831
2832 /* Global variables don't need to be copied,
2833 the receiver side will use them directly. */
2834 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2835 continue;
2836 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2837 || !use_pointer_for_field (decl, ctx))
2838 continue;
2839 tree field = lookup_field (decl, ctx);
2840 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2841 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2842 continue;
2843 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2844 TREE_THIS_VOLATILE (field) = 0;
2845 DECL_USER_ALIGN (field) = 0;
2846 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2847 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2848 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2849 if (ctx->srecord_type)
2850 {
2851 tree sfield = lookup_sfield (decl, ctx);
2852 TREE_TYPE (sfield) = TREE_TYPE (field);
2853 TREE_THIS_VOLATILE (sfield) = 0;
2854 DECL_USER_ALIGN (sfield) = 0;
2855 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2856 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2857 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2858 }
2859 }
2860 }
2861
2862 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2863 {
2864 layout_type (ctx->record_type);
2865 fixup_child_record_type (ctx);
2866 }
2867 else
2868 {
2869 location_t loc = gimple_location (ctx->stmt);
2870 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2871 /* Move VLA fields to the end. */
2872 p = &TYPE_FIELDS (ctx->record_type);
2873 while (*p)
2874 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2875 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2876 {
2877 *q = *p;
2878 *p = TREE_CHAIN (*p);
2879 TREE_CHAIN (*q) = NULL_TREE;
2880 q = &TREE_CHAIN (*q);
2881 }
2882 else
2883 p = &DECL_CHAIN (*p);
2884 *p = vla_fields;
2885 if (gimple_omp_task_taskloop_p (ctx->stmt))
2886 {
2887 /* Move fields corresponding to first and second _looptemp_
2888 clause first. There are filled by GOMP_taskloop
2889 and thus need to be in specific positions. */
2890 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2891 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2892 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2893 OMP_CLAUSE__LOOPTEMP_);
2894 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2895 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2896 p = &TYPE_FIELDS (ctx->record_type);
2897 while (*p)
2898 if (*p == f1 || *p == f2)
2899 *p = DECL_CHAIN (*p);
2900 else
2901 p = &DECL_CHAIN (*p);
2902 DECL_CHAIN (f1) = f2;
2903 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2904 TYPE_FIELDS (ctx->record_type) = f1;
2905 if (ctx->srecord_type)
2906 {
2907 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2908 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2909 p = &TYPE_FIELDS (ctx->srecord_type);
2910 while (*p)
2911 if (*p == f1 || *p == f2)
2912 *p = DECL_CHAIN (*p);
2913 else
2914 p = &DECL_CHAIN (*p);
2915 DECL_CHAIN (f1) = f2;
2916 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2917 TYPE_FIELDS (ctx->srecord_type) = f1;
2918 }
2919 }
2920 layout_type (ctx->record_type);
2921 fixup_child_record_type (ctx);
2922 if (ctx->srecord_type)
2923 layout_type (ctx->srecord_type);
2924 tree t = fold_convert_loc (loc, long_integer_type_node,
2925 TYPE_SIZE_UNIT (ctx->record_type));
2926 gimple_omp_task_set_arg_size (ctx->stmt, t);
2927 t = build_int_cst (long_integer_type_node,
2928 TYPE_ALIGN_UNIT (ctx->record_type));
2929 gimple_omp_task_set_arg_align (ctx->stmt, t);
2930 }
2931 }
2932
2933 /* Find the enclosing offload context. */
2934
2935 static omp_context *
2936 enclosing_target_ctx (omp_context *ctx)
2937 {
2938 for (; ctx; ctx = ctx->outer)
2939 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2940 break;
2941
2942 return ctx;
2943 }
2944
2945 /* Return true if ctx is part of an oacc kernels region. */
2946
2947 static bool
2948 ctx_in_oacc_kernels_region (omp_context *ctx)
2949 {
2950 for (;ctx != NULL; ctx = ctx->outer)
2951 {
2952 gimple *stmt = ctx->stmt;
2953 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2954 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2955 return true;
2956 }
2957
2958 return false;
2959 }
2960
2961 /* Check the parallelism clauses inside a kernels regions.
2962 Until kernels handling moves to use the same loop indirection
2963 scheme as parallel, we need to do this checking early. */
2964
2965 static unsigned
2966 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2967 {
2968 bool checking = true;
2969 unsigned outer_mask = 0;
2970 unsigned this_mask = 0;
2971 bool has_seq = false, has_auto = false;
2972
2973 if (ctx->outer)
2974 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2975 if (!stmt)
2976 {
2977 checking = false;
2978 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2979 return outer_mask;
2980 stmt = as_a <gomp_for *> (ctx->stmt);
2981 }
2982
2983 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2984 {
2985 switch (OMP_CLAUSE_CODE (c))
2986 {
2987 case OMP_CLAUSE_GANG:
2988 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2989 break;
2990 case OMP_CLAUSE_WORKER:
2991 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2992 break;
2993 case OMP_CLAUSE_VECTOR:
2994 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2995 break;
2996 case OMP_CLAUSE_SEQ:
2997 has_seq = true;
2998 break;
2999 case OMP_CLAUSE_AUTO:
3000 has_auto = true;
3001 break;
3002 default:
3003 break;
3004 }
3005 }
3006
3007 if (checking)
3008 {
3009 if (has_seq && (this_mask || has_auto))
3010 error_at (gimple_location (stmt), "%<seq%> overrides other"
3011 " OpenACC loop specifiers");
3012 else if (has_auto && this_mask)
3013 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
3014 " OpenACC loop specifiers");
3015
3016 if (this_mask & outer_mask)
3017 error_at (gimple_location (stmt), "inner loop uses same"
3018 " OpenACC parallelism as containing loop");
3019 }
3020
3021 return outer_mask | this_mask;
3022 }
3023
3024 /* Scan a GIMPLE_OMP_FOR. */
3025
3026 static void
3027 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
3028 {
3029 omp_context *ctx;
3030 size_t i;
3031 tree clauses = gimple_omp_for_clauses (stmt);
3032
3033 ctx = new_omp_context (stmt, outer_ctx);
3034
3035 if (is_gimple_omp_oacc (stmt))
3036 {
3037 omp_context *tgt = enclosing_target_ctx (outer_ctx);
3038
3039 if (!tgt || is_oacc_parallel (tgt))
3040 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3041 {
3042 char const *check = NULL;
3043
3044 switch (OMP_CLAUSE_CODE (c))
3045 {
3046 case OMP_CLAUSE_GANG:
3047 check = "gang";
3048 break;
3049
3050 case OMP_CLAUSE_WORKER:
3051 check = "worker";
3052 break;
3053
3054 case OMP_CLAUSE_VECTOR:
3055 check = "vector";
3056 break;
3057
3058 default:
3059 break;
3060 }
3061
3062 if (check && OMP_CLAUSE_OPERAND (c, 0))
3063 error_at (gimple_location (stmt),
3064 "argument not permitted on %qs clause in"
3065 " OpenACC %<parallel%>", check);
3066 }
3067
3068 if (tgt && is_oacc_kernels (tgt))
3069 {
3070 /* Strip out reductions, as they are not handled yet. */
3071 tree *prev_ptr = &clauses;
3072
3073 while (tree probe = *prev_ptr)
3074 {
3075 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3076
3077 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3078 *prev_ptr = *next_ptr;
3079 else
3080 prev_ptr = next_ptr;
3081 }
3082
3083 gimple_omp_for_set_clauses (stmt, clauses);
3084 check_oacc_kernel_gwv (stmt, ctx);
3085 }
3086 }
3087
3088 scan_sharing_clauses (clauses, ctx);
3089
3090 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3091 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3092 {
3093 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3094 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3095 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3096 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3097 }
3098 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3099 }
3100
3101 /* Scan an OpenMP sections directive. */
3102
3103 static void
3104 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3105 {
3106 omp_context *ctx;
3107
3108 ctx = new_omp_context (stmt, outer_ctx);
3109 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3110 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3111 }
3112
3113 /* Scan an OpenMP single directive. */
3114
3115 static void
3116 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3117 {
3118 omp_context *ctx;
3119 tree name;
3120
3121 ctx = new_omp_context (stmt, outer_ctx);
3122 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3123 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3124 name = create_tmp_var_name (".omp_copy_s");
3125 name = build_decl (gimple_location (stmt),
3126 TYPE_DECL, name, ctx->record_type);
3127 TYPE_NAME (ctx->record_type) = name;
3128
3129 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3130 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3131
3132 if (TYPE_FIELDS (ctx->record_type) == NULL)
3133 ctx->record_type = NULL;
3134 else
3135 layout_type (ctx->record_type);
3136 }
3137
3138 /* Scan a GIMPLE_OMP_TARGET. */
3139
3140 static void
3141 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3142 {
3143 omp_context *ctx;
3144 tree name;
3145 bool offloaded = is_gimple_omp_offloaded (stmt);
3146 tree clauses = gimple_omp_target_clauses (stmt);
3147
3148 ctx = new_omp_context (stmt, outer_ctx);
3149 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3150 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3151 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3152 name = create_tmp_var_name (".omp_data_t");
3153 name = build_decl (gimple_location (stmt),
3154 TYPE_DECL, name, ctx->record_type);
3155 DECL_ARTIFICIAL (name) = 1;
3156 DECL_NAMELESS (name) = 1;
3157 TYPE_NAME (ctx->record_type) = name;
3158 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3159 if (offloaded)
3160 {
3161 if (is_gimple_omp_oacc (stmt))
3162 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
3163 0, 0);
3164
3165 create_omp_child_function (ctx, false);
3166 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3167 }
3168
3169 scan_sharing_clauses (clauses, ctx);
3170 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3171
3172 if (TYPE_FIELDS (ctx->record_type) == NULL)
3173 ctx->record_type = ctx->receiver_decl = NULL;
3174 else
3175 {
3176 TYPE_FIELDS (ctx->record_type)
3177 = nreverse (TYPE_FIELDS (ctx->record_type));
3178 if (flag_checking)
3179 {
3180 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3181 for (tree field = TYPE_FIELDS (ctx->record_type);
3182 field;
3183 field = DECL_CHAIN (field))
3184 gcc_assert (DECL_ALIGN (field) == align);
3185 }
3186 layout_type (ctx->record_type);
3187 if (offloaded)
3188 fixup_child_record_type (ctx);
3189 }
3190 }
3191
3192 /* Scan an OpenMP teams directive. */
3193
3194 static void
3195 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3196 {
3197 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3198 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3199 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3200 }
3201
3202 /* Check nesting restrictions. */
3203 static bool
3204 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3205 {
3206 tree c;
3207
3208 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3209 inside an OpenACC CTX. */
3210 if (!(is_gimple_omp (stmt)
3211 && is_gimple_omp_oacc (stmt)))
3212 {
3213 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
3214 if (is_gimple_omp (ctx_->stmt)
3215 && is_gimple_omp_oacc (ctx_->stmt))
3216 {
3217 error_at (gimple_location (stmt),
3218 "non-OpenACC construct inside of OpenACC region");
3219 return false;
3220 }
3221 }
3222
3223 if (ctx != NULL)
3224 {
3225 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3226 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3227 {
3228 c = NULL_TREE;
3229 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3230 {
3231 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3232 if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD)
3233 return true;
3234 }
3235 error_at (gimple_location (stmt),
3236 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3237 " may not be nested inside simd region");
3238 return false;
3239 }
3240 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3241 {
3242 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3243 || (gimple_omp_for_kind (stmt)
3244 != GF_OMP_FOR_KIND_DISTRIBUTE))
3245 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3246 {
3247 error_at (gimple_location (stmt),
3248 "only distribute or parallel constructs are allowed to "
3249 "be closely nested inside teams construct");
3250 return false;
3251 }
3252 }
3253 }
3254 switch (gimple_code (stmt))
3255 {
3256 case GIMPLE_OMP_FOR:
3257 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3258 return true;
3259 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3260 {
3261 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3262 {
3263 error_at (gimple_location (stmt),
3264 "distribute construct must be closely nested inside "
3265 "teams construct");
3266 return false;
3267 }
3268 return true;
3269 }
3270 /* We split taskloop into task and nested taskloop in it. */
3271 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3272 return true;
3273 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3274 {
3275 bool ok = false;
3276
3277 if (ctx)
3278 switch (gimple_code (ctx->stmt))
3279 {
3280 case GIMPLE_OMP_FOR:
3281 ok = (gimple_omp_for_kind (ctx->stmt)
3282 == GF_OMP_FOR_KIND_OACC_LOOP);
3283 break;
3284
3285 case GIMPLE_OMP_TARGET:
3286 switch (gimple_omp_target_kind (ctx->stmt))
3287 {
3288 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3289 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3290 ok = true;
3291 break;
3292
3293 default:
3294 break;
3295 }
3296
3297 default:
3298 break;
3299 }
3300 else if (get_oacc_fn_attrib (current_function_decl))
3301 ok = true;
3302 if (!ok)
3303 {
3304 error_at (gimple_location (stmt),
3305 "OpenACC loop directive must be associated with"
3306 " an OpenACC compute region");
3307 return false;
3308 }
3309 }
3310 /* FALLTHRU */
3311 case GIMPLE_CALL:
3312 if (is_gimple_call (stmt)
3313 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3314 == BUILT_IN_GOMP_CANCEL
3315 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3316 == BUILT_IN_GOMP_CANCELLATION_POINT))
3317 {
3318 const char *bad = NULL;
3319 const char *kind = NULL;
3320 if (ctx == NULL)
3321 {
3322 error_at (gimple_location (stmt), "orphaned %qs construct",
3323 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3324 == BUILT_IN_GOMP_CANCEL
3325 ? "#pragma omp cancel"
3326 : "#pragma omp cancellation point");
3327 return false;
3328 }
3329 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3330 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3331 : 0)
3332 {
3333 case 1:
3334 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3335 bad = "#pragma omp parallel";
3336 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3337 == BUILT_IN_GOMP_CANCEL
3338 && !integer_zerop (gimple_call_arg (stmt, 1)))
3339 ctx->cancellable = true;
3340 kind = "parallel";
3341 break;
3342 case 2:
3343 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3344 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3345 bad = "#pragma omp for";
3346 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3347 == BUILT_IN_GOMP_CANCEL
3348 && !integer_zerop (gimple_call_arg (stmt, 1)))
3349 {
3350 ctx->cancellable = true;
3351 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3352 OMP_CLAUSE_NOWAIT))
3353 warning_at (gimple_location (stmt), 0,
3354 "%<#pragma omp cancel for%> inside "
3355 "%<nowait%> for construct");
3356 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3357 OMP_CLAUSE_ORDERED))
3358 warning_at (gimple_location (stmt), 0,
3359 "%<#pragma omp cancel for%> inside "
3360 "%<ordered%> for construct");
3361 }
3362 kind = "for";
3363 break;
3364 case 4:
3365 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3366 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3367 bad = "#pragma omp sections";
3368 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3369 == BUILT_IN_GOMP_CANCEL
3370 && !integer_zerop (gimple_call_arg (stmt, 1)))
3371 {
3372 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3373 {
3374 ctx->cancellable = true;
3375 if (find_omp_clause (gimple_omp_sections_clauses
3376 (ctx->stmt),
3377 OMP_CLAUSE_NOWAIT))
3378 warning_at (gimple_location (stmt), 0,
3379 "%<#pragma omp cancel sections%> inside "
3380 "%<nowait%> sections construct");
3381 }
3382 else
3383 {
3384 gcc_assert (ctx->outer
3385 && gimple_code (ctx->outer->stmt)
3386 == GIMPLE_OMP_SECTIONS);
3387 ctx->outer->cancellable = true;
3388 if (find_omp_clause (gimple_omp_sections_clauses
3389 (ctx->outer->stmt),
3390 OMP_CLAUSE_NOWAIT))
3391 warning_at (gimple_location (stmt), 0,
3392 "%<#pragma omp cancel sections%> inside "
3393 "%<nowait%> sections construct");
3394 }
3395 }
3396 kind = "sections";
3397 break;
3398 case 8:
3399 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3400 bad = "#pragma omp task";
3401 else
3402 ctx->cancellable = true;
3403 kind = "taskgroup";
3404 break;
3405 default:
3406 error_at (gimple_location (stmt), "invalid arguments");
3407 return false;
3408 }
3409 if (bad)
3410 {
3411 error_at (gimple_location (stmt),
3412 "%<%s %s%> construct not closely nested inside of %qs",
3413 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3414 == BUILT_IN_GOMP_CANCEL
3415 ? "#pragma omp cancel"
3416 : "#pragma omp cancellation point", kind, bad);
3417 return false;
3418 }
3419 }
3420 /* FALLTHRU */
3421 case GIMPLE_OMP_SECTIONS:
3422 case GIMPLE_OMP_SINGLE:
3423 for (; ctx != NULL; ctx = ctx->outer)
3424 switch (gimple_code (ctx->stmt))
3425 {
3426 case GIMPLE_OMP_FOR:
3427 case GIMPLE_OMP_SECTIONS:
3428 case GIMPLE_OMP_SINGLE:
3429 case GIMPLE_OMP_ORDERED:
3430 case GIMPLE_OMP_MASTER:
3431 case GIMPLE_OMP_TASK:
3432 case GIMPLE_OMP_CRITICAL:
3433 if (is_gimple_call (stmt))
3434 {
3435 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3436 != BUILT_IN_GOMP_BARRIER)
3437 return true;
3438 error_at (gimple_location (stmt),
3439 "barrier region may not be closely nested inside "
3440 "of work-sharing, critical, ordered, master or "
3441 "explicit task region");
3442 return false;
3443 }
3444 error_at (gimple_location (stmt),
3445 "work-sharing region may not be closely nested inside "
3446 "of work-sharing, critical, ordered, master or explicit "
3447 "task region");
3448 return false;
3449 case GIMPLE_OMP_PARALLEL:
3450 return true;
3451 default:
3452 break;
3453 }
3454 break;
3455 case GIMPLE_OMP_MASTER:
3456 for (; ctx != NULL; ctx = ctx->outer)
3457 switch (gimple_code (ctx->stmt))
3458 {
3459 case GIMPLE_OMP_FOR:
3460 case GIMPLE_OMP_SECTIONS:
3461 case GIMPLE_OMP_SINGLE:
3462 case GIMPLE_OMP_TASK:
3463 error_at (gimple_location (stmt),
3464 "master region may not be closely nested inside "
3465 "of work-sharing or explicit task region");
3466 return false;
3467 case GIMPLE_OMP_PARALLEL:
3468 return true;
3469 default:
3470 break;
3471 }
3472 break;
3473 case GIMPLE_OMP_TASK:
3474 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3475 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3476 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3477 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3478 {
3479 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3480 error_at (OMP_CLAUSE_LOCATION (c),
3481 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3482 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3483 return false;
3484 }
3485 break;
3486 case GIMPLE_OMP_ORDERED:
3487 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3488 c; c = OMP_CLAUSE_CHAIN (c))
3489 {
3490 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3491 {
3492 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3493 || (ctx == NULL
3494 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD));
3495 continue;
3496 }
3497 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3498 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3499 || kind == OMP_CLAUSE_DEPEND_SINK)
3500 {
3501 tree oclause;
3502 /* Look for containing ordered(N) loop. */
3503 if (ctx == NULL
3504 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3505 || (oclause
3506 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3507 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3508 {
3509 error_at (OMP_CLAUSE_LOCATION (c),
3510 "%<depend%> clause must be closely nested "
3511 "inside an ordered loop");
3512 return false;
3513 }
3514 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3515 {
3516 error_at (OMP_CLAUSE_LOCATION (c),
3517 "%<depend%> clause must be closely nested "
3518 "inside a loop with %<ordered%> clause with "
3519 "a parameter");
3520 return false;
3521 }
3522 }
3523 else
3524 {
3525 error_at (OMP_CLAUSE_LOCATION (c),
3526 "invalid depend kind in omp ordered depend");
3527 return false;
3528 }
3529 }
3530 for (; ctx != NULL; ctx = ctx->outer)
3531 switch (gimple_code (ctx->stmt))
3532 {
3533 case GIMPLE_OMP_CRITICAL:
3534 case GIMPLE_OMP_TASK:
3535 error_at (gimple_location (stmt),
3536 "ordered region may not be closely nested inside "
3537 "of critical or explicit task region");
3538 return false;
3539 case GIMPLE_OMP_FOR:
3540 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3541 OMP_CLAUSE_ORDERED) == NULL)
3542 {
3543 error_at (gimple_location (stmt),
3544 "ordered region must be closely nested inside "
3545 "a loop region with an ordered clause");
3546 return false;
3547 }
3548 return true;
3549 case GIMPLE_OMP_PARALLEL:
3550 error_at (gimple_location (stmt),
3551 "ordered region must be closely nested inside "
3552 "a loop region with an ordered clause");
3553 return false;
3554 default:
3555 break;
3556 }
3557 break;
3558 case GIMPLE_OMP_CRITICAL:
3559 {
3560 tree this_stmt_name
3561 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3562 for (; ctx != NULL; ctx = ctx->outer)
3563 if (gomp_critical *other_crit
3564 = dyn_cast <gomp_critical *> (ctx->stmt))
3565 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3566 {
3567 error_at (gimple_location (stmt),
3568 "critical region may not be nested inside a critical "
3569 "region with the same name");
3570 return false;
3571 }
3572 }
3573 break;
3574 case GIMPLE_OMP_TEAMS:
3575 if (ctx == NULL
3576 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3577 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3578 {
3579 error_at (gimple_location (stmt),
3580 "teams construct not closely nested inside of target "
3581 "region");
3582 return false;
3583 }
3584 break;
3585 case GIMPLE_OMP_TARGET:
3586 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3587 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3588 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3589 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3590 {
3591 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3592 error_at (OMP_CLAUSE_LOCATION (c),
3593 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3594 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3595 return false;
3596 }
3597 for (; ctx != NULL; ctx = ctx->outer)
3598 {
3599 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3600 {
3601 if (is_gimple_omp (stmt)
3602 && is_gimple_omp_oacc (stmt)
3603 && is_gimple_omp (ctx->stmt))
3604 {
3605 error_at (gimple_location (stmt),
3606 "OpenACC construct inside of non-OpenACC region");
3607 return false;
3608 }
3609 continue;
3610 }
3611
3612 const char *stmt_name, *ctx_stmt_name;
3613 switch (gimple_omp_target_kind (stmt))
3614 {
3615 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3616 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3617 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3618 case GF_OMP_TARGET_KIND_ENTER_DATA:
3619 stmt_name = "target enter data"; break;
3620 case GF_OMP_TARGET_KIND_EXIT_DATA:
3621 stmt_name = "target exit data"; break;
3622 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3623 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3624 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3625 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3626 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3627 stmt_name = "enter/exit data"; break;
3628 default: gcc_unreachable ();
3629 }
3630 switch (gimple_omp_target_kind (ctx->stmt))
3631 {
3632 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3633 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3634 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3635 ctx_stmt_name = "parallel"; break;
3636 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3637 ctx_stmt_name = "kernels"; break;
3638 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3639 default: gcc_unreachable ();
3640 }
3641
3642 /* OpenACC/OpenMP mismatch? */
3643 if (is_gimple_omp_oacc (stmt)
3644 != is_gimple_omp_oacc (ctx->stmt))
3645 {
3646 error_at (gimple_location (stmt),
3647 "%s %s construct inside of %s %s region",
3648 (is_gimple_omp_oacc (stmt)
3649 ? "OpenACC" : "OpenMP"), stmt_name,
3650 (is_gimple_omp_oacc (ctx->stmt)
3651 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3652 return false;
3653 }
3654 if (is_gimple_omp_offloaded (ctx->stmt))
3655 {
3656 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3657 if (is_gimple_omp_oacc (ctx->stmt))
3658 {
3659 error_at (gimple_location (stmt),
3660 "%s construct inside of %s region",
3661 stmt_name, ctx_stmt_name);
3662 return false;
3663 }
3664 else
3665 {
3666 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3667 warning_at (gimple_location (stmt), 0,
3668 "%s construct inside of %s region",
3669 stmt_name, ctx_stmt_name);
3670 }
3671 }
3672 }
3673 break;
3674 default:
3675 break;
3676 }
3677 return true;
3678 }
3679
3680
3681 /* Helper function scan_omp.
3682
3683 Callback for walk_tree or operators in walk_gimple_stmt used to
3684 scan for OMP directives in TP. */
3685
3686 static tree
3687 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3688 {
3689 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3690 omp_context *ctx = (omp_context *) wi->info;
3691 tree t = *tp;
3692
3693 switch (TREE_CODE (t))
3694 {
3695 case VAR_DECL:
3696 case PARM_DECL:
3697 case LABEL_DECL:
3698 case RESULT_DECL:
3699 if (ctx)
3700 *tp = remap_decl (t, &ctx->cb);
3701 break;
3702
3703 default:
3704 if (ctx && TYPE_P (t))
3705 *tp = remap_type (t, &ctx->cb);
3706 else if (!DECL_P (t))
3707 {
3708 *walk_subtrees = 1;
3709 if (ctx)
3710 {
3711 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3712 if (tem != TREE_TYPE (t))
3713 {
3714 if (TREE_CODE (t) == INTEGER_CST)
3715 *tp = wide_int_to_tree (tem, t);
3716 else
3717 TREE_TYPE (t) = tem;
3718 }
3719 }
3720 }
3721 break;
3722 }
3723
3724 return NULL_TREE;
3725 }
3726
3727 /* Return true if FNDECL is a setjmp or a longjmp. */
3728
3729 static bool
3730 setjmp_or_longjmp_p (const_tree fndecl)
3731 {
3732 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3733 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3734 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3735 return true;
3736
3737 tree declname = DECL_NAME (fndecl);
3738 if (!declname)
3739 return false;
3740 const char *name = IDENTIFIER_POINTER (declname);
3741 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3742 }
3743
3744
3745 /* Helper function for scan_omp.
3746
3747 Callback for walk_gimple_stmt used to scan for OMP directives in
3748 the current statement in GSI. */
3749
3750 static tree
3751 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3752 struct walk_stmt_info *wi)
3753 {
3754 gimple *stmt = gsi_stmt (*gsi);
3755 omp_context *ctx = (omp_context *) wi->info;
3756
3757 if (gimple_has_location (stmt))
3758 input_location = gimple_location (stmt);
3759
3760 /* Check the nesting restrictions. */
3761 bool remove = false;
3762 if (is_gimple_omp (stmt))
3763 remove = !check_omp_nesting_restrictions (stmt, ctx);
3764 else if (is_gimple_call (stmt))
3765 {
3766 tree fndecl = gimple_call_fndecl (stmt);
3767 if (fndecl)
3768 {
3769 if (setjmp_or_longjmp_p (fndecl)
3770 && ctx
3771 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3772 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3773 {
3774 remove = true;
3775 error_at (gimple_location (stmt),
3776 "setjmp/longjmp inside simd construct");
3777 }
3778 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3779 switch (DECL_FUNCTION_CODE (fndecl))
3780 {
3781 case BUILT_IN_GOMP_BARRIER:
3782 case BUILT_IN_GOMP_CANCEL:
3783 case BUILT_IN_GOMP_CANCELLATION_POINT:
3784 case BUILT_IN_GOMP_TASKYIELD:
3785 case BUILT_IN_GOMP_TASKWAIT:
3786 case BUILT_IN_GOMP_TASKGROUP_START:
3787 case BUILT_IN_GOMP_TASKGROUP_END:
3788 remove = !check_omp_nesting_restrictions (stmt, ctx);
3789 break;
3790 default:
3791 break;
3792 }
3793 }
3794 }
3795 if (remove)
3796 {
3797 stmt = gimple_build_nop ();
3798 gsi_replace (gsi, stmt, false);
3799 }
3800
3801 *handled_ops_p = true;
3802
3803 switch (gimple_code (stmt))
3804 {
3805 case GIMPLE_OMP_PARALLEL:
3806 taskreg_nesting_level++;
3807 scan_omp_parallel (gsi, ctx);
3808 taskreg_nesting_level--;
3809 break;
3810
3811 case GIMPLE_OMP_TASK:
3812 taskreg_nesting_level++;
3813 scan_omp_task (gsi, ctx);
3814 taskreg_nesting_level--;
3815 break;
3816
3817 case GIMPLE_OMP_FOR:
3818 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3819 break;
3820
3821 case GIMPLE_OMP_SECTIONS:
3822 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3823 break;
3824
3825 case GIMPLE_OMP_SINGLE:
3826 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3827 break;
3828
3829 case GIMPLE_OMP_SECTION:
3830 case GIMPLE_OMP_MASTER:
3831 case GIMPLE_OMP_TASKGROUP:
3832 case GIMPLE_OMP_ORDERED:
3833 case GIMPLE_OMP_CRITICAL:
3834 ctx = new_omp_context (stmt, ctx);
3835 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3836 break;
3837
3838 case GIMPLE_OMP_TARGET:
3839 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3840 break;
3841
3842 case GIMPLE_OMP_TEAMS:
3843 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3844 break;
3845
3846 case GIMPLE_BIND:
3847 {
3848 tree var;
3849
3850 *handled_ops_p = false;
3851 if (ctx)
3852 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3853 var ;
3854 var = DECL_CHAIN (var))
3855 insert_decl_map (&ctx->cb, var, var);
3856 }
3857 break;
3858 default:
3859 *handled_ops_p = false;
3860 break;
3861 }
3862
3863 return NULL_TREE;
3864 }
3865
3866
3867 /* Scan all the statements starting at the current statement. CTX
3868 contains context information about the OMP directives and
3869 clauses found during the scan. */
3870
3871 static void
3872 scan_omp (gimple_seq *body_p, omp_context *ctx)
3873 {
3874 location_t saved_location;
3875 struct walk_stmt_info wi;
3876
3877 memset (&wi, 0, sizeof (wi));
3878 wi.info = ctx;
3879 wi.want_locations = true;
3880
3881 saved_location = input_location;
3882 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3883 input_location = saved_location;
3884 }
3885 \f
3886 /* Re-gimplification and code generation routines. */
3887
3888 /* Build a call to GOMP_barrier. */
3889
3890 static gimple *
3891 build_omp_barrier (tree lhs)
3892 {
3893 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3894 : BUILT_IN_GOMP_BARRIER);
3895 gcall *g = gimple_build_call (fndecl, 0);
3896 if (lhs)
3897 gimple_call_set_lhs (g, lhs);
3898 return g;
3899 }
3900
3901 /* If a context was created for STMT when it was scanned, return it. */
3902
3903 static omp_context *
3904 maybe_lookup_ctx (gimple *stmt)
3905 {
3906 splay_tree_node n;
3907 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3908 return n ? (omp_context *) n->value : NULL;
3909 }
3910
3911
3912 /* Find the mapping for DECL in CTX or the immediately enclosing
3913 context that has a mapping for DECL.
3914
3915 If CTX is a nested parallel directive, we may have to use the decl
3916 mappings created in CTX's parent context. Suppose that we have the
3917 following parallel nesting (variable UIDs showed for clarity):
3918
3919 iD.1562 = 0;
3920 #omp parallel shared(iD.1562) -> outer parallel
3921 iD.1562 = iD.1562 + 1;
3922
3923 #omp parallel shared (iD.1562) -> inner parallel
3924 iD.1562 = iD.1562 - 1;
3925
3926 Each parallel structure will create a distinct .omp_data_s structure
3927 for copying iD.1562 in/out of the directive:
3928
3929 outer parallel .omp_data_s.1.i -> iD.1562
3930 inner parallel .omp_data_s.2.i -> iD.1562
3931
3932 A shared variable mapping will produce a copy-out operation before
3933 the parallel directive and a copy-in operation after it. So, in
3934 this case we would have:
3935
3936 iD.1562 = 0;
3937 .omp_data_o.1.i = iD.1562;
3938 #omp parallel shared(iD.1562) -> outer parallel
3939 .omp_data_i.1 = &.omp_data_o.1
3940 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3941
3942 .omp_data_o.2.i = iD.1562; -> **
3943 #omp parallel shared(iD.1562) -> inner parallel
3944 .omp_data_i.2 = &.omp_data_o.2
3945 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3946
3947
3948 ** This is a problem. The symbol iD.1562 cannot be referenced
3949 inside the body of the outer parallel region. But since we are
3950 emitting this copy operation while expanding the inner parallel
3951 directive, we need to access the CTX structure of the outer
3952 parallel directive to get the correct mapping:
3953
3954 .omp_data_o.2.i = .omp_data_i.1->i
3955
3956 Since there may be other workshare or parallel directives enclosing
3957 the parallel directive, it may be necessary to walk up the context
3958 parent chain. This is not a problem in general because nested
3959 parallelism happens only rarely. */
3960
3961 static tree
3962 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3963 {
3964 tree t;
3965 omp_context *up;
3966
3967 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3968 t = maybe_lookup_decl (decl, up);
3969
3970 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3971
3972 return t ? t : decl;
3973 }
3974
3975
3976 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3977 in outer contexts. */
3978
3979 static tree
3980 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3981 {
3982 tree t = NULL;
3983 omp_context *up;
3984
3985 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3986 t = maybe_lookup_decl (decl, up);
3987
3988 return t ? t : decl;
3989 }
3990
3991
3992 /* Construct the initialization value for reduction operation OP. */
3993
3994 tree
3995 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
3996 {
3997 switch (op)
3998 {
3999 case PLUS_EXPR:
4000 case MINUS_EXPR:
4001 case BIT_IOR_EXPR:
4002 case BIT_XOR_EXPR:
4003 case TRUTH_OR_EXPR:
4004 case TRUTH_ORIF_EXPR:
4005 case TRUTH_XOR_EXPR:
4006 case NE_EXPR:
4007 return build_zero_cst (type);
4008
4009 case MULT_EXPR:
4010 case TRUTH_AND_EXPR:
4011 case TRUTH_ANDIF_EXPR:
4012 case EQ_EXPR:
4013 return fold_convert_loc (loc, type, integer_one_node);
4014
4015 case BIT_AND_EXPR:
4016 return fold_convert_loc (loc, type, integer_minus_one_node);
4017
4018 case MAX_EXPR:
4019 if (SCALAR_FLOAT_TYPE_P (type))
4020 {
4021 REAL_VALUE_TYPE max, min;
4022 if (HONOR_INFINITIES (type))
4023 {
4024 real_inf (&max);
4025 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4026 }
4027 else
4028 real_maxval (&min, 1, TYPE_MODE (type));
4029 return build_real (type, min);
4030 }
4031 else if (POINTER_TYPE_P (type))
4032 {
4033 wide_int min
4034 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4035 return wide_int_to_tree (type, min);
4036 }
4037 else
4038 {
4039 gcc_assert (INTEGRAL_TYPE_P (type));
4040 return TYPE_MIN_VALUE (type);
4041 }
4042
4043 case MIN_EXPR:
4044 if (SCALAR_FLOAT_TYPE_P (type))
4045 {
4046 REAL_VALUE_TYPE max;
4047 if (HONOR_INFINITIES (type))
4048 real_inf (&max);
4049 else
4050 real_maxval (&max, 0, TYPE_MODE (type));
4051 return build_real (type, max);
4052 }
4053 else if (POINTER_TYPE_P (type))
4054 {
4055 wide_int max
4056 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4057 return wide_int_to_tree (type, max);
4058 }
4059 else
4060 {
4061 gcc_assert (INTEGRAL_TYPE_P (type));
4062 return TYPE_MAX_VALUE (type);
4063 }
4064
4065 default:
4066 gcc_unreachable ();
4067 }
4068 }
4069
4070 /* Construct the initialization value for reduction CLAUSE. */
4071
4072 tree
4073 omp_reduction_init (tree clause, tree type)
4074 {
4075 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4076 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4077 }
4078
4079 /* Return alignment to be assumed for var in CLAUSE, which should be
4080 OMP_CLAUSE_ALIGNED. */
4081
4082 static tree
4083 omp_clause_aligned_alignment (tree clause)
4084 {
4085 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4086 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4087
4088 /* Otherwise return implementation defined alignment. */
4089 unsigned int al = 1;
4090 machine_mode mode, vmode;
4091 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4092 if (vs)
4093 vs = 1 << floor_log2 (vs);
4094 static enum mode_class classes[]
4095 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4096 for (int i = 0; i < 4; i += 2)
4097 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4098 mode != VOIDmode;
4099 mode = GET_MODE_WIDER_MODE (mode))
4100 {
4101 vmode = targetm.vectorize.preferred_simd_mode (mode);
4102 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4103 continue;
4104 while (vs
4105 && GET_MODE_SIZE (vmode) < vs
4106 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4107 vmode = GET_MODE_2XWIDER_MODE (vmode);
4108
4109 tree type = lang_hooks.types.type_for_mode (mode, 1);
4110 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4111 continue;
4112 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4113 / GET_MODE_SIZE (mode));
4114 if (TYPE_MODE (type) != vmode)
4115 continue;
4116 if (TYPE_ALIGN_UNIT (type) > al)
4117 al = TYPE_ALIGN_UNIT (type);
4118 }
4119 return build_int_cst (integer_type_node, al);
4120 }
4121
4122 /* Return maximum possible vectorization factor for the target. */
4123
4124 static int
4125 omp_max_vf (void)
4126 {
4127 if (!optimize
4128 || optimize_debug
4129 || !flag_tree_loop_optimize
4130 || (!flag_tree_loop_vectorize
4131 && (global_options_set.x_flag_tree_loop_vectorize
4132 || global_options_set.x_flag_tree_vectorize)))
4133 return 1;
4134
4135 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4136 if (vs)
4137 {
4138 vs = 1 << floor_log2 (vs);
4139 return vs;
4140 }
4141 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4142 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4143 return GET_MODE_NUNITS (vqimode);
4144 return 1;
4145 }
4146
4147 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4148 privatization. */
4149
4150 static bool
4151 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4152 tree &idx, tree &lane, tree &ivar, tree &lvar)
4153 {
4154 if (max_vf == 0)
4155 {
4156 max_vf = omp_max_vf ();
4157 if (max_vf > 1)
4158 {
4159 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4160 OMP_CLAUSE_SAFELEN);
4161 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4162 max_vf = 1;
4163 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4164 max_vf) == -1)
4165 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4166 }
4167 if (max_vf > 1)
4168 {
4169 idx = create_tmp_var (unsigned_type_node);
4170 lane = create_tmp_var (unsigned_type_node);
4171 }
4172 }
4173 if (max_vf == 1)
4174 return false;
4175
4176 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4177 tree avar = create_tmp_var_raw (atype);
4178 if (TREE_ADDRESSABLE (new_var))
4179 TREE_ADDRESSABLE (avar) = 1;
4180 DECL_ATTRIBUTES (avar)
4181 = tree_cons (get_identifier ("omp simd array"), NULL,
4182 DECL_ATTRIBUTES (avar));
4183 gimple_add_tmp_var (avar);
4184 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4185 NULL_TREE, NULL_TREE);
4186 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4187 NULL_TREE, NULL_TREE);
4188 if (DECL_P (new_var))
4189 {
4190 SET_DECL_VALUE_EXPR (new_var, lvar);
4191 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4192 }
4193 return true;
4194 }
4195
4196 /* Helper function of lower_rec_input_clauses. For a reference
4197 in simd reduction, add an underlying variable it will reference. */
4198
4199 static void
4200 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4201 {
4202 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4203 if (TREE_CONSTANT (z))
4204 {
4205 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4206 get_name (new_vard));
4207 gimple_add_tmp_var (z);
4208 TREE_ADDRESSABLE (z) = 1;
4209 z = build_fold_addr_expr_loc (loc, z);
4210 gimplify_assign (new_vard, z, ilist);
4211 }
4212 }
4213
4214 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4215 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4216 private variables. Initialization statements go in ILIST, while calls
4217 to destructors go in DLIST. */
4218
4219 static void
4220 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4221 omp_context *ctx, struct omp_for_data *fd)
4222 {
4223 tree c, dtor, copyin_seq, x, ptr;
4224 bool copyin_by_ref = false;
4225 bool lastprivate_firstprivate = false;
4226 bool reduction_omp_orig_ref = false;
4227 int pass;
4228 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4229 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4230 int max_vf = 0;
4231 tree lane = NULL_TREE, idx = NULL_TREE;
4232 tree ivar = NULL_TREE, lvar = NULL_TREE;
4233 gimple_seq llist[2] = { NULL, NULL };
4234
4235 copyin_seq = NULL;
4236
4237 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4238 with data sharing clauses referencing variable sized vars. That
4239 is unnecessarily hard to support and very unlikely to result in
4240 vectorized code anyway. */
4241 if (is_simd)
4242 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4243 switch (OMP_CLAUSE_CODE (c))
4244 {
4245 case OMP_CLAUSE_LINEAR:
4246 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4247 max_vf = 1;
4248 /* FALLTHRU */
4249 case OMP_CLAUSE_PRIVATE:
4250 case OMP_CLAUSE_FIRSTPRIVATE:
4251 case OMP_CLAUSE_LASTPRIVATE:
4252 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4253 max_vf = 1;
4254 break;
4255 case OMP_CLAUSE_REDUCTION:
4256 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4257 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4258 max_vf = 1;
4259 break;
4260 default:
4261 continue;
4262 }
4263
4264 /* Do all the fixed sized types in the first pass, and the variable sized
4265 types in the second pass. This makes sure that the scalar arguments to
4266 the variable sized types are processed before we use them in the
4267 variable sized operations. */
4268 for (pass = 0; pass < 2; ++pass)
4269 {
4270 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4271 {
4272 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4273 tree var, new_var;
4274 bool by_ref;
4275 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4276
4277 switch (c_kind)
4278 {
4279 case OMP_CLAUSE_PRIVATE:
4280 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4281 continue;
4282 break;
4283 case OMP_CLAUSE_SHARED:
4284 /* Ignore shared directives in teams construct. */
4285 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4286 continue;
4287 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4288 {
4289 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4290 || is_global_var (OMP_CLAUSE_DECL (c)));
4291 continue;
4292 }
4293 case OMP_CLAUSE_FIRSTPRIVATE:
4294 case OMP_CLAUSE_COPYIN:
4295 break;
4296 case OMP_CLAUSE_LINEAR:
4297 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4298 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4299 lastprivate_firstprivate = true;
4300 break;
4301 case OMP_CLAUSE_REDUCTION:
4302 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4303 reduction_omp_orig_ref = true;
4304 break;
4305 case OMP_CLAUSE__LOOPTEMP_:
4306 /* Handle _looptemp_ clauses only on parallel/task. */
4307 if (fd)
4308 continue;
4309 break;
4310 case OMP_CLAUSE_LASTPRIVATE:
4311 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4312 {
4313 lastprivate_firstprivate = true;
4314 if (pass != 0 || is_taskloop_ctx (ctx))
4315 continue;
4316 }
4317 /* Even without corresponding firstprivate, if
4318 decl is Fortran allocatable, it needs outer var
4319 reference. */
4320 else if (pass == 0
4321 && lang_hooks.decls.omp_private_outer_ref
4322 (OMP_CLAUSE_DECL (c)))
4323 lastprivate_firstprivate = true;
4324 break;
4325 case OMP_CLAUSE_ALIGNED:
4326 if (pass == 0)
4327 continue;
4328 var = OMP_CLAUSE_DECL (c);
4329 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4330 && !is_global_var (var))
4331 {
4332 new_var = maybe_lookup_decl (var, ctx);
4333 if (new_var == NULL_TREE)
4334 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4335 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4336 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4337 omp_clause_aligned_alignment (c));
4338 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4339 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4340 gimplify_and_add (x, ilist);
4341 }
4342 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4343 && is_global_var (var))
4344 {
4345 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4346 new_var = lookup_decl (var, ctx);
4347 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4348 t = build_fold_addr_expr_loc (clause_loc, t);
4349 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4350 t = build_call_expr_loc (clause_loc, t2, 2, t,
4351 omp_clause_aligned_alignment (c));
4352 t = fold_convert_loc (clause_loc, ptype, t);
4353 x = create_tmp_var (ptype);
4354 t = build2 (MODIFY_EXPR, ptype, x, t);
4355 gimplify_and_add (t, ilist);
4356 t = build_simple_mem_ref_loc (clause_loc, x);
4357 SET_DECL_VALUE_EXPR (new_var, t);
4358 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4359 }
4360 continue;
4361 default:
4362 continue;
4363 }
4364
4365 new_var = var = OMP_CLAUSE_DECL (c);
4366 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4367 {
4368 var = TREE_OPERAND (var, 0);
4369 if (TREE_CODE (var) == INDIRECT_REF
4370 || TREE_CODE (var) == ADDR_EXPR)
4371 var = TREE_OPERAND (var, 0);
4372 if (is_variable_sized (var))
4373 {
4374 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4375 var = DECL_VALUE_EXPR (var);
4376 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4377 var = TREE_OPERAND (var, 0);
4378 gcc_assert (DECL_P (var));
4379 }
4380 new_var = var;
4381 }
4382 if (c_kind != OMP_CLAUSE_COPYIN)
4383 new_var = lookup_decl (var, ctx);
4384
4385 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4386 {
4387 if (pass != 0)
4388 continue;
4389 }
4390 /* C/C++ array section reductions. */
4391 else if (c_kind == OMP_CLAUSE_REDUCTION
4392 && var != OMP_CLAUSE_DECL (c))
4393 {
4394 if (pass == 0)
4395 continue;
4396
4397 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4398 if (TREE_CODE (orig_var) == INDIRECT_REF
4399 || TREE_CODE (orig_var) == ADDR_EXPR)
4400 orig_var = TREE_OPERAND (orig_var, 0);
4401 tree d = OMP_CLAUSE_DECL (c);
4402 tree type = TREE_TYPE (d);
4403 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4404 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4405 const char *name = get_name (orig_var);
4406 if (TREE_CONSTANT (v))
4407 {
4408 x = create_tmp_var_raw (type, name);
4409 gimple_add_tmp_var (x);
4410 TREE_ADDRESSABLE (x) = 1;
4411 x = build_fold_addr_expr_loc (clause_loc, x);
4412 }
4413 else
4414 {
4415 tree atmp
4416 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4417 tree t = maybe_lookup_decl (v, ctx);
4418 if (t)
4419 v = t;
4420 else
4421 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4422 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4423 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4424 TREE_TYPE (v), v,
4425 build_int_cst (TREE_TYPE (v), 1));
4426 t = fold_build2_loc (clause_loc, MULT_EXPR,
4427 TREE_TYPE (v), t,
4428 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4429 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4430 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4431 }
4432
4433 tree ptype = build_pointer_type (TREE_TYPE (type));
4434 x = fold_convert_loc (clause_loc, ptype, x);
4435 tree y = create_tmp_var (ptype, name);
4436 gimplify_assign (y, x, ilist);
4437 x = y;
4438 if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
4439 {
4440 if (orig_var != var)
4441 {
4442 gcc_assert (is_variable_sized (orig_var));
4443 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4444 x);
4445 gimplify_assign (new_var, x, ilist);
4446 tree new_orig_var = lookup_decl (orig_var, ctx);
4447 tree t = build_fold_indirect_ref (new_var);
4448 DECL_IGNORED_P (new_var) = 0;
4449 TREE_THIS_NOTRAP (t);
4450 SET_DECL_VALUE_EXPR (new_orig_var, t);
4451 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4452 }
4453 else
4454 {
4455 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4456 build_int_cst (ptype, 0));
4457 SET_DECL_VALUE_EXPR (new_var, x);
4458 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4459 }
4460 }
4461 else
4462 {
4463 gcc_assert (orig_var == var);
4464 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
4465 {
4466 x = create_tmp_var (ptype, name);
4467 TREE_ADDRESSABLE (x) = 1;
4468 gimplify_assign (x, y, ilist);
4469 x = build_fold_addr_expr_loc (clause_loc, x);
4470 }
4471 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4472 gimplify_assign (new_var, x, ilist);
4473 }
4474 tree y1 = create_tmp_var (ptype, NULL);
4475 gimplify_assign (y1, y, ilist);
4476 tree i2 = NULL_TREE, y2 = NULL_TREE;
4477 tree body2 = NULL_TREE, end2 = NULL_TREE;
4478 tree y3 = NULL_TREE, y4 = NULL_TREE;
4479 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4480 {
4481 y2 = create_tmp_var (ptype, NULL);
4482 gimplify_assign (y2, y, ilist);
4483 tree ref = build_outer_var_ref (var, ctx);
4484 /* For ref build_outer_var_ref already performs this. */
4485 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
4486 gcc_assert (is_reference (var));
4487 else if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
4488 ref = build_fold_addr_expr (ref);
4489 else if (is_reference (var))
4490 ref = build_fold_addr_expr (ref);
4491 ref = fold_convert_loc (clause_loc, ptype, ref);
4492 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4493 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4494 {
4495 y3 = create_tmp_var (ptype, NULL);
4496 gimplify_assign (y3, unshare_expr (ref), ilist);
4497 }
4498 if (is_simd)
4499 {
4500 y4 = create_tmp_var (ptype, NULL);
4501 gimplify_assign (y4, ref, dlist);
4502 }
4503 }
4504 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4505 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4506 tree body = create_artificial_label (UNKNOWN_LOCATION);
4507 tree end = create_artificial_label (UNKNOWN_LOCATION);
4508 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4509 if (y2)
4510 {
4511 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4512 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4513 body2 = create_artificial_label (UNKNOWN_LOCATION);
4514 end2 = create_artificial_label (UNKNOWN_LOCATION);
4515 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4516 }
4517 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4518 {
4519 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4520 tree decl_placeholder
4521 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4522 SET_DECL_VALUE_EXPR (decl_placeholder,
4523 build_simple_mem_ref (y1));
4524 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4525 SET_DECL_VALUE_EXPR (placeholder,
4526 y3 ? build_simple_mem_ref (y3)
4527 : error_mark_node);
4528 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4529 x = lang_hooks.decls.omp_clause_default_ctor
4530 (c, build_simple_mem_ref (y1),
4531 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4532 if (x)
4533 gimplify_and_add (x, ilist);
4534 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4535 {
4536 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4537 lower_omp (&tseq, ctx);
4538 gimple_seq_add_seq (ilist, tseq);
4539 }
4540 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4541 if (is_simd)
4542 {
4543 SET_DECL_VALUE_EXPR (decl_placeholder,
4544 build_simple_mem_ref (y2));
4545 SET_DECL_VALUE_EXPR (placeholder,
4546 build_simple_mem_ref (y4));
4547 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4548 lower_omp (&tseq, ctx);
4549 gimple_seq_add_seq (dlist, tseq);
4550 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4551 }
4552 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4553 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4554 x = lang_hooks.decls.omp_clause_dtor
4555 (c, build_simple_mem_ref (y2));
4556 if (x)
4557 {
4558 gimple_seq tseq = NULL;
4559 dtor = x;
4560 gimplify_stmt (&dtor, &tseq);
4561 gimple_seq_add_seq (dlist, tseq);
4562 }
4563 }
4564 else
4565 {
4566 x = omp_reduction_init (c, TREE_TYPE (type));
4567 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4568
4569 /* reduction(-:var) sums up the partial results, so it
4570 acts identically to reduction(+:var). */
4571 if (code == MINUS_EXPR)
4572 code = PLUS_EXPR;
4573
4574 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4575 if (is_simd)
4576 {
4577 x = build2 (code, TREE_TYPE (type),
4578 build_simple_mem_ref (y4),
4579 build_simple_mem_ref (y2));
4580 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4581 }
4582 }
4583 gimple *g
4584 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4585 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4586 gimple_seq_add_stmt (ilist, g);
4587 if (y3)
4588 {
4589 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4590 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4591 gimple_seq_add_stmt (ilist, g);
4592 }
4593 g = gimple_build_assign (i, PLUS_EXPR, i,
4594 build_int_cst (TREE_TYPE (i), 1));
4595 gimple_seq_add_stmt (ilist, g);
4596 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4597 gimple_seq_add_stmt (ilist, g);
4598 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4599 if (y2)
4600 {
4601 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4602 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4603 gimple_seq_add_stmt (dlist, g);
4604 if (y4)
4605 {
4606 g = gimple_build_assign
4607 (y4, POINTER_PLUS_EXPR, y4,
4608 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4609 gimple_seq_add_stmt (dlist, g);
4610 }
4611 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4612 build_int_cst (TREE_TYPE (i2), 1));
4613 gimple_seq_add_stmt (dlist, g);
4614 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4615 gimple_seq_add_stmt (dlist, g);
4616 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4617 }
4618 continue;
4619 }
4620 else if (is_variable_sized (var))
4621 {
4622 /* For variable sized types, we need to allocate the
4623 actual storage here. Call alloca and store the
4624 result in the pointer decl that we created elsewhere. */
4625 if (pass == 0)
4626 continue;
4627
4628 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4629 {
4630 gcall *stmt;
4631 tree tmp, atmp;
4632
4633 ptr = DECL_VALUE_EXPR (new_var);
4634 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4635 ptr = TREE_OPERAND (ptr, 0);
4636 gcc_assert (DECL_P (ptr));
4637 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4638
4639 /* void *tmp = __builtin_alloca */
4640 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4641 stmt = gimple_build_call (atmp, 2, x,
4642 size_int (DECL_ALIGN (var)));
4643 tmp = create_tmp_var_raw (ptr_type_node);
4644 gimple_add_tmp_var (tmp);
4645 gimple_call_set_lhs (stmt, tmp);
4646
4647 gimple_seq_add_stmt (ilist, stmt);
4648
4649 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4650 gimplify_assign (ptr, x, ilist);
4651 }
4652 }
4653 else if (is_reference (var))
4654 {
4655 /* For references that are being privatized for Fortran,
4656 allocate new backing storage for the new pointer
4657 variable. This allows us to avoid changing all the
4658 code that expects a pointer to something that expects
4659 a direct variable. */
4660 if (pass == 0)
4661 continue;
4662
4663 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4664 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4665 {
4666 x = build_receiver_ref (var, false, ctx);
4667 x = build_fold_addr_expr_loc (clause_loc, x);
4668 }
4669 else if (TREE_CONSTANT (x))
4670 {
4671 /* For reduction in SIMD loop, defer adding the
4672 initialization of the reference, because if we decide
4673 to use SIMD array for it, the initilization could cause
4674 expansion ICE. */
4675 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4676 x = NULL_TREE;
4677 else
4678 {
4679 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4680 get_name (var));
4681 gimple_add_tmp_var (x);
4682 TREE_ADDRESSABLE (x) = 1;
4683 x = build_fold_addr_expr_loc (clause_loc, x);
4684 }
4685 }
4686 else
4687 {
4688 tree atmp
4689 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4690 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4691 tree al = size_int (TYPE_ALIGN (rtype));
4692 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4693 }
4694
4695 if (x)
4696 {
4697 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4698 gimplify_assign (new_var, x, ilist);
4699 }
4700
4701 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4702 }
4703 else if (c_kind == OMP_CLAUSE_REDUCTION
4704 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4705 {
4706 if (pass == 0)
4707 continue;
4708 }
4709 else if (pass != 0)
4710 continue;
4711
4712 switch (OMP_CLAUSE_CODE (c))
4713 {
4714 case OMP_CLAUSE_SHARED:
4715 /* Ignore shared directives in teams construct. */
4716 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4717 continue;
4718 /* Shared global vars are just accessed directly. */
4719 if (is_global_var (new_var))
4720 break;
4721 /* For taskloop firstprivate/lastprivate, represented
4722 as firstprivate and shared clause on the task, new_var
4723 is the firstprivate var. */
4724 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4725 break;
4726 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4727 needs to be delayed until after fixup_child_record_type so
4728 that we get the correct type during the dereference. */
4729 by_ref = use_pointer_for_field (var, ctx);
4730 x = build_receiver_ref (var, by_ref, ctx);
4731 SET_DECL_VALUE_EXPR (new_var, x);
4732 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4733
4734 /* ??? If VAR is not passed by reference, and the variable
4735 hasn't been initialized yet, then we'll get a warning for
4736 the store into the omp_data_s structure. Ideally, we'd be
4737 able to notice this and not store anything at all, but
4738 we're generating code too early. Suppress the warning. */
4739 if (!by_ref)
4740 TREE_NO_WARNING (var) = 1;
4741 break;
4742
4743 case OMP_CLAUSE_LASTPRIVATE:
4744 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4745 break;
4746 /* FALLTHRU */
4747
4748 case OMP_CLAUSE_PRIVATE:
4749 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4750 x = build_outer_var_ref (var, ctx);
4751 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4752 {
4753 if (is_task_ctx (ctx))
4754 x = build_receiver_ref (var, false, ctx);
4755 else
4756 x = build_outer_var_ref (var, ctx);
4757 }
4758 else
4759 x = NULL;
4760 do_private:
4761 tree nx;
4762 nx = lang_hooks.decls.omp_clause_default_ctor
4763 (c, unshare_expr (new_var), x);
4764 if (is_simd)
4765 {
4766 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4767 if ((TREE_ADDRESSABLE (new_var) || nx || y
4768 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4769 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4770 idx, lane, ivar, lvar))
4771 {
4772 if (nx)
4773 x = lang_hooks.decls.omp_clause_default_ctor
4774 (c, unshare_expr (ivar), x);
4775 if (nx && x)
4776 gimplify_and_add (x, &llist[0]);
4777 if (y)
4778 {
4779 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4780 if (y)
4781 {
4782 gimple_seq tseq = NULL;
4783
4784 dtor = y;
4785 gimplify_stmt (&dtor, &tseq);
4786 gimple_seq_add_seq (&llist[1], tseq);
4787 }
4788 }
4789 break;
4790 }
4791 }
4792 if (nx)
4793 gimplify_and_add (nx, ilist);
4794 /* FALLTHRU */
4795
4796 do_dtor:
4797 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4798 if (x)
4799 {
4800 gimple_seq tseq = NULL;
4801
4802 dtor = x;
4803 gimplify_stmt (&dtor, &tseq);
4804 gimple_seq_add_seq (dlist, tseq);
4805 }
4806 break;
4807
4808 case OMP_CLAUSE_LINEAR:
4809 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4810 goto do_firstprivate;
4811 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4812 x = NULL;
4813 else
4814 x = build_outer_var_ref (var, ctx);
4815 goto do_private;
4816
4817 case OMP_CLAUSE_FIRSTPRIVATE:
4818 if (is_task_ctx (ctx))
4819 {
4820 if (is_reference (var) || is_variable_sized (var))
4821 goto do_dtor;
4822 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4823 ctx))
4824 || use_pointer_for_field (var, NULL))
4825 {
4826 x = build_receiver_ref (var, false, ctx);
4827 SET_DECL_VALUE_EXPR (new_var, x);
4828 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4829 goto do_dtor;
4830 }
4831 }
4832 do_firstprivate:
4833 x = build_outer_var_ref (var, ctx);
4834 if (is_simd)
4835 {
4836 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4837 && gimple_omp_for_combined_into_p (ctx->stmt))
4838 {
4839 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4840 tree stept = TREE_TYPE (t);
4841 tree ct = find_omp_clause (clauses,
4842 OMP_CLAUSE__LOOPTEMP_);
4843 gcc_assert (ct);
4844 tree l = OMP_CLAUSE_DECL (ct);
4845 tree n1 = fd->loop.n1;
4846 tree step = fd->loop.step;
4847 tree itype = TREE_TYPE (l);
4848 if (POINTER_TYPE_P (itype))
4849 itype = signed_type_for (itype);
4850 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4851 if (TYPE_UNSIGNED (itype)
4852 && fd->loop.cond_code == GT_EXPR)
4853 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4854 fold_build1 (NEGATE_EXPR, itype, l),
4855 fold_build1 (NEGATE_EXPR,
4856 itype, step));
4857 else
4858 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
4859 t = fold_build2 (MULT_EXPR, stept,
4860 fold_convert (stept, l), t);
4861
4862 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4863 {
4864 x = lang_hooks.decls.omp_clause_linear_ctor
4865 (c, new_var, x, t);
4866 gimplify_and_add (x, ilist);
4867 goto do_dtor;
4868 }
4869
4870 if (POINTER_TYPE_P (TREE_TYPE (x)))
4871 x = fold_build2 (POINTER_PLUS_EXPR,
4872 TREE_TYPE (x), x, t);
4873 else
4874 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4875 }
4876
4877 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4878 || TREE_ADDRESSABLE (new_var))
4879 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4880 idx, lane, ivar, lvar))
4881 {
4882 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4883 {
4884 tree iv = create_tmp_var (TREE_TYPE (new_var));
4885 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4886 gimplify_and_add (x, ilist);
4887 gimple_stmt_iterator gsi
4888 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4889 gassign *g
4890 = gimple_build_assign (unshare_expr (lvar), iv);
4891 gsi_insert_before_without_update (&gsi, g,
4892 GSI_SAME_STMT);
4893 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4894 enum tree_code code = PLUS_EXPR;
4895 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4896 code = POINTER_PLUS_EXPR;
4897 g = gimple_build_assign (iv, code, iv, t);
4898 gsi_insert_before_without_update (&gsi, g,
4899 GSI_SAME_STMT);
4900 break;
4901 }
4902 x = lang_hooks.decls.omp_clause_copy_ctor
4903 (c, unshare_expr (ivar), x);
4904 gimplify_and_add (x, &llist[0]);
4905 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4906 if (x)
4907 {
4908 gimple_seq tseq = NULL;
4909
4910 dtor = x;
4911 gimplify_stmt (&dtor, &tseq);
4912 gimple_seq_add_seq (&llist[1], tseq);
4913 }
4914 break;
4915 }
4916 }
4917 x = lang_hooks.decls.omp_clause_copy_ctor
4918 (c, unshare_expr (new_var), x);
4919 gimplify_and_add (x, ilist);
4920 goto do_dtor;
4921
4922 case OMP_CLAUSE__LOOPTEMP_:
4923 gcc_assert (is_taskreg_ctx (ctx));
4924 x = build_outer_var_ref (var, ctx);
4925 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4926 gimplify_and_add (x, ilist);
4927 break;
4928
4929 case OMP_CLAUSE_COPYIN:
4930 by_ref = use_pointer_for_field (var, NULL);
4931 x = build_receiver_ref (var, by_ref, ctx);
4932 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4933 append_to_statement_list (x, &copyin_seq);
4934 copyin_by_ref |= by_ref;
4935 break;
4936
4937 case OMP_CLAUSE_REDUCTION:
4938 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4939 {
4940 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4941 gimple *tseq;
4942 x = build_outer_var_ref (var, ctx);
4943
4944 if (is_reference (var)
4945 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4946 TREE_TYPE (x)))
4947 x = build_fold_addr_expr_loc (clause_loc, x);
4948 SET_DECL_VALUE_EXPR (placeholder, x);
4949 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4950 tree new_vard = new_var;
4951 if (is_reference (var))
4952 {
4953 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4954 new_vard = TREE_OPERAND (new_var, 0);
4955 gcc_assert (DECL_P (new_vard));
4956 }
4957 if (is_simd
4958 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4959 idx, lane, ivar, lvar))
4960 {
4961 if (new_vard == new_var)
4962 {
4963 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4964 SET_DECL_VALUE_EXPR (new_var, ivar);
4965 }
4966 else
4967 {
4968 SET_DECL_VALUE_EXPR (new_vard,
4969 build_fold_addr_expr (ivar));
4970 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4971 }
4972 x = lang_hooks.decls.omp_clause_default_ctor
4973 (c, unshare_expr (ivar),
4974 build_outer_var_ref (var, ctx));
4975 if (x)
4976 gimplify_and_add (x, &llist[0]);
4977 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4978 {
4979 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4980 lower_omp (&tseq, ctx);
4981 gimple_seq_add_seq (&llist[0], tseq);
4982 }
4983 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4984 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4985 lower_omp (&tseq, ctx);
4986 gimple_seq_add_seq (&llist[1], tseq);
4987 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4988 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4989 if (new_vard == new_var)
4990 SET_DECL_VALUE_EXPR (new_var, lvar);
4991 else
4992 SET_DECL_VALUE_EXPR (new_vard,
4993 build_fold_addr_expr (lvar));
4994 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4995 if (x)
4996 {
4997 tseq = NULL;
4998 dtor = x;
4999 gimplify_stmt (&dtor, &tseq);
5000 gimple_seq_add_seq (&llist[1], tseq);
5001 }
5002 break;
5003 }
5004 /* If this is a reference to constant size reduction var
5005 with placeholder, we haven't emitted the initializer
5006 for it because it is undesirable if SIMD arrays are used.
5007 But if they aren't used, we need to emit the deferred
5008 initialization now. */
5009 else if (is_reference (var) && is_simd)
5010 handle_simd_reference (clause_loc, new_vard, ilist);
5011 x = lang_hooks.decls.omp_clause_default_ctor
5012 (c, unshare_expr (new_var),
5013 build_outer_var_ref (var, ctx));
5014 if (x)
5015 gimplify_and_add (x, ilist);
5016 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5017 {
5018 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5019 lower_omp (&tseq, ctx);
5020 gimple_seq_add_seq (ilist, tseq);
5021 }
5022 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5023 if (is_simd)
5024 {
5025 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5026 lower_omp (&tseq, ctx);
5027 gimple_seq_add_seq (dlist, tseq);
5028 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5029 }
5030 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5031 goto do_dtor;
5032 }
5033 else
5034 {
5035 x = omp_reduction_init (c, TREE_TYPE (new_var));
5036 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5037 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5038
5039 /* reduction(-:var) sums up the partial results, so it
5040 acts identically to reduction(+:var). */
5041 if (code == MINUS_EXPR)
5042 code = PLUS_EXPR;
5043
5044 tree new_vard = new_var;
5045 if (is_simd && is_reference (var))
5046 {
5047 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5048 new_vard = TREE_OPERAND (new_var, 0);
5049 gcc_assert (DECL_P (new_vard));
5050 }
5051 if (is_simd
5052 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5053 idx, lane, ivar, lvar))
5054 {
5055 tree ref = build_outer_var_ref (var, ctx);
5056
5057 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5058
5059 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5060 ref = build_outer_var_ref (var, ctx);
5061 gimplify_assign (ref, x, &llist[1]);
5062
5063 if (new_vard != new_var)
5064 {
5065 SET_DECL_VALUE_EXPR (new_vard,
5066 build_fold_addr_expr (lvar));
5067 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5068 }
5069 }
5070 else
5071 {
5072 if (is_reference (var) && is_simd)
5073 handle_simd_reference (clause_loc, new_vard, ilist);
5074 gimplify_assign (new_var, x, ilist);
5075 if (is_simd)
5076 {
5077 tree ref = build_outer_var_ref (var, ctx);
5078
5079 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5080 ref = build_outer_var_ref (var, ctx);
5081 gimplify_assign (ref, x, dlist);
5082 }
5083 }
5084 }
5085 break;
5086
5087 default:
5088 gcc_unreachable ();
5089 }
5090 }
5091 }
5092
5093 if (lane)
5094 {
5095 tree uid = create_tmp_var (ptr_type_node, "simduid");
5096 /* Don't want uninit warnings on simduid, it is always uninitialized,
5097 but we use it not for the value, but for the DECL_UID only. */
5098 TREE_NO_WARNING (uid) = 1;
5099 gimple *g
5100 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5101 gimple_call_set_lhs (g, lane);
5102 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5103 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5104 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5105 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5106 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5107 gimple_omp_for_set_clauses (ctx->stmt, c);
5108 g = gimple_build_assign (lane, INTEGER_CST,
5109 build_int_cst (unsigned_type_node, 0));
5110 gimple_seq_add_stmt (ilist, g);
5111 for (int i = 0; i < 2; i++)
5112 if (llist[i])
5113 {
5114 tree vf = create_tmp_var (unsigned_type_node);
5115 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5116 gimple_call_set_lhs (g, vf);
5117 gimple_seq *seq = i == 0 ? ilist : dlist;
5118 gimple_seq_add_stmt (seq, g);
5119 tree t = build_int_cst (unsigned_type_node, 0);
5120 g = gimple_build_assign (idx, INTEGER_CST, t);
5121 gimple_seq_add_stmt (seq, g);
5122 tree body = create_artificial_label (UNKNOWN_LOCATION);
5123 tree header = create_artificial_label (UNKNOWN_LOCATION);
5124 tree end = create_artificial_label (UNKNOWN_LOCATION);
5125 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5126 gimple_seq_add_stmt (seq, gimple_build_label (body));
5127 gimple_seq_add_seq (seq, llist[i]);
5128 t = build_int_cst (unsigned_type_node, 1);
5129 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5130 gimple_seq_add_stmt (seq, g);
5131 gimple_seq_add_stmt (seq, gimple_build_label (header));
5132 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5133 gimple_seq_add_stmt (seq, g);
5134 gimple_seq_add_stmt (seq, gimple_build_label (end));
5135 }
5136 }
5137
5138 /* The copyin sequence is not to be executed by the main thread, since
5139 that would result in self-copies. Perhaps not visible to scalars,
5140 but it certainly is to C++ operator=. */
5141 if (copyin_seq)
5142 {
5143 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5144 0);
5145 x = build2 (NE_EXPR, boolean_type_node, x,
5146 build_int_cst (TREE_TYPE (x), 0));
5147 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5148 gimplify_and_add (x, ilist);
5149 }
5150
5151 /* If any copyin variable is passed by reference, we must ensure the
5152 master thread doesn't modify it before it is copied over in all
5153 threads. Similarly for variables in both firstprivate and
5154 lastprivate clauses we need to ensure the lastprivate copying
5155 happens after firstprivate copying in all threads. And similarly
5156 for UDRs if initializer expression refers to omp_orig. */
5157 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5158 {
5159 /* Don't add any barrier for #pragma omp simd or
5160 #pragma omp distribute. */
5161 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5162 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5163 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5164 }
5165
5166 /* If max_vf is non-zero, then we can use only a vectorization factor
5167 up to the max_vf we chose. So stick it into the safelen clause. */
5168 if (max_vf)
5169 {
5170 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5171 OMP_CLAUSE_SAFELEN);
5172 if (c == NULL_TREE
5173 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5174 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5175 max_vf) == 1))
5176 {
5177 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5178 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5179 max_vf);
5180 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5181 gimple_omp_for_set_clauses (ctx->stmt, c);
5182 }
5183 }
5184 }
5185
5186
5187 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5188 both parallel and workshare constructs. PREDICATE may be NULL if it's
5189 always true. */
5190
5191 static void
5192 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5193 omp_context *ctx)
5194 {
5195 tree x, c, label = NULL, orig_clauses = clauses;
5196 bool par_clauses = false;
5197 tree simduid = NULL, lastlane = NULL;
5198
5199 /* Early exit if there are no lastprivate or linear clauses. */
5200 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5201 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5202 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5203 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5204 break;
5205 if (clauses == NULL)
5206 {
5207 /* If this was a workshare clause, see if it had been combined
5208 with its parallel. In that case, look for the clauses on the
5209 parallel statement itself. */
5210 if (is_parallel_ctx (ctx))
5211 return;
5212
5213 ctx = ctx->outer;
5214 if (ctx == NULL || !is_parallel_ctx (ctx))
5215 return;
5216
5217 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5218 OMP_CLAUSE_LASTPRIVATE);
5219 if (clauses == NULL)
5220 return;
5221 par_clauses = true;
5222 }
5223
5224 if (predicate)
5225 {
5226 gcond *stmt;
5227 tree label_true, arm1, arm2;
5228
5229 label = create_artificial_label (UNKNOWN_LOCATION);
5230 label_true = create_artificial_label (UNKNOWN_LOCATION);
5231 arm1 = TREE_OPERAND (predicate, 0);
5232 arm2 = TREE_OPERAND (predicate, 1);
5233 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5234 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5235 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5236 label_true, label);
5237 gimple_seq_add_stmt (stmt_list, stmt);
5238 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5239 }
5240
5241 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5242 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5243 {
5244 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5245 if (simduid)
5246 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5247 }
5248
5249 for (c = clauses; c ;)
5250 {
5251 tree var, new_var;
5252 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5253
5254 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5255 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5256 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5257 {
5258 var = OMP_CLAUSE_DECL (c);
5259 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5260 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5261 && is_taskloop_ctx (ctx))
5262 {
5263 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5264 new_var = lookup_decl (var, ctx->outer);
5265 }
5266 else
5267 new_var = lookup_decl (var, ctx);
5268
5269 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5270 {
5271 tree val = DECL_VALUE_EXPR (new_var);
5272 if (TREE_CODE (val) == ARRAY_REF
5273 && VAR_P (TREE_OPERAND (val, 0))
5274 && lookup_attribute ("omp simd array",
5275 DECL_ATTRIBUTES (TREE_OPERAND (val,
5276 0))))
5277 {
5278 if (lastlane == NULL)
5279 {
5280 lastlane = create_tmp_var (unsigned_type_node);
5281 gcall *g
5282 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5283 2, simduid,
5284 TREE_OPERAND (val, 1));
5285 gimple_call_set_lhs (g, lastlane);
5286 gimple_seq_add_stmt (stmt_list, g);
5287 }
5288 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5289 TREE_OPERAND (val, 0), lastlane,
5290 NULL_TREE, NULL_TREE);
5291 }
5292 }
5293
5294 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5295 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5296 {
5297 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5298 gimple_seq_add_seq (stmt_list,
5299 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5300 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5301 }
5302 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5303 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5304 {
5305 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5306 gimple_seq_add_seq (stmt_list,
5307 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5308 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5309 }
5310
5311 x = NULL_TREE;
5312 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5313 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5314 {
5315 gcc_checking_assert (is_taskloop_ctx (ctx));
5316 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5317 ctx->outer->outer);
5318 if (is_global_var (ovar))
5319 x = ovar;
5320 }
5321 if (!x)
5322 x = build_outer_var_ref (var, ctx, true);
5323 if (is_reference (var))
5324 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5325 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5326 gimplify_and_add (x, stmt_list);
5327 }
5328 c = OMP_CLAUSE_CHAIN (c);
5329 if (c == NULL && !par_clauses)
5330 {
5331 /* If this was a workshare clause, see if it had been combined
5332 with its parallel. In that case, continue looking for the
5333 clauses also on the parallel statement itself. */
5334 if (is_parallel_ctx (ctx))
5335 break;
5336
5337 ctx = ctx->outer;
5338 if (ctx == NULL || !is_parallel_ctx (ctx))
5339 break;
5340
5341 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5342 OMP_CLAUSE_LASTPRIVATE);
5343 par_clauses = true;
5344 }
5345 }
5346
5347 if (label)
5348 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5349 }
5350
5351 static void
5352 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
5353 tree tid, tree var, tree new_var)
5354 {
5355 /* The atomic add at the end of the sum creates unnecessary
5356 write contention on accelerators. To work around this,
5357 create an array to store the partial reductions. Later, in
5358 lower_omp_for (for openacc), the values of array will be
5359 combined. */
5360
5361 tree t = NULL_TREE, array, x;
5362 tree type = get_base_type (var);
5363 gimple *stmt;
5364
5365 /* Now insert the partial reductions into the array. */
5366
5367 /* Find the reduction array. */
5368
5369 tree ptype = build_pointer_type (type);
5370
5371 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
5372 t = build_receiver_ref (t, false, ctx->outer);
5373
5374 array = create_tmp_var (ptype);
5375 gimplify_assign (array, t, stmt_seqp);
5376
5377 tree ptr = create_tmp_var (TREE_TYPE (array));
5378
5379 /* Find the reduction array. */
5380
5381 /* testing a unary conversion. */
5382 tree offset = create_tmp_var (sizetype);
5383 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
5384 stmt_seqp);
5385 t = create_tmp_var (sizetype);
5386 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
5387 stmt_seqp);
5388 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
5389 gimple_seq_add_stmt (stmt_seqp, stmt);
5390
5391 /* Offset expression. Does the POINTER_PLUS_EXPR take care
5392 of adding sizeof(var) to the array? */
5393 ptr = create_tmp_var (ptype);
5394 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
5395 offset);
5396 gimple_seq_add_stmt (stmt_seqp, stmt);
5397
5398 /* Move the local sum to gfc$sum[i]. */
5399 x = unshare_expr (build_simple_mem_ref (ptr));
5400 stmt = gimplify_assign (x, new_var, stmt_seqp);
5401 }
5402
5403 /* Generate code to implement the REDUCTION clauses. */
5404
5405 static void
5406 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5407 {
5408 gimple_seq sub_seq = NULL;
5409 gimple *stmt;
5410 tree x, c, tid = NULL_TREE;
5411 int count = 0;
5412
5413 /* SIMD reductions are handled in lower_rec_input_clauses. */
5414 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5415 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5416 return;
5417
5418 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5419 update in that case, otherwise use a lock. */
5420 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5421 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5422 {
5423 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5424 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5425 {
5426 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5427 count = -1;
5428 break;
5429 }
5430 count++;
5431 }
5432
5433 if (count == 0)
5434 return;
5435
5436 /* Initialize thread info for OpenACC. */
5437 if (is_gimple_omp_oacc (ctx->stmt))
5438 {
5439 /* Get the current thread id. */
5440 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
5441 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
5442 gimple *stmt = gimple_build_call (call, 0);
5443 gimple_call_set_lhs (stmt, tid);
5444 gimple_seq_add_stmt (stmt_seqp, stmt);
5445 }
5446
5447 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5448 {
5449 tree var, ref, new_var, orig_var;
5450 enum tree_code code;
5451 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5452
5453 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5454 continue;
5455
5456 orig_var = var = OMP_CLAUSE_DECL (c);
5457 if (TREE_CODE (var) == MEM_REF)
5458 {
5459 var = TREE_OPERAND (var, 0);
5460 if (TREE_CODE (var) == INDIRECT_REF
5461 || TREE_CODE (var) == ADDR_EXPR)
5462 var = TREE_OPERAND (var, 0);
5463 orig_var = var;
5464 if (is_variable_sized (var))
5465 {
5466 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5467 var = DECL_VALUE_EXPR (var);
5468 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5469 var = TREE_OPERAND (var, 0);
5470 gcc_assert (DECL_P (var));
5471 }
5472 }
5473 new_var = lookup_decl (var, ctx);
5474 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5475 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5476 ref = build_outer_var_ref (var, ctx);
5477 code = OMP_CLAUSE_REDUCTION_CODE (c);
5478
5479 /* reduction(-:var) sums up the partial results, so it acts
5480 identically to reduction(+:var). */
5481 if (code == MINUS_EXPR)
5482 code = PLUS_EXPR;
5483
5484 if (is_gimple_omp_oacc (ctx->stmt))
5485 {
5486 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
5487
5488 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
5489 }
5490 else if (count == 1)
5491 {
5492 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5493
5494 addr = save_expr (addr);
5495 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5496 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5497 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5498 gimplify_and_add (x, stmt_seqp);
5499 return;
5500 }
5501 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5502 {
5503 tree d = OMP_CLAUSE_DECL (c);
5504 tree type = TREE_TYPE (d);
5505 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5506 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5507 tree ptype = build_pointer_type (TREE_TYPE (type));
5508 /* For ref build_outer_var_ref already performs this, so
5509 only new_var needs a dereference. */
5510 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
5511 {
5512 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5513 gcc_assert (is_reference (var) && var == orig_var);
5514 }
5515 else if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
5516 {
5517 if (orig_var == var)
5518 {
5519 new_var = build_fold_addr_expr (new_var);
5520 ref = build_fold_addr_expr (ref);
5521 }
5522 }
5523 else
5524 {
5525 gcc_assert (orig_var == var);
5526 if (is_reference (var))
5527 ref = build_fold_addr_expr (ref);
5528 }
5529 if (DECL_P (v))
5530 {
5531 tree t = maybe_lookup_decl (v, ctx);
5532 if (t)
5533 v = t;
5534 else
5535 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5536 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5537 }
5538 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5539 ref = fold_convert_loc (clause_loc, ptype, ref);
5540 tree m = create_tmp_var (ptype, NULL);
5541 gimplify_assign (m, new_var, stmt_seqp);
5542 new_var = m;
5543 m = create_tmp_var (ptype, NULL);
5544 gimplify_assign (m, ref, stmt_seqp);
5545 ref = m;
5546 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5547 tree body = create_artificial_label (UNKNOWN_LOCATION);
5548 tree end = create_artificial_label (UNKNOWN_LOCATION);
5549 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5550 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5551 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5552 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5553 {
5554 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5555 tree decl_placeholder
5556 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5557 SET_DECL_VALUE_EXPR (placeholder, out);
5558 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5559 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5560 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5561 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5562 gimple_seq_add_seq (&sub_seq,
5563 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5564 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5565 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5566 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5567 }
5568 else
5569 {
5570 x = build2 (code, TREE_TYPE (out), out, priv);
5571 out = unshare_expr (out);
5572 gimplify_assign (out, x, &sub_seq);
5573 }
5574 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5575 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5576 gimple_seq_add_stmt (&sub_seq, g);
5577 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5578 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5579 gimple_seq_add_stmt (&sub_seq, g);
5580 g = gimple_build_assign (i, PLUS_EXPR, i,
5581 build_int_cst (TREE_TYPE (i), 1));
5582 gimple_seq_add_stmt (&sub_seq, g);
5583 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5584 gimple_seq_add_stmt (&sub_seq, g);
5585 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5586 }
5587 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5588 {
5589 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5590
5591 if (is_reference (var)
5592 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5593 TREE_TYPE (ref)))
5594 ref = build_fold_addr_expr_loc (clause_loc, ref);
5595 SET_DECL_VALUE_EXPR (placeholder, ref);
5596 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5597 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5598 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5599 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5600 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5601 }
5602 else
5603 {
5604 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5605 ref = build_outer_var_ref (var, ctx);
5606 gimplify_assign (ref, x, &sub_seq);
5607 }
5608 }
5609
5610 if (is_gimple_omp_oacc (ctx->stmt))
5611 return;
5612
5613 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5614 0);
5615 gimple_seq_add_stmt (stmt_seqp, stmt);
5616
5617 gimple_seq_add_seq (stmt_seqp, sub_seq);
5618
5619 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5620 0);
5621 gimple_seq_add_stmt (stmt_seqp, stmt);
5622 }
5623
5624
5625 /* Generate code to implement the COPYPRIVATE clauses. */
5626
5627 static void
5628 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5629 omp_context *ctx)
5630 {
5631 tree c;
5632
5633 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5634 {
5635 tree var, new_var, ref, x;
5636 bool by_ref;
5637 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5638
5639 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
5640 continue;
5641
5642 var = OMP_CLAUSE_DECL (c);
5643 by_ref = use_pointer_for_field (var, NULL);
5644
5645 ref = build_sender_ref (var, ctx);
5646 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5647 if (by_ref)
5648 {
5649 x = build_fold_addr_expr_loc (clause_loc, new_var);
5650 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5651 }
5652 gimplify_assign (ref, x, slist);
5653
5654 ref = build_receiver_ref (var, false, ctx);
5655 if (by_ref)
5656 {
5657 ref = fold_convert_loc (clause_loc,
5658 build_pointer_type (TREE_TYPE (new_var)),
5659 ref);
5660 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5661 }
5662 if (is_reference (var))
5663 {
5664 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
5665 ref = build_simple_mem_ref_loc (clause_loc, ref);
5666 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5667 }
5668 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
5669 gimplify_and_add (x, rlist);
5670 }
5671 }
5672
5673
5674 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5675 and REDUCTION from the sender (aka parent) side. */
5676
5677 static void
5678 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5679 omp_context *ctx)
5680 {
5681 tree c, t;
5682 int ignored_looptemp = 0;
5683 bool is_taskloop = false;
5684
5685 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5686 by GOMP_taskloop. */
5687 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5688 {
5689 ignored_looptemp = 2;
5690 is_taskloop = true;
5691 }
5692
5693 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5694 {
5695 tree val, ref, x, var;
5696 bool by_ref, do_in = false, do_out = false;
5697 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5698
5699 switch (OMP_CLAUSE_CODE (c))
5700 {
5701 case OMP_CLAUSE_PRIVATE:
5702 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5703 break;
5704 continue;
5705 case OMP_CLAUSE_FIRSTPRIVATE:
5706 case OMP_CLAUSE_COPYIN:
5707 case OMP_CLAUSE_LASTPRIVATE:
5708 case OMP_CLAUSE_REDUCTION:
5709 break;
5710 case OMP_CLAUSE_SHARED:
5711 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5712 break;
5713 continue;
5714 case OMP_CLAUSE__LOOPTEMP_:
5715 if (ignored_looptemp)
5716 {
5717 ignored_looptemp--;
5718 continue;
5719 }
5720 break;
5721 default:
5722 continue;
5723 }
5724
5725 val = OMP_CLAUSE_DECL (c);
5726 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5727 && TREE_CODE (val) == MEM_REF)
5728 {
5729 val = TREE_OPERAND (val, 0);
5730 if (TREE_CODE (val) == INDIRECT_REF
5731 || TREE_CODE (val) == ADDR_EXPR)
5732 val = TREE_OPERAND (val, 0);
5733 if (is_variable_sized (val))
5734 continue;
5735 }
5736
5737 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5738 outer taskloop region. */
5739 omp_context *ctx_for_o = ctx;
5740 if (is_taskloop
5741 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
5742 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5743 ctx_for_o = ctx->outer;
5744
5745 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
5746
5747 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
5748 && is_global_var (var))
5749 continue;
5750
5751 t = omp_member_access_dummy_var (var);
5752 if (t)
5753 {
5754 var = DECL_VALUE_EXPR (var);
5755 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
5756 if (o != t)
5757 var = unshare_and_remap (var, t, o);
5758 else
5759 var = unshare_expr (var);
5760 }
5761
5762 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
5763 {
5764 /* Handle taskloop firstprivate/lastprivate, where the
5765 lastprivate on GIMPLE_OMP_TASK is represented as
5766 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
5767 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
5768 x = omp_build_component_ref (ctx->sender_decl, f);
5769 if (use_pointer_for_field (val, ctx))
5770 var = build_fold_addr_expr (var);
5771 gimplify_assign (x, var, ilist);
5772 DECL_ABSTRACT_ORIGIN (f) = NULL;
5773 continue;
5774 }
5775
5776 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
5777 || val == OMP_CLAUSE_DECL (c))
5778 && is_variable_sized (val))
5779 continue;
5780 by_ref = use_pointer_for_field (val, NULL);
5781
5782 switch (OMP_CLAUSE_CODE (c))
5783 {
5784 case OMP_CLAUSE_PRIVATE:
5785 case OMP_CLAUSE_FIRSTPRIVATE:
5786 case OMP_CLAUSE_COPYIN:
5787 case OMP_CLAUSE__LOOPTEMP_:
5788 do_in = true;
5789 break;
5790
5791 case OMP_CLAUSE_LASTPRIVATE:
5792 if (by_ref || is_reference (val))
5793 {
5794 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5795 continue;
5796 do_in = true;
5797 }
5798 else
5799 {
5800 do_out = true;
5801 if (lang_hooks.decls.omp_private_outer_ref (val))
5802 do_in = true;
5803 }
5804 break;
5805
5806 case OMP_CLAUSE_REDUCTION:
5807 do_in = true;
5808 if (val == OMP_CLAUSE_DECL (c))
5809 do_out = !(by_ref || is_reference (val));
5810 else
5811 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
5812 break;
5813
5814 default:
5815 gcc_unreachable ();
5816 }
5817
5818 if (do_in)
5819 {
5820 ref = build_sender_ref (val, ctx);
5821 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
5822 gimplify_assign (ref, x, ilist);
5823 if (is_task_ctx (ctx))
5824 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
5825 }
5826
5827 if (do_out)
5828 {
5829 ref = build_sender_ref (val, ctx);
5830 gimplify_assign (var, ref, olist);
5831 }
5832 }
5833 }
5834
5835 /* Generate code to implement SHARED from the sender (aka parent)
5836 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
5837 list things that got automatically shared. */
5838
5839 static void
5840 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
5841 {
5842 tree var, ovar, nvar, t, f, x, record_type;
5843
5844 if (ctx->record_type == NULL)
5845 return;
5846
5847 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
5848 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
5849 {
5850 ovar = DECL_ABSTRACT_ORIGIN (f);
5851 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
5852 continue;
5853
5854 nvar = maybe_lookup_decl (ovar, ctx);
5855 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
5856 continue;
5857
5858 /* If CTX is a nested parallel directive. Find the immediately
5859 enclosing parallel or workshare construct that contains a
5860 mapping for OVAR. */
5861 var = lookup_decl_in_outer_ctx (ovar, ctx);
5862
5863 t = omp_member_access_dummy_var (var);
5864 if (t)
5865 {
5866 var = DECL_VALUE_EXPR (var);
5867 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
5868 if (o != t)
5869 var = unshare_and_remap (var, t, o);
5870 else
5871 var = unshare_expr (var);
5872 }
5873
5874 if (use_pointer_for_field (ovar, ctx))
5875 {
5876 x = build_sender_ref (ovar, ctx);
5877 var = build_fold_addr_expr (var);
5878 gimplify_assign (x, var, ilist);
5879 }
5880 else
5881 {
5882 x = build_sender_ref (ovar, ctx);
5883 gimplify_assign (x, var, ilist);
5884
5885 if (!TREE_READONLY (var)
5886 /* We don't need to receive a new reference to a result
5887 or parm decl. In fact we may not store to it as we will
5888 invalidate any pending RSO and generate wrong gimple
5889 during inlining. */
5890 && !((TREE_CODE (var) == RESULT_DECL
5891 || TREE_CODE (var) == PARM_DECL)
5892 && DECL_BY_REFERENCE (var)))
5893 {
5894 x = build_sender_ref (ovar, ctx);
5895 gimplify_assign (var, x, olist);
5896 }
5897 }
5898 }
5899 }
5900
5901 /* Emit an OpenACC head marker call, encapulating the partitioning and
5902 other information that must be processed by the target compiler.
5903 Return the maximum number of dimensions the associated loop might
5904 be partitioned over. */
5905
5906 static unsigned
5907 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
5908 gimple_seq *seq, omp_context *ctx)
5909 {
5910 unsigned levels = 0;
5911 unsigned tag = 0;
5912 tree gang_static = NULL_TREE;
5913 auto_vec<tree, 5> args;
5914
5915 args.quick_push (build_int_cst
5916 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
5917 args.quick_push (ddvar);
5918 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5919 {
5920 switch (OMP_CLAUSE_CODE (c))
5921 {
5922 case OMP_CLAUSE_GANG:
5923 tag |= OLF_DIM_GANG;
5924 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
5925 /* static:* is represented by -1, and we can ignore it, as
5926 scheduling is always static. */
5927 if (gang_static && integer_minus_onep (gang_static))
5928 gang_static = NULL_TREE;
5929 levels++;
5930 break;
5931
5932 case OMP_CLAUSE_WORKER:
5933 tag |= OLF_DIM_WORKER;
5934 levels++;
5935 break;
5936
5937 case OMP_CLAUSE_VECTOR:
5938 tag |= OLF_DIM_VECTOR;
5939 levels++;
5940 break;
5941
5942 case OMP_CLAUSE_SEQ:
5943 tag |= OLF_SEQ;
5944 break;
5945
5946 case OMP_CLAUSE_AUTO:
5947 tag |= OLF_AUTO;
5948 break;
5949
5950 case OMP_CLAUSE_INDEPENDENT:
5951 tag |= OLF_INDEPENDENT;
5952 break;
5953
5954 default:
5955 continue;
5956 }
5957 }
5958
5959 if (gang_static)
5960 {
5961 if (DECL_P (gang_static))
5962 gang_static = build_outer_var_ref (gang_static, ctx);
5963 tag |= OLF_GANG_STATIC;
5964 }
5965
5966 /* In a parallel region, loops are implicitly INDEPENDENT. */
5967 omp_context *tgt = enclosing_target_ctx (ctx);
5968 if (!tgt || is_oacc_parallel (tgt))
5969 tag |= OLF_INDEPENDENT;
5970
5971 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
5972 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
5973 | OLF_SEQ)))
5974 tag |= OLF_AUTO;
5975
5976 /* Ensure at least one level. */
5977 if (!levels)
5978 levels++;
5979
5980 args.quick_push (build_int_cst (integer_type_node, levels));
5981 args.quick_push (build_int_cst (integer_type_node, tag));
5982 if (gang_static)
5983 args.quick_push (gang_static);
5984
5985 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
5986 gimple_set_location (call, loc);
5987 gimple_set_lhs (call, ddvar);
5988 gimple_seq_add_stmt (seq, call);
5989
5990 return levels;
5991 }
5992
5993 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
5994 partitioning level of the enclosed region. */
5995
5996 static void
5997 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
5998 tree tofollow, gimple_seq *seq)
5999 {
6000 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6001 : IFN_UNIQUE_OACC_TAIL_MARK);
6002 tree marker = build_int_cst (integer_type_node, marker_kind);
6003 int nargs = 2 + (tofollow != NULL_TREE);
6004 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6005 marker, ddvar, tofollow);
6006 gimple_set_location (call, loc);
6007 gimple_set_lhs (call, ddvar);
6008 gimple_seq_add_stmt (seq, call);
6009 }
6010
6011 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6012 the loop clauses, from which we extract reductions. Initialize
6013 HEAD and TAIL. */
6014
6015 static void
6016 lower_oacc_head_tail (location_t loc, tree clauses,
6017 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6018 {
6019 bool inner = false;
6020 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6021 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6022
6023 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6024 if (!count)
6025 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6026
6027 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6028 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6029
6030 for (unsigned done = 1; count; count--, done++)
6031 {
6032 gimple_seq fork_seq = NULL;
6033 gimple_seq join_seq = NULL;
6034
6035 tree place = build_int_cst (integer_type_node, -1);
6036 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6037 fork_kind, ddvar, place);
6038 gimple_set_location (fork, loc);
6039 gimple_set_lhs (fork, ddvar);
6040
6041 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6042 join_kind, ddvar, place);
6043 gimple_set_location (join, loc);
6044 gimple_set_lhs (join, ddvar);
6045
6046 /* Mark the beginning of this level sequence. */
6047 if (inner)
6048 lower_oacc_loop_marker (loc, ddvar, true,
6049 build_int_cst (integer_type_node, count),
6050 &fork_seq);
6051 lower_oacc_loop_marker (loc, ddvar, false,
6052 build_int_cst (integer_type_node, done),
6053 &join_seq);
6054
6055 gimple_seq_add_stmt (&fork_seq, fork);
6056 gimple_seq_add_stmt (&join_seq, join);
6057
6058 /* Append this level to head. */
6059 gimple_seq_add_seq (head, fork_seq);
6060 /* Prepend it to tail. */
6061 gimple_seq_add_seq (&join_seq, *tail);
6062 *tail = join_seq;
6063
6064 inner = true;
6065 }
6066
6067 /* Mark the end of the sequence. */
6068 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6069 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6070 }
6071
6072 /* A convenience function to build an empty GIMPLE_COND with just the
6073 condition. */
6074
6075 static gcond *
6076 gimple_build_cond_empty (tree cond)
6077 {
6078 enum tree_code pred_code;
6079 tree lhs, rhs;
6080
6081 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6082 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6083 }
6084
6085 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6086 bool = false);
6087
6088 /* Build the function calls to GOMP_parallel_start etc to actually
6089 generate the parallel operation. REGION is the parallel region
6090 being expanded. BB is the block where to insert the code. WS_ARGS
6091 will be set if this is a call to a combined parallel+workshare
6092 construct, it contains the list of additional arguments needed by
6093 the workshare construct. */
6094
6095 static void
6096 expand_parallel_call (struct omp_region *region, basic_block bb,
6097 gomp_parallel *entry_stmt,
6098 vec<tree, va_gc> *ws_args)
6099 {
6100 tree t, t1, t2, val, cond, c, clauses, flags;
6101 gimple_stmt_iterator gsi;
6102 gimple *stmt;
6103 enum built_in_function start_ix;
6104 int start_ix2;
6105 location_t clause_loc;
6106 vec<tree, va_gc> *args;
6107
6108 clauses = gimple_omp_parallel_clauses (entry_stmt);
6109
6110 /* Determine what flavor of GOMP_parallel we will be
6111 emitting. */
6112 start_ix = BUILT_IN_GOMP_PARALLEL;
6113 if (is_combined_parallel (region))
6114 {
6115 switch (region->inner->type)
6116 {
6117 case GIMPLE_OMP_FOR:
6118 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6119 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
6120 + (region->inner->sched_kind
6121 == OMP_CLAUSE_SCHEDULE_RUNTIME
6122 ? 3 : region->inner->sched_kind));
6123 start_ix = (enum built_in_function)start_ix2;
6124 break;
6125 case GIMPLE_OMP_SECTIONS:
6126 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6127 break;
6128 default:
6129 gcc_unreachable ();
6130 }
6131 }
6132
6133 /* By default, the value of NUM_THREADS is zero (selected at run time)
6134 and there is no conditional. */
6135 cond = NULL_TREE;
6136 val = build_int_cst (unsigned_type_node, 0);
6137 flags = build_int_cst (unsigned_type_node, 0);
6138
6139 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6140 if (c)
6141 cond = OMP_CLAUSE_IF_EXPR (c);
6142
6143 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6144 if (c)
6145 {
6146 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6147 clause_loc = OMP_CLAUSE_LOCATION (c);
6148 }
6149 else
6150 clause_loc = gimple_location (entry_stmt);
6151
6152 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6153 if (c)
6154 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6155
6156 /* Ensure 'val' is of the correct type. */
6157 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6158
6159 /* If we found the clause 'if (cond)', build either
6160 (cond != 0) or (cond ? val : 1u). */
6161 if (cond)
6162 {
6163 cond = gimple_boolify (cond);
6164
6165 if (integer_zerop (val))
6166 val = fold_build2_loc (clause_loc,
6167 EQ_EXPR, unsigned_type_node, cond,
6168 build_int_cst (TREE_TYPE (cond), 0));
6169 else
6170 {
6171 basic_block cond_bb, then_bb, else_bb;
6172 edge e, e_then, e_else;
6173 tree tmp_then, tmp_else, tmp_join, tmp_var;
6174
6175 tmp_var = create_tmp_var (TREE_TYPE (val));
6176 if (gimple_in_ssa_p (cfun))
6177 {
6178 tmp_then = make_ssa_name (tmp_var);
6179 tmp_else = make_ssa_name (tmp_var);
6180 tmp_join = make_ssa_name (tmp_var);
6181 }
6182 else
6183 {
6184 tmp_then = tmp_var;
6185 tmp_else = tmp_var;
6186 tmp_join = tmp_var;
6187 }
6188
6189 e = split_block_after_labels (bb);
6190 cond_bb = e->src;
6191 bb = e->dest;
6192 remove_edge (e);
6193
6194 then_bb = create_empty_bb (cond_bb);
6195 else_bb = create_empty_bb (then_bb);
6196 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6197 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6198
6199 stmt = gimple_build_cond_empty (cond);
6200 gsi = gsi_start_bb (cond_bb);
6201 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6202
6203 gsi = gsi_start_bb (then_bb);
6204 expand_omp_build_assign (&gsi, tmp_then, val, true);
6205
6206 gsi = gsi_start_bb (else_bb);
6207 expand_omp_build_assign (&gsi, tmp_else,
6208 build_int_cst (unsigned_type_node, 1),
6209 true);
6210
6211 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6212 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6213 add_bb_to_loop (then_bb, cond_bb->loop_father);
6214 add_bb_to_loop (else_bb, cond_bb->loop_father);
6215 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6216 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6217
6218 if (gimple_in_ssa_p (cfun))
6219 {
6220 gphi *phi = create_phi_node (tmp_join, bb);
6221 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6222 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6223 }
6224
6225 val = tmp_join;
6226 }
6227
6228 gsi = gsi_start_bb (bb);
6229 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6230 false, GSI_CONTINUE_LINKING);
6231 }
6232
6233 gsi = gsi_last_bb (bb);
6234 t = gimple_omp_parallel_data_arg (entry_stmt);
6235 if (t == NULL)
6236 t1 = null_pointer_node;
6237 else
6238 t1 = build_fold_addr_expr (t);
6239 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6240
6241 vec_alloc (args, 4 + vec_safe_length (ws_args));
6242 args->quick_push (t2);
6243 args->quick_push (t1);
6244 args->quick_push (val);
6245 if (ws_args)
6246 args->splice (*ws_args);
6247 args->quick_push (flags);
6248
6249 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6250 builtin_decl_explicit (start_ix), args);
6251
6252 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6253 false, GSI_CONTINUE_LINKING);
6254 }
6255
6256 /* Insert a function call whose name is FUNC_NAME with the information from
6257 ENTRY_STMT into the basic_block BB. */
6258
6259 static void
6260 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6261 vec <tree, va_gc> *ws_args)
6262 {
6263 tree t, t1, t2;
6264 gimple_stmt_iterator gsi;
6265 vec <tree, va_gc> *args;
6266
6267 gcc_assert (vec_safe_length (ws_args) == 2);
6268 tree func_name = (*ws_args)[0];
6269 tree grain = (*ws_args)[1];
6270
6271 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6272 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6273 gcc_assert (count != NULL_TREE);
6274 count = OMP_CLAUSE_OPERAND (count, 0);
6275
6276 gsi = gsi_last_bb (bb);
6277 t = gimple_omp_parallel_data_arg (entry_stmt);
6278 if (t == NULL)
6279 t1 = null_pointer_node;
6280 else
6281 t1 = build_fold_addr_expr (t);
6282 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6283
6284 vec_alloc (args, 4);
6285 args->quick_push (t2);
6286 args->quick_push (t1);
6287 args->quick_push (count);
6288 args->quick_push (grain);
6289 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6290
6291 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6292 GSI_CONTINUE_LINKING);
6293 }
6294
6295 /* Build the function call to GOMP_task to actually
6296 generate the task operation. BB is the block where to insert the code. */
6297
6298 static void
6299 expand_task_call (struct omp_region *region, basic_block bb,
6300 gomp_task *entry_stmt)
6301 {
6302 tree t1, t2, t3;
6303 gimple_stmt_iterator gsi;
6304 location_t loc = gimple_location (entry_stmt);
6305
6306 tree clauses = gimple_omp_task_clauses (entry_stmt);
6307
6308 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6309 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6310 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6311 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6312 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6313 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6314
6315 unsigned int iflags
6316 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6317 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6318 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6319
6320 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6321 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6322 tree num_tasks = NULL_TREE;
6323 bool ull = false;
6324 if (taskloop_p)
6325 {
6326 gimple *g = last_stmt (region->outer->entry);
6327 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6328 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6329 struct omp_for_data fd;
6330 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6331 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6332 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6333 OMP_CLAUSE__LOOPTEMP_);
6334 startvar = OMP_CLAUSE_DECL (startvar);
6335 endvar = OMP_CLAUSE_DECL (endvar);
6336 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6337 if (fd.loop.cond_code == LT_EXPR)
6338 iflags |= GOMP_TASK_FLAG_UP;
6339 tree tclauses = gimple_omp_for_clauses (g);
6340 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6341 if (num_tasks)
6342 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6343 else
6344 {
6345 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6346 if (num_tasks)
6347 {
6348 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6349 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6350 }
6351 else
6352 num_tasks = integer_zero_node;
6353 }
6354 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6355 if (ifc == NULL_TREE)
6356 iflags |= GOMP_TASK_FLAG_IF;
6357 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6358 iflags |= GOMP_TASK_FLAG_NOGROUP;
6359 ull = fd.iter_type == long_long_unsigned_type_node;
6360 }
6361 else if (priority)
6362 iflags |= GOMP_TASK_FLAG_PRIORITY;
6363
6364 tree flags = build_int_cst (unsigned_type_node, iflags);
6365
6366 tree cond = boolean_true_node;
6367 if (ifc)
6368 {
6369 if (taskloop_p)
6370 {
6371 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6372 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6373 build_int_cst (unsigned_type_node,
6374 GOMP_TASK_FLAG_IF),
6375 build_int_cst (unsigned_type_node, 0));
6376 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6377 flags, t);
6378 }
6379 else
6380 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6381 }
6382
6383 if (finalc)
6384 {
6385 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6386 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6387 build_int_cst (unsigned_type_node,
6388 GOMP_TASK_FLAG_FINAL),
6389 build_int_cst (unsigned_type_node, 0));
6390 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6391 }
6392 if (depend)
6393 depend = OMP_CLAUSE_DECL (depend);
6394 else
6395 depend = build_int_cst (ptr_type_node, 0);
6396 if (priority)
6397 priority = fold_convert (integer_type_node,
6398 OMP_CLAUSE_PRIORITY_EXPR (priority));
6399 else
6400 priority = integer_zero_node;
6401
6402 gsi = gsi_last_bb (bb);
6403 tree t = gimple_omp_task_data_arg (entry_stmt);
6404 if (t == NULL)
6405 t2 = null_pointer_node;
6406 else
6407 t2 = build_fold_addr_expr_loc (loc, t);
6408 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6409 t = gimple_omp_task_copy_fn (entry_stmt);
6410 if (t == NULL)
6411 t3 = null_pointer_node;
6412 else
6413 t3 = build_fold_addr_expr_loc (loc, t);
6414
6415 if (taskloop_p)
6416 t = build_call_expr (ull
6417 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6418 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6419 11, t1, t2, t3,
6420 gimple_omp_task_arg_size (entry_stmt),
6421 gimple_omp_task_arg_align (entry_stmt), flags,
6422 num_tasks, priority, startvar, endvar, step);
6423 else
6424 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6425 9, t1, t2, t3,
6426 gimple_omp_task_arg_size (entry_stmt),
6427 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6428 depend, priority);
6429
6430 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6431 false, GSI_CONTINUE_LINKING);
6432 }
6433
6434
6435 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6436 catch handler and return it. This prevents programs from violating the
6437 structured block semantics with throws. */
6438
6439 static gimple_seq
6440 maybe_catch_exception (gimple_seq body)
6441 {
6442 gimple *g;
6443 tree decl;
6444
6445 if (!flag_exceptions)
6446 return body;
6447
6448 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6449 decl = lang_hooks.eh_protect_cleanup_actions ();
6450 else
6451 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6452
6453 g = gimple_build_eh_must_not_throw (decl);
6454 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6455 GIMPLE_TRY_CATCH);
6456
6457 return gimple_seq_alloc_with_stmt (g);
6458 }
6459
6460 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6461
6462 static tree
6463 vec2chain (vec<tree, va_gc> *v)
6464 {
6465 tree chain = NULL_TREE, t;
6466 unsigned ix;
6467
6468 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6469 {
6470 DECL_CHAIN (t) = chain;
6471 chain = t;
6472 }
6473
6474 return chain;
6475 }
6476
6477
6478 /* Remove barriers in REGION->EXIT's block. Note that this is only
6479 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6480 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6481 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6482 removed. */
6483
6484 static void
6485 remove_exit_barrier (struct omp_region *region)
6486 {
6487 gimple_stmt_iterator gsi;
6488 basic_block exit_bb;
6489 edge_iterator ei;
6490 edge e;
6491 gimple *stmt;
6492 int any_addressable_vars = -1;
6493
6494 exit_bb = region->exit;
6495
6496 /* If the parallel region doesn't return, we don't have REGION->EXIT
6497 block at all. */
6498 if (! exit_bb)
6499 return;
6500
6501 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6502 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6503 statements that can appear in between are extremely limited -- no
6504 memory operations at all. Here, we allow nothing at all, so the
6505 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6506 gsi = gsi_last_bb (exit_bb);
6507 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6508 gsi_prev (&gsi);
6509 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6510 return;
6511
6512 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6513 {
6514 gsi = gsi_last_bb (e->src);
6515 if (gsi_end_p (gsi))
6516 continue;
6517 stmt = gsi_stmt (gsi);
6518 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6519 && !gimple_omp_return_nowait_p (stmt))
6520 {
6521 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6522 in many cases. If there could be tasks queued, the barrier
6523 might be needed to let the tasks run before some local
6524 variable of the parallel that the task uses as shared
6525 runs out of scope. The task can be spawned either
6526 from within current function (this would be easy to check)
6527 or from some function it calls and gets passed an address
6528 of such a variable. */
6529 if (any_addressable_vars < 0)
6530 {
6531 gomp_parallel *parallel_stmt
6532 = as_a <gomp_parallel *> (last_stmt (region->entry));
6533 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6534 tree local_decls, block, decl;
6535 unsigned ix;
6536
6537 any_addressable_vars = 0;
6538 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6539 if (TREE_ADDRESSABLE (decl))
6540 {
6541 any_addressable_vars = 1;
6542 break;
6543 }
6544 for (block = gimple_block (stmt);
6545 !any_addressable_vars
6546 && block
6547 && TREE_CODE (block) == BLOCK;
6548 block = BLOCK_SUPERCONTEXT (block))
6549 {
6550 for (local_decls = BLOCK_VARS (block);
6551 local_decls;
6552 local_decls = DECL_CHAIN (local_decls))
6553 if (TREE_ADDRESSABLE (local_decls))
6554 {
6555 any_addressable_vars = 1;
6556 break;
6557 }
6558 if (block == gimple_block (parallel_stmt))
6559 break;
6560 }
6561 }
6562 if (!any_addressable_vars)
6563 gimple_omp_return_set_nowait (stmt);
6564 }
6565 }
6566 }
6567
6568 static void
6569 remove_exit_barriers (struct omp_region *region)
6570 {
6571 if (region->type == GIMPLE_OMP_PARALLEL)
6572 remove_exit_barrier (region);
6573
6574 if (region->inner)
6575 {
6576 region = region->inner;
6577 remove_exit_barriers (region);
6578 while (region->next)
6579 {
6580 region = region->next;
6581 remove_exit_barriers (region);
6582 }
6583 }
6584 }
6585
6586 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6587 calls. These can't be declared as const functions, but
6588 within one parallel body they are constant, so they can be
6589 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6590 which are declared const. Similarly for task body, except
6591 that in untied task omp_get_thread_num () can change at any task
6592 scheduling point. */
6593
6594 static void
6595 optimize_omp_library_calls (gimple *entry_stmt)
6596 {
6597 basic_block bb;
6598 gimple_stmt_iterator gsi;
6599 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6600 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6601 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6602 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
6603 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6604 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
6605 OMP_CLAUSE_UNTIED) != NULL);
6606
6607 FOR_EACH_BB_FN (bb, cfun)
6608 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6609 {
6610 gimple *call = gsi_stmt (gsi);
6611 tree decl;
6612
6613 if (is_gimple_call (call)
6614 && (decl = gimple_call_fndecl (call))
6615 && DECL_EXTERNAL (decl)
6616 && TREE_PUBLIC (decl)
6617 && DECL_INITIAL (decl) == NULL)
6618 {
6619 tree built_in;
6620
6621 if (DECL_NAME (decl) == thr_num_id)
6622 {
6623 /* In #pragma omp task untied omp_get_thread_num () can change
6624 during the execution of the task region. */
6625 if (untied_task)
6626 continue;
6627 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6628 }
6629 else if (DECL_NAME (decl) == num_thr_id)
6630 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6631 else
6632 continue;
6633
6634 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
6635 || gimple_call_num_args (call) != 0)
6636 continue;
6637
6638 if (flag_exceptions && !TREE_NOTHROW (decl))
6639 continue;
6640
6641 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
6642 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6643 TREE_TYPE (TREE_TYPE (built_in))))
6644 continue;
6645
6646 gimple_call_set_fndecl (call, built_in);
6647 }
6648 }
6649 }
6650
6651 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6652 regimplified. */
6653
6654 static tree
6655 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6656 {
6657 tree t = *tp;
6658
6659 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6660 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6661 return t;
6662
6663 if (TREE_CODE (t) == ADDR_EXPR)
6664 recompute_tree_invariant_for_addr_expr (t);
6665
6666 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6667 return NULL_TREE;
6668 }
6669
6670 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
6671
6672 static void
6673 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6674 bool after)
6675 {
6676 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6677 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
6678 !after, after ? GSI_CONTINUE_LINKING
6679 : GSI_SAME_STMT);
6680 gimple *stmt = gimple_build_assign (to, from);
6681 if (after)
6682 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6683 else
6684 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
6685 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6686 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6687 {
6688 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6689 gimple_regimplify_operands (stmt, &gsi);
6690 }
6691 }
6692
6693 /* Expand the OpenMP parallel or task directive starting at REGION. */
6694
6695 static void
6696 expand_omp_taskreg (struct omp_region *region)
6697 {
6698 basic_block entry_bb, exit_bb, new_bb;
6699 struct function *child_cfun;
6700 tree child_fn, block, t;
6701 gimple_stmt_iterator gsi;
6702 gimple *entry_stmt, *stmt;
6703 edge e;
6704 vec<tree, va_gc> *ws_args;
6705
6706 entry_stmt = last_stmt (region->entry);
6707 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
6708 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6709
6710 entry_bb = region->entry;
6711 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6712 exit_bb = region->cont;
6713 else
6714 exit_bb = region->exit;
6715
6716 bool is_cilk_for
6717 = (flag_cilkplus
6718 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6719 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6720 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6721
6722 if (is_cilk_for)
6723 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
6724 and the inner statement contains the name of the built-in function
6725 and grain. */
6726 ws_args = region->inner->ws_args;
6727 else if (is_combined_parallel (region))
6728 ws_args = region->ws_args;
6729 else
6730 ws_args = NULL;
6731
6732 if (child_cfun->cfg)
6733 {
6734 /* Due to inlining, it may happen that we have already outlined
6735 the region, in which case all we need to do is make the
6736 sub-graph unreachable and emit the parallel call. */
6737 edge entry_succ_e, exit_succ_e;
6738
6739 entry_succ_e = single_succ_edge (entry_bb);
6740
6741 gsi = gsi_last_bb (entry_bb);
6742 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
6743 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
6744 gsi_remove (&gsi, true);
6745
6746 new_bb = entry_bb;
6747 if (exit_bb)
6748 {
6749 exit_succ_e = single_succ_edge (exit_bb);
6750 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
6751 }
6752 remove_edge_and_dominated_blocks (entry_succ_e);
6753 }
6754 else
6755 {
6756 unsigned srcidx, dstidx, num;
6757
6758 /* If the parallel region needs data sent from the parent
6759 function, then the very first statement (except possible
6760 tree profile counter updates) of the parallel body
6761 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
6762 &.OMP_DATA_O is passed as an argument to the child function,
6763 we need to replace it with the argument as seen by the child
6764 function.
6765
6766 In most cases, this will end up being the identity assignment
6767 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
6768 a function call that has been inlined, the original PARM_DECL
6769 .OMP_DATA_I may have been converted into a different local
6770 variable. In which case, we need to keep the assignment. */
6771 if (gimple_omp_taskreg_data_arg (entry_stmt))
6772 {
6773 basic_block entry_succ_bb
6774 = single_succ_p (entry_bb) ? single_succ (entry_bb)
6775 : FALLTHRU_EDGE (entry_bb)->dest;
6776 tree arg;
6777 gimple *parcopy_stmt = NULL;
6778
6779 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
6780 {
6781 gimple *stmt;
6782
6783 gcc_assert (!gsi_end_p (gsi));
6784 stmt = gsi_stmt (gsi);
6785 if (gimple_code (stmt) != GIMPLE_ASSIGN)
6786 continue;
6787
6788 if (gimple_num_ops (stmt) == 2)
6789 {
6790 tree arg = gimple_assign_rhs1 (stmt);
6791
6792 /* We're ignore the subcode because we're
6793 effectively doing a STRIP_NOPS. */
6794
6795 if (TREE_CODE (arg) == ADDR_EXPR
6796 && TREE_OPERAND (arg, 0)
6797 == gimple_omp_taskreg_data_arg (entry_stmt))
6798 {
6799 parcopy_stmt = stmt;
6800 break;
6801 }
6802 }
6803 }
6804
6805 gcc_assert (parcopy_stmt != NULL);
6806 arg = DECL_ARGUMENTS (child_fn);
6807
6808 if (!gimple_in_ssa_p (cfun))
6809 {
6810 if (gimple_assign_lhs (parcopy_stmt) == arg)
6811 gsi_remove (&gsi, true);
6812 else
6813 {
6814 /* ?? Is setting the subcode really necessary ?? */
6815 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
6816 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6817 }
6818 }
6819 else
6820 {
6821 tree lhs = gimple_assign_lhs (parcopy_stmt);
6822 gcc_assert (SSA_NAME_VAR (lhs) == arg);
6823 /* We'd like to set the rhs to the default def in the child_fn,
6824 but it's too early to create ssa names in the child_fn.
6825 Instead, we set the rhs to the parm. In
6826 move_sese_region_to_fn, we introduce a default def for the
6827 parm, map the parm to it's default def, and once we encounter
6828 this stmt, replace the parm with the default def. */
6829 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6830 update_stmt (parcopy_stmt);
6831 }
6832 }
6833
6834 /* Declare local variables needed in CHILD_CFUN. */
6835 block = DECL_INITIAL (child_fn);
6836 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
6837 /* The gimplifier could record temporaries in parallel/task block
6838 rather than in containing function's local_decls chain,
6839 which would mean cgraph missed finalizing them. Do it now. */
6840 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
6841 if (TREE_CODE (t) == VAR_DECL
6842 && TREE_STATIC (t)
6843 && !DECL_EXTERNAL (t))
6844 varpool_node::finalize_decl (t);
6845 DECL_SAVED_TREE (child_fn) = NULL;
6846 /* We'll create a CFG for child_fn, so no gimple body is needed. */
6847 gimple_set_body (child_fn, NULL);
6848 TREE_USED (block) = 1;
6849
6850 /* Reset DECL_CONTEXT on function arguments. */
6851 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
6852 DECL_CONTEXT (t) = child_fn;
6853
6854 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
6855 so that it can be moved to the child function. */
6856 gsi = gsi_last_bb (entry_bb);
6857 stmt = gsi_stmt (gsi);
6858 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6859 || gimple_code (stmt) == GIMPLE_OMP_TASK));
6860 e = split_block (entry_bb, stmt);
6861 gsi_remove (&gsi, true);
6862 entry_bb = e->dest;
6863 edge e2 = NULL;
6864 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
6865 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6866 else
6867 {
6868 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
6869 gcc_assert (e2->dest == region->exit);
6870 remove_edge (BRANCH_EDGE (entry_bb));
6871 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
6872 gsi = gsi_last_bb (region->exit);
6873 gcc_assert (!gsi_end_p (gsi)
6874 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6875 gsi_remove (&gsi, true);
6876 }
6877
6878 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
6879 if (exit_bb)
6880 {
6881 gsi = gsi_last_bb (exit_bb);
6882 gcc_assert (!gsi_end_p (gsi)
6883 && (gimple_code (gsi_stmt (gsi))
6884 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
6885 stmt = gimple_build_return (NULL);
6886 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
6887 gsi_remove (&gsi, true);
6888 }
6889
6890 /* Move the parallel region into CHILD_CFUN. */
6891
6892 if (gimple_in_ssa_p (cfun))
6893 {
6894 init_tree_ssa (child_cfun);
6895 init_ssa_operands (child_cfun);
6896 child_cfun->gimple_df->in_ssa_p = true;
6897 block = NULL_TREE;
6898 }
6899 else
6900 block = gimple_block (entry_stmt);
6901
6902 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
6903 if (exit_bb)
6904 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
6905 if (e2)
6906 {
6907 basic_block dest_bb = e2->dest;
6908 if (!exit_bb)
6909 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
6910 remove_edge (e2);
6911 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
6912 }
6913 /* When the OMP expansion process cannot guarantee an up-to-date
6914 loop tree arrange for the child function to fixup loops. */
6915 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
6916 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
6917
6918 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
6919 num = vec_safe_length (child_cfun->local_decls);
6920 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
6921 {
6922 t = (*child_cfun->local_decls)[srcidx];
6923 if (DECL_CONTEXT (t) == cfun->decl)
6924 continue;
6925 if (srcidx != dstidx)
6926 (*child_cfun->local_decls)[dstidx] = t;
6927 dstidx++;
6928 }
6929 if (dstidx != num)
6930 vec_safe_truncate (child_cfun->local_decls, dstidx);
6931
6932 /* Inform the callgraph about the new function. */
6933 child_cfun->curr_properties = cfun->curr_properties;
6934 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
6935 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6936 cgraph_node *node = cgraph_node::get_create (child_fn);
6937 node->parallelized_function = 1;
6938 cgraph_node::add_new_function (child_fn, true);
6939
6940 /* Fix the callgraph edges for child_cfun. Those for cfun will be
6941 fixed in a following pass. */
6942 push_cfun (child_cfun);
6943 if (optimize)
6944 optimize_omp_library_calls (entry_stmt);
6945 cgraph_edge::rebuild_edges ();
6946
6947 /* Some EH regions might become dead, see PR34608. If
6948 pass_cleanup_cfg isn't the first pass to happen with the
6949 new child, these dead EH edges might cause problems.
6950 Clean them up now. */
6951 if (flag_exceptions)
6952 {
6953 basic_block bb;
6954 bool changed = false;
6955
6956 FOR_EACH_BB_FN (bb, cfun)
6957 changed |= gimple_purge_dead_eh_edges (bb);
6958 if (changed)
6959 cleanup_tree_cfg ();
6960 }
6961 if (gimple_in_ssa_p (cfun))
6962 update_ssa (TODO_update_ssa);
6963 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
6964 verify_loop_structure ();
6965 pop_cfun ();
6966 }
6967
6968 /* Emit a library call to launch the children threads. */
6969 if (is_cilk_for)
6970 expand_cilk_for_call (new_bb,
6971 as_a <gomp_parallel *> (entry_stmt), ws_args);
6972 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
6973 expand_parallel_call (region, new_bb,
6974 as_a <gomp_parallel *> (entry_stmt), ws_args);
6975 else
6976 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
6977 if (gimple_in_ssa_p (cfun))
6978 update_ssa (TODO_update_ssa_only_virtuals);
6979 }
6980
6981 /* Information about members of an OpenACC collapsed loop nest. */
6982
6983 struct oacc_collapse
6984 {
6985 tree base; /* Base value. */
6986 tree iters; /* Number of steps. */
6987 tree step; /* step size. */
6988 };
6989
6990 /* Helper for expand_oacc_for. Determine collapsed loop information.
6991 Fill in COUNTS array. Emit any initialization code before GSI.
6992 Return the calculated outer loop bound of BOUND_TYPE. */
6993
6994 static tree
6995 expand_oacc_collapse_init (const struct omp_for_data *fd,
6996 gimple_stmt_iterator *gsi,
6997 oacc_collapse *counts, tree bound_type)
6998 {
6999 tree total = build_int_cst (bound_type, 1);
7000 int ix;
7001
7002 gcc_assert (integer_onep (fd->loop.step));
7003 gcc_assert (integer_zerop (fd->loop.n1));
7004
7005 for (ix = 0; ix != fd->collapse; ix++)
7006 {
7007 const omp_for_data_loop *loop = &fd->loops[ix];
7008
7009 tree iter_type = TREE_TYPE (loop->v);
7010 tree diff_type = iter_type;
7011 tree plus_type = iter_type;
7012
7013 gcc_assert (loop->cond_code == fd->loop.cond_code);
7014
7015 if (POINTER_TYPE_P (iter_type))
7016 plus_type = sizetype;
7017 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7018 diff_type = signed_type_for (diff_type);
7019
7020 tree b = loop->n1;
7021 tree e = loop->n2;
7022 tree s = loop->step;
7023 bool up = loop->cond_code == LT_EXPR;
7024 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7025 bool negating;
7026 tree expr;
7027
7028 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7029 true, GSI_SAME_STMT);
7030 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7031 true, GSI_SAME_STMT);
7032
7033 /* Convert the step, avoiding possible unsigned->signed overflow. */
7034 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7035 if (negating)
7036 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7037 s = fold_convert (diff_type, s);
7038 if (negating)
7039 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7040 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7041 true, GSI_SAME_STMT);
7042
7043 /* Determine the range, avoiding possible unsigned->signed overflow. */
7044 negating = !up && TYPE_UNSIGNED (iter_type);
7045 expr = fold_build2 (MINUS_EXPR, plus_type,
7046 fold_convert (plus_type, negating ? b : e),
7047 fold_convert (plus_type, negating ? e : b));
7048 expr = fold_convert (diff_type, expr);
7049 if (negating)
7050 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7051 tree range = force_gimple_operand_gsi
7052 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7053
7054 /* Determine number of iterations. */
7055 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7056 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7057 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7058
7059 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7060 true, GSI_SAME_STMT);
7061
7062 counts[ix].base = b;
7063 counts[ix].iters = iters;
7064 counts[ix].step = s;
7065
7066 total = fold_build2 (MULT_EXPR, bound_type, total,
7067 fold_convert (bound_type, iters));
7068 }
7069
7070 return total;
7071 }
7072
7073 /* Emit initializers for collapsed loop members. IVAR is the outer
7074 loop iteration variable, from which collapsed loop iteration values
7075 are calculated. COUNTS array has been initialized by
7076 expand_oacc_collapse_inits. */
7077
7078 static void
7079 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7080 gimple_stmt_iterator *gsi,
7081 const oacc_collapse *counts, tree ivar)
7082 {
7083 tree ivar_type = TREE_TYPE (ivar);
7084
7085 /* The most rapidly changing iteration variable is the innermost
7086 one. */
7087 for (int ix = fd->collapse; ix--;)
7088 {
7089 const omp_for_data_loop *loop = &fd->loops[ix];
7090 const oacc_collapse *collapse = &counts[ix];
7091 tree iter_type = TREE_TYPE (loop->v);
7092 tree diff_type = TREE_TYPE (collapse->step);
7093 tree plus_type = iter_type;
7094 enum tree_code plus_code = PLUS_EXPR;
7095 tree expr;
7096
7097 if (POINTER_TYPE_P (iter_type))
7098 {
7099 plus_code = POINTER_PLUS_EXPR;
7100 plus_type = sizetype;
7101 }
7102
7103 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7104 fold_convert (ivar_type, collapse->iters));
7105 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7106 collapse->step);
7107 expr = fold_build2 (plus_code, iter_type, collapse->base,
7108 fold_convert (plus_type, expr));
7109 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7110 true, GSI_SAME_STMT);
7111 gassign *ass = gimple_build_assign (loop->v, expr);
7112 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7113
7114 if (ix)
7115 {
7116 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7117 fold_convert (ivar_type, collapse->iters));
7118 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7119 true, GSI_SAME_STMT);
7120 }
7121 }
7122 }
7123
7124
7125 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7126 of the combined collapse > 1 loop constructs, generate code like:
7127 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7128 if (cond3 is <)
7129 adj = STEP3 - 1;
7130 else
7131 adj = STEP3 + 1;
7132 count3 = (adj + N32 - N31) / STEP3;
7133 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7134 if (cond2 is <)
7135 adj = STEP2 - 1;
7136 else
7137 adj = STEP2 + 1;
7138 count2 = (adj + N22 - N21) / STEP2;
7139 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7140 if (cond1 is <)
7141 adj = STEP1 - 1;
7142 else
7143 adj = STEP1 + 1;
7144 count1 = (adj + N12 - N11) / STEP1;
7145 count = count1 * count2 * count3;
7146 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7147 count = 0;
7148 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7149 of the combined loop constructs, just initialize COUNTS array
7150 from the _looptemp_ clauses. */
7151
7152 /* NOTE: It *could* be better to moosh all of the BBs together,
7153 creating one larger BB with all the computation and the unexpected
7154 jump at the end. I.e.
7155
7156 bool zero3, zero2, zero1, zero;
7157
7158 zero3 = N32 c3 N31;
7159 count3 = (N32 - N31) /[cl] STEP3;
7160 zero2 = N22 c2 N21;
7161 count2 = (N22 - N21) /[cl] STEP2;
7162 zero1 = N12 c1 N11;
7163 count1 = (N12 - N11) /[cl] STEP1;
7164 zero = zero3 || zero2 || zero1;
7165 count = count1 * count2 * count3;
7166 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7167
7168 After all, we expect the zero=false, and thus we expect to have to
7169 evaluate all of the comparison expressions, so short-circuiting
7170 oughtn't be a win. Since the condition isn't protecting a
7171 denominator, we're not concerned about divide-by-zero, so we can
7172 fully evaluate count even if a numerator turned out to be wrong.
7173
7174 It seems like putting this all together would create much better
7175 scheduling opportunities, and less pressure on the chip's branch
7176 predictor. */
7177
7178 static void
7179 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7180 basic_block &entry_bb, tree *counts,
7181 basic_block &zero_iter1_bb, int &first_zero_iter1,
7182 basic_block &zero_iter2_bb, int &first_zero_iter2,
7183 basic_block &l2_dom_bb)
7184 {
7185 tree t, type = TREE_TYPE (fd->loop.v);
7186 edge e, ne;
7187 int i;
7188
7189 /* Collapsed loops need work for expansion into SSA form. */
7190 gcc_assert (!gimple_in_ssa_p (cfun));
7191
7192 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7193 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7194 {
7195 gcc_assert (fd->ordered == 0);
7196 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7197 isn't supposed to be handled, as the inner loop doesn't
7198 use it. */
7199 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7200 OMP_CLAUSE__LOOPTEMP_);
7201 gcc_assert (innerc);
7202 for (i = 0; i < fd->collapse; i++)
7203 {
7204 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7205 OMP_CLAUSE__LOOPTEMP_);
7206 gcc_assert (innerc);
7207 if (i)
7208 counts[i] = OMP_CLAUSE_DECL (innerc);
7209 else
7210 counts[0] = NULL_TREE;
7211 }
7212 return;
7213 }
7214
7215 for (i = fd->collapse; i < fd->ordered; i++)
7216 {
7217 tree itype = TREE_TYPE (fd->loops[i].v);
7218 counts[i] = NULL_TREE;
7219 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7220 fold_convert (itype, fd->loops[i].n1),
7221 fold_convert (itype, fd->loops[i].n2));
7222 if (t && integer_zerop (t))
7223 {
7224 for (i = fd->collapse; i < fd->ordered; i++)
7225 counts[i] = build_int_cst (type, 0);
7226 break;
7227 }
7228 }
7229 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7230 {
7231 tree itype = TREE_TYPE (fd->loops[i].v);
7232
7233 if (i >= fd->collapse && counts[i])
7234 continue;
7235 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7236 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7237 fold_convert (itype, fd->loops[i].n1),
7238 fold_convert (itype, fd->loops[i].n2)))
7239 == NULL_TREE || !integer_onep (t)))
7240 {
7241 gcond *cond_stmt;
7242 tree n1, n2;
7243 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7244 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7245 true, GSI_SAME_STMT);
7246 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7247 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7248 true, GSI_SAME_STMT);
7249 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7250 NULL_TREE, NULL_TREE);
7251 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7252 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7253 expand_omp_regimplify_p, NULL, NULL)
7254 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7255 expand_omp_regimplify_p, NULL, NULL))
7256 {
7257 *gsi = gsi_for_stmt (cond_stmt);
7258 gimple_regimplify_operands (cond_stmt, gsi);
7259 }
7260 e = split_block (entry_bb, cond_stmt);
7261 basic_block &zero_iter_bb
7262 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7263 int &first_zero_iter
7264 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7265 if (zero_iter_bb == NULL)
7266 {
7267 gassign *assign_stmt;
7268 first_zero_iter = i;
7269 zero_iter_bb = create_empty_bb (entry_bb);
7270 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7271 *gsi = gsi_after_labels (zero_iter_bb);
7272 if (i < fd->collapse)
7273 assign_stmt = gimple_build_assign (fd->loop.n2,
7274 build_zero_cst (type));
7275 else
7276 {
7277 counts[i] = create_tmp_reg (type, ".count");
7278 assign_stmt
7279 = gimple_build_assign (counts[i], build_zero_cst (type));
7280 }
7281 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7282 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7283 entry_bb);
7284 }
7285 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7286 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7287 e->flags = EDGE_TRUE_VALUE;
7288 e->probability = REG_BR_PROB_BASE - ne->probability;
7289 if (l2_dom_bb == NULL)
7290 l2_dom_bb = entry_bb;
7291 entry_bb = e->dest;
7292 *gsi = gsi_last_bb (entry_bb);
7293 }
7294
7295 if (POINTER_TYPE_P (itype))
7296 itype = signed_type_for (itype);
7297 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7298 ? -1 : 1));
7299 t = fold_build2 (PLUS_EXPR, itype,
7300 fold_convert (itype, fd->loops[i].step), t);
7301 t = fold_build2 (PLUS_EXPR, itype, t,
7302 fold_convert (itype, fd->loops[i].n2));
7303 t = fold_build2 (MINUS_EXPR, itype, t,
7304 fold_convert (itype, fd->loops[i].n1));
7305 /* ?? We could probably use CEIL_DIV_EXPR instead of
7306 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7307 generate the same code in the end because generically we
7308 don't know that the values involved must be negative for
7309 GT?? */
7310 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7311 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7312 fold_build1 (NEGATE_EXPR, itype, t),
7313 fold_build1 (NEGATE_EXPR, itype,
7314 fold_convert (itype,
7315 fd->loops[i].step)));
7316 else
7317 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7318 fold_convert (itype, fd->loops[i].step));
7319 t = fold_convert (type, t);
7320 if (TREE_CODE (t) == INTEGER_CST)
7321 counts[i] = t;
7322 else
7323 {
7324 if (i < fd->collapse || i != first_zero_iter2)
7325 counts[i] = create_tmp_reg (type, ".count");
7326 expand_omp_build_assign (gsi, counts[i], t);
7327 }
7328 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7329 {
7330 if (i == 0)
7331 t = counts[0];
7332 else
7333 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7334 expand_omp_build_assign (gsi, fd->loop.n2, t);
7335 }
7336 }
7337 }
7338
7339
7340 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7341 T = V;
7342 V3 = N31 + (T % count3) * STEP3;
7343 T = T / count3;
7344 V2 = N21 + (T % count2) * STEP2;
7345 T = T / count2;
7346 V1 = N11 + T * STEP1;
7347 if this loop doesn't have an inner loop construct combined with it.
7348 If it does have an inner loop construct combined with it and the
7349 iteration count isn't known constant, store values from counts array
7350 into its _looptemp_ temporaries instead. */
7351
7352 static void
7353 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7354 tree *counts, gimple *inner_stmt, tree startvar)
7355 {
7356 int i;
7357 if (gimple_omp_for_combined_p (fd->for_stmt))
7358 {
7359 /* If fd->loop.n2 is constant, then no propagation of the counts
7360 is needed, they are constant. */
7361 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7362 return;
7363
7364 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7365 ? gimple_omp_taskreg_clauses (inner_stmt)
7366 : gimple_omp_for_clauses (inner_stmt);
7367 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7368 isn't supposed to be handled, as the inner loop doesn't
7369 use it. */
7370 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7371 gcc_assert (innerc);
7372 for (i = 0; i < fd->collapse; i++)
7373 {
7374 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7375 OMP_CLAUSE__LOOPTEMP_);
7376 gcc_assert (innerc);
7377 if (i)
7378 {
7379 tree tem = OMP_CLAUSE_DECL (innerc);
7380 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7381 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7382 false, GSI_CONTINUE_LINKING);
7383 gassign *stmt = gimple_build_assign (tem, t);
7384 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7385 }
7386 }
7387 return;
7388 }
7389
7390 tree type = TREE_TYPE (fd->loop.v);
7391 tree tem = create_tmp_reg (type, ".tem");
7392 gassign *stmt = gimple_build_assign (tem, startvar);
7393 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7394
7395 for (i = fd->collapse - 1; i >= 0; i--)
7396 {
7397 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7398 itype = vtype;
7399 if (POINTER_TYPE_P (vtype))
7400 itype = signed_type_for (vtype);
7401 if (i != 0)
7402 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7403 else
7404 t = tem;
7405 t = fold_convert (itype, t);
7406 t = fold_build2 (MULT_EXPR, itype, t,
7407 fold_convert (itype, fd->loops[i].step));
7408 if (POINTER_TYPE_P (vtype))
7409 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7410 else
7411 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7412 t = force_gimple_operand_gsi (gsi, t,
7413 DECL_P (fd->loops[i].v)
7414 && TREE_ADDRESSABLE (fd->loops[i].v),
7415 NULL_TREE, false,
7416 GSI_CONTINUE_LINKING);
7417 stmt = gimple_build_assign (fd->loops[i].v, t);
7418 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7419 if (i != 0)
7420 {
7421 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7422 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7423 false, GSI_CONTINUE_LINKING);
7424 stmt = gimple_build_assign (tem, t);
7425 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7426 }
7427 }
7428 }
7429
7430
7431 /* Helper function for expand_omp_for_*. Generate code like:
7432 L10:
7433 V3 += STEP3;
7434 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7435 L11:
7436 V3 = N31;
7437 V2 += STEP2;
7438 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7439 L12:
7440 V2 = N21;
7441 V1 += STEP1;
7442 goto BODY_BB; */
7443
7444 static basic_block
7445 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7446 basic_block body_bb)
7447 {
7448 basic_block last_bb, bb, collapse_bb = NULL;
7449 int i;
7450 gimple_stmt_iterator gsi;
7451 edge e;
7452 tree t;
7453 gimple *stmt;
7454
7455 last_bb = cont_bb;
7456 for (i = fd->collapse - 1; i >= 0; i--)
7457 {
7458 tree vtype = TREE_TYPE (fd->loops[i].v);
7459
7460 bb = create_empty_bb (last_bb);
7461 add_bb_to_loop (bb, last_bb->loop_father);
7462 gsi = gsi_start_bb (bb);
7463
7464 if (i < fd->collapse - 1)
7465 {
7466 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7467 e->probability = REG_BR_PROB_BASE / 8;
7468
7469 t = fd->loops[i + 1].n1;
7470 t = force_gimple_operand_gsi (&gsi, t,
7471 DECL_P (fd->loops[i + 1].v)
7472 && TREE_ADDRESSABLE (fd->loops[i
7473 + 1].v),
7474 NULL_TREE, false,
7475 GSI_CONTINUE_LINKING);
7476 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7477 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7478 }
7479 else
7480 collapse_bb = bb;
7481
7482 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7483
7484 if (POINTER_TYPE_P (vtype))
7485 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7486 else
7487 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7488 t = force_gimple_operand_gsi (&gsi, t,
7489 DECL_P (fd->loops[i].v)
7490 && TREE_ADDRESSABLE (fd->loops[i].v),
7491 NULL_TREE, false, GSI_CONTINUE_LINKING);
7492 stmt = gimple_build_assign (fd->loops[i].v, t);
7493 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7494
7495 if (i > 0)
7496 {
7497 t = fd->loops[i].n2;
7498 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7499 false, GSI_CONTINUE_LINKING);
7500 tree v = fd->loops[i].v;
7501 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7502 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7503 false, GSI_CONTINUE_LINKING);
7504 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7505 stmt = gimple_build_cond_empty (t);
7506 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7507 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7508 e->probability = REG_BR_PROB_BASE * 7 / 8;
7509 }
7510 else
7511 make_edge (bb, body_bb, EDGE_FALLTHRU);
7512 last_bb = bb;
7513 }
7514
7515 return collapse_bb;
7516 }
7517
7518
7519 /* Expand #pragma omp ordered depend(source). */
7520
7521 static void
7522 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7523 tree *counts, location_t loc)
7524 {
7525 enum built_in_function source_ix
7526 = fd->iter_type == long_integer_type_node
7527 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7528 gimple *g
7529 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7530 build_fold_addr_expr (counts[fd->ordered]));
7531 gimple_set_location (g, loc);
7532 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7533 }
7534
7535 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7536
7537 static void
7538 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7539 tree *counts, tree c, location_t loc)
7540 {
7541 auto_vec<tree, 10> args;
7542 enum built_in_function sink_ix
7543 = fd->iter_type == long_integer_type_node
7544 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7545 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7546 int i;
7547 gimple_stmt_iterator gsi2 = *gsi;
7548 bool warned_step = false;
7549
7550 for (i = 0; i < fd->ordered; i++)
7551 {
7552 off = TREE_PURPOSE (deps);
7553 if (!integer_zerop (off))
7554 {
7555 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7556 || fd->loops[i].cond_code == GT_EXPR);
7557 bool forward = fd->loops[i].cond_code == LT_EXPR;
7558 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7559 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7560 "lexically later iteration");
7561 break;
7562 }
7563 deps = TREE_CHAIN (deps);
7564 }
7565 /* If all offsets corresponding to the collapsed loops are zero,
7566 this depend clause can be ignored. FIXME: but there is still a
7567 flush needed. We need to emit one __sync_synchronize () for it
7568 though (perhaps conditionally)? Solve this together with the
7569 conservative dependence folding optimization.
7570 if (i >= fd->collapse)
7571 return; */
7572
7573 deps = OMP_CLAUSE_DECL (c);
7574 gsi_prev (&gsi2);
7575 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7576 edge e2 = split_block_after_labels (e1->dest);
7577
7578 *gsi = gsi_after_labels (e1->dest);
7579 for (i = 0; i < fd->ordered; i++)
7580 {
7581 tree itype = TREE_TYPE (fd->loops[i].v);
7582 if (POINTER_TYPE_P (itype))
7583 itype = sizetype;
7584 if (i)
7585 deps = TREE_CHAIN (deps);
7586 off = TREE_PURPOSE (deps);
7587 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7588
7589 if (integer_zerop (off))
7590 t = boolean_true_node;
7591 else
7592 {
7593 tree a;
7594 tree co = fold_convert_loc (loc, itype, off);
7595 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7596 {
7597 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7598 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7599 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7600 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7601 co);
7602 }
7603 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7604 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7605 fd->loops[i].v, co);
7606 else
7607 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7608 fd->loops[i].v, co);
7609 if (fd->loops[i].cond_code == LT_EXPR)
7610 {
7611 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7612 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7613 fd->loops[i].n1);
7614 else
7615 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7616 fd->loops[i].n2);
7617 }
7618 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7619 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7620 fd->loops[i].n2);
7621 else
7622 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7623 fd->loops[i].n1);
7624 }
7625 if (cond)
7626 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7627 else
7628 cond = t;
7629
7630 off = fold_convert_loc (loc, itype, off);
7631
7632 if (fd->loops[i].cond_code == LT_EXPR
7633 ? !integer_onep (fd->loops[i].step)
7634 : !integer_minus_onep (fd->loops[i].step))
7635 {
7636 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7637 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7638 fold_build1_loc (loc, NEGATE_EXPR, itype,
7639 s));
7640 else
7641 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7642 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7643 build_int_cst (itype, 0));
7644 if (integer_zerop (t) && !warned_step)
7645 {
7646 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7647 "in the iteration space");
7648 warned_step = true;
7649 }
7650 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7651 cond, t);
7652 }
7653
7654 if (i <= fd->collapse - 1 && fd->collapse > 1)
7655 t = fd->loop.v;
7656 else if (counts[i])
7657 t = counts[i];
7658 else
7659 {
7660 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7661 fd->loops[i].v, fd->loops[i].n1);
7662 t = fold_convert_loc (loc, fd->iter_type, t);
7663 }
7664 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7665 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7666 fold_build1_loc (loc, NEGATE_EXPR, itype,
7667 s));
7668 else
7669 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7670 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7671 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7672 off = fold_convert_loc (loc, fd->iter_type, off);
7673 if (i <= fd->collapse - 1 && fd->collapse > 1)
7674 {
7675 if (i)
7676 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7677 off);
7678 if (i < fd->collapse - 1)
7679 {
7680 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7681 counts[i]);
7682 continue;
7683 }
7684 }
7685 off = unshare_expr (off);
7686 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7687 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7688 true, GSI_SAME_STMT);
7689 args.safe_push (t);
7690 }
7691 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7692 gimple_set_location (g, loc);
7693 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7694
7695 *gsi = gsi_last_bb (e1->src);
7696 cond = unshare_expr (cond);
7697 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7698 GSI_CONTINUE_LINKING);
7699 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7700 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7701 e3->probability = REG_BR_PROB_BASE / 8;
7702 e1->probability = REG_BR_PROB_BASE - e3->probability;
7703 e1->flags = EDGE_TRUE_VALUE;
7704 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7705
7706 *gsi = gsi_after_labels (e2->dest);
7707 }
7708
7709 /* Expand all #pragma omp ordered depend(source) and
7710 #pragma omp ordered depend(sink:...) constructs in the current
7711 #pragma omp for ordered(n) region. */
7712
7713 static void
7714 expand_omp_ordered_source_sink (struct omp_region *region,
7715 struct omp_for_data *fd, tree *counts,
7716 basic_block cont_bb)
7717 {
7718 struct omp_region *inner;
7719 int i;
7720 for (i = fd->collapse - 1; i < fd->ordered; i++)
7721 if (i == fd->collapse - 1 && fd->collapse > 1)
7722 counts[i] = NULL_TREE;
7723 else if (i >= fd->collapse && !cont_bb)
7724 counts[i] = build_zero_cst (fd->iter_type);
7725 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
7726 && integer_onep (fd->loops[i].step))
7727 counts[i] = NULL_TREE;
7728 else
7729 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
7730 tree atype
7731 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
7732 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
7733 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
7734
7735 for (inner = region->inner; inner; inner = inner->next)
7736 if (inner->type == GIMPLE_OMP_ORDERED)
7737 {
7738 gomp_ordered *ord_stmt = inner->ord_stmt;
7739 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
7740 location_t loc = gimple_location (ord_stmt);
7741 tree c;
7742 for (c = gimple_omp_ordered_clauses (ord_stmt);
7743 c; c = OMP_CLAUSE_CHAIN (c))
7744 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
7745 break;
7746 if (c)
7747 expand_omp_ordered_source (&gsi, fd, counts, loc);
7748 for (c = gimple_omp_ordered_clauses (ord_stmt);
7749 c; c = OMP_CLAUSE_CHAIN (c))
7750 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
7751 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
7752 gsi_remove (&gsi, true);
7753 }
7754 }
7755
7756 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
7757 collapsed. */
7758
7759 static basic_block
7760 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
7761 basic_block cont_bb, basic_block body_bb,
7762 bool ordered_lastprivate)
7763 {
7764 if (fd->ordered == fd->collapse)
7765 return cont_bb;
7766
7767 if (!cont_bb)
7768 {
7769 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7770 for (int i = fd->collapse; i < fd->ordered; i++)
7771 {
7772 tree type = TREE_TYPE (fd->loops[i].v);
7773 tree n1 = fold_convert (type, fd->loops[i].n1);
7774 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
7775 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7776 size_int (i - fd->collapse + 1),
7777 NULL_TREE, NULL_TREE);
7778 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7779 }
7780 return NULL;
7781 }
7782
7783 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
7784 {
7785 tree t, type = TREE_TYPE (fd->loops[i].v);
7786 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7787 expand_omp_build_assign (&gsi, fd->loops[i].v,
7788 fold_convert (type, fd->loops[i].n1));
7789 if (counts[i])
7790 expand_omp_build_assign (&gsi, counts[i],
7791 build_zero_cst (fd->iter_type));
7792 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7793 size_int (i - fd->collapse + 1),
7794 NULL_TREE, NULL_TREE);
7795 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7796 if (!gsi_end_p (gsi))
7797 gsi_prev (&gsi);
7798 else
7799 gsi = gsi_last_bb (body_bb);
7800 edge e1 = split_block (body_bb, gsi_stmt (gsi));
7801 basic_block new_body = e1->dest;
7802 if (body_bb == cont_bb)
7803 cont_bb = new_body;
7804 edge e2 = NULL;
7805 basic_block new_header;
7806 if (EDGE_COUNT (cont_bb->preds) > 0)
7807 {
7808 gsi = gsi_last_bb (cont_bb);
7809 if (POINTER_TYPE_P (type))
7810 t = fold_build_pointer_plus (fd->loops[i].v,
7811 fold_convert (sizetype,
7812 fd->loops[i].step));
7813 else
7814 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
7815 fold_convert (type, fd->loops[i].step));
7816 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7817 if (counts[i])
7818 {
7819 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
7820 build_int_cst (fd->iter_type, 1));
7821 expand_omp_build_assign (&gsi, counts[i], t);
7822 t = counts[i];
7823 }
7824 else
7825 {
7826 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7827 fd->loops[i].v, fd->loops[i].n1);
7828 t = fold_convert (fd->iter_type, t);
7829 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7830 true, GSI_SAME_STMT);
7831 }
7832 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7833 size_int (i - fd->collapse + 1),
7834 NULL_TREE, NULL_TREE);
7835 expand_omp_build_assign (&gsi, aref, t);
7836 gsi_prev (&gsi);
7837 e2 = split_block (cont_bb, gsi_stmt (gsi));
7838 new_header = e2->dest;
7839 }
7840 else
7841 new_header = cont_bb;
7842 gsi = gsi_after_labels (new_header);
7843 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
7844 true, GSI_SAME_STMT);
7845 tree n2
7846 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
7847 true, NULL_TREE, true, GSI_SAME_STMT);
7848 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
7849 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
7850 edge e3 = split_block (new_header, gsi_stmt (gsi));
7851 cont_bb = e3->dest;
7852 remove_edge (e1);
7853 make_edge (body_bb, new_header, EDGE_FALLTHRU);
7854 e3->flags = EDGE_FALSE_VALUE;
7855 e3->probability = REG_BR_PROB_BASE / 8;
7856 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
7857 e1->probability = REG_BR_PROB_BASE - e3->probability;
7858
7859 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
7860 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
7861
7862 if (e2)
7863 {
7864 struct loop *loop = alloc_loop ();
7865 loop->header = new_header;
7866 loop->latch = e2->src;
7867 add_loop (loop, body_bb->loop_father);
7868 }
7869 }
7870
7871 /* If there are any lastprivate clauses and it is possible some loops
7872 might have zero iterations, ensure all the decls are initialized,
7873 otherwise we could crash evaluating C++ class iterators with lastprivate
7874 clauses. */
7875 bool need_inits = false;
7876 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
7877 if (need_inits)
7878 {
7879 tree type = TREE_TYPE (fd->loops[i].v);
7880 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7881 expand_omp_build_assign (&gsi, fd->loops[i].v,
7882 fold_convert (type, fd->loops[i].n1));
7883 }
7884 else
7885 {
7886 tree type = TREE_TYPE (fd->loops[i].v);
7887 tree this_cond = fold_build2 (fd->loops[i].cond_code,
7888 boolean_type_node,
7889 fold_convert (type, fd->loops[i].n1),
7890 fold_convert (type, fd->loops[i].n2));
7891 if (!integer_onep (this_cond))
7892 need_inits = true;
7893 }
7894
7895 return cont_bb;
7896 }
7897
7898
7899 /* A subroutine of expand_omp_for. Generate code for a parallel
7900 loop with any schedule. Given parameters:
7901
7902 for (V = N1; V cond N2; V += STEP) BODY;
7903
7904 where COND is "<" or ">", we generate pseudocode
7905
7906 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
7907 if (more) goto L0; else goto L3;
7908 L0:
7909 V = istart0;
7910 iend = iend0;
7911 L1:
7912 BODY;
7913 V += STEP;
7914 if (V cond iend) goto L1; else goto L2;
7915 L2:
7916 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7917 L3:
7918
7919 If this is a combined omp parallel loop, instead of the call to
7920 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
7921 If this is gimple_omp_for_combined_p loop, then instead of assigning
7922 V and iend in L0 we assign the first two _looptemp_ clause decls of the
7923 inner GIMPLE_OMP_FOR and V += STEP; and
7924 if (V cond iend) goto L1; else goto L2; are removed.
7925
7926 For collapsed loops, given parameters:
7927 collapse(3)
7928 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7929 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7930 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7931 BODY;
7932
7933 we generate pseudocode
7934
7935 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
7936 if (cond3 is <)
7937 adj = STEP3 - 1;
7938 else
7939 adj = STEP3 + 1;
7940 count3 = (adj + N32 - N31) / STEP3;
7941 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
7942 if (cond2 is <)
7943 adj = STEP2 - 1;
7944 else
7945 adj = STEP2 + 1;
7946 count2 = (adj + N22 - N21) / STEP2;
7947 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
7948 if (cond1 is <)
7949 adj = STEP1 - 1;
7950 else
7951 adj = STEP1 + 1;
7952 count1 = (adj + N12 - N11) / STEP1;
7953 count = count1 * count2 * count3;
7954 goto Z1;
7955 Z0:
7956 count = 0;
7957 Z1:
7958 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
7959 if (more) goto L0; else goto L3;
7960 L0:
7961 V = istart0;
7962 T = V;
7963 V3 = N31 + (T % count3) * STEP3;
7964 T = T / count3;
7965 V2 = N21 + (T % count2) * STEP2;
7966 T = T / count2;
7967 V1 = N11 + T * STEP1;
7968 iend = iend0;
7969 L1:
7970 BODY;
7971 V += 1;
7972 if (V < iend) goto L10; else goto L2;
7973 L10:
7974 V3 += STEP3;
7975 if (V3 cond3 N32) goto L1; else goto L11;
7976 L11:
7977 V3 = N31;
7978 V2 += STEP2;
7979 if (V2 cond2 N22) goto L1; else goto L12;
7980 L12:
7981 V2 = N21;
7982 V1 += STEP1;
7983 goto L1;
7984 L2:
7985 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7986 L3:
7987
7988 */
7989
7990 static void
7991 expand_omp_for_generic (struct omp_region *region,
7992 struct omp_for_data *fd,
7993 enum built_in_function start_fn,
7994 enum built_in_function next_fn,
7995 gimple *inner_stmt)
7996 {
7997 tree type, istart0, iend0, iend;
7998 tree t, vmain, vback, bias = NULL_TREE;
7999 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8000 basic_block l2_bb = NULL, l3_bb = NULL;
8001 gimple_stmt_iterator gsi;
8002 gassign *assign_stmt;
8003 bool in_combined_parallel = is_combined_parallel (region);
8004 bool broken_loop = region->cont == NULL;
8005 edge e, ne;
8006 tree *counts = NULL;
8007 int i;
8008 bool ordered_lastprivate = false;
8009
8010 gcc_assert (!broken_loop || !in_combined_parallel);
8011 gcc_assert (fd->iter_type == long_integer_type_node
8012 || !in_combined_parallel);
8013
8014 entry_bb = region->entry;
8015 cont_bb = region->cont;
8016 collapse_bb = NULL;
8017 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8018 gcc_assert (broken_loop
8019 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8020 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8021 l1_bb = single_succ (l0_bb);
8022 if (!broken_loop)
8023 {
8024 l2_bb = create_empty_bb (cont_bb);
8025 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8026 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8027 == l1_bb));
8028 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8029 }
8030 else
8031 l2_bb = NULL;
8032 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8033 exit_bb = region->exit;
8034
8035 gsi = gsi_last_bb (entry_bb);
8036
8037 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8038 if (fd->ordered
8039 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8040 OMP_CLAUSE_LASTPRIVATE))
8041 ordered_lastprivate = false;
8042 if (fd->collapse > 1 || fd->ordered)
8043 {
8044 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8045 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8046
8047 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8048 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8049 zero_iter1_bb, first_zero_iter1,
8050 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8051
8052 if (zero_iter1_bb)
8053 {
8054 /* Some counts[i] vars might be uninitialized if
8055 some loop has zero iterations. But the body shouldn't
8056 be executed in that case, so just avoid uninit warnings. */
8057 for (i = first_zero_iter1;
8058 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8059 if (SSA_VAR_P (counts[i]))
8060 TREE_NO_WARNING (counts[i]) = 1;
8061 gsi_prev (&gsi);
8062 e = split_block (entry_bb, gsi_stmt (gsi));
8063 entry_bb = e->dest;
8064 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8065 gsi = gsi_last_bb (entry_bb);
8066 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8067 get_immediate_dominator (CDI_DOMINATORS,
8068 zero_iter1_bb));
8069 }
8070 if (zero_iter2_bb)
8071 {
8072 /* Some counts[i] vars might be uninitialized if
8073 some loop has zero iterations. But the body shouldn't
8074 be executed in that case, so just avoid uninit warnings. */
8075 for (i = first_zero_iter2; i < fd->ordered; i++)
8076 if (SSA_VAR_P (counts[i]))
8077 TREE_NO_WARNING (counts[i]) = 1;
8078 if (zero_iter1_bb)
8079 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8080 else
8081 {
8082 gsi_prev (&gsi);
8083 e = split_block (entry_bb, gsi_stmt (gsi));
8084 entry_bb = e->dest;
8085 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8086 gsi = gsi_last_bb (entry_bb);
8087 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8088 get_immediate_dominator
8089 (CDI_DOMINATORS, zero_iter2_bb));
8090 }
8091 }
8092 if (fd->collapse == 1)
8093 {
8094 counts[0] = fd->loop.n2;
8095 fd->loop = fd->loops[0];
8096 }
8097 }
8098
8099 type = TREE_TYPE (fd->loop.v);
8100 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8101 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8102 TREE_ADDRESSABLE (istart0) = 1;
8103 TREE_ADDRESSABLE (iend0) = 1;
8104
8105 /* See if we need to bias by LLONG_MIN. */
8106 if (fd->iter_type == long_long_unsigned_type_node
8107 && TREE_CODE (type) == INTEGER_TYPE
8108 && !TYPE_UNSIGNED (type)
8109 && fd->ordered == 0)
8110 {
8111 tree n1, n2;
8112
8113 if (fd->loop.cond_code == LT_EXPR)
8114 {
8115 n1 = fd->loop.n1;
8116 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8117 }
8118 else
8119 {
8120 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8121 n2 = fd->loop.n1;
8122 }
8123 if (TREE_CODE (n1) != INTEGER_CST
8124 || TREE_CODE (n2) != INTEGER_CST
8125 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8126 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8127 }
8128
8129 gimple_stmt_iterator gsif = gsi;
8130 gsi_prev (&gsif);
8131
8132 tree arr = NULL_TREE;
8133 if (in_combined_parallel)
8134 {
8135 gcc_assert (fd->ordered == 0);
8136 /* In a combined parallel loop, emit a call to
8137 GOMP_loop_foo_next. */
8138 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8139 build_fold_addr_expr (istart0),
8140 build_fold_addr_expr (iend0));
8141 }
8142 else
8143 {
8144 tree t0, t1, t2, t3, t4;
8145 /* If this is not a combined parallel loop, emit a call to
8146 GOMP_loop_foo_start in ENTRY_BB. */
8147 t4 = build_fold_addr_expr (iend0);
8148 t3 = build_fold_addr_expr (istart0);
8149 if (fd->ordered)
8150 {
8151 t0 = build_int_cst (unsigned_type_node,
8152 fd->ordered - fd->collapse + 1);
8153 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8154 fd->ordered
8155 - fd->collapse + 1),
8156 ".omp_counts");
8157 DECL_NAMELESS (arr) = 1;
8158 TREE_ADDRESSABLE (arr) = 1;
8159 TREE_STATIC (arr) = 1;
8160 vec<constructor_elt, va_gc> *v;
8161 vec_alloc (v, fd->ordered - fd->collapse + 1);
8162 int idx;
8163
8164 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8165 {
8166 tree c;
8167 if (idx == 0 && fd->collapse > 1)
8168 c = fd->loop.n2;
8169 else
8170 c = counts[idx + fd->collapse - 1];
8171 tree purpose = size_int (idx);
8172 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8173 if (TREE_CODE (c) != INTEGER_CST)
8174 TREE_STATIC (arr) = 0;
8175 }
8176
8177 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8178 if (!TREE_STATIC (arr))
8179 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8180 void_type_node, arr),
8181 true, NULL_TREE, true, GSI_SAME_STMT);
8182 t1 = build_fold_addr_expr (arr);
8183 t2 = NULL_TREE;
8184 }
8185 else
8186 {
8187 t2 = fold_convert (fd->iter_type, fd->loop.step);
8188 t1 = fd->loop.n2;
8189 t0 = fd->loop.n1;
8190 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8191 {
8192 tree innerc
8193 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8194 OMP_CLAUSE__LOOPTEMP_);
8195 gcc_assert (innerc);
8196 t0 = OMP_CLAUSE_DECL (innerc);
8197 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8198 OMP_CLAUSE__LOOPTEMP_);
8199 gcc_assert (innerc);
8200 t1 = OMP_CLAUSE_DECL (innerc);
8201 }
8202 if (POINTER_TYPE_P (TREE_TYPE (t0))
8203 && TYPE_PRECISION (TREE_TYPE (t0))
8204 != TYPE_PRECISION (fd->iter_type))
8205 {
8206 /* Avoid casting pointers to integer of a different size. */
8207 tree itype = signed_type_for (type);
8208 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8209 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8210 }
8211 else
8212 {
8213 t1 = fold_convert (fd->iter_type, t1);
8214 t0 = fold_convert (fd->iter_type, t0);
8215 }
8216 if (bias)
8217 {
8218 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8219 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8220 }
8221 }
8222 if (fd->iter_type == long_integer_type_node || fd->ordered)
8223 {
8224 if (fd->chunk_size)
8225 {
8226 t = fold_convert (fd->iter_type, fd->chunk_size);
8227 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8228 if (fd->ordered)
8229 t = build_call_expr (builtin_decl_explicit (start_fn),
8230 5, t0, t1, t, t3, t4);
8231 else
8232 t = build_call_expr (builtin_decl_explicit (start_fn),
8233 6, t0, t1, t2, t, t3, t4);
8234 }
8235 else if (fd->ordered)
8236 t = build_call_expr (builtin_decl_explicit (start_fn),
8237 4, t0, t1, t3, t4);
8238 else
8239 t = build_call_expr (builtin_decl_explicit (start_fn),
8240 5, t0, t1, t2, t3, t4);
8241 }
8242 else
8243 {
8244 tree t5;
8245 tree c_bool_type;
8246 tree bfn_decl;
8247
8248 /* The GOMP_loop_ull_*start functions have additional boolean
8249 argument, true for < loops and false for > loops.
8250 In Fortran, the C bool type can be different from
8251 boolean_type_node. */
8252 bfn_decl = builtin_decl_explicit (start_fn);
8253 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8254 t5 = build_int_cst (c_bool_type,
8255 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8256 if (fd->chunk_size)
8257 {
8258 tree bfn_decl = builtin_decl_explicit (start_fn);
8259 t = fold_convert (fd->iter_type, fd->chunk_size);
8260 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8261 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8262 }
8263 else
8264 t = build_call_expr (builtin_decl_explicit (start_fn),
8265 6, t5, t0, t1, t2, t3, t4);
8266 }
8267 }
8268 if (TREE_TYPE (t) != boolean_type_node)
8269 t = fold_build2 (NE_EXPR, boolean_type_node,
8270 t, build_int_cst (TREE_TYPE (t), 0));
8271 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8272 true, GSI_SAME_STMT);
8273 if (arr && !TREE_STATIC (arr))
8274 {
8275 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8276 TREE_THIS_VOLATILE (clobber) = 1;
8277 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8278 GSI_SAME_STMT);
8279 }
8280 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8281
8282 /* Remove the GIMPLE_OMP_FOR statement. */
8283 gsi_remove (&gsi, true);
8284
8285 if (gsi_end_p (gsif))
8286 gsif = gsi_after_labels (gsi_bb (gsif));
8287 gsi_next (&gsif);
8288
8289 /* Iteration setup for sequential loop goes in L0_BB. */
8290 tree startvar = fd->loop.v;
8291 tree endvar = NULL_TREE;
8292
8293 if (gimple_omp_for_combined_p (fd->for_stmt))
8294 {
8295 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8296 && gimple_omp_for_kind (inner_stmt)
8297 == GF_OMP_FOR_KIND_SIMD);
8298 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8299 OMP_CLAUSE__LOOPTEMP_);
8300 gcc_assert (innerc);
8301 startvar = OMP_CLAUSE_DECL (innerc);
8302 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8303 OMP_CLAUSE__LOOPTEMP_);
8304 gcc_assert (innerc);
8305 endvar = OMP_CLAUSE_DECL (innerc);
8306 }
8307
8308 gsi = gsi_start_bb (l0_bb);
8309 t = istart0;
8310 if (fd->ordered && fd->collapse == 1)
8311 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8312 fold_convert (fd->iter_type, fd->loop.step));
8313 else if (bias)
8314 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8315 if (fd->ordered && fd->collapse == 1)
8316 {
8317 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8318 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8319 fd->loop.n1, fold_convert (sizetype, t));
8320 else
8321 {
8322 t = fold_convert (TREE_TYPE (startvar), t);
8323 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8324 fd->loop.n1, t);
8325 }
8326 }
8327 else
8328 {
8329 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8330 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8331 t = fold_convert (TREE_TYPE (startvar), t);
8332 }
8333 t = force_gimple_operand_gsi (&gsi, t,
8334 DECL_P (startvar)
8335 && TREE_ADDRESSABLE (startvar),
8336 NULL_TREE, false, GSI_CONTINUE_LINKING);
8337 assign_stmt = gimple_build_assign (startvar, t);
8338 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8339
8340 t = iend0;
8341 if (fd->ordered && fd->collapse == 1)
8342 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8343 fold_convert (fd->iter_type, fd->loop.step));
8344 else if (bias)
8345 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8346 if (fd->ordered && fd->collapse == 1)
8347 {
8348 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8349 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8350 fd->loop.n1, fold_convert (sizetype, t));
8351 else
8352 {
8353 t = fold_convert (TREE_TYPE (startvar), t);
8354 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8355 fd->loop.n1, t);
8356 }
8357 }
8358 else
8359 {
8360 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8361 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8362 t = fold_convert (TREE_TYPE (startvar), t);
8363 }
8364 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8365 false, GSI_CONTINUE_LINKING);
8366 if (endvar)
8367 {
8368 assign_stmt = gimple_build_assign (endvar, iend);
8369 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8370 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8371 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8372 else
8373 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8374 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8375 }
8376 /* Handle linear clause adjustments. */
8377 tree itercnt = NULL_TREE;
8378 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8379 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8380 c; c = OMP_CLAUSE_CHAIN (c))
8381 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8382 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8383 {
8384 tree d = OMP_CLAUSE_DECL (c);
8385 bool is_ref = is_reference (d);
8386 tree t = d, a, dest;
8387 if (is_ref)
8388 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8389 tree type = TREE_TYPE (t);
8390 if (POINTER_TYPE_P (type))
8391 type = sizetype;
8392 dest = unshare_expr (t);
8393 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8394 expand_omp_build_assign (&gsif, v, t);
8395 if (itercnt == NULL_TREE)
8396 {
8397 itercnt = startvar;
8398 tree n1 = fd->loop.n1;
8399 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8400 {
8401 itercnt
8402 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8403 itercnt);
8404 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8405 }
8406 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8407 itercnt, n1);
8408 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8409 itercnt, fd->loop.step);
8410 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8411 NULL_TREE, false,
8412 GSI_CONTINUE_LINKING);
8413 }
8414 a = fold_build2 (MULT_EXPR, type,
8415 fold_convert (type, itercnt),
8416 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8417 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8418 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8419 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8420 false, GSI_CONTINUE_LINKING);
8421 assign_stmt = gimple_build_assign (dest, t);
8422 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8423 }
8424 if (fd->collapse > 1)
8425 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8426
8427 if (fd->ordered)
8428 {
8429 /* Until now, counts array contained number of iterations or
8430 variable containing it for ith loop. From now on, we need
8431 those counts only for collapsed loops, and only for the 2nd
8432 till the last collapsed one. Move those one element earlier,
8433 we'll use counts[fd->collapse - 1] for the first source/sink
8434 iteration counter and so on and counts[fd->ordered]
8435 as the array holding the current counter values for
8436 depend(source). */
8437 if (fd->collapse > 1)
8438 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8439 if (broken_loop)
8440 {
8441 int i;
8442 for (i = fd->collapse; i < fd->ordered; i++)
8443 {
8444 tree type = TREE_TYPE (fd->loops[i].v);
8445 tree this_cond
8446 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8447 fold_convert (type, fd->loops[i].n1),
8448 fold_convert (type, fd->loops[i].n2));
8449 if (!integer_onep (this_cond))
8450 break;
8451 }
8452 if (i < fd->ordered)
8453 {
8454 cont_bb
8455 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8456 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8457 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8458 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8459 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8460 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8461 make_edge (cont_bb, l1_bb, 0);
8462 l2_bb = create_empty_bb (cont_bb);
8463 broken_loop = false;
8464 }
8465 }
8466 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8467 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8468 ordered_lastprivate);
8469 if (counts[fd->collapse - 1])
8470 {
8471 gcc_assert (fd->collapse == 1);
8472 gsi = gsi_last_bb (l0_bb);
8473 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8474 istart0, true);
8475 gsi = gsi_last_bb (cont_bb);
8476 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8477 build_int_cst (fd->iter_type, 1));
8478 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8479 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8480 size_zero_node, NULL_TREE, NULL_TREE);
8481 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8482 t = counts[fd->collapse - 1];
8483 }
8484 else if (fd->collapse > 1)
8485 t = fd->loop.v;
8486 else
8487 {
8488 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8489 fd->loops[0].v, fd->loops[0].n1);
8490 t = fold_convert (fd->iter_type, t);
8491 }
8492 gsi = gsi_last_bb (l0_bb);
8493 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8494 size_zero_node, NULL_TREE, NULL_TREE);
8495 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8496 false, GSI_CONTINUE_LINKING);
8497 expand_omp_build_assign (&gsi, aref, t, true);
8498 }
8499
8500 if (!broken_loop)
8501 {
8502 /* Code to control the increment and predicate for the sequential
8503 loop goes in the CONT_BB. */
8504 gsi = gsi_last_bb (cont_bb);
8505 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8506 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8507 vmain = gimple_omp_continue_control_use (cont_stmt);
8508 vback = gimple_omp_continue_control_def (cont_stmt);
8509
8510 if (!gimple_omp_for_combined_p (fd->for_stmt))
8511 {
8512 if (POINTER_TYPE_P (type))
8513 t = fold_build_pointer_plus (vmain, fd->loop.step);
8514 else
8515 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8516 t = force_gimple_operand_gsi (&gsi, t,
8517 DECL_P (vback)
8518 && TREE_ADDRESSABLE (vback),
8519 NULL_TREE, true, GSI_SAME_STMT);
8520 assign_stmt = gimple_build_assign (vback, t);
8521 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8522
8523 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8524 {
8525 if (fd->collapse > 1)
8526 t = fd->loop.v;
8527 else
8528 {
8529 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8530 fd->loops[0].v, fd->loops[0].n1);
8531 t = fold_convert (fd->iter_type, t);
8532 }
8533 tree aref = build4 (ARRAY_REF, fd->iter_type,
8534 counts[fd->ordered], size_zero_node,
8535 NULL_TREE, NULL_TREE);
8536 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8537 true, GSI_SAME_STMT);
8538 expand_omp_build_assign (&gsi, aref, t);
8539 }
8540
8541 t = build2 (fd->loop.cond_code, boolean_type_node,
8542 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8543 iend);
8544 gcond *cond_stmt = gimple_build_cond_empty (t);
8545 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8546 }
8547
8548 /* Remove GIMPLE_OMP_CONTINUE. */
8549 gsi_remove (&gsi, true);
8550
8551 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8552 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8553
8554 /* Emit code to get the next parallel iteration in L2_BB. */
8555 gsi = gsi_start_bb (l2_bb);
8556
8557 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8558 build_fold_addr_expr (istart0),
8559 build_fold_addr_expr (iend0));
8560 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8561 false, GSI_CONTINUE_LINKING);
8562 if (TREE_TYPE (t) != boolean_type_node)
8563 t = fold_build2 (NE_EXPR, boolean_type_node,
8564 t, build_int_cst (TREE_TYPE (t), 0));
8565 gcond *cond_stmt = gimple_build_cond_empty (t);
8566 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
8567 }
8568
8569 /* Add the loop cleanup function. */
8570 gsi = gsi_last_bb (exit_bb);
8571 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8572 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
8573 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8574 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
8575 else
8576 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
8577 gcall *call_stmt = gimple_build_call (t, 0);
8578 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8579 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8580 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
8581 if (fd->ordered)
8582 {
8583 tree arr = counts[fd->ordered];
8584 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8585 TREE_THIS_VOLATILE (clobber) = 1;
8586 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8587 GSI_SAME_STMT);
8588 }
8589 gsi_remove (&gsi, true);
8590
8591 /* Connect the new blocks. */
8592 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8593 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
8594
8595 if (!broken_loop)
8596 {
8597 gimple_seq phis;
8598
8599 e = find_edge (cont_bb, l3_bb);
8600 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8601
8602 phis = phi_nodes (l3_bb);
8603 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8604 {
8605 gimple *phi = gsi_stmt (gsi);
8606 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8607 PHI_ARG_DEF_FROM_EDGE (phi, e));
8608 }
8609 remove_edge (e);
8610
8611 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
8612 e = find_edge (cont_bb, l1_bb);
8613 if (e == NULL)
8614 {
8615 e = BRANCH_EDGE (cont_bb);
8616 gcc_assert (single_succ (e->dest) == l1_bb);
8617 }
8618 if (gimple_omp_for_combined_p (fd->for_stmt))
8619 {
8620 remove_edge (e);
8621 e = NULL;
8622 }
8623 else if (fd->collapse > 1)
8624 {
8625 remove_edge (e);
8626 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8627 }
8628 else
8629 e->flags = EDGE_TRUE_VALUE;
8630 if (e)
8631 {
8632 e->probability = REG_BR_PROB_BASE * 7 / 8;
8633 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8634 }
8635 else
8636 {
8637 e = find_edge (cont_bb, l2_bb);
8638 e->flags = EDGE_FALLTHRU;
8639 }
8640 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
8641
8642 if (gimple_in_ssa_p (cfun))
8643 {
8644 /* Add phis to the outer loop that connect to the phis in the inner,
8645 original loop, and move the loop entry value of the inner phi to
8646 the loop entry value of the outer phi. */
8647 gphi_iterator psi;
8648 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8649 {
8650 source_location locus;
8651 gphi *nphi;
8652 gphi *exit_phi = psi.phi ();
8653
8654 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8655 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8656
8657 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8658 edge latch_to_l1 = find_edge (latch, l1_bb);
8659 gphi *inner_phi
8660 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8661
8662 tree t = gimple_phi_result (exit_phi);
8663 tree new_res = copy_ssa_name (t, NULL);
8664 nphi = create_phi_node (new_res, l0_bb);
8665
8666 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8667 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8668 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8669 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8670 add_phi_arg (nphi, t, entry_to_l0, locus);
8671
8672 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8673 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8674
8675 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8676 };
8677 }
8678
8679 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8680 recompute_dominator (CDI_DOMINATORS, l2_bb));
8681 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8682 recompute_dominator (CDI_DOMINATORS, l3_bb));
8683 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8684 recompute_dominator (CDI_DOMINATORS, l0_bb));
8685 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8686 recompute_dominator (CDI_DOMINATORS, l1_bb));
8687
8688 /* We enter expand_omp_for_generic with a loop. This original loop may
8689 have its own loop struct, or it may be part of an outer loop struct
8690 (which may be the fake loop). */
8691 struct loop *outer_loop = entry_bb->loop_father;
8692 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8693
8694 add_bb_to_loop (l2_bb, outer_loop);
8695
8696 /* We've added a new loop around the original loop. Allocate the
8697 corresponding loop struct. */
8698 struct loop *new_loop = alloc_loop ();
8699 new_loop->header = l0_bb;
8700 new_loop->latch = l2_bb;
8701 add_loop (new_loop, outer_loop);
8702
8703 /* Allocate a loop structure for the original loop unless we already
8704 had one. */
8705 if (!orig_loop_has_loop_struct
8706 && !gimple_omp_for_combined_p (fd->for_stmt))
8707 {
8708 struct loop *orig_loop = alloc_loop ();
8709 orig_loop->header = l1_bb;
8710 /* The loop may have multiple latches. */
8711 add_loop (orig_loop, new_loop);
8712 }
8713 }
8714 }
8715
8716
8717 /* A subroutine of expand_omp_for. Generate code for a parallel
8718 loop with static schedule and no specified chunk size. Given
8719 parameters:
8720
8721 for (V = N1; V cond N2; V += STEP) BODY;
8722
8723 where COND is "<" or ">", we generate pseudocode
8724
8725 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
8726 if (cond is <)
8727 adj = STEP - 1;
8728 else
8729 adj = STEP + 1;
8730 if ((__typeof (V)) -1 > 0 && cond is >)
8731 n = -(adj + N2 - N1) / -STEP;
8732 else
8733 n = (adj + N2 - N1) / STEP;
8734 q = n / nthreads;
8735 tt = n % nthreads;
8736 if (threadid < tt) goto L3; else goto L4;
8737 L3:
8738 tt = 0;
8739 q = q + 1;
8740 L4:
8741 s0 = q * threadid + tt;
8742 e0 = s0 + q;
8743 V = s0 * STEP + N1;
8744 if (s0 >= e0) goto L2; else goto L0;
8745 L0:
8746 e = e0 * STEP + N1;
8747 L1:
8748 BODY;
8749 V += STEP;
8750 if (V cond e) goto L1;
8751 L2:
8752 */
8753
8754 static void
8755 expand_omp_for_static_nochunk (struct omp_region *region,
8756 struct omp_for_data *fd,
8757 gimple *inner_stmt)
8758 {
8759 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
8760 tree type, itype, vmain, vback;
8761 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
8762 basic_block body_bb, cont_bb, collapse_bb = NULL;
8763 basic_block fin_bb;
8764 gimple_stmt_iterator gsi;
8765 edge ep;
8766 bool broken_loop = region->cont == NULL;
8767 tree *counts = NULL;
8768 tree n1, n2, step;
8769
8770 itype = type = TREE_TYPE (fd->loop.v);
8771 if (POINTER_TYPE_P (type))
8772 itype = signed_type_for (type);
8773
8774 entry_bb = region->entry;
8775 cont_bb = region->cont;
8776 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8777 fin_bb = BRANCH_EDGE (entry_bb)->dest;
8778 gcc_assert (broken_loop
8779 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
8780 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8781 body_bb = single_succ (seq_start_bb);
8782 if (!broken_loop)
8783 {
8784 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
8785 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
8786 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8787 }
8788 exit_bb = region->exit;
8789
8790 /* Iteration space partitioning goes in ENTRY_BB. */
8791 gsi = gsi_last_bb (entry_bb);
8792 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8793
8794 if (fd->collapse > 1)
8795 {
8796 int first_zero_iter = -1, dummy = -1;
8797 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
8798
8799 counts = XALLOCAVEC (tree, fd->collapse);
8800 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8801 fin_bb, first_zero_iter,
8802 dummy_bb, dummy, l2_dom_bb);
8803 t = NULL_TREE;
8804 }
8805 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
8806 t = integer_one_node;
8807 else
8808 t = fold_binary (fd->loop.cond_code, boolean_type_node,
8809 fold_convert (type, fd->loop.n1),
8810 fold_convert (type, fd->loop.n2));
8811 if (fd->collapse == 1
8812 && TYPE_UNSIGNED (type)
8813 && (t == NULL_TREE || !integer_onep (t)))
8814 {
8815 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
8816 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8817 true, GSI_SAME_STMT);
8818 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
8819 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8820 true, GSI_SAME_STMT);
8821 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
8822 NULL_TREE, NULL_TREE);
8823 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8824 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8825 expand_omp_regimplify_p, NULL, NULL)
8826 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8827 expand_omp_regimplify_p, NULL, NULL))
8828 {
8829 gsi = gsi_for_stmt (cond_stmt);
8830 gimple_regimplify_operands (cond_stmt, &gsi);
8831 }
8832 ep = split_block (entry_bb, cond_stmt);
8833 ep->flags = EDGE_TRUE_VALUE;
8834 entry_bb = ep->dest;
8835 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
8836 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
8837 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
8838 if (gimple_in_ssa_p (cfun))
8839 {
8840 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
8841 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
8842 !gsi_end_p (gpi); gsi_next (&gpi))
8843 {
8844 gphi *phi = gpi.phi ();
8845 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
8846 ep, UNKNOWN_LOCATION);
8847 }
8848 }
8849 gsi = gsi_last_bb (entry_bb);
8850 }
8851
8852 switch (gimple_omp_for_kind (fd->for_stmt))
8853 {
8854 case GF_OMP_FOR_KIND_FOR:
8855 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
8856 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8857 break;
8858 case GF_OMP_FOR_KIND_DISTRIBUTE:
8859 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
8860 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
8861 break;
8862 default:
8863 gcc_unreachable ();
8864 }
8865 nthreads = build_call_expr (nthreads, 0);
8866 nthreads = fold_convert (itype, nthreads);
8867 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
8868 true, GSI_SAME_STMT);
8869 threadid = build_call_expr (threadid, 0);
8870 threadid = fold_convert (itype, threadid);
8871 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
8872 true, GSI_SAME_STMT);
8873
8874 n1 = fd->loop.n1;
8875 n2 = fd->loop.n2;
8876 step = fd->loop.step;
8877 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8878 {
8879 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8880 OMP_CLAUSE__LOOPTEMP_);
8881 gcc_assert (innerc);
8882 n1 = OMP_CLAUSE_DECL (innerc);
8883 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8884 OMP_CLAUSE__LOOPTEMP_);
8885 gcc_assert (innerc);
8886 n2 = OMP_CLAUSE_DECL (innerc);
8887 }
8888 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
8889 true, NULL_TREE, true, GSI_SAME_STMT);
8890 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
8891 true, NULL_TREE, true, GSI_SAME_STMT);
8892 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
8893 true, NULL_TREE, true, GSI_SAME_STMT);
8894
8895 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
8896 t = fold_build2 (PLUS_EXPR, itype, step, t);
8897 t = fold_build2 (PLUS_EXPR, itype, t, n2);
8898 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
8899 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
8900 t = fold_build2 (TRUNC_DIV_EXPR, itype,
8901 fold_build1 (NEGATE_EXPR, itype, t),
8902 fold_build1 (NEGATE_EXPR, itype, step));
8903 else
8904 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
8905 t = fold_convert (itype, t);
8906 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8907
8908 q = create_tmp_reg (itype, "q");
8909 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
8910 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
8911 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
8912
8913 tt = create_tmp_reg (itype, "tt");
8914 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
8915 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
8916 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
8917
8918 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
8919 gcond *cond_stmt = gimple_build_cond_empty (t);
8920 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8921
8922 second_bb = split_block (entry_bb, cond_stmt)->dest;
8923 gsi = gsi_last_bb (second_bb);
8924 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8925
8926 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
8927 GSI_SAME_STMT);
8928 gassign *assign_stmt
8929 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
8930 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8931
8932 third_bb = split_block (second_bb, assign_stmt)->dest;
8933 gsi = gsi_last_bb (third_bb);
8934 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8935
8936 t = build2 (MULT_EXPR, itype, q, threadid);
8937 t = build2 (PLUS_EXPR, itype, t, tt);
8938 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8939
8940 t = fold_build2 (PLUS_EXPR, itype, s0, q);
8941 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8942
8943 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
8944 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8945
8946 /* Remove the GIMPLE_OMP_FOR statement. */
8947 gsi_remove (&gsi, true);
8948
8949 /* Setup code for sequential iteration goes in SEQ_START_BB. */
8950 gsi = gsi_start_bb (seq_start_bb);
8951
8952 tree startvar = fd->loop.v;
8953 tree endvar = NULL_TREE;
8954
8955 if (gimple_omp_for_combined_p (fd->for_stmt))
8956 {
8957 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
8958 ? gimple_omp_parallel_clauses (inner_stmt)
8959 : gimple_omp_for_clauses (inner_stmt);
8960 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
8961 gcc_assert (innerc);
8962 startvar = OMP_CLAUSE_DECL (innerc);
8963 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8964 OMP_CLAUSE__LOOPTEMP_);
8965 gcc_assert (innerc);
8966 endvar = OMP_CLAUSE_DECL (innerc);
8967 }
8968 t = fold_convert (itype, s0);
8969 t = fold_build2 (MULT_EXPR, itype, t, step);
8970 if (POINTER_TYPE_P (type))
8971 t = fold_build_pointer_plus (n1, t);
8972 else
8973 t = fold_build2 (PLUS_EXPR, type, t, n1);
8974 t = fold_convert (TREE_TYPE (startvar), t);
8975 t = force_gimple_operand_gsi (&gsi, t,
8976 DECL_P (startvar)
8977 && TREE_ADDRESSABLE (startvar),
8978 NULL_TREE, false, GSI_CONTINUE_LINKING);
8979 assign_stmt = gimple_build_assign (startvar, t);
8980 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8981
8982 t = fold_convert (itype, e0);
8983 t = fold_build2 (MULT_EXPR, itype, t, step);
8984 if (POINTER_TYPE_P (type))
8985 t = fold_build_pointer_plus (n1, t);
8986 else
8987 t = fold_build2 (PLUS_EXPR, type, t, n1);
8988 t = fold_convert (TREE_TYPE (startvar), t);
8989 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8990 false, GSI_CONTINUE_LINKING);
8991 if (endvar)
8992 {
8993 assign_stmt = gimple_build_assign (endvar, e);
8994 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8995 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
8996 assign_stmt = gimple_build_assign (fd->loop.v, e);
8997 else
8998 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
8999 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9000 }
9001 /* Handle linear clause adjustments. */
9002 tree itercnt = NULL_TREE;
9003 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9004 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9005 c; c = OMP_CLAUSE_CHAIN (c))
9006 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9007 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9008 {
9009 tree d = OMP_CLAUSE_DECL (c);
9010 bool is_ref = is_reference (d);
9011 tree t = d, a, dest;
9012 if (is_ref)
9013 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9014 if (itercnt == NULL_TREE)
9015 {
9016 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9017 {
9018 itercnt = fold_build2 (MINUS_EXPR, itype,
9019 fold_convert (itype, n1),
9020 fold_convert (itype, fd->loop.n1));
9021 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9022 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9023 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9024 NULL_TREE, false,
9025 GSI_CONTINUE_LINKING);
9026 }
9027 else
9028 itercnt = s0;
9029 }
9030 tree type = TREE_TYPE (t);
9031 if (POINTER_TYPE_P (type))
9032 type = sizetype;
9033 a = fold_build2 (MULT_EXPR, type,
9034 fold_convert (type, itercnt),
9035 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9036 dest = unshare_expr (t);
9037 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9038 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9039 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9040 false, GSI_CONTINUE_LINKING);
9041 assign_stmt = gimple_build_assign (dest, t);
9042 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9043 }
9044 if (fd->collapse > 1)
9045 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9046
9047 if (!broken_loop)
9048 {
9049 /* The code controlling the sequential loop replaces the
9050 GIMPLE_OMP_CONTINUE. */
9051 gsi = gsi_last_bb (cont_bb);
9052 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9053 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9054 vmain = gimple_omp_continue_control_use (cont_stmt);
9055 vback = gimple_omp_continue_control_def (cont_stmt);
9056
9057 if (!gimple_omp_for_combined_p (fd->for_stmt))
9058 {
9059 if (POINTER_TYPE_P (type))
9060 t = fold_build_pointer_plus (vmain, step);
9061 else
9062 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9063 t = force_gimple_operand_gsi (&gsi, t,
9064 DECL_P (vback)
9065 && TREE_ADDRESSABLE (vback),
9066 NULL_TREE, true, GSI_SAME_STMT);
9067 assign_stmt = gimple_build_assign (vback, t);
9068 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9069
9070 t = build2 (fd->loop.cond_code, boolean_type_node,
9071 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9072 ? t : vback, e);
9073 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9074 }
9075
9076 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9077 gsi_remove (&gsi, true);
9078
9079 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9080 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9081 }
9082
9083 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9084 gsi = gsi_last_bb (exit_bb);
9085 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9086 {
9087 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9088 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9089 }
9090 gsi_remove (&gsi, true);
9091
9092 /* Connect all the blocks. */
9093 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9094 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9095 ep = find_edge (entry_bb, second_bb);
9096 ep->flags = EDGE_TRUE_VALUE;
9097 ep->probability = REG_BR_PROB_BASE / 4;
9098 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9099 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9100
9101 if (!broken_loop)
9102 {
9103 ep = find_edge (cont_bb, body_bb);
9104 if (ep == NULL)
9105 {
9106 ep = BRANCH_EDGE (cont_bb);
9107 gcc_assert (single_succ (ep->dest) == body_bb);
9108 }
9109 if (gimple_omp_for_combined_p (fd->for_stmt))
9110 {
9111 remove_edge (ep);
9112 ep = NULL;
9113 }
9114 else if (fd->collapse > 1)
9115 {
9116 remove_edge (ep);
9117 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9118 }
9119 else
9120 ep->flags = EDGE_TRUE_VALUE;
9121 find_edge (cont_bb, fin_bb)->flags
9122 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9123 }
9124
9125 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9126 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9127 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9128
9129 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9130 recompute_dominator (CDI_DOMINATORS, body_bb));
9131 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9132 recompute_dominator (CDI_DOMINATORS, fin_bb));
9133
9134 struct loop *loop = body_bb->loop_father;
9135 if (loop != entry_bb->loop_father)
9136 {
9137 gcc_assert (loop->header == body_bb);
9138 gcc_assert (broken_loop
9139 || loop->latch == region->cont
9140 || single_pred (loop->latch) == region->cont);
9141 return;
9142 }
9143
9144 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9145 {
9146 loop = alloc_loop ();
9147 loop->header = body_bb;
9148 if (collapse_bb == NULL)
9149 loop->latch = cont_bb;
9150 add_loop (loop, body_bb->loop_father);
9151 }
9152 }
9153
9154 /* Return phi in E->DEST with ARG on edge E. */
9155
9156 static gphi *
9157 find_phi_with_arg_on_edge (tree arg, edge e)
9158 {
9159 basic_block bb = e->dest;
9160
9161 for (gphi_iterator gpi = gsi_start_phis (bb);
9162 !gsi_end_p (gpi);
9163 gsi_next (&gpi))
9164 {
9165 gphi *phi = gpi.phi ();
9166 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9167 return phi;
9168 }
9169
9170 return NULL;
9171 }
9172
9173 /* A subroutine of expand_omp_for. Generate code for a parallel
9174 loop with static schedule and a specified chunk size. Given
9175 parameters:
9176
9177 for (V = N1; V cond N2; V += STEP) BODY;
9178
9179 where COND is "<" or ">", we generate pseudocode
9180
9181 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9182 if (cond is <)
9183 adj = STEP - 1;
9184 else
9185 adj = STEP + 1;
9186 if ((__typeof (V)) -1 > 0 && cond is >)
9187 n = -(adj + N2 - N1) / -STEP;
9188 else
9189 n = (adj + N2 - N1) / STEP;
9190 trip = 0;
9191 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9192 here so that V is defined
9193 if the loop is not entered
9194 L0:
9195 s0 = (trip * nthreads + threadid) * CHUNK;
9196 e0 = min(s0 + CHUNK, n);
9197 if (s0 < n) goto L1; else goto L4;
9198 L1:
9199 V = s0 * STEP + N1;
9200 e = e0 * STEP + N1;
9201 L2:
9202 BODY;
9203 V += STEP;
9204 if (V cond e) goto L2; else goto L3;
9205 L3:
9206 trip += 1;
9207 goto L0;
9208 L4:
9209 */
9210
9211 static void
9212 expand_omp_for_static_chunk (struct omp_region *region,
9213 struct omp_for_data *fd, gimple *inner_stmt)
9214 {
9215 tree n, s0, e0, e, t;
9216 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9217 tree type, itype, vmain, vback, vextra;
9218 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9219 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9220 gimple_stmt_iterator gsi;
9221 edge se;
9222 bool broken_loop = region->cont == NULL;
9223 tree *counts = NULL;
9224 tree n1, n2, step;
9225
9226 itype = type = TREE_TYPE (fd->loop.v);
9227 if (POINTER_TYPE_P (type))
9228 itype = signed_type_for (type);
9229
9230 entry_bb = region->entry;
9231 se = split_block (entry_bb, last_stmt (entry_bb));
9232 entry_bb = se->src;
9233 iter_part_bb = se->dest;
9234 cont_bb = region->cont;
9235 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9236 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9237 gcc_assert (broken_loop
9238 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9239 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9240 body_bb = single_succ (seq_start_bb);
9241 if (!broken_loop)
9242 {
9243 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9244 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9245 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9246 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9247 }
9248 exit_bb = region->exit;
9249
9250 /* Trip and adjustment setup goes in ENTRY_BB. */
9251 gsi = gsi_last_bb (entry_bb);
9252 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9253
9254 if (fd->collapse > 1)
9255 {
9256 int first_zero_iter = -1, dummy = -1;
9257 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9258
9259 counts = XALLOCAVEC (tree, fd->collapse);
9260 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9261 fin_bb, first_zero_iter,
9262 dummy_bb, dummy, l2_dom_bb);
9263 t = NULL_TREE;
9264 }
9265 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9266 t = integer_one_node;
9267 else
9268 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9269 fold_convert (type, fd->loop.n1),
9270 fold_convert (type, fd->loop.n2));
9271 if (fd->collapse == 1
9272 && TYPE_UNSIGNED (type)
9273 && (t == NULL_TREE || !integer_onep (t)))
9274 {
9275 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9276 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9277 true, GSI_SAME_STMT);
9278 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9279 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9280 true, GSI_SAME_STMT);
9281 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9282 NULL_TREE, NULL_TREE);
9283 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9284 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9285 expand_omp_regimplify_p, NULL, NULL)
9286 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9287 expand_omp_regimplify_p, NULL, NULL))
9288 {
9289 gsi = gsi_for_stmt (cond_stmt);
9290 gimple_regimplify_operands (cond_stmt, &gsi);
9291 }
9292 se = split_block (entry_bb, cond_stmt);
9293 se->flags = EDGE_TRUE_VALUE;
9294 entry_bb = se->dest;
9295 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9296 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9297 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9298 if (gimple_in_ssa_p (cfun))
9299 {
9300 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9301 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9302 !gsi_end_p (gpi); gsi_next (&gpi))
9303 {
9304 gphi *phi = gpi.phi ();
9305 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9306 se, UNKNOWN_LOCATION);
9307 }
9308 }
9309 gsi = gsi_last_bb (entry_bb);
9310 }
9311
9312 switch (gimple_omp_for_kind (fd->for_stmt))
9313 {
9314 case GF_OMP_FOR_KIND_FOR:
9315 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9316 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9317 break;
9318 case GF_OMP_FOR_KIND_DISTRIBUTE:
9319 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9320 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9321 break;
9322 default:
9323 gcc_unreachable ();
9324 }
9325 nthreads = build_call_expr (nthreads, 0);
9326 nthreads = fold_convert (itype, nthreads);
9327 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9328 true, GSI_SAME_STMT);
9329 threadid = build_call_expr (threadid, 0);
9330 threadid = fold_convert (itype, threadid);
9331 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9332 true, GSI_SAME_STMT);
9333
9334 n1 = fd->loop.n1;
9335 n2 = fd->loop.n2;
9336 step = fd->loop.step;
9337 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9338 {
9339 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9340 OMP_CLAUSE__LOOPTEMP_);
9341 gcc_assert (innerc);
9342 n1 = OMP_CLAUSE_DECL (innerc);
9343 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9344 OMP_CLAUSE__LOOPTEMP_);
9345 gcc_assert (innerc);
9346 n2 = OMP_CLAUSE_DECL (innerc);
9347 }
9348 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9349 true, NULL_TREE, true, GSI_SAME_STMT);
9350 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9351 true, NULL_TREE, true, GSI_SAME_STMT);
9352 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9353 true, NULL_TREE, true, GSI_SAME_STMT);
9354 tree chunk_size = fold_convert (itype, fd->chunk_size);
9355 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9356 chunk_size
9357 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9358 GSI_SAME_STMT);
9359
9360 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9361 t = fold_build2 (PLUS_EXPR, itype, step, t);
9362 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9363 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9364 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9365 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9366 fold_build1 (NEGATE_EXPR, itype, t),
9367 fold_build1 (NEGATE_EXPR, itype, step));
9368 else
9369 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9370 t = fold_convert (itype, t);
9371 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9372 true, GSI_SAME_STMT);
9373
9374 trip_var = create_tmp_reg (itype, ".trip");
9375 if (gimple_in_ssa_p (cfun))
9376 {
9377 trip_init = make_ssa_name (trip_var);
9378 trip_main = make_ssa_name (trip_var);
9379 trip_back = make_ssa_name (trip_var);
9380 }
9381 else
9382 {
9383 trip_init = trip_var;
9384 trip_main = trip_var;
9385 trip_back = trip_var;
9386 }
9387
9388 gassign *assign_stmt
9389 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9390 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9391
9392 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9393 t = fold_build2 (MULT_EXPR, itype, t, step);
9394 if (POINTER_TYPE_P (type))
9395 t = fold_build_pointer_plus (n1, t);
9396 else
9397 t = fold_build2 (PLUS_EXPR, type, t, n1);
9398 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9399 true, GSI_SAME_STMT);
9400
9401 /* Remove the GIMPLE_OMP_FOR. */
9402 gsi_remove (&gsi, true);
9403
9404 gimple_stmt_iterator gsif = gsi;
9405
9406 /* Iteration space partitioning goes in ITER_PART_BB. */
9407 gsi = gsi_last_bb (iter_part_bb);
9408
9409 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9410 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9411 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9412 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9413 false, GSI_CONTINUE_LINKING);
9414
9415 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9416 t = fold_build2 (MIN_EXPR, itype, t, n);
9417 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9418 false, GSI_CONTINUE_LINKING);
9419
9420 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9421 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9422
9423 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9424 gsi = gsi_start_bb (seq_start_bb);
9425
9426 tree startvar = fd->loop.v;
9427 tree endvar = NULL_TREE;
9428
9429 if (gimple_omp_for_combined_p (fd->for_stmt))
9430 {
9431 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9432 ? gimple_omp_parallel_clauses (inner_stmt)
9433 : gimple_omp_for_clauses (inner_stmt);
9434 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9435 gcc_assert (innerc);
9436 startvar = OMP_CLAUSE_DECL (innerc);
9437 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9438 OMP_CLAUSE__LOOPTEMP_);
9439 gcc_assert (innerc);
9440 endvar = OMP_CLAUSE_DECL (innerc);
9441 }
9442
9443 t = fold_convert (itype, s0);
9444 t = fold_build2 (MULT_EXPR, itype, t, step);
9445 if (POINTER_TYPE_P (type))
9446 t = fold_build_pointer_plus (n1, t);
9447 else
9448 t = fold_build2 (PLUS_EXPR, type, t, n1);
9449 t = fold_convert (TREE_TYPE (startvar), t);
9450 t = force_gimple_operand_gsi (&gsi, t,
9451 DECL_P (startvar)
9452 && TREE_ADDRESSABLE (startvar),
9453 NULL_TREE, false, GSI_CONTINUE_LINKING);
9454 assign_stmt = gimple_build_assign (startvar, t);
9455 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9456
9457 t = fold_convert (itype, e0);
9458 t = fold_build2 (MULT_EXPR, itype, t, step);
9459 if (POINTER_TYPE_P (type))
9460 t = fold_build_pointer_plus (n1, t);
9461 else
9462 t = fold_build2 (PLUS_EXPR, type, t, n1);
9463 t = fold_convert (TREE_TYPE (startvar), t);
9464 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9465 false, GSI_CONTINUE_LINKING);
9466 if (endvar)
9467 {
9468 assign_stmt = gimple_build_assign (endvar, e);
9469 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9470 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9471 assign_stmt = gimple_build_assign (fd->loop.v, e);
9472 else
9473 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9474 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9475 }
9476 /* Handle linear clause adjustments. */
9477 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9478 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9479 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9480 c; c = OMP_CLAUSE_CHAIN (c))
9481 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9482 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9483 {
9484 tree d = OMP_CLAUSE_DECL (c);
9485 bool is_ref = is_reference (d);
9486 tree t = d, a, dest;
9487 if (is_ref)
9488 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9489 tree type = TREE_TYPE (t);
9490 if (POINTER_TYPE_P (type))
9491 type = sizetype;
9492 dest = unshare_expr (t);
9493 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9494 expand_omp_build_assign (&gsif, v, t);
9495 if (itercnt == NULL_TREE)
9496 {
9497 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9498 {
9499 itercntbias
9500 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9501 fold_convert (itype, fd->loop.n1));
9502 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9503 itercntbias, step);
9504 itercntbias
9505 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9506 NULL_TREE, true,
9507 GSI_SAME_STMT);
9508 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9509 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9510 NULL_TREE, false,
9511 GSI_CONTINUE_LINKING);
9512 }
9513 else
9514 itercnt = s0;
9515 }
9516 a = fold_build2 (MULT_EXPR, type,
9517 fold_convert (type, itercnt),
9518 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9519 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9520 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9521 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9522 false, GSI_CONTINUE_LINKING);
9523 assign_stmt = gimple_build_assign (dest, t);
9524 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9525 }
9526 if (fd->collapse > 1)
9527 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9528
9529 if (!broken_loop)
9530 {
9531 /* The code controlling the sequential loop goes in CONT_BB,
9532 replacing the GIMPLE_OMP_CONTINUE. */
9533 gsi = gsi_last_bb (cont_bb);
9534 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9535 vmain = gimple_omp_continue_control_use (cont_stmt);
9536 vback = gimple_omp_continue_control_def (cont_stmt);
9537
9538 if (!gimple_omp_for_combined_p (fd->for_stmt))
9539 {
9540 if (POINTER_TYPE_P (type))
9541 t = fold_build_pointer_plus (vmain, step);
9542 else
9543 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9544 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9545 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9546 true, GSI_SAME_STMT);
9547 assign_stmt = gimple_build_assign (vback, t);
9548 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9549
9550 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9551 t = build2 (EQ_EXPR, boolean_type_node,
9552 build_int_cst (itype, 0),
9553 build_int_cst (itype, 1));
9554 else
9555 t = build2 (fd->loop.cond_code, boolean_type_node,
9556 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9557 ? t : vback, e);
9558 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9559 }
9560
9561 /* Remove GIMPLE_OMP_CONTINUE. */
9562 gsi_remove (&gsi, true);
9563
9564 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9565 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9566
9567 /* Trip update code goes into TRIP_UPDATE_BB. */
9568 gsi = gsi_start_bb (trip_update_bb);
9569
9570 t = build_int_cst (itype, 1);
9571 t = build2 (PLUS_EXPR, itype, trip_main, t);
9572 assign_stmt = gimple_build_assign (trip_back, t);
9573 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9574 }
9575
9576 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9577 gsi = gsi_last_bb (exit_bb);
9578 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9579 {
9580 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9581 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9582 }
9583 gsi_remove (&gsi, true);
9584
9585 /* Connect the new blocks. */
9586 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9587 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
9588
9589 if (!broken_loop)
9590 {
9591 se = find_edge (cont_bb, body_bb);
9592 if (se == NULL)
9593 {
9594 se = BRANCH_EDGE (cont_bb);
9595 gcc_assert (single_succ (se->dest) == body_bb);
9596 }
9597 if (gimple_omp_for_combined_p (fd->for_stmt))
9598 {
9599 remove_edge (se);
9600 se = NULL;
9601 }
9602 else if (fd->collapse > 1)
9603 {
9604 remove_edge (se);
9605 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9606 }
9607 else
9608 se->flags = EDGE_TRUE_VALUE;
9609 find_edge (cont_bb, trip_update_bb)->flags
9610 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9611
9612 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9613 }
9614
9615 if (gimple_in_ssa_p (cfun))
9616 {
9617 gphi_iterator psi;
9618 gphi *phi;
9619 edge re, ene;
9620 edge_var_map *vm;
9621 size_t i;
9622
9623 gcc_assert (fd->collapse == 1 && !broken_loop);
9624
9625 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9626 remove arguments of the phi nodes in fin_bb. We need to create
9627 appropriate phi nodes in iter_part_bb instead. */
9628 se = find_edge (iter_part_bb, fin_bb);
9629 re = single_succ_edge (trip_update_bb);
9630 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
9631 ene = single_succ_edge (entry_bb);
9632
9633 psi = gsi_start_phis (fin_bb);
9634 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
9635 gsi_next (&psi), ++i)
9636 {
9637 gphi *nphi;
9638 source_location locus;
9639
9640 phi = psi.phi ();
9641 t = gimple_phi_result (phi);
9642 gcc_assert (t == redirect_edge_var_map_result (vm));
9643
9644 if (!single_pred_p (fin_bb))
9645 t = copy_ssa_name (t, phi);
9646
9647 nphi = create_phi_node (t, iter_part_bb);
9648
9649 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
9650 locus = gimple_phi_arg_location_from_edge (phi, se);
9651
9652 /* A special case -- fd->loop.v is not yet computed in
9653 iter_part_bb, we need to use vextra instead. */
9654 if (t == fd->loop.v)
9655 t = vextra;
9656 add_phi_arg (nphi, t, ene, locus);
9657 locus = redirect_edge_var_map_location (vm);
9658 tree back_arg = redirect_edge_var_map_def (vm);
9659 add_phi_arg (nphi, back_arg, re, locus);
9660 edge ce = find_edge (cont_bb, body_bb);
9661 if (ce == NULL)
9662 {
9663 ce = BRANCH_EDGE (cont_bb);
9664 gcc_assert (single_succ (ce->dest) == body_bb);
9665 ce = single_succ_edge (ce->dest);
9666 }
9667 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
9668 gcc_assert (inner_loop_phi != NULL);
9669 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
9670 find_edge (seq_start_bb, body_bb), locus);
9671
9672 if (!single_pred_p (fin_bb))
9673 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
9674 }
9675 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
9676 redirect_edge_var_map_clear (re);
9677 if (single_pred_p (fin_bb))
9678 while (1)
9679 {
9680 psi = gsi_start_phis (fin_bb);
9681 if (gsi_end_p (psi))
9682 break;
9683 remove_phi_node (&psi, false);
9684 }
9685
9686 /* Make phi node for trip. */
9687 phi = create_phi_node (trip_main, iter_part_bb);
9688 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
9689 UNKNOWN_LOCATION);
9690 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
9691 UNKNOWN_LOCATION);
9692 }
9693
9694 if (!broken_loop)
9695 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
9696 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
9697 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
9698 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9699 recompute_dominator (CDI_DOMINATORS, fin_bb));
9700 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
9701 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
9702 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9703 recompute_dominator (CDI_DOMINATORS, body_bb));
9704
9705 if (!broken_loop)
9706 {
9707 struct loop *loop = body_bb->loop_father;
9708 struct loop *trip_loop = alloc_loop ();
9709 trip_loop->header = iter_part_bb;
9710 trip_loop->latch = trip_update_bb;
9711 add_loop (trip_loop, iter_part_bb->loop_father);
9712
9713 if (loop != entry_bb->loop_father)
9714 {
9715 gcc_assert (loop->header == body_bb);
9716 gcc_assert (loop->latch == region->cont
9717 || single_pred (loop->latch) == region->cont);
9718 trip_loop->inner = loop;
9719 return;
9720 }
9721
9722 if (!gimple_omp_for_combined_p (fd->for_stmt))
9723 {
9724 loop = alloc_loop ();
9725 loop->header = body_bb;
9726 if (collapse_bb == NULL)
9727 loop->latch = cont_bb;
9728 add_loop (loop, trip_loop);
9729 }
9730 }
9731 }
9732
9733 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
9734 Given parameters:
9735 for (V = N1; V cond N2; V += STEP) BODY;
9736
9737 where COND is "<" or ">" or "!=", we generate pseudocode
9738
9739 for (ind_var = low; ind_var < high; ind_var++)
9740 {
9741 V = n1 + (ind_var * STEP)
9742
9743 <BODY>
9744 }
9745
9746 In the above pseudocode, low and high are function parameters of the
9747 child function. In the function below, we are inserting a temp.
9748 variable that will be making a call to two OMP functions that will not be
9749 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
9750 with _Cilk_for). These functions are replaced with low and high
9751 by the function that handles taskreg. */
9752
9753
9754 static void
9755 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
9756 {
9757 bool broken_loop = region->cont == NULL;
9758 basic_block entry_bb = region->entry;
9759 basic_block cont_bb = region->cont;
9760
9761 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9762 gcc_assert (broken_loop
9763 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
9764 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
9765 basic_block l1_bb, l2_bb;
9766
9767 if (!broken_loop)
9768 {
9769 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
9770 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9771 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
9772 l2_bb = BRANCH_EDGE (entry_bb)->dest;
9773 }
9774 else
9775 {
9776 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
9777 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
9778 l2_bb = single_succ (l1_bb);
9779 }
9780 basic_block exit_bb = region->exit;
9781 basic_block l2_dom_bb = NULL;
9782
9783 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
9784
9785 /* Below statements until the "tree high_val = ..." are pseudo statements
9786 used to pass information to be used by expand_omp_taskreg.
9787 low_val and high_val will be replaced by the __low and __high
9788 parameter from the child function.
9789
9790 The call_exprs part is a place-holder, it is mainly used
9791 to distinctly identify to the top-level part that this is
9792 where we should put low and high (reasoning given in header
9793 comment). */
9794
9795 tree child_fndecl
9796 = gimple_omp_parallel_child_fn (
9797 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
9798 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
9799 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
9800 {
9801 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
9802 high_val = t;
9803 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
9804 low_val = t;
9805 }
9806 gcc_assert (low_val && high_val);
9807
9808 tree type = TREE_TYPE (low_val);
9809 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
9810 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9811
9812 /* Not needed in SSA form right now. */
9813 gcc_assert (!gimple_in_ssa_p (cfun));
9814 if (l2_dom_bb == NULL)
9815 l2_dom_bb = l1_bb;
9816
9817 tree n1 = low_val;
9818 tree n2 = high_val;
9819
9820 gimple *stmt = gimple_build_assign (ind_var, n1);
9821
9822 /* Replace the GIMPLE_OMP_FOR statement. */
9823 gsi_replace (&gsi, stmt, true);
9824
9825 if (!broken_loop)
9826 {
9827 /* Code to control the increment goes in the CONT_BB. */
9828 gsi = gsi_last_bb (cont_bb);
9829 stmt = gsi_stmt (gsi);
9830 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
9831 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
9832 build_one_cst (type));
9833
9834 /* Replace GIMPLE_OMP_CONTINUE. */
9835 gsi_replace (&gsi, stmt, true);
9836 }
9837
9838 /* Emit the condition in L1_BB. */
9839 gsi = gsi_after_labels (l1_bb);
9840 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
9841 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
9842 fd->loop.step);
9843 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
9844 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
9845 fd->loop.n1, fold_convert (sizetype, t));
9846 else
9847 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
9848 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
9849 t = fold_convert (TREE_TYPE (fd->loop.v), t);
9850 expand_omp_build_assign (&gsi, fd->loop.v, t);
9851
9852 /* The condition is always '<' since the runtime will fill in the low
9853 and high values. */
9854 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
9855 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
9856
9857 /* Remove GIMPLE_OMP_RETURN. */
9858 gsi = gsi_last_bb (exit_bb);
9859 gsi_remove (&gsi, true);
9860
9861 /* Connect the new blocks. */
9862 remove_edge (FALLTHRU_EDGE (entry_bb));
9863
9864 edge e, ne;
9865 if (!broken_loop)
9866 {
9867 remove_edge (BRANCH_EDGE (entry_bb));
9868 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
9869
9870 e = BRANCH_EDGE (l1_bb);
9871 ne = FALLTHRU_EDGE (l1_bb);
9872 e->flags = EDGE_TRUE_VALUE;
9873 }
9874 else
9875 {
9876 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9877
9878 ne = single_succ_edge (l1_bb);
9879 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
9880
9881 }
9882 ne->flags = EDGE_FALSE_VALUE;
9883 e->probability = REG_BR_PROB_BASE * 7 / 8;
9884 ne->probability = REG_BR_PROB_BASE / 8;
9885
9886 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
9887 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
9888 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
9889
9890 if (!broken_loop)
9891 {
9892 struct loop *loop = alloc_loop ();
9893 loop->header = l1_bb;
9894 loop->latch = cont_bb;
9895 add_loop (loop, l1_bb->loop_father);
9896 loop->safelen = INT_MAX;
9897 }
9898
9899 /* Pick the correct library function based on the precision of the
9900 induction variable type. */
9901 tree lib_fun = NULL_TREE;
9902 if (TYPE_PRECISION (type) == 32)
9903 lib_fun = cilk_for_32_fndecl;
9904 else if (TYPE_PRECISION (type) == 64)
9905 lib_fun = cilk_for_64_fndecl;
9906 else
9907 gcc_unreachable ();
9908
9909 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
9910
9911 /* WS_ARGS contains the library function flavor to call:
9912 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
9913 user-defined grain value. If the user does not define one, then zero
9914 is passed in by the parser. */
9915 vec_alloc (region->ws_args, 2);
9916 region->ws_args->quick_push (lib_fun);
9917 region->ws_args->quick_push (fd->chunk_size);
9918 }
9919
9920 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
9921 loop. Given parameters:
9922
9923 for (V = N1; V cond N2; V += STEP) BODY;
9924
9925 where COND is "<" or ">", we generate pseudocode
9926
9927 V = N1;
9928 goto L1;
9929 L0:
9930 BODY;
9931 V += STEP;
9932 L1:
9933 if (V cond N2) goto L0; else goto L2;
9934 L2:
9935
9936 For collapsed loops, given parameters:
9937 collapse(3)
9938 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
9939 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
9940 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
9941 BODY;
9942
9943 we generate pseudocode
9944
9945 if (cond3 is <)
9946 adj = STEP3 - 1;
9947 else
9948 adj = STEP3 + 1;
9949 count3 = (adj + N32 - N31) / STEP3;
9950 if (cond2 is <)
9951 adj = STEP2 - 1;
9952 else
9953 adj = STEP2 + 1;
9954 count2 = (adj + N22 - N21) / STEP2;
9955 if (cond1 is <)
9956 adj = STEP1 - 1;
9957 else
9958 adj = STEP1 + 1;
9959 count1 = (adj + N12 - N11) / STEP1;
9960 count = count1 * count2 * count3;
9961 V = 0;
9962 V1 = N11;
9963 V2 = N21;
9964 V3 = N31;
9965 goto L1;
9966 L0:
9967 BODY;
9968 V += 1;
9969 V3 += STEP3;
9970 V2 += (V3 cond3 N32) ? 0 : STEP2;
9971 V3 = (V3 cond3 N32) ? V3 : N31;
9972 V1 += (V2 cond2 N22) ? 0 : STEP1;
9973 V2 = (V2 cond2 N22) ? V2 : N21;
9974 L1:
9975 if (V < count) goto L0; else goto L2;
9976 L2:
9977
9978 */
9979
9980 static void
9981 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
9982 {
9983 tree type, t;
9984 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
9985 gimple_stmt_iterator gsi;
9986 gimple *stmt;
9987 gcond *cond_stmt;
9988 bool broken_loop = region->cont == NULL;
9989 edge e, ne;
9990 tree *counts = NULL;
9991 int i;
9992 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9993 OMP_CLAUSE_SAFELEN);
9994 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9995 OMP_CLAUSE__SIMDUID_);
9996 tree n1, n2;
9997
9998 type = TREE_TYPE (fd->loop.v);
9999 entry_bb = region->entry;
10000 cont_bb = region->cont;
10001 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10002 gcc_assert (broken_loop
10003 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10004 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10005 if (!broken_loop)
10006 {
10007 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10008 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10009 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10010 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10011 }
10012 else
10013 {
10014 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10015 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10016 l2_bb = single_succ (l1_bb);
10017 }
10018 exit_bb = region->exit;
10019 l2_dom_bb = NULL;
10020
10021 gsi = gsi_last_bb (entry_bb);
10022
10023 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10024 /* Not needed in SSA form right now. */
10025 gcc_assert (!gimple_in_ssa_p (cfun));
10026 if (fd->collapse > 1)
10027 {
10028 int first_zero_iter = -1, dummy = -1;
10029 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10030
10031 counts = XALLOCAVEC (tree, fd->collapse);
10032 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10033 zero_iter_bb, first_zero_iter,
10034 dummy_bb, dummy, l2_dom_bb);
10035 }
10036 if (l2_dom_bb == NULL)
10037 l2_dom_bb = l1_bb;
10038
10039 n1 = fd->loop.n1;
10040 n2 = fd->loop.n2;
10041 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10042 {
10043 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10044 OMP_CLAUSE__LOOPTEMP_);
10045 gcc_assert (innerc);
10046 n1 = OMP_CLAUSE_DECL (innerc);
10047 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10048 OMP_CLAUSE__LOOPTEMP_);
10049 gcc_assert (innerc);
10050 n2 = OMP_CLAUSE_DECL (innerc);
10051 expand_omp_build_assign (&gsi, fd->loop.v,
10052 fold_convert (type, n1));
10053 if (fd->collapse > 1)
10054 {
10055 gsi_prev (&gsi);
10056 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10057 gsi_next (&gsi);
10058 }
10059 }
10060 else
10061 {
10062 expand_omp_build_assign (&gsi, fd->loop.v,
10063 fold_convert (type, fd->loop.n1));
10064 if (fd->collapse > 1)
10065 for (i = 0; i < fd->collapse; i++)
10066 {
10067 tree itype = TREE_TYPE (fd->loops[i].v);
10068 if (POINTER_TYPE_P (itype))
10069 itype = signed_type_for (itype);
10070 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10071 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10072 }
10073 }
10074
10075 /* Remove the GIMPLE_OMP_FOR statement. */
10076 gsi_remove (&gsi, true);
10077
10078 if (!broken_loop)
10079 {
10080 /* Code to control the increment goes in the CONT_BB. */
10081 gsi = gsi_last_bb (cont_bb);
10082 stmt = gsi_stmt (gsi);
10083 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10084
10085 if (POINTER_TYPE_P (type))
10086 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10087 else
10088 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10089 expand_omp_build_assign (&gsi, fd->loop.v, t);
10090
10091 if (fd->collapse > 1)
10092 {
10093 i = fd->collapse - 1;
10094 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10095 {
10096 t = fold_convert (sizetype, fd->loops[i].step);
10097 t = fold_build_pointer_plus (fd->loops[i].v, t);
10098 }
10099 else
10100 {
10101 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10102 fd->loops[i].step);
10103 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10104 fd->loops[i].v, t);
10105 }
10106 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10107
10108 for (i = fd->collapse - 1; i > 0; i--)
10109 {
10110 tree itype = TREE_TYPE (fd->loops[i].v);
10111 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10112 if (POINTER_TYPE_P (itype2))
10113 itype2 = signed_type_for (itype2);
10114 t = build3 (COND_EXPR, itype2,
10115 build2 (fd->loops[i].cond_code, boolean_type_node,
10116 fd->loops[i].v,
10117 fold_convert (itype, fd->loops[i].n2)),
10118 build_int_cst (itype2, 0),
10119 fold_convert (itype2, fd->loops[i - 1].step));
10120 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10121 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10122 else
10123 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10124 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10125
10126 t = build3 (COND_EXPR, itype,
10127 build2 (fd->loops[i].cond_code, boolean_type_node,
10128 fd->loops[i].v,
10129 fold_convert (itype, fd->loops[i].n2)),
10130 fd->loops[i].v,
10131 fold_convert (itype, fd->loops[i].n1));
10132 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10133 }
10134 }
10135
10136 /* Remove GIMPLE_OMP_CONTINUE. */
10137 gsi_remove (&gsi, true);
10138 }
10139
10140 /* Emit the condition in L1_BB. */
10141 gsi = gsi_start_bb (l1_bb);
10142
10143 t = fold_convert (type, n2);
10144 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10145 false, GSI_CONTINUE_LINKING);
10146 tree v = fd->loop.v;
10147 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10148 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10149 false, GSI_CONTINUE_LINKING);
10150 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10151 cond_stmt = gimple_build_cond_empty (t);
10152 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10153 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10154 NULL, NULL)
10155 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10156 NULL, NULL))
10157 {
10158 gsi = gsi_for_stmt (cond_stmt);
10159 gimple_regimplify_operands (cond_stmt, &gsi);
10160 }
10161
10162 /* Remove GIMPLE_OMP_RETURN. */
10163 gsi = gsi_last_bb (exit_bb);
10164 gsi_remove (&gsi, true);
10165
10166 /* Connect the new blocks. */
10167 remove_edge (FALLTHRU_EDGE (entry_bb));
10168
10169 if (!broken_loop)
10170 {
10171 remove_edge (BRANCH_EDGE (entry_bb));
10172 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10173
10174 e = BRANCH_EDGE (l1_bb);
10175 ne = FALLTHRU_EDGE (l1_bb);
10176 e->flags = EDGE_TRUE_VALUE;
10177 }
10178 else
10179 {
10180 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10181
10182 ne = single_succ_edge (l1_bb);
10183 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10184
10185 }
10186 ne->flags = EDGE_FALSE_VALUE;
10187 e->probability = REG_BR_PROB_BASE * 7 / 8;
10188 ne->probability = REG_BR_PROB_BASE / 8;
10189
10190 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10191 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10192 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10193
10194 if (!broken_loop)
10195 {
10196 struct loop *loop = alloc_loop ();
10197 loop->header = l1_bb;
10198 loop->latch = cont_bb;
10199 add_loop (loop, l1_bb->loop_father);
10200 if (safelen == NULL_TREE)
10201 loop->safelen = INT_MAX;
10202 else
10203 {
10204 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10205 if (TREE_CODE (safelen) != INTEGER_CST)
10206 loop->safelen = 0;
10207 else if (!tree_fits_uhwi_p (safelen)
10208 || tree_to_uhwi (safelen) > INT_MAX)
10209 loop->safelen = INT_MAX;
10210 else
10211 loop->safelen = tree_to_uhwi (safelen);
10212 if (loop->safelen == 1)
10213 loop->safelen = 0;
10214 }
10215 if (simduid)
10216 {
10217 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10218 cfun->has_simduid_loops = true;
10219 }
10220 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10221 the loop. */
10222 if ((flag_tree_loop_vectorize
10223 || (!global_options_set.x_flag_tree_loop_vectorize
10224 && !global_options_set.x_flag_tree_vectorize))
10225 && flag_tree_loop_optimize
10226 && loop->safelen > 1)
10227 {
10228 loop->force_vectorize = true;
10229 cfun->has_force_vectorize_loops = true;
10230 }
10231 }
10232 else if (simduid)
10233 cfun->has_simduid_loops = true;
10234 }
10235
10236 /* Taskloop construct is represented after gimplification with
10237 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10238 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10239 which should just compute all the needed loop temporaries
10240 for GIMPLE_OMP_TASK. */
10241
10242 static void
10243 expand_omp_taskloop_for_outer (struct omp_region *region,
10244 struct omp_for_data *fd,
10245 gimple *inner_stmt)
10246 {
10247 tree type, bias = NULL_TREE;
10248 basic_block entry_bb, cont_bb, exit_bb;
10249 gimple_stmt_iterator gsi;
10250 gassign *assign_stmt;
10251 tree *counts = NULL;
10252 int i;
10253
10254 gcc_assert (inner_stmt);
10255 gcc_assert (region->cont);
10256 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10257 && gimple_omp_task_taskloop_p (inner_stmt));
10258 type = TREE_TYPE (fd->loop.v);
10259
10260 /* See if we need to bias by LLONG_MIN. */
10261 if (fd->iter_type == long_long_unsigned_type_node
10262 && TREE_CODE (type) == INTEGER_TYPE
10263 && !TYPE_UNSIGNED (type))
10264 {
10265 tree n1, n2;
10266
10267 if (fd->loop.cond_code == LT_EXPR)
10268 {
10269 n1 = fd->loop.n1;
10270 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10271 }
10272 else
10273 {
10274 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10275 n2 = fd->loop.n1;
10276 }
10277 if (TREE_CODE (n1) != INTEGER_CST
10278 || TREE_CODE (n2) != INTEGER_CST
10279 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10280 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10281 }
10282
10283 entry_bb = region->entry;
10284 cont_bb = region->cont;
10285 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10286 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10287 exit_bb = region->exit;
10288
10289 gsi = gsi_last_bb (entry_bb);
10290 gimple *for_stmt = gsi_stmt (gsi);
10291 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10292 if (fd->collapse > 1)
10293 {
10294 int first_zero_iter = -1, dummy = -1;
10295 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10296
10297 counts = XALLOCAVEC (tree, fd->collapse);
10298 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10299 zero_iter_bb, first_zero_iter,
10300 dummy_bb, dummy, l2_dom_bb);
10301
10302 if (zero_iter_bb)
10303 {
10304 /* Some counts[i] vars might be uninitialized if
10305 some loop has zero iterations. But the body shouldn't
10306 be executed in that case, so just avoid uninit warnings. */
10307 for (i = first_zero_iter; i < fd->collapse; i++)
10308 if (SSA_VAR_P (counts[i]))
10309 TREE_NO_WARNING (counts[i]) = 1;
10310 gsi_prev (&gsi);
10311 edge e = split_block (entry_bb, gsi_stmt (gsi));
10312 entry_bb = e->dest;
10313 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10314 gsi = gsi_last_bb (entry_bb);
10315 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10316 get_immediate_dominator (CDI_DOMINATORS,
10317 zero_iter_bb));
10318 }
10319 }
10320
10321 tree t0, t1;
10322 t1 = fd->loop.n2;
10323 t0 = fd->loop.n1;
10324 if (POINTER_TYPE_P (TREE_TYPE (t0))
10325 && TYPE_PRECISION (TREE_TYPE (t0))
10326 != TYPE_PRECISION (fd->iter_type))
10327 {
10328 /* Avoid casting pointers to integer of a different size. */
10329 tree itype = signed_type_for (type);
10330 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10331 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10332 }
10333 else
10334 {
10335 t1 = fold_convert (fd->iter_type, t1);
10336 t0 = fold_convert (fd->iter_type, t0);
10337 }
10338 if (bias)
10339 {
10340 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10341 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10342 }
10343
10344 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10345 OMP_CLAUSE__LOOPTEMP_);
10346 gcc_assert (innerc);
10347 tree startvar = OMP_CLAUSE_DECL (innerc);
10348 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10349 gcc_assert (innerc);
10350 tree endvar = OMP_CLAUSE_DECL (innerc);
10351 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10352 {
10353 gcc_assert (innerc);
10354 for (i = 1; i < fd->collapse; i++)
10355 {
10356 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10357 OMP_CLAUSE__LOOPTEMP_);
10358 gcc_assert (innerc);
10359 }
10360 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10361 OMP_CLAUSE__LOOPTEMP_);
10362 if (innerc)
10363 {
10364 /* If needed (inner taskloop has lastprivate clause), propagate
10365 down the total number of iterations. */
10366 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10367 NULL_TREE, false,
10368 GSI_CONTINUE_LINKING);
10369 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10370 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10371 }
10372 }
10373
10374 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10375 GSI_CONTINUE_LINKING);
10376 assign_stmt = gimple_build_assign (startvar, t0);
10377 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10378
10379 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10380 GSI_CONTINUE_LINKING);
10381 assign_stmt = gimple_build_assign (endvar, t1);
10382 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10383 if (fd->collapse > 1)
10384 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10385
10386 /* Remove the GIMPLE_OMP_FOR statement. */
10387 gsi = gsi_for_stmt (for_stmt);
10388 gsi_remove (&gsi, true);
10389
10390 gsi = gsi_last_bb (cont_bb);
10391 gsi_remove (&gsi, true);
10392
10393 gsi = gsi_last_bb (exit_bb);
10394 gsi_remove (&gsi, true);
10395
10396 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10397 remove_edge (BRANCH_EDGE (entry_bb));
10398 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10399 remove_edge (BRANCH_EDGE (cont_bb));
10400 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10401 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10402 recompute_dominator (CDI_DOMINATORS, region->entry));
10403 }
10404
10405 /* Taskloop construct is represented after gimplification with
10406 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10407 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10408 GOMP_taskloop{,_ull} function arranges for each task to be given just
10409 a single range of iterations. */
10410
10411 static void
10412 expand_omp_taskloop_for_inner (struct omp_region *region,
10413 struct omp_for_data *fd,
10414 gimple *inner_stmt)
10415 {
10416 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10417 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10418 basic_block fin_bb;
10419 gimple_stmt_iterator gsi;
10420 edge ep;
10421 bool broken_loop = region->cont == NULL;
10422 tree *counts = NULL;
10423 tree n1, n2, step;
10424
10425 itype = type = TREE_TYPE (fd->loop.v);
10426 if (POINTER_TYPE_P (type))
10427 itype = signed_type_for (type);
10428
10429 /* See if we need to bias by LLONG_MIN. */
10430 if (fd->iter_type == long_long_unsigned_type_node
10431 && TREE_CODE (type) == INTEGER_TYPE
10432 && !TYPE_UNSIGNED (type))
10433 {
10434 tree n1, n2;
10435
10436 if (fd->loop.cond_code == LT_EXPR)
10437 {
10438 n1 = fd->loop.n1;
10439 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10440 }
10441 else
10442 {
10443 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10444 n2 = fd->loop.n1;
10445 }
10446 if (TREE_CODE (n1) != INTEGER_CST
10447 || TREE_CODE (n2) != INTEGER_CST
10448 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10449 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10450 }
10451
10452 entry_bb = region->entry;
10453 cont_bb = region->cont;
10454 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10455 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10456 gcc_assert (broken_loop
10457 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10458 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10459 if (!broken_loop)
10460 {
10461 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10462 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10463 }
10464 exit_bb = region->exit;
10465
10466 /* Iteration space partitioning goes in ENTRY_BB. */
10467 gsi = gsi_last_bb (entry_bb);
10468 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10469
10470 if (fd->collapse > 1)
10471 {
10472 int first_zero_iter = -1, dummy = -1;
10473 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10474
10475 counts = XALLOCAVEC (tree, fd->collapse);
10476 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10477 fin_bb, first_zero_iter,
10478 dummy_bb, dummy, l2_dom_bb);
10479 t = NULL_TREE;
10480 }
10481 else
10482 t = integer_one_node;
10483
10484 step = fd->loop.step;
10485 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10486 OMP_CLAUSE__LOOPTEMP_);
10487 gcc_assert (innerc);
10488 n1 = OMP_CLAUSE_DECL (innerc);
10489 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10490 gcc_assert (innerc);
10491 n2 = OMP_CLAUSE_DECL (innerc);
10492 if (bias)
10493 {
10494 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10495 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10496 }
10497 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10498 true, NULL_TREE, true, GSI_SAME_STMT);
10499 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10500 true, NULL_TREE, true, GSI_SAME_STMT);
10501 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10502 true, NULL_TREE, true, GSI_SAME_STMT);
10503
10504 tree startvar = fd->loop.v;
10505 tree endvar = NULL_TREE;
10506
10507 if (gimple_omp_for_combined_p (fd->for_stmt))
10508 {
10509 tree clauses = gimple_omp_for_clauses (inner_stmt);
10510 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10511 gcc_assert (innerc);
10512 startvar = OMP_CLAUSE_DECL (innerc);
10513 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10514 OMP_CLAUSE__LOOPTEMP_);
10515 gcc_assert (innerc);
10516 endvar = OMP_CLAUSE_DECL (innerc);
10517 }
10518 t = fold_convert (TREE_TYPE (startvar), n1);
10519 t = force_gimple_operand_gsi (&gsi, t,
10520 DECL_P (startvar)
10521 && TREE_ADDRESSABLE (startvar),
10522 NULL_TREE, false, GSI_CONTINUE_LINKING);
10523 gimple *assign_stmt = gimple_build_assign (startvar, t);
10524 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10525
10526 t = fold_convert (TREE_TYPE (startvar), n2);
10527 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10528 false, GSI_CONTINUE_LINKING);
10529 if (endvar)
10530 {
10531 assign_stmt = gimple_build_assign (endvar, e);
10532 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10533 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10534 assign_stmt = gimple_build_assign (fd->loop.v, e);
10535 else
10536 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10537 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10538 }
10539 if (fd->collapse > 1)
10540 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10541
10542 if (!broken_loop)
10543 {
10544 /* The code controlling the sequential loop replaces the
10545 GIMPLE_OMP_CONTINUE. */
10546 gsi = gsi_last_bb (cont_bb);
10547 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10548 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10549 vmain = gimple_omp_continue_control_use (cont_stmt);
10550 vback = gimple_omp_continue_control_def (cont_stmt);
10551
10552 if (!gimple_omp_for_combined_p (fd->for_stmt))
10553 {
10554 if (POINTER_TYPE_P (type))
10555 t = fold_build_pointer_plus (vmain, step);
10556 else
10557 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10558 t = force_gimple_operand_gsi (&gsi, t,
10559 DECL_P (vback)
10560 && TREE_ADDRESSABLE (vback),
10561 NULL_TREE, true, GSI_SAME_STMT);
10562 assign_stmt = gimple_build_assign (vback, t);
10563 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10564
10565 t = build2 (fd->loop.cond_code, boolean_type_node,
10566 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10567 ? t : vback, e);
10568 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10569 }
10570
10571 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10572 gsi_remove (&gsi, true);
10573
10574 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10575 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10576 }
10577
10578 /* Remove the GIMPLE_OMP_FOR statement. */
10579 gsi = gsi_for_stmt (fd->for_stmt);
10580 gsi_remove (&gsi, true);
10581
10582 /* Remove the GIMPLE_OMP_RETURN statement. */
10583 gsi = gsi_last_bb (exit_bb);
10584 gsi_remove (&gsi, true);
10585
10586 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10587 if (!broken_loop)
10588 remove_edge (BRANCH_EDGE (entry_bb));
10589 else
10590 {
10591 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10592 region->outer->cont = NULL;
10593 }
10594
10595 /* Connect all the blocks. */
10596 if (!broken_loop)
10597 {
10598 ep = find_edge (cont_bb, body_bb);
10599 if (gimple_omp_for_combined_p (fd->for_stmt))
10600 {
10601 remove_edge (ep);
10602 ep = NULL;
10603 }
10604 else if (fd->collapse > 1)
10605 {
10606 remove_edge (ep);
10607 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10608 }
10609 else
10610 ep->flags = EDGE_TRUE_VALUE;
10611 find_edge (cont_bb, fin_bb)->flags
10612 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10613 }
10614
10615 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10616 recompute_dominator (CDI_DOMINATORS, body_bb));
10617 if (!broken_loop)
10618 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10619 recompute_dominator (CDI_DOMINATORS, fin_bb));
10620
10621 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10622 {
10623 struct loop *loop = alloc_loop ();
10624 loop->header = body_bb;
10625 if (collapse_bb == NULL)
10626 loop->latch = cont_bb;
10627 add_loop (loop, body_bb->loop_father);
10628 }
10629 }
10630
10631 /* A subroutine of expand_omp_for. Generate code for an OpenACC
10632 partitioned loop. The lowering here is abstracted, in that the
10633 loop parameters are passed through internal functions, which are
10634 further lowered by oacc_device_lower, once we get to the target
10635 compiler. The loop is of the form:
10636
10637 for (V = B; V LTGT E; V += S) {BODY}
10638
10639 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10640 (constant 0 for no chunking) and we will have a GWV partitioning
10641 mask, specifying dimensions over which the loop is to be
10642 partitioned (see note below). We generate code that looks like:
10643
10644 <entry_bb> [incoming FALL->body, BRANCH->exit]
10645 typedef signedintify (typeof (V)) T; // underlying signed integral type
10646 T range = E - B;
10647 T chunk_no = 0;
10648 T DIR = LTGT == '<' ? +1 : -1;
10649 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10650 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10651
10652 <head_bb> [created by splitting end of entry_bb]
10653 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10654 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10655 if (!(offset LTGT bound)) goto bottom_bb;
10656
10657 <body_bb> [incoming]
10658 V = B + offset;
10659 {BODY}
10660
10661 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
10662 offset += step;
10663 if (offset LTGT bound) goto body_bb; [*]
10664
10665 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
10666 chunk_no++;
10667 if (chunk < chunk_max) goto head_bb;
10668
10669 <exit_bb> [incoming]
10670 V = B + ((range -/+ 1) / S +/- 1) * S [*]
10671
10672 [*] Needed if V live at end of loop
10673
10674 Note: CHUNKING & GWV mask are specified explicitly here. This is a
10675 transition, and will be specified by a more general mechanism shortly.
10676 */
10677
10678 static void
10679 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
10680 {
10681 tree v = fd->loop.v;
10682 enum tree_code cond_code = fd->loop.cond_code;
10683 enum tree_code plus_code = PLUS_EXPR;
10684
10685 tree chunk_size = integer_minus_one_node;
10686 tree gwv = integer_zero_node;
10687 tree iter_type = TREE_TYPE (v);
10688 tree diff_type = iter_type;
10689 tree plus_type = iter_type;
10690 struct oacc_collapse *counts = NULL;
10691
10692 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
10693 == GF_OMP_FOR_KIND_OACC_LOOP);
10694 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
10695 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
10696
10697 if (POINTER_TYPE_P (iter_type))
10698 {
10699 plus_code = POINTER_PLUS_EXPR;
10700 plus_type = sizetype;
10701 }
10702 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
10703 diff_type = signed_type_for (diff_type);
10704
10705 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
10706 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
10707 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
10708 basic_block bottom_bb = NULL;
10709
10710 /* entry_bb has two sucessors; the branch edge is to the exit
10711 block, fallthrough edge to body. */
10712 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
10713 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
10714
10715 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
10716 body_bb, or to a block whose only successor is the body_bb. Its
10717 fallthrough successor is the final block (same as the branch
10718 successor of the entry_bb). */
10719 if (cont_bb)
10720 {
10721 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10722 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
10723
10724 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
10725 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
10726 }
10727 else
10728 gcc_assert (!gimple_in_ssa_p (cfun));
10729
10730 /* The exit block only has entry_bb and cont_bb as predecessors. */
10731 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
10732
10733 tree chunk_no;
10734 tree chunk_max = NULL_TREE;
10735 tree bound, offset;
10736 tree step = create_tmp_var (diff_type, ".step");
10737 bool up = cond_code == LT_EXPR;
10738 tree dir = build_int_cst (diff_type, up ? +1 : -1);
10739 bool chunking = !gimple_in_ssa_p (cfun);;
10740 bool negating;
10741
10742 /* SSA instances. */
10743 tree offset_incr = NULL_TREE;
10744 tree offset_init = NULL_TREE;
10745
10746 gimple_stmt_iterator gsi;
10747 gassign *ass;
10748 gcall *call;
10749 gimple *stmt;
10750 tree expr;
10751 location_t loc;
10752 edge split, be, fte;
10753
10754 /* Split the end of entry_bb to create head_bb. */
10755 split = split_block (entry_bb, last_stmt (entry_bb));
10756 basic_block head_bb = split->dest;
10757 entry_bb = split->src;
10758
10759 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
10760 gsi = gsi_last_bb (entry_bb);
10761 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
10762 loc = gimple_location (for_stmt);
10763
10764 if (gimple_in_ssa_p (cfun))
10765 {
10766 offset_init = gimple_omp_for_index (for_stmt, 0);
10767 gcc_assert (integer_zerop (fd->loop.n1));
10768 /* The SSA parallelizer does gang parallelism. */
10769 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
10770 }
10771
10772 if (fd->collapse > 1)
10773 {
10774 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
10775 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
10776 TREE_TYPE (fd->loop.n2));
10777
10778 if (SSA_VAR_P (fd->loop.n2))
10779 {
10780 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
10781 true, GSI_SAME_STMT);
10782 ass = gimple_build_assign (fd->loop.n2, total);
10783 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10784 }
10785
10786 }
10787
10788 tree b = fd->loop.n1;
10789 tree e = fd->loop.n2;
10790 tree s = fd->loop.step;
10791
10792 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
10793 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
10794
10795 /* Convert the step, avoiding possible unsigned->signed overflow. */
10796 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
10797 if (negating)
10798 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
10799 s = fold_convert (diff_type, s);
10800 if (negating)
10801 s = fold_build1 (NEGATE_EXPR, diff_type, s);
10802 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
10803
10804 if (!chunking)
10805 chunk_size = integer_zero_node;
10806 expr = fold_convert (diff_type, chunk_size);
10807 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
10808 NULL_TREE, true, GSI_SAME_STMT);
10809 /* Determine the range, avoiding possible unsigned->signed overflow. */
10810 negating = !up && TYPE_UNSIGNED (iter_type);
10811 expr = fold_build2 (MINUS_EXPR, plus_type,
10812 fold_convert (plus_type, negating ? b : e),
10813 fold_convert (plus_type, negating ? e : b));
10814 expr = fold_convert (diff_type, expr);
10815 if (negating)
10816 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
10817 tree range = force_gimple_operand_gsi (&gsi, expr, true,
10818 NULL_TREE, true, GSI_SAME_STMT);
10819
10820 chunk_no = build_int_cst (diff_type, 0);
10821 if (chunking)
10822 {
10823 gcc_assert (!gimple_in_ssa_p (cfun));
10824
10825 expr = chunk_no;
10826 chunk_max = create_tmp_var (diff_type, ".chunk_max");
10827 chunk_no = create_tmp_var (diff_type, ".chunk_no");
10828
10829 ass = gimple_build_assign (chunk_no, expr);
10830 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10831
10832 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
10833 build_int_cst (integer_type_node,
10834 IFN_GOACC_LOOP_CHUNKS),
10835 dir, range, s, chunk_size, gwv);
10836 gimple_call_set_lhs (call, chunk_max);
10837 gimple_set_location (call, loc);
10838 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
10839 }
10840 else
10841 chunk_size = chunk_no;
10842
10843 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
10844 build_int_cst (integer_type_node,
10845 IFN_GOACC_LOOP_STEP),
10846 dir, range, s, chunk_size, gwv);
10847 gimple_call_set_lhs (call, step);
10848 gimple_set_location (call, loc);
10849 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
10850
10851 /* Remove the GIMPLE_OMP_FOR. */
10852 gsi_remove (&gsi, true);
10853
10854 /* Fixup edges from head_bb */
10855 be = BRANCH_EDGE (head_bb);
10856 fte = FALLTHRU_EDGE (head_bb);
10857 be->flags |= EDGE_FALSE_VALUE;
10858 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
10859
10860 basic_block body_bb = fte->dest;
10861
10862 if (gimple_in_ssa_p (cfun))
10863 {
10864 gsi = gsi_last_bb (cont_bb);
10865 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10866
10867 offset = gimple_omp_continue_control_use (cont_stmt);
10868 offset_incr = gimple_omp_continue_control_def (cont_stmt);
10869 }
10870 else
10871 {
10872 offset = create_tmp_var (diff_type, ".offset");
10873 offset_init = offset_incr = offset;
10874 }
10875 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
10876
10877 /* Loop offset & bound go into head_bb. */
10878 gsi = gsi_start_bb (head_bb);
10879
10880 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
10881 build_int_cst (integer_type_node,
10882 IFN_GOACC_LOOP_OFFSET),
10883 dir, range, s,
10884 chunk_size, gwv, chunk_no);
10885 gimple_call_set_lhs (call, offset_init);
10886 gimple_set_location (call, loc);
10887 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
10888
10889 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
10890 build_int_cst (integer_type_node,
10891 IFN_GOACC_LOOP_BOUND),
10892 dir, range, s,
10893 chunk_size, gwv, offset_init);
10894 gimple_call_set_lhs (call, bound);
10895 gimple_set_location (call, loc);
10896 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
10897
10898 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
10899 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
10900 GSI_CONTINUE_LINKING);
10901
10902 /* V assignment goes into body_bb. */
10903 if (!gimple_in_ssa_p (cfun))
10904 {
10905 gsi = gsi_start_bb (body_bb);
10906
10907 expr = build2 (plus_code, iter_type, b,
10908 fold_convert (plus_type, offset));
10909 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
10910 true, GSI_SAME_STMT);
10911 ass = gimple_build_assign (v, expr);
10912 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10913 if (fd->collapse > 1)
10914 expand_oacc_collapse_vars (fd, &gsi, counts, v);
10915 }
10916
10917 /* Loop increment goes into cont_bb. If this is not a loop, we
10918 will have spawned threads as if it was, and each one will
10919 execute one iteration. The specification is not explicit about
10920 whether such constructs are ill-formed or not, and they can
10921 occur, especially when noreturn routines are involved. */
10922 if (cont_bb)
10923 {
10924 gsi = gsi_last_bb (cont_bb);
10925 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10926 loc = gimple_location (cont_stmt);
10927
10928 /* Increment offset. */
10929 if (gimple_in_ssa_p (cfun))
10930 expr= build2 (plus_code, iter_type, offset,
10931 fold_convert (plus_type, step));
10932 else
10933 expr = build2 (PLUS_EXPR, diff_type, offset, step);
10934 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
10935 true, GSI_SAME_STMT);
10936 ass = gimple_build_assign (offset_incr, expr);
10937 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10938 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
10939 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
10940
10941 /* Remove the GIMPLE_OMP_CONTINUE. */
10942 gsi_remove (&gsi, true);
10943
10944 /* Fixup edges from cont_bb */
10945 be = BRANCH_EDGE (cont_bb);
10946 fte = FALLTHRU_EDGE (cont_bb);
10947 be->flags |= EDGE_TRUE_VALUE;
10948 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
10949
10950 if (chunking)
10951 {
10952 /* Split the beginning of exit_bb to make bottom_bb. We
10953 need to insert a nop at the start, because splitting is
10954 after a stmt, not before. */
10955 gsi = gsi_start_bb (exit_bb);
10956 stmt = gimple_build_nop ();
10957 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10958 split = split_block (exit_bb, stmt);
10959 bottom_bb = split->src;
10960 exit_bb = split->dest;
10961 gsi = gsi_last_bb (bottom_bb);
10962
10963 /* Chunk increment and test goes into bottom_bb. */
10964 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
10965 build_int_cst (diff_type, 1));
10966 ass = gimple_build_assign (chunk_no, expr);
10967 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
10968
10969 /* Chunk test at end of bottom_bb. */
10970 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
10971 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
10972 GSI_CONTINUE_LINKING);
10973
10974 /* Fixup edges from bottom_bb. */
10975 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
10976 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
10977 }
10978 }
10979
10980 gsi = gsi_last_bb (exit_bb);
10981 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
10982 loc = gimple_location (gsi_stmt (gsi));
10983
10984 if (!gimple_in_ssa_p (cfun))
10985 {
10986 /* Insert the final value of V, in case it is live. This is the
10987 value for the only thread that survives past the join. */
10988 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
10989 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
10990 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
10991 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
10992 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
10993 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
10994 true, GSI_SAME_STMT);
10995 ass = gimple_build_assign (v, expr);
10996 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
10997 }
10998
10999 /* Remove the OMP_RETURN. */
11000 gsi_remove (&gsi, true);
11001
11002 if (cont_bb)
11003 {
11004 /* We now have one or two nested loops. Update the loop
11005 structures. */
11006 struct loop *parent = entry_bb->loop_father;
11007 struct loop *body = body_bb->loop_father;
11008
11009 if (chunking)
11010 {
11011 struct loop *chunk_loop = alloc_loop ();
11012 chunk_loop->header = head_bb;
11013 chunk_loop->latch = bottom_bb;
11014 add_loop (chunk_loop, parent);
11015 parent = chunk_loop;
11016 }
11017 else if (parent != body)
11018 {
11019 gcc_assert (body->header == body_bb);
11020 gcc_assert (body->latch == cont_bb
11021 || single_pred (body->latch) == cont_bb);
11022 parent = NULL;
11023 }
11024
11025 if (parent)
11026 {
11027 struct loop *body_loop = alloc_loop ();
11028 body_loop->header = body_bb;
11029 body_loop->latch = cont_bb;
11030 add_loop (body_loop, parent);
11031 }
11032 }
11033 }
11034
11035 /* Expand the OMP loop defined by REGION. */
11036
11037 static void
11038 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11039 {
11040 struct omp_for_data fd;
11041 struct omp_for_data_loop *loops;
11042
11043 loops
11044 = (struct omp_for_data_loop *)
11045 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11046 * sizeof (struct omp_for_data_loop));
11047 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11048 &fd, loops);
11049 region->sched_kind = fd.sched_kind;
11050
11051 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11052 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11053 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11054 if (region->cont)
11055 {
11056 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11057 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11058 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11059 }
11060 else
11061 /* If there isn't a continue then this is a degerate case where
11062 the introduction of abnormal edges during lowering will prevent
11063 original loops from being detected. Fix that up. */
11064 loops_state_set (LOOPS_NEED_FIXUP);
11065
11066 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11067 expand_omp_simd (region, &fd);
11068 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11069 expand_cilk_for (region, &fd);
11070 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11071 {
11072 gcc_assert (!inner_stmt);
11073 expand_oacc_for (region, &fd);
11074 }
11075 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11076 {
11077 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11078 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11079 else
11080 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11081 }
11082 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11083 && !fd.have_ordered)
11084 {
11085 if (fd.chunk_size == NULL)
11086 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11087 else
11088 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11089 }
11090 else
11091 {
11092 int fn_index, start_ix, next_ix;
11093
11094 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11095 == GF_OMP_FOR_KIND_FOR);
11096 if (fd.chunk_size == NULL
11097 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11098 fd.chunk_size = integer_zero_node;
11099 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11100 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
11101 ? 3 : fd.sched_kind;
11102 if (!fd.ordered)
11103 fn_index += fd.have_ordered * 4;
11104 if (fd.ordered)
11105 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11106 else
11107 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11108 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11109 if (fd.iter_type == long_long_unsigned_type_node)
11110 {
11111 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11112 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11113 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11114 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11115 }
11116 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11117 (enum built_in_function) next_ix, inner_stmt);
11118 }
11119
11120 if (gimple_in_ssa_p (cfun))
11121 update_ssa (TODO_update_ssa_only_virtuals);
11122 }
11123
11124
11125 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11126
11127 v = GOMP_sections_start (n);
11128 L0:
11129 switch (v)
11130 {
11131 case 0:
11132 goto L2;
11133 case 1:
11134 section 1;
11135 goto L1;
11136 case 2:
11137 ...
11138 case n:
11139 ...
11140 default:
11141 abort ();
11142 }
11143 L1:
11144 v = GOMP_sections_next ();
11145 goto L0;
11146 L2:
11147 reduction;
11148
11149 If this is a combined parallel sections, replace the call to
11150 GOMP_sections_start with call to GOMP_sections_next. */
11151
11152 static void
11153 expand_omp_sections (struct omp_region *region)
11154 {
11155 tree t, u, vin = NULL, vmain, vnext, l2;
11156 unsigned len;
11157 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11158 gimple_stmt_iterator si, switch_si;
11159 gomp_sections *sections_stmt;
11160 gimple *stmt;
11161 gomp_continue *cont;
11162 edge_iterator ei;
11163 edge e;
11164 struct omp_region *inner;
11165 unsigned i, casei;
11166 bool exit_reachable = region->cont != NULL;
11167
11168 gcc_assert (region->exit != NULL);
11169 entry_bb = region->entry;
11170 l0_bb = single_succ (entry_bb);
11171 l1_bb = region->cont;
11172 l2_bb = region->exit;
11173 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11174 l2 = gimple_block_label (l2_bb);
11175 else
11176 {
11177 /* This can happen if there are reductions. */
11178 len = EDGE_COUNT (l0_bb->succs);
11179 gcc_assert (len > 0);
11180 e = EDGE_SUCC (l0_bb, len - 1);
11181 si = gsi_last_bb (e->dest);
11182 l2 = NULL_TREE;
11183 if (gsi_end_p (si)
11184 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11185 l2 = gimple_block_label (e->dest);
11186 else
11187 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11188 {
11189 si = gsi_last_bb (e->dest);
11190 if (gsi_end_p (si)
11191 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11192 {
11193 l2 = gimple_block_label (e->dest);
11194 break;
11195 }
11196 }
11197 }
11198 if (exit_reachable)
11199 default_bb = create_empty_bb (l1_bb->prev_bb);
11200 else
11201 default_bb = create_empty_bb (l0_bb);
11202
11203 /* We will build a switch() with enough cases for all the
11204 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11205 and a default case to abort if something goes wrong. */
11206 len = EDGE_COUNT (l0_bb->succs);
11207
11208 /* Use vec::quick_push on label_vec throughout, since we know the size
11209 in advance. */
11210 auto_vec<tree> label_vec (len);
11211
11212 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11213 GIMPLE_OMP_SECTIONS statement. */
11214 si = gsi_last_bb (entry_bb);
11215 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11216 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11217 vin = gimple_omp_sections_control (sections_stmt);
11218 if (!is_combined_parallel (region))
11219 {
11220 /* If we are not inside a combined parallel+sections region,
11221 call GOMP_sections_start. */
11222 t = build_int_cst (unsigned_type_node, len - 1);
11223 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11224 stmt = gimple_build_call (u, 1, t);
11225 }
11226 else
11227 {
11228 /* Otherwise, call GOMP_sections_next. */
11229 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11230 stmt = gimple_build_call (u, 0);
11231 }
11232 gimple_call_set_lhs (stmt, vin);
11233 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11234 gsi_remove (&si, true);
11235
11236 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11237 L0_BB. */
11238 switch_si = gsi_last_bb (l0_bb);
11239 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11240 if (exit_reachable)
11241 {
11242 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11243 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11244 vmain = gimple_omp_continue_control_use (cont);
11245 vnext = gimple_omp_continue_control_def (cont);
11246 }
11247 else
11248 {
11249 vmain = vin;
11250 vnext = NULL_TREE;
11251 }
11252
11253 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11254 label_vec.quick_push (t);
11255 i = 1;
11256
11257 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11258 for (inner = region->inner, casei = 1;
11259 inner;
11260 inner = inner->next, i++, casei++)
11261 {
11262 basic_block s_entry_bb, s_exit_bb;
11263
11264 /* Skip optional reduction region. */
11265 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11266 {
11267 --i;
11268 --casei;
11269 continue;
11270 }
11271
11272 s_entry_bb = inner->entry;
11273 s_exit_bb = inner->exit;
11274
11275 t = gimple_block_label (s_entry_bb);
11276 u = build_int_cst (unsigned_type_node, casei);
11277 u = build_case_label (u, NULL, t);
11278 label_vec.quick_push (u);
11279
11280 si = gsi_last_bb (s_entry_bb);
11281 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11282 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11283 gsi_remove (&si, true);
11284 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11285
11286 if (s_exit_bb == NULL)
11287 continue;
11288
11289 si = gsi_last_bb (s_exit_bb);
11290 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11291 gsi_remove (&si, true);
11292
11293 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11294 }
11295
11296 /* Error handling code goes in DEFAULT_BB. */
11297 t = gimple_block_label (default_bb);
11298 u = build_case_label (NULL, NULL, t);
11299 make_edge (l0_bb, default_bb, 0);
11300 add_bb_to_loop (default_bb, current_loops->tree_root);
11301
11302 stmt = gimple_build_switch (vmain, u, label_vec);
11303 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11304 gsi_remove (&switch_si, true);
11305
11306 si = gsi_start_bb (default_bb);
11307 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11308 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11309
11310 if (exit_reachable)
11311 {
11312 tree bfn_decl;
11313
11314 /* Code to get the next section goes in L1_BB. */
11315 si = gsi_last_bb (l1_bb);
11316 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11317
11318 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11319 stmt = gimple_build_call (bfn_decl, 0);
11320 gimple_call_set_lhs (stmt, vnext);
11321 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11322 gsi_remove (&si, true);
11323
11324 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11325 }
11326
11327 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11328 si = gsi_last_bb (l2_bb);
11329 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11330 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11331 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11332 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11333 else
11334 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11335 stmt = gimple_build_call (t, 0);
11336 if (gimple_omp_return_lhs (gsi_stmt (si)))
11337 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11338 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11339 gsi_remove (&si, true);
11340
11341 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11342 }
11343
11344
11345 /* Expand code for an OpenMP single directive. We've already expanded
11346 much of the code, here we simply place the GOMP_barrier call. */
11347
11348 static void
11349 expand_omp_single (struct omp_region *region)
11350 {
11351 basic_block entry_bb, exit_bb;
11352 gimple_stmt_iterator si;
11353
11354 entry_bb = region->entry;
11355 exit_bb = region->exit;
11356
11357 si = gsi_last_bb (entry_bb);
11358 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11359 gsi_remove (&si, true);
11360 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11361
11362 si = gsi_last_bb (exit_bb);
11363 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11364 {
11365 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11366 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11367 }
11368 gsi_remove (&si, true);
11369 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11370 }
11371
11372
11373 /* Generic expansion for OpenMP synchronization directives: master,
11374 ordered and critical. All we need to do here is remove the entry
11375 and exit markers for REGION. */
11376
11377 static void
11378 expand_omp_synch (struct omp_region *region)
11379 {
11380 basic_block entry_bb, exit_bb;
11381 gimple_stmt_iterator si;
11382
11383 entry_bb = region->entry;
11384 exit_bb = region->exit;
11385
11386 si = gsi_last_bb (entry_bb);
11387 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11388 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11389 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11390 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11391 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11392 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11393 gsi_remove (&si, true);
11394 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11395
11396 if (exit_bb)
11397 {
11398 si = gsi_last_bb (exit_bb);
11399 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11400 gsi_remove (&si, true);
11401 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11402 }
11403 }
11404
11405 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11406 operation as a normal volatile load. */
11407
11408 static bool
11409 expand_omp_atomic_load (basic_block load_bb, tree addr,
11410 tree loaded_val, int index)
11411 {
11412 enum built_in_function tmpbase;
11413 gimple_stmt_iterator gsi;
11414 basic_block store_bb;
11415 location_t loc;
11416 gimple *stmt;
11417 tree decl, call, type, itype;
11418
11419 gsi = gsi_last_bb (load_bb);
11420 stmt = gsi_stmt (gsi);
11421 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11422 loc = gimple_location (stmt);
11423
11424 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11425 is smaller than word size, then expand_atomic_load assumes that the load
11426 is atomic. We could avoid the builtin entirely in this case. */
11427
11428 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11429 decl = builtin_decl_explicit (tmpbase);
11430 if (decl == NULL_TREE)
11431 return false;
11432
11433 type = TREE_TYPE (loaded_val);
11434 itype = TREE_TYPE (TREE_TYPE (decl));
11435
11436 call = build_call_expr_loc (loc, decl, 2, addr,
11437 build_int_cst (NULL,
11438 gimple_omp_atomic_seq_cst_p (stmt)
11439 ? MEMMODEL_SEQ_CST
11440 : MEMMODEL_RELAXED));
11441 if (!useless_type_conversion_p (type, itype))
11442 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11443 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11444
11445 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11446 gsi_remove (&gsi, true);
11447
11448 store_bb = single_succ (load_bb);
11449 gsi = gsi_last_bb (store_bb);
11450 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11451 gsi_remove (&gsi, true);
11452
11453 if (gimple_in_ssa_p (cfun))
11454 update_ssa (TODO_update_ssa_no_phi);
11455
11456 return true;
11457 }
11458
11459 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11460 operation as a normal volatile store. */
11461
11462 static bool
11463 expand_omp_atomic_store (basic_block load_bb, tree addr,
11464 tree loaded_val, tree stored_val, int index)
11465 {
11466 enum built_in_function tmpbase;
11467 gimple_stmt_iterator gsi;
11468 basic_block store_bb = single_succ (load_bb);
11469 location_t loc;
11470 gimple *stmt;
11471 tree decl, call, type, itype;
11472 machine_mode imode;
11473 bool exchange;
11474
11475 gsi = gsi_last_bb (load_bb);
11476 stmt = gsi_stmt (gsi);
11477 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11478
11479 /* If the load value is needed, then this isn't a store but an exchange. */
11480 exchange = gimple_omp_atomic_need_value_p (stmt);
11481
11482 gsi = gsi_last_bb (store_bb);
11483 stmt = gsi_stmt (gsi);
11484 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11485 loc = gimple_location (stmt);
11486
11487 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11488 is smaller than word size, then expand_atomic_store assumes that the store
11489 is atomic. We could avoid the builtin entirely in this case. */
11490
11491 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11492 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11493 decl = builtin_decl_explicit (tmpbase);
11494 if (decl == NULL_TREE)
11495 return false;
11496
11497 type = TREE_TYPE (stored_val);
11498
11499 /* Dig out the type of the function's second argument. */
11500 itype = TREE_TYPE (decl);
11501 itype = TYPE_ARG_TYPES (itype);
11502 itype = TREE_CHAIN (itype);
11503 itype = TREE_VALUE (itype);
11504 imode = TYPE_MODE (itype);
11505
11506 if (exchange && !can_atomic_exchange_p (imode, true))
11507 return false;
11508
11509 if (!useless_type_conversion_p (itype, type))
11510 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11511 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
11512 build_int_cst (NULL,
11513 gimple_omp_atomic_seq_cst_p (stmt)
11514 ? MEMMODEL_SEQ_CST
11515 : MEMMODEL_RELAXED));
11516 if (exchange)
11517 {
11518 if (!useless_type_conversion_p (type, itype))
11519 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11520 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11521 }
11522
11523 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11524 gsi_remove (&gsi, true);
11525
11526 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11527 gsi = gsi_last_bb (load_bb);
11528 gsi_remove (&gsi, true);
11529
11530 if (gimple_in_ssa_p (cfun))
11531 update_ssa (TODO_update_ssa_no_phi);
11532
11533 return true;
11534 }
11535
11536 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11537 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
11538 size of the data type, and thus usable to find the index of the builtin
11539 decl. Returns false if the expression is not of the proper form. */
11540
11541 static bool
11542 expand_omp_atomic_fetch_op (basic_block load_bb,
11543 tree addr, tree loaded_val,
11544 tree stored_val, int index)
11545 {
11546 enum built_in_function oldbase, newbase, tmpbase;
11547 tree decl, itype, call;
11548 tree lhs, rhs;
11549 basic_block store_bb = single_succ (load_bb);
11550 gimple_stmt_iterator gsi;
11551 gimple *stmt;
11552 location_t loc;
11553 enum tree_code code;
11554 bool need_old, need_new;
11555 machine_mode imode;
11556 bool seq_cst;
11557
11558 /* We expect to find the following sequences:
11559
11560 load_bb:
11561 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
11562
11563 store_bb:
11564 val = tmp OP something; (or: something OP tmp)
11565 GIMPLE_OMP_STORE (val)
11566
11567 ???FIXME: Allow a more flexible sequence.
11568 Perhaps use data flow to pick the statements.
11569
11570 */
11571
11572 gsi = gsi_after_labels (store_bb);
11573 stmt = gsi_stmt (gsi);
11574 loc = gimple_location (stmt);
11575 if (!is_gimple_assign (stmt))
11576 return false;
11577 gsi_next (&gsi);
11578 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
11579 return false;
11580 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11581 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
11582 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
11583 gcc_checking_assert (!need_old || !need_new);
11584
11585 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
11586 return false;
11587
11588 /* Check for one of the supported fetch-op operations. */
11589 code = gimple_assign_rhs_code (stmt);
11590 switch (code)
11591 {
11592 case PLUS_EXPR:
11593 case POINTER_PLUS_EXPR:
11594 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11595 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
11596 break;
11597 case MINUS_EXPR:
11598 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11599 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
11600 break;
11601 case BIT_AND_EXPR:
11602 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11603 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
11604 break;
11605 case BIT_IOR_EXPR:
11606 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11607 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
11608 break;
11609 case BIT_XOR_EXPR:
11610 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11611 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
11612 break;
11613 default:
11614 return false;
11615 }
11616
11617 /* Make sure the expression is of the proper form. */
11618 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11619 rhs = gimple_assign_rhs2 (stmt);
11620 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11621 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11622 rhs = gimple_assign_rhs1 (stmt);
11623 else
11624 return false;
11625
11626 tmpbase = ((enum built_in_function)
11627 ((need_new ? newbase : oldbase) + index + 1));
11628 decl = builtin_decl_explicit (tmpbase);
11629 if (decl == NULL_TREE)
11630 return false;
11631 itype = TREE_TYPE (TREE_TYPE (decl));
11632 imode = TYPE_MODE (itype);
11633
11634 /* We could test all of the various optabs involved, but the fact of the
11635 matter is that (with the exception of i486 vs i586 and xadd) all targets
11636 that support any atomic operaton optab also implements compare-and-swap.
11637 Let optabs.c take care of expanding any compare-and-swap loop. */
11638 if (!can_compare_and_swap_p (imode, true))
11639 return false;
11640
11641 gsi = gsi_last_bb (load_bb);
11642 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
11643
11644 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
11645 It only requires that the operation happen atomically. Thus we can
11646 use the RELAXED memory model. */
11647 call = build_call_expr_loc (loc, decl, 3, addr,
11648 fold_convert_loc (loc, itype, rhs),
11649 build_int_cst (NULL,
11650 seq_cst ? MEMMODEL_SEQ_CST
11651 : MEMMODEL_RELAXED));
11652
11653 if (need_old || need_new)
11654 {
11655 lhs = need_old ? loaded_val : stored_val;
11656 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
11657 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
11658 }
11659 else
11660 call = fold_convert_loc (loc, void_type_node, call);
11661 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11662 gsi_remove (&gsi, true);
11663
11664 gsi = gsi_last_bb (store_bb);
11665 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11666 gsi_remove (&gsi, true);
11667 gsi = gsi_last_bb (store_bb);
11668 gsi_remove (&gsi, true);
11669
11670 if (gimple_in_ssa_p (cfun))
11671 update_ssa (TODO_update_ssa_no_phi);
11672
11673 return true;
11674 }
11675
11676 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11677
11678 oldval = *addr;
11679 repeat:
11680 newval = rhs; // with oldval replacing *addr in rhs
11681 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
11682 if (oldval != newval)
11683 goto repeat;
11684
11685 INDEX is log2 of the size of the data type, and thus usable to find the
11686 index of the builtin decl. */
11687
11688 static bool
11689 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
11690 tree addr, tree loaded_val, tree stored_val,
11691 int index)
11692 {
11693 tree loadedi, storedi, initial, new_storedi, old_vali;
11694 tree type, itype, cmpxchg, iaddr;
11695 gimple_stmt_iterator si;
11696 basic_block loop_header = single_succ (load_bb);
11697 gimple *phi, *stmt;
11698 edge e;
11699 enum built_in_function fncode;
11700
11701 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
11702 order to use the RELAXED memory model effectively. */
11703 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
11704 + index + 1);
11705 cmpxchg = builtin_decl_explicit (fncode);
11706 if (cmpxchg == NULL_TREE)
11707 return false;
11708 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11709 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
11710
11711 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
11712 return false;
11713
11714 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
11715 si = gsi_last_bb (load_bb);
11716 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11717
11718 /* For floating-point values, we'll need to view-convert them to integers
11719 so that we can perform the atomic compare and swap. Simplify the
11720 following code by always setting up the "i"ntegral variables. */
11721 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
11722 {
11723 tree iaddr_val;
11724
11725 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
11726 true));
11727 iaddr_val
11728 = force_gimple_operand_gsi (&si,
11729 fold_convert (TREE_TYPE (iaddr), addr),
11730 false, NULL_TREE, true, GSI_SAME_STMT);
11731 stmt = gimple_build_assign (iaddr, iaddr_val);
11732 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11733 loadedi = create_tmp_var (itype);
11734 if (gimple_in_ssa_p (cfun))
11735 loadedi = make_ssa_name (loadedi);
11736 }
11737 else
11738 {
11739 iaddr = addr;
11740 loadedi = loaded_val;
11741 }
11742
11743 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11744 tree loaddecl = builtin_decl_explicit (fncode);
11745 if (loaddecl)
11746 initial
11747 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
11748 build_call_expr (loaddecl, 2, iaddr,
11749 build_int_cst (NULL_TREE,
11750 MEMMODEL_RELAXED)));
11751 else
11752 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
11753 build_int_cst (TREE_TYPE (iaddr), 0));
11754
11755 initial
11756 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
11757 GSI_SAME_STMT);
11758
11759 /* Move the value to the LOADEDI temporary. */
11760 if (gimple_in_ssa_p (cfun))
11761 {
11762 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
11763 phi = create_phi_node (loadedi, loop_header);
11764 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
11765 initial);
11766 }
11767 else
11768 gsi_insert_before (&si,
11769 gimple_build_assign (loadedi, initial),
11770 GSI_SAME_STMT);
11771 if (loadedi != loaded_val)
11772 {
11773 gimple_stmt_iterator gsi2;
11774 tree x;
11775
11776 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
11777 gsi2 = gsi_start_bb (loop_header);
11778 if (gimple_in_ssa_p (cfun))
11779 {
11780 gassign *stmt;
11781 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
11782 true, GSI_SAME_STMT);
11783 stmt = gimple_build_assign (loaded_val, x);
11784 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
11785 }
11786 else
11787 {
11788 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
11789 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
11790 true, GSI_SAME_STMT);
11791 }
11792 }
11793 gsi_remove (&si, true);
11794
11795 si = gsi_last_bb (store_bb);
11796 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
11797
11798 if (iaddr == addr)
11799 storedi = stored_val;
11800 else
11801 storedi =
11802 force_gimple_operand_gsi (&si,
11803 build1 (VIEW_CONVERT_EXPR, itype,
11804 stored_val), true, NULL_TREE, true,
11805 GSI_SAME_STMT);
11806
11807 /* Build the compare&swap statement. */
11808 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
11809 new_storedi = force_gimple_operand_gsi (&si,
11810 fold_convert (TREE_TYPE (loadedi),
11811 new_storedi),
11812 true, NULL_TREE,
11813 true, GSI_SAME_STMT);
11814
11815 if (gimple_in_ssa_p (cfun))
11816 old_vali = loadedi;
11817 else
11818 {
11819 old_vali = create_tmp_var (TREE_TYPE (loadedi));
11820 stmt = gimple_build_assign (old_vali, loadedi);
11821 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11822
11823 stmt = gimple_build_assign (loadedi, new_storedi);
11824 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11825 }
11826
11827 /* Note that we always perform the comparison as an integer, even for
11828 floating point. This allows the atomic operation to properly
11829 succeed even with NaNs and -0.0. */
11830 stmt = gimple_build_cond_empty
11831 (build2 (NE_EXPR, boolean_type_node,
11832 new_storedi, old_vali));
11833 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11834
11835 /* Update cfg. */
11836 e = single_succ_edge (store_bb);
11837 e->flags &= ~EDGE_FALLTHRU;
11838 e->flags |= EDGE_FALSE_VALUE;
11839
11840 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
11841
11842 /* Copy the new value to loadedi (we already did that before the condition
11843 if we are not in SSA). */
11844 if (gimple_in_ssa_p (cfun))
11845 {
11846 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
11847 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
11848 }
11849
11850 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
11851 gsi_remove (&si, true);
11852
11853 struct loop *loop = alloc_loop ();
11854 loop->header = loop_header;
11855 loop->latch = store_bb;
11856 add_loop (loop, loop_header->loop_father);
11857
11858 if (gimple_in_ssa_p (cfun))
11859 update_ssa (TODO_update_ssa_no_phi);
11860
11861 return true;
11862 }
11863
11864 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11865
11866 GOMP_atomic_start ();
11867 *addr = rhs;
11868 GOMP_atomic_end ();
11869
11870 The result is not globally atomic, but works so long as all parallel
11871 references are within #pragma omp atomic directives. According to
11872 responses received from omp@openmp.org, appears to be within spec.
11873 Which makes sense, since that's how several other compilers handle
11874 this situation as well.
11875 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
11876 expanding. STORED_VAL is the operand of the matching
11877 GIMPLE_OMP_ATOMIC_STORE.
11878
11879 We replace
11880 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
11881 loaded_val = *addr;
11882
11883 and replace
11884 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
11885 *addr = stored_val;
11886 */
11887
11888 static bool
11889 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
11890 tree addr, tree loaded_val, tree stored_val)
11891 {
11892 gimple_stmt_iterator si;
11893 gassign *stmt;
11894 tree t;
11895
11896 si = gsi_last_bb (load_bb);
11897 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11898
11899 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
11900 t = build_call_expr (t, 0);
11901 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
11902
11903 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
11904 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11905 gsi_remove (&si, true);
11906
11907 si = gsi_last_bb (store_bb);
11908 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
11909
11910 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
11911 stored_val);
11912 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11913
11914 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
11915 t = build_call_expr (t, 0);
11916 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
11917 gsi_remove (&si, true);
11918
11919 if (gimple_in_ssa_p (cfun))
11920 update_ssa (TODO_update_ssa_no_phi);
11921 return true;
11922 }
11923
11924 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
11925 using expand_omp_atomic_fetch_op. If it failed, we try to
11926 call expand_omp_atomic_pipeline, and if it fails too, the
11927 ultimate fallback is wrapping the operation in a mutex
11928 (expand_omp_atomic_mutex). REGION is the atomic region built
11929 by build_omp_regions_1(). */
11930
11931 static void
11932 expand_omp_atomic (struct omp_region *region)
11933 {
11934 basic_block load_bb = region->entry, store_bb = region->exit;
11935 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
11936 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
11937 tree loaded_val = gimple_omp_atomic_load_lhs (load);
11938 tree addr = gimple_omp_atomic_load_rhs (load);
11939 tree stored_val = gimple_omp_atomic_store_val (store);
11940 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11941 HOST_WIDE_INT index;
11942
11943 /* Make sure the type is one of the supported sizes. */
11944 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
11945 index = exact_log2 (index);
11946 if (index >= 0 && index <= 4)
11947 {
11948 unsigned int align = TYPE_ALIGN_UNIT (type);
11949
11950 /* __sync builtins require strict data alignment. */
11951 if (exact_log2 (align) >= index)
11952 {
11953 /* Atomic load. */
11954 if (loaded_val == stored_val
11955 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
11956 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
11957 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
11958 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
11959 return;
11960
11961 /* Atomic store. */
11962 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
11963 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
11964 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
11965 && store_bb == single_succ (load_bb)
11966 && first_stmt (store_bb) == store
11967 && expand_omp_atomic_store (load_bb, addr, loaded_val,
11968 stored_val, index))
11969 return;
11970
11971 /* When possible, use specialized atomic update functions. */
11972 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
11973 && store_bb == single_succ (load_bb)
11974 && expand_omp_atomic_fetch_op (load_bb, addr,
11975 loaded_val, stored_val, index))
11976 return;
11977
11978 /* If we don't have specialized __sync builtins, try and implement
11979 as a compare and swap loop. */
11980 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
11981 loaded_val, stored_val, index))
11982 return;
11983 }
11984 }
11985
11986 /* The ultimate fallback is wrapping the operation in a mutex. */
11987 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
11988 }
11989
11990
11991 /* Encode an oacc launc argument. This matches the GOMP_LAUNCH_PACK
11992 macro on gomp-constants.h. We do not check for overflow. */
11993
11994 static tree
11995 oacc_launch_pack (unsigned code, tree device, unsigned op)
11996 {
11997 tree res;
11998
11999 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12000 if (device)
12001 {
12002 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12003 device, build_int_cst (unsigned_type_node,
12004 GOMP_LAUNCH_DEVICE_SHIFT));
12005 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12006 }
12007 return res;
12008 }
12009
12010 /* Look for compute grid dimension clauses and convert to an attribute
12011 attached to FN. This permits the target-side code to (a) massage
12012 the dimensions, (b) emit that data and (c) optimize. Non-constant
12013 dimensions are pushed onto ARGS.
12014
12015 The attribute value is a TREE_LIST. A set of dimensions is
12016 represented as a list of INTEGER_CST. Those that are runtime
12017 expres are represented as an INTEGER_CST of zero.
12018
12019 TOOO. Normally the attribute will just contain a single such list. If
12020 however it contains a list of lists, this will represent the use of
12021 device_type. Each member of the outer list is an assoc list of
12022 dimensions, keyed by the device type. The first entry will be the
12023 default. Well, that's the plan. */
12024
12025 #define OACC_FN_ATTRIB "oacc function"
12026
12027 /* Replace any existing oacc fn attribute with updated dimensions. */
12028
12029 void
12030 replace_oacc_fn_attrib (tree fn, tree dims)
12031 {
12032 tree ident = get_identifier (OACC_FN_ATTRIB);
12033 tree attribs = DECL_ATTRIBUTES (fn);
12034
12035 /* If we happen to be present as the first attrib, drop it. */
12036 if (attribs && TREE_PURPOSE (attribs) == ident)
12037 attribs = TREE_CHAIN (attribs);
12038 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12039 }
12040
12041 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12042 function attribute. Push any that are non-constant onto the ARGS
12043 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12044
12045 static void
12046 set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12047 {
12048 /* Must match GOMP_DIM ordering. */
12049 static const omp_clause_code ids[]
12050 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12051 OMP_CLAUSE_VECTOR_LENGTH };
12052 unsigned ix;
12053 tree dims[GOMP_DIM_MAX];
12054 tree attr = NULL_TREE;
12055 unsigned non_const = 0;
12056
12057 for (ix = GOMP_DIM_MAX; ix--;)
12058 {
12059 tree clause = find_omp_clause (clauses, ids[ix]);
12060 tree dim = NULL_TREE;
12061
12062 if (clause)
12063 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12064 dims[ix] = dim;
12065 if (dim && TREE_CODE (dim) != INTEGER_CST)
12066 {
12067 dim = integer_zero_node;
12068 non_const |= GOMP_DIM_MASK (ix);
12069 }
12070 attr = tree_cons (NULL_TREE, dim, attr);
12071 }
12072
12073 replace_oacc_fn_attrib (fn, attr);
12074
12075 if (non_const)
12076 {
12077 /* Push a dynamic argument set. */
12078 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12079 NULL_TREE, non_const));
12080 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12081 if (non_const & GOMP_DIM_MASK (ix))
12082 args->safe_push (dims[ix]);
12083 }
12084 }
12085
12086 /* Retrieve the oacc function attrib and return it. Non-oacc
12087 functions will return NULL. */
12088
12089 tree
12090 get_oacc_fn_attrib (tree fn)
12091 {
12092 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12093 }
12094
12095 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12096
12097 static void
12098 expand_omp_target (struct omp_region *region)
12099 {
12100 basic_block entry_bb, exit_bb, new_bb;
12101 struct function *child_cfun;
12102 tree child_fn, block, t;
12103 gimple_stmt_iterator gsi;
12104 gomp_target *entry_stmt;
12105 gimple *stmt;
12106 edge e;
12107 bool offloaded, data_region;
12108
12109 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
12110 new_bb = region->entry;
12111
12112 offloaded = is_gimple_omp_offloaded (entry_stmt);
12113 switch (gimple_omp_target_kind (entry_stmt))
12114 {
12115 case GF_OMP_TARGET_KIND_REGION:
12116 case GF_OMP_TARGET_KIND_UPDATE:
12117 case GF_OMP_TARGET_KIND_ENTER_DATA:
12118 case GF_OMP_TARGET_KIND_EXIT_DATA:
12119 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12120 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12121 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12122 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12123 data_region = false;
12124 break;
12125 case GF_OMP_TARGET_KIND_DATA:
12126 case GF_OMP_TARGET_KIND_OACC_DATA:
12127 data_region = true;
12128 break;
12129 default:
12130 gcc_unreachable ();
12131 }
12132
12133 child_fn = NULL_TREE;
12134 child_cfun = NULL;
12135 if (offloaded)
12136 {
12137 child_fn = gimple_omp_target_child_fn (entry_stmt);
12138 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12139 }
12140
12141 /* Supported by expand_omp_taskreg, but not here. */
12142 if (child_cfun != NULL)
12143 gcc_checking_assert (!child_cfun->cfg);
12144 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12145
12146 entry_bb = region->entry;
12147 exit_bb = region->exit;
12148
12149 if (offloaded)
12150 {
12151 unsigned srcidx, dstidx, num;
12152
12153 /* If the offloading region needs data sent from the parent
12154 function, then the very first statement (except possible
12155 tree profile counter updates) of the offloading body
12156 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12157 &.OMP_DATA_O is passed as an argument to the child function,
12158 we need to replace it with the argument as seen by the child
12159 function.
12160
12161 In most cases, this will end up being the identity assignment
12162 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
12163 a function call that has been inlined, the original PARM_DECL
12164 .OMP_DATA_I may have been converted into a different local
12165 variable. In which case, we need to keep the assignment. */
12166 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12167 if (data_arg)
12168 {
12169 basic_block entry_succ_bb = single_succ (entry_bb);
12170 gimple_stmt_iterator gsi;
12171 tree arg;
12172 gimple *tgtcopy_stmt = NULL;
12173 tree sender = TREE_VEC_ELT (data_arg, 0);
12174
12175 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12176 {
12177 gcc_assert (!gsi_end_p (gsi));
12178 stmt = gsi_stmt (gsi);
12179 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12180 continue;
12181
12182 if (gimple_num_ops (stmt) == 2)
12183 {
12184 tree arg = gimple_assign_rhs1 (stmt);
12185
12186 /* We're ignoring the subcode because we're
12187 effectively doing a STRIP_NOPS. */
12188
12189 if (TREE_CODE (arg) == ADDR_EXPR
12190 && TREE_OPERAND (arg, 0) == sender)
12191 {
12192 tgtcopy_stmt = stmt;
12193 break;
12194 }
12195 }
12196 }
12197
12198 gcc_assert (tgtcopy_stmt != NULL);
12199 arg = DECL_ARGUMENTS (child_fn);
12200
12201 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12202 gsi_remove (&gsi, true);
12203 }
12204
12205 /* Declare local variables needed in CHILD_CFUN. */
12206 block = DECL_INITIAL (child_fn);
12207 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
12208 /* The gimplifier could record temporaries in the offloading block
12209 rather than in containing function's local_decls chain,
12210 which would mean cgraph missed finalizing them. Do it now. */
12211 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12212 if (TREE_CODE (t) == VAR_DECL
12213 && TREE_STATIC (t)
12214 && !DECL_EXTERNAL (t))
12215 varpool_node::finalize_decl (t);
12216 DECL_SAVED_TREE (child_fn) = NULL;
12217 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12218 gimple_set_body (child_fn, NULL);
12219 TREE_USED (block) = 1;
12220
12221 /* Reset DECL_CONTEXT on function arguments. */
12222 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12223 DECL_CONTEXT (t) = child_fn;
12224
12225 /* Split ENTRY_BB at GIMPLE_*,
12226 so that it can be moved to the child function. */
12227 gsi = gsi_last_bb (entry_bb);
12228 stmt = gsi_stmt (gsi);
12229 gcc_assert (stmt
12230 && gimple_code (stmt) == gimple_code (entry_stmt));
12231 e = split_block (entry_bb, stmt);
12232 gsi_remove (&gsi, true);
12233 entry_bb = e->dest;
12234 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12235
12236 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12237 if (exit_bb)
12238 {
12239 gsi = gsi_last_bb (exit_bb);
12240 gcc_assert (!gsi_end_p (gsi)
12241 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12242 stmt = gimple_build_return (NULL);
12243 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12244 gsi_remove (&gsi, true);
12245 }
12246
12247 /* Move the offloading region into CHILD_CFUN. */
12248
12249 block = gimple_block (entry_stmt);
12250
12251 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12252 if (exit_bb)
12253 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12254 /* When the OMP expansion process cannot guarantee an up-to-date
12255 loop tree arrange for the child function to fixup loops. */
12256 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12257 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12258
12259 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12260 num = vec_safe_length (child_cfun->local_decls);
12261 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12262 {
12263 t = (*child_cfun->local_decls)[srcidx];
12264 if (DECL_CONTEXT (t) == cfun->decl)
12265 continue;
12266 if (srcidx != dstidx)
12267 (*child_cfun->local_decls)[dstidx] = t;
12268 dstidx++;
12269 }
12270 if (dstidx != num)
12271 vec_safe_truncate (child_cfun->local_decls, dstidx);
12272
12273 /* Inform the callgraph about the new function. */
12274 child_cfun->curr_properties = cfun->curr_properties;
12275 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12276 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
12277 cgraph_node *node = cgraph_node::get_create (child_fn);
12278 node->parallelized_function = 1;
12279 cgraph_node::add_new_function (child_fn, true);
12280
12281 #ifdef ENABLE_OFFLOADING
12282 /* Add the new function to the offload table. */
12283 vec_safe_push (offload_funcs, child_fn);
12284 #endif
12285
12286 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12287 fixed in a following pass. */
12288 push_cfun (child_cfun);
12289 cgraph_edge::rebuild_edges ();
12290
12291 #ifdef ENABLE_OFFLOADING
12292 /* Prevent IPA from removing child_fn as unreachable, since there are no
12293 refs from the parent function to child_fn in offload LTO mode. */
12294 cgraph_node::get (child_fn)->mark_force_output ();
12295 #endif
12296
12297 /* Some EH regions might become dead, see PR34608. If
12298 pass_cleanup_cfg isn't the first pass to happen with the
12299 new child, these dead EH edges might cause problems.
12300 Clean them up now. */
12301 if (flag_exceptions)
12302 {
12303 basic_block bb;
12304 bool changed = false;
12305
12306 FOR_EACH_BB_FN (bb, cfun)
12307 changed |= gimple_purge_dead_eh_edges (bb);
12308 if (changed)
12309 cleanup_tree_cfg ();
12310 }
12311 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12312 verify_loop_structure ();
12313 pop_cfun ();
12314 }
12315
12316 /* Emit a library call to launch the offloading region, or do data
12317 transfers. */
12318 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
12319 enum built_in_function start_ix;
12320 location_t clause_loc;
12321 unsigned int flags_i = 0;
12322
12323 switch (gimple_omp_target_kind (entry_stmt))
12324 {
12325 case GF_OMP_TARGET_KIND_REGION:
12326 start_ix = BUILT_IN_GOMP_TARGET;
12327 break;
12328 case GF_OMP_TARGET_KIND_DATA:
12329 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12330 break;
12331 case GF_OMP_TARGET_KIND_UPDATE:
12332 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12333 break;
12334 case GF_OMP_TARGET_KIND_ENTER_DATA:
12335 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12336 break;
12337 case GF_OMP_TARGET_KIND_EXIT_DATA:
12338 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12339 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12340 break;
12341 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12342 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12343 start_ix = BUILT_IN_GOACC_PARALLEL;
12344 break;
12345 case GF_OMP_TARGET_KIND_OACC_DATA:
12346 start_ix = BUILT_IN_GOACC_DATA_START;
12347 break;
12348 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12349 start_ix = BUILT_IN_GOACC_UPDATE;
12350 break;
12351 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12352 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12353 break;
12354 default:
12355 gcc_unreachable ();
12356 }
12357
12358 clauses = gimple_omp_target_clauses (entry_stmt);
12359
12360 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12361 library choose) and there is no conditional. */
12362 cond = NULL_TREE;
12363 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
12364
12365 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12366 if (c)
12367 cond = OMP_CLAUSE_IF_EXPR (c);
12368
12369 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12370 if (c)
12371 {
12372 /* Even if we pass it to all library function calls, it is currently only
12373 defined/used for the OpenMP target ones. */
12374 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12375 || start_ix == BUILT_IN_GOMP_TARGET_DATA
12376 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12377 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
12378
12379 device = OMP_CLAUSE_DEVICE_ID (c);
12380 clause_loc = OMP_CLAUSE_LOCATION (c);
12381 }
12382 else
12383 clause_loc = gimple_location (entry_stmt);
12384
12385 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12386 if (c)
12387 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12388
12389 /* Ensure 'device' is of the correct type. */
12390 device = fold_convert_loc (clause_loc, integer_type_node, device);
12391
12392 /* If we found the clause 'if (cond)', build
12393 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
12394 if (cond)
12395 {
12396 cond = gimple_boolify (cond);
12397
12398 basic_block cond_bb, then_bb, else_bb;
12399 edge e;
12400 tree tmp_var;
12401
12402 tmp_var = create_tmp_var (TREE_TYPE (device));
12403 if (offloaded)
12404 e = split_block_after_labels (new_bb);
12405 else
12406 {
12407 gsi = gsi_last_bb (new_bb);
12408 gsi_prev (&gsi);
12409 e = split_block (new_bb, gsi_stmt (gsi));
12410 }
12411 cond_bb = e->src;
12412 new_bb = e->dest;
12413 remove_edge (e);
12414
12415 then_bb = create_empty_bb (cond_bb);
12416 else_bb = create_empty_bb (then_bb);
12417 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12418 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12419
12420 stmt = gimple_build_cond_empty (cond);
12421 gsi = gsi_last_bb (cond_bb);
12422 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12423
12424 gsi = gsi_start_bb (then_bb);
12425 stmt = gimple_build_assign (tmp_var, device);
12426 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12427
12428 gsi = gsi_start_bb (else_bb);
12429 stmt = gimple_build_assign (tmp_var,
12430 build_int_cst (integer_type_node,
12431 GOMP_DEVICE_HOST_FALLBACK));
12432 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12433
12434 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12435 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
12436 add_bb_to_loop (then_bb, cond_bb->loop_father);
12437 add_bb_to_loop (else_bb, cond_bb->loop_father);
12438 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12439 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12440
12441 device = tmp_var;
12442 }
12443
12444 gsi = gsi_last_bb (new_bb);
12445 t = gimple_omp_target_data_arg (entry_stmt);
12446 if (t == NULL)
12447 {
12448 t1 = size_zero_node;
12449 t2 = build_zero_cst (ptr_type_node);
12450 t3 = t2;
12451 t4 = t2;
12452 }
12453 else
12454 {
12455 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12456 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12457 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12458 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12459 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12460 }
12461
12462 gimple *g;
12463 bool tagging = false;
12464 /* The maximum number used by any start_ix, without varargs. */
12465 auto_vec<tree, 11> args;
12466 args.quick_push (device);
12467 if (offloaded)
12468 args.quick_push (build_fold_addr_expr (child_fn));
12469 args.quick_push (t1);
12470 args.quick_push (t2);
12471 args.quick_push (t3);
12472 args.quick_push (t4);
12473 switch (start_ix)
12474 {
12475 case BUILT_IN_GOACC_DATA_START:
12476 case BUILT_IN_GOMP_TARGET_DATA:
12477 break;
12478 case BUILT_IN_GOMP_TARGET:
12479 case BUILT_IN_GOMP_TARGET_UPDATE:
12480 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12481 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12482 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12483 if (c)
12484 depend = OMP_CLAUSE_DECL (c);
12485 else
12486 depend = build_int_cst (ptr_type_node, 0);
12487 args.quick_push (depend);
12488 break;
12489 case BUILT_IN_GOACC_PARALLEL:
12490 {
12491 set_oacc_fn_attrib (child_fn, clauses, &args);
12492 tagging = true;
12493 }
12494 /* FALLTHRU */
12495 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
12496 case BUILT_IN_GOACC_UPDATE:
12497 {
12498 tree t_async = NULL_TREE;
12499
12500 /* If present, use the value specified by the respective
12501 clause, making sure that is of the correct type. */
12502 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
12503 if (c)
12504 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12505 integer_type_node,
12506 OMP_CLAUSE_ASYNC_EXPR (c));
12507 else if (!tagging)
12508 /* Default values for t_async. */
12509 t_async = fold_convert_loc (gimple_location (entry_stmt),
12510 integer_type_node,
12511 build_int_cst (integer_type_node,
12512 GOMP_ASYNC_SYNC));
12513 if (tagging && t_async)
12514 {
12515 unsigned HOST_WIDE_INT i_async;
12516
12517 if (TREE_CODE (t_async) == INTEGER_CST)
12518 {
12519 /* See if we can pack the async arg in to the tag's
12520 operand. */
12521 i_async = TREE_INT_CST_LOW (t_async);
12522
12523 if (i_async < GOMP_LAUNCH_OP_MAX)
12524 t_async = NULL_TREE;
12525 }
12526 if (t_async)
12527 i_async = GOMP_LAUNCH_OP_MAX;
12528 args.safe_push (oacc_launch_pack
12529 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
12530 }
12531 if (t_async)
12532 args.safe_push (t_async);
12533
12534 /* Save the argument index, and ... */
12535 unsigned t_wait_idx = args.length ();
12536 unsigned num_waits = 0;
12537 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
12538 if (!tagging || c)
12539 /* ... push a placeholder. */
12540 args.safe_push (integer_zero_node);
12541
12542 for (; c; c = OMP_CLAUSE_CHAIN (c))
12543 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
12544 {
12545 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12546 integer_type_node,
12547 OMP_CLAUSE_WAIT_EXPR (c)));
12548 num_waits++;
12549 }
12550
12551 if (!tagging || num_waits)
12552 {
12553 tree len;
12554
12555 /* Now that we know the number, update the placeholder. */
12556 if (tagging)
12557 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
12558 else
12559 len = build_int_cst (integer_type_node, num_waits);
12560 len = fold_convert_loc (gimple_location (entry_stmt),
12561 unsigned_type_node, len);
12562 args[t_wait_idx] = len;
12563 }
12564 }
12565 break;
12566 default:
12567 gcc_unreachable ();
12568 }
12569 if (tagging)
12570 /* Push terminal marker - zero. */
12571 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
12572
12573 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
12574 gimple_set_location (g, gimple_location (entry_stmt));
12575 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12576 if (!offloaded)
12577 {
12578 g = gsi_stmt (gsi);
12579 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
12580 gsi_remove (&gsi, true);
12581 }
12582 if (data_region && region->exit)
12583 {
12584 gsi = gsi_last_bb (region->exit);
12585 g = gsi_stmt (gsi);
12586 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
12587 gsi_remove (&gsi, true);
12588 }
12589 }
12590
12591
12592 /* Expand the parallel region tree rooted at REGION. Expansion
12593 proceeds in depth-first order. Innermost regions are expanded
12594 first. This way, parallel regions that require a new function to
12595 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
12596 internal dependencies in their body. */
12597
12598 static void
12599 expand_omp (struct omp_region *region)
12600 {
12601 while (region)
12602 {
12603 location_t saved_location;
12604 gimple *inner_stmt = NULL;
12605
12606 /* First, determine whether this is a combined parallel+workshare
12607 region. */
12608 if (region->type == GIMPLE_OMP_PARALLEL)
12609 determine_parallel_type (region);
12610
12611 if (region->type == GIMPLE_OMP_FOR
12612 && gimple_omp_for_combined_p (last_stmt (region->entry)))
12613 inner_stmt = last_stmt (region->inner->entry);
12614
12615 if (region->inner)
12616 expand_omp (region->inner);
12617
12618 saved_location = input_location;
12619 if (gimple_has_location (last_stmt (region->entry)))
12620 input_location = gimple_location (last_stmt (region->entry));
12621
12622 switch (region->type)
12623 {
12624 case GIMPLE_OMP_PARALLEL:
12625 case GIMPLE_OMP_TASK:
12626 expand_omp_taskreg (region);
12627 break;
12628
12629 case GIMPLE_OMP_FOR:
12630 expand_omp_for (region, inner_stmt);
12631 break;
12632
12633 case GIMPLE_OMP_SECTIONS:
12634 expand_omp_sections (region);
12635 break;
12636
12637 case GIMPLE_OMP_SECTION:
12638 /* Individual omp sections are handled together with their
12639 parent GIMPLE_OMP_SECTIONS region. */
12640 break;
12641
12642 case GIMPLE_OMP_SINGLE:
12643 expand_omp_single (region);
12644 break;
12645
12646 case GIMPLE_OMP_ORDERED:
12647 {
12648 gomp_ordered *ord_stmt
12649 = as_a <gomp_ordered *> (last_stmt (region->entry));
12650 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
12651 OMP_CLAUSE_DEPEND))
12652 {
12653 /* We'll expand these when expanding corresponding
12654 worksharing region with ordered(n) clause. */
12655 gcc_assert (region->outer
12656 && region->outer->type == GIMPLE_OMP_FOR);
12657 region->ord_stmt = ord_stmt;
12658 break;
12659 }
12660 }
12661 /* FALLTHRU */
12662 case GIMPLE_OMP_MASTER:
12663 case GIMPLE_OMP_TASKGROUP:
12664 case GIMPLE_OMP_CRITICAL:
12665 case GIMPLE_OMP_TEAMS:
12666 expand_omp_synch (region);
12667 break;
12668
12669 case GIMPLE_OMP_ATOMIC_LOAD:
12670 expand_omp_atomic (region);
12671 break;
12672
12673 case GIMPLE_OMP_TARGET:
12674 expand_omp_target (region);
12675 break;
12676
12677 default:
12678 gcc_unreachable ();
12679 }
12680
12681 input_location = saved_location;
12682 region = region->next;
12683 }
12684 }
12685
12686
12687 /* Helper for build_omp_regions. Scan the dominator tree starting at
12688 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
12689 true, the function ends once a single tree is built (otherwise, whole
12690 forest of OMP constructs may be built). */
12691
12692 static void
12693 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
12694 bool single_tree)
12695 {
12696 gimple_stmt_iterator gsi;
12697 gimple *stmt;
12698 basic_block son;
12699
12700 gsi = gsi_last_bb (bb);
12701 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
12702 {
12703 struct omp_region *region;
12704 enum gimple_code code;
12705
12706 stmt = gsi_stmt (gsi);
12707 code = gimple_code (stmt);
12708 if (code == GIMPLE_OMP_RETURN)
12709 {
12710 /* STMT is the return point out of region PARENT. Mark it
12711 as the exit point and make PARENT the immediately
12712 enclosing region. */
12713 gcc_assert (parent);
12714 region = parent;
12715 region->exit = bb;
12716 parent = parent->outer;
12717 }
12718 else if (code == GIMPLE_OMP_ATOMIC_STORE)
12719 {
12720 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
12721 GIMPLE_OMP_RETURN, but matches with
12722 GIMPLE_OMP_ATOMIC_LOAD. */
12723 gcc_assert (parent);
12724 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
12725 region = parent;
12726 region->exit = bb;
12727 parent = parent->outer;
12728 }
12729 else if (code == GIMPLE_OMP_CONTINUE)
12730 {
12731 gcc_assert (parent);
12732 parent->cont = bb;
12733 }
12734 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
12735 {
12736 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
12737 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
12738 }
12739 else
12740 {
12741 region = new_omp_region (bb, code, parent);
12742 /* Otherwise... */
12743 if (code == GIMPLE_OMP_TARGET)
12744 {
12745 switch (gimple_omp_target_kind (stmt))
12746 {
12747 case GF_OMP_TARGET_KIND_REGION:
12748 case GF_OMP_TARGET_KIND_DATA:
12749 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12750 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12751 case GF_OMP_TARGET_KIND_OACC_DATA:
12752 break;
12753 case GF_OMP_TARGET_KIND_UPDATE:
12754 case GF_OMP_TARGET_KIND_ENTER_DATA:
12755 case GF_OMP_TARGET_KIND_EXIT_DATA:
12756 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12757 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12758 /* ..., other than for those stand-alone directives... */
12759 region = NULL;
12760 break;
12761 default:
12762 gcc_unreachable ();
12763 }
12764 }
12765 else if (code == GIMPLE_OMP_ORDERED
12766 && find_omp_clause (gimple_omp_ordered_clauses
12767 (as_a <gomp_ordered *> (stmt)),
12768 OMP_CLAUSE_DEPEND))
12769 /* #pragma omp ordered depend is also just a stand-alone
12770 directive. */
12771 region = NULL;
12772 /* ..., this directive becomes the parent for a new region. */
12773 if (region)
12774 parent = region;
12775 }
12776 }
12777
12778 if (single_tree && !parent)
12779 return;
12780
12781 for (son = first_dom_son (CDI_DOMINATORS, bb);
12782 son;
12783 son = next_dom_son (CDI_DOMINATORS, son))
12784 build_omp_regions_1 (son, parent, single_tree);
12785 }
12786
12787 /* Builds the tree of OMP regions rooted at ROOT, storing it to
12788 root_omp_region. */
12789
12790 static void
12791 build_omp_regions_root (basic_block root)
12792 {
12793 gcc_assert (root_omp_region == NULL);
12794 build_omp_regions_1 (root, NULL, true);
12795 gcc_assert (root_omp_region != NULL);
12796 }
12797
12798 /* Expands omp construct (and its subconstructs) starting in HEAD. */
12799
12800 void
12801 omp_expand_local (basic_block head)
12802 {
12803 build_omp_regions_root (head);
12804 if (dump_file && (dump_flags & TDF_DETAILS))
12805 {
12806 fprintf (dump_file, "\nOMP region tree\n\n");
12807 dump_omp_region (dump_file, root_omp_region, 0);
12808 fprintf (dump_file, "\n");
12809 }
12810
12811 remove_exit_barriers (root_omp_region);
12812 expand_omp (root_omp_region);
12813
12814 free_omp_regions ();
12815 }
12816
12817 /* Scan the CFG and build a tree of OMP regions. Return the root of
12818 the OMP region tree. */
12819
12820 static void
12821 build_omp_regions (void)
12822 {
12823 gcc_assert (root_omp_region == NULL);
12824 calculate_dominance_info (CDI_DOMINATORS);
12825 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
12826 }
12827
12828 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
12829
12830 static unsigned int
12831 execute_expand_omp (void)
12832 {
12833 build_omp_regions ();
12834
12835 if (!root_omp_region)
12836 return 0;
12837
12838 if (dump_file)
12839 {
12840 fprintf (dump_file, "\nOMP region tree\n\n");
12841 dump_omp_region (dump_file, root_omp_region, 0);
12842 fprintf (dump_file, "\n");
12843 }
12844
12845 remove_exit_barriers (root_omp_region);
12846
12847 expand_omp (root_omp_region);
12848
12849 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12850 verify_loop_structure ();
12851 cleanup_tree_cfg ();
12852
12853 free_omp_regions ();
12854
12855 return 0;
12856 }
12857
12858 /* OMP expansion -- the default pass, run before creation of SSA form. */
12859
12860 namespace {
12861
12862 const pass_data pass_data_expand_omp =
12863 {
12864 GIMPLE_PASS, /* type */
12865 "ompexp", /* name */
12866 OPTGROUP_NONE, /* optinfo_flags */
12867 TV_NONE, /* tv_id */
12868 PROP_gimple_any, /* properties_required */
12869 PROP_gimple_eomp, /* properties_provided */
12870 0, /* properties_destroyed */
12871 0, /* todo_flags_start */
12872 0, /* todo_flags_finish */
12873 };
12874
12875 class pass_expand_omp : public gimple_opt_pass
12876 {
12877 public:
12878 pass_expand_omp (gcc::context *ctxt)
12879 : gimple_opt_pass (pass_data_expand_omp, ctxt)
12880 {}
12881
12882 /* opt_pass methods: */
12883 virtual unsigned int execute (function *)
12884 {
12885 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
12886 || flag_openmp_simd != 0)
12887 && !seen_error ());
12888
12889 /* This pass always runs, to provide PROP_gimple_eomp.
12890 But often, there is nothing to do. */
12891 if (!gate)
12892 return 0;
12893
12894 return execute_expand_omp ();
12895 }
12896
12897 }; // class pass_expand_omp
12898
12899 } // anon namespace
12900
12901 gimple_opt_pass *
12902 make_pass_expand_omp (gcc::context *ctxt)
12903 {
12904 return new pass_expand_omp (ctxt);
12905 }
12906
12907 namespace {
12908
12909 const pass_data pass_data_expand_omp_ssa =
12910 {
12911 GIMPLE_PASS, /* type */
12912 "ompexpssa", /* name */
12913 OPTGROUP_NONE, /* optinfo_flags */
12914 TV_NONE, /* tv_id */
12915 PROP_cfg | PROP_ssa, /* properties_required */
12916 PROP_gimple_eomp, /* properties_provided */
12917 0, /* properties_destroyed */
12918 0, /* todo_flags_start */
12919 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
12920 };
12921
12922 class pass_expand_omp_ssa : public gimple_opt_pass
12923 {
12924 public:
12925 pass_expand_omp_ssa (gcc::context *ctxt)
12926 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
12927 {}
12928
12929 /* opt_pass methods: */
12930 virtual bool gate (function *fun)
12931 {
12932 return !(fun->curr_properties & PROP_gimple_eomp);
12933 }
12934 virtual unsigned int execute (function *) { return execute_expand_omp (); }
12935
12936 }; // class pass_expand_omp_ssa
12937
12938 } // anon namespace
12939
12940 gimple_opt_pass *
12941 make_pass_expand_omp_ssa (gcc::context *ctxt)
12942 {
12943 return new pass_expand_omp_ssa (ctxt);
12944 }
12945 \f
12946 /* Routines to lower OMP directives into OMP-GIMPLE. */
12947
12948 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
12949 convert it to gimple. */
12950 static void
12951 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
12952 {
12953 gimple *stmt;
12954
12955 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
12956 {
12957 stmt = gimple_build_assign (dest, op, dest, src);
12958 gimple_seq_add_stmt (seq, stmt);
12959 return;
12960 }
12961
12962 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12963 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
12964 gimplify_assign (t, rdest, seq);
12965 rdest = t;
12966
12967 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12968 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
12969 gimplify_assign (t, idest, seq);
12970 idest = t;
12971
12972 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
12973 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
12974 gimplify_assign (t, rsrc, seq);
12975 rsrc = t;
12976
12977 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
12978 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
12979 gimplify_assign (t, isrc, seq);
12980 isrc = t;
12981
12982 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12983 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12984 tree result;
12985
12986 if (op == PLUS_EXPR)
12987 {
12988 stmt = gimple_build_assign (r, op, rdest, rsrc);
12989 gimple_seq_add_stmt (seq, stmt);
12990
12991 stmt = gimple_build_assign (i, op, idest, isrc);
12992 gimple_seq_add_stmt (seq, stmt);
12993 }
12994 else if (op == MULT_EXPR)
12995 {
12996 /* Let x = a + ib = dest, y = c + id = src.
12997 x * y = (ac - bd) + i(ad + bc) */
12998 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12999 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
13000 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
13001 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
13002
13003 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
13004 gimple_seq_add_stmt (seq, stmt);
13005
13006 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
13007 gimple_seq_add_stmt (seq, stmt);
13008
13009 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
13010 gimple_seq_add_stmt (seq, stmt);
13011
13012 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
13013 gimple_seq_add_stmt (seq, stmt);
13014
13015 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
13016 gimple_seq_add_stmt (seq, stmt);
13017
13018 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
13019 gimple_seq_add_stmt (seq, stmt);
13020 }
13021 else
13022 gcc_unreachable ();
13023
13024 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
13025 gimplify_assign (dest, result, seq);
13026 }
13027
13028 /* Initialize the reduction array with default values. */
13029
13030 static void
13031 oacc_init_reduction_array (tree array, tree init, tree nthreads,
13032 gimple_seq *stmt_seqp)
13033 {
13034 tree type = TREE_TYPE (TREE_TYPE (array));
13035 tree x, loop_header, loop_body, loop_exit;
13036 gimple *stmt;
13037
13038 /* Create for loop.
13039
13040 let var = the original reduction variable
13041 let array = reduction variable array
13042
13043 for (i = 0; i < nthreads; i++)
13044 var op= array[i]
13045 */
13046
13047 loop_header = create_artificial_label (UNKNOWN_LOCATION);
13048 loop_body = create_artificial_label (UNKNOWN_LOCATION);
13049 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
13050
13051 /* Create and initialize an index variable. */
13052 tree ix = create_tmp_var (sizetype);
13053 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
13054 stmt_seqp);
13055
13056 /* Insert the loop header label here. */
13057 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
13058
13059 /* Exit loop if ix >= nthreads. */
13060 x = create_tmp_var (sizetype);
13061 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
13062 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
13063 gimple_seq_add_stmt (stmt_seqp, stmt);
13064
13065 /* Insert the loop body label here. */
13066 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
13067
13068 /* Calculate the array offset. */
13069 tree offset = create_tmp_var (sizetype);
13070 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
13071 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
13072 gimple_seq_add_stmt (stmt_seqp, stmt);
13073
13074 tree ptr = create_tmp_var (TREE_TYPE (array));
13075 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
13076 gimple_seq_add_stmt (stmt_seqp, stmt);
13077
13078 /* Assign init. */
13079 gimplify_assign (build_simple_mem_ref (ptr), init, stmt_seqp);
13080
13081 /* Increment the induction variable. */
13082 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
13083 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
13084 gimple_seq_add_stmt (stmt_seqp, stmt);
13085
13086 /* Go back to the top of the loop. */
13087 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
13088
13089 /* Place the loop exit label here. */
13090 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
13091 }
13092
13093 /* Helper function to initialize local data for the reduction arrays.
13094 The reduction arrays need to be placed inside the calling function
13095 for accelerators, or else the host won't be able to preform the final
13096 reduction. */
13097
13098 static void
13099 oacc_initialize_reduction_data (tree clauses, tree nthreads,
13100 gimple_seq *stmt_seqp, omp_context *ctx)
13101 {
13102 tree c, t, oc;
13103 gimple *stmt;
13104 omp_context *octx;
13105
13106 /* Find the innermost OpenACC parallel context. */
13107 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
13108 && (gimple_omp_target_kind (ctx->stmt)
13109 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
13110 octx = ctx;
13111 else
13112 octx = ctx->outer;
13113 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
13114 && (gimple_omp_target_kind (octx->stmt)
13115 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
13116
13117 /* Extract the clauses. */
13118 oc = gimple_omp_target_clauses (octx->stmt);
13119
13120 /* Find the last outer clause. */
13121 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
13122 ;
13123
13124 /* Allocate arrays for each reduction variable. */
13125 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13126 {
13127 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
13128 continue;
13129
13130 tree var = OMP_CLAUSE_DECL (c);
13131 tree type = get_base_type (var);
13132 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
13133 ctx);
13134 tree size, call;
13135
13136 /* Calculate size of the reduction array. */
13137 t = create_tmp_var (TREE_TYPE (nthreads));
13138 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
13139 fold_convert (TREE_TYPE (nthreads),
13140 TYPE_SIZE_UNIT (type)));
13141 gimple_seq_add_stmt (stmt_seqp, stmt);
13142
13143 size = create_tmp_var (sizetype);
13144 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
13145
13146 /* Now allocate memory for it. */
13147 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
13148 stmt = gimple_build_call (call, 1, size);
13149 gimple_call_set_lhs (stmt, array);
13150 gimple_seq_add_stmt (stmt_seqp, stmt);
13151
13152 /* Initialize array. */
13153 tree init = omp_reduction_init_op (OMP_CLAUSE_LOCATION (c),
13154 OMP_CLAUSE_REDUCTION_CODE (c),
13155 type);
13156 oacc_init_reduction_array (array, init, nthreads, stmt_seqp);
13157
13158 /* Map this array into the accelerator. */
13159
13160 /* Add the reduction array to the list of clauses. */
13161 tree x = array;
13162 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
13163 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_TOFROM);
13164 OMP_CLAUSE_DECL (t) = x;
13165 OMP_CLAUSE_CHAIN (t) = NULL;
13166 if (oc)
13167 OMP_CLAUSE_CHAIN (oc) = t;
13168 else
13169 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
13170 OMP_CLAUSE_SIZE (t) = size;
13171 oc = t;
13172 }
13173 }
13174
13175 /* Helper function to process the array of partial reductions. Nthreads
13176 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
13177 cannot be used here, because nthreads on the host may be different than
13178 on the accelerator. */
13179
13180 static void
13181 oacc_finalize_reduction_data (tree clauses, tree nthreads,
13182 gimple_seq *stmt_seqp, omp_context *ctx)
13183 {
13184 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
13185 gimple *stmt;
13186
13187 /* Create for loop.
13188
13189 let var = the original reduction variable
13190 let array = reduction variable array
13191
13192 for (i = 0; i < nthreads; i++)
13193 var op= array[i]
13194 */
13195
13196 loop_header = create_artificial_label (UNKNOWN_LOCATION);
13197 loop_body = create_artificial_label (UNKNOWN_LOCATION);
13198 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
13199
13200 /* Create and initialize an index variable. */
13201 tree ix = create_tmp_var (sizetype);
13202 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
13203 stmt_seqp);
13204
13205 /* Insert the loop header label here. */
13206 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
13207
13208 /* Exit loop if ix >= nthreads. */
13209 x = create_tmp_var (sizetype);
13210 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
13211 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
13212 gimple_seq_add_stmt (stmt_seqp, stmt);
13213
13214 /* Insert the loop body label here. */
13215 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
13216
13217 /* Collapse each reduction array, one element at a time. */
13218 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13219 {
13220 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
13221 continue;
13222
13223 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
13224
13225 /* reduction(-:var) sums up the partial results, so it acts
13226 identically to reduction(+:var). */
13227 if (reduction_code == MINUS_EXPR)
13228 reduction_code = PLUS_EXPR;
13229
13230 /* Set up reduction variable var. */
13231 var = OMP_CLAUSE_DECL (c);
13232 type = get_base_type (var);
13233 array = lookup_oacc_reduction (oacc_get_reduction_array_id
13234 (OMP_CLAUSE_DECL (c)), ctx);
13235
13236 /* Calculate the array offset. */
13237 tree offset = create_tmp_var (sizetype);
13238 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
13239 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
13240 gimple_seq_add_stmt (stmt_seqp, stmt);
13241
13242 tree ptr = create_tmp_var (TREE_TYPE (array));
13243 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
13244 gimple_seq_add_stmt (stmt_seqp, stmt);
13245
13246 /* Extract array[ix] into mem. */
13247 tree mem = create_tmp_var (type);
13248 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
13249
13250 /* Find the original reduction variable. */
13251 if (is_reference (var))
13252 var = build_simple_mem_ref (var);
13253
13254 tree t = create_tmp_var (type);
13255
13256 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
13257 gimplify_and_add (unshare_expr(x), stmt_seqp);
13258
13259 /* var = var op mem */
13260 switch (OMP_CLAUSE_REDUCTION_CODE (c))
13261 {
13262 case TRUTH_ANDIF_EXPR:
13263 case TRUTH_ORIF_EXPR:
13264 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
13265 t, mem);
13266 gimplify_and_add (t, stmt_seqp);
13267 break;
13268 default:
13269 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
13270 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
13271 stmt_seqp);
13272 }
13273
13274 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
13275 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
13276 gimplify_and_add (unshare_expr(x), stmt_seqp);
13277 }
13278
13279 /* Increment the induction variable. */
13280 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
13281 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
13282 gimple_seq_add_stmt (stmt_seqp, stmt);
13283
13284 /* Go back to the top of the loop. */
13285 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
13286
13287 /* Place the loop exit label here. */
13288 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
13289 }
13290
13291 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
13292 scan that for reductions. */
13293
13294 static void
13295 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
13296 gimple_seq *out_stmt_seqp, omp_context *ctx)
13297 {
13298 gimple_stmt_iterator gsi;
13299 gimple_seq inner = NULL;
13300
13301 /* A collapse clause may have inserted a new bind block. */
13302 gsi = gsi_start (*body);
13303 while (!gsi_end_p (gsi))
13304 {
13305 gimple *stmt = gsi_stmt (gsi);
13306 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
13307 {
13308 inner = gimple_bind_body (bind_stmt);
13309 body = &inner;
13310 gsi = gsi_start (*body);
13311 }
13312 else if (dyn_cast <gomp_for *> (stmt))
13313 break;
13314 else
13315 gsi_next (&gsi);
13316 }
13317
13318 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
13319 {
13320 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
13321 enter, exit;
13322 bool reduction_found = false;
13323
13324 gimple *stmt = gsi_stmt (gsi);
13325
13326 switch (gimple_code (stmt))
13327 {
13328 case GIMPLE_OMP_FOR:
13329 clauses = gimple_omp_for_clauses (stmt);
13330
13331 /* Search for a reduction clause. */
13332 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13333 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
13334 {
13335 reduction_found = true;
13336 break;
13337 }
13338
13339 if (!reduction_found)
13340 break;
13341
13342 ctx = maybe_lookup_ctx (stmt);
13343 t = NULL_TREE;
13344
13345 /* Extract the number of threads. */
13346 nthreads = create_tmp_var (sizetype);
13347 t = oacc_max_threads (ctx);
13348 gimplify_assign (nthreads, t, in_stmt_seqp);
13349
13350 /* Determine if this is kernel will be executed on the host. */
13351 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
13352 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
13353 stmt = gimple_build_call (call, 0);
13354 gimple_call_set_lhs (stmt, acc_device);
13355 gimple_seq_add_stmt (in_stmt_seqp, stmt);
13356
13357 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
13358 acc_device_host = create_tmp_var (integer_type_node,
13359 ".acc_device_host");
13360 gimplify_assign (acc_device_host,
13361 build_int_cst (integer_type_node,
13362 GOMP_DEVICE_HOST),
13363 in_stmt_seqp);
13364
13365 enter = create_artificial_label (UNKNOWN_LOCATION);
13366 exit = create_artificial_label (UNKNOWN_LOCATION);
13367
13368 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
13369 enter, exit);
13370 gimple_seq_add_stmt (in_stmt_seqp, stmt);
13371 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
13372 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
13373 integer_one_node),
13374 in_stmt_seqp);
13375 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
13376
13377 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
13378 ctx);
13379 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
13380 break;
13381 default:
13382 // Scan for other directives which support reduction here.
13383 break;
13384 }
13385 }
13386 }
13387
13388 /* If ctx is a worksharing context inside of a cancellable parallel
13389 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13390 and conditional branch to parallel's cancel_label to handle
13391 cancellation in the implicit barrier. */
13392
13393 static void
13394 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13395 {
13396 gimple *omp_return = gimple_seq_last_stmt (*body);
13397 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13398 if (gimple_omp_return_nowait_p (omp_return))
13399 return;
13400 if (ctx->outer
13401 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13402 && ctx->outer->cancellable)
13403 {
13404 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13405 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
13406 tree lhs = create_tmp_var (c_bool_type);
13407 gimple_omp_return_set_lhs (omp_return, lhs);
13408 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
13409 gimple *g = gimple_build_cond (NE_EXPR, lhs,
13410 fold_convert (c_bool_type,
13411 boolean_false_node),
13412 ctx->outer->cancel_label, fallthru_label);
13413 gimple_seq_add_stmt (body, g);
13414 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13415 }
13416 }
13417
13418 /* Lower the OpenMP sections directive in the current statement in GSI_P.
13419 CTX is the enclosing OMP context for the current statement. */
13420
13421 static void
13422 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13423 {
13424 tree block, control;
13425 gimple_stmt_iterator tgsi;
13426 gomp_sections *stmt;
13427 gimple *t;
13428 gbind *new_stmt, *bind;
13429 gimple_seq ilist, dlist, olist, new_body;
13430
13431 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
13432
13433 push_gimplify_context ();
13434
13435 dlist = NULL;
13436 ilist = NULL;
13437 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
13438 &ilist, &dlist, ctx, NULL);
13439
13440 new_body = gimple_omp_body (stmt);
13441 gimple_omp_set_body (stmt, NULL);
13442 tgsi = gsi_start (new_body);
13443 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
13444 {
13445 omp_context *sctx;
13446 gimple *sec_start;
13447
13448 sec_start = gsi_stmt (tgsi);
13449 sctx = maybe_lookup_ctx (sec_start);
13450 gcc_assert (sctx);
13451
13452 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13453 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13454 GSI_CONTINUE_LINKING);
13455 gimple_omp_set_body (sec_start, NULL);
13456
13457 if (gsi_one_before_end_p (tgsi))
13458 {
13459 gimple_seq l = NULL;
13460 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
13461 &l, ctx);
13462 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
13463 gimple_omp_section_set_last (sec_start);
13464 }
13465
13466 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13467 GSI_CONTINUE_LINKING);
13468 }
13469
13470 block = make_node (BLOCK);
13471 bind = gimple_build_bind (NULL, new_body, block);
13472
13473 olist = NULL;
13474 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
13475
13476 block = make_node (BLOCK);
13477 new_stmt = gimple_build_bind (NULL, NULL, block);
13478 gsi_replace (gsi_p, new_stmt, true);
13479
13480 pop_gimplify_context (new_stmt);
13481 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13482 BLOCK_VARS (block) = gimple_bind_vars (bind);
13483 if (BLOCK_VARS (block))
13484 TREE_USED (block) = 1;
13485
13486 new_body = NULL;
13487 gimple_seq_add_seq (&new_body, ilist);
13488 gimple_seq_add_stmt (&new_body, stmt);
13489 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13490 gimple_seq_add_stmt (&new_body, bind);
13491
13492 control = create_tmp_var (unsigned_type_node, ".section");
13493 t = gimple_build_omp_continue (control, control);
13494 gimple_omp_sections_set_control (stmt, control);
13495 gimple_seq_add_stmt (&new_body, t);
13496
13497 gimple_seq_add_seq (&new_body, olist);
13498 if (ctx->cancellable)
13499 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
13500 gimple_seq_add_seq (&new_body, dlist);
13501
13502 new_body = maybe_catch_exception (new_body);
13503
13504 t = gimple_build_omp_return
13505 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13506 OMP_CLAUSE_NOWAIT));
13507 gimple_seq_add_stmt (&new_body, t);
13508 maybe_add_implicit_barrier_cancel (ctx, &new_body);
13509
13510 gimple_bind_set_body (new_stmt, new_body);
13511 }
13512
13513
13514 /* A subroutine of lower_omp_single. Expand the simple form of
13515 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
13516
13517 if (GOMP_single_start ())
13518 BODY;
13519 [ GOMP_barrier (); ] -> unless 'nowait' is present.
13520
13521 FIXME. It may be better to delay expanding the logic of this until
13522 pass_expand_omp. The expanded logic may make the job more difficult
13523 to a synchronization analysis pass. */
13524
13525 static void
13526 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
13527 {
13528 location_t loc = gimple_location (single_stmt);
13529 tree tlabel = create_artificial_label (loc);
13530 tree flabel = create_artificial_label (loc);
13531 gimple *call, *cond;
13532 tree lhs, decl;
13533
13534 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
13535 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
13536 call = gimple_build_call (decl, 0);
13537 gimple_call_set_lhs (call, lhs);
13538 gimple_seq_add_stmt (pre_p, call);
13539
13540 cond = gimple_build_cond (EQ_EXPR, lhs,
13541 fold_convert_loc (loc, TREE_TYPE (lhs),
13542 boolean_true_node),
13543 tlabel, flabel);
13544 gimple_seq_add_stmt (pre_p, cond);
13545 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13546 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13547 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
13548 }
13549
13550
13551 /* A subroutine of lower_omp_single. Expand the simple form of
13552 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
13553
13554 #pragma omp single copyprivate (a, b, c)
13555
13556 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13557
13558 {
13559 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13560 {
13561 BODY;
13562 copyout.a = a;
13563 copyout.b = b;
13564 copyout.c = c;
13565 GOMP_single_copy_end (&copyout);
13566 }
13567 else
13568 {
13569 a = copyout_p->a;
13570 b = copyout_p->b;
13571 c = copyout_p->c;
13572 }
13573 GOMP_barrier ();
13574 }
13575
13576 FIXME. It may be better to delay expanding the logic of this until
13577 pass_expand_omp. The expanded logic may make the job more difficult
13578 to a synchronization analysis pass. */
13579
13580 static void
13581 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13582 omp_context *ctx)
13583 {
13584 tree ptr_type, t, l0, l1, l2, bfn_decl;
13585 gimple_seq copyin_seq;
13586 location_t loc = gimple_location (single_stmt);
13587
13588 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13589
13590 ptr_type = build_pointer_type (ctx->record_type);
13591 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13592
13593 l0 = create_artificial_label (loc);
13594 l1 = create_artificial_label (loc);
13595 l2 = create_artificial_label (loc);
13596
13597 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13598 t = build_call_expr_loc (loc, bfn_decl, 0);
13599 t = fold_convert_loc (loc, ptr_type, t);
13600 gimplify_assign (ctx->receiver_decl, t, pre_p);
13601
13602 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13603 build_int_cst (ptr_type, 0));
13604 t = build3 (COND_EXPR, void_type_node, t,
13605 build_and_jump (&l0), build_and_jump (&l1));
13606 gimplify_and_add (t, pre_p);
13607
13608 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
13609
13610 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13611
13612 copyin_seq = NULL;
13613 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
13614 &copyin_seq, ctx);
13615
13616 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
13617 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13618 t = build_call_expr_loc (loc, bfn_decl, 1, t);
13619 gimplify_and_add (t, pre_p);
13620
13621 t = build_and_jump (&l2);
13622 gimplify_and_add (t, pre_p);
13623
13624 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
13625
13626 gimple_seq_add_seq (pre_p, copyin_seq);
13627
13628 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
13629 }
13630
13631
13632 /* Expand code for an OpenMP single directive. */
13633
13634 static void
13635 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13636 {
13637 tree block;
13638 gimple *t;
13639 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13640 gbind *bind;
13641 gimple_seq bind_body, bind_body_tail = NULL, dlist;
13642
13643 push_gimplify_context ();
13644
13645 block = make_node (BLOCK);
13646 bind = gimple_build_bind (NULL, NULL, block);
13647 gsi_replace (gsi_p, bind, true);
13648 bind_body = NULL;
13649 dlist = NULL;
13650 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
13651 &bind_body, &dlist, ctx, NULL);
13652 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
13653
13654 gimple_seq_add_stmt (&bind_body, single_stmt);
13655
13656 if (ctx->record_type)
13657 lower_omp_single_copy (single_stmt, &bind_body, ctx);
13658 else
13659 lower_omp_single_simple (single_stmt, &bind_body);
13660
13661 gimple_omp_set_body (single_stmt, NULL);
13662
13663 gimple_seq_add_seq (&bind_body, dlist);
13664
13665 bind_body = maybe_catch_exception (bind_body);
13666
13667 t = gimple_build_omp_return
13668 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13669 OMP_CLAUSE_NOWAIT));
13670 gimple_seq_add_stmt (&bind_body_tail, t);
13671 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13672 if (ctx->record_type)
13673 {
13674 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13675 tree clobber = build_constructor (ctx->record_type, NULL);
13676 TREE_THIS_VOLATILE (clobber) = 1;
13677 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13678 clobber), GSI_SAME_STMT);
13679 }
13680 gimple_seq_add_seq (&bind_body, bind_body_tail);
13681 gimple_bind_set_body (bind, bind_body);
13682
13683 pop_gimplify_context (bind);
13684
13685 gimple_bind_append_vars (bind, ctx->block_vars);
13686 BLOCK_VARS (block) = ctx->block_vars;
13687 if (BLOCK_VARS (block))
13688 TREE_USED (block) = 1;
13689 }
13690
13691
13692 /* Expand code for an OpenMP master directive. */
13693
13694 static void
13695 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13696 {
13697 tree block, lab = NULL, x, bfn_decl;
13698 gimple *stmt = gsi_stmt (*gsi_p);
13699 gbind *bind;
13700 location_t loc = gimple_location (stmt);
13701 gimple_seq tseq;
13702
13703 push_gimplify_context ();
13704
13705 block = make_node (BLOCK);
13706 bind = gimple_build_bind (NULL, NULL, block);
13707 gsi_replace (gsi_p, bind, true);
13708 gimple_bind_add_stmt (bind, stmt);
13709
13710 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13711 x = build_call_expr_loc (loc, bfn_decl, 0);
13712 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13713 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
13714 tseq = NULL;
13715 gimplify_and_add (x, &tseq);
13716 gimple_bind_add_seq (bind, tseq);
13717
13718 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13719 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13720 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13721 gimple_omp_set_body (stmt, NULL);
13722
13723 gimple_bind_add_stmt (bind, gimple_build_label (lab));
13724
13725 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13726
13727 pop_gimplify_context (bind);
13728
13729 gimple_bind_append_vars (bind, ctx->block_vars);
13730 BLOCK_VARS (block) = ctx->block_vars;
13731 }
13732
13733
13734 /* Expand code for an OpenMP taskgroup directive. */
13735
13736 static void
13737 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13738 {
13739 gimple *stmt = gsi_stmt (*gsi_p);
13740 gcall *x;
13741 gbind *bind;
13742 tree block = make_node (BLOCK);
13743
13744 bind = gimple_build_bind (NULL, NULL, block);
13745 gsi_replace (gsi_p, bind, true);
13746 gimple_bind_add_stmt (bind, stmt);
13747
13748 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13749 0);
13750 gimple_bind_add_stmt (bind, x);
13751
13752 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13753 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13754 gimple_omp_set_body (stmt, NULL);
13755
13756 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13757
13758 gimple_bind_append_vars (bind, ctx->block_vars);
13759 BLOCK_VARS (block) = ctx->block_vars;
13760 }
13761
13762
13763 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13764
13765 static void
13766 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13767 omp_context *ctx)
13768 {
13769 struct omp_for_data fd;
13770 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13771 return;
13772
13773 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13774 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13775 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13776 if (!fd.ordered)
13777 return;
13778
13779 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13780 tree c = gimple_omp_ordered_clauses (ord_stmt);
13781 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13782 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13783 {
13784 /* Merge depend clauses from multiple adjacent
13785 #pragma omp ordered depend(sink:...) constructs
13786 into one #pragma omp ordered depend(sink:...), so that
13787 we can optimize them together. */
13788 gimple_stmt_iterator gsi = *gsi_p;
13789 gsi_next (&gsi);
13790 while (!gsi_end_p (gsi))
13791 {
13792 gimple *stmt = gsi_stmt (gsi);
13793 if (is_gimple_debug (stmt)
13794 || gimple_code (stmt) == GIMPLE_NOP)
13795 {
13796 gsi_next (&gsi);
13797 continue;
13798 }
13799 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13800 break;
13801 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13802 c = gimple_omp_ordered_clauses (ord_stmt2);
13803 if (c == NULL_TREE
13804 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13805 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13806 break;
13807 while (*list_p)
13808 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13809 *list_p = c;
13810 gsi_remove (&gsi, true);
13811 }
13812 }
13813
13814 /* Canonicalize sink dependence clauses into one folded clause if
13815 possible.
13816
13817 The basic algorithm is to create a sink vector whose first
13818 element is the GCD of all the first elements, and whose remaining
13819 elements are the minimum of the subsequent columns.
13820
13821 We ignore dependence vectors whose first element is zero because
13822 such dependencies are known to be executed by the same thread.
13823
13824 We take into account the direction of the loop, so a minimum
13825 becomes a maximum if the loop is iterating forwards. We also
13826 ignore sink clauses where the loop direction is unknown, or where
13827 the offsets are clearly invalid because they are not a multiple
13828 of the loop increment.
13829
13830 For example:
13831
13832 #pragma omp for ordered(2)
13833 for (i=0; i < N; ++i)
13834 for (j=0; j < M; ++j)
13835 {
13836 #pragma omp ordered \
13837 depend(sink:i-8,j-2) \
13838 depend(sink:i,j-1) \ // Completely ignored because i+0.
13839 depend(sink:i-4,j-3) \
13840 depend(sink:i-6,j-4)
13841 #pragma omp ordered depend(source)
13842 }
13843
13844 Folded clause is:
13845
13846 depend(sink:-gcd(8,4,6),-min(2,3,4))
13847 -or-
13848 depend(sink:-2,-2)
13849 */
13850
13851 /* FIXME: Computing GCD's where the first element is zero is
13852 non-trivial in the presence of collapsed loops. Do this later. */
13853 if (fd.collapse > 1)
13854 return;
13855
13856 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13857 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13858 tree folded_dep = NULL_TREE;
13859 /* TRUE if the first dimension's offset is negative. */
13860 bool neg_offset_p = false;
13861
13862 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13863 unsigned int i;
13864 while ((c = *list_p) != NULL)
13865 {
13866 bool remove = false;
13867
13868 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13869 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13870 goto next_ordered_clause;
13871
13872 tree vec;
13873 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13874 vec && TREE_CODE (vec) == TREE_LIST;
13875 vec = TREE_CHAIN (vec), ++i)
13876 {
13877 gcc_assert (i < len);
13878
13879 /* extract_omp_for_data has canonicalized the condition. */
13880 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13881 || fd.loops[i].cond_code == GT_EXPR);
13882 bool forward = fd.loops[i].cond_code == LT_EXPR;
13883 bool maybe_lexically_later = true;
13884
13885 /* While the committee makes up its mind, bail if we have any
13886 non-constant steps. */
13887 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13888 goto lower_omp_ordered_ret;
13889
13890 tree itype = TREE_TYPE (TREE_VALUE (vec));
13891 if (POINTER_TYPE_P (itype))
13892 itype = sizetype;
13893 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13894 TYPE_PRECISION (itype),
13895 TYPE_SIGN (itype));
13896
13897 /* Ignore invalid offsets that are not multiples of the step. */
13898 if (!wi::multiple_of_p
13899 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13900 UNSIGNED))
13901 {
13902 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13903 "ignoring sink clause with offset that is not "
13904 "a multiple of the loop step");
13905 remove = true;
13906 goto next_ordered_clause;
13907 }
13908
13909 /* Calculate the first dimension. The first dimension of
13910 the folded dependency vector is the GCD of the first
13911 elements, while ignoring any first elements whose offset
13912 is 0. */
13913 if (i == 0)
13914 {
13915 /* Ignore dependence vectors whose first dimension is 0. */
13916 if (offset == 0)
13917 {
13918 remove = true;
13919 goto next_ordered_clause;
13920 }
13921 else
13922 {
13923 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
13924 {
13925 error_at (OMP_CLAUSE_LOCATION (c),
13926 "first offset must be in opposite direction "
13927 "of loop iterations");
13928 goto lower_omp_ordered_ret;
13929 }
13930 if (forward)
13931 offset = -offset;
13932 neg_offset_p = forward;
13933 /* Initialize the first time around. */
13934 if (folded_dep == NULL_TREE)
13935 {
13936 folded_dep = c;
13937 folded_deps[0] = offset;
13938 }
13939 else
13940 folded_deps[0] = wi::gcd (folded_deps[0],
13941 offset, UNSIGNED);
13942 }
13943 }
13944 /* Calculate minimum for the remaining dimensions. */
13945 else
13946 {
13947 folded_deps[len + i - 1] = offset;
13948 if (folded_dep == c)
13949 folded_deps[i] = offset;
13950 else if (maybe_lexically_later
13951 && !wi::eq_p (folded_deps[i], offset))
13952 {
13953 if (forward ^ wi::gts_p (folded_deps[i], offset))
13954 {
13955 unsigned int j;
13956 folded_dep = c;
13957 for (j = 1; j <= i; j++)
13958 folded_deps[j] = folded_deps[len + j - 1];
13959 }
13960 else
13961 maybe_lexically_later = false;
13962 }
13963 }
13964 }
13965 gcc_assert (i == len);
13966
13967 remove = true;
13968
13969 next_ordered_clause:
13970 if (remove)
13971 *list_p = OMP_CLAUSE_CHAIN (c);
13972 else
13973 list_p = &OMP_CLAUSE_CHAIN (c);
13974 }
13975
13976 if (folded_dep)
13977 {
13978 if (neg_offset_p)
13979 folded_deps[0] = -folded_deps[0];
13980
13981 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
13982 if (POINTER_TYPE_P (itype))
13983 itype = sizetype;
13984
13985 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
13986 = wide_int_to_tree (itype, folded_deps[0]);
13987 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
13988 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
13989 }
13990
13991 lower_omp_ordered_ret:
13992
13993 /* Ordered without clauses is #pragma omp threads, while we want
13994 a nop instead if we remove all clauses. */
13995 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
13996 gsi_replace (gsi_p, gimple_build_nop (), true);
13997 }
13998
13999
14000 /* Expand code for an OpenMP ordered directive. */
14001
14002 static void
14003 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14004 {
14005 tree block;
14006 gimple *stmt = gsi_stmt (*gsi_p);
14007 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14008 gcall *x;
14009 gbind *bind;
14010 bool simd
14011 = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt), OMP_CLAUSE_SIMD);
14012
14013 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14014 OMP_CLAUSE_DEPEND))
14015 {
14016 /* FIXME: This is needs to be moved to the expansion to verify various
14017 conditions only testable on cfg with dominators computed, and also
14018 all the depend clauses to be merged still might need to be available
14019 for the runtime checks. */
14020 if (0)
14021 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14022 return;
14023 }
14024
14025 push_gimplify_context ();
14026
14027 block = make_node (BLOCK);
14028 bind = gimple_build_bind (NULL, NULL, block);
14029 gsi_replace (gsi_p, bind, true);
14030 gimple_bind_add_stmt (bind, stmt);
14031
14032 if (simd)
14033 {
14034 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 0);
14035 cfun->has_simduid_loops = true;
14036 }
14037 else
14038 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14039 0);
14040 gimple_bind_add_stmt (bind, x);
14041
14042 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14043 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14044 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14045 gimple_omp_set_body (stmt, NULL);
14046
14047 if (simd)
14048 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 0);
14049 else
14050 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14051 0);
14052 gimple_bind_add_stmt (bind, x);
14053
14054 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14055
14056 pop_gimplify_context (bind);
14057
14058 gimple_bind_append_vars (bind, ctx->block_vars);
14059 BLOCK_VARS (block) = gimple_bind_vars (bind);
14060 }
14061
14062
14063 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14064 substitution of a couple of function calls. But in the NAMED case,
14065 requires that languages coordinate a symbol name. It is therefore
14066 best put here in common code. */
14067
14068 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14069
14070 static void
14071 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14072 {
14073 tree block;
14074 tree name, lock, unlock;
14075 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14076 gbind *bind;
14077 location_t loc = gimple_location (stmt);
14078 gimple_seq tbody;
14079
14080 name = gimple_omp_critical_name (stmt);
14081 if (name)
14082 {
14083 tree decl;
14084
14085 if (!critical_name_mutexes)
14086 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14087
14088 tree *n = critical_name_mutexes->get (name);
14089 if (n == NULL)
14090 {
14091 char *new_str;
14092
14093 decl = create_tmp_var_raw (ptr_type_node);
14094
14095 new_str = ACONCAT ((".gomp_critical_user_",
14096 IDENTIFIER_POINTER (name), NULL));
14097 DECL_NAME (decl) = get_identifier (new_str);
14098 TREE_PUBLIC (decl) = 1;
14099 TREE_STATIC (decl) = 1;
14100 DECL_COMMON (decl) = 1;
14101 DECL_ARTIFICIAL (decl) = 1;
14102 DECL_IGNORED_P (decl) = 1;
14103
14104 varpool_node::finalize_decl (decl);
14105
14106 critical_name_mutexes->put (name, decl);
14107 }
14108 else
14109 decl = *n;
14110
14111 /* If '#pragma omp critical' is inside offloaded region or
14112 inside function marked as offloadable, the symbol must be
14113 marked as offloadable too. */
14114 omp_context *octx;
14115 if (cgraph_node::get (current_function_decl)->offloadable)
14116 varpool_node::get_create (decl)->offloadable = 1;
14117 else
14118 for (octx = ctx->outer; octx; octx = octx->outer)
14119 if (is_gimple_omp_offloaded (octx->stmt))
14120 {
14121 varpool_node::get_create (decl)->offloadable = 1;
14122 break;
14123 }
14124
14125 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14126 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14127
14128 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14129 unlock = build_call_expr_loc (loc, unlock, 1,
14130 build_fold_addr_expr_loc (loc, decl));
14131 }
14132 else
14133 {
14134 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14135 lock = build_call_expr_loc (loc, lock, 0);
14136
14137 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14138 unlock = build_call_expr_loc (loc, unlock, 0);
14139 }
14140
14141 push_gimplify_context ();
14142
14143 block = make_node (BLOCK);
14144 bind = gimple_build_bind (NULL, NULL, block);
14145 gsi_replace (gsi_p, bind, true);
14146 gimple_bind_add_stmt (bind, stmt);
14147
14148 tbody = gimple_bind_body (bind);
14149 gimplify_and_add (lock, &tbody);
14150 gimple_bind_set_body (bind, tbody);
14151
14152 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14153 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14154 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14155 gimple_omp_set_body (stmt, NULL);
14156
14157 tbody = gimple_bind_body (bind);
14158 gimplify_and_add (unlock, &tbody);
14159 gimple_bind_set_body (bind, tbody);
14160
14161 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14162
14163 pop_gimplify_context (bind);
14164 gimple_bind_append_vars (bind, ctx->block_vars);
14165 BLOCK_VARS (block) = gimple_bind_vars (bind);
14166 }
14167
14168
14169 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14170 for a lastprivate clause. Given a loop control predicate of (V
14171 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14172 is appended to *DLIST, iterator initialization is appended to
14173 *BODY_P. */
14174
14175 static void
14176 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14177 gimple_seq *dlist, struct omp_context *ctx)
14178 {
14179 tree clauses, cond, vinit;
14180 enum tree_code cond_code;
14181 gimple_seq stmts;
14182
14183 cond_code = fd->loop.cond_code;
14184 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14185
14186 /* When possible, use a strict equality expression. This can let VRP
14187 type optimizations deduce the value and remove a copy. */
14188 if (tree_fits_shwi_p (fd->loop.step))
14189 {
14190 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14191 if (step == 1 || step == -1)
14192 cond_code = EQ_EXPR;
14193 }
14194
14195 tree n2 = fd->loop.n2;
14196 if (fd->collapse > 1
14197 && TREE_CODE (n2) != INTEGER_CST
14198 && gimple_omp_for_combined_into_p (fd->for_stmt))
14199 {
14200 struct omp_context *task_ctx = NULL;
14201 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14202 {
14203 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14204 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
14205 {
14206 struct omp_for_data outer_fd;
14207 extract_omp_for_data (gfor, &outer_fd, NULL);
14208 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14209 }
14210 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14211 task_ctx = ctx->outer->outer;
14212 }
14213 else if (is_task_ctx (ctx->outer))
14214 task_ctx = ctx->outer;
14215 if (task_ctx)
14216 {
14217 int i;
14218 tree innerc
14219 = find_omp_clause (gimple_omp_task_clauses (task_ctx->stmt),
14220 OMP_CLAUSE__LOOPTEMP_);
14221 gcc_assert (innerc);
14222 for (i = 0; i < fd->collapse; i++)
14223 {
14224 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14225 OMP_CLAUSE__LOOPTEMP_);
14226 gcc_assert (innerc);
14227 }
14228 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14229 OMP_CLAUSE__LOOPTEMP_);
14230 if (innerc)
14231 n2 = fold_convert (TREE_TYPE (n2),
14232 lookup_decl (OMP_CLAUSE_DECL (innerc),
14233 task_ctx));
14234 }
14235 }
14236 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14237
14238 clauses = gimple_omp_for_clauses (fd->for_stmt);
14239 stmts = NULL;
14240 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14241 if (!gimple_seq_empty_p (stmts))
14242 {
14243 gimple_seq_add_seq (&stmts, *dlist);
14244 *dlist = stmts;
14245
14246 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14247 vinit = fd->loop.n1;
14248 if (cond_code == EQ_EXPR
14249 && tree_fits_shwi_p (fd->loop.n2)
14250 && ! integer_zerop (fd->loop.n2))
14251 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
14252 else
14253 vinit = unshare_expr (vinit);
14254
14255 /* Initialize the iterator variable, so that threads that don't execute
14256 any iterations don't execute the lastprivate clauses by accident. */
14257 gimplify_assign (fd->loop.v, vinit, body_p);
14258 }
14259 }
14260
14261
14262 /* Lower code for an OMP loop directive. */
14263
14264 static void
14265 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14266 {
14267 tree *rhs_p, block;
14268 struct omp_for_data fd, *fdp = NULL;
14269 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14270 gbind *new_stmt;
14271 gimple_seq omp_for_body, body, dlist;
14272 gimple_seq oacc_head = NULL, oacc_tail = NULL;
14273 size_t i;
14274
14275 push_gimplify_context ();
14276
14277 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
14278
14279 block = make_node (BLOCK);
14280 new_stmt = gimple_build_bind (NULL, NULL, block);
14281 /* Replace at gsi right away, so that 'stmt' is no member
14282 of a sequence anymore as we're going to add to a different
14283 one below. */
14284 gsi_replace (gsi_p, new_stmt, true);
14285
14286 /* Move declaration of temporaries in the loop body before we make
14287 it go away. */
14288 omp_for_body = gimple_omp_body (stmt);
14289 if (!gimple_seq_empty_p (omp_for_body)
14290 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14291 {
14292 gbind *inner_bind
14293 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
14294 tree vars = gimple_bind_vars (inner_bind);
14295 gimple_bind_append_vars (new_stmt, vars);
14296 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14297 keep them on the inner_bind and it's block. */
14298 gimple_bind_set_vars (inner_bind, NULL_TREE);
14299 if (gimple_bind_block (inner_bind))
14300 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
14301 }
14302
14303 if (gimple_omp_for_combined_into_p (stmt))
14304 {
14305 extract_omp_for_data (stmt, &fd, NULL);
14306 fdp = &fd;
14307
14308 /* We need two temporaries with fd.loop.v type (istart/iend)
14309 and then (fd.collapse - 1) temporaries with the same
14310 type for count2 ... countN-1 vars if not constant. */
14311 size_t count = 2;
14312 tree type = fd.iter_type;
14313 if (fd.collapse > 1
14314 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14315 count += fd.collapse - 1;
14316 bool taskreg_for
14317 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14318 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
14319 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14320 tree clauses = *pc;
14321 if (taskreg_for)
14322 outerc
14323 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
14324 OMP_CLAUSE__LOOPTEMP_);
14325 for (i = 0; i < count; i++)
14326 {
14327 tree temp;
14328 if (taskreg_for)
14329 {
14330 gcc_assert (outerc);
14331 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14332 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14333 OMP_CLAUSE__LOOPTEMP_);
14334 }
14335 else
14336 {
14337 temp = create_tmp_var (type);
14338 insert_decl_map (&ctx->outer->cb, temp, temp);
14339 }
14340 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14341 OMP_CLAUSE_DECL (*pc) = temp;
14342 pc = &OMP_CLAUSE_CHAIN (*pc);
14343 }
14344 *pc = clauses;
14345 }
14346
14347 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
14348 dlist = NULL;
14349 body = NULL;
14350 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14351 fdp);
14352 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
14353
14354 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14355
14356 /* Lower the header expressions. At this point, we can assume that
14357 the header is of the form:
14358
14359 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14360
14361 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14362 using the .omp_data_s mapping, if needed. */
14363 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
14364 {
14365 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
14366 if (!is_gimple_min_invariant (*rhs_p))
14367 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14368
14369 rhs_p = gimple_omp_for_final_ptr (stmt, i);
14370 if (!is_gimple_min_invariant (*rhs_p))
14371 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14372
14373 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
14374 if (!is_gimple_min_invariant (*rhs_p))
14375 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14376 }
14377
14378 /* Once lowered, extract the bounds and clauses. */
14379 extract_omp_for_data (stmt, &fd, NULL);
14380
14381 if (is_gimple_omp_oacc (ctx->stmt)
14382 && !ctx_in_oacc_kernels_region (ctx))
14383 lower_oacc_head_tail (gimple_location (stmt),
14384 gimple_omp_for_clauses (stmt),
14385 &oacc_head, &oacc_tail, ctx);
14386
14387 /* Add OpenACC partitioning markers just before the loop */
14388 if (oacc_head)
14389 gimple_seq_add_seq (&body, oacc_head);
14390
14391 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
14392
14393 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14394 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14395 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14396 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14397 {
14398 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14399 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14400 OMP_CLAUSE_LINEAR_STEP (c)
14401 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14402 ctx);
14403 }
14404
14405 gimple_seq_add_stmt (&body, stmt);
14406 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
14407
14408 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14409 fd.loop.v));
14410
14411 /* After the loop, add exit clauses. */
14412 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
14413
14414 if (ctx->cancellable)
14415 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14416
14417 gimple_seq_add_seq (&body, dlist);
14418
14419 body = maybe_catch_exception (body);
14420
14421 /* Region exit marker goes at the end of the loop body. */
14422 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
14423 maybe_add_implicit_barrier_cancel (ctx, &body);
14424
14425 /* Add OpenACC joining and reduction markers just after the loop. */
14426 if (oacc_tail)
14427 gimple_seq_add_seq (&body, oacc_tail);
14428
14429 pop_gimplify_context (new_stmt);
14430
14431 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14432 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
14433 if (BLOCK_VARS (block))
14434 TREE_USED (block) = 1;
14435
14436 gimple_bind_set_body (new_stmt, body);
14437 gimple_omp_set_body (stmt, NULL);
14438 gimple_omp_for_set_pre_body (stmt, NULL);
14439 }
14440
14441 /* Callback for walk_stmts. Check if the current statement only contains
14442 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
14443
14444 static tree
14445 check_combined_parallel (gimple_stmt_iterator *gsi_p,
14446 bool *handled_ops_p,
14447 struct walk_stmt_info *wi)
14448 {
14449 int *info = (int *) wi->info;
14450 gimple *stmt = gsi_stmt (*gsi_p);
14451
14452 *handled_ops_p = true;
14453 switch (gimple_code (stmt))
14454 {
14455 WALK_SUBSTMTS;
14456
14457 case GIMPLE_OMP_FOR:
14458 case GIMPLE_OMP_SECTIONS:
14459 *info = *info == 0 ? 1 : -1;
14460 break;
14461 default:
14462 *info = -1;
14463 break;
14464 }
14465 return NULL;
14466 }
14467
14468 struct omp_taskcopy_context
14469 {
14470 /* This field must be at the beginning, as we do "inheritance": Some
14471 callback functions for tree-inline.c (e.g., omp_copy_decl)
14472 receive a copy_body_data pointer that is up-casted to an
14473 omp_context pointer. */
14474 copy_body_data cb;
14475 omp_context *ctx;
14476 };
14477
14478 static tree
14479 task_copyfn_copy_decl (tree var, copy_body_data *cb)
14480 {
14481 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14482
14483 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
14484 return create_tmp_var (TREE_TYPE (var));
14485
14486 return var;
14487 }
14488
14489 static tree
14490 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14491 {
14492 tree name, new_fields = NULL, type, f;
14493
14494 type = lang_hooks.types.make_type (RECORD_TYPE);
14495 name = DECL_NAME (TYPE_NAME (orig_type));
14496 name = build_decl (gimple_location (tcctx->ctx->stmt),
14497 TYPE_DECL, name, type);
14498 TYPE_NAME (type) = name;
14499
14500 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14501 {
14502 tree new_f = copy_node (f);
14503 DECL_CONTEXT (new_f) = type;
14504 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14505 TREE_CHAIN (new_f) = new_fields;
14506 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14507 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14508 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14509 &tcctx->cb, NULL);
14510 new_fields = new_f;
14511 tcctx->cb.decl_map->put (f, new_f);
14512 }
14513 TYPE_FIELDS (type) = nreverse (new_fields);
14514 layout_type (type);
14515 return type;
14516 }
14517
14518 /* Create task copyfn. */
14519
14520 static void
14521 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
14522 {
14523 struct function *child_cfun;
14524 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14525 tree record_type, srecord_type, bind, list;
14526 bool record_needs_remap = false, srecord_needs_remap = false;
14527 splay_tree_node n;
14528 struct omp_taskcopy_context tcctx;
14529 location_t loc = gimple_location (task_stmt);
14530
14531 child_fn = gimple_omp_task_copy_fn (task_stmt);
14532 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14533 gcc_assert (child_cfun->cfg == NULL);
14534 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14535
14536 /* Reset DECL_CONTEXT on function arguments. */
14537 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
14538 DECL_CONTEXT (t) = child_fn;
14539
14540 /* Populate the function. */
14541 push_gimplify_context ();
14542 push_cfun (child_cfun);
14543
14544 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14545 TREE_SIDE_EFFECTS (bind) = 1;
14546 list = NULL;
14547 DECL_SAVED_TREE (child_fn) = bind;
14548 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
14549
14550 /* Remap src and dst argument types if needed. */
14551 record_type = ctx->record_type;
14552 srecord_type = ctx->srecord_type;
14553 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
14554 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14555 {
14556 record_needs_remap = true;
14557 break;
14558 }
14559 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
14560 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14561 {
14562 srecord_needs_remap = true;
14563 break;
14564 }
14565
14566 if (record_needs_remap || srecord_needs_remap)
14567 {
14568 memset (&tcctx, '\0', sizeof (tcctx));
14569 tcctx.cb.src_fn = ctx->cb.src_fn;
14570 tcctx.cb.dst_fn = child_fn;
14571 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
14572 gcc_checking_assert (tcctx.cb.src_node);
14573 tcctx.cb.dst_node = tcctx.cb.src_node;
14574 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14575 tcctx.cb.copy_decl = task_copyfn_copy_decl;
14576 tcctx.cb.eh_lp_nr = 0;
14577 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
14578 tcctx.cb.decl_map = new hash_map<tree, tree>;
14579 tcctx.ctx = ctx;
14580
14581 if (record_needs_remap)
14582 record_type = task_copyfn_remap_type (&tcctx, record_type);
14583 if (srecord_needs_remap)
14584 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14585 }
14586 else
14587 tcctx.cb.decl_map = NULL;
14588
14589 arg = DECL_ARGUMENTS (child_fn);
14590 TREE_TYPE (arg) = build_pointer_type (record_type);
14591 sarg = DECL_CHAIN (arg);
14592 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14593
14594 /* First pass: initialize temporaries used in record_type and srecord_type
14595 sizes and field offsets. */
14596 if (tcctx.cb.decl_map)
14597 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14598 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14599 {
14600 tree *p;
14601
14602 decl = OMP_CLAUSE_DECL (c);
14603 p = tcctx.cb.decl_map->get (decl);
14604 if (p == NULL)
14605 continue;
14606 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14607 sf = (tree) n->value;
14608 sf = *tcctx.cb.decl_map->get (sf);
14609 src = build_simple_mem_ref_loc (loc, sarg);
14610 src = omp_build_component_ref (src, sf);
14611 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
14612 append_to_statement_list (t, &list);
14613 }
14614
14615 /* Second pass: copy shared var pointers and copy construct non-VLA
14616 firstprivate vars. */
14617 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14618 switch (OMP_CLAUSE_CODE (c))
14619 {
14620 splay_tree_key key;
14621 case OMP_CLAUSE_SHARED:
14622 decl = OMP_CLAUSE_DECL (c);
14623 key = (splay_tree_key) decl;
14624 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14625 key = (splay_tree_key) &DECL_UID (decl);
14626 n = splay_tree_lookup (ctx->field_map, key);
14627 if (n == NULL)
14628 break;
14629 f = (tree) n->value;
14630 if (tcctx.cb.decl_map)
14631 f = *tcctx.cb.decl_map->get (f);
14632 n = splay_tree_lookup (ctx->sfield_map, key);
14633 sf = (tree) n->value;
14634 if (tcctx.cb.decl_map)
14635 sf = *tcctx.cb.decl_map->get (sf);
14636 src = build_simple_mem_ref_loc (loc, sarg);
14637 src = omp_build_component_ref (src, sf);
14638 dst = build_simple_mem_ref_loc (loc, arg);
14639 dst = omp_build_component_ref (dst, f);
14640 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14641 append_to_statement_list (t, &list);
14642 break;
14643 case OMP_CLAUSE_FIRSTPRIVATE:
14644 decl = OMP_CLAUSE_DECL (c);
14645 if (is_variable_sized (decl))
14646 break;
14647 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14648 if (n == NULL)
14649 break;
14650 f = (tree) n->value;
14651 if (tcctx.cb.decl_map)
14652 f = *tcctx.cb.decl_map->get (f);
14653 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14654 if (n != NULL)
14655 {
14656 sf = (tree) n->value;
14657 if (tcctx.cb.decl_map)
14658 sf = *tcctx.cb.decl_map->get (sf);
14659 src = build_simple_mem_ref_loc (loc, sarg);
14660 src = omp_build_component_ref (src, sf);
14661 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
14662 src = build_simple_mem_ref_loc (loc, src);
14663 }
14664 else
14665 src = decl;
14666 dst = build_simple_mem_ref_loc (loc, arg);
14667 dst = omp_build_component_ref (dst, f);
14668 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14669 append_to_statement_list (t, &list);
14670 break;
14671 case OMP_CLAUSE_PRIVATE:
14672 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14673 break;
14674 decl = OMP_CLAUSE_DECL (c);
14675 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14676 f = (tree) n->value;
14677 if (tcctx.cb.decl_map)
14678 f = *tcctx.cb.decl_map->get (f);
14679 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14680 if (n != NULL)
14681 {
14682 sf = (tree) n->value;
14683 if (tcctx.cb.decl_map)
14684 sf = *tcctx.cb.decl_map->get (sf);
14685 src = build_simple_mem_ref_loc (loc, sarg);
14686 src = omp_build_component_ref (src, sf);
14687 if (use_pointer_for_field (decl, NULL))
14688 src = build_simple_mem_ref_loc (loc, src);
14689 }
14690 else
14691 src = decl;
14692 dst = build_simple_mem_ref_loc (loc, arg);
14693 dst = omp_build_component_ref (dst, f);
14694 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14695 append_to_statement_list (t, &list);
14696 break;
14697 default:
14698 break;
14699 }
14700
14701 /* Last pass: handle VLA firstprivates. */
14702 if (tcctx.cb.decl_map)
14703 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14704 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14705 {
14706 tree ind, ptr, df;
14707
14708 decl = OMP_CLAUSE_DECL (c);
14709 if (!is_variable_sized (decl))
14710 continue;
14711 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14712 if (n == NULL)
14713 continue;
14714 f = (tree) n->value;
14715 f = *tcctx.cb.decl_map->get (f);
14716 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14717 ind = DECL_VALUE_EXPR (decl);
14718 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14719 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14720 n = splay_tree_lookup (ctx->sfield_map,
14721 (splay_tree_key) TREE_OPERAND (ind, 0));
14722 sf = (tree) n->value;
14723 sf = *tcctx.cb.decl_map->get (sf);
14724 src = build_simple_mem_ref_loc (loc, sarg);
14725 src = omp_build_component_ref (src, sf);
14726 src = build_simple_mem_ref_loc (loc, src);
14727 dst = build_simple_mem_ref_loc (loc, arg);
14728 dst = omp_build_component_ref (dst, f);
14729 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14730 append_to_statement_list (t, &list);
14731 n = splay_tree_lookup (ctx->field_map,
14732 (splay_tree_key) TREE_OPERAND (ind, 0));
14733 df = (tree) n->value;
14734 df = *tcctx.cb.decl_map->get (df);
14735 ptr = build_simple_mem_ref_loc (loc, arg);
14736 ptr = omp_build_component_ref (ptr, df);
14737 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
14738 build_fold_addr_expr_loc (loc, dst));
14739 append_to_statement_list (t, &list);
14740 }
14741
14742 t = build1 (RETURN_EXPR, void_type_node, NULL);
14743 append_to_statement_list (t, &list);
14744
14745 if (tcctx.cb.decl_map)
14746 delete tcctx.cb.decl_map;
14747 pop_gimplify_context (NULL);
14748 BIND_EXPR_BODY (bind) = list;
14749 pop_cfun ();
14750 }
14751
14752 static void
14753 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
14754 {
14755 tree c, clauses;
14756 gimple *g;
14757 size_t n_in = 0, n_out = 0, idx = 2, i;
14758
14759 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
14760 gcc_assert (clauses);
14761 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14762 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14763 switch (OMP_CLAUSE_DEPEND_KIND (c))
14764 {
14765 case OMP_CLAUSE_DEPEND_IN:
14766 n_in++;
14767 break;
14768 case OMP_CLAUSE_DEPEND_OUT:
14769 case OMP_CLAUSE_DEPEND_INOUT:
14770 n_out++;
14771 break;
14772 case OMP_CLAUSE_DEPEND_SOURCE:
14773 case OMP_CLAUSE_DEPEND_SINK:
14774 /* FALLTHRU */
14775 default:
14776 gcc_unreachable ();
14777 }
14778 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
14779 tree array = create_tmp_var (type);
14780 TREE_ADDRESSABLE (array) = 1;
14781 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14782 NULL_TREE);
14783 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14784 gimple_seq_add_stmt (iseq, g);
14785 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14786 NULL_TREE);
14787 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14788 gimple_seq_add_stmt (iseq, g);
14789 for (i = 0; i < 2; i++)
14790 {
14791 if ((i ? n_in : n_out) == 0)
14792 continue;
14793 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14794 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14795 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14796 {
14797 tree t = OMP_CLAUSE_DECL (c);
14798 t = fold_convert (ptr_type_node, t);
14799 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14800 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14801 NULL_TREE, NULL_TREE);
14802 g = gimple_build_assign (r, t);
14803 gimple_seq_add_stmt (iseq, g);
14804 }
14805 }
14806 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14807 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
14808 OMP_CLAUSE_CHAIN (c) = *pclauses;
14809 *pclauses = c;
14810 tree clobber = build_constructor (type, NULL);
14811 TREE_THIS_VOLATILE (clobber) = 1;
14812 g = gimple_build_assign (array, clobber);
14813 gimple_seq_add_stmt (oseq, g);
14814 }
14815
14816 /* Lower the OpenMP parallel or task directive in the current statement
14817 in GSI_P. CTX holds context information for the directive. */
14818
14819 static void
14820 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14821 {
14822 tree clauses;
14823 tree child_fn, t;
14824 gimple *stmt = gsi_stmt (*gsi_p);
14825 gbind *par_bind, *bind, *dep_bind = NULL;
14826 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
14827 location_t loc = gimple_location (stmt);
14828
14829 clauses = gimple_omp_taskreg_clauses (stmt);
14830 par_bind
14831 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
14832 par_body = gimple_bind_body (par_bind);
14833 child_fn = ctx->cb.dst_fn;
14834 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14835 && !gimple_omp_parallel_combined_p (stmt))
14836 {
14837 struct walk_stmt_info wi;
14838 int ws_num = 0;
14839
14840 memset (&wi, 0, sizeof (wi));
14841 wi.info = &ws_num;
14842 wi.val_only = true;
14843 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
14844 if (ws_num == 1)
14845 gimple_omp_parallel_set_combined_p (stmt, true);
14846 }
14847 gimple_seq dep_ilist = NULL;
14848 gimple_seq dep_olist = NULL;
14849 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14850 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14851 {
14852 push_gimplify_context ();
14853 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14854 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14855 &dep_ilist, &dep_olist);
14856 }
14857
14858 if (ctx->srecord_type)
14859 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
14860
14861 push_gimplify_context ();
14862
14863 par_olist = NULL;
14864 par_ilist = NULL;
14865 par_rlist = NULL;
14866 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
14867 lower_omp (&par_body, ctx);
14868 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
14869 lower_reduction_clauses (clauses, &par_rlist, ctx);
14870
14871 /* Declare all the variables created by mapping and the variables
14872 declared in the scope of the parallel body. */
14873 record_vars_into (ctx->block_vars, child_fn);
14874 record_vars_into (gimple_bind_vars (par_bind), child_fn);
14875
14876 if (ctx->record_type)
14877 {
14878 ctx->sender_decl
14879 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14880 : ctx->record_type, ".omp_data_o");
14881 DECL_NAMELESS (ctx->sender_decl) = 1;
14882 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
14883 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
14884 }
14885
14886 olist = NULL;
14887 ilist = NULL;
14888 lower_send_clauses (clauses, &ilist, &olist, ctx);
14889 lower_send_shared_vars (&ilist, &olist, ctx);
14890
14891 if (ctx->record_type)
14892 {
14893 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
14894 TREE_THIS_VOLATILE (clobber) = 1;
14895 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14896 clobber));
14897 }
14898
14899 /* Once all the expansions are done, sequence all the different
14900 fragments inside gimple_omp_body. */
14901
14902 new_body = NULL;
14903
14904 if (ctx->record_type)
14905 {
14906 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14907 /* fixup_child_record_type might have changed receiver_decl's type. */
14908 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
14909 gimple_seq_add_stmt (&new_body,
14910 gimple_build_assign (ctx->receiver_decl, t));
14911 }
14912
14913 gimple_seq_add_seq (&new_body, par_ilist);
14914 gimple_seq_add_seq (&new_body, par_body);
14915 gimple_seq_add_seq (&new_body, par_rlist);
14916 if (ctx->cancellable)
14917 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14918 gimple_seq_add_seq (&new_body, par_olist);
14919 new_body = maybe_catch_exception (new_body);
14920 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
14921 gimple_seq_add_stmt (&new_body,
14922 gimple_build_omp_continue (integer_zero_node,
14923 integer_zero_node));
14924 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14925 gimple_omp_set_body (stmt, new_body);
14926
14927 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
14928 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14929 gimple_bind_add_seq (bind, ilist);
14930 gimple_bind_add_stmt (bind, stmt);
14931 gimple_bind_add_seq (bind, olist);
14932
14933 pop_gimplify_context (NULL);
14934
14935 if (dep_bind)
14936 {
14937 gimple_bind_add_seq (dep_bind, dep_ilist);
14938 gimple_bind_add_stmt (dep_bind, bind);
14939 gimple_bind_add_seq (dep_bind, dep_olist);
14940 pop_gimplify_context (dep_bind);
14941 }
14942 }
14943
14944 /* Lower the GIMPLE_OMP_TARGET in the current statement
14945 in GSI_P. CTX holds context information for the directive. */
14946
14947 static void
14948 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14949 {
14950 tree clauses;
14951 tree child_fn, t, c;
14952 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
14953 gbind *tgt_bind, *bind, *dep_bind = NULL;
14954 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
14955 location_t loc = gimple_location (stmt);
14956 bool offloaded, data_region;
14957 unsigned int map_cnt = 0;
14958 bool has_depend = false;
14959
14960 offloaded = is_gimple_omp_offloaded (stmt);
14961 switch (gimple_omp_target_kind (stmt))
14962 {
14963 case GF_OMP_TARGET_KIND_REGION:
14964 case GF_OMP_TARGET_KIND_UPDATE:
14965 case GF_OMP_TARGET_KIND_ENTER_DATA:
14966 case GF_OMP_TARGET_KIND_EXIT_DATA:
14967 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
14968 case GF_OMP_TARGET_KIND_OACC_KERNELS:
14969 case GF_OMP_TARGET_KIND_OACC_UPDATE:
14970 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
14971 data_region = false;
14972 break;
14973 case GF_OMP_TARGET_KIND_DATA:
14974 case GF_OMP_TARGET_KIND_OACC_DATA:
14975 data_region = true;
14976 break;
14977 default:
14978 gcc_unreachable ();
14979 }
14980
14981 clauses = gimple_omp_target_clauses (stmt);
14982
14983 gimple_seq dep_ilist = NULL;
14984 gimple_seq dep_olist = NULL;
14985 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14986 {
14987 push_gimplify_context ();
14988 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14989 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
14990 &dep_ilist, &dep_olist);
14991 has_depend = true;
14992 }
14993
14994 tgt_bind = NULL;
14995 tgt_body = NULL;
14996 if (offloaded)
14997 {
14998 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
14999 tgt_body = gimple_bind_body (tgt_bind);
15000 }
15001 else if (data_region)
15002 tgt_body = gimple_omp_body (stmt);
15003 child_fn = ctx->cb.dst_fn;
15004
15005 push_gimplify_context ();
15006
15007 irlist = NULL;
15008 orlist = NULL;
15009 if (offloaded
15010 && is_gimple_omp_oacc (stmt))
15011 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
15012
15013 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15014 switch (OMP_CLAUSE_CODE (c))
15015 {
15016 tree var, x;
15017
15018 default:
15019 break;
15020 case OMP_CLAUSE_MAP:
15021 #if CHECKING_P
15022 /* First check what we're prepared to handle in the following. */
15023 switch (OMP_CLAUSE_MAP_KIND (c))
15024 {
15025 case GOMP_MAP_ALLOC:
15026 case GOMP_MAP_TO:
15027 case GOMP_MAP_FROM:
15028 case GOMP_MAP_TOFROM:
15029 case GOMP_MAP_POINTER:
15030 case GOMP_MAP_TO_PSET:
15031 case GOMP_MAP_FORCE_DEALLOC:
15032 case GOMP_MAP_RELEASE:
15033 case GOMP_MAP_ALWAYS_TO:
15034 case GOMP_MAP_ALWAYS_FROM:
15035 case GOMP_MAP_ALWAYS_TOFROM:
15036 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15037 case GOMP_MAP_STRUCT:
15038 break;
15039 case GOMP_MAP_FORCE_ALLOC:
15040 case GOMP_MAP_FORCE_TO:
15041 case GOMP_MAP_FORCE_FROM:
15042 case GOMP_MAP_FORCE_TOFROM:
15043 case GOMP_MAP_FORCE_PRESENT:
15044 case GOMP_MAP_FORCE_DEVICEPTR:
15045 gcc_assert (is_gimple_omp_oacc (stmt));
15046 break;
15047 default:
15048 gcc_unreachable ();
15049 }
15050 #endif
15051 /* FALLTHRU */
15052 case OMP_CLAUSE_TO:
15053 case OMP_CLAUSE_FROM:
15054 var = OMP_CLAUSE_DECL (c);
15055 if (!DECL_P (var))
15056 {
15057 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15058 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15059 && (OMP_CLAUSE_MAP_KIND (c)
15060 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15061 map_cnt++;
15062 continue;
15063 }
15064
15065 if (DECL_SIZE (var)
15066 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15067 {
15068 tree var2 = DECL_VALUE_EXPR (var);
15069 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15070 var2 = TREE_OPERAND (var2, 0);
15071 gcc_assert (DECL_P (var2));
15072 var = var2;
15073 }
15074
15075 if (offloaded
15076 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15077 {
15078 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15079 {
15080 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15081 && varpool_node::get_create (var)->offloadable)
15082 continue;
15083
15084 tree type = build_pointer_type (TREE_TYPE (var));
15085 tree new_var = lookup_decl (var, ctx);
15086 x = create_tmp_var_raw (type, get_name (new_var));
15087 gimple_add_tmp_var (x);
15088 x = build_simple_mem_ref (x);
15089 SET_DECL_VALUE_EXPR (new_var, x);
15090 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15091 }
15092 continue;
15093 }
15094
15095 if (offloaded && OMP_CLAUSE_MAP_PRIVATE (c))
15096 {
15097 map_cnt++;
15098 continue;
15099 }
15100
15101 if (!maybe_lookup_field (var, ctx))
15102 continue;
15103
15104 if (offloaded)
15105 {
15106 x = build_receiver_ref (var, true, ctx);
15107 tree new_var = lookup_decl (var, ctx);
15108
15109 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15110 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15111 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15112 x = build_simple_mem_ref (x);
15113 SET_DECL_VALUE_EXPR (new_var, x);
15114 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15115 }
15116 map_cnt++;
15117 break;
15118
15119 case OMP_CLAUSE_FIRSTPRIVATE:
15120 map_cnt++;
15121 var = OMP_CLAUSE_DECL (c);
15122 if (!is_reference (var)
15123 && !is_gimple_reg_type (TREE_TYPE (var)))
15124 {
15125 tree new_var = lookup_decl (var, ctx);
15126 if (is_variable_sized (var))
15127 {
15128 tree pvar = DECL_VALUE_EXPR (var);
15129 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15130 pvar = TREE_OPERAND (pvar, 0);
15131 gcc_assert (DECL_P (pvar));
15132 tree new_pvar = lookup_decl (pvar, ctx);
15133 x = build_fold_indirect_ref (new_pvar);
15134 TREE_THIS_NOTRAP (x) = 1;
15135 }
15136 else
15137 x = build_receiver_ref (var, true, ctx);
15138 SET_DECL_VALUE_EXPR (new_var, x);
15139 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15140 }
15141 break;
15142
15143 case OMP_CLAUSE_PRIVATE:
15144 var = OMP_CLAUSE_DECL (c);
15145 if (is_variable_sized (var))
15146 {
15147 tree new_var = lookup_decl (var, ctx);
15148 tree pvar = DECL_VALUE_EXPR (var);
15149 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15150 pvar = TREE_OPERAND (pvar, 0);
15151 gcc_assert (DECL_P (pvar));
15152 tree new_pvar = lookup_decl (pvar, ctx);
15153 x = build_fold_indirect_ref (new_pvar);
15154 TREE_THIS_NOTRAP (x) = 1;
15155 SET_DECL_VALUE_EXPR (new_var, x);
15156 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15157 }
15158 break;
15159
15160 case OMP_CLAUSE_USE_DEVICE_PTR:
15161 case OMP_CLAUSE_IS_DEVICE_PTR:
15162 var = OMP_CLAUSE_DECL (c);
15163 map_cnt++;
15164 if (is_variable_sized (var))
15165 {
15166 tree new_var = lookup_decl (var, ctx);
15167 tree pvar = DECL_VALUE_EXPR (var);
15168 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15169 pvar = TREE_OPERAND (pvar, 0);
15170 gcc_assert (DECL_P (pvar));
15171 tree new_pvar = lookup_decl (pvar, ctx);
15172 x = build_fold_indirect_ref (new_pvar);
15173 TREE_THIS_NOTRAP (x) = 1;
15174 SET_DECL_VALUE_EXPR (new_var, x);
15175 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15176 }
15177 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15178 {
15179 tree new_var = lookup_decl (var, ctx);
15180 tree type = build_pointer_type (TREE_TYPE (var));
15181 x = create_tmp_var_raw (type, get_name (new_var));
15182 gimple_add_tmp_var (x);
15183 x = build_simple_mem_ref (x);
15184 SET_DECL_VALUE_EXPR (new_var, x);
15185 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15186 }
15187 break;
15188 }
15189
15190 if (offloaded)
15191 {
15192 target_nesting_level++;
15193 lower_omp (&tgt_body, ctx);
15194 target_nesting_level--;
15195 }
15196 else if (data_region)
15197 lower_omp (&tgt_body, ctx);
15198
15199 if (offloaded)
15200 {
15201 /* Declare all the variables created by mapping and the variables
15202 declared in the scope of the target body. */
15203 record_vars_into (ctx->block_vars, child_fn);
15204 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15205 }
15206
15207 olist = NULL;
15208 ilist = NULL;
15209 if (ctx->record_type)
15210 {
15211 ctx->sender_decl
15212 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15213 DECL_NAMELESS (ctx->sender_decl) = 1;
15214 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15215 t = make_tree_vec (3);
15216 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15217 TREE_VEC_ELT (t, 1)
15218 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15219 ".omp_data_sizes");
15220 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15221 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15222 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
15223 tree tkind_type = short_unsigned_type_node;
15224 int talign_shift = 8;
15225 TREE_VEC_ELT (t, 2)
15226 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
15227 ".omp_data_kinds");
15228 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15229 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15230 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15231 gimple_omp_target_set_data_arg (stmt, t);
15232
15233 vec<constructor_elt, va_gc> *vsize;
15234 vec<constructor_elt, va_gc> *vkind;
15235 vec_alloc (vsize, map_cnt);
15236 vec_alloc (vkind, map_cnt);
15237 unsigned int map_idx = 0;
15238
15239 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15240 switch (OMP_CLAUSE_CODE (c))
15241 {
15242 tree ovar, nc, s, purpose, var, x, type;
15243 unsigned int talign;
15244
15245 default:
15246 break;
15247 case OMP_CLAUSE_MAP:
15248 case OMP_CLAUSE_TO:
15249 case OMP_CLAUSE_FROM:
15250 nc = c;
15251 ovar = OMP_CLAUSE_DECL (c);
15252 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15253 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15254 break;
15255 if (!DECL_P (ovar))
15256 {
15257 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15258 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15259 {
15260 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15261 == get_base_address (ovar));
15262 nc = OMP_CLAUSE_CHAIN (c);
15263 ovar = OMP_CLAUSE_DECL (nc);
15264 }
15265 else
15266 {
15267 tree x = build_sender_ref (ovar, ctx);
15268 tree v
15269 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15270 gimplify_assign (x, v, &ilist);
15271 nc = NULL_TREE;
15272 }
15273 }
15274 else
15275 {
15276 if (DECL_SIZE (ovar)
15277 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15278 {
15279 tree ovar2 = DECL_VALUE_EXPR (ovar);
15280 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15281 ovar2 = TREE_OPERAND (ovar2, 0);
15282 gcc_assert (DECL_P (ovar2));
15283 ovar = ovar2;
15284 }
15285 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15286 && OMP_CLAUSE_MAP_PRIVATE (c))
15287 {
15288 if (!maybe_lookup_field ((splay_tree_key) &DECL_UID (ovar),
15289 ctx))
15290 continue;
15291 }
15292 else if (!maybe_lookup_field (ovar, ctx))
15293 continue;
15294 }
15295
15296 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
15297 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15298 talign = DECL_ALIGN_UNIT (ovar);
15299 if (nc)
15300 {
15301 var = lookup_decl_in_outer_ctx (ovar, ctx);
15302 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15303 && OMP_CLAUSE_MAP_PRIVATE (c))
15304 x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar),
15305 ctx);
15306 else
15307 x = build_sender_ref (ovar, ctx);
15308 if (maybe_lookup_oacc_reduction (var, ctx))
15309 {
15310 gcc_checking_assert (offloaded
15311 && is_gimple_omp_oacc (stmt));
15312 gimplify_assign (x, var, &ilist);
15313 }
15314 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15315 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15316 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15317 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
15318 {
15319 gcc_assert (offloaded);
15320 tree avar
15321 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
15322 mark_addressable (avar);
15323 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
15324 talign = DECL_ALIGN_UNIT (avar);
15325 avar = build_fold_addr_expr (avar);
15326 gimplify_assign (x, avar, &ilist);
15327 }
15328 else if (is_gimple_reg (var))
15329 {
15330 gcc_assert (offloaded);
15331 tree avar = create_tmp_var (TREE_TYPE (var));
15332 mark_addressable (avar);
15333 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15334 if (GOMP_MAP_COPY_TO_P (map_kind)
15335 || map_kind == GOMP_MAP_POINTER
15336 || map_kind == GOMP_MAP_TO_PSET
15337 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15338 gimplify_assign (avar, var, &ilist);
15339 avar = build_fold_addr_expr (avar);
15340 gimplify_assign (x, avar, &ilist);
15341 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15342 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15343 && !TYPE_READONLY (TREE_TYPE (var)))
15344 {
15345 x = unshare_expr (x);
15346 x = build_simple_mem_ref (x);
15347 gimplify_assign (var, x, &olist);
15348 }
15349 }
15350 else
15351 {
15352 var = build_fold_addr_expr (var);
15353 gimplify_assign (x, var, &ilist);
15354 }
15355 }
15356 s = OMP_CLAUSE_SIZE (c);
15357 if (s == NULL_TREE)
15358 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15359 s = fold_convert (size_type_node, s);
15360 purpose = size_int (map_idx++);
15361 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15362 if (TREE_CODE (s) != INTEGER_CST)
15363 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15364
15365 unsigned HOST_WIDE_INT tkind, tkind_zero;
15366 switch (OMP_CLAUSE_CODE (c))
15367 {
15368 case OMP_CLAUSE_MAP:
15369 tkind = OMP_CLAUSE_MAP_KIND (c);
15370 tkind_zero = tkind;
15371 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15372 switch (tkind)
15373 {
15374 case GOMP_MAP_ALLOC:
15375 case GOMP_MAP_TO:
15376 case GOMP_MAP_FROM:
15377 case GOMP_MAP_TOFROM:
15378 case GOMP_MAP_ALWAYS_TO:
15379 case GOMP_MAP_ALWAYS_FROM:
15380 case GOMP_MAP_ALWAYS_TOFROM:
15381 case GOMP_MAP_RELEASE:
15382 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15383 break;
15384 case GOMP_MAP_DELETE:
15385 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15386 default:
15387 break;
15388 }
15389 if (tkind_zero != tkind)
15390 {
15391 if (integer_zerop (s))
15392 tkind = tkind_zero;
15393 else if (integer_nonzerop (s))
15394 tkind_zero = tkind;
15395 }
15396 break;
15397 case OMP_CLAUSE_TO:
15398 tkind = GOMP_MAP_TO;
15399 tkind_zero = tkind;
15400 break;
15401 case OMP_CLAUSE_FROM:
15402 tkind = GOMP_MAP_FROM;
15403 tkind_zero = tkind;
15404 break;
15405 default:
15406 gcc_unreachable ();
15407 }
15408 gcc_checking_assert (tkind
15409 < (HOST_WIDE_INT_C (1U) << talign_shift));
15410 gcc_checking_assert (tkind_zero
15411 < (HOST_WIDE_INT_C (1U) << talign_shift));
15412 talign = ceil_log2 (talign);
15413 tkind |= talign << talign_shift;
15414 tkind_zero |= talign << talign_shift;
15415 gcc_checking_assert (tkind
15416 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15417 gcc_checking_assert (tkind_zero
15418 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15419 if (tkind == tkind_zero)
15420 x = build_int_cstu (tkind_type, tkind);
15421 else
15422 {
15423 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15424 x = build3 (COND_EXPR, tkind_type,
15425 fold_build2 (EQ_EXPR, boolean_type_node,
15426 unshare_expr (s), size_zero_node),
15427 build_int_cstu (tkind_type, tkind_zero),
15428 build_int_cstu (tkind_type, tkind));
15429 }
15430 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
15431 if (nc && nc != c)
15432 c = nc;
15433 break;
15434
15435 case OMP_CLAUSE_FIRSTPRIVATE:
15436 ovar = OMP_CLAUSE_DECL (c);
15437 if (is_reference (ovar))
15438 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15439 else
15440 talign = DECL_ALIGN_UNIT (ovar);
15441 var = lookup_decl_in_outer_ctx (ovar, ctx);
15442 x = build_sender_ref (ovar, ctx);
15443 tkind = GOMP_MAP_FIRSTPRIVATE;
15444 type = TREE_TYPE (ovar);
15445 if (is_reference (ovar))
15446 type = TREE_TYPE (type);
15447 bool use_firstprivate_int, force_addr;
15448 use_firstprivate_int = false;
15449 force_addr = false;
15450 if ((INTEGRAL_TYPE_P (type)
15451 && TYPE_PRECISION (type) <= POINTER_SIZE)
15452 || TREE_CODE (type) == POINTER_TYPE)
15453 use_firstprivate_int = true;
15454 if (has_depend)
15455 {
15456 if (is_reference (var))
15457 use_firstprivate_int = false;
15458 else if (is_gimple_reg (var))
15459 {
15460 if (DECL_HAS_VALUE_EXPR_P (var))
15461 {
15462 tree v = get_base_address (var);
15463 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15464 {
15465 use_firstprivate_int = false;
15466 force_addr = true;
15467 }
15468 else
15469 switch (TREE_CODE (v))
15470 {
15471 case INDIRECT_REF:
15472 case MEM_REF:
15473 use_firstprivate_int = false;
15474 force_addr = true;
15475 break;
15476 default:
15477 break;
15478 }
15479 }
15480 }
15481 else
15482 use_firstprivate_int = false;
15483 }
15484 if (use_firstprivate_int)
15485 {
15486 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15487 tree t = var;
15488 if (is_reference (var))
15489 t = build_simple_mem_ref (var);
15490 if (TREE_CODE (type) != POINTER_TYPE)
15491 t = fold_convert (pointer_sized_int_node, t);
15492 t = fold_convert (TREE_TYPE (x), t);
15493 gimplify_assign (x, t, &ilist);
15494 }
15495 else if (is_reference (var))
15496 gimplify_assign (x, var, &ilist);
15497 else if (!force_addr && is_gimple_reg (var))
15498 {
15499 tree avar = create_tmp_var (TREE_TYPE (var));
15500 mark_addressable (avar);
15501 gimplify_assign (avar, var, &ilist);
15502 avar = build_fold_addr_expr (avar);
15503 gimplify_assign (x, avar, &ilist);
15504 }
15505 else
15506 {
15507 var = build_fold_addr_expr (var);
15508 gimplify_assign (x, var, &ilist);
15509 }
15510 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15511 s = size_int (0);
15512 else if (is_reference (var))
15513 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15514 else
15515 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15516 s = fold_convert (size_type_node, s);
15517 purpose = size_int (map_idx++);
15518 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15519 if (TREE_CODE (s) != INTEGER_CST)
15520 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15521
15522 gcc_checking_assert (tkind
15523 < (HOST_WIDE_INT_C (1U) << talign_shift));
15524 talign = ceil_log2 (talign);
15525 tkind |= talign << talign_shift;
15526 gcc_checking_assert (tkind
15527 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15528 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15529 build_int_cstu (tkind_type, tkind));
15530 break;
15531
15532 case OMP_CLAUSE_USE_DEVICE_PTR:
15533 case OMP_CLAUSE_IS_DEVICE_PTR:
15534 ovar = OMP_CLAUSE_DECL (c);
15535 var = lookup_decl_in_outer_ctx (ovar, ctx);
15536 x = build_sender_ref (ovar, ctx);
15537 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15538 tkind = GOMP_MAP_USE_DEVICE_PTR;
15539 else
15540 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15541 type = TREE_TYPE (ovar);
15542 if (TREE_CODE (type) == ARRAY_TYPE)
15543 var = build_fold_addr_expr (var);
15544 else
15545 {
15546 if (is_reference (ovar))
15547 {
15548 type = TREE_TYPE (type);
15549 if (TREE_CODE (type) != ARRAY_TYPE)
15550 var = build_simple_mem_ref (var);
15551 var = fold_convert (TREE_TYPE (x), var);
15552 }
15553 }
15554 gimplify_assign (x, var, &ilist);
15555 s = size_int (0);
15556 purpose = size_int (map_idx++);
15557 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15558 gcc_checking_assert (tkind
15559 < (HOST_WIDE_INT_C (1U) << talign_shift));
15560 gcc_checking_assert (tkind
15561 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15562 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15563 build_int_cstu (tkind_type, tkind));
15564 break;
15565 }
15566
15567 gcc_assert (map_idx == map_cnt);
15568
15569 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15570 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15571 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15572 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
15573 for (int i = 1; i <= 2; i++)
15574 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15575 {
15576 gimple_seq initlist = NULL;
15577 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15578 TREE_VEC_ELT (t, i)),
15579 &initlist, true, NULL_TREE);
15580 gimple_seq_add_seq (&ilist, initlist);
15581
15582 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15583 NULL);
15584 TREE_THIS_VOLATILE (clobber) = 1;
15585 gimple_seq_add_stmt (&olist,
15586 gimple_build_assign (TREE_VEC_ELT (t, i),
15587 clobber));
15588 }
15589
15590 tree clobber = build_constructor (ctx->record_type, NULL);
15591 TREE_THIS_VOLATILE (clobber) = 1;
15592 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15593 clobber));
15594 }
15595
15596 /* Once all the expansions are done, sequence all the different
15597 fragments inside gimple_omp_body. */
15598
15599 new_body = NULL;
15600
15601 if (offloaded
15602 && ctx->record_type)
15603 {
15604 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15605 /* fixup_child_record_type might have changed receiver_decl's type. */
15606 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15607 gimple_seq_add_stmt (&new_body,
15608 gimple_build_assign (ctx->receiver_decl, t));
15609 }
15610
15611 if (offloaded || data_region)
15612 {
15613 tree prev = NULL_TREE;
15614 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15615 switch (OMP_CLAUSE_CODE (c))
15616 {
15617 tree var, x;
15618 default:
15619 break;
15620 case OMP_CLAUSE_FIRSTPRIVATE:
15621 var = OMP_CLAUSE_DECL (c);
15622 if (is_reference (var)
15623 || is_gimple_reg_type (TREE_TYPE (var)))
15624 {
15625 tree new_var = lookup_decl (var, ctx);
15626 tree type;
15627 type = TREE_TYPE (var);
15628 if (is_reference (var))
15629 type = TREE_TYPE (type);
15630 bool use_firstprivate_int;
15631 use_firstprivate_int = false;
15632 if ((INTEGRAL_TYPE_P (type)
15633 && TYPE_PRECISION (type) <= POINTER_SIZE)
15634 || TREE_CODE (type) == POINTER_TYPE)
15635 use_firstprivate_int = true;
15636 if (has_depend)
15637 {
15638 tree v = lookup_decl_in_outer_ctx (var, ctx);
15639 if (is_reference (v))
15640 use_firstprivate_int = false;
15641 else if (is_gimple_reg (v))
15642 {
15643 if (DECL_HAS_VALUE_EXPR_P (v))
15644 {
15645 v = get_base_address (v);
15646 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15647 use_firstprivate_int = false;
15648 else
15649 switch (TREE_CODE (v))
15650 {
15651 case INDIRECT_REF:
15652 case MEM_REF:
15653 use_firstprivate_int = false;
15654 break;
15655 default:
15656 break;
15657 }
15658 }
15659 }
15660 else
15661 use_firstprivate_int = false;
15662 }
15663 if (use_firstprivate_int)
15664 {
15665 x = build_receiver_ref (var, false, ctx);
15666 if (TREE_CODE (type) != POINTER_TYPE)
15667 x = fold_convert (pointer_sized_int_node, x);
15668 x = fold_convert (type, x);
15669 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15670 fb_rvalue);
15671 if (is_reference (var))
15672 {
15673 tree v = create_tmp_var_raw (type, get_name (var));
15674 gimple_add_tmp_var (v);
15675 TREE_ADDRESSABLE (v) = 1;
15676 gimple_seq_add_stmt (&new_body,
15677 gimple_build_assign (v, x));
15678 x = build_fold_addr_expr (v);
15679 }
15680 gimple_seq_add_stmt (&new_body,
15681 gimple_build_assign (new_var, x));
15682 }
15683 else
15684 {
15685 x = build_receiver_ref (var, !is_reference (var), ctx);
15686 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15687 fb_rvalue);
15688 gimple_seq_add_stmt (&new_body,
15689 gimple_build_assign (new_var, x));
15690 }
15691 }
15692 else if (is_variable_sized (var))
15693 {
15694 tree pvar = DECL_VALUE_EXPR (var);
15695 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15696 pvar = TREE_OPERAND (pvar, 0);
15697 gcc_assert (DECL_P (pvar));
15698 tree new_var = lookup_decl (pvar, ctx);
15699 x = build_receiver_ref (var, false, ctx);
15700 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15701 gimple_seq_add_stmt (&new_body,
15702 gimple_build_assign (new_var, x));
15703 }
15704 break;
15705 case OMP_CLAUSE_PRIVATE:
15706 var = OMP_CLAUSE_DECL (c);
15707 if (is_reference (var))
15708 {
15709 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15710 tree new_var = lookup_decl (var, ctx);
15711 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15712 if (TREE_CONSTANT (x))
15713 {
15714 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15715 get_name (var));
15716 gimple_add_tmp_var (x);
15717 TREE_ADDRESSABLE (x) = 1;
15718 x = build_fold_addr_expr_loc (clause_loc, x);
15719 }
15720 else
15721 {
15722 tree atmp
15723 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15724 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15725 tree al = size_int (TYPE_ALIGN (rtype));
15726 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15727 }
15728
15729 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15730 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15731 gimple_seq_add_stmt (&new_body,
15732 gimple_build_assign (new_var, x));
15733 }
15734 break;
15735 case OMP_CLAUSE_USE_DEVICE_PTR:
15736 case OMP_CLAUSE_IS_DEVICE_PTR:
15737 var = OMP_CLAUSE_DECL (c);
15738 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15739 x = build_sender_ref (var, ctx);
15740 else
15741 x = build_receiver_ref (var, false, ctx);
15742 if (is_variable_sized (var))
15743 {
15744 tree pvar = DECL_VALUE_EXPR (var);
15745 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15746 pvar = TREE_OPERAND (pvar, 0);
15747 gcc_assert (DECL_P (pvar));
15748 tree new_var = lookup_decl (pvar, ctx);
15749 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15750 gimple_seq_add_stmt (&new_body,
15751 gimple_build_assign (new_var, x));
15752 }
15753 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15754 {
15755 tree new_var = lookup_decl (var, ctx);
15756 new_var = DECL_VALUE_EXPR (new_var);
15757 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15758 new_var = TREE_OPERAND (new_var, 0);
15759 gcc_assert (DECL_P (new_var));
15760 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15761 gimple_seq_add_stmt (&new_body,
15762 gimple_build_assign (new_var, x));
15763 }
15764 else
15765 {
15766 tree type = TREE_TYPE (var);
15767 tree new_var = lookup_decl (var, ctx);
15768 if (is_reference (var))
15769 {
15770 type = TREE_TYPE (type);
15771 if (TREE_CODE (type) != ARRAY_TYPE)
15772 {
15773 tree v = create_tmp_var_raw (type, get_name (var));
15774 gimple_add_tmp_var (v);
15775 TREE_ADDRESSABLE (v) = 1;
15776 x = fold_convert (type, x);
15777 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15778 fb_rvalue);
15779 gimple_seq_add_stmt (&new_body,
15780 gimple_build_assign (v, x));
15781 x = build_fold_addr_expr (v);
15782 }
15783 }
15784 x = fold_convert (TREE_TYPE (new_var), x);
15785 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15786 gimple_seq_add_stmt (&new_body,
15787 gimple_build_assign (new_var, x));
15788 }
15789 break;
15790 }
15791 /* Handle GOMP_MAP_FIRSTPRIVATE_POINTER in second pass,
15792 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15793 are already handled. */
15794 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15795 switch (OMP_CLAUSE_CODE (c))
15796 {
15797 tree var;
15798 default:
15799 break;
15800 case OMP_CLAUSE_MAP:
15801 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
15802 {
15803 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15804 HOST_WIDE_INT offset = 0;
15805 gcc_assert (prev);
15806 var = OMP_CLAUSE_DECL (c);
15807 if (DECL_P (var)
15808 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15809 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15810 ctx))
15811 && varpool_node::get_create (var)->offloadable)
15812 break;
15813 if (TREE_CODE (var) == INDIRECT_REF
15814 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15815 var = TREE_OPERAND (var, 0);
15816 if (TREE_CODE (var) == COMPONENT_REF)
15817 {
15818 var = get_addr_base_and_unit_offset (var, &offset);
15819 gcc_assert (var != NULL_TREE && DECL_P (var));
15820 }
15821 else if (DECL_SIZE (var)
15822 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15823 {
15824 tree var2 = DECL_VALUE_EXPR (var);
15825 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15826 var2 = TREE_OPERAND (var2, 0);
15827 gcc_assert (DECL_P (var2));
15828 var = var2;
15829 }
15830 tree new_var = lookup_decl (var, ctx), x;
15831 tree type = TREE_TYPE (new_var);
15832 bool is_ref;
15833 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15834 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15835 == COMPONENT_REF))
15836 {
15837 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15838 is_ref = true;
15839 new_var = build2 (MEM_REF, type,
15840 build_fold_addr_expr (new_var),
15841 build_int_cst (build_pointer_type (type),
15842 offset));
15843 }
15844 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
15845 {
15846 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
15847 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
15848 new_var = build2 (MEM_REF, type,
15849 build_fold_addr_expr (new_var),
15850 build_int_cst (build_pointer_type (type),
15851 offset));
15852 }
15853 else
15854 is_ref = is_reference (var);
15855 bool ref_to_array = false;
15856 if (is_ref)
15857 {
15858 type = TREE_TYPE (type);
15859 if (TREE_CODE (type) == ARRAY_TYPE)
15860 {
15861 type = build_pointer_type (type);
15862 ref_to_array = true;
15863 }
15864 }
15865 else if (TREE_CODE (type) == ARRAY_TYPE)
15866 {
15867 tree decl2 = DECL_VALUE_EXPR (new_var);
15868 gcc_assert (TREE_CODE (decl2) == MEM_REF);
15869 decl2 = TREE_OPERAND (decl2, 0);
15870 gcc_assert (DECL_P (decl2));
15871 new_var = decl2;
15872 type = TREE_TYPE (new_var);
15873 }
15874 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
15875 x = fold_convert_loc (clause_loc, type, x);
15876 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
15877 {
15878 tree bias = OMP_CLAUSE_SIZE (c);
15879 if (DECL_P (bias))
15880 bias = lookup_decl (bias, ctx);
15881 bias = fold_convert_loc (clause_loc, sizetype, bias);
15882 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
15883 bias);
15884 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
15885 TREE_TYPE (x), x, bias);
15886 }
15887 if (ref_to_array)
15888 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15889 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15890 if (is_ref && !ref_to_array)
15891 {
15892 tree t = create_tmp_var_raw (type, get_name (var));
15893 gimple_add_tmp_var (t);
15894 TREE_ADDRESSABLE (t) = 1;
15895 gimple_seq_add_stmt (&new_body,
15896 gimple_build_assign (t, x));
15897 x = build_fold_addr_expr_loc (clause_loc, t);
15898 }
15899 gimple_seq_add_stmt (&new_body,
15900 gimple_build_assign (new_var, x));
15901 prev = NULL_TREE;
15902 }
15903 else if (OMP_CLAUSE_CHAIN (c)
15904 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
15905 == OMP_CLAUSE_MAP
15906 && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15907 == GOMP_MAP_FIRSTPRIVATE_POINTER)
15908 prev = c;
15909 break;
15910 case OMP_CLAUSE_PRIVATE:
15911 var = OMP_CLAUSE_DECL (c);
15912 if (is_variable_sized (var))
15913 {
15914 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15915 tree new_var = lookup_decl (var, ctx);
15916 tree pvar = DECL_VALUE_EXPR (var);
15917 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15918 pvar = TREE_OPERAND (pvar, 0);
15919 gcc_assert (DECL_P (pvar));
15920 tree new_pvar = lookup_decl (pvar, ctx);
15921 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15922 tree al = size_int (DECL_ALIGN (var));
15923 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
15924 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15925 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
15926 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15927 gimple_seq_add_stmt (&new_body,
15928 gimple_build_assign (new_pvar, x));
15929 }
15930 break;
15931 }
15932 gimple_seq_add_seq (&new_body, tgt_body);
15933 if (offloaded)
15934 new_body = maybe_catch_exception (new_body);
15935 }
15936 else if (data_region)
15937 new_body = tgt_body;
15938 if (offloaded || data_region)
15939 {
15940 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15941 gimple_omp_set_body (stmt, new_body);
15942 }
15943
15944 bind = gimple_build_bind (NULL, NULL,
15945 tgt_bind ? gimple_bind_block (tgt_bind)
15946 : NULL_TREE);
15947 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15948 gimple_bind_add_seq (bind, irlist);
15949 gimple_bind_add_seq (bind, ilist);
15950 gimple_bind_add_stmt (bind, stmt);
15951 gimple_bind_add_seq (bind, olist);
15952 gimple_bind_add_seq (bind, orlist);
15953
15954 pop_gimplify_context (NULL);
15955
15956 if (dep_bind)
15957 {
15958 gimple_bind_add_seq (dep_bind, dep_ilist);
15959 gimple_bind_add_stmt (dep_bind, bind);
15960 gimple_bind_add_seq (dep_bind, dep_olist);
15961 pop_gimplify_context (dep_bind);
15962 }
15963 }
15964
15965 /* Expand code for an OpenMP teams directive. */
15966
15967 static void
15968 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15969 {
15970 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
15971 push_gimplify_context ();
15972
15973 tree block = make_node (BLOCK);
15974 gbind *bind = gimple_build_bind (NULL, NULL, block);
15975 gsi_replace (gsi_p, bind, true);
15976 gimple_seq bind_body = NULL;
15977 gimple_seq dlist = NULL;
15978 gimple_seq olist = NULL;
15979
15980 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15981 OMP_CLAUSE_NUM_TEAMS);
15982 if (num_teams == NULL_TREE)
15983 num_teams = build_int_cst (unsigned_type_node, 0);
15984 else
15985 {
15986 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
15987 num_teams = fold_convert (unsigned_type_node, num_teams);
15988 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
15989 }
15990 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15991 OMP_CLAUSE_THREAD_LIMIT);
15992 if (thread_limit == NULL_TREE)
15993 thread_limit = build_int_cst (unsigned_type_node, 0);
15994 else
15995 {
15996 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
15997 thread_limit = fold_convert (unsigned_type_node, thread_limit);
15998 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
15999 fb_rvalue);
16000 }
16001
16002 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16003 &bind_body, &dlist, ctx, NULL);
16004 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16005 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16006 gimple_seq_add_stmt (&bind_body, teams_stmt);
16007
16008 location_t loc = gimple_location (teams_stmt);
16009 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16010 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16011 gimple_set_location (call, loc);
16012 gimple_seq_add_stmt (&bind_body, call);
16013
16014 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16015 gimple_omp_set_body (teams_stmt, NULL);
16016 gimple_seq_add_seq (&bind_body, olist);
16017 gimple_seq_add_seq (&bind_body, dlist);
16018 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16019 gimple_bind_set_body (bind, bind_body);
16020
16021 pop_gimplify_context (bind);
16022
16023 gimple_bind_append_vars (bind, ctx->block_vars);
16024 BLOCK_VARS (block) = ctx->block_vars;
16025 if (BLOCK_VARS (block))
16026 TREE_USED (block) = 1;
16027 }
16028
16029
16030 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16031 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16032 of OMP context, but with task_shared_vars set. */
16033
16034 static tree
16035 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16036 void *data)
16037 {
16038 tree t = *tp;
16039
16040 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16041 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16042 return t;
16043
16044 if (task_shared_vars
16045 && DECL_P (t)
16046 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16047 return t;
16048
16049 /* If a global variable has been privatized, TREE_CONSTANT on
16050 ADDR_EXPR might be wrong. */
16051 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16052 recompute_tree_invariant_for_addr_expr (t);
16053
16054 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16055 return NULL_TREE;
16056 }
16057
16058 /* Data to be communicated between lower_omp_regimplify_operands and
16059 lower_omp_regimplify_operands_p. */
16060
16061 struct lower_omp_regimplify_operands_data
16062 {
16063 omp_context *ctx;
16064 vec<tree> *decls;
16065 };
16066
16067 /* Helper function for lower_omp_regimplify_operands. Find
16068 omp_member_access_dummy_var vars and adjust temporarily their
16069 DECL_VALUE_EXPRs if needed. */
16070
16071 static tree
16072 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16073 void *data)
16074 {
16075 tree t = omp_member_access_dummy_var (*tp);
16076 if (t)
16077 {
16078 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16079 lower_omp_regimplify_operands_data *ldata
16080 = (lower_omp_regimplify_operands_data *) wi->info;
16081 tree o = maybe_lookup_decl (t, ldata->ctx);
16082 if (o != t)
16083 {
16084 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16085 ldata->decls->safe_push (*tp);
16086 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16087 SET_DECL_VALUE_EXPR (*tp, v);
16088 }
16089 }
16090 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16091 return NULL_TREE;
16092 }
16093
16094 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16095 of omp_member_access_dummy_var vars during regimplification. */
16096
16097 static void
16098 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16099 gimple_stmt_iterator *gsi_p)
16100 {
16101 auto_vec<tree, 10> decls;
16102 if (ctx)
16103 {
16104 struct walk_stmt_info wi;
16105 memset (&wi, '\0', sizeof (wi));
16106 struct lower_omp_regimplify_operands_data data;
16107 data.ctx = ctx;
16108 data.decls = &decls;
16109 wi.info = &data;
16110 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16111 }
16112 gimple_regimplify_operands (stmt, gsi_p);
16113 while (!decls.is_empty ())
16114 {
16115 tree t = decls.pop ();
16116 tree v = decls.pop ();
16117 SET_DECL_VALUE_EXPR (t, v);
16118 }
16119 }
16120
16121 static void
16122 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16123 {
16124 gimple *stmt = gsi_stmt (*gsi_p);
16125 struct walk_stmt_info wi;
16126 gcall *call_stmt;
16127
16128 if (gimple_has_location (stmt))
16129 input_location = gimple_location (stmt);
16130
16131 if (task_shared_vars)
16132 memset (&wi, '\0', sizeof (wi));
16133
16134 /* If we have issued syntax errors, avoid doing any heavy lifting.
16135 Just replace the OMP directives with a NOP to avoid
16136 confusing RTL expansion. */
16137 if (seen_error () && is_gimple_omp (stmt))
16138 {
16139 gsi_replace (gsi_p, gimple_build_nop (), true);
16140 return;
16141 }
16142
16143 switch (gimple_code (stmt))
16144 {
16145 case GIMPLE_COND:
16146 {
16147 gcond *cond_stmt = as_a <gcond *> (stmt);
16148 if ((ctx || task_shared_vars)
16149 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16150 lower_omp_regimplify_p,
16151 ctx ? NULL : &wi, NULL)
16152 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16153 lower_omp_regimplify_p,
16154 ctx ? NULL : &wi, NULL)))
16155 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16156 }
16157 break;
16158 case GIMPLE_CATCH:
16159 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16160 break;
16161 case GIMPLE_EH_FILTER:
16162 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16163 break;
16164 case GIMPLE_TRY:
16165 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16166 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16167 break;
16168 case GIMPLE_TRANSACTION:
16169 lower_omp (gimple_transaction_body_ptr (
16170 as_a <gtransaction *> (stmt)),
16171 ctx);
16172 break;
16173 case GIMPLE_BIND:
16174 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
16175 break;
16176 case GIMPLE_OMP_PARALLEL:
16177 case GIMPLE_OMP_TASK:
16178 ctx = maybe_lookup_ctx (stmt);
16179 gcc_assert (ctx);
16180 if (ctx->cancellable)
16181 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16182 lower_omp_taskreg (gsi_p, ctx);
16183 break;
16184 case GIMPLE_OMP_FOR:
16185 ctx = maybe_lookup_ctx (stmt);
16186 gcc_assert (ctx);
16187 if (ctx->cancellable)
16188 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16189 lower_omp_for (gsi_p, ctx);
16190 break;
16191 case GIMPLE_OMP_SECTIONS:
16192 ctx = maybe_lookup_ctx (stmt);
16193 gcc_assert (ctx);
16194 if (ctx->cancellable)
16195 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16196 lower_omp_sections (gsi_p, ctx);
16197 break;
16198 case GIMPLE_OMP_SINGLE:
16199 ctx = maybe_lookup_ctx (stmt);
16200 gcc_assert (ctx);
16201 lower_omp_single (gsi_p, ctx);
16202 break;
16203 case GIMPLE_OMP_MASTER:
16204 ctx = maybe_lookup_ctx (stmt);
16205 gcc_assert (ctx);
16206 lower_omp_master (gsi_p, ctx);
16207 break;
16208 case GIMPLE_OMP_TASKGROUP:
16209 ctx = maybe_lookup_ctx (stmt);
16210 gcc_assert (ctx);
16211 lower_omp_taskgroup (gsi_p, ctx);
16212 break;
16213 case GIMPLE_OMP_ORDERED:
16214 ctx = maybe_lookup_ctx (stmt);
16215 gcc_assert (ctx);
16216 lower_omp_ordered (gsi_p, ctx);
16217 break;
16218 case GIMPLE_OMP_CRITICAL:
16219 ctx = maybe_lookup_ctx (stmt);
16220 gcc_assert (ctx);
16221 lower_omp_critical (gsi_p, ctx);
16222 break;
16223 case GIMPLE_OMP_ATOMIC_LOAD:
16224 if ((ctx || task_shared_vars)
16225 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16226 as_a <gomp_atomic_load *> (stmt)),
16227 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
16228 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16229 break;
16230 case GIMPLE_OMP_TARGET:
16231 ctx = maybe_lookup_ctx (stmt);
16232 gcc_assert (ctx);
16233 lower_omp_target (gsi_p, ctx);
16234 break;
16235 case GIMPLE_OMP_TEAMS:
16236 ctx = maybe_lookup_ctx (stmt);
16237 gcc_assert (ctx);
16238 lower_omp_teams (gsi_p, ctx);
16239 break;
16240 case GIMPLE_CALL:
16241 tree fndecl;
16242 call_stmt = as_a <gcall *> (stmt);
16243 fndecl = gimple_call_fndecl (call_stmt);
16244 if (fndecl
16245 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16246 switch (DECL_FUNCTION_CODE (fndecl))
16247 {
16248 case BUILT_IN_GOMP_BARRIER:
16249 if (ctx == NULL)
16250 break;
16251 /* FALLTHRU */
16252 case BUILT_IN_GOMP_CANCEL:
16253 case BUILT_IN_GOMP_CANCELLATION_POINT:
16254 omp_context *cctx;
16255 cctx = ctx;
16256 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16257 cctx = cctx->outer;
16258 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
16259 if (!cctx->cancellable)
16260 {
16261 if (DECL_FUNCTION_CODE (fndecl)
16262 == BUILT_IN_GOMP_CANCELLATION_POINT)
16263 {
16264 stmt = gimple_build_nop ();
16265 gsi_replace (gsi_p, stmt, false);
16266 }
16267 break;
16268 }
16269 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16270 {
16271 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
16272 gimple_call_set_fndecl (call_stmt, fndecl);
16273 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
16274 }
16275 tree lhs;
16276 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
16277 gimple_call_set_lhs (call_stmt, lhs);
16278 tree fallthru_label;
16279 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
16280 gimple *g;
16281 g = gimple_build_label (fallthru_label);
16282 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16283 g = gimple_build_cond (NE_EXPR, lhs,
16284 fold_convert (TREE_TYPE (lhs),
16285 boolean_false_node),
16286 cctx->cancel_label, fallthru_label);
16287 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16288 break;
16289 default:
16290 break;
16291 }
16292 /* FALLTHRU */
16293 default:
16294 if ((ctx || task_shared_vars)
16295 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16296 ctx ? NULL : &wi))
16297 {
16298 /* Just remove clobbers, this should happen only if we have
16299 "privatized" local addressable variables in SIMD regions,
16300 the clobber isn't needed in that case and gimplifying address
16301 of the ARRAY_REF into a pointer and creating MEM_REF based
16302 clobber would create worse code than we get with the clobber
16303 dropped. */
16304 if (gimple_clobber_p (stmt))
16305 {
16306 gsi_replace (gsi_p, gimple_build_nop (), true);
16307 break;
16308 }
16309 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16310 }
16311 break;
16312 }
16313 }
16314
16315 static void
16316 lower_omp (gimple_seq *body, omp_context *ctx)
16317 {
16318 location_t saved_location = input_location;
16319 gimple_stmt_iterator gsi;
16320 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16321 lower_omp_1 (&gsi, ctx);
16322 /* During gimplification, we haven't folded statments inside offloading
16323 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16324 if (target_nesting_level || taskreg_nesting_level)
16325 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16326 fold_stmt (&gsi);
16327 input_location = saved_location;
16328 }
16329 \f
16330 /* Main entry point. */
16331
16332 static unsigned int
16333 execute_lower_omp (void)
16334 {
16335 gimple_seq body;
16336 int i;
16337 omp_context *ctx;
16338
16339 /* This pass always runs, to provide PROP_gimple_lomp.
16340 But often, there is nothing to do. */
16341 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16342 && flag_openmp_simd == 0)
16343 return 0;
16344
16345 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16346 delete_omp_context);
16347
16348 body = gimple_body (current_function_decl);
16349 scan_omp (&body, NULL);
16350 gcc_assert (taskreg_nesting_level == 0);
16351 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16352 finish_taskreg_scan (ctx);
16353 taskreg_contexts.release ();
16354
16355 if (all_contexts->root)
16356 {
16357 if (task_shared_vars)
16358 push_gimplify_context ();
16359 lower_omp (&body, NULL);
16360 if (task_shared_vars)
16361 pop_gimplify_context (NULL);
16362 }
16363
16364 if (all_contexts)
16365 {
16366 splay_tree_delete (all_contexts);
16367 all_contexts = NULL;
16368 }
16369 BITMAP_FREE (task_shared_vars);
16370 return 0;
16371 }
16372
16373 namespace {
16374
16375 const pass_data pass_data_lower_omp =
16376 {
16377 GIMPLE_PASS, /* type */
16378 "omplower", /* name */
16379 OPTGROUP_NONE, /* optinfo_flags */
16380 TV_NONE, /* tv_id */
16381 PROP_gimple_any, /* properties_required */
16382 PROP_gimple_lomp, /* properties_provided */
16383 0, /* properties_destroyed */
16384 0, /* todo_flags_start */
16385 0, /* todo_flags_finish */
16386 };
16387
16388 class pass_lower_omp : public gimple_opt_pass
16389 {
16390 public:
16391 pass_lower_omp (gcc::context *ctxt)
16392 : gimple_opt_pass (pass_data_lower_omp, ctxt)
16393 {}
16394
16395 /* opt_pass methods: */
16396 virtual unsigned int execute (function *) { return execute_lower_omp (); }
16397
16398 }; // class pass_lower_omp
16399
16400 } // anon namespace
16401
16402 gimple_opt_pass *
16403 make_pass_lower_omp (gcc::context *ctxt)
16404 {
16405 return new pass_lower_omp (ctxt);
16406 }
16407 \f
16408 /* The following is a utility to diagnose structured block violations.
16409 It is not part of the "omplower" pass, as that's invoked too late. It
16410 should be invoked by the respective front ends after gimplification. */
16411
16412 static splay_tree all_labels;
16413
16414 /* Check for mismatched contexts and generate an error if needed. Return
16415 true if an error is detected. */
16416
16417 static bool
16418 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
16419 gimple *branch_ctx, gimple *label_ctx)
16420 {
16421 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16422 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16423
16424 if (label_ctx == branch_ctx)
16425 return false;
16426
16427 const char* kind = NULL;
16428
16429 if (flag_cilkplus)
16430 {
16431 if ((branch_ctx
16432 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16433 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16434 || (label_ctx
16435 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16436 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16437 kind = "Cilk Plus";
16438 }
16439 if (flag_openacc)
16440 {
16441 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16442 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16443 {
16444 gcc_checking_assert (kind == NULL);
16445 kind = "OpenACC";
16446 }
16447 }
16448 if (kind == NULL)
16449 {
16450 gcc_checking_assert (flag_openmp);
16451 kind = "OpenMP";
16452 }
16453
16454 /*
16455 Previously we kept track of the label's entire context in diagnose_sb_[12]
16456 so we could traverse it and issue a correct "exit" or "enter" error
16457 message upon a structured block violation.
16458
16459 We built the context by building a list with tree_cons'ing, but there is
16460 no easy counterpart in gimple tuples. It seems like far too much work
16461 for issuing exit/enter error messages. If someone really misses the
16462 distinct error message... patches welcome.
16463 */
16464
16465 #if 0
16466 /* Try to avoid confusing the user by producing and error message
16467 with correct "exit" or "enter" verbiage. We prefer "exit"
16468 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16469 if (branch_ctx == NULL)
16470 exit_p = false;
16471 else
16472 {
16473 while (label_ctx)
16474 {
16475 if (TREE_VALUE (label_ctx) == branch_ctx)
16476 {
16477 exit_p = false;
16478 break;
16479 }
16480 label_ctx = TREE_CHAIN (label_ctx);
16481 }
16482 }
16483
16484 if (exit_p)
16485 error ("invalid exit from %s structured block", kind);
16486 else
16487 error ("invalid entry to %s structured block", kind);
16488 #endif
16489
16490 /* If it's obvious we have an invalid entry, be specific about the error. */
16491 if (branch_ctx == NULL)
16492 error ("invalid entry to %s structured block", kind);
16493 else
16494 {
16495 /* Otherwise, be vague and lazy, but efficient. */
16496 error ("invalid branch to/from %s structured block", kind);
16497 }
16498
16499 gsi_replace (gsi_p, gimple_build_nop (), false);
16500 return true;
16501 }
16502
16503 /* Pass 1: Create a minimal tree of structured blocks, and record
16504 where each label is found. */
16505
16506 static tree
16507 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16508 struct walk_stmt_info *wi)
16509 {
16510 gimple *context = (gimple *) wi->info;
16511 gimple *inner_context;
16512 gimple *stmt = gsi_stmt (*gsi_p);
16513
16514 *handled_ops_p = true;
16515
16516 switch (gimple_code (stmt))
16517 {
16518 WALK_SUBSTMTS;
16519
16520 case GIMPLE_OMP_PARALLEL:
16521 case GIMPLE_OMP_TASK:
16522 case GIMPLE_OMP_SECTIONS:
16523 case GIMPLE_OMP_SINGLE:
16524 case GIMPLE_OMP_SECTION:
16525 case GIMPLE_OMP_MASTER:
16526 case GIMPLE_OMP_ORDERED:
16527 case GIMPLE_OMP_CRITICAL:
16528 case GIMPLE_OMP_TARGET:
16529 case GIMPLE_OMP_TEAMS:
16530 case GIMPLE_OMP_TASKGROUP:
16531 /* The minimal context here is just the current OMP construct. */
16532 inner_context = stmt;
16533 wi->info = inner_context;
16534 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16535 wi->info = context;
16536 break;
16537
16538 case GIMPLE_OMP_FOR:
16539 inner_context = stmt;
16540 wi->info = inner_context;
16541 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16542 walk them. */
16543 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16544 diagnose_sb_1, NULL, wi);
16545 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16546 wi->info = context;
16547 break;
16548
16549 case GIMPLE_LABEL:
16550 splay_tree_insert (all_labels,
16551 (splay_tree_key) gimple_label_label (
16552 as_a <glabel *> (stmt)),
16553 (splay_tree_value) context);
16554 break;
16555
16556 default:
16557 break;
16558 }
16559
16560 return NULL_TREE;
16561 }
16562
16563 /* Pass 2: Check each branch and see if its context differs from that of
16564 the destination label's context. */
16565
16566 static tree
16567 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16568 struct walk_stmt_info *wi)
16569 {
16570 gimple *context = (gimple *) wi->info;
16571 splay_tree_node n;
16572 gimple *stmt = gsi_stmt (*gsi_p);
16573
16574 *handled_ops_p = true;
16575
16576 switch (gimple_code (stmt))
16577 {
16578 WALK_SUBSTMTS;
16579
16580 case GIMPLE_OMP_PARALLEL:
16581 case GIMPLE_OMP_TASK:
16582 case GIMPLE_OMP_SECTIONS:
16583 case GIMPLE_OMP_SINGLE:
16584 case GIMPLE_OMP_SECTION:
16585 case GIMPLE_OMP_MASTER:
16586 case GIMPLE_OMP_ORDERED:
16587 case GIMPLE_OMP_CRITICAL:
16588 case GIMPLE_OMP_TARGET:
16589 case GIMPLE_OMP_TEAMS:
16590 case GIMPLE_OMP_TASKGROUP:
16591 wi->info = stmt;
16592 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16593 wi->info = context;
16594 break;
16595
16596 case GIMPLE_OMP_FOR:
16597 wi->info = stmt;
16598 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16599 walk them. */
16600 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16601 diagnose_sb_2, NULL, wi);
16602 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16603 wi->info = context;
16604 break;
16605
16606 case GIMPLE_COND:
16607 {
16608 gcond *cond_stmt = as_a <gcond *> (stmt);
16609 tree lab = gimple_cond_true_label (cond_stmt);
16610 if (lab)
16611 {
16612 n = splay_tree_lookup (all_labels,
16613 (splay_tree_key) lab);
16614 diagnose_sb_0 (gsi_p, context,
16615 n ? (gimple *) n->value : NULL);
16616 }
16617 lab = gimple_cond_false_label (cond_stmt);
16618 if (lab)
16619 {
16620 n = splay_tree_lookup (all_labels,
16621 (splay_tree_key) lab);
16622 diagnose_sb_0 (gsi_p, context,
16623 n ? (gimple *) n->value : NULL);
16624 }
16625 }
16626 break;
16627
16628 case GIMPLE_GOTO:
16629 {
16630 tree lab = gimple_goto_dest (stmt);
16631 if (TREE_CODE (lab) != LABEL_DECL)
16632 break;
16633
16634 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16635 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
16636 }
16637 break;
16638
16639 case GIMPLE_SWITCH:
16640 {
16641 gswitch *switch_stmt = as_a <gswitch *> (stmt);
16642 unsigned int i;
16643 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
16644 {
16645 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
16646 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16647 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
16648 break;
16649 }
16650 }
16651 break;
16652
16653 case GIMPLE_RETURN:
16654 diagnose_sb_0 (gsi_p, context, NULL);
16655 break;
16656
16657 default:
16658 break;
16659 }
16660
16661 return NULL_TREE;
16662 }
16663
16664 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16665 GIMPLE_* codes. */
16666 bool
16667 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16668 int *region_idx)
16669 {
16670 gimple *last = last_stmt (bb);
16671 enum gimple_code code = gimple_code (last);
16672 struct omp_region *cur_region = *region;
16673 bool fallthru = false;
16674
16675 switch (code)
16676 {
16677 case GIMPLE_OMP_PARALLEL:
16678 case GIMPLE_OMP_TASK:
16679 case GIMPLE_OMP_FOR:
16680 case GIMPLE_OMP_SINGLE:
16681 case GIMPLE_OMP_TEAMS:
16682 case GIMPLE_OMP_MASTER:
16683 case GIMPLE_OMP_TASKGROUP:
16684 case GIMPLE_OMP_CRITICAL:
16685 case GIMPLE_OMP_SECTION:
16686 cur_region = new_omp_region (bb, code, cur_region);
16687 fallthru = true;
16688 break;
16689
16690 case GIMPLE_OMP_ORDERED:
16691 cur_region = new_omp_region (bb, code, cur_region);
16692 fallthru = true;
16693 if (find_omp_clause (gimple_omp_ordered_clauses
16694 (as_a <gomp_ordered *> (last)),
16695 OMP_CLAUSE_DEPEND))
16696 cur_region = cur_region->outer;
16697 break;
16698
16699 case GIMPLE_OMP_TARGET:
16700 cur_region = new_omp_region (bb, code, cur_region);
16701 fallthru = true;
16702 switch (gimple_omp_target_kind (last))
16703 {
16704 case GF_OMP_TARGET_KIND_REGION:
16705 case GF_OMP_TARGET_KIND_DATA:
16706 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16707 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16708 case GF_OMP_TARGET_KIND_OACC_DATA:
16709 break;
16710 case GF_OMP_TARGET_KIND_UPDATE:
16711 case GF_OMP_TARGET_KIND_ENTER_DATA:
16712 case GF_OMP_TARGET_KIND_EXIT_DATA:
16713 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16714 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
16715 cur_region = cur_region->outer;
16716 break;
16717 default:
16718 gcc_unreachable ();
16719 }
16720 break;
16721
16722 case GIMPLE_OMP_SECTIONS:
16723 cur_region = new_omp_region (bb, code, cur_region);
16724 fallthru = true;
16725 break;
16726
16727 case GIMPLE_OMP_SECTIONS_SWITCH:
16728 fallthru = false;
16729 break;
16730
16731 case GIMPLE_OMP_ATOMIC_LOAD:
16732 case GIMPLE_OMP_ATOMIC_STORE:
16733 fallthru = true;
16734 break;
16735
16736 case GIMPLE_OMP_RETURN:
16737 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16738 somewhere other than the next block. This will be
16739 created later. */
16740 cur_region->exit = bb;
16741 if (cur_region->type == GIMPLE_OMP_TASK)
16742 /* Add an edge corresponding to not scheduling the task
16743 immediately. */
16744 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
16745 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16746 cur_region = cur_region->outer;
16747 break;
16748
16749 case GIMPLE_OMP_CONTINUE:
16750 cur_region->cont = bb;
16751 switch (cur_region->type)
16752 {
16753 case GIMPLE_OMP_FOR:
16754 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16755 succs edges as abnormal to prevent splitting
16756 them. */
16757 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16758 /* Make the loopback edge. */
16759 make_edge (bb, single_succ (cur_region->entry),
16760 EDGE_ABNORMAL);
16761
16762 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16763 corresponds to the case that the body of the loop
16764 is not executed at all. */
16765 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16766 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16767 fallthru = false;
16768 break;
16769
16770 case GIMPLE_OMP_SECTIONS:
16771 /* Wire up the edges into and out of the nested sections. */
16772 {
16773 basic_block switch_bb = single_succ (cur_region->entry);
16774
16775 struct omp_region *i;
16776 for (i = cur_region->inner; i ; i = i->next)
16777 {
16778 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16779 make_edge (switch_bb, i->entry, 0);
16780 make_edge (i->exit, bb, EDGE_FALLTHRU);
16781 }
16782
16783 /* Make the loopback edge to the block with
16784 GIMPLE_OMP_SECTIONS_SWITCH. */
16785 make_edge (bb, switch_bb, 0);
16786
16787 /* Make the edge from the switch to exit. */
16788 make_edge (switch_bb, bb->next_bb, 0);
16789 fallthru = false;
16790 }
16791 break;
16792
16793 case GIMPLE_OMP_TASK:
16794 fallthru = true;
16795 break;
16796
16797 default:
16798 gcc_unreachable ();
16799 }
16800 break;
16801
16802 default:
16803 gcc_unreachable ();
16804 }
16805
16806 if (*region != cur_region)
16807 {
16808 *region = cur_region;
16809 if (cur_region)
16810 *region_idx = cur_region->entry->index;
16811 else
16812 *region_idx = 0;
16813 }
16814
16815 return fallthru;
16816 }
16817
16818 static unsigned int
16819 diagnose_omp_structured_block_errors (void)
16820 {
16821 struct walk_stmt_info wi;
16822 gimple_seq body = gimple_body (current_function_decl);
16823
16824 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16825
16826 memset (&wi, 0, sizeof (wi));
16827 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
16828
16829 memset (&wi, 0, sizeof (wi));
16830 wi.want_locations = true;
16831 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
16832
16833 gimple_set_body (current_function_decl, body);
16834
16835 splay_tree_delete (all_labels);
16836 all_labels = NULL;
16837
16838 return 0;
16839 }
16840
16841 namespace {
16842
16843 const pass_data pass_data_diagnose_omp_blocks =
16844 {
16845 GIMPLE_PASS, /* type */
16846 "*diagnose_omp_blocks", /* name */
16847 OPTGROUP_NONE, /* optinfo_flags */
16848 TV_NONE, /* tv_id */
16849 PROP_gimple_any, /* properties_required */
16850 0, /* properties_provided */
16851 0, /* properties_destroyed */
16852 0, /* todo_flags_start */
16853 0, /* todo_flags_finish */
16854 };
16855
16856 class pass_diagnose_omp_blocks : public gimple_opt_pass
16857 {
16858 public:
16859 pass_diagnose_omp_blocks (gcc::context *ctxt)
16860 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
16861 {}
16862
16863 /* opt_pass methods: */
16864 virtual bool gate (function *)
16865 {
16866 return flag_cilkplus || flag_openacc || flag_openmp;
16867 }
16868 virtual unsigned int execute (function *)
16869 {
16870 return diagnose_omp_structured_block_errors ();
16871 }
16872
16873 }; // class pass_diagnose_omp_blocks
16874
16875 } // anon namespace
16876
16877 gimple_opt_pass *
16878 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
16879 {
16880 return new pass_diagnose_omp_blocks (ctxt);
16881 }
16882 \f
16883 /* SIMD clone supporting code. */
16884
16885 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
16886 of arguments to reserve space for. */
16887
16888 static struct cgraph_simd_clone *
16889 simd_clone_struct_alloc (int nargs)
16890 {
16891 struct cgraph_simd_clone *clone_info;
16892 size_t len = (sizeof (struct cgraph_simd_clone)
16893 + nargs * sizeof (struct cgraph_simd_clone_arg));
16894 clone_info = (struct cgraph_simd_clone *)
16895 ggc_internal_cleared_alloc (len);
16896 return clone_info;
16897 }
16898
16899 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
16900
16901 static inline void
16902 simd_clone_struct_copy (struct cgraph_simd_clone *to,
16903 struct cgraph_simd_clone *from)
16904 {
16905 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
16906 + ((from->nargs - from->inbranch)
16907 * sizeof (struct cgraph_simd_clone_arg))));
16908 }
16909
16910 /* Return vector of parameter types of function FNDECL. This uses
16911 TYPE_ARG_TYPES if available, otherwise falls back to types of
16912 DECL_ARGUMENTS types. */
16913
16914 vec<tree>
16915 simd_clone_vector_of_formal_parm_types (tree fndecl)
16916 {
16917 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
16918 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
16919 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
16920 unsigned int i;
16921 tree arg;
16922 FOR_EACH_VEC_ELT (args, i, arg)
16923 args[i] = TREE_TYPE (args[i]);
16924 return args;
16925 }
16926
16927 /* Given a simd function in NODE, extract the simd specific
16928 information from the OMP clauses passed in CLAUSES, and return
16929 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
16930 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
16931 otherwise set to FALSE. */
16932
16933 static struct cgraph_simd_clone *
16934 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
16935 bool *inbranch_specified)
16936 {
16937 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
16938 tree t;
16939 int n;
16940 *inbranch_specified = false;
16941
16942 n = args.length ();
16943 if (n > 0 && args.last () == void_type_node)
16944 n--;
16945
16946 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
16947 be cloned have a distinctive artificial label in addition to "omp
16948 declare simd". */
16949 bool cilk_clone
16950 = (flag_cilkplus
16951 && lookup_attribute ("cilk simd function",
16952 DECL_ATTRIBUTES (node->decl)));
16953
16954 /* Allocate one more than needed just in case this is an in-branch
16955 clone which will require a mask argument. */
16956 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
16957 clone_info->nargs = n;
16958 clone_info->cilk_elemental = cilk_clone;
16959
16960 if (!clauses)
16961 {
16962 args.release ();
16963 return clone_info;
16964 }
16965 clauses = TREE_VALUE (clauses);
16966 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
16967 return clone_info;
16968
16969 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16970 {
16971 switch (OMP_CLAUSE_CODE (t))
16972 {
16973 case OMP_CLAUSE_INBRANCH:
16974 clone_info->inbranch = 1;
16975 *inbranch_specified = true;
16976 break;
16977 case OMP_CLAUSE_NOTINBRANCH:
16978 clone_info->inbranch = 0;
16979 *inbranch_specified = true;
16980 break;
16981 case OMP_CLAUSE_SIMDLEN:
16982 clone_info->simdlen
16983 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
16984 break;
16985 case OMP_CLAUSE_LINEAR:
16986 {
16987 tree decl = OMP_CLAUSE_DECL (t);
16988 tree step = OMP_CLAUSE_LINEAR_STEP (t);
16989 int argno = TREE_INT_CST_LOW (decl);
16990 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
16991 {
16992 clone_info->args[argno].arg_type
16993 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
16994 clone_info->args[argno].linear_step = tree_to_shwi (step);
16995 gcc_assert (clone_info->args[argno].linear_step >= 0
16996 && clone_info->args[argno].linear_step < n);
16997 }
16998 else
16999 {
17000 if (POINTER_TYPE_P (args[argno]))
17001 step = fold_convert (ssizetype, step);
17002 if (!tree_fits_shwi_p (step))
17003 {
17004 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17005 "ignoring large linear step");
17006 args.release ();
17007 return NULL;
17008 }
17009 else if (integer_zerop (step))
17010 {
17011 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17012 "ignoring zero linear step");
17013 args.release ();
17014 return NULL;
17015 }
17016 else
17017 {
17018 enum cgraph_simd_clone_arg_type arg_type;
17019 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17020 switch (OMP_CLAUSE_LINEAR_KIND (t))
17021 {
17022 case OMP_CLAUSE_LINEAR_REF:
17023 arg_type
17024 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17025 break;
17026 case OMP_CLAUSE_LINEAR_UVAL:
17027 arg_type
17028 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17029 break;
17030 case OMP_CLAUSE_LINEAR_VAL:
17031 case OMP_CLAUSE_LINEAR_DEFAULT:
17032 arg_type
17033 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17034 break;
17035 default:
17036 gcc_unreachable ();
17037 }
17038 else
17039 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17040 clone_info->args[argno].arg_type = arg_type;
17041 clone_info->args[argno].linear_step = tree_to_shwi (step);
17042 }
17043 }
17044 break;
17045 }
17046 case OMP_CLAUSE_UNIFORM:
17047 {
17048 tree decl = OMP_CLAUSE_DECL (t);
17049 int argno = tree_to_uhwi (decl);
17050 clone_info->args[argno].arg_type
17051 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17052 break;
17053 }
17054 case OMP_CLAUSE_ALIGNED:
17055 {
17056 tree decl = OMP_CLAUSE_DECL (t);
17057 int argno = tree_to_uhwi (decl);
17058 clone_info->args[argno].alignment
17059 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17060 break;
17061 }
17062 default:
17063 break;
17064 }
17065 }
17066 args.release ();
17067 return clone_info;
17068 }
17069
17070 /* Given a SIMD clone in NODE, calculate the characteristic data
17071 type and return the coresponding type. The characteristic data
17072 type is computed as described in the Intel Vector ABI. */
17073
17074 static tree
17075 simd_clone_compute_base_data_type (struct cgraph_node *node,
17076 struct cgraph_simd_clone *clone_info)
17077 {
17078 tree type = integer_type_node;
17079 tree fndecl = node->decl;
17080
17081 /* a) For non-void function, the characteristic data type is the
17082 return type. */
17083 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17084 type = TREE_TYPE (TREE_TYPE (fndecl));
17085
17086 /* b) If the function has any non-uniform, non-linear parameters,
17087 then the characteristic data type is the type of the first
17088 such parameter. */
17089 else
17090 {
17091 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17092 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17093 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17094 {
17095 type = map[i];
17096 break;
17097 }
17098 map.release ();
17099 }
17100
17101 /* c) If the characteristic data type determined by a) or b) above
17102 is struct, union, or class type which is pass-by-value (except
17103 for the type that maps to the built-in complex data type), the
17104 characteristic data type is int. */
17105 if (RECORD_OR_UNION_TYPE_P (type)
17106 && !aggregate_value_p (type, NULL)
17107 && TREE_CODE (type) != COMPLEX_TYPE)
17108 return integer_type_node;
17109
17110 /* d) If none of the above three classes is applicable, the
17111 characteristic data type is int. */
17112
17113 return type;
17114
17115 /* e) For Intel Xeon Phi native and offload compilation, if the
17116 resulting characteristic data type is 8-bit or 16-bit integer
17117 data type, the characteristic data type is int. */
17118 /* Well, we don't handle Xeon Phi yet. */
17119 }
17120
17121 static tree
17122 simd_clone_mangle (struct cgraph_node *node,
17123 struct cgraph_simd_clone *clone_info)
17124 {
17125 char vecsize_mangle = clone_info->vecsize_mangle;
17126 char mask = clone_info->inbranch ? 'M' : 'N';
17127 unsigned int simdlen = clone_info->simdlen;
17128 unsigned int n;
17129 pretty_printer pp;
17130
17131 gcc_assert (vecsize_mangle && simdlen);
17132
17133 pp_string (&pp, "_ZGV");
17134 pp_character (&pp, vecsize_mangle);
17135 pp_character (&pp, mask);
17136 pp_decimal_int (&pp, simdlen);
17137
17138 for (n = 0; n < clone_info->nargs; ++n)
17139 {
17140 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17141
17142 switch (arg.arg_type)
17143 {
17144 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17145 pp_character (&pp, 'u');
17146 break;
17147 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17148 pp_character (&pp, 'l');
17149 goto mangle_linear;
17150 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17151 pp_character (&pp, 'R');
17152 goto mangle_linear;
17153 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17154 pp_character (&pp, 'L');
17155 goto mangle_linear;
17156 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17157 pp_character (&pp, 'U');
17158 goto mangle_linear;
17159 mangle_linear:
17160 gcc_assert (arg.linear_step != 0);
17161 if (arg.linear_step > 1)
17162 pp_unsigned_wide_integer (&pp, arg.linear_step);
17163 else if (arg.linear_step < 0)
17164 {
17165 pp_character (&pp, 'n');
17166 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17167 arg.linear_step));
17168 }
17169 break;
17170 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17171 pp_character (&pp, 's');
17172 pp_unsigned_wide_integer (&pp, arg.linear_step);
17173 break;
17174 default:
17175 pp_character (&pp, 'v');
17176 }
17177 if (arg.alignment)
17178 {
17179 pp_character (&pp, 'a');
17180 pp_decimal_int (&pp, arg.alignment);
17181 }
17182 }
17183
17184 pp_underscore (&pp);
17185 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17186 if (*str == '*')
17187 ++str;
17188 pp_string (&pp, str);
17189 str = pp_formatted_text (&pp);
17190
17191 /* If there already is a SIMD clone with the same mangled name, don't
17192 add another one. This can happen e.g. for
17193 #pragma omp declare simd
17194 #pragma omp declare simd simdlen(8)
17195 int foo (int, int);
17196 if the simdlen is assumed to be 8 for the first one, etc. */
17197 for (struct cgraph_node *clone = node->simd_clones; clone;
17198 clone = clone->simdclone->next_clone)
17199 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17200 str) == 0)
17201 return NULL_TREE;
17202
17203 return get_identifier (str);
17204 }
17205
17206 /* Create a simd clone of OLD_NODE and return it. */
17207
17208 static struct cgraph_node *
17209 simd_clone_create (struct cgraph_node *old_node)
17210 {
17211 struct cgraph_node *new_node;
17212 if (old_node->definition)
17213 {
17214 if (!old_node->has_gimple_body_p ())
17215 return NULL;
17216 old_node->get_body ();
17217 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17218 false, NULL, NULL,
17219 "simdclone");
17220 }
17221 else
17222 {
17223 tree old_decl = old_node->decl;
17224 tree new_decl = copy_node (old_node->decl);
17225 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17226 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17227 SET_DECL_RTL (new_decl, NULL);
17228 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17229 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
17230 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
17231 if (old_node->in_other_partition)
17232 new_node->in_other_partition = 1;
17233 symtab->call_cgraph_insertion_hooks (new_node);
17234 }
17235 if (new_node == NULL)
17236 return new_node;
17237
17238 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17239
17240 /* The function cgraph_function_versioning () will force the new
17241 symbol local. Undo this, and inherit external visability from
17242 the old node. */
17243 new_node->local.local = old_node->local.local;
17244 new_node->externally_visible = old_node->externally_visible;
17245
17246 return new_node;
17247 }
17248
17249 /* Adjust the return type of the given function to its appropriate
17250 vector counterpart. Returns a simd array to be used throughout the
17251 function as a return value. */
17252
17253 static tree
17254 simd_clone_adjust_return_type (struct cgraph_node *node)
17255 {
17256 tree fndecl = node->decl;
17257 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17258 unsigned int veclen;
17259 tree t;
17260
17261 /* Adjust the function return type. */
17262 if (orig_rettype == void_type_node)
17263 return NULL_TREE;
17264 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
17265 t = TREE_TYPE (TREE_TYPE (fndecl));
17266 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
17267 veclen = node->simdclone->vecsize_int;
17268 else
17269 veclen = node->simdclone->vecsize_float;
17270 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
17271 if (veclen > node->simdclone->simdlen)
17272 veclen = node->simdclone->simdlen;
17273 if (POINTER_TYPE_P (t))
17274 t = pointer_sized_int_node;
17275 if (veclen == node->simdclone->simdlen)
17276 t = build_vector_type (t, node->simdclone->simdlen);
17277 else
17278 {
17279 t = build_vector_type (t, veclen);
17280 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
17281 }
17282 TREE_TYPE (TREE_TYPE (fndecl)) = t;
17283 if (!node->definition)
17284 return NULL_TREE;
17285
17286 t = DECL_RESULT (fndecl);
17287 /* Adjust the DECL_RESULT. */
17288 gcc_assert (TREE_TYPE (t) != void_type_node);
17289 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17290 relayout_decl (t);
17291
17292 tree atype = build_array_type_nelts (orig_rettype,
17293 node->simdclone->simdlen);
17294 if (veclen != node->simdclone->simdlen)
17295 return build1 (VIEW_CONVERT_EXPR, atype, t);
17296
17297 /* Set up a SIMD array to use as the return value. */
17298 tree retval = create_tmp_var_raw (atype, "retval");
17299 gimple_add_tmp_var (retval);
17300 return retval;
17301 }
17302
17303 /* Each vector argument has a corresponding array to be used locally
17304 as part of the eventual loop. Create such temporary array and
17305 return it.
17306
17307 PREFIX is the prefix to be used for the temporary.
17308
17309 TYPE is the inner element type.
17310
17311 SIMDLEN is the number of elements. */
17312
17313 static tree
17314 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17315 {
17316 tree atype = build_array_type_nelts (type, simdlen);
17317 tree avar = create_tmp_var_raw (atype, prefix);
17318 gimple_add_tmp_var (avar);
17319 return avar;
17320 }
17321
17322 /* Modify the function argument types to their corresponding vector
17323 counterparts if appropriate. Also, create one array for each simd
17324 argument to be used locally when using the function arguments as
17325 part of the loop.
17326
17327 NODE is the function whose arguments are to be adjusted.
17328
17329 Returns an adjustment vector that will be filled describing how the
17330 argument types will be adjusted. */
17331
17332 static ipa_parm_adjustment_vec
17333 simd_clone_adjust_argument_types (struct cgraph_node *node)
17334 {
17335 vec<tree> args;
17336 ipa_parm_adjustment_vec adjustments;
17337
17338 if (node->definition)
17339 args = ipa_get_vector_of_formal_parms (node->decl);
17340 else
17341 args = simd_clone_vector_of_formal_parm_types (node->decl);
17342 adjustments.create (args.length ());
17343 unsigned i, j, veclen;
17344 struct ipa_parm_adjustment adj;
17345 for (i = 0; i < node->simdclone->nargs; ++i)
17346 {
17347 memset (&adj, 0, sizeof (adj));
17348 tree parm = args[i];
17349 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17350 adj.base_index = i;
17351 adj.base = parm;
17352
17353 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17354 node->simdclone->args[i].orig_type = parm_type;
17355
17356 switch (node->simdclone->args[i].arg_type)
17357 {
17358 default:
17359 /* No adjustment necessary for scalar arguments. */
17360 adj.op = IPA_PARM_OP_COPY;
17361 break;
17362 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17363 if (node->definition)
17364 node->simdclone->args[i].simd_array
17365 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17366 TREE_TYPE (parm_type),
17367 node->simdclone->simdlen);
17368 adj.op = IPA_PARM_OP_COPY;
17369 break;
17370 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17371 case SIMD_CLONE_ARG_TYPE_VECTOR:
17372 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17373 veclen = node->simdclone->vecsize_int;
17374 else
17375 veclen = node->simdclone->vecsize_float;
17376 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17377 if (veclen > node->simdclone->simdlen)
17378 veclen = node->simdclone->simdlen;
17379 adj.arg_prefix = "simd";
17380 if (POINTER_TYPE_P (parm_type))
17381 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17382 else
17383 adj.type = build_vector_type (parm_type, veclen);
17384 node->simdclone->args[i].vector_type = adj.type;
17385 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17386 {
17387 adjustments.safe_push (adj);
17388 if (j == veclen)
17389 {
17390 memset (&adj, 0, sizeof (adj));
17391 adj.op = IPA_PARM_OP_NEW;
17392 adj.arg_prefix = "simd";
17393 adj.base_index = i;
17394 adj.type = node->simdclone->args[i].vector_type;
17395 }
17396 }
17397
17398 if (node->definition)
17399 node->simdclone->args[i].simd_array
17400 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17401 parm_type, node->simdclone->simdlen);
17402 }
17403 adjustments.safe_push (adj);
17404 }
17405
17406 if (node->simdclone->inbranch)
17407 {
17408 tree base_type
17409 = simd_clone_compute_base_data_type (node->simdclone->origin,
17410 node->simdclone);
17411
17412 memset (&adj, 0, sizeof (adj));
17413 adj.op = IPA_PARM_OP_NEW;
17414 adj.arg_prefix = "mask";
17415
17416 adj.base_index = i;
17417 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17418 veclen = node->simdclone->vecsize_int;
17419 else
17420 veclen = node->simdclone->vecsize_float;
17421 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17422 if (veclen > node->simdclone->simdlen)
17423 veclen = node->simdclone->simdlen;
17424 if (POINTER_TYPE_P (base_type))
17425 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17426 else
17427 adj.type = build_vector_type (base_type, veclen);
17428 adjustments.safe_push (adj);
17429
17430 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17431 adjustments.safe_push (adj);
17432
17433 /* We have previously allocated one extra entry for the mask. Use
17434 it and fill it. */
17435 struct cgraph_simd_clone *sc = node->simdclone;
17436 sc->nargs++;
17437 if (node->definition)
17438 {
17439 sc->args[i].orig_arg
17440 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17441 sc->args[i].simd_array
17442 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17443 }
17444 sc->args[i].orig_type = base_type;
17445 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17446 }
17447
17448 if (node->definition)
17449 ipa_modify_formal_parameters (node->decl, adjustments);
17450 else
17451 {
17452 tree new_arg_types = NULL_TREE, new_reversed;
17453 bool last_parm_void = false;
17454 if (args.length () > 0 && args.last () == void_type_node)
17455 last_parm_void = true;
17456
17457 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17458 j = adjustments.length ();
17459 for (i = 0; i < j; i++)
17460 {
17461 struct ipa_parm_adjustment *adj = &adjustments[i];
17462 tree ptype;
17463 if (adj->op == IPA_PARM_OP_COPY)
17464 ptype = args[adj->base_index];
17465 else
17466 ptype = adj->type;
17467 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17468 }
17469 new_reversed = nreverse (new_arg_types);
17470 if (last_parm_void)
17471 {
17472 if (new_reversed)
17473 TREE_CHAIN (new_arg_types) = void_list_node;
17474 else
17475 new_reversed = void_list_node;
17476 }
17477
17478 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17479 TYPE_ARG_TYPES (new_type) = new_reversed;
17480 TREE_TYPE (node->decl) = new_type;
17481
17482 adjustments.release ();
17483 }
17484 args.release ();
17485 return adjustments;
17486 }
17487
17488 /* Initialize and copy the function arguments in NODE to their
17489 corresponding local simd arrays. Returns a fresh gimple_seq with
17490 the instruction sequence generated. */
17491
17492 static gimple_seq
17493 simd_clone_init_simd_arrays (struct cgraph_node *node,
17494 ipa_parm_adjustment_vec adjustments)
17495 {
17496 gimple_seq seq = NULL;
17497 unsigned i = 0, j = 0, k;
17498
17499 for (tree arg = DECL_ARGUMENTS (node->decl);
17500 arg;
17501 arg = DECL_CHAIN (arg), i++, j++)
17502 {
17503 if (adjustments[j].op == IPA_PARM_OP_COPY
17504 || POINTER_TYPE_P (TREE_TYPE (arg)))
17505 continue;
17506
17507 node->simdclone->args[i].vector_arg = arg;
17508
17509 tree array = node->simdclone->args[i].simd_array;
17510 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17511 {
17512 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17513 tree ptr = build_fold_addr_expr (array);
17514 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17515 build_int_cst (ptype, 0));
17516 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17517 gimplify_and_add (t, &seq);
17518 }
17519 else
17520 {
17521 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17522 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17523 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17524 {
17525 tree ptr = build_fold_addr_expr (array);
17526 int elemsize;
17527 if (k)
17528 {
17529 arg = DECL_CHAIN (arg);
17530 j++;
17531 }
17532 elemsize
17533 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17534 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17535 build_int_cst (ptype, k * elemsize));
17536 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17537 gimplify_and_add (t, &seq);
17538 }
17539 }
17540 }
17541 return seq;
17542 }
17543
17544 /* Callback info for ipa_simd_modify_stmt_ops below. */
17545
17546 struct modify_stmt_info {
17547 ipa_parm_adjustment_vec adjustments;
17548 gimple *stmt;
17549 /* True if the parent statement was modified by
17550 ipa_simd_modify_stmt_ops. */
17551 bool modified;
17552 };
17553
17554 /* Callback for walk_gimple_op.
17555
17556 Adjust operands from a given statement as specified in the
17557 adjustments vector in the callback data. */
17558
17559 static tree
17560 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17561 {
17562 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17563 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17564 tree *orig_tp = tp;
17565 if (TREE_CODE (*tp) == ADDR_EXPR)
17566 tp = &TREE_OPERAND (*tp, 0);
17567 struct ipa_parm_adjustment *cand = NULL;
17568 if (TREE_CODE (*tp) == PARM_DECL)
17569 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17570 else
17571 {
17572 if (TYPE_P (*tp))
17573 *walk_subtrees = 0;
17574 }
17575
17576 tree repl = NULL_TREE;
17577 if (cand)
17578 repl = unshare_expr (cand->new_decl);
17579 else
17580 {
17581 if (tp != orig_tp)
17582 {
17583 *walk_subtrees = 0;
17584 bool modified = info->modified;
17585 info->modified = false;
17586 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17587 if (!info->modified)
17588 {
17589 info->modified = modified;
17590 return NULL_TREE;
17591 }
17592 info->modified = modified;
17593 repl = *tp;
17594 }
17595 else
17596 return NULL_TREE;
17597 }
17598
17599 if (tp != orig_tp)
17600 {
17601 repl = build_fold_addr_expr (repl);
17602 gimple *stmt;
17603 if (is_gimple_debug (info->stmt))
17604 {
17605 tree vexpr = make_node (DEBUG_EXPR_DECL);
17606 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17607 DECL_ARTIFICIAL (vexpr) = 1;
17608 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17609 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17610 repl = vexpr;
17611 }
17612 else
17613 {
17614 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
17615 repl = gimple_assign_lhs (stmt);
17616 }
17617 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
17618 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17619 *orig_tp = repl;
17620 }
17621 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
17622 {
17623 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17624 *tp = vce;
17625 }
17626 else
17627 *tp = repl;
17628
17629 info->modified = true;
17630 return NULL_TREE;
17631 }
17632
17633 /* Traverse the function body and perform all modifications as
17634 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17635 modified such that the replacement/reduction value will now be an
17636 offset into the corresponding simd_array.
17637
17638 This function will replace all function argument uses with their
17639 corresponding simd array elements, and ajust the return values
17640 accordingly. */
17641
17642 static void
17643 ipa_simd_modify_function_body (struct cgraph_node *node,
17644 ipa_parm_adjustment_vec adjustments,
17645 tree retval_array, tree iter)
17646 {
17647 basic_block bb;
17648 unsigned int i, j, l;
17649
17650 /* Re-use the adjustments array, but this time use it to replace
17651 every function argument use to an offset into the corresponding
17652 simd_array. */
17653 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17654 {
17655 if (!node->simdclone->args[i].vector_arg)
17656 continue;
17657
17658 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17659 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17660 adjustments[j].new_decl
17661 = build4 (ARRAY_REF,
17662 basetype,
17663 node->simdclone->args[i].simd_array,
17664 iter,
17665 NULL_TREE, NULL_TREE);
17666 if (adjustments[j].op == IPA_PARM_OP_NONE
17667 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17668 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17669 }
17670
17671 l = adjustments.length ();
17672 for (i = 1; i < num_ssa_names; i++)
17673 {
17674 tree name = ssa_name (i);
17675 if (name
17676 && SSA_NAME_VAR (name)
17677 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17678 {
17679 for (j = 0; j < l; j++)
17680 if (SSA_NAME_VAR (name) == adjustments[j].base
17681 && adjustments[j].new_decl)
17682 {
17683 tree base_var;
17684 if (adjustments[j].new_ssa_base == NULL_TREE)
17685 {
17686 base_var
17687 = copy_var_decl (adjustments[j].base,
17688 DECL_NAME (adjustments[j].base),
17689 TREE_TYPE (adjustments[j].base));
17690 adjustments[j].new_ssa_base = base_var;
17691 }
17692 else
17693 base_var = adjustments[j].new_ssa_base;
17694 if (SSA_NAME_IS_DEFAULT_DEF (name))
17695 {
17696 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17697 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17698 tree new_decl = unshare_expr (adjustments[j].new_decl);
17699 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17700 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17701 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
17702 gimple *stmt = gimple_build_assign (name, new_decl);
17703 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17704 }
17705 else
17706 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17707 }
17708 }
17709 }
17710
17711 struct modify_stmt_info info;
17712 info.adjustments = adjustments;
17713
17714 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17715 {
17716 gimple_stmt_iterator gsi;
17717
17718 gsi = gsi_start_bb (bb);
17719 while (!gsi_end_p (gsi))
17720 {
17721 gimple *stmt = gsi_stmt (gsi);
17722 info.stmt = stmt;
17723 struct walk_stmt_info wi;
17724
17725 memset (&wi, 0, sizeof (wi));
17726 info.modified = false;
17727 wi.info = &info;
17728 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17729
17730 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
17731 {
17732 tree retval = gimple_return_retval (return_stmt);
17733 if (!retval)
17734 {
17735 gsi_remove (&gsi, true);
17736 continue;
17737 }
17738
17739 /* Replace `return foo' with `retval_array[iter] = foo'. */
17740 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17741 retval_array, iter, NULL, NULL);
17742 stmt = gimple_build_assign (ref, retval);
17743 gsi_replace (&gsi, stmt, true);
17744 info.modified = true;
17745 }
17746
17747 if (info.modified)
17748 {
17749 update_stmt (stmt);
17750 if (maybe_clean_eh_stmt (stmt))
17751 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17752 }
17753 gsi_next (&gsi);
17754 }
17755 }
17756 }
17757
17758 /* Adjust the argument types in NODE to their appropriate vector
17759 counterparts. */
17760
17761 static void
17762 simd_clone_adjust (struct cgraph_node *node)
17763 {
17764 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
17765
17766 targetm.simd_clone.adjust (node);
17767
17768 tree retval = simd_clone_adjust_return_type (node);
17769 ipa_parm_adjustment_vec adjustments
17770 = simd_clone_adjust_argument_types (node);
17771
17772 push_gimplify_context ();
17773
17774 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
17775
17776 /* Adjust all uses of vector arguments accordingly. Adjust all
17777 return values accordingly. */
17778 tree iter = create_tmp_var (unsigned_type_node, "iter");
17779 tree iter1 = make_ssa_name (iter);
17780 tree iter2 = make_ssa_name (iter);
17781 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
17782
17783 /* Initialize the iteration variable. */
17784 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17785 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
17786 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17787 /* Insert the SIMD array and iv initialization at function
17788 entry. */
17789 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
17790
17791 pop_gimplify_context (NULL);
17792
17793 /* Create a new BB right before the original exit BB, to hold the
17794 iteration increment and the condition/branch. */
17795 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
17796 basic_block incr_bb = create_empty_bb (orig_exit);
17797 add_bb_to_loop (incr_bb, body_bb->loop_father);
17798 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
17799 flag. Set it now to be a FALLTHRU_EDGE. */
17800 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
17801 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
17802 for (unsigned i = 0;
17803 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
17804 {
17805 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
17806 redirect_edge_succ (e, incr_bb);
17807 }
17808 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
17809 e->probability = REG_BR_PROB_BASE;
17810 gsi = gsi_last_bb (incr_bb);
17811 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
17812 build_int_cst (unsigned_type_node, 1));
17813 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17814
17815 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
17816 struct loop *loop = alloc_loop ();
17817 cfun->has_force_vectorize_loops = true;
17818 loop->safelen = node->simdclone->simdlen;
17819 loop->force_vectorize = true;
17820 loop->header = body_bb;
17821
17822 /* Branch around the body if the mask applies. */
17823 if (node->simdclone->inbranch)
17824 {
17825 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
17826 tree mask_array
17827 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
17828 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
17829 tree aref = build4 (ARRAY_REF,
17830 TREE_TYPE (TREE_TYPE (mask_array)),
17831 mask_array, iter1,
17832 NULL, NULL);
17833 g = gimple_build_assign (mask, aref);
17834 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17835 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
17836 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
17837 {
17838 aref = build1 (VIEW_CONVERT_EXPR,
17839 build_nonstandard_integer_type (bitsize, 0), mask);
17840 mask = make_ssa_name (TREE_TYPE (aref));
17841 g = gimple_build_assign (mask, aref);
17842 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17843 }
17844
17845 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
17846 NULL, NULL);
17847 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17848 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
17849 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
17850 }
17851
17852 /* Generate the condition. */
17853 g = gimple_build_cond (LT_EXPR,
17854 iter2,
17855 build_int_cst (unsigned_type_node,
17856 node->simdclone->simdlen),
17857 NULL, NULL);
17858 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17859 e = split_block (incr_bb, gsi_stmt (gsi));
17860 basic_block latch_bb = e->dest;
17861 basic_block new_exit_bb;
17862 new_exit_bb = split_block_after_labels (latch_bb)->dest;
17863 loop->latch = latch_bb;
17864
17865 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
17866
17867 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
17868 /* The successor of incr_bb is already pointing to latch_bb; just
17869 change the flags.
17870 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
17871 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
17872
17873 gphi *phi = create_phi_node (iter1, body_bb);
17874 edge preheader_edge = find_edge (entry_bb, body_bb);
17875 edge latch_edge = single_succ_edge (latch_bb);
17876 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
17877 UNKNOWN_LOCATION);
17878 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
17879
17880 /* Generate the new return. */
17881 gsi = gsi_last_bb (new_exit_bb);
17882 if (retval
17883 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
17884 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
17885 retval = TREE_OPERAND (retval, 0);
17886 else if (retval)
17887 {
17888 retval = build1 (VIEW_CONVERT_EXPR,
17889 TREE_TYPE (TREE_TYPE (node->decl)),
17890 retval);
17891 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
17892 false, GSI_CONTINUE_LINKING);
17893 }
17894 g = gimple_build_return (retval);
17895 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17896
17897 /* Handle aligned clauses by replacing default defs of the aligned
17898 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
17899 lhs. Handle linear by adding PHIs. */
17900 for (unsigned i = 0; i < node->simdclone->nargs; i++)
17901 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
17902 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
17903 || !is_gimple_reg_type
17904 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
17905 {
17906 tree orig_arg = node->simdclone->args[i].orig_arg;
17907 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
17908 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
17909 else
17910 {
17911 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
17912 gimple_add_tmp_var (iter1);
17913 }
17914 gsi = gsi_after_labels (entry_bb);
17915 g = gimple_build_assign (iter1, orig_arg);
17916 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17917 gsi = gsi_after_labels (body_bb);
17918 g = gimple_build_assign (orig_arg, iter1);
17919 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17920 }
17921 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
17922 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
17923 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
17924 == REFERENCE_TYPE
17925 && TREE_ADDRESSABLE
17926 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
17927 {
17928 tree orig_arg = node->simdclone->args[i].orig_arg;
17929 tree def = ssa_default_def (cfun, orig_arg);
17930 if (def && !has_zero_uses (def))
17931 {
17932 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
17933 gimple_add_tmp_var (iter1);
17934 gsi = gsi_after_labels (entry_bb);
17935 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
17936 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17937 gsi = gsi_after_labels (body_bb);
17938 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
17939 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17940 }
17941 }
17942 else if (node->simdclone->args[i].alignment
17943 && node->simdclone->args[i].arg_type
17944 == SIMD_CLONE_ARG_TYPE_UNIFORM
17945 && (node->simdclone->args[i].alignment
17946 & (node->simdclone->args[i].alignment - 1)) == 0
17947 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
17948 == POINTER_TYPE)
17949 {
17950 unsigned int alignment = node->simdclone->args[i].alignment;
17951 tree orig_arg = node->simdclone->args[i].orig_arg;
17952 tree def = ssa_default_def (cfun, orig_arg);
17953 if (def && !has_zero_uses (def))
17954 {
17955 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
17956 gimple_seq seq = NULL;
17957 bool need_cvt = false;
17958 gcall *call
17959 = gimple_build_call (fn, 2, def, size_int (alignment));
17960 g = call;
17961 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
17962 ptr_type_node))
17963 need_cvt = true;
17964 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
17965 gimple_call_set_lhs (g, t);
17966 gimple_seq_add_stmt_without_update (&seq, g);
17967 if (need_cvt)
17968 {
17969 t = make_ssa_name (orig_arg);
17970 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
17971 gimple_seq_add_stmt_without_update (&seq, g);
17972 }
17973 gsi_insert_seq_on_edge_immediate
17974 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
17975
17976 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17977 int freq = compute_call_stmt_bb_frequency (current_function_decl,
17978 entry_bb);
17979 node->create_edge (cgraph_node::get_create (fn),
17980 call, entry_bb->count, freq);
17981
17982 imm_use_iterator iter;
17983 use_operand_p use_p;
17984 gimple *use_stmt;
17985 tree repl = gimple_get_lhs (g);
17986 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
17987 if (is_gimple_debug (use_stmt) || use_stmt == call)
17988 continue;
17989 else
17990 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
17991 SET_USE (use_p, repl);
17992 }
17993 }
17994 else if ((node->simdclone->args[i].arg_type
17995 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
17996 || (node->simdclone->args[i].arg_type
17997 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP))
17998 {
17999 tree orig_arg = node->simdclone->args[i].orig_arg;
18000 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18001 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
18002 tree def = NULL_TREE;
18003 if (TREE_ADDRESSABLE (orig_arg))
18004 {
18005 def = make_ssa_name (TREE_TYPE (orig_arg));
18006 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18007 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18008 gsi = gsi_after_labels (entry_bb);
18009 g = gimple_build_assign (def, orig_arg);
18010 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18011 }
18012 else
18013 {
18014 def = ssa_default_def (cfun, orig_arg);
18015 if (!def || has_zero_uses (def))
18016 def = NULL_TREE;
18017 else
18018 {
18019 iter1 = make_ssa_name (orig_arg);
18020 iter2 = make_ssa_name (orig_arg);
18021 }
18022 }
18023 if (def)
18024 {
18025 phi = create_phi_node (iter1, body_bb);
18026 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18027 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18028 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18029 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18030 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18031 ? TREE_TYPE (orig_arg) : sizetype;
18032 tree addcst
18033 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
18034 g = gimple_build_assign (iter2, code, iter1, addcst);
18035 gsi = gsi_last_bb (incr_bb);
18036 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18037
18038 imm_use_iterator iter;
18039 use_operand_p use_p;
18040 gimple *use_stmt;
18041 if (TREE_ADDRESSABLE (orig_arg))
18042 {
18043 gsi = gsi_after_labels (body_bb);
18044 g = gimple_build_assign (orig_arg, iter1);
18045 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18046 }
18047 else
18048 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18049 if (use_stmt == phi)
18050 continue;
18051 else
18052 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18053 SET_USE (use_p, iter1);
18054 }
18055 }
18056 else if (node->simdclone->args[i].arg_type
18057 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP)
18058 {
18059 tree orig_arg = node->simdclone->args[i].orig_arg;
18060 tree def = ssa_default_def (cfun, orig_arg);
18061 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18062 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18063 if (def && !has_zero_uses (def))
18064 {
18065 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18066 iter1 = make_ssa_name (orig_arg);
18067 iter2 = make_ssa_name (orig_arg);
18068 tree iter3 = make_ssa_name (rtype);
18069 tree iter4 = make_ssa_name (rtype);
18070 tree iter5 = make_ssa_name (rtype);
18071 gsi = gsi_after_labels (entry_bb);
18072 gimple *load
18073 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18074 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18075
18076 tree array = node->simdclone->args[i].simd_array;
18077 TREE_ADDRESSABLE (array) = 1;
18078 tree ptr = build_fold_addr_expr (array);
18079 phi = create_phi_node (iter1, body_bb);
18080 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18081 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18082 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18083 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18084 gsi = gsi_last_bb (incr_bb);
18085 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18086
18087 phi = create_phi_node (iter4, body_bb);
18088 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18089 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18090 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18091 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18092 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18093 ? TREE_TYPE (iter3) : sizetype;
18094 tree addcst
18095 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
18096 g = gimple_build_assign (iter5, code, iter4, addcst);
18097 gsi = gsi_last_bb (incr_bb);
18098 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18099
18100 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18101 gsi = gsi_after_labels (body_bb);
18102 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18103
18104 imm_use_iterator iter;
18105 use_operand_p use_p;
18106 gimple *use_stmt;
18107 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18108 if (use_stmt == load)
18109 continue;
18110 else
18111 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18112 SET_USE (use_p, iter1);
18113
18114 if (!TYPE_READONLY (rtype))
18115 {
18116 tree v = make_ssa_name (rtype);
18117 tree aref = build4 (ARRAY_REF, rtype, array,
18118 size_zero_node, NULL_TREE,
18119 NULL_TREE);
18120 gsi = gsi_after_labels (new_exit_bb);
18121 g = gimple_build_assign (v, aref);
18122 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18123 g = gimple_build_assign (build_simple_mem_ref (def), v);
18124 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18125 }
18126 }
18127 }
18128
18129 calculate_dominance_info (CDI_DOMINATORS);
18130 add_loop (loop, loop->header->loop_father);
18131 update_ssa (TODO_update_ssa);
18132
18133 pop_cfun ();
18134 }
18135
18136 /* If the function in NODE is tagged as an elemental SIMD function,
18137 create the appropriate SIMD clones. */
18138
18139 static void
18140 expand_simd_clones (struct cgraph_node *node)
18141 {
18142 tree attr = lookup_attribute ("omp declare simd",
18143 DECL_ATTRIBUTES (node->decl));
18144 if (attr == NULL_TREE
18145 || node->global.inlined_to
18146 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
18147 return;
18148
18149 /* Ignore
18150 #pragma omp declare simd
18151 extern int foo ();
18152 in C, there we don't know the argument types at all. */
18153 if (!node->definition
18154 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18155 return;
18156
18157 do
18158 {
18159 /* Start with parsing the "omp declare simd" attribute(s). */
18160 bool inbranch_clause_specified;
18161 struct cgraph_simd_clone *clone_info
18162 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18163 &inbranch_clause_specified);
18164 if (clone_info == NULL)
18165 continue;
18166
18167 int orig_simdlen = clone_info->simdlen;
18168 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18169 /* The target can return 0 (no simd clones should be created),
18170 1 (just one ISA of simd clones should be created) or higher
18171 count of ISA variants. In that case, clone_info is initialized
18172 for the first ISA variant. */
18173 int count
18174 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18175 base_type, 0);
18176 if (count == 0)
18177 continue;
18178
18179 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18180 also create one inbranch and one !inbranch clone of it. */
18181 for (int i = 0; i < count * 2; i++)
18182 {
18183 struct cgraph_simd_clone *clone = clone_info;
18184 if (inbranch_clause_specified && (i & 1) != 0)
18185 continue;
18186
18187 if (i != 0)
18188 {
18189 clone = simd_clone_struct_alloc (clone_info->nargs
18190 + ((i & 1) != 0));
18191 simd_clone_struct_copy (clone, clone_info);
18192 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18193 and simd_clone_adjust_argument_types did to the first
18194 clone's info. */
18195 clone->nargs -= clone_info->inbranch;
18196 clone->simdlen = orig_simdlen;
18197 /* And call the target hook again to get the right ISA. */
18198 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18199 base_type,
18200 i / 2);
18201 if ((i & 1) != 0)
18202 clone->inbranch = 1;
18203 }
18204
18205 /* simd_clone_mangle might fail if such a clone has been created
18206 already. */
18207 tree id = simd_clone_mangle (node, clone);
18208 if (id == NULL_TREE)
18209 continue;
18210
18211 /* Only when we are sure we want to create the clone actually
18212 clone the function (or definitions) or create another
18213 extern FUNCTION_DECL (for prototypes without definitions). */
18214 struct cgraph_node *n = simd_clone_create (node);
18215 if (n == NULL)
18216 continue;
18217
18218 n->simdclone = clone;
18219 clone->origin = node;
18220 clone->next_clone = NULL;
18221 if (node->simd_clones == NULL)
18222 {
18223 clone->prev_clone = n;
18224 node->simd_clones = n;
18225 }
18226 else
18227 {
18228 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18229 clone->prev_clone->simdclone->next_clone = n;
18230 node->simd_clones->simdclone->prev_clone = n;
18231 }
18232 symtab->change_decl_assembler_name (n->decl, id);
18233 /* And finally adjust the return type, parameters and for
18234 definitions also function body. */
18235 if (node->definition)
18236 simd_clone_adjust (n);
18237 else
18238 {
18239 simd_clone_adjust_return_type (n);
18240 simd_clone_adjust_argument_types (n);
18241 }
18242 }
18243 }
18244 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18245 }
18246
18247 /* Entry point for IPA simd clone creation pass. */
18248
18249 static unsigned int
18250 ipa_omp_simd_clone (void)
18251 {
18252 struct cgraph_node *node;
18253 FOR_EACH_FUNCTION (node)
18254 expand_simd_clones (node);
18255 return 0;
18256 }
18257
18258 namespace {
18259
18260 const pass_data pass_data_omp_simd_clone =
18261 {
18262 SIMPLE_IPA_PASS, /* type */
18263 "simdclone", /* name */
18264 OPTGROUP_NONE, /* optinfo_flags */
18265 TV_NONE, /* tv_id */
18266 ( PROP_ssa | PROP_cfg ), /* properties_required */
18267 0, /* properties_provided */
18268 0, /* properties_destroyed */
18269 0, /* todo_flags_start */
18270 0, /* todo_flags_finish */
18271 };
18272
18273 class pass_omp_simd_clone : public simple_ipa_opt_pass
18274 {
18275 public:
18276 pass_omp_simd_clone(gcc::context *ctxt)
18277 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18278 {}
18279
18280 /* opt_pass methods: */
18281 virtual bool gate (function *);
18282 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
18283 };
18284
18285 bool
18286 pass_omp_simd_clone::gate (function *)
18287 {
18288 return ((flag_openmp || flag_openmp_simd
18289 || flag_cilkplus
18290 || (in_lto_p && !flag_wpa))
18291 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
18292 }
18293
18294 } // anon namespace
18295
18296 simple_ipa_opt_pass *
18297 make_pass_omp_simd_clone (gcc::context *ctxt)
18298 {
18299 return new pass_omp_simd_clone (ctxt);
18300 }
18301
18302 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18303 adds their addresses and sizes to constructor-vector V_CTOR. */
18304 static void
18305 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18306 vec<constructor_elt, va_gc> *v_ctor)
18307 {
18308 unsigned len = vec_safe_length (v_decls);
18309 for (unsigned i = 0; i < len; i++)
18310 {
18311 tree it = (*v_decls)[i];
18312 bool is_function = TREE_CODE (it) != VAR_DECL;
18313
18314 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
18315 if (!is_function)
18316 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
18317 fold_convert (const_ptr_type_node,
18318 DECL_SIZE_UNIT (it)));
18319 }
18320 }
18321
18322 /* Create new symbols containing (address, size) pairs for global variables,
18323 marked with "omp declare target" attribute, as well as addresses for the
18324 functions, which are outlined offloading regions. */
18325 void
18326 omp_finish_file (void)
18327 {
18328 unsigned num_funcs = vec_safe_length (offload_funcs);
18329 unsigned num_vars = vec_safe_length (offload_vars);
18330
18331 if (num_funcs == 0 && num_vars == 0)
18332 return;
18333
18334 if (targetm_common.have_named_sections)
18335 {
18336 vec<constructor_elt, va_gc> *v_f, *v_v;
18337 vec_alloc (v_f, num_funcs);
18338 vec_alloc (v_v, num_vars * 2);
18339
18340 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18341 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18342
18343 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18344 num_vars * 2);
18345 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18346 num_funcs);
18347 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18348 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18349 tree ctor_v = build_constructor (vars_decl_type, v_v);
18350 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18351 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18352 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18353 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18354 get_identifier (".offload_func_table"),
18355 funcs_decl_type);
18356 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18357 get_identifier (".offload_var_table"),
18358 vars_decl_type);
18359 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18360 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18361 otherwise a joint table in a binary will contain padding between
18362 tables from multiple object files. */
18363 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18364 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18365 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18366 DECL_INITIAL (funcs_decl) = ctor_f;
18367 DECL_INITIAL (vars_decl) = ctor_v;
18368 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18369 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18370
18371 varpool_node::finalize_decl (vars_decl);
18372 varpool_node::finalize_decl (funcs_decl);
18373 }
18374 else
18375 {
18376 for (unsigned i = 0; i < num_funcs; i++)
18377 {
18378 tree it = (*offload_funcs)[i];
18379 targetm.record_offload_symbol (it);
18380 }
18381 for (unsigned i = 0; i < num_vars; i++)
18382 {
18383 tree it = (*offload_vars)[i];
18384 targetm.record_offload_symbol (it);
18385 }
18386 }
18387 }
18388
18389 /* Find the number of threads (POS = false), or thread number (POS =
18390 true) for an OpenACC region partitioned as MASK. Setup code
18391 required for the calculation is added to SEQ. */
18392
18393 static tree
18394 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18395 {
18396 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18397 unsigned ix;
18398
18399 /* Start at gang level, and examine relevant dimension indices. */
18400 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18401 if (GOMP_DIM_MASK (ix) & mask)
18402 {
18403 tree arg = build_int_cst (unsigned_type_node, ix);
18404
18405 if (res)
18406 {
18407 /* We had an outer index, so scale that by the size of
18408 this dimension. */
18409 tree n = create_tmp_var (integer_type_node);
18410 gimple *call
18411 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18412
18413 gimple_call_set_lhs (call, n);
18414 gimple_seq_add_stmt (seq, call);
18415 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18416 }
18417 if (pos)
18418 {
18419 /* Determine index in this dimension. */
18420 tree id = create_tmp_var (integer_type_node);
18421 gimple *call = gimple_build_call_internal
18422 (IFN_GOACC_DIM_POS, 1, arg);
18423
18424 gimple_call_set_lhs (call, id);
18425 gimple_seq_add_stmt (seq, call);
18426 if (res)
18427 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18428 else
18429 res = id;
18430 }
18431 }
18432
18433 if (res == NULL_TREE)
18434 res = integer_zero_node;
18435
18436 return res;
18437 }
18438
18439 /* Transform IFN_GOACC_LOOP calls to actual code. See
18440 expand_oacc_for for where these are generated. At the vector
18441 level, we stride loops, such that each member of a warp will
18442 operate on adjacent iterations. At the worker and gang level,
18443 each gang/warp executes a set of contiguous iterations. Chunking
18444 can override this such that each iteration engine executes a
18445 contiguous chunk, and then moves on to stride to the next chunk. */
18446
18447 static void
18448 oacc_xform_loop (gcall *call)
18449 {
18450 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18451 enum ifn_goacc_loop_kind code
18452 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18453 tree dir = gimple_call_arg (call, 1);
18454 tree range = gimple_call_arg (call, 2);
18455 tree step = gimple_call_arg (call, 3);
18456 tree chunk_size = NULL_TREE;
18457 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18458 tree lhs = gimple_call_lhs (call);
18459 tree type = TREE_TYPE (lhs);
18460 tree diff_type = TREE_TYPE (range);
18461 tree r = NULL_TREE;
18462 gimple_seq seq = NULL;
18463 bool chunking = false, striding = true;
18464 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18465 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18466
18467 #ifdef ACCEL_COMPILER
18468 chunk_size = gimple_call_arg (call, 4);
18469 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18470 || integer_zerop (chunk_size)) /* Default (also static). */
18471 {
18472 /* If we're at the gang level, we want each to execute a
18473 contiguous run of iterations. Otherwise we want each element
18474 to stride. */
18475 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18476 chunking = false;
18477 }
18478 else
18479 {
18480 /* Chunk of size 1 is striding. */
18481 striding = integer_onep (chunk_size);
18482 chunking = !striding;
18483 }
18484 #endif
18485
18486 /* striding=true, chunking=true
18487 -> invalid.
18488 striding=true, chunking=false
18489 -> chunks=1
18490 striding=false,chunking=true
18491 -> chunks=ceil (range/(chunksize*threads*step))
18492 striding=false,chunking=false
18493 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18494 push_gimplify_context (true);
18495
18496 switch (code)
18497 {
18498 default: gcc_unreachable ();
18499
18500 case IFN_GOACC_LOOP_CHUNKS:
18501 if (!chunking)
18502 r = build_int_cst (type, 1);
18503 else
18504 {
18505 /* chunk_max
18506 = (range - dir) / (chunks * step * num_threads) + dir */
18507 tree per = oacc_thread_numbers (false, mask, &seq);
18508 per = fold_convert (type, per);
18509 chunk_size = fold_convert (type, chunk_size);
18510 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18511 per = fold_build2 (MULT_EXPR, type, per, step);
18512 r = build2 (MINUS_EXPR, type, range, dir);
18513 r = build2 (PLUS_EXPR, type, r, per);
18514 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18515 }
18516 break;
18517
18518 case IFN_GOACC_LOOP_STEP:
18519 {
18520 /* If striding, step by the entire compute volume, otherwise
18521 step by the inner volume. */
18522 unsigned volume = striding ? mask : inner_mask;
18523
18524 r = oacc_thread_numbers (false, volume, &seq);
18525 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18526 }
18527 break;
18528
18529 case IFN_GOACC_LOOP_OFFSET:
18530 if (striding)
18531 {
18532 r = oacc_thread_numbers (true, mask, &seq);
18533 r = fold_convert (diff_type, r);
18534 }
18535 else
18536 {
18537 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18538 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18539 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18540 inner_size, outer_size);
18541
18542 volume = fold_convert (diff_type, volume);
18543 if (chunking)
18544 chunk_size = fold_convert (diff_type, chunk_size);
18545 else
18546 {
18547 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18548
18549 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18550 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18551 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18552 }
18553
18554 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18555 fold_convert (diff_type, inner_size));
18556 r = oacc_thread_numbers (true, outer_mask, &seq);
18557 r = fold_convert (diff_type, r);
18558 r = build2 (MULT_EXPR, diff_type, r, span);
18559
18560 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18561 inner = fold_convert (diff_type, inner);
18562 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18563
18564 if (chunking)
18565 {
18566 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18567 tree per
18568 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18569 per = build2 (MULT_EXPR, diff_type, per, chunk);
18570
18571 r = build2 (PLUS_EXPR, diff_type, r, per);
18572 }
18573 }
18574 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18575 if (type != diff_type)
18576 r = fold_convert (type, r);
18577 break;
18578
18579 case IFN_GOACC_LOOP_BOUND:
18580 if (striding)
18581 r = range;
18582 else
18583 {
18584 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18585 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18586 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18587 inner_size, outer_size);
18588
18589 volume = fold_convert (diff_type, volume);
18590 if (chunking)
18591 chunk_size = fold_convert (diff_type, chunk_size);
18592 else
18593 {
18594 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18595
18596 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18597 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18598 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18599 }
18600
18601 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18602 fold_convert (diff_type, inner_size));
18603
18604 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18605
18606 tree offset = gimple_call_arg (call, 6);
18607 r = build2 (PLUS_EXPR, diff_type, r,
18608 fold_convert (diff_type, offset));
18609 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18610 diff_type, r, range);
18611 }
18612 if (diff_type != type)
18613 r = fold_convert (type, r);
18614 break;
18615 }
18616
18617 gimplify_assign (lhs, r, &seq);
18618
18619 pop_gimplify_context (NULL);
18620
18621 gsi_replace_with_seq (&gsi, seq, true);
18622 }
18623
18624 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18625 raw attribute. DIMS is an array of dimensions, which is returned.
18626 Returns the function level dimensionality -- the level at which an
18627 offload routine wishes to partition a loop. */
18628
18629 static int
18630 oacc_validate_dims (tree fn, tree attrs, int *dims)
18631 {
18632 tree purpose[GOMP_DIM_MAX];
18633 unsigned ix;
18634 tree pos = TREE_VALUE (attrs);
18635 int fn_level = -1;
18636
18637 /* Make sure the attribute creator attached the dimension
18638 information. */
18639 gcc_assert (pos);
18640
18641 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18642 {
18643 purpose[ix] = TREE_PURPOSE (pos);
18644
18645 if (purpose[ix])
18646 {
18647 if (integer_zerop (purpose[ix]))
18648 fn_level = ix + 1;
18649 else if (fn_level < 0)
18650 fn_level = ix;
18651 }
18652
18653 tree val = TREE_VALUE (pos);
18654 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18655 pos = TREE_CHAIN (pos);
18656 }
18657
18658 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18659
18660 /* Default anything left to 1. */
18661 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18662 if (dims[ix] < 0)
18663 {
18664 dims[ix] = 1;
18665 changed = true;
18666 }
18667
18668 if (changed)
18669 {
18670 /* Replace the attribute with new values. */
18671 pos = NULL_TREE;
18672 for (ix = GOMP_DIM_MAX; ix--;)
18673 pos = tree_cons (purpose[ix],
18674 build_int_cst (integer_type_node, dims[ix]),
18675 pos);
18676 replace_oacc_fn_attrib (fn, pos);
18677 }
18678
18679 return fn_level;
18680 }
18681
18682 /* Create an empty OpenACC loop structure at LOC. */
18683
18684 static oacc_loop *
18685 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18686 {
18687 oacc_loop *loop = XCNEW (oacc_loop);
18688
18689 loop->parent = parent;
18690 loop->child = loop->sibling = NULL;
18691
18692 if (parent)
18693 {
18694 loop->sibling = parent->child;
18695 parent->child = loop;
18696 }
18697
18698 loop->loc = loc;
18699 loop->marker = NULL;
18700 memset (loop->heads, 0, sizeof (loop->heads));
18701 memset (loop->tails, 0, sizeof (loop->tails));
18702 loop->routine = NULL_TREE;
18703
18704 loop->mask = loop->flags = 0;
18705 loop->chunk_size = 0;
18706 loop->head_end = NULL;
18707
18708 return loop;
18709 }
18710
18711 /* Create an outermost, dummy OpenACC loop for offloaded function
18712 DECL. */
18713
18714 static oacc_loop *
18715 new_oacc_loop_outer (tree decl)
18716 {
18717 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18718 }
18719
18720 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18721 Link into PARENT loop. Return the new loop. */
18722
18723 static oacc_loop *
18724 new_oacc_loop (oacc_loop *parent, gcall *marker)
18725 {
18726 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18727
18728 loop->marker = marker;
18729
18730 /* TODO: This is where device_type flattening would occur for the loop
18731 flags. */
18732
18733 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18734
18735 tree chunk_size = integer_zero_node;
18736 if (loop->flags & OLF_GANG_STATIC)
18737 chunk_size = gimple_call_arg (marker, 4);
18738 loop->chunk_size = chunk_size;
18739
18740 return loop;
18741 }
18742
18743 /* Create a dummy loop encompassing a call to a openACC routine.
18744 Extract the routine's partitioning requirements. */
18745
18746 static void
18747 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18748 {
18749 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18750 int dims[GOMP_DIM_MAX];
18751 int level = oacc_validate_dims (decl, attrs, dims);
18752
18753 gcc_assert (level >= 0);
18754
18755 loop->marker = call;
18756 loop->routine = decl;
18757 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18758 ^ (GOMP_DIM_MASK (level) - 1));
18759 }
18760
18761 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18762 Return the parent loop. */
18763
18764 static oacc_loop *
18765 finish_oacc_loop (oacc_loop *loop)
18766 {
18767 return loop->parent;
18768 }
18769
18770 /* Free all OpenACC loop structures within LOOP (inclusive). */
18771
18772 static void
18773 free_oacc_loop (oacc_loop *loop)
18774 {
18775 if (loop->sibling)
18776 free_oacc_loop (loop->sibling);
18777 if (loop->child)
18778 free_oacc_loop (loop->child);
18779
18780 free (loop);
18781 }
18782
18783 /* Dump out the OpenACC loop head or tail beginning at FROM. */
18784
18785 static void
18786 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
18787 const char *title, int level)
18788 {
18789 enum ifn_unique_kind kind
18790 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
18791
18792 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
18793 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
18794 {
18795 gimple *stmt = gsi_stmt (gsi);
18796
18797 if (is_gimple_call (stmt)
18798 && gimple_call_internal_p (stmt)
18799 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
18800 {
18801 enum ifn_unique_kind k
18802 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
18803 (gimple_call_arg (stmt, 0)));
18804
18805 if (k == kind && stmt != from)
18806 break;
18807 }
18808 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
18809
18810 gsi_next (&gsi);
18811 while (gsi_end_p (gsi))
18812 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
18813 }
18814 }
18815
18816 /* Dump OpenACC loops LOOP, its siblings and its children. */
18817
18818 static void
18819 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
18820 {
18821 int ix;
18822
18823 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
18824 loop->flags, loop->mask,
18825 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
18826
18827 if (loop->marker)
18828 print_gimple_stmt (file, loop->marker, depth * 2, 0);
18829
18830 if (loop->routine)
18831 fprintf (file, "%*sRoutine %s:%u:%s\n",
18832 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
18833 DECL_SOURCE_LINE (loop->routine),
18834 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
18835
18836 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18837 if (loop->heads[ix])
18838 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
18839 for (ix = GOMP_DIM_MAX; ix--;)
18840 if (loop->tails[ix])
18841 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
18842
18843 if (loop->child)
18844 dump_oacc_loop (file, loop->child, depth + 1);
18845 if (loop->sibling)
18846 dump_oacc_loop (file, loop->sibling, depth);
18847 }
18848
18849 void debug_oacc_loop (oacc_loop *);
18850
18851 /* Dump loops to stderr. */
18852
18853 DEBUG_FUNCTION void
18854 debug_oacc_loop (oacc_loop *loop)
18855 {
18856 dump_oacc_loop (stderr, loop, 0);
18857 }
18858
18859 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
18860 structures as we go. By construction these loops are properly
18861 nested. */
18862
18863 static void
18864 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
18865 {
18866 int marker = 0;
18867 int remaining = 0;
18868
18869 if (bb->flags & BB_VISITED)
18870 return;
18871
18872 follow:
18873 bb->flags |= BB_VISITED;
18874
18875 /* Scan for loop markers. */
18876 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
18877 gsi_next (&gsi))
18878 {
18879 gimple *stmt = gsi_stmt (gsi);
18880
18881 if (!is_gimple_call (stmt))
18882 continue;
18883
18884 gcall *call = as_a <gcall *> (stmt);
18885
18886 /* If this is a routine, make a dummy loop for it. */
18887 if (tree decl = gimple_call_fndecl (call))
18888 if (tree attrs = get_oacc_fn_attrib (decl))
18889 {
18890 gcc_assert (!marker);
18891 new_oacc_loop_routine (loop, call, decl, attrs);
18892 }
18893
18894 if (!gimple_call_internal_p (call))
18895 continue;
18896
18897 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
18898 continue;
18899
18900 enum ifn_unique_kind kind
18901 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18902 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
18903 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
18904 {
18905 if (gimple_call_num_args (call) == 2)
18906 {
18907 gcc_assert (marker && !remaining);
18908 marker = 0;
18909 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
18910 loop = finish_oacc_loop (loop);
18911 else
18912 loop->head_end = call;
18913 }
18914 else
18915 {
18916 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
18917
18918 if (!marker)
18919 {
18920 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
18921 loop = new_oacc_loop (loop, call);
18922 remaining = count;
18923 }
18924 gcc_assert (count == remaining);
18925 if (remaining)
18926 {
18927 remaining--;
18928 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
18929 loop->heads[marker] = call;
18930 else
18931 loop->tails[remaining] = call;
18932 }
18933 marker++;
18934 }
18935 }
18936 }
18937 if (remaining || marker)
18938 {
18939 bb = single_succ (bb);
18940 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
18941 goto follow;
18942 }
18943
18944 /* Walk successor blocks. */
18945 edge e;
18946 edge_iterator ei;
18947
18948 FOR_EACH_EDGE (e, ei, bb->succs)
18949 oacc_loop_discover_walk (loop, e->dest);
18950 }
18951
18952 /* LOOP is the first sibling. Reverse the order in place and return
18953 the new first sibling. Recurse to child loops. */
18954
18955 static oacc_loop *
18956 oacc_loop_sibling_nreverse (oacc_loop *loop)
18957 {
18958 oacc_loop *last = NULL;
18959 do
18960 {
18961 if (loop->child)
18962 loop->child = oacc_loop_sibling_nreverse (loop->child);
18963
18964 oacc_loop *next = loop->sibling;
18965 loop->sibling = last;
18966 last = loop;
18967 loop = next;
18968 }
18969 while (loop);
18970
18971 return last;
18972 }
18973
18974 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
18975 the current function. */
18976
18977 static oacc_loop *
18978 oacc_loop_discovery ()
18979 {
18980 basic_block bb;
18981
18982 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
18983 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
18984
18985 /* The siblings were constructed in reverse order, reverse them so
18986 that diagnostics come out in an unsurprising order. */
18987 top = oacc_loop_sibling_nreverse (top);
18988
18989 /* Reset the visited flags. */
18990 FOR_ALL_BB_FN (bb, cfun)
18991 bb->flags &= ~BB_VISITED;
18992
18993 return top;
18994 }
18995
18996 /* Transform the abstract internal function markers starting at FROM
18997 to be for partitioning level LEVEL. Stop when we meet another HEAD
18998 or TAIL marker. */
18999
19000 static void
19001 oacc_loop_xform_head_tail (gcall *from, int level)
19002 {
19003 enum ifn_unique_kind kind
19004 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19005 tree replacement = build_int_cst (unsigned_type_node, level);
19006
19007 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19008 {
19009 gimple *stmt = gsi_stmt (gsi);
19010
19011 if (is_gimple_call (stmt)
19012 && gimple_call_internal_p (stmt)
19013 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19014 {
19015 enum ifn_unique_kind k
19016 = ((enum ifn_unique_kind)
19017 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19018
19019 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19020 *gimple_call_arg_ptr (stmt, 2) = replacement;
19021 else if (k == kind && stmt != from)
19022 break;
19023 }
19024 gsi_next (&gsi);
19025 while (gsi_end_p (gsi))
19026 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19027 }
19028 }
19029
19030 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19031 determined partitioning mask and chunking argument. */
19032
19033 static void
19034 oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19035 {
19036 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19037
19038 for (;;)
19039 {
19040 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19041 {
19042 gimple *stmt = gsi_stmt (gsi);
19043
19044 if (!is_gimple_call (stmt))
19045 continue;
19046
19047 gcall *call = as_a <gcall *> (stmt);
19048
19049 if (!gimple_call_internal_p (call))
19050 continue;
19051
19052 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19053 continue;
19054
19055 *gimple_call_arg_ptr (call, 5) = mask_arg;
19056 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19057 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19058 == IFN_GOACC_LOOP_BOUND)
19059 return;
19060 }
19061
19062 /* If we didn't see LOOP_BOUND, it should be in the single
19063 successor block. */
19064 basic_block bb = single_succ (gsi_bb (gsi));
19065 gsi = gsi_start_bb (bb);
19066 }
19067 }
19068
19069 /* Process the discovered OpenACC loops, setting the correct
19070 partitioning level etc. */
19071
19072 static void
19073 oacc_loop_process (oacc_loop *loop)
19074 {
19075 if (loop->child)
19076 oacc_loop_process (loop->child);
19077
19078 if (loop->mask && !loop->routine)
19079 {
19080 int ix;
19081 unsigned mask = loop->mask;
19082 unsigned dim = GOMP_DIM_GANG;
19083 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19084 tree chunk_arg = loop->chunk_size;
19085
19086 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19087
19088 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19089 {
19090 gcc_assert (mask);
19091
19092 while (!(GOMP_DIM_MASK (dim) & mask))
19093 dim++;
19094
19095 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19096 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19097
19098 mask ^= GOMP_DIM_MASK (dim);
19099 }
19100 }
19101
19102 if (loop->sibling)
19103 oacc_loop_process (loop->sibling);
19104 }
19105
19106 /* Walk the OpenACC loop heirarchy checking and assigning the
19107 programmer-specified partitionings. OUTER_MASK is the partitioning
19108 this loop is contained within. Return partitiong mask used within
19109 this loop nest. */
19110
19111 static unsigned
19112 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19113 {
19114 unsigned this_mask = loop->mask;
19115 bool has_auto = false;
19116 bool noisy = true;
19117
19118 #ifdef ACCEL_COMPILER
19119 /* When device_type is supported, we want the device compiler to be
19120 noisy, if the loop parameters are device_type-specific. */
19121 noisy = false;
19122 #endif
19123
19124 if (!loop->routine)
19125 {
19126 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19127 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19128
19129 this_mask = ((loop->flags >> OLF_DIM_BASE)
19130 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19131
19132 if ((this_mask != 0) + auto_par + seq_par > 1)
19133 {
19134 if (noisy)
19135 error_at (loop->loc,
19136 seq_par
19137 ? "%<seq%> overrides other OpenACC loop specifiers"
19138 : "%<auto%> conflicts with other OpenACC loop specifiers");
19139 auto_par = false;
19140 loop->flags &= ~OLF_AUTO;
19141 if (seq_par)
19142 {
19143 loop->flags &=
19144 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19145 this_mask = 0;
19146 }
19147 }
19148 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19149 has_auto = true;
19150 }
19151
19152 if (this_mask & outer_mask)
19153 {
19154 const oacc_loop *outer;
19155 for (outer = loop->parent; outer; outer = outer->parent)
19156 if (outer->mask & this_mask)
19157 break;
19158
19159 if (noisy)
19160 {
19161 if (outer)
19162 {
19163 error_at (loop->loc,
19164 "%s uses same OpenACC parallelism as containing loop",
19165 loop->routine ? "routine call" : "inner loop");
19166 inform (outer->loc, "containing loop here");
19167 }
19168 else
19169 error_at (loop->loc,
19170 "%s uses OpenACC parallelism disallowed by containing routine",
19171 loop->routine ? "routine call" : "loop");
19172
19173 if (loop->routine)
19174 inform (DECL_SOURCE_LOCATION (loop->routine),
19175 "routine %qD declared here", loop->routine);
19176 }
19177 this_mask &= ~outer_mask;
19178 }
19179 else
19180 {
19181 unsigned outermost = this_mask & -this_mask;
19182
19183 if (outermost && outermost <= outer_mask)
19184 {
19185 if (noisy)
19186 {
19187 error_at (loop->loc,
19188 "incorrectly nested OpenACC loop parallelism");
19189
19190 const oacc_loop *outer;
19191 for (outer = loop->parent;
19192 outer->flags && outer->flags < outermost;
19193 outer = outer->parent)
19194 continue;
19195 inform (outer->loc, "containing loop here");
19196 }
19197
19198 this_mask &= ~outermost;
19199 }
19200 }
19201
19202 loop->mask = this_mask;
19203
19204 if (loop->child
19205 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19206 has_auto = true;
19207
19208 if (loop->sibling
19209 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19210 has_auto = true;
19211
19212 return has_auto;
19213 }
19214
19215 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19216 axes. */
19217
19218 static void
19219 oacc_loop_partition (oacc_loop *loop, int fn_level)
19220 {
19221 unsigned outer_mask = 0;
19222
19223 if (fn_level >= 0)
19224 outer_mask = GOMP_DIM_MASK (fn_level) - 1;
19225
19226 oacc_loop_fixed_partitions (loop, outer_mask);
19227 }
19228
19229 /* Default fork/join early expander. Delete the function calls if
19230 there is no RTL expander. */
19231
19232 bool
19233 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19234 const int *ARG_UNUSED (dims), bool is_fork)
19235 {
19236 if (is_fork)
19237 return targetm.have_oacc_fork ();
19238 else
19239 return targetm.have_oacc_join ();
19240 }
19241
19242 /* Main entry point for oacc transformations which run on the device
19243 compiler after LTO, so we know what the target device is at this
19244 point (including the host fallback). */
19245
19246 static unsigned int
19247 execute_oacc_device_lower ()
19248 {
19249 tree attrs = get_oacc_fn_attrib (current_function_decl);
19250 int dims[GOMP_DIM_MAX];
19251
19252 if (!attrs)
19253 /* Not an offloaded function. */
19254 return 0;
19255
19256 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19257
19258 /* Discover, partition and process the loops. */
19259 oacc_loop *loops = oacc_loop_discovery ();
19260 oacc_loop_partition (loops, fn_level);
19261 oacc_loop_process (loops);
19262 if (dump_file)
19263 {
19264 fprintf (dump_file, "OpenACC loops\n");
19265 dump_oacc_loop (dump_file, loops, 0);
19266 fprintf (dump_file, "\n");
19267 }
19268
19269 /* Now lower internal loop functions to target-specific code
19270 sequences. */
19271 basic_block bb;
19272 FOR_ALL_BB_FN (bb, cfun)
19273 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19274 {
19275 gimple *stmt = gsi_stmt (gsi);
19276 if (!is_gimple_call (stmt))
19277 {
19278 gsi_next (&gsi);
19279 continue;
19280 }
19281
19282 gcall *call = as_a <gcall *> (stmt);
19283 if (!gimple_call_internal_p (call))
19284 {
19285 gsi_next (&gsi);
19286 continue;
19287 }
19288
19289 /* Rewind to allow rescan. */
19290 gsi_prev (&gsi);
19291 bool rescan = false, remove = false;
19292 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19293
19294 switch (ifn_code)
19295 {
19296 default: break;
19297
19298 case IFN_GOACC_LOOP:
19299 oacc_xform_loop (call);
19300 rescan = true;
19301 break;
19302
19303 case IFN_UNIQUE:
19304 {
19305 enum ifn_unique_kind kind
19306 = ((enum ifn_unique_kind)
19307 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19308
19309 switch (kind)
19310 {
19311 default:
19312 gcc_unreachable ();
19313
19314 case IFN_UNIQUE_OACC_FORK:
19315 case IFN_UNIQUE_OACC_JOIN:
19316 if (integer_minus_onep (gimple_call_arg (call, 2)))
19317 remove = true;
19318 else if (!targetm.goacc.fork_join
19319 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19320 remove = true;
19321 break;
19322
19323 case IFN_UNIQUE_OACC_HEAD_MARK:
19324 case IFN_UNIQUE_OACC_TAIL_MARK:
19325 remove = true;
19326 break;
19327 }
19328 break;
19329 }
19330 }
19331
19332 if (gsi_end_p (gsi))
19333 /* We rewound past the beginning of the BB. */
19334 gsi = gsi_start_bb (bb);
19335 else
19336 /* Undo the rewind. */
19337 gsi_next (&gsi);
19338
19339 if (remove)
19340 {
19341 if (gimple_vdef (call))
19342 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19343 if (gimple_call_lhs (call))
19344 {
19345 /* Propagate the data dependency var. */
19346 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19347 gimple_call_arg (call, 1));
19348 gsi_replace (&gsi, ass, false);
19349 }
19350 else
19351 gsi_remove (&gsi, true);
19352 }
19353 else if (!rescan)
19354 /* If not rescanning, advance over the call. */
19355 gsi_next (&gsi);
19356 }
19357
19358 free_oacc_loop (loops);
19359
19360 return 0;
19361 }
19362
19363 /* Default launch dimension validator. Force everything to 1. A
19364 backend that wants to provide larger dimensions must override this
19365 hook. */
19366
19367 bool
19368 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19369 int ARG_UNUSED (fn_level))
19370 {
19371 bool changed = false;
19372
19373 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19374 {
19375 if (dims[ix] != 1)
19376 {
19377 dims[ix] = 1;
19378 changed = true;
19379 }
19380 }
19381
19382 return changed;
19383 }
19384
19385 namespace {
19386
19387 const pass_data pass_data_oacc_device_lower =
19388 {
19389 GIMPLE_PASS, /* type */
19390 "oaccdevlow", /* name */
19391 OPTGROUP_NONE, /* optinfo_flags */
19392 TV_NONE, /* tv_id */
19393 PROP_cfg, /* properties_required */
19394 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19395 0, /* properties_destroyed */
19396 0, /* todo_flags_start */
19397 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19398 };
19399
19400 class pass_oacc_device_lower : public gimple_opt_pass
19401 {
19402 public:
19403 pass_oacc_device_lower (gcc::context *ctxt)
19404 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19405 {}
19406
19407 /* opt_pass methods: */
19408 virtual unsigned int execute (function *)
19409 {
19410 bool gate = flag_openacc != 0;
19411
19412 if (!gate)
19413 return 0;
19414
19415 return execute_oacc_device_lower ();
19416 }
19417
19418 }; // class pass_oacc_transform
19419
19420 } // anon namespace
19421
19422 gimple_opt_pass *
19423 make_pass_oacc_device_lower (gcc::context *ctxt)
19424 {
19425 return new pass_oacc_device_lower (ctxt);
19426 }
19427
19428 #include "gt-omp-low.h"