builtin-integral-1.c: Require c99_runtime.
[official-gcc.git] / gcc / omp-low.c
blobbe472c035367e36c6023c46a212f78621be76870
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.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2016 Free Software Foundation, Inc.
9 This file is part of GCC.
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.
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.
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/>. */
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"
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.
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. */
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. */
99 struct omp_region
101 /* The enclosing region. */
102 struct omp_region *outer;
104 /* First child region. */
105 struct omp_region *inner;
107 /* Next peer region. */
108 struct omp_region *next;
110 /* Block containing the omp directive as its last stmt. */
111 basic_block entry;
113 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
114 basic_block exit;
116 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
117 basic_block cont;
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;
124 /* The code for the omp directive of this region. */
125 enum gimple_code type;
127 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
128 enum omp_clause_schedule_kind sched_kind;
130 /* Schedule modifiers. */
131 unsigned char sched_modifiers;
133 /* True if this is a combined parallel+workshare region. */
134 bool is_combined_parallel;
136 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
137 a depend clause. */
138 gomp_ordered *ord_stmt;
141 /* Context structure. Used to store information about each parallel
142 directive in the code. */
144 struct omp_context
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
150 copy_body_data cb;
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context *outer;
154 gimple *stmt;
156 /* Map variables to fields in a structure that allows communication
157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map;
169 tree srecord_type;
171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
173 tree block_vars;
175 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
176 barriers should jump to during omplower pass. */
177 tree cancel_label;
179 /* What to do with variables with implicitly determined sharing
180 attributes. */
181 enum omp_clause_default_kind default_kind;
183 /* Nesting depth of this context. Used to beautify error messages re
184 invalid gotos. The outermost ctx is depth 1, with depth 0 being
185 reserved for the main body of the function. */
186 int depth;
188 /* True if this parallel directive is nested within another. */
189 bool is_nested;
191 /* True if this construct can be cancelled. */
192 bool cancellable;
195 /* A structure holding the elements of:
196 for (V = N1; V cond N2; V += STEP) [...] */
198 struct omp_for_data_loop
200 tree v, n1, n2, step;
201 enum tree_code cond_code;
204 /* A structure describing the main elements of a parallel loop. */
206 struct omp_for_data
208 struct omp_for_data_loop loop;
209 tree chunk_size;
210 gomp_for *for_stmt;
211 tree pre, iter_type;
212 int collapse;
213 int ordered;
214 bool have_nowait, have_ordered, simd_schedule;
215 unsigned char sched_modifiers;
216 enum omp_clause_schedule_kind sched_kind;
217 struct omp_for_data_loop *loops;
220 /* Describe the OpenACC looping structure of a function. The entire
221 function is held in a 'NULL' loop. */
223 struct oacc_loop
225 oacc_loop *parent; /* Containing loop. */
227 oacc_loop *child; /* First inner loop. */
229 oacc_loop *sibling; /* Next loop within same parent. */
231 location_t loc; /* Location of the loop start. */
233 gcall *marker; /* Initial head marker. */
235 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
236 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
238 tree routine; /* Pseudo-loop enclosing a routine. */
240 unsigned mask; /* Partitioning mask. */
241 unsigned flags; /* Partitioning flags. */
242 tree chunk_size; /* Chunk size. */
243 gcall *head_end; /* Final marker of head sequence. */
246 /* Flags for an OpenACC loop. */
248 enum oacc_loop_flags {
249 OLF_SEQ = 1u << 0, /* Explicitly sequential */
250 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
251 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
252 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
254 /* Explicitly specified loop axes. */
255 OLF_DIM_BASE = 4,
256 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
257 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
258 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
260 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
264 static splay_tree all_contexts;
265 static int taskreg_nesting_level;
266 static int target_nesting_level;
267 static struct omp_region *root_omp_region;
268 static bitmap task_shared_vars;
269 static vec<omp_context *> taskreg_contexts;
270 static bool omp_any_child_fn_dumped;
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);
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;
286 /* Return true if CTX corresponds to an oacc parallel region. */
288 static bool
289 is_oacc_parallel (omp_context *ctx)
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));
297 /* Return true if CTX corresponds to an oacc kernels region. */
299 static bool
300 is_oacc_kernels (omp_context *ctx)
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));
308 /* If DECL is the artificial dummy VAR_DECL created for non-static
309 data member privatization, return the underlying "this" parameter,
310 otherwise return NULL. */
312 tree
313 omp_member_access_dummy_var (tree decl)
315 if (!VAR_P (decl)
316 || !DECL_ARTIFICIAL (decl)
317 || !DECL_IGNORED_P (decl)
318 || !DECL_HAS_VALUE_EXPR_P (decl)
319 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
320 return NULL_TREE;
322 tree v = DECL_VALUE_EXPR (decl);
323 if (TREE_CODE (v) != COMPONENT_REF)
324 return NULL_TREE;
326 while (1)
327 switch (TREE_CODE (v))
329 case COMPONENT_REF:
330 case MEM_REF:
331 case INDIRECT_REF:
332 CASE_CONVERT:
333 case POINTER_PLUS_EXPR:
334 v = TREE_OPERAND (v, 0);
335 continue;
336 case PARM_DECL:
337 if (DECL_CONTEXT (v) == current_function_decl
338 && DECL_ARTIFICIAL (v)
339 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
340 return v;
341 return NULL_TREE;
342 default:
343 return NULL_TREE;
347 /* Helper for unshare_and_remap, called through walk_tree. */
349 static tree
350 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
352 tree *pair = (tree *) data;
353 if (*tp == pair[0])
355 *tp = unshare_expr (pair[1]);
356 *walk_subtrees = 0;
358 else if (IS_TYPE_OR_DECL_P (*tp))
359 *walk_subtrees = 0;
360 return NULL_TREE;
363 /* Return unshare_expr (X) with all occurrences of FROM
364 replaced with TO. */
366 static tree
367 unshare_and_remap (tree x, tree from, tree to)
369 tree pair[2] = { from, to };
370 x = unshare_expr (x);
371 walk_tree (&x, unshare_and_remap_1, pair, NULL);
372 return x;
375 /* Holds offload tables with decls. */
376 vec<tree, va_gc> *offload_funcs, *offload_vars;
378 /* Convenience function for calling scan_omp_1_op on tree operands. */
380 static inline tree
381 scan_omp_op (tree *tp, omp_context *ctx)
383 struct walk_stmt_info wi;
385 memset (&wi, 0, sizeof (wi));
386 wi.info = ctx;
387 wi.want_locations = true;
389 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
392 static void lower_omp (gimple_seq *, omp_context *);
393 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
394 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
396 /* Find an OMP clause of type KIND within CLAUSES. */
398 tree
399 find_omp_clause (tree clauses, enum omp_clause_code kind)
401 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
402 if (OMP_CLAUSE_CODE (clauses) == kind)
403 return clauses;
405 return NULL_TREE;
408 /* Return true if CTX is for an omp parallel. */
410 static inline bool
411 is_parallel_ctx (omp_context *ctx)
413 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
417 /* Return true if CTX is for an omp task. */
419 static inline bool
420 is_task_ctx (omp_context *ctx)
422 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
426 /* Return true if CTX is for an omp taskloop. */
428 static inline bool
429 is_taskloop_ctx (omp_context *ctx)
431 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
432 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
436 /* Return true if CTX is for an omp parallel or omp task. */
438 static inline bool
439 is_taskreg_ctx (omp_context *ctx)
441 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
445 /* Return true if REGION is a combined parallel+workshare region. */
447 static inline bool
448 is_combined_parallel (struct omp_region *region)
450 return region->is_combined_parallel;
454 /* Extract the header elements of parallel loop FOR_STMT and store
455 them into *FD. */
457 static void
458 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
459 struct omp_for_data_loop *loops)
461 tree t, var, *collapse_iter, *collapse_count;
462 tree count = NULL_TREE, iter_type = long_integer_type_node;
463 struct omp_for_data_loop *loop;
464 int i;
465 struct omp_for_data_loop dummy_loop;
466 location_t loc = gimple_location (for_stmt);
467 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
468 bool distribute = gimple_omp_for_kind (for_stmt)
469 == GF_OMP_FOR_KIND_DISTRIBUTE;
470 bool taskloop = gimple_omp_for_kind (for_stmt)
471 == GF_OMP_FOR_KIND_TASKLOOP;
472 tree iterv, countv;
474 fd->for_stmt = for_stmt;
475 fd->pre = NULL;
476 if (gimple_omp_for_collapse (for_stmt) > 1)
477 fd->loops = loops;
478 else
479 fd->loops = &fd->loop;
481 fd->have_nowait = distribute || simd;
482 fd->have_ordered = false;
483 fd->collapse = 1;
484 fd->ordered = 0;
485 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
486 fd->sched_modifiers = 0;
487 fd->chunk_size = NULL_TREE;
488 fd->simd_schedule = false;
489 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
490 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
491 collapse_iter = NULL;
492 collapse_count = NULL;
494 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
495 switch (OMP_CLAUSE_CODE (t))
497 case OMP_CLAUSE_NOWAIT:
498 fd->have_nowait = true;
499 break;
500 case OMP_CLAUSE_ORDERED:
501 fd->have_ordered = true;
502 if (OMP_CLAUSE_ORDERED_EXPR (t))
503 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
504 break;
505 case OMP_CLAUSE_SCHEDULE:
506 gcc_assert (!distribute && !taskloop);
507 fd->sched_kind
508 = (enum omp_clause_schedule_kind)
509 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
510 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
511 & ~OMP_CLAUSE_SCHEDULE_MASK);
512 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
513 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
514 break;
515 case OMP_CLAUSE_DIST_SCHEDULE:
516 gcc_assert (distribute);
517 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
518 break;
519 case OMP_CLAUSE_COLLAPSE:
520 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
521 if (fd->collapse > 1)
523 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
524 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
526 break;
527 default:
528 break;
530 if (fd->ordered && fd->collapse == 1 && loops != NULL)
532 fd->loops = loops;
533 iterv = NULL_TREE;
534 countv = NULL_TREE;
535 collapse_iter = &iterv;
536 collapse_count = &countv;
539 /* FIXME: for now map schedule(auto) to schedule(static).
540 There should be analysis to determine whether all iterations
541 are approximately the same amount of work (then schedule(static)
542 is best) or if it varies (then schedule(dynamic,N) is better). */
543 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
545 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
546 gcc_assert (fd->chunk_size == NULL);
548 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
549 if (taskloop)
550 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
551 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
552 gcc_assert (fd->chunk_size == NULL);
553 else if (fd->chunk_size == NULL)
555 /* We only need to compute a default chunk size for ordered
556 static loops and dynamic loops. */
557 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
558 || fd->have_ordered)
559 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
560 ? integer_zero_node : integer_one_node;
563 int cnt = fd->ordered ? fd->ordered : fd->collapse;
564 for (i = 0; i < cnt; i++)
566 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
567 loop = &fd->loop;
568 else if (loops != NULL)
569 loop = loops + i;
570 else
571 loop = &dummy_loop;
573 loop->v = gimple_omp_for_index (for_stmt, i);
574 gcc_assert (SSA_VAR_P (loop->v));
575 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
576 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
577 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
578 loop->n1 = gimple_omp_for_initial (for_stmt, i);
580 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
581 loop->n2 = gimple_omp_for_final (for_stmt, i);
582 switch (loop->cond_code)
584 case LT_EXPR:
585 case GT_EXPR:
586 break;
587 case NE_EXPR:
588 gcc_assert (gimple_omp_for_kind (for_stmt)
589 == GF_OMP_FOR_KIND_CILKSIMD
590 || (gimple_omp_for_kind (for_stmt)
591 == GF_OMP_FOR_KIND_CILKFOR));
592 break;
593 case LE_EXPR:
594 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
595 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
596 else
597 loop->n2 = fold_build2_loc (loc,
598 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
599 build_int_cst (TREE_TYPE (loop->n2), 1));
600 loop->cond_code = LT_EXPR;
601 break;
602 case GE_EXPR:
603 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
604 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
605 else
606 loop->n2 = fold_build2_loc (loc,
607 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
608 build_int_cst (TREE_TYPE (loop->n2), 1));
609 loop->cond_code = GT_EXPR;
610 break;
611 default:
612 gcc_unreachable ();
615 t = gimple_omp_for_incr (for_stmt, i);
616 gcc_assert (TREE_OPERAND (t, 0) == var);
617 switch (TREE_CODE (t))
619 case PLUS_EXPR:
620 loop->step = TREE_OPERAND (t, 1);
621 break;
622 case POINTER_PLUS_EXPR:
623 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
624 break;
625 case MINUS_EXPR:
626 loop->step = TREE_OPERAND (t, 1);
627 loop->step = fold_build1_loc (loc,
628 NEGATE_EXPR, TREE_TYPE (loop->step),
629 loop->step);
630 break;
631 default:
632 gcc_unreachable ();
635 if (simd
636 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
637 && !fd->have_ordered))
639 if (fd->collapse == 1)
640 iter_type = TREE_TYPE (loop->v);
641 else if (i == 0
642 || TYPE_PRECISION (iter_type)
643 < TYPE_PRECISION (TREE_TYPE (loop->v)))
644 iter_type
645 = build_nonstandard_integer_type
646 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
648 else if (iter_type != long_long_unsigned_type_node)
650 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
651 iter_type = long_long_unsigned_type_node;
652 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
653 && TYPE_PRECISION (TREE_TYPE (loop->v))
654 >= TYPE_PRECISION (iter_type))
656 tree n;
658 if (loop->cond_code == LT_EXPR)
659 n = fold_build2_loc (loc,
660 PLUS_EXPR, TREE_TYPE (loop->v),
661 loop->n2, loop->step);
662 else
663 n = loop->n1;
664 if (TREE_CODE (n) != INTEGER_CST
665 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
666 iter_type = long_long_unsigned_type_node;
668 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
669 > TYPE_PRECISION (iter_type))
671 tree n1, n2;
673 if (loop->cond_code == LT_EXPR)
675 n1 = loop->n1;
676 n2 = fold_build2_loc (loc,
677 PLUS_EXPR, TREE_TYPE (loop->v),
678 loop->n2, loop->step);
680 else
682 n1 = fold_build2_loc (loc,
683 MINUS_EXPR, TREE_TYPE (loop->v),
684 loop->n2, loop->step);
685 n2 = loop->n1;
687 if (TREE_CODE (n1) != INTEGER_CST
688 || TREE_CODE (n2) != INTEGER_CST
689 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
690 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
691 iter_type = long_long_unsigned_type_node;
695 if (i >= fd->collapse)
696 continue;
698 if (collapse_count && *collapse_count == NULL)
700 t = fold_binary (loop->cond_code, boolean_type_node,
701 fold_convert (TREE_TYPE (loop->v), loop->n1),
702 fold_convert (TREE_TYPE (loop->v), loop->n2));
703 if (t && integer_zerop (t))
704 count = build_zero_cst (long_long_unsigned_type_node);
705 else if ((i == 0 || count != NULL_TREE)
706 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
707 && TREE_CONSTANT (loop->n1)
708 && TREE_CONSTANT (loop->n2)
709 && TREE_CODE (loop->step) == INTEGER_CST)
711 tree itype = TREE_TYPE (loop->v);
713 if (POINTER_TYPE_P (itype))
714 itype = signed_type_for (itype);
715 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
716 t = fold_build2_loc (loc,
717 PLUS_EXPR, itype,
718 fold_convert_loc (loc, itype, loop->step), t);
719 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
720 fold_convert_loc (loc, itype, loop->n2));
721 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
722 fold_convert_loc (loc, itype, loop->n1));
723 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
724 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
725 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
726 fold_build1_loc (loc, NEGATE_EXPR, itype,
727 fold_convert_loc (loc, itype,
728 loop->step)));
729 else
730 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
731 fold_convert_loc (loc, itype, loop->step));
732 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
733 if (count != NULL_TREE)
734 count = fold_build2_loc (loc,
735 MULT_EXPR, long_long_unsigned_type_node,
736 count, t);
737 else
738 count = t;
739 if (TREE_CODE (count) != INTEGER_CST)
740 count = NULL_TREE;
742 else if (count && !integer_zerop (count))
743 count = NULL_TREE;
747 if (count
748 && !simd
749 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
750 || fd->have_ordered))
752 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
753 iter_type = long_long_unsigned_type_node;
754 else
755 iter_type = long_integer_type_node;
757 else if (collapse_iter && *collapse_iter != NULL)
758 iter_type = TREE_TYPE (*collapse_iter);
759 fd->iter_type = iter_type;
760 if (collapse_iter && *collapse_iter == NULL)
761 *collapse_iter = create_tmp_var (iter_type, ".iter");
762 if (collapse_count && *collapse_count == NULL)
764 if (count)
765 *collapse_count = fold_convert_loc (loc, iter_type, count);
766 else
767 *collapse_count = create_tmp_var (iter_type, ".count");
770 if (fd->collapse > 1 || (fd->ordered && loops))
772 fd->loop.v = *collapse_iter;
773 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
774 fd->loop.n2 = *collapse_count;
775 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
776 fd->loop.cond_code = LT_EXPR;
778 else if (loops)
779 loops[0] = fd->loop;
783 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
784 is the immediate dominator of PAR_ENTRY_BB, return true if there
785 are no data dependencies that would prevent expanding the parallel
786 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
788 When expanding a combined parallel+workshare region, the call to
789 the child function may need additional arguments in the case of
790 GIMPLE_OMP_FOR regions. In some cases, these arguments are
791 computed out of variables passed in from the parent to the child
792 via 'struct .omp_data_s'. For instance:
794 #pragma omp parallel for schedule (guided, i * 4)
795 for (j ...)
797 Is lowered into:
799 # BLOCK 2 (PAR_ENTRY_BB)
800 .omp_data_o.i = i;
801 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
803 # BLOCK 3 (WS_ENTRY_BB)
804 .omp_data_i = &.omp_data_o;
805 D.1667 = .omp_data_i->i;
806 D.1598 = D.1667 * 4;
807 #pragma omp for schedule (guided, D.1598)
809 When we outline the parallel region, the call to the child function
810 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
811 that value is computed *after* the call site. So, in principle we
812 cannot do the transformation.
814 To see whether the code in WS_ENTRY_BB blocks the combined
815 parallel+workshare call, we collect all the variables used in the
816 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
817 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
818 call.
820 FIXME. If we had the SSA form built at this point, we could merely
821 hoist the code in block 3 into block 2 and be done with it. But at
822 this point we don't have dataflow information and though we could
823 hack something up here, it is really not worth the aggravation. */
825 static bool
826 workshare_safe_to_combine_p (basic_block ws_entry_bb)
828 struct omp_for_data fd;
829 gimple *ws_stmt = last_stmt (ws_entry_bb);
831 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
832 return true;
834 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
836 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
838 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
839 return false;
840 if (fd.iter_type != long_integer_type_node)
841 return false;
843 /* FIXME. We give up too easily here. If any of these arguments
844 are not constants, they will likely involve variables that have
845 been mapped into fields of .omp_data_s for sharing with the child
846 function. With appropriate data flow, it would be possible to
847 see through this. */
848 if (!is_gimple_min_invariant (fd.loop.n1)
849 || !is_gimple_min_invariant (fd.loop.n2)
850 || !is_gimple_min_invariant (fd.loop.step)
851 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
852 return false;
854 return true;
858 static int omp_max_vf (void);
860 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
861 presence (SIMD_SCHEDULE). */
863 static tree
864 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
866 if (!simd_schedule)
867 return chunk_size;
869 int vf = omp_max_vf ();
870 if (vf == 1)
871 return chunk_size;
873 tree type = TREE_TYPE (chunk_size);
874 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
875 build_int_cst (type, vf - 1));
876 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
877 build_int_cst (type, -vf));
881 /* Collect additional arguments needed to emit a combined
882 parallel+workshare call. WS_STMT is the workshare directive being
883 expanded. */
885 static vec<tree, va_gc> *
886 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
888 tree t;
889 location_t loc = gimple_location (ws_stmt);
890 vec<tree, va_gc> *ws_args;
892 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
894 struct omp_for_data fd;
895 tree n1, n2;
897 extract_omp_for_data (for_stmt, &fd, NULL);
898 n1 = fd.loop.n1;
899 n2 = fd.loop.n2;
901 if (gimple_omp_for_combined_into_p (for_stmt))
903 tree innerc
904 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
905 OMP_CLAUSE__LOOPTEMP_);
906 gcc_assert (innerc);
907 n1 = OMP_CLAUSE_DECL (innerc);
908 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
909 OMP_CLAUSE__LOOPTEMP_);
910 gcc_assert (innerc);
911 n2 = OMP_CLAUSE_DECL (innerc);
914 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
916 t = fold_convert_loc (loc, long_integer_type_node, n1);
917 ws_args->quick_push (t);
919 t = fold_convert_loc (loc, long_integer_type_node, n2);
920 ws_args->quick_push (t);
922 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
923 ws_args->quick_push (t);
925 if (fd.chunk_size)
927 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
928 t = omp_adjust_chunk_size (t, fd.simd_schedule);
929 ws_args->quick_push (t);
932 return ws_args;
934 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
936 /* Number of sections is equal to the number of edges from the
937 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
938 the exit of the sections region. */
939 basic_block bb = single_succ (gimple_bb (ws_stmt));
940 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
941 vec_alloc (ws_args, 1);
942 ws_args->quick_push (t);
943 return ws_args;
946 gcc_unreachable ();
950 /* Discover whether REGION is a combined parallel+workshare region. */
952 static void
953 determine_parallel_type (struct omp_region *region)
955 basic_block par_entry_bb, par_exit_bb;
956 basic_block ws_entry_bb, ws_exit_bb;
958 if (region == NULL || region->inner == NULL
959 || region->exit == NULL || region->inner->exit == NULL
960 || region->inner->cont == NULL)
961 return;
963 /* We only support parallel+for and parallel+sections. */
964 if (region->type != GIMPLE_OMP_PARALLEL
965 || (region->inner->type != GIMPLE_OMP_FOR
966 && region->inner->type != GIMPLE_OMP_SECTIONS))
967 return;
969 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
970 WS_EXIT_BB -> PAR_EXIT_BB. */
971 par_entry_bb = region->entry;
972 par_exit_bb = region->exit;
973 ws_entry_bb = region->inner->entry;
974 ws_exit_bb = region->inner->exit;
976 if (single_succ (par_entry_bb) == ws_entry_bb
977 && single_succ (ws_exit_bb) == par_exit_bb
978 && workshare_safe_to_combine_p (ws_entry_bb)
979 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
980 || (last_and_only_stmt (ws_entry_bb)
981 && last_and_only_stmt (par_exit_bb))))
983 gimple *par_stmt = last_stmt (par_entry_bb);
984 gimple *ws_stmt = last_stmt (ws_entry_bb);
986 if (region->inner->type == GIMPLE_OMP_FOR)
988 /* If this is a combined parallel loop, we need to determine
989 whether or not to use the combined library calls. There
990 are two cases where we do not apply the transformation:
991 static loops and any kind of ordered loop. In the first
992 case, we already open code the loop so there is no need
993 to do anything else. In the latter case, the combined
994 parallel loop call would still need extra synchronization
995 to implement ordered semantics, so there would not be any
996 gain in using the combined call. */
997 tree clauses = gimple_omp_for_clauses (ws_stmt);
998 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
999 if (c == NULL
1000 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1001 == OMP_CLAUSE_SCHEDULE_STATIC)
1002 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1004 region->is_combined_parallel = false;
1005 region->inner->is_combined_parallel = false;
1006 return;
1010 region->is_combined_parallel = true;
1011 region->inner->is_combined_parallel = true;
1012 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1017 /* Return true if EXPR is variable sized. */
1019 static inline bool
1020 is_variable_sized (const_tree expr)
1022 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1025 /* Return true if DECL is a reference type. */
1027 static inline bool
1028 is_reference (tree decl)
1030 return lang_hooks.decls.omp_privatize_by_reference (decl);
1033 /* Return the type of a decl. If the decl is reference type,
1034 return its base type. */
1035 static inline tree
1036 get_base_type (tree decl)
1038 tree type = TREE_TYPE (decl);
1039 if (is_reference (decl))
1040 type = TREE_TYPE (type);
1041 return type;
1044 /* Lookup variables. The "maybe" form
1045 allows for the variable form to not have been entered, otherwise we
1046 assert that the variable must have been entered. */
1048 static inline tree
1049 lookup_decl (tree var, omp_context *ctx)
1051 tree *n = ctx->cb.decl_map->get (var);
1052 return *n;
1055 static inline tree
1056 maybe_lookup_decl (const_tree var, omp_context *ctx)
1058 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1059 return n ? *n : NULL_TREE;
1062 static inline tree
1063 lookup_field (tree var, omp_context *ctx)
1065 splay_tree_node n;
1066 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1067 return (tree) n->value;
1070 static inline tree
1071 lookup_sfield (splay_tree_key key, omp_context *ctx)
1073 splay_tree_node n;
1074 n = splay_tree_lookup (ctx->sfield_map
1075 ? ctx->sfield_map : ctx->field_map, key);
1076 return (tree) n->value;
1079 static inline tree
1080 lookup_sfield (tree var, omp_context *ctx)
1082 return lookup_sfield ((splay_tree_key) var, ctx);
1085 static inline tree
1086 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1088 splay_tree_node n;
1089 n = splay_tree_lookup (ctx->field_map, key);
1090 return n ? (tree) n->value : NULL_TREE;
1093 static inline tree
1094 maybe_lookup_field (tree var, omp_context *ctx)
1096 return maybe_lookup_field ((splay_tree_key) var, ctx);
1099 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1100 the parallel context if DECL is to be shared. */
1102 static bool
1103 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1105 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1106 return true;
1108 /* We can only use copy-in/copy-out semantics for shared variables
1109 when we know the value is not accessible from an outer scope. */
1110 if (shared_ctx)
1112 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1114 /* ??? Trivially accessible from anywhere. But why would we even
1115 be passing an address in this case? Should we simply assert
1116 this to be false, or should we have a cleanup pass that removes
1117 these from the list of mappings? */
1118 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1119 return true;
1121 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1122 without analyzing the expression whether or not its location
1123 is accessible to anyone else. In the case of nested parallel
1124 regions it certainly may be. */
1125 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1126 return true;
1128 /* Do not use copy-in/copy-out for variables that have their
1129 address taken. */
1130 if (TREE_ADDRESSABLE (decl))
1131 return true;
1133 /* lower_send_shared_vars only uses copy-in, but not copy-out
1134 for these. */
1135 if (TREE_READONLY (decl)
1136 || ((TREE_CODE (decl) == RESULT_DECL
1137 || TREE_CODE (decl) == PARM_DECL)
1138 && DECL_BY_REFERENCE (decl)))
1139 return false;
1141 /* Disallow copy-in/out in nested parallel if
1142 decl is shared in outer parallel, otherwise
1143 each thread could store the shared variable
1144 in its own copy-in location, making the
1145 variable no longer really shared. */
1146 if (shared_ctx->is_nested)
1148 omp_context *up;
1150 for (up = shared_ctx->outer; up; up = up->outer)
1151 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1152 break;
1154 if (up)
1156 tree c;
1158 for (c = gimple_omp_taskreg_clauses (up->stmt);
1159 c; c = OMP_CLAUSE_CHAIN (c))
1160 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1161 && OMP_CLAUSE_DECL (c) == decl)
1162 break;
1164 if (c)
1165 goto maybe_mark_addressable_and_ret;
1169 /* For tasks avoid using copy-in/out. As tasks can be
1170 deferred or executed in different thread, when GOMP_task
1171 returns, the task hasn't necessarily terminated. */
1172 if (is_task_ctx (shared_ctx))
1174 tree outer;
1175 maybe_mark_addressable_and_ret:
1176 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1177 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1179 /* Taking address of OUTER in lower_send_shared_vars
1180 might need regimplification of everything that uses the
1181 variable. */
1182 if (!task_shared_vars)
1183 task_shared_vars = BITMAP_ALLOC (NULL);
1184 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1185 TREE_ADDRESSABLE (outer) = 1;
1187 return true;
1191 return false;
1194 /* Construct a new automatic decl similar to VAR. */
1196 static tree
1197 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1199 tree copy = copy_var_decl (var, name, type);
1201 DECL_CONTEXT (copy) = current_function_decl;
1202 DECL_CHAIN (copy) = ctx->block_vars;
1203 /* If VAR is listed in task_shared_vars, it means it wasn't
1204 originally addressable and is just because task needs to take
1205 it's address. But we don't need to take address of privatizations
1206 from that var. */
1207 if (TREE_ADDRESSABLE (var)
1208 && task_shared_vars
1209 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1210 TREE_ADDRESSABLE (copy) = 0;
1211 ctx->block_vars = copy;
1213 return copy;
1216 static tree
1217 omp_copy_decl_1 (tree var, omp_context *ctx)
1219 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1222 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1223 as appropriate. */
1224 static tree
1225 omp_build_component_ref (tree obj, tree field)
1227 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1228 if (TREE_THIS_VOLATILE (field))
1229 TREE_THIS_VOLATILE (ret) |= 1;
1230 if (TREE_READONLY (field))
1231 TREE_READONLY (ret) |= 1;
1232 return ret;
1235 /* Build tree nodes to access the field for VAR on the receiver side. */
1237 static tree
1238 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1240 tree x, field = lookup_field (var, ctx);
1242 /* If the receiver record type was remapped in the child function,
1243 remap the field into the new record type. */
1244 x = maybe_lookup_field (field, ctx);
1245 if (x != NULL)
1246 field = x;
1248 x = build_simple_mem_ref (ctx->receiver_decl);
1249 TREE_THIS_NOTRAP (x) = 1;
1250 x = omp_build_component_ref (x, field);
1251 if (by_ref)
1253 x = build_simple_mem_ref (x);
1254 TREE_THIS_NOTRAP (x) = 1;
1257 return x;
1260 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1261 of a parallel, this is a component reference; for workshare constructs
1262 this is some variable. */
1264 static tree
1265 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1267 tree x;
1269 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1270 x = var;
1271 else if (is_variable_sized (var))
1273 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1274 x = build_outer_var_ref (x, ctx, lastprivate);
1275 x = build_simple_mem_ref (x);
1277 else if (is_taskreg_ctx (ctx))
1279 bool by_ref = use_pointer_for_field (var, NULL);
1280 x = build_receiver_ref (var, by_ref, ctx);
1282 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1283 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1285 /* #pragma omp simd isn't a worksharing construct, and can reference even
1286 private vars in its linear etc. clauses. */
1287 x = NULL_TREE;
1288 if (ctx->outer && is_taskreg_ctx (ctx))
1289 x = lookup_decl (var, ctx->outer);
1290 else if (ctx->outer)
1291 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1292 if (x == NULL_TREE)
1293 x = var;
1295 else if (lastprivate && is_taskloop_ctx (ctx))
1297 gcc_assert (ctx->outer);
1298 splay_tree_node n
1299 = splay_tree_lookup (ctx->outer->field_map,
1300 (splay_tree_key) &DECL_UID (var));
1301 if (n == NULL)
1303 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1304 x = var;
1305 else
1306 x = lookup_decl (var, ctx->outer);
1308 else
1310 tree field = (tree) n->value;
1311 /* If the receiver record type was remapped in the child function,
1312 remap the field into the new record type. */
1313 x = maybe_lookup_field (field, ctx->outer);
1314 if (x != NULL)
1315 field = x;
1317 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1318 x = omp_build_component_ref (x, field);
1319 if (use_pointer_for_field (var, ctx->outer))
1320 x = build_simple_mem_ref (x);
1323 else if (ctx->outer)
1324 x = lookup_decl (var, ctx->outer);
1325 else if (is_reference (var))
1326 /* This can happen with orphaned constructs. If var is reference, it is
1327 possible it is shared and as such valid. */
1328 x = var;
1329 else if (omp_member_access_dummy_var (var))
1330 x = var;
1331 else
1332 gcc_unreachable ();
1334 if (x == var)
1336 tree t = omp_member_access_dummy_var (var);
1337 if (t)
1339 x = DECL_VALUE_EXPR (var);
1340 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1341 if (o != t)
1342 x = unshare_and_remap (x, t, o);
1343 else
1344 x = unshare_expr (x);
1348 if (is_reference (var))
1349 x = build_simple_mem_ref (x);
1351 return x;
1354 /* Build tree nodes to access the field for VAR on the sender side. */
1356 static tree
1357 build_sender_ref (splay_tree_key key, omp_context *ctx)
1359 tree field = lookup_sfield (key, ctx);
1360 return omp_build_component_ref (ctx->sender_decl, field);
1363 static tree
1364 build_sender_ref (tree var, omp_context *ctx)
1366 return build_sender_ref ((splay_tree_key) var, ctx);
1369 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1370 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1372 static void
1373 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1374 bool base_pointers_restrict = false)
1376 tree field, type, sfield = NULL_TREE;
1377 splay_tree_key key = (splay_tree_key) var;
1379 if ((mask & 8) != 0)
1381 key = (splay_tree_key) &DECL_UID (var);
1382 gcc_checking_assert (key != (splay_tree_key) var);
1384 gcc_assert ((mask & 1) == 0
1385 || !splay_tree_lookup (ctx->field_map, key));
1386 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1387 || !splay_tree_lookup (ctx->sfield_map, key));
1388 gcc_assert ((mask & 3) == 3
1389 || !is_gimple_omp_oacc (ctx->stmt));
1391 type = TREE_TYPE (var);
1392 /* Prevent redeclaring the var in the split-off function with a restrict
1393 pointer type. Note that we only clear type itself, restrict qualifiers in
1394 the pointed-to type will be ignored by points-to analysis. */
1395 if (POINTER_TYPE_P (type)
1396 && TYPE_RESTRICT (type))
1397 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1399 if (mask & 4)
1401 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1402 type = build_pointer_type (build_pointer_type (type));
1404 else if (by_ref)
1406 type = build_pointer_type (type);
1407 if (base_pointers_restrict)
1408 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1410 else if ((mask & 3) == 1 && is_reference (var))
1411 type = TREE_TYPE (type);
1413 field = build_decl (DECL_SOURCE_LOCATION (var),
1414 FIELD_DECL, DECL_NAME (var), type);
1416 /* Remember what variable this field was created for. This does have a
1417 side effect of making dwarf2out ignore this member, so for helpful
1418 debugging we clear it later in delete_omp_context. */
1419 DECL_ABSTRACT_ORIGIN (field) = var;
1420 if (type == TREE_TYPE (var))
1422 DECL_ALIGN (field) = DECL_ALIGN (var);
1423 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1424 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1426 else
1427 DECL_ALIGN (field) = TYPE_ALIGN (type);
1429 if ((mask & 3) == 3)
1431 insert_field_into_struct (ctx->record_type, field);
1432 if (ctx->srecord_type)
1434 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1435 FIELD_DECL, DECL_NAME (var), type);
1436 DECL_ABSTRACT_ORIGIN (sfield) = var;
1437 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1438 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1439 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1440 insert_field_into_struct (ctx->srecord_type, sfield);
1443 else
1445 if (ctx->srecord_type == NULL_TREE)
1447 tree t;
1449 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1450 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1451 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1453 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1454 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1455 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1456 insert_field_into_struct (ctx->srecord_type, sfield);
1457 splay_tree_insert (ctx->sfield_map,
1458 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1459 (splay_tree_value) sfield);
1462 sfield = field;
1463 insert_field_into_struct ((mask & 1) ? ctx->record_type
1464 : ctx->srecord_type, field);
1467 if (mask & 1)
1468 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1469 if ((mask & 2) && ctx->sfield_map)
1470 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1473 static tree
1474 install_var_local (tree var, omp_context *ctx)
1476 tree new_var = omp_copy_decl_1 (var, ctx);
1477 insert_decl_map (&ctx->cb, var, new_var);
1478 return new_var;
1481 /* Adjust the replacement for DECL in CTX for the new context. This means
1482 copying the DECL_VALUE_EXPR, and fixing up the type. */
1484 static void
1485 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1487 tree new_decl, size;
1489 new_decl = lookup_decl (decl, ctx);
1491 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1493 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1494 && DECL_HAS_VALUE_EXPR_P (decl))
1496 tree ve = DECL_VALUE_EXPR (decl);
1497 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1498 SET_DECL_VALUE_EXPR (new_decl, ve);
1499 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1502 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1504 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1505 if (size == error_mark_node)
1506 size = TYPE_SIZE (TREE_TYPE (new_decl));
1507 DECL_SIZE (new_decl) = size;
1509 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1510 if (size == error_mark_node)
1511 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1512 DECL_SIZE_UNIT (new_decl) = size;
1516 /* The callback for remap_decl. Search all containing contexts for a
1517 mapping of the variable; this avoids having to duplicate the splay
1518 tree ahead of time. We know a mapping doesn't already exist in the
1519 given context. Create new mappings to implement default semantics. */
1521 static tree
1522 omp_copy_decl (tree var, copy_body_data *cb)
1524 omp_context *ctx = (omp_context *) cb;
1525 tree new_var;
1527 if (TREE_CODE (var) == LABEL_DECL)
1529 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1530 DECL_CONTEXT (new_var) = current_function_decl;
1531 insert_decl_map (&ctx->cb, var, new_var);
1532 return new_var;
1535 while (!is_taskreg_ctx (ctx))
1537 ctx = ctx->outer;
1538 if (ctx == NULL)
1539 return var;
1540 new_var = maybe_lookup_decl (var, ctx);
1541 if (new_var)
1542 return new_var;
1545 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1546 return var;
1548 return error_mark_node;
1552 /* Debugging dumps for parallel regions. */
1553 void dump_omp_region (FILE *, struct omp_region *, int);
1554 void debug_omp_region (struct omp_region *);
1555 void debug_all_omp_regions (void);
1557 /* Dump the parallel region tree rooted at REGION. */
1559 void
1560 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1562 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1563 gimple_code_name[region->type]);
1565 if (region->inner)
1566 dump_omp_region (file, region->inner, indent + 4);
1568 if (region->cont)
1570 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1571 region->cont->index);
1574 if (region->exit)
1575 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1576 region->exit->index);
1577 else
1578 fprintf (file, "%*s[no exit marker]\n", indent, "");
1580 if (region->next)
1581 dump_omp_region (file, region->next, indent);
1584 DEBUG_FUNCTION void
1585 debug_omp_region (struct omp_region *region)
1587 dump_omp_region (stderr, region, 0);
1590 DEBUG_FUNCTION void
1591 debug_all_omp_regions (void)
1593 dump_omp_region (stderr, root_omp_region, 0);
1597 /* Create a new parallel region starting at STMT inside region PARENT. */
1599 static struct omp_region *
1600 new_omp_region (basic_block bb, enum gimple_code type,
1601 struct omp_region *parent)
1603 struct omp_region *region = XCNEW (struct omp_region);
1605 region->outer = parent;
1606 region->entry = bb;
1607 region->type = type;
1609 if (parent)
1611 /* This is a nested region. Add it to the list of inner
1612 regions in PARENT. */
1613 region->next = parent->inner;
1614 parent->inner = region;
1616 else
1618 /* This is a toplevel region. Add it to the list of toplevel
1619 regions in ROOT_OMP_REGION. */
1620 region->next = root_omp_region;
1621 root_omp_region = region;
1624 return region;
1627 /* Release the memory associated with the region tree rooted at REGION. */
1629 static void
1630 free_omp_region_1 (struct omp_region *region)
1632 struct omp_region *i, *n;
1634 for (i = region->inner; i ; i = n)
1636 n = i->next;
1637 free_omp_region_1 (i);
1640 free (region);
1643 /* Release the memory for the entire omp region tree. */
1645 void
1646 free_omp_regions (void)
1648 struct omp_region *r, *n;
1649 for (r = root_omp_region; r ; r = n)
1651 n = r->next;
1652 free_omp_region_1 (r);
1654 root_omp_region = NULL;
1658 /* Create a new context, with OUTER_CTX being the surrounding context. */
1660 static omp_context *
1661 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1663 omp_context *ctx = XCNEW (omp_context);
1665 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1666 (splay_tree_value) ctx);
1667 ctx->stmt = stmt;
1669 if (outer_ctx)
1671 ctx->outer = outer_ctx;
1672 ctx->cb = outer_ctx->cb;
1673 ctx->cb.block = NULL;
1674 ctx->depth = outer_ctx->depth + 1;
1676 else
1678 ctx->cb.src_fn = current_function_decl;
1679 ctx->cb.dst_fn = current_function_decl;
1680 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1681 gcc_checking_assert (ctx->cb.src_node);
1682 ctx->cb.dst_node = ctx->cb.src_node;
1683 ctx->cb.src_cfun = cfun;
1684 ctx->cb.copy_decl = omp_copy_decl;
1685 ctx->cb.eh_lp_nr = 0;
1686 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1687 ctx->depth = 1;
1690 ctx->cb.decl_map = new hash_map<tree, tree>;
1692 return ctx;
1695 static gimple_seq maybe_catch_exception (gimple_seq);
1697 /* Finalize task copyfn. */
1699 static void
1700 finalize_task_copyfn (gomp_task *task_stmt)
1702 struct function *child_cfun;
1703 tree child_fn;
1704 gimple_seq seq = NULL, new_seq;
1705 gbind *bind;
1707 child_fn = gimple_omp_task_copy_fn (task_stmt);
1708 if (child_fn == NULL_TREE)
1709 return;
1711 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1712 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1714 push_cfun (child_cfun);
1715 bind = gimplify_body (child_fn, false);
1716 gimple_seq_add_stmt (&seq, bind);
1717 new_seq = maybe_catch_exception (seq);
1718 if (new_seq != seq)
1720 bind = gimple_build_bind (NULL, new_seq, NULL);
1721 seq = NULL;
1722 gimple_seq_add_stmt (&seq, bind);
1724 gimple_set_body (child_fn, seq);
1725 pop_cfun ();
1727 /* Inform the callgraph about the new function. */
1728 cgraph_node *node = cgraph_node::get_create (child_fn);
1729 node->parallelized_function = 1;
1730 cgraph_node::add_new_function (child_fn, false);
1733 /* Destroy a omp_context data structures. Called through the splay tree
1734 value delete callback. */
1736 static void
1737 delete_omp_context (splay_tree_value value)
1739 omp_context *ctx = (omp_context *) value;
1741 delete ctx->cb.decl_map;
1743 if (ctx->field_map)
1744 splay_tree_delete (ctx->field_map);
1745 if (ctx->sfield_map)
1746 splay_tree_delete (ctx->sfield_map);
1748 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1749 it produces corrupt debug information. */
1750 if (ctx->record_type)
1752 tree t;
1753 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1754 DECL_ABSTRACT_ORIGIN (t) = NULL;
1756 if (ctx->srecord_type)
1758 tree t;
1759 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1760 DECL_ABSTRACT_ORIGIN (t) = NULL;
1763 if (is_task_ctx (ctx))
1764 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1766 XDELETE (ctx);
1769 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1770 context. */
1772 static void
1773 fixup_child_record_type (omp_context *ctx)
1775 tree f, type = ctx->record_type;
1777 /* ??? It isn't sufficient to just call remap_type here, because
1778 variably_modified_type_p doesn't work the way we expect for
1779 record types. Testing each field for whether it needs remapping
1780 and creating a new record by hand works, however. */
1781 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1782 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1783 break;
1784 if (f)
1786 tree name, new_fields = NULL;
1788 type = lang_hooks.types.make_type (RECORD_TYPE);
1789 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1790 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1791 TYPE_DECL, name, type);
1792 TYPE_NAME (type) = name;
1794 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1796 tree new_f = copy_node (f);
1797 DECL_CONTEXT (new_f) = type;
1798 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1799 DECL_CHAIN (new_f) = new_fields;
1800 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1801 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1802 &ctx->cb, NULL);
1803 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1804 &ctx->cb, NULL);
1805 new_fields = new_f;
1807 /* Arrange to be able to look up the receiver field
1808 given the sender field. */
1809 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1810 (splay_tree_value) new_f);
1812 TYPE_FIELDS (type) = nreverse (new_fields);
1813 layout_type (type);
1816 /* In a target region we never modify any of the pointers in *.omp_data_i,
1817 so attempt to help the optimizers. */
1818 if (is_gimple_omp_offloaded (ctx->stmt))
1819 type = build_qualified_type (type, TYPE_QUAL_CONST);
1821 TREE_TYPE (ctx->receiver_decl)
1822 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1825 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1826 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1827 restrict. */
1829 static void
1830 scan_sharing_clauses (tree clauses, omp_context *ctx,
1831 bool base_pointers_restrict = false)
1833 tree c, decl;
1834 bool scan_array_reductions = false;
1836 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1838 bool by_ref;
1840 switch (OMP_CLAUSE_CODE (c))
1842 case OMP_CLAUSE_PRIVATE:
1843 decl = OMP_CLAUSE_DECL (c);
1844 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1845 goto do_private;
1846 else if (!is_variable_sized (decl))
1847 install_var_local (decl, ctx);
1848 break;
1850 case OMP_CLAUSE_SHARED:
1851 decl = OMP_CLAUSE_DECL (c);
1852 /* Ignore shared directives in teams construct. */
1853 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1855 /* Global variables don't need to be copied,
1856 the receiver side will use them directly. */
1857 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1858 if (is_global_var (odecl))
1859 break;
1860 insert_decl_map (&ctx->cb, decl, odecl);
1861 break;
1863 gcc_assert (is_taskreg_ctx (ctx));
1864 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1865 || !is_variable_sized (decl));
1866 /* Global variables don't need to be copied,
1867 the receiver side will use them directly. */
1868 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1869 break;
1870 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1872 use_pointer_for_field (decl, ctx);
1873 break;
1875 by_ref = use_pointer_for_field (decl, NULL);
1876 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1877 || TREE_ADDRESSABLE (decl)
1878 || by_ref
1879 || is_reference (decl))
1881 by_ref = use_pointer_for_field (decl, ctx);
1882 install_var_field (decl, by_ref, 3, ctx);
1883 install_var_local (decl, ctx);
1884 break;
1886 /* We don't need to copy const scalar vars back. */
1887 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1888 goto do_private;
1890 case OMP_CLAUSE_REDUCTION:
1891 decl = OMP_CLAUSE_DECL (c);
1892 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1893 && TREE_CODE (decl) == MEM_REF)
1895 tree t = TREE_OPERAND (decl, 0);
1896 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1897 t = TREE_OPERAND (t, 0);
1898 if (TREE_CODE (t) == INDIRECT_REF
1899 || TREE_CODE (t) == ADDR_EXPR)
1900 t = TREE_OPERAND (t, 0);
1901 install_var_local (t, ctx);
1902 if (is_taskreg_ctx (ctx)
1903 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1904 && !is_variable_sized (t))
1906 by_ref = use_pointer_for_field (t, ctx);
1907 install_var_field (t, by_ref, 3, ctx);
1909 break;
1911 goto do_private;
1913 case OMP_CLAUSE_LASTPRIVATE:
1914 /* Let the corresponding firstprivate clause create
1915 the variable. */
1916 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1917 break;
1918 /* FALLTHRU */
1920 case OMP_CLAUSE_FIRSTPRIVATE:
1921 case OMP_CLAUSE_LINEAR:
1922 decl = OMP_CLAUSE_DECL (c);
1923 do_private:
1924 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1925 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1926 && is_gimple_omp_offloaded (ctx->stmt))
1928 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1929 install_var_field (decl, !is_reference (decl), 3, ctx);
1930 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1931 install_var_field (decl, true, 3, ctx);
1932 else
1933 install_var_field (decl, false, 3, ctx);
1935 if (is_variable_sized (decl))
1937 if (is_task_ctx (ctx))
1938 install_var_field (decl, false, 1, ctx);
1939 break;
1941 else if (is_taskreg_ctx (ctx))
1943 bool global
1944 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1945 by_ref = use_pointer_for_field (decl, NULL);
1947 if (is_task_ctx (ctx)
1948 && (global || by_ref || is_reference (decl)))
1950 install_var_field (decl, false, 1, ctx);
1951 if (!global)
1952 install_var_field (decl, by_ref, 2, ctx);
1954 else if (!global)
1955 install_var_field (decl, by_ref, 3, ctx);
1957 install_var_local (decl, ctx);
1958 break;
1960 case OMP_CLAUSE_USE_DEVICE_PTR:
1961 decl = OMP_CLAUSE_DECL (c);
1962 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1963 install_var_field (decl, true, 3, ctx);
1964 else
1965 install_var_field (decl, false, 3, ctx);
1966 if (DECL_SIZE (decl)
1967 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1969 tree decl2 = DECL_VALUE_EXPR (decl);
1970 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1971 decl2 = TREE_OPERAND (decl2, 0);
1972 gcc_assert (DECL_P (decl2));
1973 install_var_local (decl2, ctx);
1975 install_var_local (decl, ctx);
1976 break;
1978 case OMP_CLAUSE_IS_DEVICE_PTR:
1979 decl = OMP_CLAUSE_DECL (c);
1980 goto do_private;
1982 case OMP_CLAUSE__LOOPTEMP_:
1983 gcc_assert (is_taskreg_ctx (ctx));
1984 decl = OMP_CLAUSE_DECL (c);
1985 install_var_field (decl, false, 3, ctx);
1986 install_var_local (decl, ctx);
1987 break;
1989 case OMP_CLAUSE_COPYPRIVATE:
1990 case OMP_CLAUSE_COPYIN:
1991 decl = OMP_CLAUSE_DECL (c);
1992 by_ref = use_pointer_for_field (decl, NULL);
1993 install_var_field (decl, by_ref, 3, ctx);
1994 break;
1996 case OMP_CLAUSE_DEFAULT:
1997 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1998 break;
2000 case OMP_CLAUSE_FINAL:
2001 case OMP_CLAUSE_IF:
2002 case OMP_CLAUSE_NUM_THREADS:
2003 case OMP_CLAUSE_NUM_TEAMS:
2004 case OMP_CLAUSE_THREAD_LIMIT:
2005 case OMP_CLAUSE_DEVICE:
2006 case OMP_CLAUSE_SCHEDULE:
2007 case OMP_CLAUSE_DIST_SCHEDULE:
2008 case OMP_CLAUSE_DEPEND:
2009 case OMP_CLAUSE_PRIORITY:
2010 case OMP_CLAUSE_GRAINSIZE:
2011 case OMP_CLAUSE_NUM_TASKS:
2012 case OMP_CLAUSE__CILK_FOR_COUNT_:
2013 case OMP_CLAUSE_NUM_GANGS:
2014 case OMP_CLAUSE_NUM_WORKERS:
2015 case OMP_CLAUSE_VECTOR_LENGTH:
2016 if (ctx->outer)
2017 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2018 break;
2020 case OMP_CLAUSE_TO:
2021 case OMP_CLAUSE_FROM:
2022 case OMP_CLAUSE_MAP:
2023 if (ctx->outer)
2024 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2025 decl = OMP_CLAUSE_DECL (c);
2026 /* Global variables with "omp declare target" attribute
2027 don't need to be copied, the receiver side will use them
2028 directly. However, global variables with "omp declare target link"
2029 attribute need to be copied. */
2030 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2031 && DECL_P (decl)
2032 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2033 && (OMP_CLAUSE_MAP_KIND (c)
2034 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2035 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2036 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2037 && varpool_node::get_create (decl)->offloadable
2038 && !lookup_attribute ("omp declare target link",
2039 DECL_ATTRIBUTES (decl)))
2040 break;
2041 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2042 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2044 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2045 not offloaded; there is nothing to map for those. */
2046 if (!is_gimple_omp_offloaded (ctx->stmt)
2047 && !POINTER_TYPE_P (TREE_TYPE (decl))
2048 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2049 break;
2051 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2052 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2053 || (OMP_CLAUSE_MAP_KIND (c)
2054 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2056 if (TREE_CODE (decl) == COMPONENT_REF
2057 || (TREE_CODE (decl) == INDIRECT_REF
2058 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2059 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2060 == REFERENCE_TYPE)))
2061 break;
2062 if (DECL_SIZE (decl)
2063 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2065 tree decl2 = DECL_VALUE_EXPR (decl);
2066 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2067 decl2 = TREE_OPERAND (decl2, 0);
2068 gcc_assert (DECL_P (decl2));
2069 install_var_local (decl2, ctx);
2071 install_var_local (decl, ctx);
2072 break;
2074 if (DECL_P (decl))
2076 if (DECL_SIZE (decl)
2077 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2079 tree decl2 = DECL_VALUE_EXPR (decl);
2080 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2081 decl2 = TREE_OPERAND (decl2, 0);
2082 gcc_assert (DECL_P (decl2));
2083 install_var_field (decl2, true, 3, ctx);
2084 install_var_local (decl2, ctx);
2085 install_var_local (decl, ctx);
2087 else
2089 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2090 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2091 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2092 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2093 install_var_field (decl, true, 7, ctx);
2094 else
2095 install_var_field (decl, true, 3, ctx,
2096 base_pointers_restrict);
2097 if (is_gimple_omp_offloaded (ctx->stmt))
2098 install_var_local (decl, ctx);
2101 else
2103 tree base = get_base_address (decl);
2104 tree nc = OMP_CLAUSE_CHAIN (c);
2105 if (DECL_P (base)
2106 && nc != NULL_TREE
2107 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2108 && OMP_CLAUSE_DECL (nc) == base
2109 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2110 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2112 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2113 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2115 else
2117 if (ctx->outer)
2119 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2120 decl = OMP_CLAUSE_DECL (c);
2122 gcc_assert (!splay_tree_lookup (ctx->field_map,
2123 (splay_tree_key) decl));
2124 tree field
2125 = build_decl (OMP_CLAUSE_LOCATION (c),
2126 FIELD_DECL, NULL_TREE, ptr_type_node);
2127 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2128 insert_field_into_struct (ctx->record_type, field);
2129 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2130 (splay_tree_value) field);
2133 break;
2135 case OMP_CLAUSE_NOWAIT:
2136 case OMP_CLAUSE_ORDERED:
2137 case OMP_CLAUSE_COLLAPSE:
2138 case OMP_CLAUSE_UNTIED:
2139 case OMP_CLAUSE_MERGEABLE:
2140 case OMP_CLAUSE_PROC_BIND:
2141 case OMP_CLAUSE_SAFELEN:
2142 case OMP_CLAUSE_SIMDLEN:
2143 case OMP_CLAUSE_THREADS:
2144 case OMP_CLAUSE_SIMD:
2145 case OMP_CLAUSE_NOGROUP:
2146 case OMP_CLAUSE_DEFAULTMAP:
2147 case OMP_CLAUSE_ASYNC:
2148 case OMP_CLAUSE_WAIT:
2149 case OMP_CLAUSE_GANG:
2150 case OMP_CLAUSE_WORKER:
2151 case OMP_CLAUSE_VECTOR:
2152 case OMP_CLAUSE_TILE:
2153 case OMP_CLAUSE_INDEPENDENT:
2154 case OMP_CLAUSE_AUTO:
2155 case OMP_CLAUSE_SEQ:
2156 break;
2158 case OMP_CLAUSE_ALIGNED:
2159 decl = OMP_CLAUSE_DECL (c);
2160 if (is_global_var (decl)
2161 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2162 install_var_local (decl, ctx);
2163 break;
2165 case OMP_CLAUSE_DEVICE_RESIDENT:
2166 case OMP_CLAUSE__CACHE_:
2167 sorry ("Clause not supported yet");
2168 break;
2170 default:
2171 gcc_unreachable ();
2175 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2177 switch (OMP_CLAUSE_CODE (c))
2179 case OMP_CLAUSE_LASTPRIVATE:
2180 /* Let the corresponding firstprivate clause create
2181 the variable. */
2182 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2183 scan_array_reductions = true;
2184 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2185 break;
2186 /* FALLTHRU */
2188 case OMP_CLAUSE_FIRSTPRIVATE:
2189 case OMP_CLAUSE_PRIVATE:
2190 case OMP_CLAUSE_LINEAR:
2191 case OMP_CLAUSE_IS_DEVICE_PTR:
2192 decl = OMP_CLAUSE_DECL (c);
2193 if (is_variable_sized (decl))
2195 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2196 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2197 && is_gimple_omp_offloaded (ctx->stmt))
2199 tree decl2 = DECL_VALUE_EXPR (decl);
2200 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2201 decl2 = TREE_OPERAND (decl2, 0);
2202 gcc_assert (DECL_P (decl2));
2203 install_var_local (decl2, ctx);
2204 fixup_remapped_decl (decl2, ctx, false);
2206 install_var_local (decl, ctx);
2208 fixup_remapped_decl (decl, ctx,
2209 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2210 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2211 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2212 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2213 scan_array_reductions = true;
2214 break;
2216 case OMP_CLAUSE_REDUCTION:
2217 decl = OMP_CLAUSE_DECL (c);
2218 if (TREE_CODE (decl) != MEM_REF)
2220 if (is_variable_sized (decl))
2221 install_var_local (decl, ctx);
2222 fixup_remapped_decl (decl, ctx, false);
2224 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2225 scan_array_reductions = true;
2226 break;
2228 case OMP_CLAUSE_SHARED:
2229 /* Ignore shared directives in teams construct. */
2230 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2231 break;
2232 decl = OMP_CLAUSE_DECL (c);
2233 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2234 break;
2235 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2237 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2238 ctx->outer)))
2239 break;
2240 bool by_ref = use_pointer_for_field (decl, ctx);
2241 install_var_field (decl, by_ref, 11, ctx);
2242 break;
2244 fixup_remapped_decl (decl, ctx, false);
2245 break;
2247 case OMP_CLAUSE_MAP:
2248 if (!is_gimple_omp_offloaded (ctx->stmt))
2249 break;
2250 decl = OMP_CLAUSE_DECL (c);
2251 if (DECL_P (decl)
2252 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2253 && (OMP_CLAUSE_MAP_KIND (c)
2254 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2255 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2256 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2257 && varpool_node::get_create (decl)->offloadable)
2258 break;
2259 if (DECL_P (decl))
2261 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2262 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2263 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2264 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2266 tree new_decl = lookup_decl (decl, ctx);
2267 TREE_TYPE (new_decl)
2268 = remap_type (TREE_TYPE (decl), &ctx->cb);
2270 else if (DECL_SIZE (decl)
2271 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2273 tree decl2 = DECL_VALUE_EXPR (decl);
2274 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2275 decl2 = TREE_OPERAND (decl2, 0);
2276 gcc_assert (DECL_P (decl2));
2277 fixup_remapped_decl (decl2, ctx, false);
2278 fixup_remapped_decl (decl, ctx, true);
2280 else
2281 fixup_remapped_decl (decl, ctx, false);
2283 break;
2285 case OMP_CLAUSE_COPYPRIVATE:
2286 case OMP_CLAUSE_COPYIN:
2287 case OMP_CLAUSE_DEFAULT:
2288 case OMP_CLAUSE_IF:
2289 case OMP_CLAUSE_NUM_THREADS:
2290 case OMP_CLAUSE_NUM_TEAMS:
2291 case OMP_CLAUSE_THREAD_LIMIT:
2292 case OMP_CLAUSE_DEVICE:
2293 case OMP_CLAUSE_SCHEDULE:
2294 case OMP_CLAUSE_DIST_SCHEDULE:
2295 case OMP_CLAUSE_NOWAIT:
2296 case OMP_CLAUSE_ORDERED:
2297 case OMP_CLAUSE_COLLAPSE:
2298 case OMP_CLAUSE_UNTIED:
2299 case OMP_CLAUSE_FINAL:
2300 case OMP_CLAUSE_MERGEABLE:
2301 case OMP_CLAUSE_PROC_BIND:
2302 case OMP_CLAUSE_SAFELEN:
2303 case OMP_CLAUSE_SIMDLEN:
2304 case OMP_CLAUSE_ALIGNED:
2305 case OMP_CLAUSE_DEPEND:
2306 case OMP_CLAUSE__LOOPTEMP_:
2307 case OMP_CLAUSE_TO:
2308 case OMP_CLAUSE_FROM:
2309 case OMP_CLAUSE_PRIORITY:
2310 case OMP_CLAUSE_GRAINSIZE:
2311 case OMP_CLAUSE_NUM_TASKS:
2312 case OMP_CLAUSE_THREADS:
2313 case OMP_CLAUSE_SIMD:
2314 case OMP_CLAUSE_NOGROUP:
2315 case OMP_CLAUSE_DEFAULTMAP:
2316 case OMP_CLAUSE_USE_DEVICE_PTR:
2317 case OMP_CLAUSE__CILK_FOR_COUNT_:
2318 case OMP_CLAUSE_ASYNC:
2319 case OMP_CLAUSE_WAIT:
2320 case OMP_CLAUSE_NUM_GANGS:
2321 case OMP_CLAUSE_NUM_WORKERS:
2322 case OMP_CLAUSE_VECTOR_LENGTH:
2323 case OMP_CLAUSE_GANG:
2324 case OMP_CLAUSE_WORKER:
2325 case OMP_CLAUSE_VECTOR:
2326 case OMP_CLAUSE_TILE:
2327 case OMP_CLAUSE_INDEPENDENT:
2328 case OMP_CLAUSE_AUTO:
2329 case OMP_CLAUSE_SEQ:
2330 break;
2332 case OMP_CLAUSE_DEVICE_RESIDENT:
2333 case OMP_CLAUSE__CACHE_:
2334 sorry ("Clause not supported yet");
2335 break;
2337 default:
2338 gcc_unreachable ();
2342 gcc_checking_assert (!scan_array_reductions
2343 || !is_gimple_omp_oacc (ctx->stmt));
2344 if (scan_array_reductions)
2345 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2346 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2347 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2349 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2350 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2352 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2353 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2354 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2355 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2356 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2357 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2360 /* Create a new name for omp child function. Returns an identifier. If
2361 IS_CILK_FOR is true then the suffix for the child function is
2362 "_cilk_for_fn." */
2364 static tree
2365 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2367 if (is_cilk_for)
2368 return clone_function_name (current_function_decl, "_cilk_for_fn");
2369 return clone_function_name (current_function_decl,
2370 task_copy ? "_omp_cpyfn" : "_omp_fn");
2373 /* Returns the type of the induction variable for the child function for
2374 _Cilk_for and the types for _high and _low variables based on TYPE. */
2376 static tree
2377 cilk_for_check_loop_diff_type (tree type)
2379 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2381 if (TYPE_UNSIGNED (type))
2382 return uint32_type_node;
2383 else
2384 return integer_type_node;
2386 else
2388 if (TYPE_UNSIGNED (type))
2389 return uint64_type_node;
2390 else
2391 return long_long_integer_type_node;
2395 /* Build a decl for the omp child function. It'll not contain a body
2396 yet, just the bare decl. */
2398 static void
2399 create_omp_child_function (omp_context *ctx, bool task_copy)
2401 tree decl, type, name, t;
2403 tree cilk_for_count
2404 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2405 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2406 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2407 tree cilk_var_type = NULL_TREE;
2409 name = create_omp_child_function_name (task_copy,
2410 cilk_for_count != NULL_TREE);
2411 if (task_copy)
2412 type = build_function_type_list (void_type_node, ptr_type_node,
2413 ptr_type_node, NULL_TREE);
2414 else if (cilk_for_count)
2416 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2417 cilk_var_type = cilk_for_check_loop_diff_type (type);
2418 type = build_function_type_list (void_type_node, ptr_type_node,
2419 cilk_var_type, cilk_var_type, NULL_TREE);
2421 else
2422 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2424 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2426 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2427 || !task_copy);
2428 if (!task_copy)
2429 ctx->cb.dst_fn = decl;
2430 else
2431 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2433 TREE_STATIC (decl) = 1;
2434 TREE_USED (decl) = 1;
2435 DECL_ARTIFICIAL (decl) = 1;
2436 DECL_IGNORED_P (decl) = 0;
2437 TREE_PUBLIC (decl) = 0;
2438 DECL_UNINLINABLE (decl) = 1;
2439 DECL_EXTERNAL (decl) = 0;
2440 DECL_CONTEXT (decl) = NULL_TREE;
2441 DECL_INITIAL (decl) = make_node (BLOCK);
2442 if (cgraph_node::get (current_function_decl)->offloadable)
2443 cgraph_node::get_create (decl)->offloadable = 1;
2444 else
2446 omp_context *octx;
2447 for (octx = ctx; octx; octx = octx->outer)
2448 if (is_gimple_omp_offloaded (octx->stmt))
2450 cgraph_node::get_create (decl)->offloadable = 1;
2451 if (ENABLE_OFFLOADING)
2452 g->have_offload = true;
2454 break;
2458 if (cgraph_node::get_create (decl)->offloadable
2459 && !lookup_attribute ("omp declare target",
2460 DECL_ATTRIBUTES (current_function_decl)))
2461 DECL_ATTRIBUTES (decl)
2462 = tree_cons (get_identifier ("omp target entrypoint"),
2463 NULL_TREE, DECL_ATTRIBUTES (decl));
2465 t = build_decl (DECL_SOURCE_LOCATION (decl),
2466 RESULT_DECL, NULL_TREE, void_type_node);
2467 DECL_ARTIFICIAL (t) = 1;
2468 DECL_IGNORED_P (t) = 1;
2469 DECL_CONTEXT (t) = decl;
2470 DECL_RESULT (decl) = t;
2472 /* _Cilk_for's child function requires two extra parameters called
2473 __low and __high that are set the by Cilk runtime when it calls this
2474 function. */
2475 if (cilk_for_count)
2477 t = build_decl (DECL_SOURCE_LOCATION (decl),
2478 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2479 DECL_ARTIFICIAL (t) = 1;
2480 DECL_NAMELESS (t) = 1;
2481 DECL_ARG_TYPE (t) = ptr_type_node;
2482 DECL_CONTEXT (t) = current_function_decl;
2483 TREE_USED (t) = 1;
2484 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2485 DECL_ARGUMENTS (decl) = t;
2487 t = build_decl (DECL_SOURCE_LOCATION (decl),
2488 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2489 DECL_ARTIFICIAL (t) = 1;
2490 DECL_NAMELESS (t) = 1;
2491 DECL_ARG_TYPE (t) = ptr_type_node;
2492 DECL_CONTEXT (t) = current_function_decl;
2493 TREE_USED (t) = 1;
2494 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2495 DECL_ARGUMENTS (decl) = t;
2498 tree data_name = get_identifier (".omp_data_i");
2499 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2500 ptr_type_node);
2501 DECL_ARTIFICIAL (t) = 1;
2502 DECL_NAMELESS (t) = 1;
2503 DECL_ARG_TYPE (t) = ptr_type_node;
2504 DECL_CONTEXT (t) = current_function_decl;
2505 TREE_USED (t) = 1;
2506 TREE_READONLY (t) = 1;
2507 if (cilk_for_count)
2508 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2509 DECL_ARGUMENTS (decl) = t;
2510 if (!task_copy)
2511 ctx->receiver_decl = t;
2512 else
2514 t = build_decl (DECL_SOURCE_LOCATION (decl),
2515 PARM_DECL, get_identifier (".omp_data_o"),
2516 ptr_type_node);
2517 DECL_ARTIFICIAL (t) = 1;
2518 DECL_NAMELESS (t) = 1;
2519 DECL_ARG_TYPE (t) = ptr_type_node;
2520 DECL_CONTEXT (t) = current_function_decl;
2521 TREE_USED (t) = 1;
2522 TREE_ADDRESSABLE (t) = 1;
2523 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2524 DECL_ARGUMENTS (decl) = t;
2527 /* Allocate memory for the function structure. The call to
2528 allocate_struct_function clobbers CFUN, so we need to restore
2529 it afterward. */
2530 push_struct_function (decl);
2531 cfun->function_end_locus = gimple_location (ctx->stmt);
2532 pop_cfun ();
2535 /* Callback for walk_gimple_seq. Check if combined parallel
2536 contains gimple_omp_for_combined_into_p OMP_FOR. */
2538 static tree
2539 find_combined_for (gimple_stmt_iterator *gsi_p,
2540 bool *handled_ops_p,
2541 struct walk_stmt_info *wi)
2543 gimple *stmt = gsi_stmt (*gsi_p);
2545 *handled_ops_p = true;
2546 switch (gimple_code (stmt))
2548 WALK_SUBSTMTS;
2550 case GIMPLE_OMP_FOR:
2551 if (gimple_omp_for_combined_into_p (stmt)
2552 && gimple_omp_for_kind (stmt)
2553 == *(const enum gf_mask *) (wi->info))
2555 wi->info = stmt;
2556 return integer_zero_node;
2558 break;
2559 default:
2560 break;
2562 return NULL;
2565 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2567 static void
2568 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2569 omp_context *outer_ctx)
2571 struct walk_stmt_info wi;
2573 memset (&wi, 0, sizeof (wi));
2574 wi.val_only = true;
2575 wi.info = (void *) &msk;
2576 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2577 if (wi.info != (void *) &msk)
2579 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2580 struct omp_for_data fd;
2581 extract_omp_for_data (for_stmt, &fd, NULL);
2582 /* We need two temporaries with fd.loop.v type (istart/iend)
2583 and then (fd.collapse - 1) temporaries with the same
2584 type for count2 ... countN-1 vars if not constant. */
2585 size_t count = 2, i;
2586 tree type = fd.iter_type;
2587 if (fd.collapse > 1
2588 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2590 count += fd.collapse - 1;
2591 /* If there are lastprivate clauses on the inner
2592 GIMPLE_OMP_FOR, add one more temporaries for the total number
2593 of iterations (product of count1 ... countN-1). */
2594 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2595 OMP_CLAUSE_LASTPRIVATE))
2596 count++;
2597 else if (msk == GF_OMP_FOR_KIND_FOR
2598 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2599 OMP_CLAUSE_LASTPRIVATE))
2600 count++;
2602 for (i = 0; i < count; i++)
2604 tree temp = create_tmp_var (type);
2605 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2606 insert_decl_map (&outer_ctx->cb, temp, temp);
2607 OMP_CLAUSE_DECL (c) = temp;
2608 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2609 gimple_omp_taskreg_set_clauses (stmt, c);
2614 /* Scan an OpenMP parallel directive. */
2616 static void
2617 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2619 omp_context *ctx;
2620 tree name;
2621 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2623 /* Ignore parallel directives with empty bodies, unless there
2624 are copyin clauses. */
2625 if (optimize > 0
2626 && empty_body_p (gimple_omp_body (stmt))
2627 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2628 OMP_CLAUSE_COPYIN) == NULL)
2630 gsi_replace (gsi, gimple_build_nop (), false);
2631 return;
2634 if (gimple_omp_parallel_combined_p (stmt))
2635 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2637 ctx = new_omp_context (stmt, outer_ctx);
2638 taskreg_contexts.safe_push (ctx);
2639 if (taskreg_nesting_level > 1)
2640 ctx->is_nested = true;
2641 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2642 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2643 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2644 name = create_tmp_var_name (".omp_data_s");
2645 name = build_decl (gimple_location (stmt),
2646 TYPE_DECL, name, ctx->record_type);
2647 DECL_ARTIFICIAL (name) = 1;
2648 DECL_NAMELESS (name) = 1;
2649 TYPE_NAME (ctx->record_type) = name;
2650 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2651 create_omp_child_function (ctx, false);
2652 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2654 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2655 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2657 if (TYPE_FIELDS (ctx->record_type) == NULL)
2658 ctx->record_type = ctx->receiver_decl = NULL;
2661 /* Scan an OpenMP task directive. */
2663 static void
2664 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2666 omp_context *ctx;
2667 tree name, t;
2668 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2670 /* Ignore task directives with empty bodies. */
2671 if (optimize > 0
2672 && empty_body_p (gimple_omp_body (stmt)))
2674 gsi_replace (gsi, gimple_build_nop (), false);
2675 return;
2678 if (gimple_omp_task_taskloop_p (stmt))
2679 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2681 ctx = new_omp_context (stmt, outer_ctx);
2682 taskreg_contexts.safe_push (ctx);
2683 if (taskreg_nesting_level > 1)
2684 ctx->is_nested = true;
2685 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2686 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2687 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2688 name = create_tmp_var_name (".omp_data_s");
2689 name = build_decl (gimple_location (stmt),
2690 TYPE_DECL, name, ctx->record_type);
2691 DECL_ARTIFICIAL (name) = 1;
2692 DECL_NAMELESS (name) = 1;
2693 TYPE_NAME (ctx->record_type) = name;
2694 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2695 create_omp_child_function (ctx, false);
2696 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2698 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2700 if (ctx->srecord_type)
2702 name = create_tmp_var_name (".omp_data_a");
2703 name = build_decl (gimple_location (stmt),
2704 TYPE_DECL, name, ctx->srecord_type);
2705 DECL_ARTIFICIAL (name) = 1;
2706 DECL_NAMELESS (name) = 1;
2707 TYPE_NAME (ctx->srecord_type) = name;
2708 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2709 create_omp_child_function (ctx, true);
2712 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2714 if (TYPE_FIELDS (ctx->record_type) == NULL)
2716 ctx->record_type = ctx->receiver_decl = NULL;
2717 t = build_int_cst (long_integer_type_node, 0);
2718 gimple_omp_task_set_arg_size (stmt, t);
2719 t = build_int_cst (long_integer_type_node, 1);
2720 gimple_omp_task_set_arg_align (stmt, t);
2725 /* If any decls have been made addressable during scan_omp,
2726 adjust their fields if needed, and layout record types
2727 of parallel/task constructs. */
2729 static void
2730 finish_taskreg_scan (omp_context *ctx)
2732 if (ctx->record_type == NULL_TREE)
2733 return;
2735 /* If any task_shared_vars were needed, verify all
2736 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2737 statements if use_pointer_for_field hasn't changed
2738 because of that. If it did, update field types now. */
2739 if (task_shared_vars)
2741 tree c;
2743 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2744 c; c = OMP_CLAUSE_CHAIN (c))
2745 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2746 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2748 tree decl = OMP_CLAUSE_DECL (c);
2750 /* Global variables don't need to be copied,
2751 the receiver side will use them directly. */
2752 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2753 continue;
2754 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2755 || !use_pointer_for_field (decl, ctx))
2756 continue;
2757 tree field = lookup_field (decl, ctx);
2758 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2759 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2760 continue;
2761 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2762 TREE_THIS_VOLATILE (field) = 0;
2763 DECL_USER_ALIGN (field) = 0;
2764 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2765 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2766 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2767 if (ctx->srecord_type)
2769 tree sfield = lookup_sfield (decl, ctx);
2770 TREE_TYPE (sfield) = TREE_TYPE (field);
2771 TREE_THIS_VOLATILE (sfield) = 0;
2772 DECL_USER_ALIGN (sfield) = 0;
2773 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2774 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2775 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2780 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2782 layout_type (ctx->record_type);
2783 fixup_child_record_type (ctx);
2785 else
2787 location_t loc = gimple_location (ctx->stmt);
2788 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2789 /* Move VLA fields to the end. */
2790 p = &TYPE_FIELDS (ctx->record_type);
2791 while (*p)
2792 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2793 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2795 *q = *p;
2796 *p = TREE_CHAIN (*p);
2797 TREE_CHAIN (*q) = NULL_TREE;
2798 q = &TREE_CHAIN (*q);
2800 else
2801 p = &DECL_CHAIN (*p);
2802 *p = vla_fields;
2803 if (gimple_omp_task_taskloop_p (ctx->stmt))
2805 /* Move fields corresponding to first and second _looptemp_
2806 clause first. There are filled by GOMP_taskloop
2807 and thus need to be in specific positions. */
2808 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2809 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2810 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2811 OMP_CLAUSE__LOOPTEMP_);
2812 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2813 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2814 p = &TYPE_FIELDS (ctx->record_type);
2815 while (*p)
2816 if (*p == f1 || *p == f2)
2817 *p = DECL_CHAIN (*p);
2818 else
2819 p = &DECL_CHAIN (*p);
2820 DECL_CHAIN (f1) = f2;
2821 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2822 TYPE_FIELDS (ctx->record_type) = f1;
2823 if (ctx->srecord_type)
2825 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2826 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2827 p = &TYPE_FIELDS (ctx->srecord_type);
2828 while (*p)
2829 if (*p == f1 || *p == f2)
2830 *p = DECL_CHAIN (*p);
2831 else
2832 p = &DECL_CHAIN (*p);
2833 DECL_CHAIN (f1) = f2;
2834 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2835 TYPE_FIELDS (ctx->srecord_type) = f1;
2838 layout_type (ctx->record_type);
2839 fixup_child_record_type (ctx);
2840 if (ctx->srecord_type)
2841 layout_type (ctx->srecord_type);
2842 tree t = fold_convert_loc (loc, long_integer_type_node,
2843 TYPE_SIZE_UNIT (ctx->record_type));
2844 gimple_omp_task_set_arg_size (ctx->stmt, t);
2845 t = build_int_cst (long_integer_type_node,
2846 TYPE_ALIGN_UNIT (ctx->record_type));
2847 gimple_omp_task_set_arg_align (ctx->stmt, t);
2851 /* Find the enclosing offload context. */
2853 static omp_context *
2854 enclosing_target_ctx (omp_context *ctx)
2856 for (; ctx; ctx = ctx->outer)
2857 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2858 break;
2860 return ctx;
2863 /* Return true if ctx is part of an oacc kernels region. */
2865 static bool
2866 ctx_in_oacc_kernels_region (omp_context *ctx)
2868 for (;ctx != NULL; ctx = ctx->outer)
2870 gimple *stmt = ctx->stmt;
2871 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2872 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2873 return true;
2876 return false;
2879 /* Check the parallelism clauses inside a kernels regions.
2880 Until kernels handling moves to use the same loop indirection
2881 scheme as parallel, we need to do this checking early. */
2883 static unsigned
2884 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2886 bool checking = true;
2887 unsigned outer_mask = 0;
2888 unsigned this_mask = 0;
2889 bool has_seq = false, has_auto = false;
2891 if (ctx->outer)
2892 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2893 if (!stmt)
2895 checking = false;
2896 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2897 return outer_mask;
2898 stmt = as_a <gomp_for *> (ctx->stmt);
2901 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2903 switch (OMP_CLAUSE_CODE (c))
2905 case OMP_CLAUSE_GANG:
2906 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2907 break;
2908 case OMP_CLAUSE_WORKER:
2909 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2910 break;
2911 case OMP_CLAUSE_VECTOR:
2912 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2913 break;
2914 case OMP_CLAUSE_SEQ:
2915 has_seq = true;
2916 break;
2917 case OMP_CLAUSE_AUTO:
2918 has_auto = true;
2919 break;
2920 default:
2921 break;
2925 if (checking)
2927 if (has_seq && (this_mask || has_auto))
2928 error_at (gimple_location (stmt), "%<seq%> overrides other"
2929 " OpenACC loop specifiers");
2930 else if (has_auto && this_mask)
2931 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2932 " OpenACC loop specifiers");
2934 if (this_mask & outer_mask)
2935 error_at (gimple_location (stmt), "inner loop uses same"
2936 " OpenACC parallelism as containing loop");
2939 return outer_mask | this_mask;
2942 /* Scan a GIMPLE_OMP_FOR. */
2944 static void
2945 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2947 omp_context *ctx;
2948 size_t i;
2949 tree clauses = gimple_omp_for_clauses (stmt);
2951 ctx = new_omp_context (stmt, outer_ctx);
2953 if (is_gimple_omp_oacc (stmt))
2955 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2957 if (!tgt || is_oacc_parallel (tgt))
2958 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2960 char const *check = NULL;
2962 switch (OMP_CLAUSE_CODE (c))
2964 case OMP_CLAUSE_GANG:
2965 check = "gang";
2966 break;
2968 case OMP_CLAUSE_WORKER:
2969 check = "worker";
2970 break;
2972 case OMP_CLAUSE_VECTOR:
2973 check = "vector";
2974 break;
2976 default:
2977 break;
2980 if (check && OMP_CLAUSE_OPERAND (c, 0))
2981 error_at (gimple_location (stmt),
2982 "argument not permitted on %qs clause in"
2983 " OpenACC %<parallel%>", check);
2986 if (tgt && is_oacc_kernels (tgt))
2988 /* Strip out reductions, as they are not handled yet. */
2989 tree *prev_ptr = &clauses;
2991 while (tree probe = *prev_ptr)
2993 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
2995 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
2996 *prev_ptr = *next_ptr;
2997 else
2998 prev_ptr = next_ptr;
3001 gimple_omp_for_set_clauses (stmt, clauses);
3002 check_oacc_kernel_gwv (stmt, ctx);
3006 scan_sharing_clauses (clauses, ctx);
3008 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3009 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3011 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3012 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3013 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3014 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3016 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3019 /* Scan an OpenMP sections directive. */
3021 static void
3022 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3024 omp_context *ctx;
3026 ctx = new_omp_context (stmt, outer_ctx);
3027 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3028 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3031 /* Scan an OpenMP single directive. */
3033 static void
3034 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3036 omp_context *ctx;
3037 tree name;
3039 ctx = new_omp_context (stmt, outer_ctx);
3040 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3041 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3042 name = create_tmp_var_name (".omp_copy_s");
3043 name = build_decl (gimple_location (stmt),
3044 TYPE_DECL, name, ctx->record_type);
3045 TYPE_NAME (ctx->record_type) = name;
3047 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3048 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3050 if (TYPE_FIELDS (ctx->record_type) == NULL)
3051 ctx->record_type = NULL;
3052 else
3053 layout_type (ctx->record_type);
3056 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3057 used in the corresponding offloaded function are restrict. */
3059 static bool
3060 omp_target_base_pointers_restrict_p (tree clauses)
3062 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3063 used by OpenACC. */
3064 if (flag_openacc == 0)
3065 return false;
3067 /* I. Basic example:
3069 void foo (void)
3071 unsigned int a[2], b[2];
3073 #pragma acc kernels \
3074 copyout (a) \
3075 copyout (b)
3077 a[0] = 0;
3078 b[0] = 1;
3082 After gimplification, we have:
3084 #pragma omp target oacc_kernels \
3085 map(force_from:a [len: 8]) \
3086 map(force_from:b [len: 8])
3088 a[0] = 0;
3089 b[0] = 1;
3092 Because both mappings have the force prefix, we know that they will be
3093 allocated when calling the corresponding offloaded function, which means we
3094 can mark the base pointers for a and b in the offloaded function as
3095 restrict. */
3097 tree c;
3098 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3100 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3101 return false;
3103 switch (OMP_CLAUSE_MAP_KIND (c))
3105 case GOMP_MAP_FORCE_ALLOC:
3106 case GOMP_MAP_FORCE_TO:
3107 case GOMP_MAP_FORCE_FROM:
3108 case GOMP_MAP_FORCE_TOFROM:
3109 break;
3110 default:
3111 return false;
3115 return true;
3118 /* Scan a GIMPLE_OMP_TARGET. */
3120 static void
3121 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3123 omp_context *ctx;
3124 tree name;
3125 bool offloaded = is_gimple_omp_offloaded (stmt);
3126 tree clauses = gimple_omp_target_clauses (stmt);
3128 ctx = new_omp_context (stmt, outer_ctx);
3129 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3130 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3131 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3132 name = create_tmp_var_name (".omp_data_t");
3133 name = build_decl (gimple_location (stmt),
3134 TYPE_DECL, name, ctx->record_type);
3135 DECL_ARTIFICIAL (name) = 1;
3136 DECL_NAMELESS (name) = 1;
3137 TYPE_NAME (ctx->record_type) = name;
3138 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3140 bool base_pointers_restrict = false;
3141 if (offloaded)
3143 create_omp_child_function (ctx, false);
3144 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3146 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3147 if (base_pointers_restrict
3148 && dump_file && (dump_flags & TDF_DETAILS))
3149 fprintf (dump_file,
3150 "Base pointers in offloaded function are restrict\n");
3153 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3154 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3156 if (TYPE_FIELDS (ctx->record_type) == NULL)
3157 ctx->record_type = ctx->receiver_decl = NULL;
3158 else
3160 TYPE_FIELDS (ctx->record_type)
3161 = nreverse (TYPE_FIELDS (ctx->record_type));
3162 if (flag_checking)
3164 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3165 for (tree field = TYPE_FIELDS (ctx->record_type);
3166 field;
3167 field = DECL_CHAIN (field))
3168 gcc_assert (DECL_ALIGN (field) == align);
3170 layout_type (ctx->record_type);
3171 if (offloaded)
3172 fixup_child_record_type (ctx);
3176 /* Scan an OpenMP teams directive. */
3178 static void
3179 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3181 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3182 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3183 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3186 /* Check nesting restrictions. */
3187 static bool
3188 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3190 tree c;
3192 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3193 inside an OpenACC CTX. */
3194 if (!(is_gimple_omp (stmt)
3195 && is_gimple_omp_oacc (stmt)))
3197 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3198 if (is_gimple_omp (octx->stmt)
3199 && is_gimple_omp_oacc (octx->stmt)
3200 /* Except for atomic codes that we share with OpenMP. */
3201 && ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3202 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3204 error_at (gimple_location (stmt),
3205 "non-OpenACC construct inside of OpenACC region");
3206 return false;
3210 if (ctx != NULL)
3212 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3213 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3215 c = NULL_TREE;
3216 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3218 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3219 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3221 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3222 && (ctx->outer == NULL
3223 || !gimple_omp_for_combined_into_p (ctx->stmt)
3224 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3225 || (gimple_omp_for_kind (ctx->outer->stmt)
3226 != GF_OMP_FOR_KIND_FOR)
3227 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3229 error_at (gimple_location (stmt),
3230 "%<ordered simd threads%> must be closely "
3231 "nested inside of %<for simd%> region");
3232 return false;
3234 return true;
3237 error_at (gimple_location (stmt),
3238 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3239 " may not be nested inside %<simd%> region");
3240 return false;
3242 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3244 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3245 || (gimple_omp_for_kind (stmt)
3246 != GF_OMP_FOR_KIND_DISTRIBUTE))
3247 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3249 error_at (gimple_location (stmt),
3250 "only %<distribute%> or %<parallel%> regions are "
3251 "allowed to be strictly nested inside %<teams%> "
3252 "region");
3253 return false;
3257 switch (gimple_code (stmt))
3259 case GIMPLE_OMP_FOR:
3260 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3261 return true;
3262 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3264 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3266 error_at (gimple_location (stmt),
3267 "%<distribute%> region must be strictly nested "
3268 "inside %<teams%> construct");
3269 return false;
3271 return true;
3273 /* We split taskloop into task and nested taskloop in it. */
3274 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3275 return true;
3276 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3278 bool ok = false;
3280 if (ctx)
3281 switch (gimple_code (ctx->stmt))
3283 case GIMPLE_OMP_FOR:
3284 ok = (gimple_omp_for_kind (ctx->stmt)
3285 == GF_OMP_FOR_KIND_OACC_LOOP);
3286 break;
3288 case GIMPLE_OMP_TARGET:
3289 switch (gimple_omp_target_kind (ctx->stmt))
3291 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3292 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3293 ok = true;
3294 break;
3296 default:
3297 break;
3300 default:
3301 break;
3303 else if (get_oacc_fn_attrib (current_function_decl))
3304 ok = true;
3305 if (!ok)
3307 error_at (gimple_location (stmt),
3308 "OpenACC loop directive must be associated with"
3309 " an OpenACC compute region");
3310 return false;
3313 /* FALLTHRU */
3314 case GIMPLE_CALL:
3315 if (is_gimple_call (stmt)
3316 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3317 == BUILT_IN_GOMP_CANCEL
3318 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3319 == BUILT_IN_GOMP_CANCELLATION_POINT))
3321 const char *bad = NULL;
3322 const char *kind = NULL;
3323 const char *construct
3324 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3325 == BUILT_IN_GOMP_CANCEL)
3326 ? "#pragma omp cancel"
3327 : "#pragma omp cancellation point";
3328 if (ctx == NULL)
3330 error_at (gimple_location (stmt), "orphaned %qs construct",
3331 construct);
3332 return false;
3334 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3335 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3336 : 0)
3338 case 1:
3339 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3340 bad = "#pragma omp parallel";
3341 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3342 == BUILT_IN_GOMP_CANCEL
3343 && !integer_zerop (gimple_call_arg (stmt, 1)))
3344 ctx->cancellable = true;
3345 kind = "parallel";
3346 break;
3347 case 2:
3348 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3349 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3350 bad = "#pragma omp for";
3351 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3352 == BUILT_IN_GOMP_CANCEL
3353 && !integer_zerop (gimple_call_arg (stmt, 1)))
3355 ctx->cancellable = true;
3356 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3357 OMP_CLAUSE_NOWAIT))
3358 warning_at (gimple_location (stmt), 0,
3359 "%<#pragma omp cancel for%> inside "
3360 "%<nowait%> for construct");
3361 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3362 OMP_CLAUSE_ORDERED))
3363 warning_at (gimple_location (stmt), 0,
3364 "%<#pragma omp cancel for%> inside "
3365 "%<ordered%> for construct");
3367 kind = "for";
3368 break;
3369 case 4:
3370 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3371 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3372 bad = "#pragma omp sections";
3373 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 == BUILT_IN_GOMP_CANCEL
3375 && !integer_zerop (gimple_call_arg (stmt, 1)))
3377 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3379 ctx->cancellable = true;
3380 if (find_omp_clause (gimple_omp_sections_clauses
3381 (ctx->stmt),
3382 OMP_CLAUSE_NOWAIT))
3383 warning_at (gimple_location (stmt), 0,
3384 "%<#pragma omp cancel sections%> inside "
3385 "%<nowait%> sections construct");
3387 else
3389 gcc_assert (ctx->outer
3390 && gimple_code (ctx->outer->stmt)
3391 == GIMPLE_OMP_SECTIONS);
3392 ctx->outer->cancellable = true;
3393 if (find_omp_clause (gimple_omp_sections_clauses
3394 (ctx->outer->stmt),
3395 OMP_CLAUSE_NOWAIT))
3396 warning_at (gimple_location (stmt), 0,
3397 "%<#pragma omp cancel sections%> inside "
3398 "%<nowait%> sections construct");
3401 kind = "sections";
3402 break;
3403 case 8:
3404 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3405 bad = "#pragma omp task";
3406 else
3408 for (omp_context *octx = ctx->outer;
3409 octx; octx = octx->outer)
3411 switch (gimple_code (octx->stmt))
3413 case GIMPLE_OMP_TASKGROUP:
3414 break;
3415 case GIMPLE_OMP_TARGET:
3416 if (gimple_omp_target_kind (octx->stmt)
3417 != GF_OMP_TARGET_KIND_REGION)
3418 continue;
3419 /* FALLTHRU */
3420 case GIMPLE_OMP_PARALLEL:
3421 case GIMPLE_OMP_TEAMS:
3422 error_at (gimple_location (stmt),
3423 "%<%s taskgroup%> construct not closely "
3424 "nested inside of %<taskgroup%> region",
3425 construct);
3426 return false;
3427 default:
3428 continue;
3430 break;
3432 ctx->cancellable = true;
3434 kind = "taskgroup";
3435 break;
3436 default:
3437 error_at (gimple_location (stmt), "invalid arguments");
3438 return false;
3440 if (bad)
3442 error_at (gimple_location (stmt),
3443 "%<%s %s%> construct not closely nested inside of %qs",
3444 construct, kind, bad);
3445 return false;
3448 /* FALLTHRU */
3449 case GIMPLE_OMP_SECTIONS:
3450 case GIMPLE_OMP_SINGLE:
3451 for (; ctx != NULL; ctx = ctx->outer)
3452 switch (gimple_code (ctx->stmt))
3454 case GIMPLE_OMP_FOR:
3455 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3456 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3457 break;
3458 /* FALLTHRU */
3459 case GIMPLE_OMP_SECTIONS:
3460 case GIMPLE_OMP_SINGLE:
3461 case GIMPLE_OMP_ORDERED:
3462 case GIMPLE_OMP_MASTER:
3463 case GIMPLE_OMP_TASK:
3464 case GIMPLE_OMP_CRITICAL:
3465 if (is_gimple_call (stmt))
3467 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3468 != BUILT_IN_GOMP_BARRIER)
3469 return true;
3470 error_at (gimple_location (stmt),
3471 "barrier region may not be closely nested inside "
3472 "of work-sharing, %<critical%>, %<ordered%>, "
3473 "%<master%>, explicit %<task%> or %<taskloop%> "
3474 "region");
3475 return false;
3477 error_at (gimple_location (stmt),
3478 "work-sharing region may not be closely nested inside "
3479 "of work-sharing, %<critical%>, %<ordered%>, "
3480 "%<master%>, explicit %<task%> or %<taskloop%> region");
3481 return false;
3482 case GIMPLE_OMP_PARALLEL:
3483 case GIMPLE_OMP_TEAMS:
3484 return true;
3485 case GIMPLE_OMP_TARGET:
3486 if (gimple_omp_target_kind (ctx->stmt)
3487 == GF_OMP_TARGET_KIND_REGION)
3488 return true;
3489 break;
3490 default:
3491 break;
3493 break;
3494 case GIMPLE_OMP_MASTER:
3495 for (; ctx != NULL; ctx = ctx->outer)
3496 switch (gimple_code (ctx->stmt))
3498 case GIMPLE_OMP_FOR:
3499 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3500 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3501 break;
3502 /* FALLTHRU */
3503 case GIMPLE_OMP_SECTIONS:
3504 case GIMPLE_OMP_SINGLE:
3505 case GIMPLE_OMP_TASK:
3506 error_at (gimple_location (stmt),
3507 "%<master%> region may not be closely nested inside "
3508 "of work-sharing, explicit %<task%> or %<taskloop%> "
3509 "region");
3510 return false;
3511 case GIMPLE_OMP_PARALLEL:
3512 case GIMPLE_OMP_TEAMS:
3513 return true;
3514 case GIMPLE_OMP_TARGET:
3515 if (gimple_omp_target_kind (ctx->stmt)
3516 == GF_OMP_TARGET_KIND_REGION)
3517 return true;
3518 break;
3519 default:
3520 break;
3522 break;
3523 case GIMPLE_OMP_TASK:
3524 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3525 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3526 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3527 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3529 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3530 error_at (OMP_CLAUSE_LOCATION (c),
3531 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3532 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3533 return false;
3535 break;
3536 case GIMPLE_OMP_ORDERED:
3537 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3538 c; c = OMP_CLAUSE_CHAIN (c))
3540 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3542 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3543 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3544 continue;
3546 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3547 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3548 || kind == OMP_CLAUSE_DEPEND_SINK)
3550 tree oclause;
3551 /* Look for containing ordered(N) loop. */
3552 if (ctx == NULL
3553 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3554 || (oclause
3555 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3556 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3558 error_at (OMP_CLAUSE_LOCATION (c),
3559 "%<ordered%> construct with %<depend%> clause "
3560 "must be closely nested inside an %<ordered%> "
3561 "loop");
3562 return false;
3564 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3566 error_at (OMP_CLAUSE_LOCATION (c),
3567 "%<ordered%> construct with %<depend%> clause "
3568 "must be closely nested inside a loop with "
3569 "%<ordered%> clause with a parameter");
3570 return false;
3573 else
3575 error_at (OMP_CLAUSE_LOCATION (c),
3576 "invalid depend kind in omp %<ordered%> %<depend%>");
3577 return false;
3580 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3581 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3583 /* ordered simd must be closely nested inside of simd region,
3584 and simd region must not encounter constructs other than
3585 ordered simd, therefore ordered simd may be either orphaned,
3586 or ctx->stmt must be simd. The latter case is handled already
3587 earlier. */
3588 if (ctx != NULL)
3590 error_at (gimple_location (stmt),
3591 "%<ordered%> %<simd%> must be closely nested inside "
3592 "%<simd%> region");
3593 return false;
3596 for (; ctx != NULL; ctx = ctx->outer)
3597 switch (gimple_code (ctx->stmt))
3599 case GIMPLE_OMP_CRITICAL:
3600 case GIMPLE_OMP_TASK:
3601 case GIMPLE_OMP_ORDERED:
3602 ordered_in_taskloop:
3603 error_at (gimple_location (stmt),
3604 "%<ordered%> region may not be closely nested inside "
3605 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3606 "%<taskloop%> region");
3607 return false;
3608 case GIMPLE_OMP_FOR:
3609 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3610 goto ordered_in_taskloop;
3611 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3612 OMP_CLAUSE_ORDERED) == NULL)
3614 error_at (gimple_location (stmt),
3615 "%<ordered%> region must be closely nested inside "
3616 "a loop region with an %<ordered%> clause");
3617 return false;
3619 return true;
3620 case GIMPLE_OMP_TARGET:
3621 if (gimple_omp_target_kind (ctx->stmt)
3622 != GF_OMP_TARGET_KIND_REGION)
3623 break;
3624 /* FALLTHRU */
3625 case GIMPLE_OMP_PARALLEL:
3626 case GIMPLE_OMP_TEAMS:
3627 error_at (gimple_location (stmt),
3628 "%<ordered%> region must be closely nested inside "
3629 "a loop region with an %<ordered%> clause");
3630 return false;
3631 default:
3632 break;
3634 break;
3635 case GIMPLE_OMP_CRITICAL:
3637 tree this_stmt_name
3638 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3639 for (; ctx != NULL; ctx = ctx->outer)
3640 if (gomp_critical *other_crit
3641 = dyn_cast <gomp_critical *> (ctx->stmt))
3642 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3644 error_at (gimple_location (stmt),
3645 "%<critical%> region may not be nested inside "
3646 "a %<critical%> region with the same name");
3647 return false;
3650 break;
3651 case GIMPLE_OMP_TEAMS:
3652 if (ctx == NULL
3653 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3654 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3656 error_at (gimple_location (stmt),
3657 "%<teams%> construct not closely nested inside of "
3658 "%<target%> construct");
3659 return false;
3661 break;
3662 case GIMPLE_OMP_TARGET:
3663 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3664 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3665 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3666 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3668 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3669 error_at (OMP_CLAUSE_LOCATION (c),
3670 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3671 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3672 return false;
3674 for (; ctx != NULL; ctx = ctx->outer)
3676 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3678 if (is_gimple_omp (stmt)
3679 && is_gimple_omp_oacc (stmt)
3680 && is_gimple_omp (ctx->stmt))
3682 error_at (gimple_location (stmt),
3683 "OpenACC construct inside of non-OpenACC region");
3684 return false;
3686 continue;
3689 const char *stmt_name, *ctx_stmt_name;
3690 switch (gimple_omp_target_kind (stmt))
3692 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3693 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3694 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3695 case GF_OMP_TARGET_KIND_ENTER_DATA:
3696 stmt_name = "target enter data"; break;
3697 case GF_OMP_TARGET_KIND_EXIT_DATA:
3698 stmt_name = "target exit data"; break;
3699 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3700 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3701 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3702 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3703 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3704 stmt_name = "enter/exit data"; break;
3705 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3706 break;
3707 default: gcc_unreachable ();
3709 switch (gimple_omp_target_kind (ctx->stmt))
3711 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3712 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3713 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3714 ctx_stmt_name = "parallel"; break;
3715 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3716 ctx_stmt_name = "kernels"; break;
3717 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3718 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3719 ctx_stmt_name = "host_data"; break;
3720 default: gcc_unreachable ();
3723 /* OpenACC/OpenMP mismatch? */
3724 if (is_gimple_omp_oacc (stmt)
3725 != is_gimple_omp_oacc (ctx->stmt))
3727 error_at (gimple_location (stmt),
3728 "%s %qs construct inside of %s %qs region",
3729 (is_gimple_omp_oacc (stmt)
3730 ? "OpenACC" : "OpenMP"), stmt_name,
3731 (is_gimple_omp_oacc (ctx->stmt)
3732 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3733 return false;
3735 if (is_gimple_omp_offloaded (ctx->stmt))
3737 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3738 if (is_gimple_omp_oacc (ctx->stmt))
3740 error_at (gimple_location (stmt),
3741 "%qs construct inside of %qs region",
3742 stmt_name, ctx_stmt_name);
3743 return false;
3745 else
3747 warning_at (gimple_location (stmt), 0,
3748 "%qs construct inside of %qs region",
3749 stmt_name, ctx_stmt_name);
3753 break;
3754 default:
3755 break;
3757 return true;
3761 /* Helper function scan_omp.
3763 Callback for walk_tree or operators in walk_gimple_stmt used to
3764 scan for OMP directives in TP. */
3766 static tree
3767 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3769 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3770 omp_context *ctx = (omp_context *) wi->info;
3771 tree t = *tp;
3773 switch (TREE_CODE (t))
3775 case VAR_DECL:
3776 case PARM_DECL:
3777 case LABEL_DECL:
3778 case RESULT_DECL:
3779 if (ctx)
3780 *tp = remap_decl (t, &ctx->cb);
3781 break;
3783 default:
3784 if (ctx && TYPE_P (t))
3785 *tp = remap_type (t, &ctx->cb);
3786 else if (!DECL_P (t))
3788 *walk_subtrees = 1;
3789 if (ctx)
3791 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3792 if (tem != TREE_TYPE (t))
3794 if (TREE_CODE (t) == INTEGER_CST)
3795 *tp = wide_int_to_tree (tem, t);
3796 else
3797 TREE_TYPE (t) = tem;
3801 break;
3804 return NULL_TREE;
3807 /* Return true if FNDECL is a setjmp or a longjmp. */
3809 static bool
3810 setjmp_or_longjmp_p (const_tree fndecl)
3812 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3813 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3814 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3815 return true;
3817 tree declname = DECL_NAME (fndecl);
3818 if (!declname)
3819 return false;
3820 const char *name = IDENTIFIER_POINTER (declname);
3821 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3825 /* Helper function for scan_omp.
3827 Callback for walk_gimple_stmt used to scan for OMP directives in
3828 the current statement in GSI. */
3830 static tree
3831 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3832 struct walk_stmt_info *wi)
3834 gimple *stmt = gsi_stmt (*gsi);
3835 omp_context *ctx = (omp_context *) wi->info;
3837 if (gimple_has_location (stmt))
3838 input_location = gimple_location (stmt);
3840 /* Check the nesting restrictions. */
3841 bool remove = false;
3842 if (is_gimple_omp (stmt))
3843 remove = !check_omp_nesting_restrictions (stmt, ctx);
3844 else if (is_gimple_call (stmt))
3846 tree fndecl = gimple_call_fndecl (stmt);
3847 if (fndecl)
3849 if (setjmp_or_longjmp_p (fndecl)
3850 && ctx
3851 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3852 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3854 remove = true;
3855 error_at (gimple_location (stmt),
3856 "setjmp/longjmp inside simd construct");
3858 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3859 switch (DECL_FUNCTION_CODE (fndecl))
3861 case BUILT_IN_GOMP_BARRIER:
3862 case BUILT_IN_GOMP_CANCEL:
3863 case BUILT_IN_GOMP_CANCELLATION_POINT:
3864 case BUILT_IN_GOMP_TASKYIELD:
3865 case BUILT_IN_GOMP_TASKWAIT:
3866 case BUILT_IN_GOMP_TASKGROUP_START:
3867 case BUILT_IN_GOMP_TASKGROUP_END:
3868 remove = !check_omp_nesting_restrictions (stmt, ctx);
3869 break;
3870 default:
3871 break;
3875 if (remove)
3877 stmt = gimple_build_nop ();
3878 gsi_replace (gsi, stmt, false);
3881 *handled_ops_p = true;
3883 switch (gimple_code (stmt))
3885 case GIMPLE_OMP_PARALLEL:
3886 taskreg_nesting_level++;
3887 scan_omp_parallel (gsi, ctx);
3888 taskreg_nesting_level--;
3889 break;
3891 case GIMPLE_OMP_TASK:
3892 taskreg_nesting_level++;
3893 scan_omp_task (gsi, ctx);
3894 taskreg_nesting_level--;
3895 break;
3897 case GIMPLE_OMP_FOR:
3898 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3899 break;
3901 case GIMPLE_OMP_SECTIONS:
3902 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3903 break;
3905 case GIMPLE_OMP_SINGLE:
3906 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3907 break;
3909 case GIMPLE_OMP_SECTION:
3910 case GIMPLE_OMP_MASTER:
3911 case GIMPLE_OMP_TASKGROUP:
3912 case GIMPLE_OMP_ORDERED:
3913 case GIMPLE_OMP_CRITICAL:
3914 ctx = new_omp_context (stmt, ctx);
3915 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3916 break;
3918 case GIMPLE_OMP_TARGET:
3919 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3920 break;
3922 case GIMPLE_OMP_TEAMS:
3923 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3924 break;
3926 case GIMPLE_BIND:
3928 tree var;
3930 *handled_ops_p = false;
3931 if (ctx)
3932 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3933 var ;
3934 var = DECL_CHAIN (var))
3935 insert_decl_map (&ctx->cb, var, var);
3937 break;
3938 default:
3939 *handled_ops_p = false;
3940 break;
3943 return NULL_TREE;
3947 /* Scan all the statements starting at the current statement. CTX
3948 contains context information about the OMP directives and
3949 clauses found during the scan. */
3951 static void
3952 scan_omp (gimple_seq *body_p, omp_context *ctx)
3954 location_t saved_location;
3955 struct walk_stmt_info wi;
3957 memset (&wi, 0, sizeof (wi));
3958 wi.info = ctx;
3959 wi.want_locations = true;
3961 saved_location = input_location;
3962 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3963 input_location = saved_location;
3966 /* Re-gimplification and code generation routines. */
3968 /* Build a call to GOMP_barrier. */
3970 static gimple *
3971 build_omp_barrier (tree lhs)
3973 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3974 : BUILT_IN_GOMP_BARRIER);
3975 gcall *g = gimple_build_call (fndecl, 0);
3976 if (lhs)
3977 gimple_call_set_lhs (g, lhs);
3978 return g;
3981 /* If a context was created for STMT when it was scanned, return it. */
3983 static omp_context *
3984 maybe_lookup_ctx (gimple *stmt)
3986 splay_tree_node n;
3987 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3988 return n ? (omp_context *) n->value : NULL;
3992 /* Find the mapping for DECL in CTX or the immediately enclosing
3993 context that has a mapping for DECL.
3995 If CTX is a nested parallel directive, we may have to use the decl
3996 mappings created in CTX's parent context. Suppose that we have the
3997 following parallel nesting (variable UIDs showed for clarity):
3999 iD.1562 = 0;
4000 #omp parallel shared(iD.1562) -> outer parallel
4001 iD.1562 = iD.1562 + 1;
4003 #omp parallel shared (iD.1562) -> inner parallel
4004 iD.1562 = iD.1562 - 1;
4006 Each parallel structure will create a distinct .omp_data_s structure
4007 for copying iD.1562 in/out of the directive:
4009 outer parallel .omp_data_s.1.i -> iD.1562
4010 inner parallel .omp_data_s.2.i -> iD.1562
4012 A shared variable mapping will produce a copy-out operation before
4013 the parallel directive and a copy-in operation after it. So, in
4014 this case we would have:
4016 iD.1562 = 0;
4017 .omp_data_o.1.i = iD.1562;
4018 #omp parallel shared(iD.1562) -> outer parallel
4019 .omp_data_i.1 = &.omp_data_o.1
4020 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4022 .omp_data_o.2.i = iD.1562; -> **
4023 #omp parallel shared(iD.1562) -> inner parallel
4024 .omp_data_i.2 = &.omp_data_o.2
4025 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4028 ** This is a problem. The symbol iD.1562 cannot be referenced
4029 inside the body of the outer parallel region. But since we are
4030 emitting this copy operation while expanding the inner parallel
4031 directive, we need to access the CTX structure of the outer
4032 parallel directive to get the correct mapping:
4034 .omp_data_o.2.i = .omp_data_i.1->i
4036 Since there may be other workshare or parallel directives enclosing
4037 the parallel directive, it may be necessary to walk up the context
4038 parent chain. This is not a problem in general because nested
4039 parallelism happens only rarely. */
4041 static tree
4042 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4044 tree t;
4045 omp_context *up;
4047 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4048 t = maybe_lookup_decl (decl, up);
4050 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4052 return t ? t : decl;
4056 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4057 in outer contexts. */
4059 static tree
4060 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4062 tree t = NULL;
4063 omp_context *up;
4065 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4066 t = maybe_lookup_decl (decl, up);
4068 return t ? t : decl;
4072 /* Construct the initialization value for reduction operation OP. */
4074 tree
4075 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4077 switch (op)
4079 case PLUS_EXPR:
4080 case MINUS_EXPR:
4081 case BIT_IOR_EXPR:
4082 case BIT_XOR_EXPR:
4083 case TRUTH_OR_EXPR:
4084 case TRUTH_ORIF_EXPR:
4085 case TRUTH_XOR_EXPR:
4086 case NE_EXPR:
4087 return build_zero_cst (type);
4089 case MULT_EXPR:
4090 case TRUTH_AND_EXPR:
4091 case TRUTH_ANDIF_EXPR:
4092 case EQ_EXPR:
4093 return fold_convert_loc (loc, type, integer_one_node);
4095 case BIT_AND_EXPR:
4096 return fold_convert_loc (loc, type, integer_minus_one_node);
4098 case MAX_EXPR:
4099 if (SCALAR_FLOAT_TYPE_P (type))
4101 REAL_VALUE_TYPE max, min;
4102 if (HONOR_INFINITIES (type))
4104 real_inf (&max);
4105 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4107 else
4108 real_maxval (&min, 1, TYPE_MODE (type));
4109 return build_real (type, min);
4111 else if (POINTER_TYPE_P (type))
4113 wide_int min
4114 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4115 return wide_int_to_tree (type, min);
4117 else
4119 gcc_assert (INTEGRAL_TYPE_P (type));
4120 return TYPE_MIN_VALUE (type);
4123 case MIN_EXPR:
4124 if (SCALAR_FLOAT_TYPE_P (type))
4126 REAL_VALUE_TYPE max;
4127 if (HONOR_INFINITIES (type))
4128 real_inf (&max);
4129 else
4130 real_maxval (&max, 0, TYPE_MODE (type));
4131 return build_real (type, max);
4133 else if (POINTER_TYPE_P (type))
4135 wide_int max
4136 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4137 return wide_int_to_tree (type, max);
4139 else
4141 gcc_assert (INTEGRAL_TYPE_P (type));
4142 return TYPE_MAX_VALUE (type);
4145 default:
4146 gcc_unreachable ();
4150 /* Construct the initialization value for reduction CLAUSE. */
4152 tree
4153 omp_reduction_init (tree clause, tree type)
4155 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4156 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4159 /* Return alignment to be assumed for var in CLAUSE, which should be
4160 OMP_CLAUSE_ALIGNED. */
4162 static tree
4163 omp_clause_aligned_alignment (tree clause)
4165 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4166 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4168 /* Otherwise return implementation defined alignment. */
4169 unsigned int al = 1;
4170 machine_mode mode, vmode;
4171 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4172 if (vs)
4173 vs = 1 << floor_log2 (vs);
4174 static enum mode_class classes[]
4175 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4176 for (int i = 0; i < 4; i += 2)
4177 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4178 mode != VOIDmode;
4179 mode = GET_MODE_WIDER_MODE (mode))
4181 vmode = targetm.vectorize.preferred_simd_mode (mode);
4182 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4183 continue;
4184 while (vs
4185 && GET_MODE_SIZE (vmode) < vs
4186 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4187 vmode = GET_MODE_2XWIDER_MODE (vmode);
4189 tree type = lang_hooks.types.type_for_mode (mode, 1);
4190 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4191 continue;
4192 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4193 / GET_MODE_SIZE (mode));
4194 if (TYPE_MODE (type) != vmode)
4195 continue;
4196 if (TYPE_ALIGN_UNIT (type) > al)
4197 al = TYPE_ALIGN_UNIT (type);
4199 return build_int_cst (integer_type_node, al);
4202 /* Return maximum possible vectorization factor for the target. */
4204 static int
4205 omp_max_vf (void)
4207 if (!optimize
4208 || optimize_debug
4209 || !flag_tree_loop_optimize
4210 || (!flag_tree_loop_vectorize
4211 && (global_options_set.x_flag_tree_loop_vectorize
4212 || global_options_set.x_flag_tree_vectorize)))
4213 return 1;
4215 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4216 if (vs)
4218 vs = 1 << floor_log2 (vs);
4219 return vs;
4221 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4222 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4223 return GET_MODE_NUNITS (vqimode);
4224 return 1;
4227 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4228 privatization. */
4230 static bool
4231 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4232 tree &idx, tree &lane, tree &ivar, tree &lvar)
4234 if (max_vf == 0)
4236 max_vf = omp_max_vf ();
4237 if (max_vf > 1)
4239 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4240 OMP_CLAUSE_SAFELEN);
4241 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4242 max_vf = 1;
4243 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4244 max_vf) == -1)
4245 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4247 if (max_vf > 1)
4249 idx = create_tmp_var (unsigned_type_node);
4250 lane = create_tmp_var (unsigned_type_node);
4253 if (max_vf == 1)
4254 return false;
4256 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4257 tree avar = create_tmp_var_raw (atype);
4258 if (TREE_ADDRESSABLE (new_var))
4259 TREE_ADDRESSABLE (avar) = 1;
4260 DECL_ATTRIBUTES (avar)
4261 = tree_cons (get_identifier ("omp simd array"), NULL,
4262 DECL_ATTRIBUTES (avar));
4263 gimple_add_tmp_var (avar);
4264 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4265 NULL_TREE, NULL_TREE);
4266 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4267 NULL_TREE, NULL_TREE);
4268 if (DECL_P (new_var))
4270 SET_DECL_VALUE_EXPR (new_var, lvar);
4271 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4273 return true;
4276 /* Helper function of lower_rec_input_clauses. For a reference
4277 in simd reduction, add an underlying variable it will reference. */
4279 static void
4280 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4282 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4283 if (TREE_CONSTANT (z))
4285 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4286 get_name (new_vard));
4287 gimple_add_tmp_var (z);
4288 TREE_ADDRESSABLE (z) = 1;
4289 z = build_fold_addr_expr_loc (loc, z);
4290 gimplify_assign (new_vard, z, ilist);
4294 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4295 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4296 private variables. Initialization statements go in ILIST, while calls
4297 to destructors go in DLIST. */
4299 static void
4300 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4301 omp_context *ctx, struct omp_for_data *fd)
4303 tree c, dtor, copyin_seq, x, ptr;
4304 bool copyin_by_ref = false;
4305 bool lastprivate_firstprivate = false;
4306 bool reduction_omp_orig_ref = false;
4307 int pass;
4308 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4309 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4310 int max_vf = 0;
4311 tree lane = NULL_TREE, idx = NULL_TREE;
4312 tree ivar = NULL_TREE, lvar = NULL_TREE;
4313 gimple_seq llist[2] = { NULL, NULL };
4315 copyin_seq = NULL;
4317 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4318 with data sharing clauses referencing variable sized vars. That
4319 is unnecessarily hard to support and very unlikely to result in
4320 vectorized code anyway. */
4321 if (is_simd)
4322 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4323 switch (OMP_CLAUSE_CODE (c))
4325 case OMP_CLAUSE_LINEAR:
4326 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4327 max_vf = 1;
4328 /* FALLTHRU */
4329 case OMP_CLAUSE_PRIVATE:
4330 case OMP_CLAUSE_FIRSTPRIVATE:
4331 case OMP_CLAUSE_LASTPRIVATE:
4332 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4333 max_vf = 1;
4334 break;
4335 case OMP_CLAUSE_REDUCTION:
4336 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4337 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4338 max_vf = 1;
4339 break;
4340 default:
4341 continue;
4344 /* Do all the fixed sized types in the first pass, and the variable sized
4345 types in the second pass. This makes sure that the scalar arguments to
4346 the variable sized types are processed before we use them in the
4347 variable sized operations. */
4348 for (pass = 0; pass < 2; ++pass)
4350 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4352 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4353 tree var, new_var;
4354 bool by_ref;
4355 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4357 switch (c_kind)
4359 case OMP_CLAUSE_PRIVATE:
4360 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4361 continue;
4362 break;
4363 case OMP_CLAUSE_SHARED:
4364 /* Ignore shared directives in teams construct. */
4365 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4366 continue;
4367 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4369 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4370 || is_global_var (OMP_CLAUSE_DECL (c)));
4371 continue;
4373 case OMP_CLAUSE_FIRSTPRIVATE:
4374 case OMP_CLAUSE_COPYIN:
4375 break;
4376 case OMP_CLAUSE_LINEAR:
4377 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4378 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4379 lastprivate_firstprivate = true;
4380 break;
4381 case OMP_CLAUSE_REDUCTION:
4382 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4383 reduction_omp_orig_ref = true;
4384 break;
4385 case OMP_CLAUSE__LOOPTEMP_:
4386 /* Handle _looptemp_ clauses only on parallel/task. */
4387 if (fd)
4388 continue;
4389 break;
4390 case OMP_CLAUSE_LASTPRIVATE:
4391 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4393 lastprivate_firstprivate = true;
4394 if (pass != 0 || is_taskloop_ctx (ctx))
4395 continue;
4397 /* Even without corresponding firstprivate, if
4398 decl is Fortran allocatable, it needs outer var
4399 reference. */
4400 else if (pass == 0
4401 && lang_hooks.decls.omp_private_outer_ref
4402 (OMP_CLAUSE_DECL (c)))
4403 lastprivate_firstprivate = true;
4404 break;
4405 case OMP_CLAUSE_ALIGNED:
4406 if (pass == 0)
4407 continue;
4408 var = OMP_CLAUSE_DECL (c);
4409 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4410 && !is_global_var (var))
4412 new_var = maybe_lookup_decl (var, ctx);
4413 if (new_var == NULL_TREE)
4414 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4415 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4416 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4417 omp_clause_aligned_alignment (c));
4418 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4419 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4420 gimplify_and_add (x, ilist);
4422 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4423 && is_global_var (var))
4425 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4426 new_var = lookup_decl (var, ctx);
4427 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4428 t = build_fold_addr_expr_loc (clause_loc, t);
4429 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4430 t = build_call_expr_loc (clause_loc, t2, 2, t,
4431 omp_clause_aligned_alignment (c));
4432 t = fold_convert_loc (clause_loc, ptype, t);
4433 x = create_tmp_var (ptype);
4434 t = build2 (MODIFY_EXPR, ptype, x, t);
4435 gimplify_and_add (t, ilist);
4436 t = build_simple_mem_ref_loc (clause_loc, x);
4437 SET_DECL_VALUE_EXPR (new_var, t);
4438 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4440 continue;
4441 default:
4442 continue;
4445 new_var = var = OMP_CLAUSE_DECL (c);
4446 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4448 var = TREE_OPERAND (var, 0);
4449 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4450 var = TREE_OPERAND (var, 0);
4451 if (TREE_CODE (var) == INDIRECT_REF
4452 || TREE_CODE (var) == ADDR_EXPR)
4453 var = TREE_OPERAND (var, 0);
4454 if (is_variable_sized (var))
4456 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4457 var = DECL_VALUE_EXPR (var);
4458 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4459 var = TREE_OPERAND (var, 0);
4460 gcc_assert (DECL_P (var));
4462 new_var = var;
4464 if (c_kind != OMP_CLAUSE_COPYIN)
4465 new_var = lookup_decl (var, ctx);
4467 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4469 if (pass != 0)
4470 continue;
4472 /* C/C++ array section reductions. */
4473 else if (c_kind == OMP_CLAUSE_REDUCTION
4474 && var != OMP_CLAUSE_DECL (c))
4476 if (pass == 0)
4477 continue;
4479 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4480 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4481 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4483 tree b = TREE_OPERAND (orig_var, 1);
4484 b = maybe_lookup_decl (b, ctx);
4485 if (b == NULL)
4487 b = TREE_OPERAND (orig_var, 1);
4488 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4490 if (integer_zerop (bias))
4491 bias = b;
4492 else
4494 bias = fold_convert_loc (clause_loc,
4495 TREE_TYPE (b), bias);
4496 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4497 TREE_TYPE (b), b, bias);
4499 orig_var = TREE_OPERAND (orig_var, 0);
4501 if (TREE_CODE (orig_var) == INDIRECT_REF
4502 || TREE_CODE (orig_var) == ADDR_EXPR)
4503 orig_var = TREE_OPERAND (orig_var, 0);
4504 tree d = OMP_CLAUSE_DECL (c);
4505 tree type = TREE_TYPE (d);
4506 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4507 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4508 const char *name = get_name (orig_var);
4509 if (TREE_CONSTANT (v))
4511 x = create_tmp_var_raw (type, name);
4512 gimple_add_tmp_var (x);
4513 TREE_ADDRESSABLE (x) = 1;
4514 x = build_fold_addr_expr_loc (clause_loc, x);
4516 else
4518 tree atmp
4519 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4520 tree t = maybe_lookup_decl (v, ctx);
4521 if (t)
4522 v = t;
4523 else
4524 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4525 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4526 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4527 TREE_TYPE (v), v,
4528 build_int_cst (TREE_TYPE (v), 1));
4529 t = fold_build2_loc (clause_loc, MULT_EXPR,
4530 TREE_TYPE (v), t,
4531 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4532 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4533 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4536 tree ptype = build_pointer_type (TREE_TYPE (type));
4537 x = fold_convert_loc (clause_loc, ptype, x);
4538 tree y = create_tmp_var (ptype, name);
4539 gimplify_assign (y, x, ilist);
4540 x = y;
4541 tree yb = y;
4543 if (!integer_zerop (bias))
4545 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4546 bias);
4547 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4549 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4550 pointer_sized_int_node, yb, bias);
4551 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4552 yb = create_tmp_var (ptype, name);
4553 gimplify_assign (yb, x, ilist);
4554 x = yb;
4557 d = TREE_OPERAND (d, 0);
4558 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4559 d = TREE_OPERAND (d, 0);
4560 if (TREE_CODE (d) == ADDR_EXPR)
4562 if (orig_var != var)
4564 gcc_assert (is_variable_sized (orig_var));
4565 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4567 gimplify_assign (new_var, x, ilist);
4568 tree new_orig_var = lookup_decl (orig_var, ctx);
4569 tree t = build_fold_indirect_ref (new_var);
4570 DECL_IGNORED_P (new_var) = 0;
4571 TREE_THIS_NOTRAP (t);
4572 SET_DECL_VALUE_EXPR (new_orig_var, t);
4573 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4575 else
4577 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4578 build_int_cst (ptype, 0));
4579 SET_DECL_VALUE_EXPR (new_var, x);
4580 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4583 else
4585 gcc_assert (orig_var == var);
4586 if (TREE_CODE (d) == INDIRECT_REF)
4588 x = create_tmp_var (ptype, name);
4589 TREE_ADDRESSABLE (x) = 1;
4590 gimplify_assign (x, yb, ilist);
4591 x = build_fold_addr_expr_loc (clause_loc, x);
4593 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4594 gimplify_assign (new_var, x, ilist);
4596 tree y1 = create_tmp_var (ptype, NULL);
4597 gimplify_assign (y1, y, ilist);
4598 tree i2 = NULL_TREE, y2 = NULL_TREE;
4599 tree body2 = NULL_TREE, end2 = NULL_TREE;
4600 tree y3 = NULL_TREE, y4 = NULL_TREE;
4601 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4603 y2 = create_tmp_var (ptype, NULL);
4604 gimplify_assign (y2, y, ilist);
4605 tree ref = build_outer_var_ref (var, ctx);
4606 /* For ref build_outer_var_ref already performs this. */
4607 if (TREE_CODE (d) == INDIRECT_REF)
4608 gcc_assert (is_reference (var));
4609 else if (TREE_CODE (d) == ADDR_EXPR)
4610 ref = build_fold_addr_expr (ref);
4611 else if (is_reference (var))
4612 ref = build_fold_addr_expr (ref);
4613 ref = fold_convert_loc (clause_loc, ptype, ref);
4614 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4615 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4617 y3 = create_tmp_var (ptype, NULL);
4618 gimplify_assign (y3, unshare_expr (ref), ilist);
4620 if (is_simd)
4622 y4 = create_tmp_var (ptype, NULL);
4623 gimplify_assign (y4, ref, dlist);
4626 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4627 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4628 tree body = create_artificial_label (UNKNOWN_LOCATION);
4629 tree end = create_artificial_label (UNKNOWN_LOCATION);
4630 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4631 if (y2)
4633 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4634 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4635 body2 = create_artificial_label (UNKNOWN_LOCATION);
4636 end2 = create_artificial_label (UNKNOWN_LOCATION);
4637 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4639 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4641 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4642 tree decl_placeholder
4643 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4644 SET_DECL_VALUE_EXPR (decl_placeholder,
4645 build_simple_mem_ref (y1));
4646 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4647 SET_DECL_VALUE_EXPR (placeholder,
4648 y3 ? build_simple_mem_ref (y3)
4649 : error_mark_node);
4650 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4651 x = lang_hooks.decls.omp_clause_default_ctor
4652 (c, build_simple_mem_ref (y1),
4653 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4654 if (x)
4655 gimplify_and_add (x, ilist);
4656 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4658 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4659 lower_omp (&tseq, ctx);
4660 gimple_seq_add_seq (ilist, tseq);
4662 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4663 if (is_simd)
4665 SET_DECL_VALUE_EXPR (decl_placeholder,
4666 build_simple_mem_ref (y2));
4667 SET_DECL_VALUE_EXPR (placeholder,
4668 build_simple_mem_ref (y4));
4669 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4670 lower_omp (&tseq, ctx);
4671 gimple_seq_add_seq (dlist, tseq);
4672 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4674 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4675 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4676 x = lang_hooks.decls.omp_clause_dtor
4677 (c, build_simple_mem_ref (y2));
4678 if (x)
4680 gimple_seq tseq = NULL;
4681 dtor = x;
4682 gimplify_stmt (&dtor, &tseq);
4683 gimple_seq_add_seq (dlist, tseq);
4686 else
4688 x = omp_reduction_init (c, TREE_TYPE (type));
4689 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4691 /* reduction(-:var) sums up the partial results, so it
4692 acts identically to reduction(+:var). */
4693 if (code == MINUS_EXPR)
4694 code = PLUS_EXPR;
4696 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4697 if (is_simd)
4699 x = build2 (code, TREE_TYPE (type),
4700 build_simple_mem_ref (y4),
4701 build_simple_mem_ref (y2));
4702 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4705 gimple *g
4706 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4707 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4708 gimple_seq_add_stmt (ilist, g);
4709 if (y3)
4711 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4712 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4713 gimple_seq_add_stmt (ilist, g);
4715 g = gimple_build_assign (i, PLUS_EXPR, i,
4716 build_int_cst (TREE_TYPE (i), 1));
4717 gimple_seq_add_stmt (ilist, g);
4718 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4719 gimple_seq_add_stmt (ilist, g);
4720 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4721 if (y2)
4723 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4724 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4725 gimple_seq_add_stmt (dlist, g);
4726 if (y4)
4728 g = gimple_build_assign
4729 (y4, POINTER_PLUS_EXPR, y4,
4730 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4731 gimple_seq_add_stmt (dlist, g);
4733 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4734 build_int_cst (TREE_TYPE (i2), 1));
4735 gimple_seq_add_stmt (dlist, g);
4736 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4737 gimple_seq_add_stmt (dlist, g);
4738 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4740 continue;
4742 else if (is_variable_sized (var))
4744 /* For variable sized types, we need to allocate the
4745 actual storage here. Call alloca and store the
4746 result in the pointer decl that we created elsewhere. */
4747 if (pass == 0)
4748 continue;
4750 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4752 gcall *stmt;
4753 tree tmp, atmp;
4755 ptr = DECL_VALUE_EXPR (new_var);
4756 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4757 ptr = TREE_OPERAND (ptr, 0);
4758 gcc_assert (DECL_P (ptr));
4759 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4761 /* void *tmp = __builtin_alloca */
4762 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4763 stmt = gimple_build_call (atmp, 2, x,
4764 size_int (DECL_ALIGN (var)));
4765 tmp = create_tmp_var_raw (ptr_type_node);
4766 gimple_add_tmp_var (tmp);
4767 gimple_call_set_lhs (stmt, tmp);
4769 gimple_seq_add_stmt (ilist, stmt);
4771 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4772 gimplify_assign (ptr, x, ilist);
4775 else if (is_reference (var) && !is_oacc_parallel (ctx))
4777 /* For references that are being privatized for Fortran,
4778 allocate new backing storage for the new pointer
4779 variable. This allows us to avoid changing all the
4780 code that expects a pointer to something that expects
4781 a direct variable. */
4782 if (pass == 0)
4783 continue;
4785 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4786 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4788 x = build_receiver_ref (var, false, ctx);
4789 x = build_fold_addr_expr_loc (clause_loc, x);
4791 else if (TREE_CONSTANT (x))
4793 /* For reduction in SIMD loop, defer adding the
4794 initialization of the reference, because if we decide
4795 to use SIMD array for it, the initilization could cause
4796 expansion ICE. */
4797 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4798 x = NULL_TREE;
4799 else
4801 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4802 get_name (var));
4803 gimple_add_tmp_var (x);
4804 TREE_ADDRESSABLE (x) = 1;
4805 x = build_fold_addr_expr_loc (clause_loc, x);
4808 else
4810 tree atmp
4811 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4812 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4813 tree al = size_int (TYPE_ALIGN (rtype));
4814 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4817 if (x)
4819 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4820 gimplify_assign (new_var, x, ilist);
4823 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4825 else if (c_kind == OMP_CLAUSE_REDUCTION
4826 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4828 if (pass == 0)
4829 continue;
4831 else if (pass != 0)
4832 continue;
4834 switch (OMP_CLAUSE_CODE (c))
4836 case OMP_CLAUSE_SHARED:
4837 /* Ignore shared directives in teams construct. */
4838 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4839 continue;
4840 /* Shared global vars are just accessed directly. */
4841 if (is_global_var (new_var))
4842 break;
4843 /* For taskloop firstprivate/lastprivate, represented
4844 as firstprivate and shared clause on the task, new_var
4845 is the firstprivate var. */
4846 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4847 break;
4848 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4849 needs to be delayed until after fixup_child_record_type so
4850 that we get the correct type during the dereference. */
4851 by_ref = use_pointer_for_field (var, ctx);
4852 x = build_receiver_ref (var, by_ref, ctx);
4853 SET_DECL_VALUE_EXPR (new_var, x);
4854 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4856 /* ??? If VAR is not passed by reference, and the variable
4857 hasn't been initialized yet, then we'll get a warning for
4858 the store into the omp_data_s structure. Ideally, we'd be
4859 able to notice this and not store anything at all, but
4860 we're generating code too early. Suppress the warning. */
4861 if (!by_ref)
4862 TREE_NO_WARNING (var) = 1;
4863 break;
4865 case OMP_CLAUSE_LASTPRIVATE:
4866 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4867 break;
4868 /* FALLTHRU */
4870 case OMP_CLAUSE_PRIVATE:
4871 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4872 x = build_outer_var_ref (var, ctx);
4873 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4875 if (is_task_ctx (ctx))
4876 x = build_receiver_ref (var, false, ctx);
4877 else
4878 x = build_outer_var_ref (var, ctx);
4880 else
4881 x = NULL;
4882 do_private:
4883 tree nx;
4884 nx = lang_hooks.decls.omp_clause_default_ctor
4885 (c, unshare_expr (new_var), x);
4886 if (is_simd)
4888 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4889 if ((TREE_ADDRESSABLE (new_var) || nx || y
4890 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4891 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4892 idx, lane, ivar, lvar))
4894 if (nx)
4895 x = lang_hooks.decls.omp_clause_default_ctor
4896 (c, unshare_expr (ivar), x);
4897 if (nx && x)
4898 gimplify_and_add (x, &llist[0]);
4899 if (y)
4901 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4902 if (y)
4904 gimple_seq tseq = NULL;
4906 dtor = y;
4907 gimplify_stmt (&dtor, &tseq);
4908 gimple_seq_add_seq (&llist[1], tseq);
4911 break;
4914 if (nx)
4915 gimplify_and_add (nx, ilist);
4916 /* FALLTHRU */
4918 do_dtor:
4919 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4920 if (x)
4922 gimple_seq tseq = NULL;
4924 dtor = x;
4925 gimplify_stmt (&dtor, &tseq);
4926 gimple_seq_add_seq (dlist, tseq);
4928 break;
4930 case OMP_CLAUSE_LINEAR:
4931 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4932 goto do_firstprivate;
4933 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4934 x = NULL;
4935 else
4936 x = build_outer_var_ref (var, ctx);
4937 goto do_private;
4939 case OMP_CLAUSE_FIRSTPRIVATE:
4940 if (is_task_ctx (ctx))
4942 if (is_reference (var) || is_variable_sized (var))
4943 goto do_dtor;
4944 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4945 ctx))
4946 || use_pointer_for_field (var, NULL))
4948 x = build_receiver_ref (var, false, ctx);
4949 SET_DECL_VALUE_EXPR (new_var, x);
4950 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4951 goto do_dtor;
4954 do_firstprivate:
4955 x = build_outer_var_ref (var, ctx);
4956 if (is_simd)
4958 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4959 && gimple_omp_for_combined_into_p (ctx->stmt))
4961 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4962 tree stept = TREE_TYPE (t);
4963 tree ct = find_omp_clause (clauses,
4964 OMP_CLAUSE__LOOPTEMP_);
4965 gcc_assert (ct);
4966 tree l = OMP_CLAUSE_DECL (ct);
4967 tree n1 = fd->loop.n1;
4968 tree step = fd->loop.step;
4969 tree itype = TREE_TYPE (l);
4970 if (POINTER_TYPE_P (itype))
4971 itype = signed_type_for (itype);
4972 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4973 if (TYPE_UNSIGNED (itype)
4974 && fd->loop.cond_code == GT_EXPR)
4975 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4976 fold_build1 (NEGATE_EXPR, itype, l),
4977 fold_build1 (NEGATE_EXPR,
4978 itype, step));
4979 else
4980 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
4981 t = fold_build2 (MULT_EXPR, stept,
4982 fold_convert (stept, l), t);
4984 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4986 x = lang_hooks.decls.omp_clause_linear_ctor
4987 (c, new_var, x, t);
4988 gimplify_and_add (x, ilist);
4989 goto do_dtor;
4992 if (POINTER_TYPE_P (TREE_TYPE (x)))
4993 x = fold_build2 (POINTER_PLUS_EXPR,
4994 TREE_TYPE (x), x, t);
4995 else
4996 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4999 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5000 || TREE_ADDRESSABLE (new_var))
5001 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5002 idx, lane, ivar, lvar))
5004 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5006 tree iv = create_tmp_var (TREE_TYPE (new_var));
5007 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5008 gimplify_and_add (x, ilist);
5009 gimple_stmt_iterator gsi
5010 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5011 gassign *g
5012 = gimple_build_assign (unshare_expr (lvar), iv);
5013 gsi_insert_before_without_update (&gsi, g,
5014 GSI_SAME_STMT);
5015 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5016 enum tree_code code = PLUS_EXPR;
5017 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5018 code = POINTER_PLUS_EXPR;
5019 g = gimple_build_assign (iv, code, iv, t);
5020 gsi_insert_before_without_update (&gsi, g,
5021 GSI_SAME_STMT);
5022 break;
5024 x = lang_hooks.decls.omp_clause_copy_ctor
5025 (c, unshare_expr (ivar), x);
5026 gimplify_and_add (x, &llist[0]);
5027 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5028 if (x)
5030 gimple_seq tseq = NULL;
5032 dtor = x;
5033 gimplify_stmt (&dtor, &tseq);
5034 gimple_seq_add_seq (&llist[1], tseq);
5036 break;
5039 x = lang_hooks.decls.omp_clause_copy_ctor
5040 (c, unshare_expr (new_var), x);
5041 gimplify_and_add (x, ilist);
5042 goto do_dtor;
5044 case OMP_CLAUSE__LOOPTEMP_:
5045 gcc_assert (is_taskreg_ctx (ctx));
5046 x = build_outer_var_ref (var, ctx);
5047 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5048 gimplify_and_add (x, ilist);
5049 break;
5051 case OMP_CLAUSE_COPYIN:
5052 by_ref = use_pointer_for_field (var, NULL);
5053 x = build_receiver_ref (var, by_ref, ctx);
5054 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5055 append_to_statement_list (x, &copyin_seq);
5056 copyin_by_ref |= by_ref;
5057 break;
5059 case OMP_CLAUSE_REDUCTION:
5060 /* OpenACC reductions are initialized using the
5061 GOACC_REDUCTION internal function. */
5062 if (is_gimple_omp_oacc (ctx->stmt))
5063 break;
5064 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5066 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5067 gimple *tseq;
5068 x = build_outer_var_ref (var, ctx);
5070 if (is_reference (var)
5071 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5072 TREE_TYPE (x)))
5073 x = build_fold_addr_expr_loc (clause_loc, x);
5074 SET_DECL_VALUE_EXPR (placeholder, x);
5075 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5076 tree new_vard = new_var;
5077 if (is_reference (var))
5079 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5080 new_vard = TREE_OPERAND (new_var, 0);
5081 gcc_assert (DECL_P (new_vard));
5083 if (is_simd
5084 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5085 idx, lane, ivar, lvar))
5087 if (new_vard == new_var)
5089 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5090 SET_DECL_VALUE_EXPR (new_var, ivar);
5092 else
5094 SET_DECL_VALUE_EXPR (new_vard,
5095 build_fold_addr_expr (ivar));
5096 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5098 x = lang_hooks.decls.omp_clause_default_ctor
5099 (c, unshare_expr (ivar),
5100 build_outer_var_ref (var, ctx));
5101 if (x)
5102 gimplify_and_add (x, &llist[0]);
5103 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5105 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5106 lower_omp (&tseq, ctx);
5107 gimple_seq_add_seq (&llist[0], tseq);
5109 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5110 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5111 lower_omp (&tseq, ctx);
5112 gimple_seq_add_seq (&llist[1], tseq);
5113 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5114 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5115 if (new_vard == new_var)
5116 SET_DECL_VALUE_EXPR (new_var, lvar);
5117 else
5118 SET_DECL_VALUE_EXPR (new_vard,
5119 build_fold_addr_expr (lvar));
5120 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5121 if (x)
5123 tseq = NULL;
5124 dtor = x;
5125 gimplify_stmt (&dtor, &tseq);
5126 gimple_seq_add_seq (&llist[1], tseq);
5128 break;
5130 /* If this is a reference to constant size reduction var
5131 with placeholder, we haven't emitted the initializer
5132 for it because it is undesirable if SIMD arrays are used.
5133 But if they aren't used, we need to emit the deferred
5134 initialization now. */
5135 else if (is_reference (var) && is_simd)
5136 handle_simd_reference (clause_loc, new_vard, ilist);
5137 x = lang_hooks.decls.omp_clause_default_ctor
5138 (c, unshare_expr (new_var),
5139 build_outer_var_ref (var, ctx));
5140 if (x)
5141 gimplify_and_add (x, ilist);
5142 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5144 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5145 lower_omp (&tseq, ctx);
5146 gimple_seq_add_seq (ilist, tseq);
5148 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5149 if (is_simd)
5151 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5152 lower_omp (&tseq, ctx);
5153 gimple_seq_add_seq (dlist, tseq);
5154 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5156 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5157 goto do_dtor;
5159 else
5161 x = omp_reduction_init (c, TREE_TYPE (new_var));
5162 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5163 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5165 /* reduction(-:var) sums up the partial results, so it
5166 acts identically to reduction(+:var). */
5167 if (code == MINUS_EXPR)
5168 code = PLUS_EXPR;
5170 tree new_vard = new_var;
5171 if (is_simd && is_reference (var))
5173 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5174 new_vard = TREE_OPERAND (new_var, 0);
5175 gcc_assert (DECL_P (new_vard));
5177 if (is_simd
5178 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5179 idx, lane, ivar, lvar))
5181 tree ref = build_outer_var_ref (var, ctx);
5183 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5185 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5186 ref = build_outer_var_ref (var, ctx);
5187 gimplify_assign (ref, x, &llist[1]);
5189 if (new_vard != new_var)
5191 SET_DECL_VALUE_EXPR (new_vard,
5192 build_fold_addr_expr (lvar));
5193 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5196 else
5198 if (is_reference (var) && is_simd)
5199 handle_simd_reference (clause_loc, new_vard, ilist);
5200 gimplify_assign (new_var, x, ilist);
5201 if (is_simd)
5203 tree ref = build_outer_var_ref (var, ctx);
5205 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5206 ref = build_outer_var_ref (var, ctx);
5207 gimplify_assign (ref, x, dlist);
5211 break;
5213 default:
5214 gcc_unreachable ();
5219 if (lane)
5221 tree uid = create_tmp_var (ptr_type_node, "simduid");
5222 /* Don't want uninit warnings on simduid, it is always uninitialized,
5223 but we use it not for the value, but for the DECL_UID only. */
5224 TREE_NO_WARNING (uid) = 1;
5225 gimple *g
5226 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5227 gimple_call_set_lhs (g, lane);
5228 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5229 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5230 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5231 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5232 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5233 gimple_omp_for_set_clauses (ctx->stmt, c);
5234 g = gimple_build_assign (lane, INTEGER_CST,
5235 build_int_cst (unsigned_type_node, 0));
5236 gimple_seq_add_stmt (ilist, g);
5237 for (int i = 0; i < 2; i++)
5238 if (llist[i])
5240 tree vf = create_tmp_var (unsigned_type_node);
5241 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5242 gimple_call_set_lhs (g, vf);
5243 gimple_seq *seq = i == 0 ? ilist : dlist;
5244 gimple_seq_add_stmt (seq, g);
5245 tree t = build_int_cst (unsigned_type_node, 0);
5246 g = gimple_build_assign (idx, INTEGER_CST, t);
5247 gimple_seq_add_stmt (seq, g);
5248 tree body = create_artificial_label (UNKNOWN_LOCATION);
5249 tree header = create_artificial_label (UNKNOWN_LOCATION);
5250 tree end = create_artificial_label (UNKNOWN_LOCATION);
5251 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5252 gimple_seq_add_stmt (seq, gimple_build_label (body));
5253 gimple_seq_add_seq (seq, llist[i]);
5254 t = build_int_cst (unsigned_type_node, 1);
5255 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5256 gimple_seq_add_stmt (seq, g);
5257 gimple_seq_add_stmt (seq, gimple_build_label (header));
5258 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5259 gimple_seq_add_stmt (seq, g);
5260 gimple_seq_add_stmt (seq, gimple_build_label (end));
5264 /* The copyin sequence is not to be executed by the main thread, since
5265 that would result in self-copies. Perhaps not visible to scalars,
5266 but it certainly is to C++ operator=. */
5267 if (copyin_seq)
5269 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5271 x = build2 (NE_EXPR, boolean_type_node, x,
5272 build_int_cst (TREE_TYPE (x), 0));
5273 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5274 gimplify_and_add (x, ilist);
5277 /* If any copyin variable is passed by reference, we must ensure the
5278 master thread doesn't modify it before it is copied over in all
5279 threads. Similarly for variables in both firstprivate and
5280 lastprivate clauses we need to ensure the lastprivate copying
5281 happens after firstprivate copying in all threads. And similarly
5282 for UDRs if initializer expression refers to omp_orig. */
5283 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5285 /* Don't add any barrier for #pragma omp simd or
5286 #pragma omp distribute. */
5287 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5288 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5289 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5292 /* If max_vf is non-zero, then we can use only a vectorization factor
5293 up to the max_vf we chose. So stick it into the safelen clause. */
5294 if (max_vf)
5296 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5297 OMP_CLAUSE_SAFELEN);
5298 if (c == NULL_TREE
5299 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5300 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5301 max_vf) == 1))
5303 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5304 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5305 max_vf);
5306 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5307 gimple_omp_for_set_clauses (ctx->stmt, c);
5313 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5314 both parallel and workshare constructs. PREDICATE may be NULL if it's
5315 always true. */
5317 static void
5318 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5319 omp_context *ctx)
5321 tree x, c, label = NULL, orig_clauses = clauses;
5322 bool par_clauses = false;
5323 tree simduid = NULL, lastlane = NULL;
5325 /* Early exit if there are no lastprivate or linear clauses. */
5326 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5327 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5328 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5329 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5330 break;
5331 if (clauses == NULL)
5333 /* If this was a workshare clause, see if it had been combined
5334 with its parallel. In that case, look for the clauses on the
5335 parallel statement itself. */
5336 if (is_parallel_ctx (ctx))
5337 return;
5339 ctx = ctx->outer;
5340 if (ctx == NULL || !is_parallel_ctx (ctx))
5341 return;
5343 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5344 OMP_CLAUSE_LASTPRIVATE);
5345 if (clauses == NULL)
5346 return;
5347 par_clauses = true;
5350 if (predicate)
5352 gcond *stmt;
5353 tree label_true, arm1, arm2;
5355 label = create_artificial_label (UNKNOWN_LOCATION);
5356 label_true = create_artificial_label (UNKNOWN_LOCATION);
5357 arm1 = TREE_OPERAND (predicate, 0);
5358 arm2 = TREE_OPERAND (predicate, 1);
5359 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5360 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5361 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5362 label_true, label);
5363 gimple_seq_add_stmt (stmt_list, stmt);
5364 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5367 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5368 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5370 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5371 if (simduid)
5372 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5375 for (c = clauses; c ;)
5377 tree var, new_var;
5378 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5380 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5381 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5382 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5384 var = OMP_CLAUSE_DECL (c);
5385 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5386 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5387 && is_taskloop_ctx (ctx))
5389 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5390 new_var = lookup_decl (var, ctx->outer);
5392 else
5393 new_var = lookup_decl (var, ctx);
5395 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5397 tree val = DECL_VALUE_EXPR (new_var);
5398 if (TREE_CODE (val) == ARRAY_REF
5399 && VAR_P (TREE_OPERAND (val, 0))
5400 && lookup_attribute ("omp simd array",
5401 DECL_ATTRIBUTES (TREE_OPERAND (val,
5402 0))))
5404 if (lastlane == NULL)
5406 lastlane = create_tmp_var (unsigned_type_node);
5407 gcall *g
5408 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5409 2, simduid,
5410 TREE_OPERAND (val, 1));
5411 gimple_call_set_lhs (g, lastlane);
5412 gimple_seq_add_stmt (stmt_list, g);
5414 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5415 TREE_OPERAND (val, 0), lastlane,
5416 NULL_TREE, NULL_TREE);
5420 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5421 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5423 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5424 gimple_seq_add_seq (stmt_list,
5425 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5426 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5428 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5429 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5431 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5432 gimple_seq_add_seq (stmt_list,
5433 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5434 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5437 x = NULL_TREE;
5438 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5439 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5441 gcc_checking_assert (is_taskloop_ctx (ctx));
5442 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5443 ctx->outer->outer);
5444 if (is_global_var (ovar))
5445 x = ovar;
5447 if (!x)
5448 x = build_outer_var_ref (var, ctx, true);
5449 if (is_reference (var))
5450 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5451 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5452 gimplify_and_add (x, stmt_list);
5454 c = OMP_CLAUSE_CHAIN (c);
5455 if (c == NULL && !par_clauses)
5457 /* If this was a workshare clause, see if it had been combined
5458 with its parallel. In that case, continue looking for the
5459 clauses also on the parallel statement itself. */
5460 if (is_parallel_ctx (ctx))
5461 break;
5463 ctx = ctx->outer;
5464 if (ctx == NULL || !is_parallel_ctx (ctx))
5465 break;
5467 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5468 OMP_CLAUSE_LASTPRIVATE);
5469 par_clauses = true;
5473 if (label)
5474 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5477 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5478 (which might be a placeholder). INNER is true if this is an inner
5479 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5480 join markers. Generate the before-loop forking sequence in
5481 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5482 general form of these sequences is
5484 GOACC_REDUCTION_SETUP
5485 GOACC_FORK
5486 GOACC_REDUCTION_INIT
5488 GOACC_REDUCTION_FINI
5489 GOACC_JOIN
5490 GOACC_REDUCTION_TEARDOWN. */
5492 static void
5493 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5494 gcall *fork, gcall *join, gimple_seq *fork_seq,
5495 gimple_seq *join_seq, omp_context *ctx)
5497 gimple_seq before_fork = NULL;
5498 gimple_seq after_fork = NULL;
5499 gimple_seq before_join = NULL;
5500 gimple_seq after_join = NULL;
5501 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5502 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5503 unsigned offset = 0;
5505 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5506 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5508 tree orig = OMP_CLAUSE_DECL (c);
5509 tree var = maybe_lookup_decl (orig, ctx);
5510 tree ref_to_res = NULL_TREE;
5511 tree incoming, outgoing;
5513 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5514 if (rcode == MINUS_EXPR)
5515 rcode = PLUS_EXPR;
5516 else if (rcode == TRUTH_ANDIF_EXPR)
5517 rcode = BIT_AND_EXPR;
5518 else if (rcode == TRUTH_ORIF_EXPR)
5519 rcode = BIT_IOR_EXPR;
5520 tree op = build_int_cst (unsigned_type_node, rcode);
5522 if (!var)
5523 var = orig;
5524 gcc_assert (!is_reference (var));
5526 incoming = outgoing = var;
5528 if (!inner)
5530 /* See if an outer construct also reduces this variable. */
5531 omp_context *outer = ctx;
5533 while (omp_context *probe = outer->outer)
5535 enum gimple_code type = gimple_code (probe->stmt);
5536 tree cls;
5538 switch (type)
5540 case GIMPLE_OMP_FOR:
5541 cls = gimple_omp_for_clauses (probe->stmt);
5542 break;
5544 case GIMPLE_OMP_TARGET:
5545 if (gimple_omp_target_kind (probe->stmt)
5546 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5547 goto do_lookup;
5549 cls = gimple_omp_target_clauses (probe->stmt);
5550 break;
5552 default:
5553 goto do_lookup;
5556 outer = probe;
5557 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5558 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5559 && orig == OMP_CLAUSE_DECL (cls))
5560 goto has_outer_reduction;
5563 do_lookup:
5564 /* This is the outermost construct with this reduction,
5565 see if there's a mapping for it. */
5566 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5567 && maybe_lookup_field (orig, outer))
5569 ref_to_res = build_receiver_ref (orig, false, outer);
5570 if (is_reference (orig))
5571 ref_to_res = build_simple_mem_ref (ref_to_res);
5573 outgoing = var;
5574 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5576 else
5577 incoming = outgoing = orig;
5579 has_outer_reduction:;
5582 if (!ref_to_res)
5583 ref_to_res = integer_zero_node;
5585 /* Determine position in reduction buffer, which may be used
5586 by target. */
5587 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5588 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5589 offset = (offset + align - 1) & ~(align - 1);
5590 tree off = build_int_cst (sizetype, offset);
5591 offset += GET_MODE_SIZE (mode);
5593 if (!init_code)
5595 init_code = build_int_cst (integer_type_node,
5596 IFN_GOACC_REDUCTION_INIT);
5597 fini_code = build_int_cst (integer_type_node,
5598 IFN_GOACC_REDUCTION_FINI);
5599 setup_code = build_int_cst (integer_type_node,
5600 IFN_GOACC_REDUCTION_SETUP);
5601 teardown_code = build_int_cst (integer_type_node,
5602 IFN_GOACC_REDUCTION_TEARDOWN);
5605 tree setup_call
5606 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5607 TREE_TYPE (var), 6, setup_code,
5608 unshare_expr (ref_to_res),
5609 incoming, level, op, off);
5610 tree init_call
5611 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5612 TREE_TYPE (var), 6, init_code,
5613 unshare_expr (ref_to_res),
5614 var, level, op, off);
5615 tree fini_call
5616 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5617 TREE_TYPE (var), 6, fini_code,
5618 unshare_expr (ref_to_res),
5619 var, level, op, off);
5620 tree teardown_call
5621 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5622 TREE_TYPE (var), 6, teardown_code,
5623 ref_to_res, var, level, op, off);
5625 gimplify_assign (var, setup_call, &before_fork);
5626 gimplify_assign (var, init_call, &after_fork);
5627 gimplify_assign (var, fini_call, &before_join);
5628 gimplify_assign (outgoing, teardown_call, &after_join);
5631 /* Now stitch things together. */
5632 gimple_seq_add_seq (fork_seq, before_fork);
5633 if (fork)
5634 gimple_seq_add_stmt (fork_seq, fork);
5635 gimple_seq_add_seq (fork_seq, after_fork);
5637 gimple_seq_add_seq (join_seq, before_join);
5638 if (join)
5639 gimple_seq_add_stmt (join_seq, join);
5640 gimple_seq_add_seq (join_seq, after_join);
5643 /* Generate code to implement the REDUCTION clauses. */
5645 static void
5646 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5648 gimple_seq sub_seq = NULL;
5649 gimple *stmt;
5650 tree x, c;
5651 int count = 0;
5653 /* OpenACC loop reductions are handled elsewhere. */
5654 if (is_gimple_omp_oacc (ctx->stmt))
5655 return;
5657 /* SIMD reductions are handled in lower_rec_input_clauses. */
5658 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5659 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5660 return;
5662 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5663 update in that case, otherwise use a lock. */
5664 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5665 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5667 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5668 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5670 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5671 count = -1;
5672 break;
5674 count++;
5677 if (count == 0)
5678 return;
5680 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5682 tree var, ref, new_var, orig_var;
5683 enum tree_code code;
5684 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5686 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5687 continue;
5689 orig_var = var = OMP_CLAUSE_DECL (c);
5690 if (TREE_CODE (var) == MEM_REF)
5692 var = TREE_OPERAND (var, 0);
5693 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5694 var = TREE_OPERAND (var, 0);
5695 if (TREE_CODE (var) == INDIRECT_REF
5696 || TREE_CODE (var) == ADDR_EXPR)
5697 var = TREE_OPERAND (var, 0);
5698 orig_var = var;
5699 if (is_variable_sized (var))
5701 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5702 var = DECL_VALUE_EXPR (var);
5703 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5704 var = TREE_OPERAND (var, 0);
5705 gcc_assert (DECL_P (var));
5708 new_var = lookup_decl (var, ctx);
5709 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5710 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5711 ref = build_outer_var_ref (var, ctx);
5712 code = OMP_CLAUSE_REDUCTION_CODE (c);
5714 /* reduction(-:var) sums up the partial results, so it acts
5715 identically to reduction(+:var). */
5716 if (code == MINUS_EXPR)
5717 code = PLUS_EXPR;
5719 if (count == 1)
5721 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5723 addr = save_expr (addr);
5724 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5725 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5726 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5727 gimplify_and_add (x, stmt_seqp);
5728 return;
5730 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5732 tree d = OMP_CLAUSE_DECL (c);
5733 tree type = TREE_TYPE (d);
5734 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5735 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5736 tree ptype = build_pointer_type (TREE_TYPE (type));
5737 tree bias = TREE_OPERAND (d, 1);
5738 d = TREE_OPERAND (d, 0);
5739 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5741 tree b = TREE_OPERAND (d, 1);
5742 b = maybe_lookup_decl (b, ctx);
5743 if (b == NULL)
5745 b = TREE_OPERAND (d, 1);
5746 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5748 if (integer_zerop (bias))
5749 bias = b;
5750 else
5752 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5753 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5754 TREE_TYPE (b), b, bias);
5756 d = TREE_OPERAND (d, 0);
5758 /* For ref build_outer_var_ref already performs this, so
5759 only new_var needs a dereference. */
5760 if (TREE_CODE (d) == INDIRECT_REF)
5762 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5763 gcc_assert (is_reference (var) && var == orig_var);
5765 else if (TREE_CODE (d) == ADDR_EXPR)
5767 if (orig_var == var)
5769 new_var = build_fold_addr_expr (new_var);
5770 ref = build_fold_addr_expr (ref);
5773 else
5775 gcc_assert (orig_var == var);
5776 if (is_reference (var))
5777 ref = build_fold_addr_expr (ref);
5779 if (DECL_P (v))
5781 tree t = maybe_lookup_decl (v, ctx);
5782 if (t)
5783 v = t;
5784 else
5785 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5786 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5788 if (!integer_zerop (bias))
5790 bias = fold_convert_loc (clause_loc, sizetype, bias);
5791 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5792 TREE_TYPE (new_var), new_var,
5793 unshare_expr (bias));
5794 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5795 TREE_TYPE (ref), ref, bias);
5797 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5798 ref = fold_convert_loc (clause_loc, ptype, ref);
5799 tree m = create_tmp_var (ptype, NULL);
5800 gimplify_assign (m, new_var, stmt_seqp);
5801 new_var = m;
5802 m = create_tmp_var (ptype, NULL);
5803 gimplify_assign (m, ref, stmt_seqp);
5804 ref = m;
5805 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5806 tree body = create_artificial_label (UNKNOWN_LOCATION);
5807 tree end = create_artificial_label (UNKNOWN_LOCATION);
5808 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5809 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5810 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5811 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5813 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5814 tree decl_placeholder
5815 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5816 SET_DECL_VALUE_EXPR (placeholder, out);
5817 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5818 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5819 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5820 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5821 gimple_seq_add_seq (&sub_seq,
5822 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5823 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5824 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5825 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5827 else
5829 x = build2 (code, TREE_TYPE (out), out, priv);
5830 out = unshare_expr (out);
5831 gimplify_assign (out, x, &sub_seq);
5833 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5834 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5835 gimple_seq_add_stmt (&sub_seq, g);
5836 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5837 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5838 gimple_seq_add_stmt (&sub_seq, g);
5839 g = gimple_build_assign (i, PLUS_EXPR, i,
5840 build_int_cst (TREE_TYPE (i), 1));
5841 gimple_seq_add_stmt (&sub_seq, g);
5842 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5843 gimple_seq_add_stmt (&sub_seq, g);
5844 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5846 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5848 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5850 if (is_reference (var)
5851 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5852 TREE_TYPE (ref)))
5853 ref = build_fold_addr_expr_loc (clause_loc, ref);
5854 SET_DECL_VALUE_EXPR (placeholder, ref);
5855 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5856 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5857 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5858 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5859 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5861 else
5863 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5864 ref = build_outer_var_ref (var, ctx);
5865 gimplify_assign (ref, x, &sub_seq);
5869 if (is_gimple_omp_oacc (ctx->stmt))
5870 return;
5872 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5874 gimple_seq_add_stmt (stmt_seqp, stmt);
5876 gimple_seq_add_seq (stmt_seqp, sub_seq);
5878 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5880 gimple_seq_add_stmt (stmt_seqp, stmt);
5884 /* Generate code to implement the COPYPRIVATE clauses. */
5886 static void
5887 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5888 omp_context *ctx)
5890 tree c;
5892 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5894 tree var, new_var, ref, x;
5895 bool by_ref;
5896 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5898 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
5899 continue;
5901 var = OMP_CLAUSE_DECL (c);
5902 by_ref = use_pointer_for_field (var, NULL);
5904 ref = build_sender_ref (var, ctx);
5905 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5906 if (by_ref)
5908 x = build_fold_addr_expr_loc (clause_loc, new_var);
5909 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5911 gimplify_assign (ref, x, slist);
5913 ref = build_receiver_ref (var, false, ctx);
5914 if (by_ref)
5916 ref = fold_convert_loc (clause_loc,
5917 build_pointer_type (TREE_TYPE (new_var)),
5918 ref);
5919 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5921 if (is_reference (var))
5923 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
5924 ref = build_simple_mem_ref_loc (clause_loc, ref);
5925 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5927 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
5928 gimplify_and_add (x, rlist);
5933 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5934 and REDUCTION from the sender (aka parent) side. */
5936 static void
5937 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5938 omp_context *ctx)
5940 tree c, t;
5941 int ignored_looptemp = 0;
5942 bool is_taskloop = false;
5944 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5945 by GOMP_taskloop. */
5946 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5948 ignored_looptemp = 2;
5949 is_taskloop = true;
5952 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5954 tree val, ref, x, var;
5955 bool by_ref, do_in = false, do_out = false;
5956 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5958 switch (OMP_CLAUSE_CODE (c))
5960 case OMP_CLAUSE_PRIVATE:
5961 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5962 break;
5963 continue;
5964 case OMP_CLAUSE_FIRSTPRIVATE:
5965 case OMP_CLAUSE_COPYIN:
5966 case OMP_CLAUSE_LASTPRIVATE:
5967 case OMP_CLAUSE_REDUCTION:
5968 break;
5969 case OMP_CLAUSE_SHARED:
5970 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5971 break;
5972 continue;
5973 case OMP_CLAUSE__LOOPTEMP_:
5974 if (ignored_looptemp)
5976 ignored_looptemp--;
5977 continue;
5979 break;
5980 default:
5981 continue;
5984 val = OMP_CLAUSE_DECL (c);
5985 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5986 && TREE_CODE (val) == MEM_REF)
5988 val = TREE_OPERAND (val, 0);
5989 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
5990 val = TREE_OPERAND (val, 0);
5991 if (TREE_CODE (val) == INDIRECT_REF
5992 || TREE_CODE (val) == ADDR_EXPR)
5993 val = TREE_OPERAND (val, 0);
5994 if (is_variable_sized (val))
5995 continue;
5998 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5999 outer taskloop region. */
6000 omp_context *ctx_for_o = ctx;
6001 if (is_taskloop
6002 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6003 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6004 ctx_for_o = ctx->outer;
6006 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6008 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6009 && is_global_var (var))
6010 continue;
6012 t = omp_member_access_dummy_var (var);
6013 if (t)
6015 var = DECL_VALUE_EXPR (var);
6016 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6017 if (o != t)
6018 var = unshare_and_remap (var, t, o);
6019 else
6020 var = unshare_expr (var);
6023 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6025 /* Handle taskloop firstprivate/lastprivate, where the
6026 lastprivate on GIMPLE_OMP_TASK is represented as
6027 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6028 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6029 x = omp_build_component_ref (ctx->sender_decl, f);
6030 if (use_pointer_for_field (val, ctx))
6031 var = build_fold_addr_expr (var);
6032 gimplify_assign (x, var, ilist);
6033 DECL_ABSTRACT_ORIGIN (f) = NULL;
6034 continue;
6037 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6038 || val == OMP_CLAUSE_DECL (c))
6039 && is_variable_sized (val))
6040 continue;
6041 by_ref = use_pointer_for_field (val, NULL);
6043 switch (OMP_CLAUSE_CODE (c))
6045 case OMP_CLAUSE_PRIVATE:
6046 case OMP_CLAUSE_FIRSTPRIVATE:
6047 case OMP_CLAUSE_COPYIN:
6048 case OMP_CLAUSE__LOOPTEMP_:
6049 do_in = true;
6050 break;
6052 case OMP_CLAUSE_LASTPRIVATE:
6053 if (by_ref || is_reference (val))
6055 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6056 continue;
6057 do_in = true;
6059 else
6061 do_out = true;
6062 if (lang_hooks.decls.omp_private_outer_ref (val))
6063 do_in = true;
6065 break;
6067 case OMP_CLAUSE_REDUCTION:
6068 do_in = true;
6069 if (val == OMP_CLAUSE_DECL (c))
6070 do_out = !(by_ref || is_reference (val));
6071 else
6072 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6073 break;
6075 default:
6076 gcc_unreachable ();
6079 if (do_in)
6081 ref = build_sender_ref (val, ctx);
6082 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6083 gimplify_assign (ref, x, ilist);
6084 if (is_task_ctx (ctx))
6085 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6088 if (do_out)
6090 ref = build_sender_ref (val, ctx);
6091 gimplify_assign (var, ref, olist);
6096 /* Generate code to implement SHARED from the sender (aka parent)
6097 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6098 list things that got automatically shared. */
6100 static void
6101 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6103 tree var, ovar, nvar, t, f, x, record_type;
6105 if (ctx->record_type == NULL)
6106 return;
6108 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6109 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6111 ovar = DECL_ABSTRACT_ORIGIN (f);
6112 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6113 continue;
6115 nvar = maybe_lookup_decl (ovar, ctx);
6116 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6117 continue;
6119 /* If CTX is a nested parallel directive. Find the immediately
6120 enclosing parallel or workshare construct that contains a
6121 mapping for OVAR. */
6122 var = lookup_decl_in_outer_ctx (ovar, ctx);
6124 t = omp_member_access_dummy_var (var);
6125 if (t)
6127 var = DECL_VALUE_EXPR (var);
6128 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6129 if (o != t)
6130 var = unshare_and_remap (var, t, o);
6131 else
6132 var = unshare_expr (var);
6135 if (use_pointer_for_field (ovar, ctx))
6137 x = build_sender_ref (ovar, ctx);
6138 var = build_fold_addr_expr (var);
6139 gimplify_assign (x, var, ilist);
6141 else
6143 x = build_sender_ref (ovar, ctx);
6144 gimplify_assign (x, var, ilist);
6146 if (!TREE_READONLY (var)
6147 /* We don't need to receive a new reference to a result
6148 or parm decl. In fact we may not store to it as we will
6149 invalidate any pending RSO and generate wrong gimple
6150 during inlining. */
6151 && !((TREE_CODE (var) == RESULT_DECL
6152 || TREE_CODE (var) == PARM_DECL)
6153 && DECL_BY_REFERENCE (var)))
6155 x = build_sender_ref (ovar, ctx);
6156 gimplify_assign (var, x, olist);
6162 /* Emit an OpenACC head marker call, encapulating the partitioning and
6163 other information that must be processed by the target compiler.
6164 Return the maximum number of dimensions the associated loop might
6165 be partitioned over. */
6167 static unsigned
6168 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6169 gimple_seq *seq, omp_context *ctx)
6171 unsigned levels = 0;
6172 unsigned tag = 0;
6173 tree gang_static = NULL_TREE;
6174 auto_vec<tree, 5> args;
6176 args.quick_push (build_int_cst
6177 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6178 args.quick_push (ddvar);
6179 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6181 switch (OMP_CLAUSE_CODE (c))
6183 case OMP_CLAUSE_GANG:
6184 tag |= OLF_DIM_GANG;
6185 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6186 /* static:* is represented by -1, and we can ignore it, as
6187 scheduling is always static. */
6188 if (gang_static && integer_minus_onep (gang_static))
6189 gang_static = NULL_TREE;
6190 levels++;
6191 break;
6193 case OMP_CLAUSE_WORKER:
6194 tag |= OLF_DIM_WORKER;
6195 levels++;
6196 break;
6198 case OMP_CLAUSE_VECTOR:
6199 tag |= OLF_DIM_VECTOR;
6200 levels++;
6201 break;
6203 case OMP_CLAUSE_SEQ:
6204 tag |= OLF_SEQ;
6205 break;
6207 case OMP_CLAUSE_AUTO:
6208 tag |= OLF_AUTO;
6209 break;
6211 case OMP_CLAUSE_INDEPENDENT:
6212 tag |= OLF_INDEPENDENT;
6213 break;
6215 default:
6216 continue;
6220 if (gang_static)
6222 if (DECL_P (gang_static))
6223 gang_static = build_outer_var_ref (gang_static, ctx);
6224 tag |= OLF_GANG_STATIC;
6227 /* In a parallel region, loops are implicitly INDEPENDENT. */
6228 omp_context *tgt = enclosing_target_ctx (ctx);
6229 if (!tgt || is_oacc_parallel (tgt))
6230 tag |= OLF_INDEPENDENT;
6232 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6233 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6234 | OLF_SEQ)))
6235 tag |= OLF_AUTO;
6237 /* Ensure at least one level. */
6238 if (!levels)
6239 levels++;
6241 args.quick_push (build_int_cst (integer_type_node, levels));
6242 args.quick_push (build_int_cst (integer_type_node, tag));
6243 if (gang_static)
6244 args.quick_push (gang_static);
6246 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6247 gimple_set_location (call, loc);
6248 gimple_set_lhs (call, ddvar);
6249 gimple_seq_add_stmt (seq, call);
6251 return levels;
6254 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6255 partitioning level of the enclosed region. */
6257 static void
6258 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6259 tree tofollow, gimple_seq *seq)
6261 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6262 : IFN_UNIQUE_OACC_TAIL_MARK);
6263 tree marker = build_int_cst (integer_type_node, marker_kind);
6264 int nargs = 2 + (tofollow != NULL_TREE);
6265 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6266 marker, ddvar, tofollow);
6267 gimple_set_location (call, loc);
6268 gimple_set_lhs (call, ddvar);
6269 gimple_seq_add_stmt (seq, call);
6272 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6273 the loop clauses, from which we extract reductions. Initialize
6274 HEAD and TAIL. */
6276 static void
6277 lower_oacc_head_tail (location_t loc, tree clauses,
6278 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6280 bool inner = false;
6281 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6282 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6284 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6285 if (!count)
6286 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6288 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6289 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6291 for (unsigned done = 1; count; count--, done++)
6293 gimple_seq fork_seq = NULL;
6294 gimple_seq join_seq = NULL;
6296 tree place = build_int_cst (integer_type_node, -1);
6297 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6298 fork_kind, ddvar, place);
6299 gimple_set_location (fork, loc);
6300 gimple_set_lhs (fork, ddvar);
6302 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6303 join_kind, ddvar, place);
6304 gimple_set_location (join, loc);
6305 gimple_set_lhs (join, ddvar);
6307 /* Mark the beginning of this level sequence. */
6308 if (inner)
6309 lower_oacc_loop_marker (loc, ddvar, true,
6310 build_int_cst (integer_type_node, count),
6311 &fork_seq);
6312 lower_oacc_loop_marker (loc, ddvar, false,
6313 build_int_cst (integer_type_node, done),
6314 &join_seq);
6316 lower_oacc_reductions (loc, clauses, place, inner,
6317 fork, join, &fork_seq, &join_seq, ctx);
6319 /* Append this level to head. */
6320 gimple_seq_add_seq (head, fork_seq);
6321 /* Prepend it to tail. */
6322 gimple_seq_add_seq (&join_seq, *tail);
6323 *tail = join_seq;
6325 inner = true;
6328 /* Mark the end of the sequence. */
6329 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6330 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6333 /* A convenience function to build an empty GIMPLE_COND with just the
6334 condition. */
6336 static gcond *
6337 gimple_build_cond_empty (tree cond)
6339 enum tree_code pred_code;
6340 tree lhs, rhs;
6342 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6343 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6346 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6347 bool = false);
6349 /* Build the function calls to GOMP_parallel_start etc to actually
6350 generate the parallel operation. REGION is the parallel region
6351 being expanded. BB is the block where to insert the code. WS_ARGS
6352 will be set if this is a call to a combined parallel+workshare
6353 construct, it contains the list of additional arguments needed by
6354 the workshare construct. */
6356 static void
6357 expand_parallel_call (struct omp_region *region, basic_block bb,
6358 gomp_parallel *entry_stmt,
6359 vec<tree, va_gc> *ws_args)
6361 tree t, t1, t2, val, cond, c, clauses, flags;
6362 gimple_stmt_iterator gsi;
6363 gimple *stmt;
6364 enum built_in_function start_ix;
6365 int start_ix2;
6366 location_t clause_loc;
6367 vec<tree, va_gc> *args;
6369 clauses = gimple_omp_parallel_clauses (entry_stmt);
6371 /* Determine what flavor of GOMP_parallel we will be
6372 emitting. */
6373 start_ix = BUILT_IN_GOMP_PARALLEL;
6374 if (is_combined_parallel (region))
6376 switch (region->inner->type)
6378 case GIMPLE_OMP_FOR:
6379 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6380 switch (region->inner->sched_kind)
6382 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6383 start_ix2 = 3;
6384 break;
6385 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6386 case OMP_CLAUSE_SCHEDULE_GUIDED:
6387 if (region->inner->sched_modifiers
6388 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6390 start_ix2 = 3 + region->inner->sched_kind;
6391 break;
6393 /* FALLTHRU */
6394 default:
6395 start_ix2 = region->inner->sched_kind;
6396 break;
6398 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6399 start_ix = (enum built_in_function) start_ix2;
6400 break;
6401 case GIMPLE_OMP_SECTIONS:
6402 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6403 break;
6404 default:
6405 gcc_unreachable ();
6409 /* By default, the value of NUM_THREADS is zero (selected at run time)
6410 and there is no conditional. */
6411 cond = NULL_TREE;
6412 val = build_int_cst (unsigned_type_node, 0);
6413 flags = build_int_cst (unsigned_type_node, 0);
6415 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6416 if (c)
6417 cond = OMP_CLAUSE_IF_EXPR (c);
6419 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6420 if (c)
6422 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6423 clause_loc = OMP_CLAUSE_LOCATION (c);
6425 else
6426 clause_loc = gimple_location (entry_stmt);
6428 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6429 if (c)
6430 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6432 /* Ensure 'val' is of the correct type. */
6433 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6435 /* If we found the clause 'if (cond)', build either
6436 (cond != 0) or (cond ? val : 1u). */
6437 if (cond)
6439 cond = gimple_boolify (cond);
6441 if (integer_zerop (val))
6442 val = fold_build2_loc (clause_loc,
6443 EQ_EXPR, unsigned_type_node, cond,
6444 build_int_cst (TREE_TYPE (cond), 0));
6445 else
6447 basic_block cond_bb, then_bb, else_bb;
6448 edge e, e_then, e_else;
6449 tree tmp_then, tmp_else, tmp_join, tmp_var;
6451 tmp_var = create_tmp_var (TREE_TYPE (val));
6452 if (gimple_in_ssa_p (cfun))
6454 tmp_then = make_ssa_name (tmp_var);
6455 tmp_else = make_ssa_name (tmp_var);
6456 tmp_join = make_ssa_name (tmp_var);
6458 else
6460 tmp_then = tmp_var;
6461 tmp_else = tmp_var;
6462 tmp_join = tmp_var;
6465 e = split_block_after_labels (bb);
6466 cond_bb = e->src;
6467 bb = e->dest;
6468 remove_edge (e);
6470 then_bb = create_empty_bb (cond_bb);
6471 else_bb = create_empty_bb (then_bb);
6472 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6473 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6475 stmt = gimple_build_cond_empty (cond);
6476 gsi = gsi_start_bb (cond_bb);
6477 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6479 gsi = gsi_start_bb (then_bb);
6480 expand_omp_build_assign (&gsi, tmp_then, val, true);
6482 gsi = gsi_start_bb (else_bb);
6483 expand_omp_build_assign (&gsi, tmp_else,
6484 build_int_cst (unsigned_type_node, 1),
6485 true);
6487 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6488 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6489 add_bb_to_loop (then_bb, cond_bb->loop_father);
6490 add_bb_to_loop (else_bb, cond_bb->loop_father);
6491 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6492 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6494 if (gimple_in_ssa_p (cfun))
6496 gphi *phi = create_phi_node (tmp_join, bb);
6497 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6498 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6501 val = tmp_join;
6504 gsi = gsi_start_bb (bb);
6505 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6506 false, GSI_CONTINUE_LINKING);
6509 gsi = gsi_last_bb (bb);
6510 t = gimple_omp_parallel_data_arg (entry_stmt);
6511 if (t == NULL)
6512 t1 = null_pointer_node;
6513 else
6514 t1 = build_fold_addr_expr (t);
6515 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6517 vec_alloc (args, 4 + vec_safe_length (ws_args));
6518 args->quick_push (t2);
6519 args->quick_push (t1);
6520 args->quick_push (val);
6521 if (ws_args)
6522 args->splice (*ws_args);
6523 args->quick_push (flags);
6525 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6526 builtin_decl_explicit (start_ix), args);
6528 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6529 false, GSI_CONTINUE_LINKING);
6532 /* Insert a function call whose name is FUNC_NAME with the information from
6533 ENTRY_STMT into the basic_block BB. */
6535 static void
6536 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6537 vec <tree, va_gc> *ws_args)
6539 tree t, t1, t2;
6540 gimple_stmt_iterator gsi;
6541 vec <tree, va_gc> *args;
6543 gcc_assert (vec_safe_length (ws_args) == 2);
6544 tree func_name = (*ws_args)[0];
6545 tree grain = (*ws_args)[1];
6547 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6548 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6549 gcc_assert (count != NULL_TREE);
6550 count = OMP_CLAUSE_OPERAND (count, 0);
6552 gsi = gsi_last_bb (bb);
6553 t = gimple_omp_parallel_data_arg (entry_stmt);
6554 if (t == NULL)
6555 t1 = null_pointer_node;
6556 else
6557 t1 = build_fold_addr_expr (t);
6558 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6560 vec_alloc (args, 4);
6561 args->quick_push (t2);
6562 args->quick_push (t1);
6563 args->quick_push (count);
6564 args->quick_push (grain);
6565 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6567 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6568 GSI_CONTINUE_LINKING);
6571 /* Build the function call to GOMP_task to actually
6572 generate the task operation. BB is the block where to insert the code. */
6574 static void
6575 expand_task_call (struct omp_region *region, basic_block bb,
6576 gomp_task *entry_stmt)
6578 tree t1, t2, t3;
6579 gimple_stmt_iterator gsi;
6580 location_t loc = gimple_location (entry_stmt);
6582 tree clauses = gimple_omp_task_clauses (entry_stmt);
6584 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6585 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6586 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6587 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6588 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6589 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6591 unsigned int iflags
6592 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6593 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6594 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6596 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6597 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6598 tree num_tasks = NULL_TREE;
6599 bool ull = false;
6600 if (taskloop_p)
6602 gimple *g = last_stmt (region->outer->entry);
6603 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6604 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6605 struct omp_for_data fd;
6606 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6607 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6608 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6609 OMP_CLAUSE__LOOPTEMP_);
6610 startvar = OMP_CLAUSE_DECL (startvar);
6611 endvar = OMP_CLAUSE_DECL (endvar);
6612 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6613 if (fd.loop.cond_code == LT_EXPR)
6614 iflags |= GOMP_TASK_FLAG_UP;
6615 tree tclauses = gimple_omp_for_clauses (g);
6616 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6617 if (num_tasks)
6618 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6619 else
6621 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6622 if (num_tasks)
6624 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6625 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6627 else
6628 num_tasks = integer_zero_node;
6630 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6631 if (ifc == NULL_TREE)
6632 iflags |= GOMP_TASK_FLAG_IF;
6633 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6634 iflags |= GOMP_TASK_FLAG_NOGROUP;
6635 ull = fd.iter_type == long_long_unsigned_type_node;
6637 else if (priority)
6638 iflags |= GOMP_TASK_FLAG_PRIORITY;
6640 tree flags = build_int_cst (unsigned_type_node, iflags);
6642 tree cond = boolean_true_node;
6643 if (ifc)
6645 if (taskloop_p)
6647 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6648 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6649 build_int_cst (unsigned_type_node,
6650 GOMP_TASK_FLAG_IF),
6651 build_int_cst (unsigned_type_node, 0));
6652 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6653 flags, t);
6655 else
6656 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6659 if (finalc)
6661 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6662 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6663 build_int_cst (unsigned_type_node,
6664 GOMP_TASK_FLAG_FINAL),
6665 build_int_cst (unsigned_type_node, 0));
6666 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6668 if (depend)
6669 depend = OMP_CLAUSE_DECL (depend);
6670 else
6671 depend = build_int_cst (ptr_type_node, 0);
6672 if (priority)
6673 priority = fold_convert (integer_type_node,
6674 OMP_CLAUSE_PRIORITY_EXPR (priority));
6675 else
6676 priority = integer_zero_node;
6678 gsi = gsi_last_bb (bb);
6679 tree t = gimple_omp_task_data_arg (entry_stmt);
6680 if (t == NULL)
6681 t2 = null_pointer_node;
6682 else
6683 t2 = build_fold_addr_expr_loc (loc, t);
6684 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6685 t = gimple_omp_task_copy_fn (entry_stmt);
6686 if (t == NULL)
6687 t3 = null_pointer_node;
6688 else
6689 t3 = build_fold_addr_expr_loc (loc, t);
6691 if (taskloop_p)
6692 t = build_call_expr (ull
6693 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6694 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6695 11, t1, t2, t3,
6696 gimple_omp_task_arg_size (entry_stmt),
6697 gimple_omp_task_arg_align (entry_stmt), flags,
6698 num_tasks, priority, startvar, endvar, step);
6699 else
6700 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6701 9, t1, t2, t3,
6702 gimple_omp_task_arg_size (entry_stmt),
6703 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6704 depend, priority);
6706 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6707 false, GSI_CONTINUE_LINKING);
6711 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6712 catch handler and return it. This prevents programs from violating the
6713 structured block semantics with throws. */
6715 static gimple_seq
6716 maybe_catch_exception (gimple_seq body)
6718 gimple *g;
6719 tree decl;
6721 if (!flag_exceptions)
6722 return body;
6724 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6725 decl = lang_hooks.eh_protect_cleanup_actions ();
6726 else
6727 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6729 g = gimple_build_eh_must_not_throw (decl);
6730 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6731 GIMPLE_TRY_CATCH);
6733 return gimple_seq_alloc_with_stmt (g);
6736 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6738 static tree
6739 vec2chain (vec<tree, va_gc> *v)
6741 tree chain = NULL_TREE, t;
6742 unsigned ix;
6744 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6746 DECL_CHAIN (t) = chain;
6747 chain = t;
6750 return chain;
6754 /* Remove barriers in REGION->EXIT's block. Note that this is only
6755 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6756 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6757 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6758 removed. */
6760 static void
6761 remove_exit_barrier (struct omp_region *region)
6763 gimple_stmt_iterator gsi;
6764 basic_block exit_bb;
6765 edge_iterator ei;
6766 edge e;
6767 gimple *stmt;
6768 int any_addressable_vars = -1;
6770 exit_bb = region->exit;
6772 /* If the parallel region doesn't return, we don't have REGION->EXIT
6773 block at all. */
6774 if (! exit_bb)
6775 return;
6777 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6778 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6779 statements that can appear in between are extremely limited -- no
6780 memory operations at all. Here, we allow nothing at all, so the
6781 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6782 gsi = gsi_last_bb (exit_bb);
6783 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6784 gsi_prev (&gsi);
6785 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6786 return;
6788 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6790 gsi = gsi_last_bb (e->src);
6791 if (gsi_end_p (gsi))
6792 continue;
6793 stmt = gsi_stmt (gsi);
6794 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6795 && !gimple_omp_return_nowait_p (stmt))
6797 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6798 in many cases. If there could be tasks queued, the barrier
6799 might be needed to let the tasks run before some local
6800 variable of the parallel that the task uses as shared
6801 runs out of scope. The task can be spawned either
6802 from within current function (this would be easy to check)
6803 or from some function it calls and gets passed an address
6804 of such a variable. */
6805 if (any_addressable_vars < 0)
6807 gomp_parallel *parallel_stmt
6808 = as_a <gomp_parallel *> (last_stmt (region->entry));
6809 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6810 tree local_decls, block, decl;
6811 unsigned ix;
6813 any_addressable_vars = 0;
6814 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6815 if (TREE_ADDRESSABLE (decl))
6817 any_addressable_vars = 1;
6818 break;
6820 for (block = gimple_block (stmt);
6821 !any_addressable_vars
6822 && block
6823 && TREE_CODE (block) == BLOCK;
6824 block = BLOCK_SUPERCONTEXT (block))
6826 for (local_decls = BLOCK_VARS (block);
6827 local_decls;
6828 local_decls = DECL_CHAIN (local_decls))
6829 if (TREE_ADDRESSABLE (local_decls))
6831 any_addressable_vars = 1;
6832 break;
6834 if (block == gimple_block (parallel_stmt))
6835 break;
6838 if (!any_addressable_vars)
6839 gimple_omp_return_set_nowait (stmt);
6844 static void
6845 remove_exit_barriers (struct omp_region *region)
6847 if (region->type == GIMPLE_OMP_PARALLEL)
6848 remove_exit_barrier (region);
6850 if (region->inner)
6852 region = region->inner;
6853 remove_exit_barriers (region);
6854 while (region->next)
6856 region = region->next;
6857 remove_exit_barriers (region);
6862 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6863 calls. These can't be declared as const functions, but
6864 within one parallel body they are constant, so they can be
6865 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6866 which are declared const. Similarly for task body, except
6867 that in untied task omp_get_thread_num () can change at any task
6868 scheduling point. */
6870 static void
6871 optimize_omp_library_calls (gimple *entry_stmt)
6873 basic_block bb;
6874 gimple_stmt_iterator gsi;
6875 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6876 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6877 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6878 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
6879 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6880 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
6881 OMP_CLAUSE_UNTIED) != NULL);
6883 FOR_EACH_BB_FN (bb, cfun)
6884 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6886 gimple *call = gsi_stmt (gsi);
6887 tree decl;
6889 if (is_gimple_call (call)
6890 && (decl = gimple_call_fndecl (call))
6891 && DECL_EXTERNAL (decl)
6892 && TREE_PUBLIC (decl)
6893 && DECL_INITIAL (decl) == NULL)
6895 tree built_in;
6897 if (DECL_NAME (decl) == thr_num_id)
6899 /* In #pragma omp task untied omp_get_thread_num () can change
6900 during the execution of the task region. */
6901 if (untied_task)
6902 continue;
6903 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6905 else if (DECL_NAME (decl) == num_thr_id)
6906 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6907 else
6908 continue;
6910 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
6911 || gimple_call_num_args (call) != 0)
6912 continue;
6914 if (flag_exceptions && !TREE_NOTHROW (decl))
6915 continue;
6917 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
6918 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6919 TREE_TYPE (TREE_TYPE (built_in))))
6920 continue;
6922 gimple_call_set_fndecl (call, built_in);
6927 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6928 regimplified. */
6930 static tree
6931 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6933 tree t = *tp;
6935 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6936 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6937 return t;
6939 if (TREE_CODE (t) == ADDR_EXPR)
6940 recompute_tree_invariant_for_addr_expr (t);
6942 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6943 return NULL_TREE;
6946 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
6948 static void
6949 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6950 bool after)
6952 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6953 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
6954 !after, after ? GSI_CONTINUE_LINKING
6955 : GSI_SAME_STMT);
6956 gimple *stmt = gimple_build_assign (to, from);
6957 if (after)
6958 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6959 else
6960 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
6961 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6962 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6964 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6965 gimple_regimplify_operands (stmt, &gsi);
6969 /* Expand the OpenMP parallel or task directive starting at REGION. */
6971 static void
6972 expand_omp_taskreg (struct omp_region *region)
6974 basic_block entry_bb, exit_bb, new_bb;
6975 struct function *child_cfun;
6976 tree child_fn, block, t;
6977 gimple_stmt_iterator gsi;
6978 gimple *entry_stmt, *stmt;
6979 edge e;
6980 vec<tree, va_gc> *ws_args;
6982 entry_stmt = last_stmt (region->entry);
6983 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
6984 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6986 entry_bb = region->entry;
6987 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6988 exit_bb = region->cont;
6989 else
6990 exit_bb = region->exit;
6992 bool is_cilk_for
6993 = (flag_cilkplus
6994 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6995 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6996 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6998 if (is_cilk_for)
6999 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7000 and the inner statement contains the name of the built-in function
7001 and grain. */
7002 ws_args = region->inner->ws_args;
7003 else if (is_combined_parallel (region))
7004 ws_args = region->ws_args;
7005 else
7006 ws_args = NULL;
7008 if (child_cfun->cfg)
7010 /* Due to inlining, it may happen that we have already outlined
7011 the region, in which case all we need to do is make the
7012 sub-graph unreachable and emit the parallel call. */
7013 edge entry_succ_e, exit_succ_e;
7015 entry_succ_e = single_succ_edge (entry_bb);
7017 gsi = gsi_last_bb (entry_bb);
7018 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7019 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7020 gsi_remove (&gsi, true);
7022 new_bb = entry_bb;
7023 if (exit_bb)
7025 exit_succ_e = single_succ_edge (exit_bb);
7026 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7028 remove_edge_and_dominated_blocks (entry_succ_e);
7030 else
7032 unsigned srcidx, dstidx, num;
7034 /* If the parallel region needs data sent from the parent
7035 function, then the very first statement (except possible
7036 tree profile counter updates) of the parallel body
7037 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7038 &.OMP_DATA_O is passed as an argument to the child function,
7039 we need to replace it with the argument as seen by the child
7040 function.
7042 In most cases, this will end up being the identity assignment
7043 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7044 a function call that has been inlined, the original PARM_DECL
7045 .OMP_DATA_I may have been converted into a different local
7046 variable. In which case, we need to keep the assignment. */
7047 if (gimple_omp_taskreg_data_arg (entry_stmt))
7049 basic_block entry_succ_bb
7050 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7051 : FALLTHRU_EDGE (entry_bb)->dest;
7052 tree arg;
7053 gimple *parcopy_stmt = NULL;
7055 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7057 gimple *stmt;
7059 gcc_assert (!gsi_end_p (gsi));
7060 stmt = gsi_stmt (gsi);
7061 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7062 continue;
7064 if (gimple_num_ops (stmt) == 2)
7066 tree arg = gimple_assign_rhs1 (stmt);
7068 /* We're ignore the subcode because we're
7069 effectively doing a STRIP_NOPS. */
7071 if (TREE_CODE (arg) == ADDR_EXPR
7072 && TREE_OPERAND (arg, 0)
7073 == gimple_omp_taskreg_data_arg (entry_stmt))
7075 parcopy_stmt = stmt;
7076 break;
7081 gcc_assert (parcopy_stmt != NULL);
7082 arg = DECL_ARGUMENTS (child_fn);
7084 if (!gimple_in_ssa_p (cfun))
7086 if (gimple_assign_lhs (parcopy_stmt) == arg)
7087 gsi_remove (&gsi, true);
7088 else
7090 /* ?? Is setting the subcode really necessary ?? */
7091 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7092 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7095 else
7097 tree lhs = gimple_assign_lhs (parcopy_stmt);
7098 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7099 /* We'd like to set the rhs to the default def in the child_fn,
7100 but it's too early to create ssa names in the child_fn.
7101 Instead, we set the rhs to the parm. In
7102 move_sese_region_to_fn, we introduce a default def for the
7103 parm, map the parm to it's default def, and once we encounter
7104 this stmt, replace the parm with the default def. */
7105 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7106 update_stmt (parcopy_stmt);
7110 /* Declare local variables needed in CHILD_CFUN. */
7111 block = DECL_INITIAL (child_fn);
7112 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7113 /* The gimplifier could record temporaries in parallel/task block
7114 rather than in containing function's local_decls chain,
7115 which would mean cgraph missed finalizing them. Do it now. */
7116 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7117 if (TREE_CODE (t) == VAR_DECL
7118 && TREE_STATIC (t)
7119 && !DECL_EXTERNAL (t))
7120 varpool_node::finalize_decl (t);
7121 DECL_SAVED_TREE (child_fn) = NULL;
7122 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7123 gimple_set_body (child_fn, NULL);
7124 TREE_USED (block) = 1;
7126 /* Reset DECL_CONTEXT on function arguments. */
7127 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7128 DECL_CONTEXT (t) = child_fn;
7130 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7131 so that it can be moved to the child function. */
7132 gsi = gsi_last_bb (entry_bb);
7133 stmt = gsi_stmt (gsi);
7134 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7135 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7136 e = split_block (entry_bb, stmt);
7137 gsi_remove (&gsi, true);
7138 entry_bb = e->dest;
7139 edge e2 = NULL;
7140 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7141 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7142 else
7144 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7145 gcc_assert (e2->dest == region->exit);
7146 remove_edge (BRANCH_EDGE (entry_bb));
7147 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7148 gsi = gsi_last_bb (region->exit);
7149 gcc_assert (!gsi_end_p (gsi)
7150 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7151 gsi_remove (&gsi, true);
7154 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7155 if (exit_bb)
7157 gsi = gsi_last_bb (exit_bb);
7158 gcc_assert (!gsi_end_p (gsi)
7159 && (gimple_code (gsi_stmt (gsi))
7160 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7161 stmt = gimple_build_return (NULL);
7162 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7163 gsi_remove (&gsi, true);
7166 /* Move the parallel region into CHILD_CFUN. */
7168 if (gimple_in_ssa_p (cfun))
7170 init_tree_ssa (child_cfun);
7171 init_ssa_operands (child_cfun);
7172 child_cfun->gimple_df->in_ssa_p = true;
7173 block = NULL_TREE;
7175 else
7176 block = gimple_block (entry_stmt);
7178 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7179 if (exit_bb)
7180 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7181 if (e2)
7183 basic_block dest_bb = e2->dest;
7184 if (!exit_bb)
7185 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7186 remove_edge (e2);
7187 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7189 /* When the OMP expansion process cannot guarantee an up-to-date
7190 loop tree arrange for the child function to fixup loops. */
7191 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7192 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7194 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7195 num = vec_safe_length (child_cfun->local_decls);
7196 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7198 t = (*child_cfun->local_decls)[srcidx];
7199 if (DECL_CONTEXT (t) == cfun->decl)
7200 continue;
7201 if (srcidx != dstidx)
7202 (*child_cfun->local_decls)[dstidx] = t;
7203 dstidx++;
7205 if (dstidx != num)
7206 vec_safe_truncate (child_cfun->local_decls, dstidx);
7208 /* Inform the callgraph about the new function. */
7209 child_cfun->curr_properties = cfun->curr_properties;
7210 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7211 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7212 cgraph_node *node = cgraph_node::get_create (child_fn);
7213 node->parallelized_function = 1;
7214 cgraph_node::add_new_function (child_fn, true);
7216 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7217 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7219 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7220 fixed in a following pass. */
7221 push_cfun (child_cfun);
7222 if (need_asm)
7223 assign_assembler_name_if_neeeded (child_fn);
7225 if (optimize)
7226 optimize_omp_library_calls (entry_stmt);
7227 cgraph_edge::rebuild_edges ();
7229 /* Some EH regions might become dead, see PR34608. If
7230 pass_cleanup_cfg isn't the first pass to happen with the
7231 new child, these dead EH edges might cause problems.
7232 Clean them up now. */
7233 if (flag_exceptions)
7235 basic_block bb;
7236 bool changed = false;
7238 FOR_EACH_BB_FN (bb, cfun)
7239 changed |= gimple_purge_dead_eh_edges (bb);
7240 if (changed)
7241 cleanup_tree_cfg ();
7243 if (gimple_in_ssa_p (cfun))
7244 update_ssa (TODO_update_ssa);
7245 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7246 verify_loop_structure ();
7247 pop_cfun ();
7249 if (dump_file && !gimple_in_ssa_p (cfun))
7251 omp_any_child_fn_dumped = true;
7252 dump_function_header (dump_file, child_fn, dump_flags);
7253 dump_function_to_file (child_fn, dump_file, dump_flags);
7257 /* Emit a library call to launch the children threads. */
7258 if (is_cilk_for)
7259 expand_cilk_for_call (new_bb,
7260 as_a <gomp_parallel *> (entry_stmt), ws_args);
7261 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7262 expand_parallel_call (region, new_bb,
7263 as_a <gomp_parallel *> (entry_stmt), ws_args);
7264 else
7265 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7266 if (gimple_in_ssa_p (cfun))
7267 update_ssa (TODO_update_ssa_only_virtuals);
7270 /* Information about members of an OpenACC collapsed loop nest. */
7272 struct oacc_collapse
7274 tree base; /* Base value. */
7275 tree iters; /* Number of steps. */
7276 tree step; /* step size. */
7279 /* Helper for expand_oacc_for. Determine collapsed loop information.
7280 Fill in COUNTS array. Emit any initialization code before GSI.
7281 Return the calculated outer loop bound of BOUND_TYPE. */
7283 static tree
7284 expand_oacc_collapse_init (const struct omp_for_data *fd,
7285 gimple_stmt_iterator *gsi,
7286 oacc_collapse *counts, tree bound_type)
7288 tree total = build_int_cst (bound_type, 1);
7289 int ix;
7291 gcc_assert (integer_onep (fd->loop.step));
7292 gcc_assert (integer_zerop (fd->loop.n1));
7294 for (ix = 0; ix != fd->collapse; ix++)
7296 const omp_for_data_loop *loop = &fd->loops[ix];
7298 tree iter_type = TREE_TYPE (loop->v);
7299 tree diff_type = iter_type;
7300 tree plus_type = iter_type;
7302 gcc_assert (loop->cond_code == fd->loop.cond_code);
7304 if (POINTER_TYPE_P (iter_type))
7305 plus_type = sizetype;
7306 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7307 diff_type = signed_type_for (diff_type);
7309 tree b = loop->n1;
7310 tree e = loop->n2;
7311 tree s = loop->step;
7312 bool up = loop->cond_code == LT_EXPR;
7313 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7314 bool negating;
7315 tree expr;
7317 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7318 true, GSI_SAME_STMT);
7319 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7320 true, GSI_SAME_STMT);
7322 /* Convert the step, avoiding possible unsigned->signed overflow. */
7323 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7324 if (negating)
7325 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7326 s = fold_convert (diff_type, s);
7327 if (negating)
7328 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7329 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7330 true, GSI_SAME_STMT);
7332 /* Determine the range, avoiding possible unsigned->signed overflow. */
7333 negating = !up && TYPE_UNSIGNED (iter_type);
7334 expr = fold_build2 (MINUS_EXPR, plus_type,
7335 fold_convert (plus_type, negating ? b : e),
7336 fold_convert (plus_type, negating ? e : b));
7337 expr = fold_convert (diff_type, expr);
7338 if (negating)
7339 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7340 tree range = force_gimple_operand_gsi
7341 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7343 /* Determine number of iterations. */
7344 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7345 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7346 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7348 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7349 true, GSI_SAME_STMT);
7351 counts[ix].base = b;
7352 counts[ix].iters = iters;
7353 counts[ix].step = s;
7355 total = fold_build2 (MULT_EXPR, bound_type, total,
7356 fold_convert (bound_type, iters));
7359 return total;
7362 /* Emit initializers for collapsed loop members. IVAR is the outer
7363 loop iteration variable, from which collapsed loop iteration values
7364 are calculated. COUNTS array has been initialized by
7365 expand_oacc_collapse_inits. */
7367 static void
7368 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7369 gimple_stmt_iterator *gsi,
7370 const oacc_collapse *counts, tree ivar)
7372 tree ivar_type = TREE_TYPE (ivar);
7374 /* The most rapidly changing iteration variable is the innermost
7375 one. */
7376 for (int ix = fd->collapse; ix--;)
7378 const omp_for_data_loop *loop = &fd->loops[ix];
7379 const oacc_collapse *collapse = &counts[ix];
7380 tree iter_type = TREE_TYPE (loop->v);
7381 tree diff_type = TREE_TYPE (collapse->step);
7382 tree plus_type = iter_type;
7383 enum tree_code plus_code = PLUS_EXPR;
7384 tree expr;
7386 if (POINTER_TYPE_P (iter_type))
7388 plus_code = POINTER_PLUS_EXPR;
7389 plus_type = sizetype;
7392 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7393 fold_convert (ivar_type, collapse->iters));
7394 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7395 collapse->step);
7396 expr = fold_build2 (plus_code, iter_type, collapse->base,
7397 fold_convert (plus_type, expr));
7398 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7399 true, GSI_SAME_STMT);
7400 gassign *ass = gimple_build_assign (loop->v, expr);
7401 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7403 if (ix)
7405 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7406 fold_convert (ivar_type, collapse->iters));
7407 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7408 true, GSI_SAME_STMT);
7414 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7415 of the combined collapse > 1 loop constructs, generate code like:
7416 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7417 if (cond3 is <)
7418 adj = STEP3 - 1;
7419 else
7420 adj = STEP3 + 1;
7421 count3 = (adj + N32 - N31) / STEP3;
7422 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7423 if (cond2 is <)
7424 adj = STEP2 - 1;
7425 else
7426 adj = STEP2 + 1;
7427 count2 = (adj + N22 - N21) / STEP2;
7428 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7429 if (cond1 is <)
7430 adj = STEP1 - 1;
7431 else
7432 adj = STEP1 + 1;
7433 count1 = (adj + N12 - N11) / STEP1;
7434 count = count1 * count2 * count3;
7435 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7436 count = 0;
7437 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7438 of the combined loop constructs, just initialize COUNTS array
7439 from the _looptemp_ clauses. */
7441 /* NOTE: It *could* be better to moosh all of the BBs together,
7442 creating one larger BB with all the computation and the unexpected
7443 jump at the end. I.e.
7445 bool zero3, zero2, zero1, zero;
7447 zero3 = N32 c3 N31;
7448 count3 = (N32 - N31) /[cl] STEP3;
7449 zero2 = N22 c2 N21;
7450 count2 = (N22 - N21) /[cl] STEP2;
7451 zero1 = N12 c1 N11;
7452 count1 = (N12 - N11) /[cl] STEP1;
7453 zero = zero3 || zero2 || zero1;
7454 count = count1 * count2 * count3;
7455 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7457 After all, we expect the zero=false, and thus we expect to have to
7458 evaluate all of the comparison expressions, so short-circuiting
7459 oughtn't be a win. Since the condition isn't protecting a
7460 denominator, we're not concerned about divide-by-zero, so we can
7461 fully evaluate count even if a numerator turned out to be wrong.
7463 It seems like putting this all together would create much better
7464 scheduling opportunities, and less pressure on the chip's branch
7465 predictor. */
7467 static void
7468 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7469 basic_block &entry_bb, tree *counts,
7470 basic_block &zero_iter1_bb, int &first_zero_iter1,
7471 basic_block &zero_iter2_bb, int &first_zero_iter2,
7472 basic_block &l2_dom_bb)
7474 tree t, type = TREE_TYPE (fd->loop.v);
7475 edge e, ne;
7476 int i;
7478 /* Collapsed loops need work for expansion into SSA form. */
7479 gcc_assert (!gimple_in_ssa_p (cfun));
7481 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7482 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7484 gcc_assert (fd->ordered == 0);
7485 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7486 isn't supposed to be handled, as the inner loop doesn't
7487 use it. */
7488 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7489 OMP_CLAUSE__LOOPTEMP_);
7490 gcc_assert (innerc);
7491 for (i = 0; i < fd->collapse; i++)
7493 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7494 OMP_CLAUSE__LOOPTEMP_);
7495 gcc_assert (innerc);
7496 if (i)
7497 counts[i] = OMP_CLAUSE_DECL (innerc);
7498 else
7499 counts[0] = NULL_TREE;
7501 return;
7504 for (i = fd->collapse; i < fd->ordered; i++)
7506 tree itype = TREE_TYPE (fd->loops[i].v);
7507 counts[i] = NULL_TREE;
7508 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7509 fold_convert (itype, fd->loops[i].n1),
7510 fold_convert (itype, fd->loops[i].n2));
7511 if (t && integer_zerop (t))
7513 for (i = fd->collapse; i < fd->ordered; i++)
7514 counts[i] = build_int_cst (type, 0);
7515 break;
7518 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7520 tree itype = TREE_TYPE (fd->loops[i].v);
7522 if (i >= fd->collapse && counts[i])
7523 continue;
7524 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7525 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7526 fold_convert (itype, fd->loops[i].n1),
7527 fold_convert (itype, fd->loops[i].n2)))
7528 == NULL_TREE || !integer_onep (t)))
7530 gcond *cond_stmt;
7531 tree n1, n2;
7532 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7533 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7534 true, GSI_SAME_STMT);
7535 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7536 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7537 true, GSI_SAME_STMT);
7538 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7539 NULL_TREE, NULL_TREE);
7540 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7541 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7542 expand_omp_regimplify_p, NULL, NULL)
7543 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7544 expand_omp_regimplify_p, NULL, NULL))
7546 *gsi = gsi_for_stmt (cond_stmt);
7547 gimple_regimplify_operands (cond_stmt, gsi);
7549 e = split_block (entry_bb, cond_stmt);
7550 basic_block &zero_iter_bb
7551 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7552 int &first_zero_iter
7553 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7554 if (zero_iter_bb == NULL)
7556 gassign *assign_stmt;
7557 first_zero_iter = i;
7558 zero_iter_bb = create_empty_bb (entry_bb);
7559 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7560 *gsi = gsi_after_labels (zero_iter_bb);
7561 if (i < fd->collapse)
7562 assign_stmt = gimple_build_assign (fd->loop.n2,
7563 build_zero_cst (type));
7564 else
7566 counts[i] = create_tmp_reg (type, ".count");
7567 assign_stmt
7568 = gimple_build_assign (counts[i], build_zero_cst (type));
7570 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7571 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7572 entry_bb);
7574 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7575 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7576 e->flags = EDGE_TRUE_VALUE;
7577 e->probability = REG_BR_PROB_BASE - ne->probability;
7578 if (l2_dom_bb == NULL)
7579 l2_dom_bb = entry_bb;
7580 entry_bb = e->dest;
7581 *gsi = gsi_last_bb (entry_bb);
7584 if (POINTER_TYPE_P (itype))
7585 itype = signed_type_for (itype);
7586 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7587 ? -1 : 1));
7588 t = fold_build2 (PLUS_EXPR, itype,
7589 fold_convert (itype, fd->loops[i].step), t);
7590 t = fold_build2 (PLUS_EXPR, itype, t,
7591 fold_convert (itype, fd->loops[i].n2));
7592 t = fold_build2 (MINUS_EXPR, itype, t,
7593 fold_convert (itype, fd->loops[i].n1));
7594 /* ?? We could probably use CEIL_DIV_EXPR instead of
7595 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7596 generate the same code in the end because generically we
7597 don't know that the values involved must be negative for
7598 GT?? */
7599 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7600 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7601 fold_build1 (NEGATE_EXPR, itype, t),
7602 fold_build1 (NEGATE_EXPR, itype,
7603 fold_convert (itype,
7604 fd->loops[i].step)));
7605 else
7606 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7607 fold_convert (itype, fd->loops[i].step));
7608 t = fold_convert (type, t);
7609 if (TREE_CODE (t) == INTEGER_CST)
7610 counts[i] = t;
7611 else
7613 if (i < fd->collapse || i != first_zero_iter2)
7614 counts[i] = create_tmp_reg (type, ".count");
7615 expand_omp_build_assign (gsi, counts[i], t);
7617 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7619 if (i == 0)
7620 t = counts[0];
7621 else
7622 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7623 expand_omp_build_assign (gsi, fd->loop.n2, t);
7629 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7630 T = V;
7631 V3 = N31 + (T % count3) * STEP3;
7632 T = T / count3;
7633 V2 = N21 + (T % count2) * STEP2;
7634 T = T / count2;
7635 V1 = N11 + T * STEP1;
7636 if this loop doesn't have an inner loop construct combined with it.
7637 If it does have an inner loop construct combined with it and the
7638 iteration count isn't known constant, store values from counts array
7639 into its _looptemp_ temporaries instead. */
7641 static void
7642 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7643 tree *counts, gimple *inner_stmt, tree startvar)
7645 int i;
7646 if (gimple_omp_for_combined_p (fd->for_stmt))
7648 /* If fd->loop.n2 is constant, then no propagation of the counts
7649 is needed, they are constant. */
7650 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7651 return;
7653 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7654 ? gimple_omp_taskreg_clauses (inner_stmt)
7655 : gimple_omp_for_clauses (inner_stmt);
7656 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7657 isn't supposed to be handled, as the inner loop doesn't
7658 use it. */
7659 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7660 gcc_assert (innerc);
7661 for (i = 0; i < fd->collapse; i++)
7663 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7664 OMP_CLAUSE__LOOPTEMP_);
7665 gcc_assert (innerc);
7666 if (i)
7668 tree tem = OMP_CLAUSE_DECL (innerc);
7669 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7670 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7671 false, GSI_CONTINUE_LINKING);
7672 gassign *stmt = gimple_build_assign (tem, t);
7673 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7676 return;
7679 tree type = TREE_TYPE (fd->loop.v);
7680 tree tem = create_tmp_reg (type, ".tem");
7681 gassign *stmt = gimple_build_assign (tem, startvar);
7682 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7684 for (i = fd->collapse - 1; i >= 0; i--)
7686 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7687 itype = vtype;
7688 if (POINTER_TYPE_P (vtype))
7689 itype = signed_type_for (vtype);
7690 if (i != 0)
7691 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7692 else
7693 t = tem;
7694 t = fold_convert (itype, t);
7695 t = fold_build2 (MULT_EXPR, itype, t,
7696 fold_convert (itype, fd->loops[i].step));
7697 if (POINTER_TYPE_P (vtype))
7698 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7699 else
7700 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7701 t = force_gimple_operand_gsi (gsi, t,
7702 DECL_P (fd->loops[i].v)
7703 && TREE_ADDRESSABLE (fd->loops[i].v),
7704 NULL_TREE, false,
7705 GSI_CONTINUE_LINKING);
7706 stmt = gimple_build_assign (fd->loops[i].v, t);
7707 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7708 if (i != 0)
7710 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7711 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7712 false, GSI_CONTINUE_LINKING);
7713 stmt = gimple_build_assign (tem, t);
7714 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7720 /* Helper function for expand_omp_for_*. Generate code like:
7721 L10:
7722 V3 += STEP3;
7723 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7724 L11:
7725 V3 = N31;
7726 V2 += STEP2;
7727 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7728 L12:
7729 V2 = N21;
7730 V1 += STEP1;
7731 goto BODY_BB; */
7733 static basic_block
7734 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7735 basic_block body_bb)
7737 basic_block last_bb, bb, collapse_bb = NULL;
7738 int i;
7739 gimple_stmt_iterator gsi;
7740 edge e;
7741 tree t;
7742 gimple *stmt;
7744 last_bb = cont_bb;
7745 for (i = fd->collapse - 1; i >= 0; i--)
7747 tree vtype = TREE_TYPE (fd->loops[i].v);
7749 bb = create_empty_bb (last_bb);
7750 add_bb_to_loop (bb, last_bb->loop_father);
7751 gsi = gsi_start_bb (bb);
7753 if (i < fd->collapse - 1)
7755 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7756 e->probability = REG_BR_PROB_BASE / 8;
7758 t = fd->loops[i + 1].n1;
7759 t = force_gimple_operand_gsi (&gsi, t,
7760 DECL_P (fd->loops[i + 1].v)
7761 && TREE_ADDRESSABLE (fd->loops[i
7762 + 1].v),
7763 NULL_TREE, false,
7764 GSI_CONTINUE_LINKING);
7765 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7766 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7768 else
7769 collapse_bb = bb;
7771 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7773 if (POINTER_TYPE_P (vtype))
7774 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7775 else
7776 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7777 t = force_gimple_operand_gsi (&gsi, t,
7778 DECL_P (fd->loops[i].v)
7779 && TREE_ADDRESSABLE (fd->loops[i].v),
7780 NULL_TREE, false, GSI_CONTINUE_LINKING);
7781 stmt = gimple_build_assign (fd->loops[i].v, t);
7782 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7784 if (i > 0)
7786 t = fd->loops[i].n2;
7787 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7788 false, GSI_CONTINUE_LINKING);
7789 tree v = fd->loops[i].v;
7790 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7791 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7792 false, GSI_CONTINUE_LINKING);
7793 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7794 stmt = gimple_build_cond_empty (t);
7795 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7796 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7797 e->probability = REG_BR_PROB_BASE * 7 / 8;
7799 else
7800 make_edge (bb, body_bb, EDGE_FALLTHRU);
7801 last_bb = bb;
7804 return collapse_bb;
7808 /* Expand #pragma omp ordered depend(source). */
7810 static void
7811 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7812 tree *counts, location_t loc)
7814 enum built_in_function source_ix
7815 = fd->iter_type == long_integer_type_node
7816 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7817 gimple *g
7818 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7819 build_fold_addr_expr (counts[fd->ordered]));
7820 gimple_set_location (g, loc);
7821 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7824 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7826 static void
7827 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7828 tree *counts, tree c, location_t loc)
7830 auto_vec<tree, 10> args;
7831 enum built_in_function sink_ix
7832 = fd->iter_type == long_integer_type_node
7833 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7834 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7835 int i;
7836 gimple_stmt_iterator gsi2 = *gsi;
7837 bool warned_step = false;
7839 for (i = 0; i < fd->ordered; i++)
7841 off = TREE_PURPOSE (deps);
7842 if (!integer_zerop (off))
7844 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7845 || fd->loops[i].cond_code == GT_EXPR);
7846 bool forward = fd->loops[i].cond_code == LT_EXPR;
7847 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7848 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7849 "lexically later iteration");
7850 break;
7852 deps = TREE_CHAIN (deps);
7854 /* If all offsets corresponding to the collapsed loops are zero,
7855 this depend clause can be ignored. FIXME: but there is still a
7856 flush needed. We need to emit one __sync_synchronize () for it
7857 though (perhaps conditionally)? Solve this together with the
7858 conservative dependence folding optimization.
7859 if (i >= fd->collapse)
7860 return; */
7862 deps = OMP_CLAUSE_DECL (c);
7863 gsi_prev (&gsi2);
7864 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7865 edge e2 = split_block_after_labels (e1->dest);
7867 *gsi = gsi_after_labels (e1->dest);
7868 for (i = 0; i < fd->ordered; i++)
7870 tree itype = TREE_TYPE (fd->loops[i].v);
7871 if (POINTER_TYPE_P (itype))
7872 itype = sizetype;
7873 if (i)
7874 deps = TREE_CHAIN (deps);
7875 off = TREE_PURPOSE (deps);
7876 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7878 if (integer_zerop (off))
7879 t = boolean_true_node;
7880 else
7882 tree a;
7883 tree co = fold_convert_loc (loc, itype, off);
7884 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7886 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7887 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7888 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7889 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7890 co);
7892 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7893 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7894 fd->loops[i].v, co);
7895 else
7896 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7897 fd->loops[i].v, co);
7898 if (fd->loops[i].cond_code == LT_EXPR)
7900 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7901 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7902 fd->loops[i].n1);
7903 else
7904 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7905 fd->loops[i].n2);
7907 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7908 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7909 fd->loops[i].n2);
7910 else
7911 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7912 fd->loops[i].n1);
7914 if (cond)
7915 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7916 else
7917 cond = t;
7919 off = fold_convert_loc (loc, itype, off);
7921 if (fd->loops[i].cond_code == LT_EXPR
7922 ? !integer_onep (fd->loops[i].step)
7923 : !integer_minus_onep (fd->loops[i].step))
7925 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7926 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7927 fold_build1_loc (loc, NEGATE_EXPR, itype,
7928 s));
7929 else
7930 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7931 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7932 build_int_cst (itype, 0));
7933 if (integer_zerop (t) && !warned_step)
7935 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7936 "in the iteration space");
7937 warned_step = true;
7939 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7940 cond, t);
7943 if (i <= fd->collapse - 1 && fd->collapse > 1)
7944 t = fd->loop.v;
7945 else if (counts[i])
7946 t = counts[i];
7947 else
7949 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7950 fd->loops[i].v, fd->loops[i].n1);
7951 t = fold_convert_loc (loc, fd->iter_type, t);
7953 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7954 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7955 fold_build1_loc (loc, NEGATE_EXPR, itype,
7956 s));
7957 else
7958 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7959 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7960 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7961 off = fold_convert_loc (loc, fd->iter_type, off);
7962 if (i <= fd->collapse - 1 && fd->collapse > 1)
7964 if (i)
7965 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7966 off);
7967 if (i < fd->collapse - 1)
7969 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7970 counts[i]);
7971 continue;
7974 off = unshare_expr (off);
7975 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7976 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7977 true, GSI_SAME_STMT);
7978 args.safe_push (t);
7980 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7981 gimple_set_location (g, loc);
7982 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7984 *gsi = gsi_last_bb (e1->src);
7985 cond = unshare_expr (cond);
7986 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7987 GSI_CONTINUE_LINKING);
7988 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7989 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7990 e3->probability = REG_BR_PROB_BASE / 8;
7991 e1->probability = REG_BR_PROB_BASE - e3->probability;
7992 e1->flags = EDGE_TRUE_VALUE;
7993 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7995 *gsi = gsi_after_labels (e2->dest);
7998 /* Expand all #pragma omp ordered depend(source) and
7999 #pragma omp ordered depend(sink:...) constructs in the current
8000 #pragma omp for ordered(n) region. */
8002 static void
8003 expand_omp_ordered_source_sink (struct omp_region *region,
8004 struct omp_for_data *fd, tree *counts,
8005 basic_block cont_bb)
8007 struct omp_region *inner;
8008 int i;
8009 for (i = fd->collapse - 1; i < fd->ordered; i++)
8010 if (i == fd->collapse - 1 && fd->collapse > 1)
8011 counts[i] = NULL_TREE;
8012 else if (i >= fd->collapse && !cont_bb)
8013 counts[i] = build_zero_cst (fd->iter_type);
8014 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8015 && integer_onep (fd->loops[i].step))
8016 counts[i] = NULL_TREE;
8017 else
8018 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8019 tree atype
8020 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8021 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8022 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8024 for (inner = region->inner; inner; inner = inner->next)
8025 if (inner->type == GIMPLE_OMP_ORDERED)
8027 gomp_ordered *ord_stmt = inner->ord_stmt;
8028 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8029 location_t loc = gimple_location (ord_stmt);
8030 tree c;
8031 for (c = gimple_omp_ordered_clauses (ord_stmt);
8032 c; c = OMP_CLAUSE_CHAIN (c))
8033 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8034 break;
8035 if (c)
8036 expand_omp_ordered_source (&gsi, fd, counts, loc);
8037 for (c = gimple_omp_ordered_clauses (ord_stmt);
8038 c; c = OMP_CLAUSE_CHAIN (c))
8039 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8040 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8041 gsi_remove (&gsi, true);
8045 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8046 collapsed. */
8048 static basic_block
8049 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8050 basic_block cont_bb, basic_block body_bb,
8051 bool ordered_lastprivate)
8053 if (fd->ordered == fd->collapse)
8054 return cont_bb;
8056 if (!cont_bb)
8058 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8059 for (int i = fd->collapse; i < fd->ordered; i++)
8061 tree type = TREE_TYPE (fd->loops[i].v);
8062 tree n1 = fold_convert (type, fd->loops[i].n1);
8063 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8064 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8065 size_int (i - fd->collapse + 1),
8066 NULL_TREE, NULL_TREE);
8067 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8069 return NULL;
8072 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8074 tree t, type = TREE_TYPE (fd->loops[i].v);
8075 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8076 expand_omp_build_assign (&gsi, fd->loops[i].v,
8077 fold_convert (type, fd->loops[i].n1));
8078 if (counts[i])
8079 expand_omp_build_assign (&gsi, counts[i],
8080 build_zero_cst (fd->iter_type));
8081 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8082 size_int (i - fd->collapse + 1),
8083 NULL_TREE, NULL_TREE);
8084 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8085 if (!gsi_end_p (gsi))
8086 gsi_prev (&gsi);
8087 else
8088 gsi = gsi_last_bb (body_bb);
8089 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8090 basic_block new_body = e1->dest;
8091 if (body_bb == cont_bb)
8092 cont_bb = new_body;
8093 edge e2 = NULL;
8094 basic_block new_header;
8095 if (EDGE_COUNT (cont_bb->preds) > 0)
8097 gsi = gsi_last_bb (cont_bb);
8098 if (POINTER_TYPE_P (type))
8099 t = fold_build_pointer_plus (fd->loops[i].v,
8100 fold_convert (sizetype,
8101 fd->loops[i].step));
8102 else
8103 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8104 fold_convert (type, fd->loops[i].step));
8105 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8106 if (counts[i])
8108 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8109 build_int_cst (fd->iter_type, 1));
8110 expand_omp_build_assign (&gsi, counts[i], t);
8111 t = counts[i];
8113 else
8115 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8116 fd->loops[i].v, fd->loops[i].n1);
8117 t = fold_convert (fd->iter_type, t);
8118 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8119 true, GSI_SAME_STMT);
8121 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8122 size_int (i - fd->collapse + 1),
8123 NULL_TREE, NULL_TREE);
8124 expand_omp_build_assign (&gsi, aref, t);
8125 gsi_prev (&gsi);
8126 e2 = split_block (cont_bb, gsi_stmt (gsi));
8127 new_header = e2->dest;
8129 else
8130 new_header = cont_bb;
8131 gsi = gsi_after_labels (new_header);
8132 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8133 true, GSI_SAME_STMT);
8134 tree n2
8135 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8136 true, NULL_TREE, true, GSI_SAME_STMT);
8137 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8138 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8139 edge e3 = split_block (new_header, gsi_stmt (gsi));
8140 cont_bb = e3->dest;
8141 remove_edge (e1);
8142 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8143 e3->flags = EDGE_FALSE_VALUE;
8144 e3->probability = REG_BR_PROB_BASE / 8;
8145 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8146 e1->probability = REG_BR_PROB_BASE - e3->probability;
8148 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8149 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8151 if (e2)
8153 struct loop *loop = alloc_loop ();
8154 loop->header = new_header;
8155 loop->latch = e2->src;
8156 add_loop (loop, body_bb->loop_father);
8160 /* If there are any lastprivate clauses and it is possible some loops
8161 might have zero iterations, ensure all the decls are initialized,
8162 otherwise we could crash evaluating C++ class iterators with lastprivate
8163 clauses. */
8164 bool need_inits = false;
8165 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8166 if (need_inits)
8168 tree type = TREE_TYPE (fd->loops[i].v);
8169 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8170 expand_omp_build_assign (&gsi, fd->loops[i].v,
8171 fold_convert (type, fd->loops[i].n1));
8173 else
8175 tree type = TREE_TYPE (fd->loops[i].v);
8176 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8177 boolean_type_node,
8178 fold_convert (type, fd->loops[i].n1),
8179 fold_convert (type, fd->loops[i].n2));
8180 if (!integer_onep (this_cond))
8181 need_inits = true;
8184 return cont_bb;
8188 /* A subroutine of expand_omp_for. Generate code for a parallel
8189 loop with any schedule. Given parameters:
8191 for (V = N1; V cond N2; V += STEP) BODY;
8193 where COND is "<" or ">", we generate pseudocode
8195 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8196 if (more) goto L0; else goto L3;
8198 V = istart0;
8199 iend = iend0;
8201 BODY;
8202 V += STEP;
8203 if (V cond iend) goto L1; else goto L2;
8205 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8208 If this is a combined omp parallel loop, instead of the call to
8209 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8210 If this is gimple_omp_for_combined_p loop, then instead of assigning
8211 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8212 inner GIMPLE_OMP_FOR and V += STEP; and
8213 if (V cond iend) goto L1; else goto L2; are removed.
8215 For collapsed loops, given parameters:
8216 collapse(3)
8217 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8218 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8219 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8220 BODY;
8222 we generate pseudocode
8224 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8225 if (cond3 is <)
8226 adj = STEP3 - 1;
8227 else
8228 adj = STEP3 + 1;
8229 count3 = (adj + N32 - N31) / STEP3;
8230 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8231 if (cond2 is <)
8232 adj = STEP2 - 1;
8233 else
8234 adj = STEP2 + 1;
8235 count2 = (adj + N22 - N21) / STEP2;
8236 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8237 if (cond1 is <)
8238 adj = STEP1 - 1;
8239 else
8240 adj = STEP1 + 1;
8241 count1 = (adj + N12 - N11) / STEP1;
8242 count = count1 * count2 * count3;
8243 goto Z1;
8245 count = 0;
8247 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8248 if (more) goto L0; else goto L3;
8250 V = istart0;
8251 T = V;
8252 V3 = N31 + (T % count3) * STEP3;
8253 T = T / count3;
8254 V2 = N21 + (T % count2) * STEP2;
8255 T = T / count2;
8256 V1 = N11 + T * STEP1;
8257 iend = iend0;
8259 BODY;
8260 V += 1;
8261 if (V < iend) goto L10; else goto L2;
8262 L10:
8263 V3 += STEP3;
8264 if (V3 cond3 N32) goto L1; else goto L11;
8265 L11:
8266 V3 = N31;
8267 V2 += STEP2;
8268 if (V2 cond2 N22) goto L1; else goto L12;
8269 L12:
8270 V2 = N21;
8271 V1 += STEP1;
8272 goto L1;
8274 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8279 static void
8280 expand_omp_for_generic (struct omp_region *region,
8281 struct omp_for_data *fd,
8282 enum built_in_function start_fn,
8283 enum built_in_function next_fn,
8284 gimple *inner_stmt)
8286 tree type, istart0, iend0, iend;
8287 tree t, vmain, vback, bias = NULL_TREE;
8288 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8289 basic_block l2_bb = NULL, l3_bb = NULL;
8290 gimple_stmt_iterator gsi;
8291 gassign *assign_stmt;
8292 bool in_combined_parallel = is_combined_parallel (region);
8293 bool broken_loop = region->cont == NULL;
8294 edge e, ne;
8295 tree *counts = NULL;
8296 int i;
8297 bool ordered_lastprivate = false;
8299 gcc_assert (!broken_loop || !in_combined_parallel);
8300 gcc_assert (fd->iter_type == long_integer_type_node
8301 || !in_combined_parallel);
8303 entry_bb = region->entry;
8304 cont_bb = region->cont;
8305 collapse_bb = NULL;
8306 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8307 gcc_assert (broken_loop
8308 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8309 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8310 l1_bb = single_succ (l0_bb);
8311 if (!broken_loop)
8313 l2_bb = create_empty_bb (cont_bb);
8314 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8315 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8316 == l1_bb));
8317 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8319 else
8320 l2_bb = NULL;
8321 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8322 exit_bb = region->exit;
8324 gsi = gsi_last_bb (entry_bb);
8326 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8327 if (fd->ordered
8328 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8329 OMP_CLAUSE_LASTPRIVATE))
8330 ordered_lastprivate = false;
8331 if (fd->collapse > 1 || fd->ordered)
8333 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8334 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8336 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8337 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8338 zero_iter1_bb, first_zero_iter1,
8339 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8341 if (zero_iter1_bb)
8343 /* Some counts[i] vars might be uninitialized if
8344 some loop has zero iterations. But the body shouldn't
8345 be executed in that case, so just avoid uninit warnings. */
8346 for (i = first_zero_iter1;
8347 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8348 if (SSA_VAR_P (counts[i]))
8349 TREE_NO_WARNING (counts[i]) = 1;
8350 gsi_prev (&gsi);
8351 e = split_block (entry_bb, gsi_stmt (gsi));
8352 entry_bb = e->dest;
8353 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8354 gsi = gsi_last_bb (entry_bb);
8355 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8356 get_immediate_dominator (CDI_DOMINATORS,
8357 zero_iter1_bb));
8359 if (zero_iter2_bb)
8361 /* Some counts[i] vars might be uninitialized if
8362 some loop has zero iterations. But the body shouldn't
8363 be executed in that case, so just avoid uninit warnings. */
8364 for (i = first_zero_iter2; i < fd->ordered; i++)
8365 if (SSA_VAR_P (counts[i]))
8366 TREE_NO_WARNING (counts[i]) = 1;
8367 if (zero_iter1_bb)
8368 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8369 else
8371 gsi_prev (&gsi);
8372 e = split_block (entry_bb, gsi_stmt (gsi));
8373 entry_bb = e->dest;
8374 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8375 gsi = gsi_last_bb (entry_bb);
8376 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8377 get_immediate_dominator
8378 (CDI_DOMINATORS, zero_iter2_bb));
8381 if (fd->collapse == 1)
8383 counts[0] = fd->loop.n2;
8384 fd->loop = fd->loops[0];
8388 type = TREE_TYPE (fd->loop.v);
8389 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8390 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8391 TREE_ADDRESSABLE (istart0) = 1;
8392 TREE_ADDRESSABLE (iend0) = 1;
8394 /* See if we need to bias by LLONG_MIN. */
8395 if (fd->iter_type == long_long_unsigned_type_node
8396 && TREE_CODE (type) == INTEGER_TYPE
8397 && !TYPE_UNSIGNED (type)
8398 && fd->ordered == 0)
8400 tree n1, n2;
8402 if (fd->loop.cond_code == LT_EXPR)
8404 n1 = fd->loop.n1;
8405 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8407 else
8409 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8410 n2 = fd->loop.n1;
8412 if (TREE_CODE (n1) != INTEGER_CST
8413 || TREE_CODE (n2) != INTEGER_CST
8414 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8415 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8418 gimple_stmt_iterator gsif = gsi;
8419 gsi_prev (&gsif);
8421 tree arr = NULL_TREE;
8422 if (in_combined_parallel)
8424 gcc_assert (fd->ordered == 0);
8425 /* In a combined parallel loop, emit a call to
8426 GOMP_loop_foo_next. */
8427 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8428 build_fold_addr_expr (istart0),
8429 build_fold_addr_expr (iend0));
8431 else
8433 tree t0, t1, t2, t3, t4;
8434 /* If this is not a combined parallel loop, emit a call to
8435 GOMP_loop_foo_start in ENTRY_BB. */
8436 t4 = build_fold_addr_expr (iend0);
8437 t3 = build_fold_addr_expr (istart0);
8438 if (fd->ordered)
8440 t0 = build_int_cst (unsigned_type_node,
8441 fd->ordered - fd->collapse + 1);
8442 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8443 fd->ordered
8444 - fd->collapse + 1),
8445 ".omp_counts");
8446 DECL_NAMELESS (arr) = 1;
8447 TREE_ADDRESSABLE (arr) = 1;
8448 TREE_STATIC (arr) = 1;
8449 vec<constructor_elt, va_gc> *v;
8450 vec_alloc (v, fd->ordered - fd->collapse + 1);
8451 int idx;
8453 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8455 tree c;
8456 if (idx == 0 && fd->collapse > 1)
8457 c = fd->loop.n2;
8458 else
8459 c = counts[idx + fd->collapse - 1];
8460 tree purpose = size_int (idx);
8461 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8462 if (TREE_CODE (c) != INTEGER_CST)
8463 TREE_STATIC (arr) = 0;
8466 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8467 if (!TREE_STATIC (arr))
8468 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8469 void_type_node, arr),
8470 true, NULL_TREE, true, GSI_SAME_STMT);
8471 t1 = build_fold_addr_expr (arr);
8472 t2 = NULL_TREE;
8474 else
8476 t2 = fold_convert (fd->iter_type, fd->loop.step);
8477 t1 = fd->loop.n2;
8478 t0 = fd->loop.n1;
8479 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8481 tree innerc
8482 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8483 OMP_CLAUSE__LOOPTEMP_);
8484 gcc_assert (innerc);
8485 t0 = OMP_CLAUSE_DECL (innerc);
8486 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8487 OMP_CLAUSE__LOOPTEMP_);
8488 gcc_assert (innerc);
8489 t1 = OMP_CLAUSE_DECL (innerc);
8491 if (POINTER_TYPE_P (TREE_TYPE (t0))
8492 && TYPE_PRECISION (TREE_TYPE (t0))
8493 != TYPE_PRECISION (fd->iter_type))
8495 /* Avoid casting pointers to integer of a different size. */
8496 tree itype = signed_type_for (type);
8497 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8498 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8500 else
8502 t1 = fold_convert (fd->iter_type, t1);
8503 t0 = fold_convert (fd->iter_type, t0);
8505 if (bias)
8507 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8508 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8511 if (fd->iter_type == long_integer_type_node || fd->ordered)
8513 if (fd->chunk_size)
8515 t = fold_convert (fd->iter_type, fd->chunk_size);
8516 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8517 if (fd->ordered)
8518 t = build_call_expr (builtin_decl_explicit (start_fn),
8519 5, t0, t1, t, t3, t4);
8520 else
8521 t = build_call_expr (builtin_decl_explicit (start_fn),
8522 6, t0, t1, t2, t, t3, t4);
8524 else if (fd->ordered)
8525 t = build_call_expr (builtin_decl_explicit (start_fn),
8526 4, t0, t1, t3, t4);
8527 else
8528 t = build_call_expr (builtin_decl_explicit (start_fn),
8529 5, t0, t1, t2, t3, t4);
8531 else
8533 tree t5;
8534 tree c_bool_type;
8535 tree bfn_decl;
8537 /* The GOMP_loop_ull_*start functions have additional boolean
8538 argument, true for < loops and false for > loops.
8539 In Fortran, the C bool type can be different from
8540 boolean_type_node. */
8541 bfn_decl = builtin_decl_explicit (start_fn);
8542 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8543 t5 = build_int_cst (c_bool_type,
8544 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8545 if (fd->chunk_size)
8547 tree bfn_decl = builtin_decl_explicit (start_fn);
8548 t = fold_convert (fd->iter_type, fd->chunk_size);
8549 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8550 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8552 else
8553 t = build_call_expr (builtin_decl_explicit (start_fn),
8554 6, t5, t0, t1, t2, t3, t4);
8557 if (TREE_TYPE (t) != boolean_type_node)
8558 t = fold_build2 (NE_EXPR, boolean_type_node,
8559 t, build_int_cst (TREE_TYPE (t), 0));
8560 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8561 true, GSI_SAME_STMT);
8562 if (arr && !TREE_STATIC (arr))
8564 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8565 TREE_THIS_VOLATILE (clobber) = 1;
8566 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8567 GSI_SAME_STMT);
8569 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8571 /* Remove the GIMPLE_OMP_FOR statement. */
8572 gsi_remove (&gsi, true);
8574 if (gsi_end_p (gsif))
8575 gsif = gsi_after_labels (gsi_bb (gsif));
8576 gsi_next (&gsif);
8578 /* Iteration setup for sequential loop goes in L0_BB. */
8579 tree startvar = fd->loop.v;
8580 tree endvar = NULL_TREE;
8582 if (gimple_omp_for_combined_p (fd->for_stmt))
8584 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8585 && gimple_omp_for_kind (inner_stmt)
8586 == GF_OMP_FOR_KIND_SIMD);
8587 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8588 OMP_CLAUSE__LOOPTEMP_);
8589 gcc_assert (innerc);
8590 startvar = OMP_CLAUSE_DECL (innerc);
8591 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8592 OMP_CLAUSE__LOOPTEMP_);
8593 gcc_assert (innerc);
8594 endvar = OMP_CLAUSE_DECL (innerc);
8597 gsi = gsi_start_bb (l0_bb);
8598 t = istart0;
8599 if (fd->ordered && fd->collapse == 1)
8600 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8601 fold_convert (fd->iter_type, fd->loop.step));
8602 else if (bias)
8603 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8604 if (fd->ordered && fd->collapse == 1)
8606 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8607 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8608 fd->loop.n1, fold_convert (sizetype, t));
8609 else
8611 t = fold_convert (TREE_TYPE (startvar), t);
8612 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8613 fd->loop.n1, t);
8616 else
8618 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8619 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8620 t = fold_convert (TREE_TYPE (startvar), t);
8622 t = force_gimple_operand_gsi (&gsi, t,
8623 DECL_P (startvar)
8624 && TREE_ADDRESSABLE (startvar),
8625 NULL_TREE, false, GSI_CONTINUE_LINKING);
8626 assign_stmt = gimple_build_assign (startvar, t);
8627 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8629 t = iend0;
8630 if (fd->ordered && fd->collapse == 1)
8631 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8632 fold_convert (fd->iter_type, fd->loop.step));
8633 else if (bias)
8634 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8635 if (fd->ordered && fd->collapse == 1)
8637 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8638 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8639 fd->loop.n1, fold_convert (sizetype, t));
8640 else
8642 t = fold_convert (TREE_TYPE (startvar), t);
8643 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8644 fd->loop.n1, t);
8647 else
8649 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8650 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8651 t = fold_convert (TREE_TYPE (startvar), t);
8653 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8654 false, GSI_CONTINUE_LINKING);
8655 if (endvar)
8657 assign_stmt = gimple_build_assign (endvar, iend);
8658 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8659 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8660 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8661 else
8662 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8663 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8665 /* Handle linear clause adjustments. */
8666 tree itercnt = NULL_TREE;
8667 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8668 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8669 c; c = OMP_CLAUSE_CHAIN (c))
8670 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8671 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8673 tree d = OMP_CLAUSE_DECL (c);
8674 bool is_ref = is_reference (d);
8675 tree t = d, a, dest;
8676 if (is_ref)
8677 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8678 tree type = TREE_TYPE (t);
8679 if (POINTER_TYPE_P (type))
8680 type = sizetype;
8681 dest = unshare_expr (t);
8682 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8683 expand_omp_build_assign (&gsif, v, t);
8684 if (itercnt == NULL_TREE)
8686 itercnt = startvar;
8687 tree n1 = fd->loop.n1;
8688 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8690 itercnt
8691 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8692 itercnt);
8693 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8695 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8696 itercnt, n1);
8697 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8698 itercnt, fd->loop.step);
8699 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8700 NULL_TREE, false,
8701 GSI_CONTINUE_LINKING);
8703 a = fold_build2 (MULT_EXPR, type,
8704 fold_convert (type, itercnt),
8705 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8706 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8707 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8708 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8709 false, GSI_CONTINUE_LINKING);
8710 assign_stmt = gimple_build_assign (dest, t);
8711 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8713 if (fd->collapse > 1)
8714 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8716 if (fd->ordered)
8718 /* Until now, counts array contained number of iterations or
8719 variable containing it for ith loop. From now on, we need
8720 those counts only for collapsed loops, and only for the 2nd
8721 till the last collapsed one. Move those one element earlier,
8722 we'll use counts[fd->collapse - 1] for the first source/sink
8723 iteration counter and so on and counts[fd->ordered]
8724 as the array holding the current counter values for
8725 depend(source). */
8726 if (fd->collapse > 1)
8727 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8728 if (broken_loop)
8730 int i;
8731 for (i = fd->collapse; i < fd->ordered; i++)
8733 tree type = TREE_TYPE (fd->loops[i].v);
8734 tree this_cond
8735 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8736 fold_convert (type, fd->loops[i].n1),
8737 fold_convert (type, fd->loops[i].n2));
8738 if (!integer_onep (this_cond))
8739 break;
8741 if (i < fd->ordered)
8743 cont_bb
8744 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8745 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8746 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8747 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8748 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8749 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8750 make_edge (cont_bb, l1_bb, 0);
8751 l2_bb = create_empty_bb (cont_bb);
8752 broken_loop = false;
8755 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8756 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8757 ordered_lastprivate);
8758 if (counts[fd->collapse - 1])
8760 gcc_assert (fd->collapse == 1);
8761 gsi = gsi_last_bb (l0_bb);
8762 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8763 istart0, true);
8764 gsi = gsi_last_bb (cont_bb);
8765 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8766 build_int_cst (fd->iter_type, 1));
8767 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8768 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8769 size_zero_node, NULL_TREE, NULL_TREE);
8770 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8771 t = counts[fd->collapse - 1];
8773 else if (fd->collapse > 1)
8774 t = fd->loop.v;
8775 else
8777 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8778 fd->loops[0].v, fd->loops[0].n1);
8779 t = fold_convert (fd->iter_type, t);
8781 gsi = gsi_last_bb (l0_bb);
8782 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8783 size_zero_node, NULL_TREE, NULL_TREE);
8784 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8785 false, GSI_CONTINUE_LINKING);
8786 expand_omp_build_assign (&gsi, aref, t, true);
8789 if (!broken_loop)
8791 /* Code to control the increment and predicate for the sequential
8792 loop goes in the CONT_BB. */
8793 gsi = gsi_last_bb (cont_bb);
8794 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8795 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8796 vmain = gimple_omp_continue_control_use (cont_stmt);
8797 vback = gimple_omp_continue_control_def (cont_stmt);
8799 if (!gimple_omp_for_combined_p (fd->for_stmt))
8801 if (POINTER_TYPE_P (type))
8802 t = fold_build_pointer_plus (vmain, fd->loop.step);
8803 else
8804 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8805 t = force_gimple_operand_gsi (&gsi, t,
8806 DECL_P (vback)
8807 && TREE_ADDRESSABLE (vback),
8808 NULL_TREE, true, GSI_SAME_STMT);
8809 assign_stmt = gimple_build_assign (vback, t);
8810 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8812 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8814 if (fd->collapse > 1)
8815 t = fd->loop.v;
8816 else
8818 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8819 fd->loops[0].v, fd->loops[0].n1);
8820 t = fold_convert (fd->iter_type, t);
8822 tree aref = build4 (ARRAY_REF, fd->iter_type,
8823 counts[fd->ordered], size_zero_node,
8824 NULL_TREE, NULL_TREE);
8825 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8826 true, GSI_SAME_STMT);
8827 expand_omp_build_assign (&gsi, aref, t);
8830 t = build2 (fd->loop.cond_code, boolean_type_node,
8831 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8832 iend);
8833 gcond *cond_stmt = gimple_build_cond_empty (t);
8834 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8837 /* Remove GIMPLE_OMP_CONTINUE. */
8838 gsi_remove (&gsi, true);
8840 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8841 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8843 /* Emit code to get the next parallel iteration in L2_BB. */
8844 gsi = gsi_start_bb (l2_bb);
8846 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8847 build_fold_addr_expr (istart0),
8848 build_fold_addr_expr (iend0));
8849 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8850 false, GSI_CONTINUE_LINKING);
8851 if (TREE_TYPE (t) != boolean_type_node)
8852 t = fold_build2 (NE_EXPR, boolean_type_node,
8853 t, build_int_cst (TREE_TYPE (t), 0));
8854 gcond *cond_stmt = gimple_build_cond_empty (t);
8855 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
8858 /* Add the loop cleanup function. */
8859 gsi = gsi_last_bb (exit_bb);
8860 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8861 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
8862 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8863 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
8864 else
8865 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
8866 gcall *call_stmt = gimple_build_call (t, 0);
8867 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8868 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8869 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
8870 if (fd->ordered)
8872 tree arr = counts[fd->ordered];
8873 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8874 TREE_THIS_VOLATILE (clobber) = 1;
8875 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8876 GSI_SAME_STMT);
8878 gsi_remove (&gsi, true);
8880 /* Connect the new blocks. */
8881 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8882 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
8884 if (!broken_loop)
8886 gimple_seq phis;
8888 e = find_edge (cont_bb, l3_bb);
8889 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8891 phis = phi_nodes (l3_bb);
8892 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8894 gimple *phi = gsi_stmt (gsi);
8895 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8896 PHI_ARG_DEF_FROM_EDGE (phi, e));
8898 remove_edge (e);
8900 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
8901 e = find_edge (cont_bb, l1_bb);
8902 if (e == NULL)
8904 e = BRANCH_EDGE (cont_bb);
8905 gcc_assert (single_succ (e->dest) == l1_bb);
8907 if (gimple_omp_for_combined_p (fd->for_stmt))
8909 remove_edge (e);
8910 e = NULL;
8912 else if (fd->collapse > 1)
8914 remove_edge (e);
8915 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8917 else
8918 e->flags = EDGE_TRUE_VALUE;
8919 if (e)
8921 e->probability = REG_BR_PROB_BASE * 7 / 8;
8922 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8924 else
8926 e = find_edge (cont_bb, l2_bb);
8927 e->flags = EDGE_FALLTHRU;
8929 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
8931 if (gimple_in_ssa_p (cfun))
8933 /* Add phis to the outer loop that connect to the phis in the inner,
8934 original loop, and move the loop entry value of the inner phi to
8935 the loop entry value of the outer phi. */
8936 gphi_iterator psi;
8937 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8939 source_location locus;
8940 gphi *nphi;
8941 gphi *exit_phi = psi.phi ();
8943 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8944 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8946 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8947 edge latch_to_l1 = find_edge (latch, l1_bb);
8948 gphi *inner_phi
8949 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8951 tree t = gimple_phi_result (exit_phi);
8952 tree new_res = copy_ssa_name (t, NULL);
8953 nphi = create_phi_node (new_res, l0_bb);
8955 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8956 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8957 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8958 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8959 add_phi_arg (nphi, t, entry_to_l0, locus);
8961 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8962 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8964 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8968 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8969 recompute_dominator (CDI_DOMINATORS, l2_bb));
8970 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8971 recompute_dominator (CDI_DOMINATORS, l3_bb));
8972 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8973 recompute_dominator (CDI_DOMINATORS, l0_bb));
8974 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8975 recompute_dominator (CDI_DOMINATORS, l1_bb));
8977 /* We enter expand_omp_for_generic with a loop. This original loop may
8978 have its own loop struct, or it may be part of an outer loop struct
8979 (which may be the fake loop). */
8980 struct loop *outer_loop = entry_bb->loop_father;
8981 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8983 add_bb_to_loop (l2_bb, outer_loop);
8985 /* We've added a new loop around the original loop. Allocate the
8986 corresponding loop struct. */
8987 struct loop *new_loop = alloc_loop ();
8988 new_loop->header = l0_bb;
8989 new_loop->latch = l2_bb;
8990 add_loop (new_loop, outer_loop);
8992 /* Allocate a loop structure for the original loop unless we already
8993 had one. */
8994 if (!orig_loop_has_loop_struct
8995 && !gimple_omp_for_combined_p (fd->for_stmt))
8997 struct loop *orig_loop = alloc_loop ();
8998 orig_loop->header = l1_bb;
8999 /* The loop may have multiple latches. */
9000 add_loop (orig_loop, new_loop);
9006 /* A subroutine of expand_omp_for. Generate code for a parallel
9007 loop with static schedule and no specified chunk size. Given
9008 parameters:
9010 for (V = N1; V cond N2; V += STEP) BODY;
9012 where COND is "<" or ">", we generate pseudocode
9014 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9015 if (cond is <)
9016 adj = STEP - 1;
9017 else
9018 adj = STEP + 1;
9019 if ((__typeof (V)) -1 > 0 && cond is >)
9020 n = -(adj + N2 - N1) / -STEP;
9021 else
9022 n = (adj + N2 - N1) / STEP;
9023 q = n / nthreads;
9024 tt = n % nthreads;
9025 if (threadid < tt) goto L3; else goto L4;
9027 tt = 0;
9028 q = q + 1;
9030 s0 = q * threadid + tt;
9031 e0 = s0 + q;
9032 V = s0 * STEP + N1;
9033 if (s0 >= e0) goto L2; else goto L0;
9035 e = e0 * STEP + N1;
9037 BODY;
9038 V += STEP;
9039 if (V cond e) goto L1;
9043 static void
9044 expand_omp_for_static_nochunk (struct omp_region *region,
9045 struct omp_for_data *fd,
9046 gimple *inner_stmt)
9048 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9049 tree type, itype, vmain, vback;
9050 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9051 basic_block body_bb, cont_bb, collapse_bb = NULL;
9052 basic_block fin_bb;
9053 gimple_stmt_iterator gsi;
9054 edge ep;
9055 bool broken_loop = region->cont == NULL;
9056 tree *counts = NULL;
9057 tree n1, n2, step;
9059 itype = type = TREE_TYPE (fd->loop.v);
9060 if (POINTER_TYPE_P (type))
9061 itype = signed_type_for (type);
9063 entry_bb = region->entry;
9064 cont_bb = region->cont;
9065 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9066 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9067 gcc_assert (broken_loop
9068 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9069 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9070 body_bb = single_succ (seq_start_bb);
9071 if (!broken_loop)
9073 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9074 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9075 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9077 exit_bb = region->exit;
9079 /* Iteration space partitioning goes in ENTRY_BB. */
9080 gsi = gsi_last_bb (entry_bb);
9081 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9083 if (fd->collapse > 1)
9085 int first_zero_iter = -1, dummy = -1;
9086 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9088 counts = XALLOCAVEC (tree, fd->collapse);
9089 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9090 fin_bb, first_zero_iter,
9091 dummy_bb, dummy, l2_dom_bb);
9092 t = NULL_TREE;
9094 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9095 t = integer_one_node;
9096 else
9097 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9098 fold_convert (type, fd->loop.n1),
9099 fold_convert (type, fd->loop.n2));
9100 if (fd->collapse == 1
9101 && TYPE_UNSIGNED (type)
9102 && (t == NULL_TREE || !integer_onep (t)))
9104 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9105 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9106 true, GSI_SAME_STMT);
9107 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9108 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9109 true, GSI_SAME_STMT);
9110 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9111 NULL_TREE, NULL_TREE);
9112 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9113 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9114 expand_omp_regimplify_p, NULL, NULL)
9115 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9116 expand_omp_regimplify_p, NULL, NULL))
9118 gsi = gsi_for_stmt (cond_stmt);
9119 gimple_regimplify_operands (cond_stmt, &gsi);
9121 ep = split_block (entry_bb, cond_stmt);
9122 ep->flags = EDGE_TRUE_VALUE;
9123 entry_bb = ep->dest;
9124 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9125 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9126 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9127 if (gimple_in_ssa_p (cfun))
9129 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9130 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9131 !gsi_end_p (gpi); gsi_next (&gpi))
9133 gphi *phi = gpi.phi ();
9134 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9135 ep, UNKNOWN_LOCATION);
9138 gsi = gsi_last_bb (entry_bb);
9141 switch (gimple_omp_for_kind (fd->for_stmt))
9143 case GF_OMP_FOR_KIND_FOR:
9144 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9145 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9146 break;
9147 case GF_OMP_FOR_KIND_DISTRIBUTE:
9148 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9149 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9150 break;
9151 default:
9152 gcc_unreachable ();
9154 nthreads = build_call_expr (nthreads, 0);
9155 nthreads = fold_convert (itype, nthreads);
9156 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9157 true, GSI_SAME_STMT);
9158 threadid = build_call_expr (threadid, 0);
9159 threadid = fold_convert (itype, threadid);
9160 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9161 true, GSI_SAME_STMT);
9163 n1 = fd->loop.n1;
9164 n2 = fd->loop.n2;
9165 step = fd->loop.step;
9166 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9168 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9169 OMP_CLAUSE__LOOPTEMP_);
9170 gcc_assert (innerc);
9171 n1 = OMP_CLAUSE_DECL (innerc);
9172 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9173 OMP_CLAUSE__LOOPTEMP_);
9174 gcc_assert (innerc);
9175 n2 = OMP_CLAUSE_DECL (innerc);
9177 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9178 true, NULL_TREE, true, GSI_SAME_STMT);
9179 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9180 true, NULL_TREE, true, GSI_SAME_STMT);
9181 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9182 true, NULL_TREE, true, GSI_SAME_STMT);
9184 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9185 t = fold_build2 (PLUS_EXPR, itype, step, t);
9186 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9187 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9188 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9189 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9190 fold_build1 (NEGATE_EXPR, itype, t),
9191 fold_build1 (NEGATE_EXPR, itype, step));
9192 else
9193 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9194 t = fold_convert (itype, t);
9195 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9197 q = create_tmp_reg (itype, "q");
9198 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9199 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9200 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9202 tt = create_tmp_reg (itype, "tt");
9203 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9204 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9205 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9207 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9208 gcond *cond_stmt = gimple_build_cond_empty (t);
9209 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9211 second_bb = split_block (entry_bb, cond_stmt)->dest;
9212 gsi = gsi_last_bb (second_bb);
9213 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9215 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9216 GSI_SAME_STMT);
9217 gassign *assign_stmt
9218 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9219 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9221 third_bb = split_block (second_bb, assign_stmt)->dest;
9222 gsi = gsi_last_bb (third_bb);
9223 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9225 t = build2 (MULT_EXPR, itype, q, threadid);
9226 t = build2 (PLUS_EXPR, itype, t, tt);
9227 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9229 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9230 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9232 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9233 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9235 /* Remove the GIMPLE_OMP_FOR statement. */
9236 gsi_remove (&gsi, true);
9238 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9239 gsi = gsi_start_bb (seq_start_bb);
9241 tree startvar = fd->loop.v;
9242 tree endvar = NULL_TREE;
9244 if (gimple_omp_for_combined_p (fd->for_stmt))
9246 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9247 ? gimple_omp_parallel_clauses (inner_stmt)
9248 : gimple_omp_for_clauses (inner_stmt);
9249 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9250 gcc_assert (innerc);
9251 startvar = OMP_CLAUSE_DECL (innerc);
9252 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9253 OMP_CLAUSE__LOOPTEMP_);
9254 gcc_assert (innerc);
9255 endvar = OMP_CLAUSE_DECL (innerc);
9256 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9257 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9259 int i;
9260 for (i = 1; i < fd->collapse; i++)
9262 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9263 OMP_CLAUSE__LOOPTEMP_);
9264 gcc_assert (innerc);
9266 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9267 OMP_CLAUSE__LOOPTEMP_);
9268 if (innerc)
9270 /* If needed (distribute parallel for with lastprivate),
9271 propagate down the total number of iterations. */
9272 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9273 fd->loop.n2);
9274 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9275 GSI_CONTINUE_LINKING);
9276 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9277 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9281 t = fold_convert (itype, s0);
9282 t = fold_build2 (MULT_EXPR, itype, t, step);
9283 if (POINTER_TYPE_P (type))
9284 t = fold_build_pointer_plus (n1, t);
9285 else
9286 t = fold_build2 (PLUS_EXPR, type, t, n1);
9287 t = fold_convert (TREE_TYPE (startvar), t);
9288 t = force_gimple_operand_gsi (&gsi, t,
9289 DECL_P (startvar)
9290 && TREE_ADDRESSABLE (startvar),
9291 NULL_TREE, false, GSI_CONTINUE_LINKING);
9292 assign_stmt = gimple_build_assign (startvar, t);
9293 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9295 t = fold_convert (itype, e0);
9296 t = fold_build2 (MULT_EXPR, itype, t, step);
9297 if (POINTER_TYPE_P (type))
9298 t = fold_build_pointer_plus (n1, t);
9299 else
9300 t = fold_build2 (PLUS_EXPR, type, t, n1);
9301 t = fold_convert (TREE_TYPE (startvar), t);
9302 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9303 false, GSI_CONTINUE_LINKING);
9304 if (endvar)
9306 assign_stmt = gimple_build_assign (endvar, e);
9307 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9308 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9309 assign_stmt = gimple_build_assign (fd->loop.v, e);
9310 else
9311 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9312 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9314 /* Handle linear clause adjustments. */
9315 tree itercnt = NULL_TREE;
9316 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9317 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9318 c; c = OMP_CLAUSE_CHAIN (c))
9319 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9320 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9322 tree d = OMP_CLAUSE_DECL (c);
9323 bool is_ref = is_reference (d);
9324 tree t = d, a, dest;
9325 if (is_ref)
9326 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9327 if (itercnt == NULL_TREE)
9329 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9331 itercnt = fold_build2 (MINUS_EXPR, itype,
9332 fold_convert (itype, n1),
9333 fold_convert (itype, fd->loop.n1));
9334 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9335 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9336 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9337 NULL_TREE, false,
9338 GSI_CONTINUE_LINKING);
9340 else
9341 itercnt = s0;
9343 tree type = TREE_TYPE (t);
9344 if (POINTER_TYPE_P (type))
9345 type = sizetype;
9346 a = fold_build2 (MULT_EXPR, type,
9347 fold_convert (type, itercnt),
9348 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9349 dest = unshare_expr (t);
9350 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9351 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9352 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9353 false, GSI_CONTINUE_LINKING);
9354 assign_stmt = gimple_build_assign (dest, t);
9355 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9357 if (fd->collapse > 1)
9358 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9360 if (!broken_loop)
9362 /* The code controlling the sequential loop replaces the
9363 GIMPLE_OMP_CONTINUE. */
9364 gsi = gsi_last_bb (cont_bb);
9365 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9366 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9367 vmain = gimple_omp_continue_control_use (cont_stmt);
9368 vback = gimple_omp_continue_control_def (cont_stmt);
9370 if (!gimple_omp_for_combined_p (fd->for_stmt))
9372 if (POINTER_TYPE_P (type))
9373 t = fold_build_pointer_plus (vmain, step);
9374 else
9375 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9376 t = force_gimple_operand_gsi (&gsi, t,
9377 DECL_P (vback)
9378 && TREE_ADDRESSABLE (vback),
9379 NULL_TREE, true, GSI_SAME_STMT);
9380 assign_stmt = gimple_build_assign (vback, t);
9381 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9383 t = build2 (fd->loop.cond_code, boolean_type_node,
9384 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9385 ? t : vback, e);
9386 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9389 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9390 gsi_remove (&gsi, true);
9392 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9393 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9396 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9397 gsi = gsi_last_bb (exit_bb);
9398 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9400 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9401 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9403 gsi_remove (&gsi, true);
9405 /* Connect all the blocks. */
9406 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9407 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9408 ep = find_edge (entry_bb, second_bb);
9409 ep->flags = EDGE_TRUE_VALUE;
9410 ep->probability = REG_BR_PROB_BASE / 4;
9411 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9412 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9414 if (!broken_loop)
9416 ep = find_edge (cont_bb, body_bb);
9417 if (ep == NULL)
9419 ep = BRANCH_EDGE (cont_bb);
9420 gcc_assert (single_succ (ep->dest) == body_bb);
9422 if (gimple_omp_for_combined_p (fd->for_stmt))
9424 remove_edge (ep);
9425 ep = NULL;
9427 else if (fd->collapse > 1)
9429 remove_edge (ep);
9430 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9432 else
9433 ep->flags = EDGE_TRUE_VALUE;
9434 find_edge (cont_bb, fin_bb)->flags
9435 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9438 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9439 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9440 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9442 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9443 recompute_dominator (CDI_DOMINATORS, body_bb));
9444 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9445 recompute_dominator (CDI_DOMINATORS, fin_bb));
9447 struct loop *loop = body_bb->loop_father;
9448 if (loop != entry_bb->loop_father)
9450 gcc_assert (loop->header == body_bb);
9451 gcc_assert (broken_loop
9452 || loop->latch == region->cont
9453 || single_pred (loop->latch) == region->cont);
9454 return;
9457 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9459 loop = alloc_loop ();
9460 loop->header = body_bb;
9461 if (collapse_bb == NULL)
9462 loop->latch = cont_bb;
9463 add_loop (loop, body_bb->loop_father);
9467 /* Return phi in E->DEST with ARG on edge E. */
9469 static gphi *
9470 find_phi_with_arg_on_edge (tree arg, edge e)
9472 basic_block bb = e->dest;
9474 for (gphi_iterator gpi = gsi_start_phis (bb);
9475 !gsi_end_p (gpi);
9476 gsi_next (&gpi))
9478 gphi *phi = gpi.phi ();
9479 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9480 return phi;
9483 return NULL;
9486 /* A subroutine of expand_omp_for. Generate code for a parallel
9487 loop with static schedule and a specified chunk size. Given
9488 parameters:
9490 for (V = N1; V cond N2; V += STEP) BODY;
9492 where COND is "<" or ">", we generate pseudocode
9494 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9495 if (cond is <)
9496 adj = STEP - 1;
9497 else
9498 adj = STEP + 1;
9499 if ((__typeof (V)) -1 > 0 && cond is >)
9500 n = -(adj + N2 - N1) / -STEP;
9501 else
9502 n = (adj + N2 - N1) / STEP;
9503 trip = 0;
9504 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9505 here so that V is defined
9506 if the loop is not entered
9508 s0 = (trip * nthreads + threadid) * CHUNK;
9509 e0 = min(s0 + CHUNK, n);
9510 if (s0 < n) goto L1; else goto L4;
9512 V = s0 * STEP + N1;
9513 e = e0 * STEP + N1;
9515 BODY;
9516 V += STEP;
9517 if (V cond e) goto L2; else goto L3;
9519 trip += 1;
9520 goto L0;
9524 static void
9525 expand_omp_for_static_chunk (struct omp_region *region,
9526 struct omp_for_data *fd, gimple *inner_stmt)
9528 tree n, s0, e0, e, t;
9529 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9530 tree type, itype, vmain, vback, vextra;
9531 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9532 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9533 gimple_stmt_iterator gsi;
9534 edge se;
9535 bool broken_loop = region->cont == NULL;
9536 tree *counts = NULL;
9537 tree n1, n2, step;
9539 itype = type = TREE_TYPE (fd->loop.v);
9540 if (POINTER_TYPE_P (type))
9541 itype = signed_type_for (type);
9543 entry_bb = region->entry;
9544 se = split_block (entry_bb, last_stmt (entry_bb));
9545 entry_bb = se->src;
9546 iter_part_bb = se->dest;
9547 cont_bb = region->cont;
9548 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9549 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9550 gcc_assert (broken_loop
9551 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9552 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9553 body_bb = single_succ (seq_start_bb);
9554 if (!broken_loop)
9556 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9557 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9558 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9559 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9561 exit_bb = region->exit;
9563 /* Trip and adjustment setup goes in ENTRY_BB. */
9564 gsi = gsi_last_bb (entry_bb);
9565 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9567 if (fd->collapse > 1)
9569 int first_zero_iter = -1, dummy = -1;
9570 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9572 counts = XALLOCAVEC (tree, fd->collapse);
9573 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9574 fin_bb, first_zero_iter,
9575 dummy_bb, dummy, l2_dom_bb);
9576 t = NULL_TREE;
9578 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9579 t = integer_one_node;
9580 else
9581 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9582 fold_convert (type, fd->loop.n1),
9583 fold_convert (type, fd->loop.n2));
9584 if (fd->collapse == 1
9585 && TYPE_UNSIGNED (type)
9586 && (t == NULL_TREE || !integer_onep (t)))
9588 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9589 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9590 true, GSI_SAME_STMT);
9591 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9592 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9593 true, GSI_SAME_STMT);
9594 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9595 NULL_TREE, NULL_TREE);
9596 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9597 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9598 expand_omp_regimplify_p, NULL, NULL)
9599 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9600 expand_omp_regimplify_p, NULL, NULL))
9602 gsi = gsi_for_stmt (cond_stmt);
9603 gimple_regimplify_operands (cond_stmt, &gsi);
9605 se = split_block (entry_bb, cond_stmt);
9606 se->flags = EDGE_TRUE_VALUE;
9607 entry_bb = se->dest;
9608 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9609 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9610 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9611 if (gimple_in_ssa_p (cfun))
9613 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9614 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9615 !gsi_end_p (gpi); gsi_next (&gpi))
9617 gphi *phi = gpi.phi ();
9618 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9619 se, UNKNOWN_LOCATION);
9622 gsi = gsi_last_bb (entry_bb);
9625 switch (gimple_omp_for_kind (fd->for_stmt))
9627 case GF_OMP_FOR_KIND_FOR:
9628 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9629 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9630 break;
9631 case GF_OMP_FOR_KIND_DISTRIBUTE:
9632 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9633 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9634 break;
9635 default:
9636 gcc_unreachable ();
9638 nthreads = build_call_expr (nthreads, 0);
9639 nthreads = fold_convert (itype, nthreads);
9640 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9641 true, GSI_SAME_STMT);
9642 threadid = build_call_expr (threadid, 0);
9643 threadid = fold_convert (itype, threadid);
9644 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9645 true, GSI_SAME_STMT);
9647 n1 = fd->loop.n1;
9648 n2 = fd->loop.n2;
9649 step = fd->loop.step;
9650 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9652 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9653 OMP_CLAUSE__LOOPTEMP_);
9654 gcc_assert (innerc);
9655 n1 = OMP_CLAUSE_DECL (innerc);
9656 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9657 OMP_CLAUSE__LOOPTEMP_);
9658 gcc_assert (innerc);
9659 n2 = OMP_CLAUSE_DECL (innerc);
9661 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9662 true, NULL_TREE, true, GSI_SAME_STMT);
9663 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9664 true, NULL_TREE, true, GSI_SAME_STMT);
9665 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9666 true, NULL_TREE, true, GSI_SAME_STMT);
9667 tree chunk_size = fold_convert (itype, fd->chunk_size);
9668 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9669 chunk_size
9670 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9671 GSI_SAME_STMT);
9673 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9674 t = fold_build2 (PLUS_EXPR, itype, step, t);
9675 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9676 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9677 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9678 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9679 fold_build1 (NEGATE_EXPR, itype, t),
9680 fold_build1 (NEGATE_EXPR, itype, step));
9681 else
9682 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9683 t = fold_convert (itype, t);
9684 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9685 true, GSI_SAME_STMT);
9687 trip_var = create_tmp_reg (itype, ".trip");
9688 if (gimple_in_ssa_p (cfun))
9690 trip_init = make_ssa_name (trip_var);
9691 trip_main = make_ssa_name (trip_var);
9692 trip_back = make_ssa_name (trip_var);
9694 else
9696 trip_init = trip_var;
9697 trip_main = trip_var;
9698 trip_back = trip_var;
9701 gassign *assign_stmt
9702 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9703 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9705 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9706 t = fold_build2 (MULT_EXPR, itype, t, step);
9707 if (POINTER_TYPE_P (type))
9708 t = fold_build_pointer_plus (n1, t);
9709 else
9710 t = fold_build2 (PLUS_EXPR, type, t, n1);
9711 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9712 true, GSI_SAME_STMT);
9714 /* Remove the GIMPLE_OMP_FOR. */
9715 gsi_remove (&gsi, true);
9717 gimple_stmt_iterator gsif = gsi;
9719 /* Iteration space partitioning goes in ITER_PART_BB. */
9720 gsi = gsi_last_bb (iter_part_bb);
9722 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9723 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9724 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9725 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9726 false, GSI_CONTINUE_LINKING);
9728 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9729 t = fold_build2 (MIN_EXPR, itype, t, n);
9730 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9731 false, GSI_CONTINUE_LINKING);
9733 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9734 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9736 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9737 gsi = gsi_start_bb (seq_start_bb);
9739 tree startvar = fd->loop.v;
9740 tree endvar = NULL_TREE;
9742 if (gimple_omp_for_combined_p (fd->for_stmt))
9744 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9745 ? gimple_omp_parallel_clauses (inner_stmt)
9746 : gimple_omp_for_clauses (inner_stmt);
9747 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9748 gcc_assert (innerc);
9749 startvar = OMP_CLAUSE_DECL (innerc);
9750 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9751 OMP_CLAUSE__LOOPTEMP_);
9752 gcc_assert (innerc);
9753 endvar = OMP_CLAUSE_DECL (innerc);
9754 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9755 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9757 int i;
9758 for (i = 1; i < fd->collapse; i++)
9760 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9761 OMP_CLAUSE__LOOPTEMP_);
9762 gcc_assert (innerc);
9764 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9765 OMP_CLAUSE__LOOPTEMP_);
9766 if (innerc)
9768 /* If needed (distribute parallel for with lastprivate),
9769 propagate down the total number of iterations. */
9770 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9771 fd->loop.n2);
9772 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9773 GSI_CONTINUE_LINKING);
9774 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9775 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9780 t = fold_convert (itype, s0);
9781 t = fold_build2 (MULT_EXPR, itype, t, step);
9782 if (POINTER_TYPE_P (type))
9783 t = fold_build_pointer_plus (n1, t);
9784 else
9785 t = fold_build2 (PLUS_EXPR, type, t, n1);
9786 t = fold_convert (TREE_TYPE (startvar), t);
9787 t = force_gimple_operand_gsi (&gsi, t,
9788 DECL_P (startvar)
9789 && TREE_ADDRESSABLE (startvar),
9790 NULL_TREE, false, GSI_CONTINUE_LINKING);
9791 assign_stmt = gimple_build_assign (startvar, t);
9792 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9794 t = fold_convert (itype, e0);
9795 t = fold_build2 (MULT_EXPR, itype, t, step);
9796 if (POINTER_TYPE_P (type))
9797 t = fold_build_pointer_plus (n1, t);
9798 else
9799 t = fold_build2 (PLUS_EXPR, type, t, n1);
9800 t = fold_convert (TREE_TYPE (startvar), t);
9801 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9802 false, GSI_CONTINUE_LINKING);
9803 if (endvar)
9805 assign_stmt = gimple_build_assign (endvar, e);
9806 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9807 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9808 assign_stmt = gimple_build_assign (fd->loop.v, e);
9809 else
9810 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9811 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9813 /* Handle linear clause adjustments. */
9814 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9815 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9816 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9817 c; c = OMP_CLAUSE_CHAIN (c))
9818 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9819 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9821 tree d = OMP_CLAUSE_DECL (c);
9822 bool is_ref = is_reference (d);
9823 tree t = d, a, dest;
9824 if (is_ref)
9825 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9826 tree type = TREE_TYPE (t);
9827 if (POINTER_TYPE_P (type))
9828 type = sizetype;
9829 dest = unshare_expr (t);
9830 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9831 expand_omp_build_assign (&gsif, v, t);
9832 if (itercnt == NULL_TREE)
9834 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9836 itercntbias
9837 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9838 fold_convert (itype, fd->loop.n1));
9839 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9840 itercntbias, step);
9841 itercntbias
9842 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9843 NULL_TREE, true,
9844 GSI_SAME_STMT);
9845 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9846 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9847 NULL_TREE, false,
9848 GSI_CONTINUE_LINKING);
9850 else
9851 itercnt = s0;
9853 a = fold_build2 (MULT_EXPR, type,
9854 fold_convert (type, itercnt),
9855 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9856 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9857 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9858 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9859 false, GSI_CONTINUE_LINKING);
9860 assign_stmt = gimple_build_assign (dest, t);
9861 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9863 if (fd->collapse > 1)
9864 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9866 if (!broken_loop)
9868 /* The code controlling the sequential loop goes in CONT_BB,
9869 replacing the GIMPLE_OMP_CONTINUE. */
9870 gsi = gsi_last_bb (cont_bb);
9871 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9872 vmain = gimple_omp_continue_control_use (cont_stmt);
9873 vback = gimple_omp_continue_control_def (cont_stmt);
9875 if (!gimple_omp_for_combined_p (fd->for_stmt))
9877 if (POINTER_TYPE_P (type))
9878 t = fold_build_pointer_plus (vmain, step);
9879 else
9880 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9881 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9882 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9883 true, GSI_SAME_STMT);
9884 assign_stmt = gimple_build_assign (vback, t);
9885 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9887 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9888 t = build2 (EQ_EXPR, boolean_type_node,
9889 build_int_cst (itype, 0),
9890 build_int_cst (itype, 1));
9891 else
9892 t = build2 (fd->loop.cond_code, boolean_type_node,
9893 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9894 ? t : vback, e);
9895 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9898 /* Remove GIMPLE_OMP_CONTINUE. */
9899 gsi_remove (&gsi, true);
9901 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9902 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9904 /* Trip update code goes into TRIP_UPDATE_BB. */
9905 gsi = gsi_start_bb (trip_update_bb);
9907 t = build_int_cst (itype, 1);
9908 t = build2 (PLUS_EXPR, itype, trip_main, t);
9909 assign_stmt = gimple_build_assign (trip_back, t);
9910 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9913 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9914 gsi = gsi_last_bb (exit_bb);
9915 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9917 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9918 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9920 gsi_remove (&gsi, true);
9922 /* Connect the new blocks. */
9923 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9924 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
9926 if (!broken_loop)
9928 se = find_edge (cont_bb, body_bb);
9929 if (se == NULL)
9931 se = BRANCH_EDGE (cont_bb);
9932 gcc_assert (single_succ (se->dest) == body_bb);
9934 if (gimple_omp_for_combined_p (fd->for_stmt))
9936 remove_edge (se);
9937 se = NULL;
9939 else if (fd->collapse > 1)
9941 remove_edge (se);
9942 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9944 else
9945 se->flags = EDGE_TRUE_VALUE;
9946 find_edge (cont_bb, trip_update_bb)->flags
9947 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9949 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9952 if (gimple_in_ssa_p (cfun))
9954 gphi_iterator psi;
9955 gphi *phi;
9956 edge re, ene;
9957 edge_var_map *vm;
9958 size_t i;
9960 gcc_assert (fd->collapse == 1 && !broken_loop);
9962 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9963 remove arguments of the phi nodes in fin_bb. We need to create
9964 appropriate phi nodes in iter_part_bb instead. */
9965 se = find_edge (iter_part_bb, fin_bb);
9966 re = single_succ_edge (trip_update_bb);
9967 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
9968 ene = single_succ_edge (entry_bb);
9970 psi = gsi_start_phis (fin_bb);
9971 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
9972 gsi_next (&psi), ++i)
9974 gphi *nphi;
9975 source_location locus;
9977 phi = psi.phi ();
9978 t = gimple_phi_result (phi);
9979 gcc_assert (t == redirect_edge_var_map_result (vm));
9981 if (!single_pred_p (fin_bb))
9982 t = copy_ssa_name (t, phi);
9984 nphi = create_phi_node (t, iter_part_bb);
9986 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
9987 locus = gimple_phi_arg_location_from_edge (phi, se);
9989 /* A special case -- fd->loop.v is not yet computed in
9990 iter_part_bb, we need to use vextra instead. */
9991 if (t == fd->loop.v)
9992 t = vextra;
9993 add_phi_arg (nphi, t, ene, locus);
9994 locus = redirect_edge_var_map_location (vm);
9995 tree back_arg = redirect_edge_var_map_def (vm);
9996 add_phi_arg (nphi, back_arg, re, locus);
9997 edge ce = find_edge (cont_bb, body_bb);
9998 if (ce == NULL)
10000 ce = BRANCH_EDGE (cont_bb);
10001 gcc_assert (single_succ (ce->dest) == body_bb);
10002 ce = single_succ_edge (ce->dest);
10004 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10005 gcc_assert (inner_loop_phi != NULL);
10006 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10007 find_edge (seq_start_bb, body_bb), locus);
10009 if (!single_pred_p (fin_bb))
10010 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10012 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10013 redirect_edge_var_map_clear (re);
10014 if (single_pred_p (fin_bb))
10015 while (1)
10017 psi = gsi_start_phis (fin_bb);
10018 if (gsi_end_p (psi))
10019 break;
10020 remove_phi_node (&psi, false);
10023 /* Make phi node for trip. */
10024 phi = create_phi_node (trip_main, iter_part_bb);
10025 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10026 UNKNOWN_LOCATION);
10027 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10028 UNKNOWN_LOCATION);
10031 if (!broken_loop)
10032 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10033 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10034 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10035 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10036 recompute_dominator (CDI_DOMINATORS, fin_bb));
10037 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10038 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10039 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10040 recompute_dominator (CDI_DOMINATORS, body_bb));
10042 if (!broken_loop)
10044 struct loop *loop = body_bb->loop_father;
10045 struct loop *trip_loop = alloc_loop ();
10046 trip_loop->header = iter_part_bb;
10047 trip_loop->latch = trip_update_bb;
10048 add_loop (trip_loop, iter_part_bb->loop_father);
10050 if (loop != entry_bb->loop_father)
10052 gcc_assert (loop->header == body_bb);
10053 gcc_assert (loop->latch == region->cont
10054 || single_pred (loop->latch) == region->cont);
10055 trip_loop->inner = loop;
10056 return;
10059 if (!gimple_omp_for_combined_p (fd->for_stmt))
10061 loop = alloc_loop ();
10062 loop->header = body_bb;
10063 if (collapse_bb == NULL)
10064 loop->latch = cont_bb;
10065 add_loop (loop, trip_loop);
10070 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10071 Given parameters:
10072 for (V = N1; V cond N2; V += STEP) BODY;
10074 where COND is "<" or ">" or "!=", we generate pseudocode
10076 for (ind_var = low; ind_var < high; ind_var++)
10078 V = n1 + (ind_var * STEP)
10080 <BODY>
10083 In the above pseudocode, low and high are function parameters of the
10084 child function. In the function below, we are inserting a temp.
10085 variable that will be making a call to two OMP functions that will not be
10086 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10087 with _Cilk_for). These functions are replaced with low and high
10088 by the function that handles taskreg. */
10091 static void
10092 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10094 bool broken_loop = region->cont == NULL;
10095 basic_block entry_bb = region->entry;
10096 basic_block cont_bb = region->cont;
10098 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10099 gcc_assert (broken_loop
10100 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10101 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10102 basic_block l1_bb, l2_bb;
10104 if (!broken_loop)
10106 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10107 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10108 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10109 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10111 else
10113 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10114 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10115 l2_bb = single_succ (l1_bb);
10117 basic_block exit_bb = region->exit;
10118 basic_block l2_dom_bb = NULL;
10120 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10122 /* Below statements until the "tree high_val = ..." are pseudo statements
10123 used to pass information to be used by expand_omp_taskreg.
10124 low_val and high_val will be replaced by the __low and __high
10125 parameter from the child function.
10127 The call_exprs part is a place-holder, it is mainly used
10128 to distinctly identify to the top-level part that this is
10129 where we should put low and high (reasoning given in header
10130 comment). */
10132 tree child_fndecl
10133 = gimple_omp_parallel_child_fn (
10134 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10135 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10136 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10138 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10139 high_val = t;
10140 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10141 low_val = t;
10143 gcc_assert (low_val && high_val);
10145 tree type = TREE_TYPE (low_val);
10146 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10147 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10149 /* Not needed in SSA form right now. */
10150 gcc_assert (!gimple_in_ssa_p (cfun));
10151 if (l2_dom_bb == NULL)
10152 l2_dom_bb = l1_bb;
10154 tree n1 = low_val;
10155 tree n2 = high_val;
10157 gimple *stmt = gimple_build_assign (ind_var, n1);
10159 /* Replace the GIMPLE_OMP_FOR statement. */
10160 gsi_replace (&gsi, stmt, true);
10162 if (!broken_loop)
10164 /* Code to control the increment goes in the CONT_BB. */
10165 gsi = gsi_last_bb (cont_bb);
10166 stmt = gsi_stmt (gsi);
10167 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10168 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10169 build_one_cst (type));
10171 /* Replace GIMPLE_OMP_CONTINUE. */
10172 gsi_replace (&gsi, stmt, true);
10175 /* Emit the condition in L1_BB. */
10176 gsi = gsi_after_labels (l1_bb);
10177 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10178 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10179 fd->loop.step);
10180 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10181 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10182 fd->loop.n1, fold_convert (sizetype, t));
10183 else
10184 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10185 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10186 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10187 expand_omp_build_assign (&gsi, fd->loop.v, t);
10189 /* The condition is always '<' since the runtime will fill in the low
10190 and high values. */
10191 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10192 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10194 /* Remove GIMPLE_OMP_RETURN. */
10195 gsi = gsi_last_bb (exit_bb);
10196 gsi_remove (&gsi, true);
10198 /* Connect the new blocks. */
10199 remove_edge (FALLTHRU_EDGE (entry_bb));
10201 edge e, ne;
10202 if (!broken_loop)
10204 remove_edge (BRANCH_EDGE (entry_bb));
10205 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10207 e = BRANCH_EDGE (l1_bb);
10208 ne = FALLTHRU_EDGE (l1_bb);
10209 e->flags = EDGE_TRUE_VALUE;
10211 else
10213 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10215 ne = single_succ_edge (l1_bb);
10216 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10219 ne->flags = EDGE_FALSE_VALUE;
10220 e->probability = REG_BR_PROB_BASE * 7 / 8;
10221 ne->probability = REG_BR_PROB_BASE / 8;
10223 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10224 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10225 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10227 if (!broken_loop)
10229 struct loop *loop = alloc_loop ();
10230 loop->header = l1_bb;
10231 loop->latch = cont_bb;
10232 add_loop (loop, l1_bb->loop_father);
10233 loop->safelen = INT_MAX;
10236 /* Pick the correct library function based on the precision of the
10237 induction variable type. */
10238 tree lib_fun = NULL_TREE;
10239 if (TYPE_PRECISION (type) == 32)
10240 lib_fun = cilk_for_32_fndecl;
10241 else if (TYPE_PRECISION (type) == 64)
10242 lib_fun = cilk_for_64_fndecl;
10243 else
10244 gcc_unreachable ();
10246 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10248 /* WS_ARGS contains the library function flavor to call:
10249 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10250 user-defined grain value. If the user does not define one, then zero
10251 is passed in by the parser. */
10252 vec_alloc (region->ws_args, 2);
10253 region->ws_args->quick_push (lib_fun);
10254 region->ws_args->quick_push (fd->chunk_size);
10257 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10258 loop. Given parameters:
10260 for (V = N1; V cond N2; V += STEP) BODY;
10262 where COND is "<" or ">", we generate pseudocode
10264 V = N1;
10265 goto L1;
10267 BODY;
10268 V += STEP;
10270 if (V cond N2) goto L0; else goto L2;
10273 For collapsed loops, given parameters:
10274 collapse(3)
10275 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10276 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10277 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10278 BODY;
10280 we generate pseudocode
10282 if (cond3 is <)
10283 adj = STEP3 - 1;
10284 else
10285 adj = STEP3 + 1;
10286 count3 = (adj + N32 - N31) / STEP3;
10287 if (cond2 is <)
10288 adj = STEP2 - 1;
10289 else
10290 adj = STEP2 + 1;
10291 count2 = (adj + N22 - N21) / STEP2;
10292 if (cond1 is <)
10293 adj = STEP1 - 1;
10294 else
10295 adj = STEP1 + 1;
10296 count1 = (adj + N12 - N11) / STEP1;
10297 count = count1 * count2 * count3;
10298 V = 0;
10299 V1 = N11;
10300 V2 = N21;
10301 V3 = N31;
10302 goto L1;
10304 BODY;
10305 V += 1;
10306 V3 += STEP3;
10307 V2 += (V3 cond3 N32) ? 0 : STEP2;
10308 V3 = (V3 cond3 N32) ? V3 : N31;
10309 V1 += (V2 cond2 N22) ? 0 : STEP1;
10310 V2 = (V2 cond2 N22) ? V2 : N21;
10312 if (V < count) goto L0; else goto L2;
10317 static void
10318 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10320 tree type, t;
10321 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10322 gimple_stmt_iterator gsi;
10323 gimple *stmt;
10324 gcond *cond_stmt;
10325 bool broken_loop = region->cont == NULL;
10326 edge e, ne;
10327 tree *counts = NULL;
10328 int i;
10329 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10330 OMP_CLAUSE_SAFELEN);
10331 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10332 OMP_CLAUSE__SIMDUID_);
10333 tree n1, n2;
10335 type = TREE_TYPE (fd->loop.v);
10336 entry_bb = region->entry;
10337 cont_bb = region->cont;
10338 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10339 gcc_assert (broken_loop
10340 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10341 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10342 if (!broken_loop)
10344 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10345 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10346 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10347 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10349 else
10351 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10352 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10353 l2_bb = single_succ (l1_bb);
10355 exit_bb = region->exit;
10356 l2_dom_bb = NULL;
10358 gsi = gsi_last_bb (entry_bb);
10360 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10361 /* Not needed in SSA form right now. */
10362 gcc_assert (!gimple_in_ssa_p (cfun));
10363 if (fd->collapse > 1)
10365 int first_zero_iter = -1, dummy = -1;
10366 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10368 counts = XALLOCAVEC (tree, fd->collapse);
10369 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10370 zero_iter_bb, first_zero_iter,
10371 dummy_bb, dummy, l2_dom_bb);
10373 if (l2_dom_bb == NULL)
10374 l2_dom_bb = l1_bb;
10376 n1 = fd->loop.n1;
10377 n2 = fd->loop.n2;
10378 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10380 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10381 OMP_CLAUSE__LOOPTEMP_);
10382 gcc_assert (innerc);
10383 n1 = OMP_CLAUSE_DECL (innerc);
10384 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10385 OMP_CLAUSE__LOOPTEMP_);
10386 gcc_assert (innerc);
10387 n2 = OMP_CLAUSE_DECL (innerc);
10388 expand_omp_build_assign (&gsi, fd->loop.v,
10389 fold_convert (type, n1));
10390 if (fd->collapse > 1)
10392 gsi_prev (&gsi);
10393 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10394 gsi_next (&gsi);
10397 else
10399 expand_omp_build_assign (&gsi, fd->loop.v,
10400 fold_convert (type, fd->loop.n1));
10401 if (fd->collapse > 1)
10402 for (i = 0; i < fd->collapse; i++)
10404 tree itype = TREE_TYPE (fd->loops[i].v);
10405 if (POINTER_TYPE_P (itype))
10406 itype = signed_type_for (itype);
10407 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10408 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10412 /* Remove the GIMPLE_OMP_FOR statement. */
10413 gsi_remove (&gsi, true);
10415 if (!broken_loop)
10417 /* Code to control the increment goes in the CONT_BB. */
10418 gsi = gsi_last_bb (cont_bb);
10419 stmt = gsi_stmt (gsi);
10420 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10422 if (POINTER_TYPE_P (type))
10423 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10424 else
10425 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10426 expand_omp_build_assign (&gsi, fd->loop.v, t);
10428 if (fd->collapse > 1)
10430 i = fd->collapse - 1;
10431 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10433 t = fold_convert (sizetype, fd->loops[i].step);
10434 t = fold_build_pointer_plus (fd->loops[i].v, t);
10436 else
10438 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10439 fd->loops[i].step);
10440 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10441 fd->loops[i].v, t);
10443 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10445 for (i = fd->collapse - 1; i > 0; i--)
10447 tree itype = TREE_TYPE (fd->loops[i].v);
10448 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10449 if (POINTER_TYPE_P (itype2))
10450 itype2 = signed_type_for (itype2);
10451 t = build3 (COND_EXPR, itype2,
10452 build2 (fd->loops[i].cond_code, boolean_type_node,
10453 fd->loops[i].v,
10454 fold_convert (itype, fd->loops[i].n2)),
10455 build_int_cst (itype2, 0),
10456 fold_convert (itype2, fd->loops[i - 1].step));
10457 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10458 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10459 else
10460 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10461 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10463 t = build3 (COND_EXPR, itype,
10464 build2 (fd->loops[i].cond_code, boolean_type_node,
10465 fd->loops[i].v,
10466 fold_convert (itype, fd->loops[i].n2)),
10467 fd->loops[i].v,
10468 fold_convert (itype, fd->loops[i].n1));
10469 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10473 /* Remove GIMPLE_OMP_CONTINUE. */
10474 gsi_remove (&gsi, true);
10477 /* Emit the condition in L1_BB. */
10478 gsi = gsi_start_bb (l1_bb);
10480 t = fold_convert (type, n2);
10481 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10482 false, GSI_CONTINUE_LINKING);
10483 tree v = fd->loop.v;
10484 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10485 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10486 false, GSI_CONTINUE_LINKING);
10487 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10488 cond_stmt = gimple_build_cond_empty (t);
10489 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10490 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10491 NULL, NULL)
10492 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10493 NULL, NULL))
10495 gsi = gsi_for_stmt (cond_stmt);
10496 gimple_regimplify_operands (cond_stmt, &gsi);
10499 /* Remove GIMPLE_OMP_RETURN. */
10500 gsi = gsi_last_bb (exit_bb);
10501 gsi_remove (&gsi, true);
10503 /* Connect the new blocks. */
10504 remove_edge (FALLTHRU_EDGE (entry_bb));
10506 if (!broken_loop)
10508 remove_edge (BRANCH_EDGE (entry_bb));
10509 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10511 e = BRANCH_EDGE (l1_bb);
10512 ne = FALLTHRU_EDGE (l1_bb);
10513 e->flags = EDGE_TRUE_VALUE;
10515 else
10517 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10519 ne = single_succ_edge (l1_bb);
10520 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10523 ne->flags = EDGE_FALSE_VALUE;
10524 e->probability = REG_BR_PROB_BASE * 7 / 8;
10525 ne->probability = REG_BR_PROB_BASE / 8;
10527 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10528 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10529 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10531 if (!broken_loop)
10533 struct loop *loop = alloc_loop ();
10534 loop->header = l1_bb;
10535 loop->latch = cont_bb;
10536 add_loop (loop, l1_bb->loop_father);
10537 if (safelen == NULL_TREE)
10538 loop->safelen = INT_MAX;
10539 else
10541 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10542 if (TREE_CODE (safelen) != INTEGER_CST)
10543 loop->safelen = 0;
10544 else if (!tree_fits_uhwi_p (safelen)
10545 || tree_to_uhwi (safelen) > INT_MAX)
10546 loop->safelen = INT_MAX;
10547 else
10548 loop->safelen = tree_to_uhwi (safelen);
10549 if (loop->safelen == 1)
10550 loop->safelen = 0;
10552 if (simduid)
10554 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10555 cfun->has_simduid_loops = true;
10557 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10558 the loop. */
10559 if ((flag_tree_loop_vectorize
10560 || (!global_options_set.x_flag_tree_loop_vectorize
10561 && !global_options_set.x_flag_tree_vectorize))
10562 && flag_tree_loop_optimize
10563 && loop->safelen > 1)
10565 loop->force_vectorize = true;
10566 cfun->has_force_vectorize_loops = true;
10569 else if (simduid)
10570 cfun->has_simduid_loops = true;
10573 /* Taskloop construct is represented after gimplification with
10574 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10575 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10576 which should just compute all the needed loop temporaries
10577 for GIMPLE_OMP_TASK. */
10579 static void
10580 expand_omp_taskloop_for_outer (struct omp_region *region,
10581 struct omp_for_data *fd,
10582 gimple *inner_stmt)
10584 tree type, bias = NULL_TREE;
10585 basic_block entry_bb, cont_bb, exit_bb;
10586 gimple_stmt_iterator gsi;
10587 gassign *assign_stmt;
10588 tree *counts = NULL;
10589 int i;
10591 gcc_assert (inner_stmt);
10592 gcc_assert (region->cont);
10593 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10594 && gimple_omp_task_taskloop_p (inner_stmt));
10595 type = TREE_TYPE (fd->loop.v);
10597 /* See if we need to bias by LLONG_MIN. */
10598 if (fd->iter_type == long_long_unsigned_type_node
10599 && TREE_CODE (type) == INTEGER_TYPE
10600 && !TYPE_UNSIGNED (type))
10602 tree n1, n2;
10604 if (fd->loop.cond_code == LT_EXPR)
10606 n1 = fd->loop.n1;
10607 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10609 else
10611 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10612 n2 = fd->loop.n1;
10614 if (TREE_CODE (n1) != INTEGER_CST
10615 || TREE_CODE (n2) != INTEGER_CST
10616 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10617 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10620 entry_bb = region->entry;
10621 cont_bb = region->cont;
10622 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10623 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10624 exit_bb = region->exit;
10626 gsi = gsi_last_bb (entry_bb);
10627 gimple *for_stmt = gsi_stmt (gsi);
10628 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10629 if (fd->collapse > 1)
10631 int first_zero_iter = -1, dummy = -1;
10632 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10634 counts = XALLOCAVEC (tree, fd->collapse);
10635 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10636 zero_iter_bb, first_zero_iter,
10637 dummy_bb, dummy, l2_dom_bb);
10639 if (zero_iter_bb)
10641 /* Some counts[i] vars might be uninitialized if
10642 some loop has zero iterations. But the body shouldn't
10643 be executed in that case, so just avoid uninit warnings. */
10644 for (i = first_zero_iter; i < fd->collapse; i++)
10645 if (SSA_VAR_P (counts[i]))
10646 TREE_NO_WARNING (counts[i]) = 1;
10647 gsi_prev (&gsi);
10648 edge e = split_block (entry_bb, gsi_stmt (gsi));
10649 entry_bb = e->dest;
10650 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10651 gsi = gsi_last_bb (entry_bb);
10652 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10653 get_immediate_dominator (CDI_DOMINATORS,
10654 zero_iter_bb));
10658 tree t0, t1;
10659 t1 = fd->loop.n2;
10660 t0 = fd->loop.n1;
10661 if (POINTER_TYPE_P (TREE_TYPE (t0))
10662 && TYPE_PRECISION (TREE_TYPE (t0))
10663 != TYPE_PRECISION (fd->iter_type))
10665 /* Avoid casting pointers to integer of a different size. */
10666 tree itype = signed_type_for (type);
10667 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10668 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10670 else
10672 t1 = fold_convert (fd->iter_type, t1);
10673 t0 = fold_convert (fd->iter_type, t0);
10675 if (bias)
10677 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10678 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10681 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10682 OMP_CLAUSE__LOOPTEMP_);
10683 gcc_assert (innerc);
10684 tree startvar = OMP_CLAUSE_DECL (innerc);
10685 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10686 gcc_assert (innerc);
10687 tree endvar = OMP_CLAUSE_DECL (innerc);
10688 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10690 gcc_assert (innerc);
10691 for (i = 1; i < fd->collapse; i++)
10693 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10694 OMP_CLAUSE__LOOPTEMP_);
10695 gcc_assert (innerc);
10697 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10698 OMP_CLAUSE__LOOPTEMP_);
10699 if (innerc)
10701 /* If needed (inner taskloop has lastprivate clause), propagate
10702 down the total number of iterations. */
10703 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10704 NULL_TREE, false,
10705 GSI_CONTINUE_LINKING);
10706 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10707 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10711 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10712 GSI_CONTINUE_LINKING);
10713 assign_stmt = gimple_build_assign (startvar, t0);
10714 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10716 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10717 GSI_CONTINUE_LINKING);
10718 assign_stmt = gimple_build_assign (endvar, t1);
10719 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10720 if (fd->collapse > 1)
10721 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10723 /* Remove the GIMPLE_OMP_FOR statement. */
10724 gsi = gsi_for_stmt (for_stmt);
10725 gsi_remove (&gsi, true);
10727 gsi = gsi_last_bb (cont_bb);
10728 gsi_remove (&gsi, true);
10730 gsi = gsi_last_bb (exit_bb);
10731 gsi_remove (&gsi, true);
10733 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10734 remove_edge (BRANCH_EDGE (entry_bb));
10735 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10736 remove_edge (BRANCH_EDGE (cont_bb));
10737 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10738 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10739 recompute_dominator (CDI_DOMINATORS, region->entry));
10742 /* Taskloop construct is represented after gimplification with
10743 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10744 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10745 GOMP_taskloop{,_ull} function arranges for each task to be given just
10746 a single range of iterations. */
10748 static void
10749 expand_omp_taskloop_for_inner (struct omp_region *region,
10750 struct omp_for_data *fd,
10751 gimple *inner_stmt)
10753 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10754 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10755 basic_block fin_bb;
10756 gimple_stmt_iterator gsi;
10757 edge ep;
10758 bool broken_loop = region->cont == NULL;
10759 tree *counts = NULL;
10760 tree n1, n2, step;
10762 itype = type = TREE_TYPE (fd->loop.v);
10763 if (POINTER_TYPE_P (type))
10764 itype = signed_type_for (type);
10766 /* See if we need to bias by LLONG_MIN. */
10767 if (fd->iter_type == long_long_unsigned_type_node
10768 && TREE_CODE (type) == INTEGER_TYPE
10769 && !TYPE_UNSIGNED (type))
10771 tree n1, n2;
10773 if (fd->loop.cond_code == LT_EXPR)
10775 n1 = fd->loop.n1;
10776 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10778 else
10780 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10781 n2 = fd->loop.n1;
10783 if (TREE_CODE (n1) != INTEGER_CST
10784 || TREE_CODE (n2) != INTEGER_CST
10785 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10786 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10789 entry_bb = region->entry;
10790 cont_bb = region->cont;
10791 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10792 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10793 gcc_assert (broken_loop
10794 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10795 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10796 if (!broken_loop)
10798 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10799 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10801 exit_bb = region->exit;
10803 /* Iteration space partitioning goes in ENTRY_BB. */
10804 gsi = gsi_last_bb (entry_bb);
10805 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10807 if (fd->collapse > 1)
10809 int first_zero_iter = -1, dummy = -1;
10810 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10812 counts = XALLOCAVEC (tree, fd->collapse);
10813 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10814 fin_bb, first_zero_iter,
10815 dummy_bb, dummy, l2_dom_bb);
10816 t = NULL_TREE;
10818 else
10819 t = integer_one_node;
10821 step = fd->loop.step;
10822 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10823 OMP_CLAUSE__LOOPTEMP_);
10824 gcc_assert (innerc);
10825 n1 = OMP_CLAUSE_DECL (innerc);
10826 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10827 gcc_assert (innerc);
10828 n2 = OMP_CLAUSE_DECL (innerc);
10829 if (bias)
10831 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10832 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10834 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10835 true, NULL_TREE, true, GSI_SAME_STMT);
10836 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10837 true, NULL_TREE, true, GSI_SAME_STMT);
10838 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10839 true, NULL_TREE, true, GSI_SAME_STMT);
10841 tree startvar = fd->loop.v;
10842 tree endvar = NULL_TREE;
10844 if (gimple_omp_for_combined_p (fd->for_stmt))
10846 tree clauses = gimple_omp_for_clauses (inner_stmt);
10847 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10848 gcc_assert (innerc);
10849 startvar = OMP_CLAUSE_DECL (innerc);
10850 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10851 OMP_CLAUSE__LOOPTEMP_);
10852 gcc_assert (innerc);
10853 endvar = OMP_CLAUSE_DECL (innerc);
10855 t = fold_convert (TREE_TYPE (startvar), n1);
10856 t = force_gimple_operand_gsi (&gsi, t,
10857 DECL_P (startvar)
10858 && TREE_ADDRESSABLE (startvar),
10859 NULL_TREE, false, GSI_CONTINUE_LINKING);
10860 gimple *assign_stmt = gimple_build_assign (startvar, t);
10861 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10863 t = fold_convert (TREE_TYPE (startvar), n2);
10864 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10865 false, GSI_CONTINUE_LINKING);
10866 if (endvar)
10868 assign_stmt = gimple_build_assign (endvar, e);
10869 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10870 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10871 assign_stmt = gimple_build_assign (fd->loop.v, e);
10872 else
10873 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10874 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10876 if (fd->collapse > 1)
10877 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10879 if (!broken_loop)
10881 /* The code controlling the sequential loop replaces the
10882 GIMPLE_OMP_CONTINUE. */
10883 gsi = gsi_last_bb (cont_bb);
10884 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10885 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10886 vmain = gimple_omp_continue_control_use (cont_stmt);
10887 vback = gimple_omp_continue_control_def (cont_stmt);
10889 if (!gimple_omp_for_combined_p (fd->for_stmt))
10891 if (POINTER_TYPE_P (type))
10892 t = fold_build_pointer_plus (vmain, step);
10893 else
10894 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10895 t = force_gimple_operand_gsi (&gsi, t,
10896 DECL_P (vback)
10897 && TREE_ADDRESSABLE (vback),
10898 NULL_TREE, true, GSI_SAME_STMT);
10899 assign_stmt = gimple_build_assign (vback, t);
10900 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10902 t = build2 (fd->loop.cond_code, boolean_type_node,
10903 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10904 ? t : vback, e);
10905 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10908 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10909 gsi_remove (&gsi, true);
10911 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10912 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10915 /* Remove the GIMPLE_OMP_FOR statement. */
10916 gsi = gsi_for_stmt (fd->for_stmt);
10917 gsi_remove (&gsi, true);
10919 /* Remove the GIMPLE_OMP_RETURN statement. */
10920 gsi = gsi_last_bb (exit_bb);
10921 gsi_remove (&gsi, true);
10923 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10924 if (!broken_loop)
10925 remove_edge (BRANCH_EDGE (entry_bb));
10926 else
10928 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10929 region->outer->cont = NULL;
10932 /* Connect all the blocks. */
10933 if (!broken_loop)
10935 ep = find_edge (cont_bb, body_bb);
10936 if (gimple_omp_for_combined_p (fd->for_stmt))
10938 remove_edge (ep);
10939 ep = NULL;
10941 else if (fd->collapse > 1)
10943 remove_edge (ep);
10944 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10946 else
10947 ep->flags = EDGE_TRUE_VALUE;
10948 find_edge (cont_bb, fin_bb)->flags
10949 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10952 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10953 recompute_dominator (CDI_DOMINATORS, body_bb));
10954 if (!broken_loop)
10955 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10956 recompute_dominator (CDI_DOMINATORS, fin_bb));
10958 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10960 struct loop *loop = alloc_loop ();
10961 loop->header = body_bb;
10962 if (collapse_bb == NULL)
10963 loop->latch = cont_bb;
10964 add_loop (loop, body_bb->loop_father);
10968 /* A subroutine of expand_omp_for. Generate code for an OpenACC
10969 partitioned loop. The lowering here is abstracted, in that the
10970 loop parameters are passed through internal functions, which are
10971 further lowered by oacc_device_lower, once we get to the target
10972 compiler. The loop is of the form:
10974 for (V = B; V LTGT E; V += S) {BODY}
10976 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10977 (constant 0 for no chunking) and we will have a GWV partitioning
10978 mask, specifying dimensions over which the loop is to be
10979 partitioned (see note below). We generate code that looks like:
10981 <entry_bb> [incoming FALL->body, BRANCH->exit]
10982 typedef signedintify (typeof (V)) T; // underlying signed integral type
10983 T range = E - B;
10984 T chunk_no = 0;
10985 T DIR = LTGT == '<' ? +1 : -1;
10986 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10987 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10989 <head_bb> [created by splitting end of entry_bb]
10990 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10991 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10992 if (!(offset LTGT bound)) goto bottom_bb;
10994 <body_bb> [incoming]
10995 V = B + offset;
10996 {BODY}
10998 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
10999 offset += step;
11000 if (offset LTGT bound) goto body_bb; [*]
11002 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11003 chunk_no++;
11004 if (chunk < chunk_max) goto head_bb;
11006 <exit_bb> [incoming]
11007 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11009 [*] Needed if V live at end of loop
11011 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11012 transition, and will be specified by a more general mechanism shortly.
11015 static void
11016 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11018 tree v = fd->loop.v;
11019 enum tree_code cond_code = fd->loop.cond_code;
11020 enum tree_code plus_code = PLUS_EXPR;
11022 tree chunk_size = integer_minus_one_node;
11023 tree gwv = integer_zero_node;
11024 tree iter_type = TREE_TYPE (v);
11025 tree diff_type = iter_type;
11026 tree plus_type = iter_type;
11027 struct oacc_collapse *counts = NULL;
11029 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11030 == GF_OMP_FOR_KIND_OACC_LOOP);
11031 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11032 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11034 if (POINTER_TYPE_P (iter_type))
11036 plus_code = POINTER_PLUS_EXPR;
11037 plus_type = sizetype;
11039 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11040 diff_type = signed_type_for (diff_type);
11042 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11043 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11044 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11045 basic_block bottom_bb = NULL;
11047 /* entry_bb has two sucessors; the branch edge is to the exit
11048 block, fallthrough edge to body. */
11049 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11050 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11052 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11053 body_bb, or to a block whose only successor is the body_bb. Its
11054 fallthrough successor is the final block (same as the branch
11055 successor of the entry_bb). */
11056 if (cont_bb)
11058 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11059 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11061 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11062 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11064 else
11065 gcc_assert (!gimple_in_ssa_p (cfun));
11067 /* The exit block only has entry_bb and cont_bb as predecessors. */
11068 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11070 tree chunk_no;
11071 tree chunk_max = NULL_TREE;
11072 tree bound, offset;
11073 tree step = create_tmp_var (diff_type, ".step");
11074 bool up = cond_code == LT_EXPR;
11075 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11076 bool chunking = !gimple_in_ssa_p (cfun);;
11077 bool negating;
11079 /* SSA instances. */
11080 tree offset_incr = NULL_TREE;
11081 tree offset_init = NULL_TREE;
11083 gimple_stmt_iterator gsi;
11084 gassign *ass;
11085 gcall *call;
11086 gimple *stmt;
11087 tree expr;
11088 location_t loc;
11089 edge split, be, fte;
11091 /* Split the end of entry_bb to create head_bb. */
11092 split = split_block (entry_bb, last_stmt (entry_bb));
11093 basic_block head_bb = split->dest;
11094 entry_bb = split->src;
11096 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11097 gsi = gsi_last_bb (entry_bb);
11098 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11099 loc = gimple_location (for_stmt);
11101 if (gimple_in_ssa_p (cfun))
11103 offset_init = gimple_omp_for_index (for_stmt, 0);
11104 gcc_assert (integer_zerop (fd->loop.n1));
11105 /* The SSA parallelizer does gang parallelism. */
11106 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11109 if (fd->collapse > 1)
11111 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11112 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11113 TREE_TYPE (fd->loop.n2));
11115 if (SSA_VAR_P (fd->loop.n2))
11117 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11118 true, GSI_SAME_STMT);
11119 ass = gimple_build_assign (fd->loop.n2, total);
11120 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11125 tree b = fd->loop.n1;
11126 tree e = fd->loop.n2;
11127 tree s = fd->loop.step;
11129 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11130 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11132 /* Convert the step, avoiding possible unsigned->signed overflow. */
11133 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11134 if (negating)
11135 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11136 s = fold_convert (diff_type, s);
11137 if (negating)
11138 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11139 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11141 if (!chunking)
11142 chunk_size = integer_zero_node;
11143 expr = fold_convert (diff_type, chunk_size);
11144 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11145 NULL_TREE, true, GSI_SAME_STMT);
11146 /* Determine the range, avoiding possible unsigned->signed overflow. */
11147 negating = !up && TYPE_UNSIGNED (iter_type);
11148 expr = fold_build2 (MINUS_EXPR, plus_type,
11149 fold_convert (plus_type, negating ? b : e),
11150 fold_convert (plus_type, negating ? e : b));
11151 expr = fold_convert (diff_type, expr);
11152 if (negating)
11153 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11154 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11155 NULL_TREE, true, GSI_SAME_STMT);
11157 chunk_no = build_int_cst (diff_type, 0);
11158 if (chunking)
11160 gcc_assert (!gimple_in_ssa_p (cfun));
11162 expr = chunk_no;
11163 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11164 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11166 ass = gimple_build_assign (chunk_no, expr);
11167 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11169 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11170 build_int_cst (integer_type_node,
11171 IFN_GOACC_LOOP_CHUNKS),
11172 dir, range, s, chunk_size, gwv);
11173 gimple_call_set_lhs (call, chunk_max);
11174 gimple_set_location (call, loc);
11175 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11177 else
11178 chunk_size = chunk_no;
11180 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11181 build_int_cst (integer_type_node,
11182 IFN_GOACC_LOOP_STEP),
11183 dir, range, s, chunk_size, gwv);
11184 gimple_call_set_lhs (call, step);
11185 gimple_set_location (call, loc);
11186 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11188 /* Remove the GIMPLE_OMP_FOR. */
11189 gsi_remove (&gsi, true);
11191 /* Fixup edges from head_bb */
11192 be = BRANCH_EDGE (head_bb);
11193 fte = FALLTHRU_EDGE (head_bb);
11194 be->flags |= EDGE_FALSE_VALUE;
11195 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11197 basic_block body_bb = fte->dest;
11199 if (gimple_in_ssa_p (cfun))
11201 gsi = gsi_last_bb (cont_bb);
11202 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11204 offset = gimple_omp_continue_control_use (cont_stmt);
11205 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11207 else
11209 offset = create_tmp_var (diff_type, ".offset");
11210 offset_init = offset_incr = offset;
11212 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11214 /* Loop offset & bound go into head_bb. */
11215 gsi = gsi_start_bb (head_bb);
11217 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11218 build_int_cst (integer_type_node,
11219 IFN_GOACC_LOOP_OFFSET),
11220 dir, range, s,
11221 chunk_size, gwv, chunk_no);
11222 gimple_call_set_lhs (call, offset_init);
11223 gimple_set_location (call, loc);
11224 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11226 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11227 build_int_cst (integer_type_node,
11228 IFN_GOACC_LOOP_BOUND),
11229 dir, range, s,
11230 chunk_size, gwv, offset_init);
11231 gimple_call_set_lhs (call, bound);
11232 gimple_set_location (call, loc);
11233 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11235 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11236 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11237 GSI_CONTINUE_LINKING);
11239 /* V assignment goes into body_bb. */
11240 if (!gimple_in_ssa_p (cfun))
11242 gsi = gsi_start_bb (body_bb);
11244 expr = build2 (plus_code, iter_type, b,
11245 fold_convert (plus_type, offset));
11246 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11247 true, GSI_SAME_STMT);
11248 ass = gimple_build_assign (v, expr);
11249 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11250 if (fd->collapse > 1)
11251 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11254 /* Loop increment goes into cont_bb. If this is not a loop, we
11255 will have spawned threads as if it was, and each one will
11256 execute one iteration. The specification is not explicit about
11257 whether such constructs are ill-formed or not, and they can
11258 occur, especially when noreturn routines are involved. */
11259 if (cont_bb)
11261 gsi = gsi_last_bb (cont_bb);
11262 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11263 loc = gimple_location (cont_stmt);
11265 /* Increment offset. */
11266 if (gimple_in_ssa_p (cfun))
11267 expr= build2 (plus_code, iter_type, offset,
11268 fold_convert (plus_type, step));
11269 else
11270 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11271 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11272 true, GSI_SAME_STMT);
11273 ass = gimple_build_assign (offset_incr, expr);
11274 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11275 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11276 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11278 /* Remove the GIMPLE_OMP_CONTINUE. */
11279 gsi_remove (&gsi, true);
11281 /* Fixup edges from cont_bb */
11282 be = BRANCH_EDGE (cont_bb);
11283 fte = FALLTHRU_EDGE (cont_bb);
11284 be->flags |= EDGE_TRUE_VALUE;
11285 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11287 if (chunking)
11289 /* Split the beginning of exit_bb to make bottom_bb. We
11290 need to insert a nop at the start, because splitting is
11291 after a stmt, not before. */
11292 gsi = gsi_start_bb (exit_bb);
11293 stmt = gimple_build_nop ();
11294 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11295 split = split_block (exit_bb, stmt);
11296 bottom_bb = split->src;
11297 exit_bb = split->dest;
11298 gsi = gsi_last_bb (bottom_bb);
11300 /* Chunk increment and test goes into bottom_bb. */
11301 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11302 build_int_cst (diff_type, 1));
11303 ass = gimple_build_assign (chunk_no, expr);
11304 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11306 /* Chunk test at end of bottom_bb. */
11307 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11308 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11309 GSI_CONTINUE_LINKING);
11311 /* Fixup edges from bottom_bb. */
11312 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11313 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11317 gsi = gsi_last_bb (exit_bb);
11318 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11319 loc = gimple_location (gsi_stmt (gsi));
11321 if (!gimple_in_ssa_p (cfun))
11323 /* Insert the final value of V, in case it is live. This is the
11324 value for the only thread that survives past the join. */
11325 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11326 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11327 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11328 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11329 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11330 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11331 true, GSI_SAME_STMT);
11332 ass = gimple_build_assign (v, expr);
11333 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11336 /* Remove the OMP_RETURN. */
11337 gsi_remove (&gsi, true);
11339 if (cont_bb)
11341 /* We now have one or two nested loops. Update the loop
11342 structures. */
11343 struct loop *parent = entry_bb->loop_father;
11344 struct loop *body = body_bb->loop_father;
11346 if (chunking)
11348 struct loop *chunk_loop = alloc_loop ();
11349 chunk_loop->header = head_bb;
11350 chunk_loop->latch = bottom_bb;
11351 add_loop (chunk_loop, parent);
11352 parent = chunk_loop;
11354 else if (parent != body)
11356 gcc_assert (body->header == body_bb);
11357 gcc_assert (body->latch == cont_bb
11358 || single_pred (body->latch) == cont_bb);
11359 parent = NULL;
11362 if (parent)
11364 struct loop *body_loop = alloc_loop ();
11365 body_loop->header = body_bb;
11366 body_loop->latch = cont_bb;
11367 add_loop (body_loop, parent);
11372 /* Expand the OMP loop defined by REGION. */
11374 static void
11375 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11377 struct omp_for_data fd;
11378 struct omp_for_data_loop *loops;
11380 loops
11381 = (struct omp_for_data_loop *)
11382 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11383 * sizeof (struct omp_for_data_loop));
11384 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11385 &fd, loops);
11386 region->sched_kind = fd.sched_kind;
11387 region->sched_modifiers = fd.sched_modifiers;
11389 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11390 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11391 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11392 if (region->cont)
11394 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11395 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11396 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11398 else
11399 /* If there isn't a continue then this is a degerate case where
11400 the introduction of abnormal edges during lowering will prevent
11401 original loops from being detected. Fix that up. */
11402 loops_state_set (LOOPS_NEED_FIXUP);
11404 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11405 expand_omp_simd (region, &fd);
11406 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11407 expand_cilk_for (region, &fd);
11408 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11410 gcc_assert (!inner_stmt);
11411 expand_oacc_for (region, &fd);
11413 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11415 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11416 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11417 else
11418 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11420 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11421 && !fd.have_ordered)
11423 if (fd.chunk_size == NULL)
11424 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11425 else
11426 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11428 else
11430 int fn_index, start_ix, next_ix;
11432 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11433 == GF_OMP_FOR_KIND_FOR);
11434 if (fd.chunk_size == NULL
11435 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11436 fd.chunk_size = integer_zero_node;
11437 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11438 switch (fd.sched_kind)
11440 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11441 fn_index = 3;
11442 break;
11443 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11444 case OMP_CLAUSE_SCHEDULE_GUIDED:
11445 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11446 && !fd.ordered
11447 && !fd.have_ordered)
11449 fn_index = 3 + fd.sched_kind;
11450 break;
11452 /* FALLTHRU */
11453 default:
11454 fn_index = fd.sched_kind;
11455 break;
11457 if (!fd.ordered)
11458 fn_index += fd.have_ordered * 6;
11459 if (fd.ordered)
11460 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11461 else
11462 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11463 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11464 if (fd.iter_type == long_long_unsigned_type_node)
11466 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11467 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11468 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11469 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11471 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11472 (enum built_in_function) next_ix, inner_stmt);
11475 if (gimple_in_ssa_p (cfun))
11476 update_ssa (TODO_update_ssa_only_virtuals);
11480 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11482 v = GOMP_sections_start (n);
11484 switch (v)
11486 case 0:
11487 goto L2;
11488 case 1:
11489 section 1;
11490 goto L1;
11491 case 2:
11493 case n:
11495 default:
11496 abort ();
11499 v = GOMP_sections_next ();
11500 goto L0;
11502 reduction;
11504 If this is a combined parallel sections, replace the call to
11505 GOMP_sections_start with call to GOMP_sections_next. */
11507 static void
11508 expand_omp_sections (struct omp_region *region)
11510 tree t, u, vin = NULL, vmain, vnext, l2;
11511 unsigned len;
11512 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11513 gimple_stmt_iterator si, switch_si;
11514 gomp_sections *sections_stmt;
11515 gimple *stmt;
11516 gomp_continue *cont;
11517 edge_iterator ei;
11518 edge e;
11519 struct omp_region *inner;
11520 unsigned i, casei;
11521 bool exit_reachable = region->cont != NULL;
11523 gcc_assert (region->exit != NULL);
11524 entry_bb = region->entry;
11525 l0_bb = single_succ (entry_bb);
11526 l1_bb = region->cont;
11527 l2_bb = region->exit;
11528 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11529 l2 = gimple_block_label (l2_bb);
11530 else
11532 /* This can happen if there are reductions. */
11533 len = EDGE_COUNT (l0_bb->succs);
11534 gcc_assert (len > 0);
11535 e = EDGE_SUCC (l0_bb, len - 1);
11536 si = gsi_last_bb (e->dest);
11537 l2 = NULL_TREE;
11538 if (gsi_end_p (si)
11539 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11540 l2 = gimple_block_label (e->dest);
11541 else
11542 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11544 si = gsi_last_bb (e->dest);
11545 if (gsi_end_p (si)
11546 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11548 l2 = gimple_block_label (e->dest);
11549 break;
11553 if (exit_reachable)
11554 default_bb = create_empty_bb (l1_bb->prev_bb);
11555 else
11556 default_bb = create_empty_bb (l0_bb);
11558 /* We will build a switch() with enough cases for all the
11559 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11560 and a default case to abort if something goes wrong. */
11561 len = EDGE_COUNT (l0_bb->succs);
11563 /* Use vec::quick_push on label_vec throughout, since we know the size
11564 in advance. */
11565 auto_vec<tree> label_vec (len);
11567 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11568 GIMPLE_OMP_SECTIONS statement. */
11569 si = gsi_last_bb (entry_bb);
11570 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11571 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11572 vin = gimple_omp_sections_control (sections_stmt);
11573 if (!is_combined_parallel (region))
11575 /* If we are not inside a combined parallel+sections region,
11576 call GOMP_sections_start. */
11577 t = build_int_cst (unsigned_type_node, len - 1);
11578 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11579 stmt = gimple_build_call (u, 1, t);
11581 else
11583 /* Otherwise, call GOMP_sections_next. */
11584 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11585 stmt = gimple_build_call (u, 0);
11587 gimple_call_set_lhs (stmt, vin);
11588 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11589 gsi_remove (&si, true);
11591 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11592 L0_BB. */
11593 switch_si = gsi_last_bb (l0_bb);
11594 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11595 if (exit_reachable)
11597 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11598 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11599 vmain = gimple_omp_continue_control_use (cont);
11600 vnext = gimple_omp_continue_control_def (cont);
11602 else
11604 vmain = vin;
11605 vnext = NULL_TREE;
11608 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11609 label_vec.quick_push (t);
11610 i = 1;
11612 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11613 for (inner = region->inner, casei = 1;
11614 inner;
11615 inner = inner->next, i++, casei++)
11617 basic_block s_entry_bb, s_exit_bb;
11619 /* Skip optional reduction region. */
11620 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11622 --i;
11623 --casei;
11624 continue;
11627 s_entry_bb = inner->entry;
11628 s_exit_bb = inner->exit;
11630 t = gimple_block_label (s_entry_bb);
11631 u = build_int_cst (unsigned_type_node, casei);
11632 u = build_case_label (u, NULL, t);
11633 label_vec.quick_push (u);
11635 si = gsi_last_bb (s_entry_bb);
11636 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11637 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11638 gsi_remove (&si, true);
11639 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11641 if (s_exit_bb == NULL)
11642 continue;
11644 si = gsi_last_bb (s_exit_bb);
11645 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11646 gsi_remove (&si, true);
11648 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11651 /* Error handling code goes in DEFAULT_BB. */
11652 t = gimple_block_label (default_bb);
11653 u = build_case_label (NULL, NULL, t);
11654 make_edge (l0_bb, default_bb, 0);
11655 add_bb_to_loop (default_bb, current_loops->tree_root);
11657 stmt = gimple_build_switch (vmain, u, label_vec);
11658 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11659 gsi_remove (&switch_si, true);
11661 si = gsi_start_bb (default_bb);
11662 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11663 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11665 if (exit_reachable)
11667 tree bfn_decl;
11669 /* Code to get the next section goes in L1_BB. */
11670 si = gsi_last_bb (l1_bb);
11671 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11673 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11674 stmt = gimple_build_call (bfn_decl, 0);
11675 gimple_call_set_lhs (stmt, vnext);
11676 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11677 gsi_remove (&si, true);
11679 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11682 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11683 si = gsi_last_bb (l2_bb);
11684 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11685 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11686 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11687 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11688 else
11689 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11690 stmt = gimple_build_call (t, 0);
11691 if (gimple_omp_return_lhs (gsi_stmt (si)))
11692 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11693 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11694 gsi_remove (&si, true);
11696 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11700 /* Expand code for an OpenMP single directive. We've already expanded
11701 much of the code, here we simply place the GOMP_barrier call. */
11703 static void
11704 expand_omp_single (struct omp_region *region)
11706 basic_block entry_bb, exit_bb;
11707 gimple_stmt_iterator si;
11709 entry_bb = region->entry;
11710 exit_bb = region->exit;
11712 si = gsi_last_bb (entry_bb);
11713 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11714 gsi_remove (&si, true);
11715 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11717 si = gsi_last_bb (exit_bb);
11718 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11720 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11721 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11723 gsi_remove (&si, true);
11724 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11728 /* Generic expansion for OpenMP synchronization directives: master,
11729 ordered and critical. All we need to do here is remove the entry
11730 and exit markers for REGION. */
11732 static void
11733 expand_omp_synch (struct omp_region *region)
11735 basic_block entry_bb, exit_bb;
11736 gimple_stmt_iterator si;
11738 entry_bb = region->entry;
11739 exit_bb = region->exit;
11741 si = gsi_last_bb (entry_bb);
11742 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11743 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11744 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11745 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11746 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11747 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11748 gsi_remove (&si, true);
11749 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11751 if (exit_bb)
11753 si = gsi_last_bb (exit_bb);
11754 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11755 gsi_remove (&si, true);
11756 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11760 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11761 operation as a normal volatile load. */
11763 static bool
11764 expand_omp_atomic_load (basic_block load_bb, tree addr,
11765 tree loaded_val, int index)
11767 enum built_in_function tmpbase;
11768 gimple_stmt_iterator gsi;
11769 basic_block store_bb;
11770 location_t loc;
11771 gimple *stmt;
11772 tree decl, call, type, itype;
11774 gsi = gsi_last_bb (load_bb);
11775 stmt = gsi_stmt (gsi);
11776 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11777 loc = gimple_location (stmt);
11779 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11780 is smaller than word size, then expand_atomic_load assumes that the load
11781 is atomic. We could avoid the builtin entirely in this case. */
11783 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11784 decl = builtin_decl_explicit (tmpbase);
11785 if (decl == NULL_TREE)
11786 return false;
11788 type = TREE_TYPE (loaded_val);
11789 itype = TREE_TYPE (TREE_TYPE (decl));
11791 call = build_call_expr_loc (loc, decl, 2, addr,
11792 build_int_cst (NULL,
11793 gimple_omp_atomic_seq_cst_p (stmt)
11794 ? MEMMODEL_SEQ_CST
11795 : MEMMODEL_RELAXED));
11796 if (!useless_type_conversion_p (type, itype))
11797 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11798 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11800 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11801 gsi_remove (&gsi, true);
11803 store_bb = single_succ (load_bb);
11804 gsi = gsi_last_bb (store_bb);
11805 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11806 gsi_remove (&gsi, true);
11808 if (gimple_in_ssa_p (cfun))
11809 update_ssa (TODO_update_ssa_no_phi);
11811 return true;
11814 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11815 operation as a normal volatile store. */
11817 static bool
11818 expand_omp_atomic_store (basic_block load_bb, tree addr,
11819 tree loaded_val, tree stored_val, int index)
11821 enum built_in_function tmpbase;
11822 gimple_stmt_iterator gsi;
11823 basic_block store_bb = single_succ (load_bb);
11824 location_t loc;
11825 gimple *stmt;
11826 tree decl, call, type, itype;
11827 machine_mode imode;
11828 bool exchange;
11830 gsi = gsi_last_bb (load_bb);
11831 stmt = gsi_stmt (gsi);
11832 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11834 /* If the load value is needed, then this isn't a store but an exchange. */
11835 exchange = gimple_omp_atomic_need_value_p (stmt);
11837 gsi = gsi_last_bb (store_bb);
11838 stmt = gsi_stmt (gsi);
11839 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11840 loc = gimple_location (stmt);
11842 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11843 is smaller than word size, then expand_atomic_store assumes that the store
11844 is atomic. We could avoid the builtin entirely in this case. */
11846 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11847 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11848 decl = builtin_decl_explicit (tmpbase);
11849 if (decl == NULL_TREE)
11850 return false;
11852 type = TREE_TYPE (stored_val);
11854 /* Dig out the type of the function's second argument. */
11855 itype = TREE_TYPE (decl);
11856 itype = TYPE_ARG_TYPES (itype);
11857 itype = TREE_CHAIN (itype);
11858 itype = TREE_VALUE (itype);
11859 imode = TYPE_MODE (itype);
11861 if (exchange && !can_atomic_exchange_p (imode, true))
11862 return false;
11864 if (!useless_type_conversion_p (itype, type))
11865 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11866 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
11867 build_int_cst (NULL,
11868 gimple_omp_atomic_seq_cst_p (stmt)
11869 ? MEMMODEL_SEQ_CST
11870 : MEMMODEL_RELAXED));
11871 if (exchange)
11873 if (!useless_type_conversion_p (type, itype))
11874 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11875 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11878 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11879 gsi_remove (&gsi, true);
11881 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11882 gsi = gsi_last_bb (load_bb);
11883 gsi_remove (&gsi, true);
11885 if (gimple_in_ssa_p (cfun))
11886 update_ssa (TODO_update_ssa_no_phi);
11888 return true;
11891 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11892 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
11893 size of the data type, and thus usable to find the index of the builtin
11894 decl. Returns false if the expression is not of the proper form. */
11896 static bool
11897 expand_omp_atomic_fetch_op (basic_block load_bb,
11898 tree addr, tree loaded_val,
11899 tree stored_val, int index)
11901 enum built_in_function oldbase, newbase, tmpbase;
11902 tree decl, itype, call;
11903 tree lhs, rhs;
11904 basic_block store_bb = single_succ (load_bb);
11905 gimple_stmt_iterator gsi;
11906 gimple *stmt;
11907 location_t loc;
11908 enum tree_code code;
11909 bool need_old, need_new;
11910 machine_mode imode;
11911 bool seq_cst;
11913 /* We expect to find the following sequences:
11915 load_bb:
11916 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
11918 store_bb:
11919 val = tmp OP something; (or: something OP tmp)
11920 GIMPLE_OMP_STORE (val)
11922 ???FIXME: Allow a more flexible sequence.
11923 Perhaps use data flow to pick the statements.
11927 gsi = gsi_after_labels (store_bb);
11928 stmt = gsi_stmt (gsi);
11929 loc = gimple_location (stmt);
11930 if (!is_gimple_assign (stmt))
11931 return false;
11932 gsi_next (&gsi);
11933 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
11934 return false;
11935 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11936 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
11937 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
11938 gcc_checking_assert (!need_old || !need_new);
11940 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
11941 return false;
11943 /* Check for one of the supported fetch-op operations. */
11944 code = gimple_assign_rhs_code (stmt);
11945 switch (code)
11947 case PLUS_EXPR:
11948 case POINTER_PLUS_EXPR:
11949 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11950 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
11951 break;
11952 case MINUS_EXPR:
11953 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11954 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
11955 break;
11956 case BIT_AND_EXPR:
11957 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11958 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
11959 break;
11960 case BIT_IOR_EXPR:
11961 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11962 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
11963 break;
11964 case BIT_XOR_EXPR:
11965 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11966 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
11967 break;
11968 default:
11969 return false;
11972 /* Make sure the expression is of the proper form. */
11973 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11974 rhs = gimple_assign_rhs2 (stmt);
11975 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11976 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11977 rhs = gimple_assign_rhs1 (stmt);
11978 else
11979 return false;
11981 tmpbase = ((enum built_in_function)
11982 ((need_new ? newbase : oldbase) + index + 1));
11983 decl = builtin_decl_explicit (tmpbase);
11984 if (decl == NULL_TREE)
11985 return false;
11986 itype = TREE_TYPE (TREE_TYPE (decl));
11987 imode = TYPE_MODE (itype);
11989 /* We could test all of the various optabs involved, but the fact of the
11990 matter is that (with the exception of i486 vs i586 and xadd) all targets
11991 that support any atomic operaton optab also implements compare-and-swap.
11992 Let optabs.c take care of expanding any compare-and-swap loop. */
11993 if (!can_compare_and_swap_p (imode, true))
11994 return false;
11996 gsi = gsi_last_bb (load_bb);
11997 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
11999 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12000 It only requires that the operation happen atomically. Thus we can
12001 use the RELAXED memory model. */
12002 call = build_call_expr_loc (loc, decl, 3, addr,
12003 fold_convert_loc (loc, itype, rhs),
12004 build_int_cst (NULL,
12005 seq_cst ? MEMMODEL_SEQ_CST
12006 : MEMMODEL_RELAXED));
12008 if (need_old || need_new)
12010 lhs = need_old ? loaded_val : stored_val;
12011 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12012 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12014 else
12015 call = fold_convert_loc (loc, void_type_node, call);
12016 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12017 gsi_remove (&gsi, true);
12019 gsi = gsi_last_bb (store_bb);
12020 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12021 gsi_remove (&gsi, true);
12022 gsi = gsi_last_bb (store_bb);
12023 stmt = gsi_stmt (gsi);
12024 gsi_remove (&gsi, true);
12026 if (gimple_in_ssa_p (cfun))
12028 release_defs (stmt);
12029 update_ssa (TODO_update_ssa_no_phi);
12032 return true;
12035 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12037 oldval = *addr;
12038 repeat:
12039 newval = rhs; // with oldval replacing *addr in rhs
12040 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12041 if (oldval != newval)
12042 goto repeat;
12044 INDEX is log2 of the size of the data type, and thus usable to find the
12045 index of the builtin decl. */
12047 static bool
12048 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12049 tree addr, tree loaded_val, tree stored_val,
12050 int index)
12052 tree loadedi, storedi, initial, new_storedi, old_vali;
12053 tree type, itype, cmpxchg, iaddr;
12054 gimple_stmt_iterator si;
12055 basic_block loop_header = single_succ (load_bb);
12056 gimple *phi, *stmt;
12057 edge e;
12058 enum built_in_function fncode;
12060 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12061 order to use the RELAXED memory model effectively. */
12062 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12063 + index + 1);
12064 cmpxchg = builtin_decl_explicit (fncode);
12065 if (cmpxchg == NULL_TREE)
12066 return false;
12067 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12068 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12070 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12071 return false;
12073 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12074 si = gsi_last_bb (load_bb);
12075 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12077 /* For floating-point values, we'll need to view-convert them to integers
12078 so that we can perform the atomic compare and swap. Simplify the
12079 following code by always setting up the "i"ntegral variables. */
12080 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12082 tree iaddr_val;
12084 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12085 true));
12086 iaddr_val
12087 = force_gimple_operand_gsi (&si,
12088 fold_convert (TREE_TYPE (iaddr), addr),
12089 false, NULL_TREE, true, GSI_SAME_STMT);
12090 stmt = gimple_build_assign (iaddr, iaddr_val);
12091 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12092 loadedi = create_tmp_var (itype);
12093 if (gimple_in_ssa_p (cfun))
12094 loadedi = make_ssa_name (loadedi);
12096 else
12098 iaddr = addr;
12099 loadedi = loaded_val;
12102 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12103 tree loaddecl = builtin_decl_explicit (fncode);
12104 if (loaddecl)
12105 initial
12106 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12107 build_call_expr (loaddecl, 2, iaddr,
12108 build_int_cst (NULL_TREE,
12109 MEMMODEL_RELAXED)));
12110 else
12111 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12112 build_int_cst (TREE_TYPE (iaddr), 0));
12114 initial
12115 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12116 GSI_SAME_STMT);
12118 /* Move the value to the LOADEDI temporary. */
12119 if (gimple_in_ssa_p (cfun))
12121 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12122 phi = create_phi_node (loadedi, loop_header);
12123 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12124 initial);
12126 else
12127 gsi_insert_before (&si,
12128 gimple_build_assign (loadedi, initial),
12129 GSI_SAME_STMT);
12130 if (loadedi != loaded_val)
12132 gimple_stmt_iterator gsi2;
12133 tree x;
12135 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12136 gsi2 = gsi_start_bb (loop_header);
12137 if (gimple_in_ssa_p (cfun))
12139 gassign *stmt;
12140 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12141 true, GSI_SAME_STMT);
12142 stmt = gimple_build_assign (loaded_val, x);
12143 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12145 else
12147 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12148 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12149 true, GSI_SAME_STMT);
12152 gsi_remove (&si, true);
12154 si = gsi_last_bb (store_bb);
12155 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12157 if (iaddr == addr)
12158 storedi = stored_val;
12159 else
12160 storedi =
12161 force_gimple_operand_gsi (&si,
12162 build1 (VIEW_CONVERT_EXPR, itype,
12163 stored_val), true, NULL_TREE, true,
12164 GSI_SAME_STMT);
12166 /* Build the compare&swap statement. */
12167 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12168 new_storedi = force_gimple_operand_gsi (&si,
12169 fold_convert (TREE_TYPE (loadedi),
12170 new_storedi),
12171 true, NULL_TREE,
12172 true, GSI_SAME_STMT);
12174 if (gimple_in_ssa_p (cfun))
12175 old_vali = loadedi;
12176 else
12178 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12179 stmt = gimple_build_assign (old_vali, loadedi);
12180 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12182 stmt = gimple_build_assign (loadedi, new_storedi);
12183 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12186 /* Note that we always perform the comparison as an integer, even for
12187 floating point. This allows the atomic operation to properly
12188 succeed even with NaNs and -0.0. */
12189 stmt = gimple_build_cond_empty
12190 (build2 (NE_EXPR, boolean_type_node,
12191 new_storedi, old_vali));
12192 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12194 /* Update cfg. */
12195 e = single_succ_edge (store_bb);
12196 e->flags &= ~EDGE_FALLTHRU;
12197 e->flags |= EDGE_FALSE_VALUE;
12199 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12201 /* Copy the new value to loadedi (we already did that before the condition
12202 if we are not in SSA). */
12203 if (gimple_in_ssa_p (cfun))
12205 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12206 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12209 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12210 gsi_remove (&si, true);
12212 struct loop *loop = alloc_loop ();
12213 loop->header = loop_header;
12214 loop->latch = store_bb;
12215 add_loop (loop, loop_header->loop_father);
12217 if (gimple_in_ssa_p (cfun))
12218 update_ssa (TODO_update_ssa_no_phi);
12220 return true;
12223 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12225 GOMP_atomic_start ();
12226 *addr = rhs;
12227 GOMP_atomic_end ();
12229 The result is not globally atomic, but works so long as all parallel
12230 references are within #pragma omp atomic directives. According to
12231 responses received from omp@openmp.org, appears to be within spec.
12232 Which makes sense, since that's how several other compilers handle
12233 this situation as well.
12234 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12235 expanding. STORED_VAL is the operand of the matching
12236 GIMPLE_OMP_ATOMIC_STORE.
12238 We replace
12239 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12240 loaded_val = *addr;
12242 and replace
12243 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12244 *addr = stored_val;
12247 static bool
12248 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12249 tree addr, tree loaded_val, tree stored_val)
12251 gimple_stmt_iterator si;
12252 gassign *stmt;
12253 tree t;
12255 si = gsi_last_bb (load_bb);
12256 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12258 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12259 t = build_call_expr (t, 0);
12260 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12262 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12263 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12264 gsi_remove (&si, true);
12266 si = gsi_last_bb (store_bb);
12267 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12269 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12270 stored_val);
12271 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12273 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12274 t = build_call_expr (t, 0);
12275 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12276 gsi_remove (&si, true);
12278 if (gimple_in_ssa_p (cfun))
12279 update_ssa (TODO_update_ssa_no_phi);
12280 return true;
12283 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12284 using expand_omp_atomic_fetch_op. If it failed, we try to
12285 call expand_omp_atomic_pipeline, and if it fails too, the
12286 ultimate fallback is wrapping the operation in a mutex
12287 (expand_omp_atomic_mutex). REGION is the atomic region built
12288 by build_omp_regions_1(). */
12290 static void
12291 expand_omp_atomic (struct omp_region *region)
12293 basic_block load_bb = region->entry, store_bb = region->exit;
12294 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12295 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12296 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12297 tree addr = gimple_omp_atomic_load_rhs (load);
12298 tree stored_val = gimple_omp_atomic_store_val (store);
12299 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12300 HOST_WIDE_INT index;
12302 /* Make sure the type is one of the supported sizes. */
12303 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12304 index = exact_log2 (index);
12305 if (index >= 0 && index <= 4)
12307 unsigned int align = TYPE_ALIGN_UNIT (type);
12309 /* __sync builtins require strict data alignment. */
12310 if (exact_log2 (align) >= index)
12312 /* Atomic load. */
12313 if (loaded_val == stored_val
12314 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12315 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12316 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12317 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12318 return;
12320 /* Atomic store. */
12321 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12322 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12323 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12324 && store_bb == single_succ (load_bb)
12325 && first_stmt (store_bb) == store
12326 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12327 stored_val, index))
12328 return;
12330 /* When possible, use specialized atomic update functions. */
12331 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12332 && store_bb == single_succ (load_bb)
12333 && expand_omp_atomic_fetch_op (load_bb, addr,
12334 loaded_val, stored_val, index))
12335 return;
12337 /* If we don't have specialized __sync builtins, try and implement
12338 as a compare and swap loop. */
12339 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12340 loaded_val, stored_val, index))
12341 return;
12345 /* The ultimate fallback is wrapping the operation in a mutex. */
12346 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12350 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12351 macro on gomp-constants.h. We do not check for overflow. */
12353 static tree
12354 oacc_launch_pack (unsigned code, tree device, unsigned op)
12356 tree res;
12358 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12359 if (device)
12361 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12362 device, build_int_cst (unsigned_type_node,
12363 GOMP_LAUNCH_DEVICE_SHIFT));
12364 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12366 return res;
12369 /* Look for compute grid dimension clauses and convert to an attribute
12370 attached to FN. This permits the target-side code to (a) massage
12371 the dimensions, (b) emit that data and (c) optimize. Non-constant
12372 dimensions are pushed onto ARGS.
12374 The attribute value is a TREE_LIST. A set of dimensions is
12375 represented as a list of INTEGER_CST. Those that are runtime
12376 exprs are represented as an INTEGER_CST of zero.
12378 TOOO. Normally the attribute will just contain a single such list. If
12379 however it contains a list of lists, this will represent the use of
12380 device_type. Each member of the outer list is an assoc list of
12381 dimensions, keyed by the device type. The first entry will be the
12382 default. Well, that's the plan. */
12384 #define OACC_FN_ATTRIB "oacc function"
12386 /* Replace any existing oacc fn attribute with updated dimensions. */
12388 void
12389 replace_oacc_fn_attrib (tree fn, tree dims)
12391 tree ident = get_identifier (OACC_FN_ATTRIB);
12392 tree attribs = DECL_ATTRIBUTES (fn);
12394 /* If we happen to be present as the first attrib, drop it. */
12395 if (attribs && TREE_PURPOSE (attribs) == ident)
12396 attribs = TREE_CHAIN (attribs);
12397 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12400 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12401 function attribute. Push any that are non-constant onto the ARGS
12402 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12404 static void
12405 set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12407 /* Must match GOMP_DIM ordering. */
12408 static const omp_clause_code ids[]
12409 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12410 OMP_CLAUSE_VECTOR_LENGTH };
12411 unsigned ix;
12412 tree dims[GOMP_DIM_MAX];
12413 tree attr = NULL_TREE;
12414 unsigned non_const = 0;
12416 for (ix = GOMP_DIM_MAX; ix--;)
12418 tree clause = find_omp_clause (clauses, ids[ix]);
12419 tree dim = NULL_TREE;
12421 if (clause)
12422 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12423 dims[ix] = dim;
12424 if (dim && TREE_CODE (dim) != INTEGER_CST)
12426 dim = integer_zero_node;
12427 non_const |= GOMP_DIM_MASK (ix);
12429 attr = tree_cons (NULL_TREE, dim, attr);
12432 replace_oacc_fn_attrib (fn, attr);
12434 if (non_const)
12436 /* Push a dynamic argument set. */
12437 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12438 NULL_TREE, non_const));
12439 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12440 if (non_const & GOMP_DIM_MASK (ix))
12441 args->safe_push (dims[ix]);
12445 /* Process the routine's dimension clauess to generate an attribute
12446 value. Issue diagnostics as appropriate. We default to SEQ
12447 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12448 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12449 can have a loop partitioned on it. non-zero indicates
12450 yes, zero indicates no. By construction once a non-zero has been
12451 reached, further inner dimensions must also be non-zero. We set
12452 TREE_VALUE to zero for the dimensions that may be partitioned and
12453 1 for the other ones -- if a loop is (erroneously) spawned at
12454 an outer level, we don't want to try and partition it. */
12456 tree
12457 build_oacc_routine_dims (tree clauses)
12459 /* Must match GOMP_DIM ordering. */
12460 static const omp_clause_code ids[] =
12461 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12462 int ix;
12463 int level = -1;
12465 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12466 for (ix = GOMP_DIM_MAX + 1; ix--;)
12467 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12469 if (level >= 0)
12470 error_at (OMP_CLAUSE_LOCATION (clauses),
12471 "multiple loop axes specified for routine");
12472 level = ix;
12473 break;
12476 /* Default to SEQ. */
12477 if (level < 0)
12478 level = GOMP_DIM_MAX;
12480 tree dims = NULL_TREE;
12482 for (ix = GOMP_DIM_MAX; ix--;)
12483 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12484 build_int_cst (integer_type_node, ix < level), dims);
12486 return dims;
12489 /* Retrieve the oacc function attrib and return it. Non-oacc
12490 functions will return NULL. */
12492 tree
12493 get_oacc_fn_attrib (tree fn)
12495 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12498 /* Extract an oacc execution dimension from FN. FN must be an
12499 offloaded function or routine that has already had its execution
12500 dimensions lowered to the target-specific values. */
12503 get_oacc_fn_dim_size (tree fn, int axis)
12505 tree attrs = get_oacc_fn_attrib (fn);
12507 gcc_assert (axis < GOMP_DIM_MAX);
12509 tree dims = TREE_VALUE (attrs);
12510 while (axis--)
12511 dims = TREE_CHAIN (dims);
12513 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12515 return size;
12518 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12519 IFN_GOACC_DIM_SIZE call. */
12522 get_oacc_ifn_dim_arg (const gimple *stmt)
12524 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12525 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12526 tree arg = gimple_call_arg (stmt, 0);
12527 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12529 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12530 return (int) axis;
12533 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12534 at REGION_EXIT. */
12536 static void
12537 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12538 basic_block region_exit)
12540 struct loop *outer = region_entry->loop_father;
12541 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12543 /* Don't parallelize the kernels region if it contains more than one outer
12544 loop. */
12545 unsigned int nr_outer_loops = 0;
12546 struct loop *single_outer = NULL;
12547 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12549 gcc_assert (loop_outer (loop) == outer);
12551 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12552 continue;
12554 if (region_exit != NULL
12555 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12556 continue;
12558 nr_outer_loops++;
12559 single_outer = loop;
12561 if (nr_outer_loops != 1)
12562 return;
12564 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12565 if (loop->next)
12566 return;
12568 /* Mark the loops in the region. */
12569 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12570 loop->in_oacc_kernels_region = true;
12573 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12575 static void
12576 expand_omp_target (struct omp_region *region)
12578 basic_block entry_bb, exit_bb, new_bb;
12579 struct function *child_cfun;
12580 tree child_fn, block, t;
12581 gimple_stmt_iterator gsi;
12582 gomp_target *entry_stmt;
12583 gimple *stmt;
12584 edge e;
12585 bool offloaded, data_region;
12587 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
12588 new_bb = region->entry;
12590 offloaded = is_gimple_omp_offloaded (entry_stmt);
12591 switch (gimple_omp_target_kind (entry_stmt))
12593 case GF_OMP_TARGET_KIND_REGION:
12594 case GF_OMP_TARGET_KIND_UPDATE:
12595 case GF_OMP_TARGET_KIND_ENTER_DATA:
12596 case GF_OMP_TARGET_KIND_EXIT_DATA:
12597 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12598 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12599 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12600 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12601 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12602 data_region = false;
12603 break;
12604 case GF_OMP_TARGET_KIND_DATA:
12605 case GF_OMP_TARGET_KIND_OACC_DATA:
12606 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12607 data_region = true;
12608 break;
12609 default:
12610 gcc_unreachable ();
12613 child_fn = NULL_TREE;
12614 child_cfun = NULL;
12615 if (offloaded)
12617 child_fn = gimple_omp_target_child_fn (entry_stmt);
12618 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12621 /* Supported by expand_omp_taskreg, but not here. */
12622 if (child_cfun != NULL)
12623 gcc_checking_assert (!child_cfun->cfg);
12624 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12626 entry_bb = region->entry;
12627 exit_bb = region->exit;
12629 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
12630 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
12632 if (offloaded)
12634 unsigned srcidx, dstidx, num;
12636 /* If the offloading region needs data sent from the parent
12637 function, then the very first statement (except possible
12638 tree profile counter updates) of the offloading body
12639 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12640 &.OMP_DATA_O is passed as an argument to the child function,
12641 we need to replace it with the argument as seen by the child
12642 function.
12644 In most cases, this will end up being the identity assignment
12645 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
12646 a function call that has been inlined, the original PARM_DECL
12647 .OMP_DATA_I may have been converted into a different local
12648 variable. In which case, we need to keep the assignment. */
12649 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12650 if (data_arg)
12652 basic_block entry_succ_bb = single_succ (entry_bb);
12653 gimple_stmt_iterator gsi;
12654 tree arg;
12655 gimple *tgtcopy_stmt = NULL;
12656 tree sender = TREE_VEC_ELT (data_arg, 0);
12658 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12660 gcc_assert (!gsi_end_p (gsi));
12661 stmt = gsi_stmt (gsi);
12662 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12663 continue;
12665 if (gimple_num_ops (stmt) == 2)
12667 tree arg = gimple_assign_rhs1 (stmt);
12669 /* We're ignoring the subcode because we're
12670 effectively doing a STRIP_NOPS. */
12672 if (TREE_CODE (arg) == ADDR_EXPR
12673 && TREE_OPERAND (arg, 0) == sender)
12675 tgtcopy_stmt = stmt;
12676 break;
12681 gcc_assert (tgtcopy_stmt != NULL);
12682 arg = DECL_ARGUMENTS (child_fn);
12684 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12685 gsi_remove (&gsi, true);
12688 /* Declare local variables needed in CHILD_CFUN. */
12689 block = DECL_INITIAL (child_fn);
12690 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
12691 /* The gimplifier could record temporaries in the offloading block
12692 rather than in containing function's local_decls chain,
12693 which would mean cgraph missed finalizing them. Do it now. */
12694 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12695 if (TREE_CODE (t) == VAR_DECL
12696 && TREE_STATIC (t)
12697 && !DECL_EXTERNAL (t))
12698 varpool_node::finalize_decl (t);
12699 DECL_SAVED_TREE (child_fn) = NULL;
12700 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12701 gimple_set_body (child_fn, NULL);
12702 TREE_USED (block) = 1;
12704 /* Reset DECL_CONTEXT on function arguments. */
12705 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12706 DECL_CONTEXT (t) = child_fn;
12708 /* Split ENTRY_BB at GIMPLE_*,
12709 so that it can be moved to the child function. */
12710 gsi = gsi_last_bb (entry_bb);
12711 stmt = gsi_stmt (gsi);
12712 gcc_assert (stmt
12713 && gimple_code (stmt) == gimple_code (entry_stmt));
12714 e = split_block (entry_bb, stmt);
12715 gsi_remove (&gsi, true);
12716 entry_bb = e->dest;
12717 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12719 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12720 if (exit_bb)
12722 gsi = gsi_last_bb (exit_bb);
12723 gcc_assert (!gsi_end_p (gsi)
12724 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12725 stmt = gimple_build_return (NULL);
12726 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12727 gsi_remove (&gsi, true);
12730 /* Move the offloading region into CHILD_CFUN. */
12732 block = gimple_block (entry_stmt);
12734 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12735 if (exit_bb)
12736 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12737 /* When the OMP expansion process cannot guarantee an up-to-date
12738 loop tree arrange for the child function to fixup loops. */
12739 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12740 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12742 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12743 num = vec_safe_length (child_cfun->local_decls);
12744 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12746 t = (*child_cfun->local_decls)[srcidx];
12747 if (DECL_CONTEXT (t) == cfun->decl)
12748 continue;
12749 if (srcidx != dstidx)
12750 (*child_cfun->local_decls)[dstidx] = t;
12751 dstidx++;
12753 if (dstidx != num)
12754 vec_safe_truncate (child_cfun->local_decls, dstidx);
12756 /* Inform the callgraph about the new function. */
12757 child_cfun->curr_properties = cfun->curr_properties;
12758 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12759 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
12760 cgraph_node *node = cgraph_node::get_create (child_fn);
12761 node->parallelized_function = 1;
12762 cgraph_node::add_new_function (child_fn, true);
12764 /* Add the new function to the offload table. */
12765 if (ENABLE_OFFLOADING)
12766 vec_safe_push (offload_funcs, child_fn);
12768 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
12769 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
12771 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12772 fixed in a following pass. */
12773 push_cfun (child_cfun);
12774 if (need_asm)
12775 assign_assembler_name_if_neeeded (child_fn);
12776 cgraph_edge::rebuild_edges ();
12778 /* Some EH regions might become dead, see PR34608. If
12779 pass_cleanup_cfg isn't the first pass to happen with the
12780 new child, these dead EH edges might cause problems.
12781 Clean them up now. */
12782 if (flag_exceptions)
12784 basic_block bb;
12785 bool changed = false;
12787 FOR_EACH_BB_FN (bb, cfun)
12788 changed |= gimple_purge_dead_eh_edges (bb);
12789 if (changed)
12790 cleanup_tree_cfg ();
12792 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12793 verify_loop_structure ();
12794 pop_cfun ();
12796 if (dump_file && !gimple_in_ssa_p (cfun))
12798 omp_any_child_fn_dumped = true;
12799 dump_function_header (dump_file, child_fn, dump_flags);
12800 dump_function_to_file (child_fn, dump_file, dump_flags);
12804 /* Emit a library call to launch the offloading region, or do data
12805 transfers. */
12806 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
12807 enum built_in_function start_ix;
12808 location_t clause_loc;
12809 unsigned int flags_i = 0;
12811 switch (gimple_omp_target_kind (entry_stmt))
12813 case GF_OMP_TARGET_KIND_REGION:
12814 start_ix = BUILT_IN_GOMP_TARGET;
12815 break;
12816 case GF_OMP_TARGET_KIND_DATA:
12817 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12818 break;
12819 case GF_OMP_TARGET_KIND_UPDATE:
12820 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12821 break;
12822 case GF_OMP_TARGET_KIND_ENTER_DATA:
12823 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12824 break;
12825 case GF_OMP_TARGET_KIND_EXIT_DATA:
12826 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12827 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12828 break;
12829 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12830 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12831 start_ix = BUILT_IN_GOACC_PARALLEL;
12832 break;
12833 case GF_OMP_TARGET_KIND_OACC_DATA:
12834 start_ix = BUILT_IN_GOACC_DATA_START;
12835 break;
12836 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12837 start_ix = BUILT_IN_GOACC_UPDATE;
12838 break;
12839 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12840 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12841 break;
12842 case GF_OMP_TARGET_KIND_OACC_DECLARE:
12843 start_ix = BUILT_IN_GOACC_DECLARE;
12844 break;
12845 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
12846 start_ix = BUILT_IN_GOACC_HOST_DATA;
12847 break;
12848 default:
12849 gcc_unreachable ();
12852 clauses = gimple_omp_target_clauses (entry_stmt);
12854 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12855 library choose) and there is no conditional. */
12856 cond = NULL_TREE;
12857 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
12859 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12860 if (c)
12861 cond = OMP_CLAUSE_IF_EXPR (c);
12863 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12864 if (c)
12866 /* Even if we pass it to all library function calls, it is currently only
12867 defined/used for the OpenMP target ones. */
12868 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12869 || start_ix == BUILT_IN_GOMP_TARGET_DATA
12870 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12871 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
12873 device = OMP_CLAUSE_DEVICE_ID (c);
12874 clause_loc = OMP_CLAUSE_LOCATION (c);
12876 else
12877 clause_loc = gimple_location (entry_stmt);
12879 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12880 if (c)
12881 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12883 /* Ensure 'device' is of the correct type. */
12884 device = fold_convert_loc (clause_loc, integer_type_node, device);
12886 /* If we found the clause 'if (cond)', build
12887 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
12888 if (cond)
12890 cond = gimple_boolify (cond);
12892 basic_block cond_bb, then_bb, else_bb;
12893 edge e;
12894 tree tmp_var;
12896 tmp_var = create_tmp_var (TREE_TYPE (device));
12897 if (offloaded)
12898 e = split_block_after_labels (new_bb);
12899 else
12901 gsi = gsi_last_bb (new_bb);
12902 gsi_prev (&gsi);
12903 e = split_block (new_bb, gsi_stmt (gsi));
12905 cond_bb = e->src;
12906 new_bb = e->dest;
12907 remove_edge (e);
12909 then_bb = create_empty_bb (cond_bb);
12910 else_bb = create_empty_bb (then_bb);
12911 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12912 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12914 stmt = gimple_build_cond_empty (cond);
12915 gsi = gsi_last_bb (cond_bb);
12916 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12918 gsi = gsi_start_bb (then_bb);
12919 stmt = gimple_build_assign (tmp_var, device);
12920 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12922 gsi = gsi_start_bb (else_bb);
12923 stmt = gimple_build_assign (tmp_var,
12924 build_int_cst (integer_type_node,
12925 GOMP_DEVICE_HOST_FALLBACK));
12926 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12928 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12929 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
12930 add_bb_to_loop (then_bb, cond_bb->loop_father);
12931 add_bb_to_loop (else_bb, cond_bb->loop_father);
12932 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12933 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12935 device = tmp_var;
12938 gsi = gsi_last_bb (new_bb);
12939 t = gimple_omp_target_data_arg (entry_stmt);
12940 if (t == NULL)
12942 t1 = size_zero_node;
12943 t2 = build_zero_cst (ptr_type_node);
12944 t3 = t2;
12945 t4 = t2;
12947 else
12949 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12950 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12951 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12952 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12953 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12956 gimple *g;
12957 bool tagging = false;
12958 /* The maximum number used by any start_ix, without varargs. */
12959 auto_vec<tree, 11> args;
12960 args.quick_push (device);
12961 if (offloaded)
12962 args.quick_push (build_fold_addr_expr (child_fn));
12963 args.quick_push (t1);
12964 args.quick_push (t2);
12965 args.quick_push (t3);
12966 args.quick_push (t4);
12967 switch (start_ix)
12969 case BUILT_IN_GOACC_DATA_START:
12970 case BUILT_IN_GOACC_DECLARE:
12971 case BUILT_IN_GOMP_TARGET_DATA:
12972 case BUILT_IN_GOACC_HOST_DATA:
12973 break;
12974 case BUILT_IN_GOMP_TARGET:
12975 case BUILT_IN_GOMP_TARGET_UPDATE:
12976 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12977 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12978 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12979 if (c)
12980 depend = OMP_CLAUSE_DECL (c);
12981 else
12982 depend = build_int_cst (ptr_type_node, 0);
12983 args.quick_push (depend);
12984 if (start_ix == BUILT_IN_GOMP_TARGET)
12986 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12987 if (c)
12989 t = fold_convert (integer_type_node,
12990 OMP_CLAUSE_NUM_TEAMS_EXPR (c));
12991 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12992 true, GSI_SAME_STMT);
12994 else
12995 t = integer_minus_one_node;
12996 args.quick_push (t);
12997 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12998 if (c)
13000 t = fold_convert (integer_type_node,
13001 OMP_CLAUSE_THREAD_LIMIT_EXPR (c));
13002 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
13003 true, GSI_SAME_STMT);
13005 else
13006 t = integer_minus_one_node;
13007 args.quick_push (t);
13009 break;
13010 case BUILT_IN_GOACC_PARALLEL:
13012 set_oacc_fn_attrib (child_fn, clauses, &args);
13013 tagging = true;
13015 /* FALLTHRU */
13016 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13017 case BUILT_IN_GOACC_UPDATE:
13019 tree t_async = NULL_TREE;
13021 /* If present, use the value specified by the respective
13022 clause, making sure that is of the correct type. */
13023 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13024 if (c)
13025 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13026 integer_type_node,
13027 OMP_CLAUSE_ASYNC_EXPR (c));
13028 else if (!tagging)
13029 /* Default values for t_async. */
13030 t_async = fold_convert_loc (gimple_location (entry_stmt),
13031 integer_type_node,
13032 build_int_cst (integer_type_node,
13033 GOMP_ASYNC_SYNC));
13034 if (tagging && t_async)
13036 unsigned HOST_WIDE_INT i_async;
13038 if (TREE_CODE (t_async) == INTEGER_CST)
13040 /* See if we can pack the async arg in to the tag's
13041 operand. */
13042 i_async = TREE_INT_CST_LOW (t_async);
13044 if (i_async < GOMP_LAUNCH_OP_MAX)
13045 t_async = NULL_TREE;
13047 if (t_async)
13048 i_async = GOMP_LAUNCH_OP_MAX;
13049 args.safe_push (oacc_launch_pack
13050 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
13052 if (t_async)
13053 args.safe_push (t_async);
13055 /* Save the argument index, and ... */
13056 unsigned t_wait_idx = args.length ();
13057 unsigned num_waits = 0;
13058 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13059 if (!tagging || c)
13060 /* ... push a placeholder. */
13061 args.safe_push (integer_zero_node);
13063 for (; c; c = OMP_CLAUSE_CHAIN (c))
13064 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13066 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13067 integer_type_node,
13068 OMP_CLAUSE_WAIT_EXPR (c)));
13069 num_waits++;
13072 if (!tagging || num_waits)
13074 tree len;
13076 /* Now that we know the number, update the placeholder. */
13077 if (tagging)
13078 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13079 else
13080 len = build_int_cst (integer_type_node, num_waits);
13081 len = fold_convert_loc (gimple_location (entry_stmt),
13082 unsigned_type_node, len);
13083 args[t_wait_idx] = len;
13086 break;
13087 default:
13088 gcc_unreachable ();
13090 if (tagging)
13091 /* Push terminal marker - zero. */
13092 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13094 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13095 gimple_set_location (g, gimple_location (entry_stmt));
13096 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13097 if (!offloaded)
13099 g = gsi_stmt (gsi);
13100 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13101 gsi_remove (&gsi, true);
13103 if (data_region && region->exit)
13105 gsi = gsi_last_bb (region->exit);
13106 g = gsi_stmt (gsi);
13107 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13108 gsi_remove (&gsi, true);
13113 /* Expand the parallel region tree rooted at REGION. Expansion
13114 proceeds in depth-first order. Innermost regions are expanded
13115 first. This way, parallel regions that require a new function to
13116 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13117 internal dependencies in their body. */
13119 static void
13120 expand_omp (struct omp_region *region)
13122 omp_any_child_fn_dumped = false;
13123 while (region)
13125 location_t saved_location;
13126 gimple *inner_stmt = NULL;
13128 /* First, determine whether this is a combined parallel+workshare
13129 region. */
13130 if (region->type == GIMPLE_OMP_PARALLEL)
13131 determine_parallel_type (region);
13133 if (region->type == GIMPLE_OMP_FOR
13134 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13135 inner_stmt = last_stmt (region->inner->entry);
13137 if (region->inner)
13138 expand_omp (region->inner);
13140 saved_location = input_location;
13141 if (gimple_has_location (last_stmt (region->entry)))
13142 input_location = gimple_location (last_stmt (region->entry));
13144 switch (region->type)
13146 case GIMPLE_OMP_PARALLEL:
13147 case GIMPLE_OMP_TASK:
13148 expand_omp_taskreg (region);
13149 break;
13151 case GIMPLE_OMP_FOR:
13152 expand_omp_for (region, inner_stmt);
13153 break;
13155 case GIMPLE_OMP_SECTIONS:
13156 expand_omp_sections (region);
13157 break;
13159 case GIMPLE_OMP_SECTION:
13160 /* Individual omp sections are handled together with their
13161 parent GIMPLE_OMP_SECTIONS region. */
13162 break;
13164 case GIMPLE_OMP_SINGLE:
13165 expand_omp_single (region);
13166 break;
13168 case GIMPLE_OMP_ORDERED:
13170 gomp_ordered *ord_stmt
13171 = as_a <gomp_ordered *> (last_stmt (region->entry));
13172 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13173 OMP_CLAUSE_DEPEND))
13175 /* We'll expand these when expanding corresponding
13176 worksharing region with ordered(n) clause. */
13177 gcc_assert (region->outer
13178 && region->outer->type == GIMPLE_OMP_FOR);
13179 region->ord_stmt = ord_stmt;
13180 break;
13183 /* FALLTHRU */
13184 case GIMPLE_OMP_MASTER:
13185 case GIMPLE_OMP_TASKGROUP:
13186 case GIMPLE_OMP_CRITICAL:
13187 case GIMPLE_OMP_TEAMS:
13188 expand_omp_synch (region);
13189 break;
13191 case GIMPLE_OMP_ATOMIC_LOAD:
13192 expand_omp_atomic (region);
13193 break;
13195 case GIMPLE_OMP_TARGET:
13196 expand_omp_target (region);
13197 break;
13199 default:
13200 gcc_unreachable ();
13203 input_location = saved_location;
13204 region = region->next;
13206 if (omp_any_child_fn_dumped)
13208 if (dump_file)
13209 dump_function_header (dump_file, current_function_decl, dump_flags);
13210 omp_any_child_fn_dumped = false;
13215 /* Helper for build_omp_regions. Scan the dominator tree starting at
13216 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13217 true, the function ends once a single tree is built (otherwise, whole
13218 forest of OMP constructs may be built). */
13220 static void
13221 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13222 bool single_tree)
13224 gimple_stmt_iterator gsi;
13225 gimple *stmt;
13226 basic_block son;
13228 gsi = gsi_last_bb (bb);
13229 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13231 struct omp_region *region;
13232 enum gimple_code code;
13234 stmt = gsi_stmt (gsi);
13235 code = gimple_code (stmt);
13236 if (code == GIMPLE_OMP_RETURN)
13238 /* STMT is the return point out of region PARENT. Mark it
13239 as the exit point and make PARENT the immediately
13240 enclosing region. */
13241 gcc_assert (parent);
13242 region = parent;
13243 region->exit = bb;
13244 parent = parent->outer;
13246 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13248 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13249 GIMPLE_OMP_RETURN, but matches with
13250 GIMPLE_OMP_ATOMIC_LOAD. */
13251 gcc_assert (parent);
13252 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13253 region = parent;
13254 region->exit = bb;
13255 parent = parent->outer;
13257 else if (code == GIMPLE_OMP_CONTINUE)
13259 gcc_assert (parent);
13260 parent->cont = bb;
13262 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13264 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13265 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13267 else
13269 region = new_omp_region (bb, code, parent);
13270 /* Otherwise... */
13271 if (code == GIMPLE_OMP_TARGET)
13273 switch (gimple_omp_target_kind (stmt))
13275 case GF_OMP_TARGET_KIND_REGION:
13276 case GF_OMP_TARGET_KIND_DATA:
13277 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13278 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13279 case GF_OMP_TARGET_KIND_OACC_DATA:
13280 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13281 break;
13282 case GF_OMP_TARGET_KIND_UPDATE:
13283 case GF_OMP_TARGET_KIND_ENTER_DATA:
13284 case GF_OMP_TARGET_KIND_EXIT_DATA:
13285 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13286 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13287 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13288 /* ..., other than for those stand-alone directives... */
13289 region = NULL;
13290 break;
13291 default:
13292 gcc_unreachable ();
13295 else if (code == GIMPLE_OMP_ORDERED
13296 && find_omp_clause (gimple_omp_ordered_clauses
13297 (as_a <gomp_ordered *> (stmt)),
13298 OMP_CLAUSE_DEPEND))
13299 /* #pragma omp ordered depend is also just a stand-alone
13300 directive. */
13301 region = NULL;
13302 /* ..., this directive becomes the parent for a new region. */
13303 if (region)
13304 parent = region;
13308 if (single_tree && !parent)
13309 return;
13311 for (son = first_dom_son (CDI_DOMINATORS, bb);
13312 son;
13313 son = next_dom_son (CDI_DOMINATORS, son))
13314 build_omp_regions_1 (son, parent, single_tree);
13317 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13318 root_omp_region. */
13320 static void
13321 build_omp_regions_root (basic_block root)
13323 gcc_assert (root_omp_region == NULL);
13324 build_omp_regions_1 (root, NULL, true);
13325 gcc_assert (root_omp_region != NULL);
13328 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13330 void
13331 omp_expand_local (basic_block head)
13333 build_omp_regions_root (head);
13334 if (dump_file && (dump_flags & TDF_DETAILS))
13336 fprintf (dump_file, "\nOMP region tree\n\n");
13337 dump_omp_region (dump_file, root_omp_region, 0);
13338 fprintf (dump_file, "\n");
13341 remove_exit_barriers (root_omp_region);
13342 expand_omp (root_omp_region);
13344 free_omp_regions ();
13347 /* Scan the CFG and build a tree of OMP regions. Return the root of
13348 the OMP region tree. */
13350 static void
13351 build_omp_regions (void)
13353 gcc_assert (root_omp_region == NULL);
13354 calculate_dominance_info (CDI_DOMINATORS);
13355 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
13358 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13360 static unsigned int
13361 execute_expand_omp (void)
13363 build_omp_regions ();
13365 if (!root_omp_region)
13366 return 0;
13368 if (dump_file)
13370 fprintf (dump_file, "\nOMP region tree\n\n");
13371 dump_omp_region (dump_file, root_omp_region, 0);
13372 fprintf (dump_file, "\n");
13375 remove_exit_barriers (root_omp_region);
13377 expand_omp (root_omp_region);
13379 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13380 verify_loop_structure ();
13381 cleanup_tree_cfg ();
13383 free_omp_regions ();
13385 return 0;
13388 /* OMP expansion -- the default pass, run before creation of SSA form. */
13390 namespace {
13392 const pass_data pass_data_expand_omp =
13394 GIMPLE_PASS, /* type */
13395 "ompexp", /* name */
13396 OPTGROUP_NONE, /* optinfo_flags */
13397 TV_NONE, /* tv_id */
13398 PROP_gimple_any, /* properties_required */
13399 PROP_gimple_eomp, /* properties_provided */
13400 0, /* properties_destroyed */
13401 0, /* todo_flags_start */
13402 0, /* todo_flags_finish */
13405 class pass_expand_omp : public gimple_opt_pass
13407 public:
13408 pass_expand_omp (gcc::context *ctxt)
13409 : gimple_opt_pass (pass_data_expand_omp, ctxt)
13412 /* opt_pass methods: */
13413 virtual unsigned int execute (function *)
13415 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
13416 || flag_openmp_simd != 0)
13417 && !seen_error ());
13419 /* This pass always runs, to provide PROP_gimple_eomp.
13420 But often, there is nothing to do. */
13421 if (!gate)
13422 return 0;
13424 return execute_expand_omp ();
13427 }; // class pass_expand_omp
13429 } // anon namespace
13431 gimple_opt_pass *
13432 make_pass_expand_omp (gcc::context *ctxt)
13434 return new pass_expand_omp (ctxt);
13437 namespace {
13439 const pass_data pass_data_expand_omp_ssa =
13441 GIMPLE_PASS, /* type */
13442 "ompexpssa", /* name */
13443 OPTGROUP_NONE, /* optinfo_flags */
13444 TV_NONE, /* tv_id */
13445 PROP_cfg | PROP_ssa, /* properties_required */
13446 PROP_gimple_eomp, /* properties_provided */
13447 0, /* properties_destroyed */
13448 0, /* todo_flags_start */
13449 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
13452 class pass_expand_omp_ssa : public gimple_opt_pass
13454 public:
13455 pass_expand_omp_ssa (gcc::context *ctxt)
13456 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
13459 /* opt_pass methods: */
13460 virtual bool gate (function *fun)
13462 return !(fun->curr_properties & PROP_gimple_eomp);
13464 virtual unsigned int execute (function *) { return execute_expand_omp (); }
13465 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
13467 }; // class pass_expand_omp_ssa
13469 } // anon namespace
13471 gimple_opt_pass *
13472 make_pass_expand_omp_ssa (gcc::context *ctxt)
13474 return new pass_expand_omp_ssa (ctxt);
13477 /* Routines to lower OMP directives into OMP-GIMPLE. */
13479 /* If ctx is a worksharing context inside of a cancellable parallel
13480 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13481 and conditional branch to parallel's cancel_label to handle
13482 cancellation in the implicit barrier. */
13484 static void
13485 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13487 gimple *omp_return = gimple_seq_last_stmt (*body);
13488 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13489 if (gimple_omp_return_nowait_p (omp_return))
13490 return;
13491 if (ctx->outer
13492 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13493 && ctx->outer->cancellable)
13495 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13496 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
13497 tree lhs = create_tmp_var (c_bool_type);
13498 gimple_omp_return_set_lhs (omp_return, lhs);
13499 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
13500 gimple *g = gimple_build_cond (NE_EXPR, lhs,
13501 fold_convert (c_bool_type,
13502 boolean_false_node),
13503 ctx->outer->cancel_label, fallthru_label);
13504 gimple_seq_add_stmt (body, g);
13505 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13509 /* Lower the OpenMP sections directive in the current statement in GSI_P.
13510 CTX is the enclosing OMP context for the current statement. */
13512 static void
13513 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13515 tree block, control;
13516 gimple_stmt_iterator tgsi;
13517 gomp_sections *stmt;
13518 gimple *t;
13519 gbind *new_stmt, *bind;
13520 gimple_seq ilist, dlist, olist, new_body;
13522 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
13524 push_gimplify_context ();
13526 dlist = NULL;
13527 ilist = NULL;
13528 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
13529 &ilist, &dlist, ctx, NULL);
13531 new_body = gimple_omp_body (stmt);
13532 gimple_omp_set_body (stmt, NULL);
13533 tgsi = gsi_start (new_body);
13534 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
13536 omp_context *sctx;
13537 gimple *sec_start;
13539 sec_start = gsi_stmt (tgsi);
13540 sctx = maybe_lookup_ctx (sec_start);
13541 gcc_assert (sctx);
13543 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13544 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13545 GSI_CONTINUE_LINKING);
13546 gimple_omp_set_body (sec_start, NULL);
13548 if (gsi_one_before_end_p (tgsi))
13550 gimple_seq l = NULL;
13551 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
13552 &l, ctx);
13553 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
13554 gimple_omp_section_set_last (sec_start);
13557 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13558 GSI_CONTINUE_LINKING);
13561 block = make_node (BLOCK);
13562 bind = gimple_build_bind (NULL, new_body, block);
13564 olist = NULL;
13565 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
13567 block = make_node (BLOCK);
13568 new_stmt = gimple_build_bind (NULL, NULL, block);
13569 gsi_replace (gsi_p, new_stmt, true);
13571 pop_gimplify_context (new_stmt);
13572 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13573 BLOCK_VARS (block) = gimple_bind_vars (bind);
13574 if (BLOCK_VARS (block))
13575 TREE_USED (block) = 1;
13577 new_body = NULL;
13578 gimple_seq_add_seq (&new_body, ilist);
13579 gimple_seq_add_stmt (&new_body, stmt);
13580 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13581 gimple_seq_add_stmt (&new_body, bind);
13583 control = create_tmp_var (unsigned_type_node, ".section");
13584 t = gimple_build_omp_continue (control, control);
13585 gimple_omp_sections_set_control (stmt, control);
13586 gimple_seq_add_stmt (&new_body, t);
13588 gimple_seq_add_seq (&new_body, olist);
13589 if (ctx->cancellable)
13590 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
13591 gimple_seq_add_seq (&new_body, dlist);
13593 new_body = maybe_catch_exception (new_body);
13595 t = gimple_build_omp_return
13596 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13597 OMP_CLAUSE_NOWAIT));
13598 gimple_seq_add_stmt (&new_body, t);
13599 maybe_add_implicit_barrier_cancel (ctx, &new_body);
13601 gimple_bind_set_body (new_stmt, new_body);
13605 /* A subroutine of lower_omp_single. Expand the simple form of
13606 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
13608 if (GOMP_single_start ())
13609 BODY;
13610 [ GOMP_barrier (); ] -> unless 'nowait' is present.
13612 FIXME. It may be better to delay expanding the logic of this until
13613 pass_expand_omp. The expanded logic may make the job more difficult
13614 to a synchronization analysis pass. */
13616 static void
13617 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
13619 location_t loc = gimple_location (single_stmt);
13620 tree tlabel = create_artificial_label (loc);
13621 tree flabel = create_artificial_label (loc);
13622 gimple *call, *cond;
13623 tree lhs, decl;
13625 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
13626 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
13627 call = gimple_build_call (decl, 0);
13628 gimple_call_set_lhs (call, lhs);
13629 gimple_seq_add_stmt (pre_p, call);
13631 cond = gimple_build_cond (EQ_EXPR, lhs,
13632 fold_convert_loc (loc, TREE_TYPE (lhs),
13633 boolean_true_node),
13634 tlabel, flabel);
13635 gimple_seq_add_stmt (pre_p, cond);
13636 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13637 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13638 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
13642 /* A subroutine of lower_omp_single. Expand the simple form of
13643 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
13645 #pragma omp single copyprivate (a, b, c)
13647 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13650 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13652 BODY;
13653 copyout.a = a;
13654 copyout.b = b;
13655 copyout.c = c;
13656 GOMP_single_copy_end (&copyout);
13658 else
13660 a = copyout_p->a;
13661 b = copyout_p->b;
13662 c = copyout_p->c;
13664 GOMP_barrier ();
13667 FIXME. It may be better to delay expanding the logic of this until
13668 pass_expand_omp. The expanded logic may make the job more difficult
13669 to a synchronization analysis pass. */
13671 static void
13672 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13673 omp_context *ctx)
13675 tree ptr_type, t, l0, l1, l2, bfn_decl;
13676 gimple_seq copyin_seq;
13677 location_t loc = gimple_location (single_stmt);
13679 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13681 ptr_type = build_pointer_type (ctx->record_type);
13682 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13684 l0 = create_artificial_label (loc);
13685 l1 = create_artificial_label (loc);
13686 l2 = create_artificial_label (loc);
13688 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13689 t = build_call_expr_loc (loc, bfn_decl, 0);
13690 t = fold_convert_loc (loc, ptr_type, t);
13691 gimplify_assign (ctx->receiver_decl, t, pre_p);
13693 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13694 build_int_cst (ptr_type, 0));
13695 t = build3 (COND_EXPR, void_type_node, t,
13696 build_and_jump (&l0), build_and_jump (&l1));
13697 gimplify_and_add (t, pre_p);
13699 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
13701 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13703 copyin_seq = NULL;
13704 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
13705 &copyin_seq, ctx);
13707 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
13708 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13709 t = build_call_expr_loc (loc, bfn_decl, 1, t);
13710 gimplify_and_add (t, pre_p);
13712 t = build_and_jump (&l2);
13713 gimplify_and_add (t, pre_p);
13715 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
13717 gimple_seq_add_seq (pre_p, copyin_seq);
13719 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
13723 /* Expand code for an OpenMP single directive. */
13725 static void
13726 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13728 tree block;
13729 gimple *t;
13730 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13731 gbind *bind;
13732 gimple_seq bind_body, bind_body_tail = NULL, dlist;
13734 push_gimplify_context ();
13736 block = make_node (BLOCK);
13737 bind = gimple_build_bind (NULL, NULL, block);
13738 gsi_replace (gsi_p, bind, true);
13739 bind_body = NULL;
13740 dlist = NULL;
13741 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
13742 &bind_body, &dlist, ctx, NULL);
13743 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
13745 gimple_seq_add_stmt (&bind_body, single_stmt);
13747 if (ctx->record_type)
13748 lower_omp_single_copy (single_stmt, &bind_body, ctx);
13749 else
13750 lower_omp_single_simple (single_stmt, &bind_body);
13752 gimple_omp_set_body (single_stmt, NULL);
13754 gimple_seq_add_seq (&bind_body, dlist);
13756 bind_body = maybe_catch_exception (bind_body);
13758 t = gimple_build_omp_return
13759 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13760 OMP_CLAUSE_NOWAIT));
13761 gimple_seq_add_stmt (&bind_body_tail, t);
13762 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13763 if (ctx->record_type)
13765 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13766 tree clobber = build_constructor (ctx->record_type, NULL);
13767 TREE_THIS_VOLATILE (clobber) = 1;
13768 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13769 clobber), GSI_SAME_STMT);
13771 gimple_seq_add_seq (&bind_body, bind_body_tail);
13772 gimple_bind_set_body (bind, bind_body);
13774 pop_gimplify_context (bind);
13776 gimple_bind_append_vars (bind, ctx->block_vars);
13777 BLOCK_VARS (block) = ctx->block_vars;
13778 if (BLOCK_VARS (block))
13779 TREE_USED (block) = 1;
13783 /* Expand code for an OpenMP master directive. */
13785 static void
13786 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13788 tree block, lab = NULL, x, bfn_decl;
13789 gimple *stmt = gsi_stmt (*gsi_p);
13790 gbind *bind;
13791 location_t loc = gimple_location (stmt);
13792 gimple_seq tseq;
13794 push_gimplify_context ();
13796 block = make_node (BLOCK);
13797 bind = gimple_build_bind (NULL, NULL, block);
13798 gsi_replace (gsi_p, bind, true);
13799 gimple_bind_add_stmt (bind, stmt);
13801 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13802 x = build_call_expr_loc (loc, bfn_decl, 0);
13803 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13804 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
13805 tseq = NULL;
13806 gimplify_and_add (x, &tseq);
13807 gimple_bind_add_seq (bind, tseq);
13809 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13810 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13811 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13812 gimple_omp_set_body (stmt, NULL);
13814 gimple_bind_add_stmt (bind, gimple_build_label (lab));
13816 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13818 pop_gimplify_context (bind);
13820 gimple_bind_append_vars (bind, ctx->block_vars);
13821 BLOCK_VARS (block) = ctx->block_vars;
13825 /* Expand code for an OpenMP taskgroup directive. */
13827 static void
13828 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13830 gimple *stmt = gsi_stmt (*gsi_p);
13831 gcall *x;
13832 gbind *bind;
13833 tree block = make_node (BLOCK);
13835 bind = gimple_build_bind (NULL, NULL, block);
13836 gsi_replace (gsi_p, bind, true);
13837 gimple_bind_add_stmt (bind, stmt);
13839 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13841 gimple_bind_add_stmt (bind, x);
13843 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13844 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13845 gimple_omp_set_body (stmt, NULL);
13847 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13849 gimple_bind_append_vars (bind, ctx->block_vars);
13850 BLOCK_VARS (block) = ctx->block_vars;
13854 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13856 static void
13857 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13858 omp_context *ctx)
13860 struct omp_for_data fd;
13861 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13862 return;
13864 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13865 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13866 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13867 if (!fd.ordered)
13868 return;
13870 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13871 tree c = gimple_omp_ordered_clauses (ord_stmt);
13872 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13873 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13875 /* Merge depend clauses from multiple adjacent
13876 #pragma omp ordered depend(sink:...) constructs
13877 into one #pragma omp ordered depend(sink:...), so that
13878 we can optimize them together. */
13879 gimple_stmt_iterator gsi = *gsi_p;
13880 gsi_next (&gsi);
13881 while (!gsi_end_p (gsi))
13883 gimple *stmt = gsi_stmt (gsi);
13884 if (is_gimple_debug (stmt)
13885 || gimple_code (stmt) == GIMPLE_NOP)
13887 gsi_next (&gsi);
13888 continue;
13890 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13891 break;
13892 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13893 c = gimple_omp_ordered_clauses (ord_stmt2);
13894 if (c == NULL_TREE
13895 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13896 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13897 break;
13898 while (*list_p)
13899 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13900 *list_p = c;
13901 gsi_remove (&gsi, true);
13905 /* Canonicalize sink dependence clauses into one folded clause if
13906 possible.
13908 The basic algorithm is to create a sink vector whose first
13909 element is the GCD of all the first elements, and whose remaining
13910 elements are the minimum of the subsequent columns.
13912 We ignore dependence vectors whose first element is zero because
13913 such dependencies are known to be executed by the same thread.
13915 We take into account the direction of the loop, so a minimum
13916 becomes a maximum if the loop is iterating forwards. We also
13917 ignore sink clauses where the loop direction is unknown, or where
13918 the offsets are clearly invalid because they are not a multiple
13919 of the loop increment.
13921 For example:
13923 #pragma omp for ordered(2)
13924 for (i=0; i < N; ++i)
13925 for (j=0; j < M; ++j)
13927 #pragma omp ordered \
13928 depend(sink:i-8,j-2) \
13929 depend(sink:i,j-1) \ // Completely ignored because i+0.
13930 depend(sink:i-4,j-3) \
13931 depend(sink:i-6,j-4)
13932 #pragma omp ordered depend(source)
13935 Folded clause is:
13937 depend(sink:-gcd(8,4,6),-min(2,3,4))
13938 -or-
13939 depend(sink:-2,-2)
13942 /* FIXME: Computing GCD's where the first element is zero is
13943 non-trivial in the presence of collapsed loops. Do this later. */
13944 if (fd.collapse > 1)
13945 return;
13947 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13948 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13949 tree folded_dep = NULL_TREE;
13950 /* TRUE if the first dimension's offset is negative. */
13951 bool neg_offset_p = false;
13953 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13954 unsigned int i;
13955 while ((c = *list_p) != NULL)
13957 bool remove = false;
13959 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13960 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13961 goto next_ordered_clause;
13963 tree vec;
13964 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13965 vec && TREE_CODE (vec) == TREE_LIST;
13966 vec = TREE_CHAIN (vec), ++i)
13968 gcc_assert (i < len);
13970 /* extract_omp_for_data has canonicalized the condition. */
13971 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13972 || fd.loops[i].cond_code == GT_EXPR);
13973 bool forward = fd.loops[i].cond_code == LT_EXPR;
13974 bool maybe_lexically_later = true;
13976 /* While the committee makes up its mind, bail if we have any
13977 non-constant steps. */
13978 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13979 goto lower_omp_ordered_ret;
13981 tree itype = TREE_TYPE (TREE_VALUE (vec));
13982 if (POINTER_TYPE_P (itype))
13983 itype = sizetype;
13984 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13985 TYPE_PRECISION (itype),
13986 TYPE_SIGN (itype));
13988 /* Ignore invalid offsets that are not multiples of the step. */
13989 if (!wi::multiple_of_p
13990 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13991 UNSIGNED))
13993 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13994 "ignoring sink clause with offset that is not "
13995 "a multiple of the loop step");
13996 remove = true;
13997 goto next_ordered_clause;
14000 /* Calculate the first dimension. The first dimension of
14001 the folded dependency vector is the GCD of the first
14002 elements, while ignoring any first elements whose offset
14003 is 0. */
14004 if (i == 0)
14006 /* Ignore dependence vectors whose first dimension is 0. */
14007 if (offset == 0)
14009 remove = true;
14010 goto next_ordered_clause;
14012 else
14014 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14016 error_at (OMP_CLAUSE_LOCATION (c),
14017 "first offset must be in opposite direction "
14018 "of loop iterations");
14019 goto lower_omp_ordered_ret;
14021 if (forward)
14022 offset = -offset;
14023 neg_offset_p = forward;
14024 /* Initialize the first time around. */
14025 if (folded_dep == NULL_TREE)
14027 folded_dep = c;
14028 folded_deps[0] = offset;
14030 else
14031 folded_deps[0] = wi::gcd (folded_deps[0],
14032 offset, UNSIGNED);
14035 /* Calculate minimum for the remaining dimensions. */
14036 else
14038 folded_deps[len + i - 1] = offset;
14039 if (folded_dep == c)
14040 folded_deps[i] = offset;
14041 else if (maybe_lexically_later
14042 && !wi::eq_p (folded_deps[i], offset))
14044 if (forward ^ wi::gts_p (folded_deps[i], offset))
14046 unsigned int j;
14047 folded_dep = c;
14048 for (j = 1; j <= i; j++)
14049 folded_deps[j] = folded_deps[len + j - 1];
14051 else
14052 maybe_lexically_later = false;
14056 gcc_assert (i == len);
14058 remove = true;
14060 next_ordered_clause:
14061 if (remove)
14062 *list_p = OMP_CLAUSE_CHAIN (c);
14063 else
14064 list_p = &OMP_CLAUSE_CHAIN (c);
14067 if (folded_dep)
14069 if (neg_offset_p)
14070 folded_deps[0] = -folded_deps[0];
14072 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14073 if (POINTER_TYPE_P (itype))
14074 itype = sizetype;
14076 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14077 = wide_int_to_tree (itype, folded_deps[0]);
14078 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14079 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14082 lower_omp_ordered_ret:
14084 /* Ordered without clauses is #pragma omp threads, while we want
14085 a nop instead if we remove all clauses. */
14086 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14087 gsi_replace (gsi_p, gimple_build_nop (), true);
14091 /* Expand code for an OpenMP ordered directive. */
14093 static void
14094 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14096 tree block;
14097 gimple *stmt = gsi_stmt (*gsi_p);
14098 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14099 gcall *x;
14100 gbind *bind;
14101 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14102 OMP_CLAUSE_SIMD);
14103 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14104 OMP_CLAUSE_THREADS);
14106 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14107 OMP_CLAUSE_DEPEND))
14109 /* FIXME: This is needs to be moved to the expansion to verify various
14110 conditions only testable on cfg with dominators computed, and also
14111 all the depend clauses to be merged still might need to be available
14112 for the runtime checks. */
14113 if (0)
14114 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14115 return;
14118 push_gimplify_context ();
14120 block = make_node (BLOCK);
14121 bind = gimple_build_bind (NULL, NULL, block);
14122 gsi_replace (gsi_p, bind, true);
14123 gimple_bind_add_stmt (bind, stmt);
14125 if (simd)
14127 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14128 build_int_cst (NULL_TREE, threads));
14129 cfun->has_simduid_loops = true;
14131 else
14132 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14134 gimple_bind_add_stmt (bind, x);
14136 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14137 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14138 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14139 gimple_omp_set_body (stmt, NULL);
14141 if (simd)
14142 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14143 build_int_cst (NULL_TREE, threads));
14144 else
14145 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14147 gimple_bind_add_stmt (bind, x);
14149 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14151 pop_gimplify_context (bind);
14153 gimple_bind_append_vars (bind, ctx->block_vars);
14154 BLOCK_VARS (block) = gimple_bind_vars (bind);
14158 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14159 substitution of a couple of function calls. But in the NAMED case,
14160 requires that languages coordinate a symbol name. It is therefore
14161 best put here in common code. */
14163 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14165 static void
14166 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14168 tree block;
14169 tree name, lock, unlock;
14170 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14171 gbind *bind;
14172 location_t loc = gimple_location (stmt);
14173 gimple_seq tbody;
14175 name = gimple_omp_critical_name (stmt);
14176 if (name)
14178 tree decl;
14180 if (!critical_name_mutexes)
14181 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14183 tree *n = critical_name_mutexes->get (name);
14184 if (n == NULL)
14186 char *new_str;
14188 decl = create_tmp_var_raw (ptr_type_node);
14190 new_str = ACONCAT ((".gomp_critical_user_",
14191 IDENTIFIER_POINTER (name), NULL));
14192 DECL_NAME (decl) = get_identifier (new_str);
14193 TREE_PUBLIC (decl) = 1;
14194 TREE_STATIC (decl) = 1;
14195 DECL_COMMON (decl) = 1;
14196 DECL_ARTIFICIAL (decl) = 1;
14197 DECL_IGNORED_P (decl) = 1;
14199 varpool_node::finalize_decl (decl);
14201 critical_name_mutexes->put (name, decl);
14203 else
14204 decl = *n;
14206 /* If '#pragma omp critical' is inside offloaded region or
14207 inside function marked as offloadable, the symbol must be
14208 marked as offloadable too. */
14209 omp_context *octx;
14210 if (cgraph_node::get (current_function_decl)->offloadable)
14211 varpool_node::get_create (decl)->offloadable = 1;
14212 else
14213 for (octx = ctx->outer; octx; octx = octx->outer)
14214 if (is_gimple_omp_offloaded (octx->stmt))
14216 varpool_node::get_create (decl)->offloadable = 1;
14217 break;
14220 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14221 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14223 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14224 unlock = build_call_expr_loc (loc, unlock, 1,
14225 build_fold_addr_expr_loc (loc, decl));
14227 else
14229 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14230 lock = build_call_expr_loc (loc, lock, 0);
14232 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14233 unlock = build_call_expr_loc (loc, unlock, 0);
14236 push_gimplify_context ();
14238 block = make_node (BLOCK);
14239 bind = gimple_build_bind (NULL, NULL, block);
14240 gsi_replace (gsi_p, bind, true);
14241 gimple_bind_add_stmt (bind, stmt);
14243 tbody = gimple_bind_body (bind);
14244 gimplify_and_add (lock, &tbody);
14245 gimple_bind_set_body (bind, tbody);
14247 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14248 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14249 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14250 gimple_omp_set_body (stmt, NULL);
14252 tbody = gimple_bind_body (bind);
14253 gimplify_and_add (unlock, &tbody);
14254 gimple_bind_set_body (bind, tbody);
14256 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14258 pop_gimplify_context (bind);
14259 gimple_bind_append_vars (bind, ctx->block_vars);
14260 BLOCK_VARS (block) = gimple_bind_vars (bind);
14264 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14265 for a lastprivate clause. Given a loop control predicate of (V
14266 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14267 is appended to *DLIST, iterator initialization is appended to
14268 *BODY_P. */
14270 static void
14271 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14272 gimple_seq *dlist, struct omp_context *ctx)
14274 tree clauses, cond, vinit;
14275 enum tree_code cond_code;
14276 gimple_seq stmts;
14278 cond_code = fd->loop.cond_code;
14279 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14281 /* When possible, use a strict equality expression. This can let VRP
14282 type optimizations deduce the value and remove a copy. */
14283 if (tree_fits_shwi_p (fd->loop.step))
14285 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14286 if (step == 1 || step == -1)
14287 cond_code = EQ_EXPR;
14290 tree n2 = fd->loop.n2;
14291 if (fd->collapse > 1
14292 && TREE_CODE (n2) != INTEGER_CST
14293 && gimple_omp_for_combined_into_p (fd->for_stmt))
14295 struct omp_context *taskreg_ctx = NULL;
14296 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14298 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14299 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14300 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14302 if (gimple_omp_for_combined_into_p (gfor))
14304 gcc_assert (ctx->outer->outer
14305 && is_parallel_ctx (ctx->outer->outer));
14306 taskreg_ctx = ctx->outer->outer;
14308 else
14310 struct omp_for_data outer_fd;
14311 extract_omp_for_data (gfor, &outer_fd, NULL);
14312 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14315 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14316 taskreg_ctx = ctx->outer->outer;
14318 else if (is_taskreg_ctx (ctx->outer))
14319 taskreg_ctx = ctx->outer;
14320 if (taskreg_ctx)
14322 int i;
14323 tree innerc
14324 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14325 OMP_CLAUSE__LOOPTEMP_);
14326 gcc_assert (innerc);
14327 for (i = 0; i < fd->collapse; i++)
14329 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14330 OMP_CLAUSE__LOOPTEMP_);
14331 gcc_assert (innerc);
14333 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14334 OMP_CLAUSE__LOOPTEMP_);
14335 if (innerc)
14336 n2 = fold_convert (TREE_TYPE (n2),
14337 lookup_decl (OMP_CLAUSE_DECL (innerc),
14338 taskreg_ctx));
14341 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14343 clauses = gimple_omp_for_clauses (fd->for_stmt);
14344 stmts = NULL;
14345 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14346 if (!gimple_seq_empty_p (stmts))
14348 gimple_seq_add_seq (&stmts, *dlist);
14349 *dlist = stmts;
14351 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14352 vinit = fd->loop.n1;
14353 if (cond_code == EQ_EXPR
14354 && tree_fits_shwi_p (fd->loop.n2)
14355 && ! integer_zerop (fd->loop.n2))
14356 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
14357 else
14358 vinit = unshare_expr (vinit);
14360 /* Initialize the iterator variable, so that threads that don't execute
14361 any iterations don't execute the lastprivate clauses by accident. */
14362 gimplify_assign (fd->loop.v, vinit, body_p);
14367 /* Lower code for an OMP loop directive. */
14369 static void
14370 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14372 tree *rhs_p, block;
14373 struct omp_for_data fd, *fdp = NULL;
14374 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14375 gbind *new_stmt;
14376 gimple_seq omp_for_body, body, dlist;
14377 gimple_seq oacc_head = NULL, oacc_tail = NULL;
14378 size_t i;
14380 push_gimplify_context ();
14382 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
14384 block = make_node (BLOCK);
14385 new_stmt = gimple_build_bind (NULL, NULL, block);
14386 /* Replace at gsi right away, so that 'stmt' is no member
14387 of a sequence anymore as we're going to add to a different
14388 one below. */
14389 gsi_replace (gsi_p, new_stmt, true);
14391 /* Move declaration of temporaries in the loop body before we make
14392 it go away. */
14393 omp_for_body = gimple_omp_body (stmt);
14394 if (!gimple_seq_empty_p (omp_for_body)
14395 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14397 gbind *inner_bind
14398 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
14399 tree vars = gimple_bind_vars (inner_bind);
14400 gimple_bind_append_vars (new_stmt, vars);
14401 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14402 keep them on the inner_bind and it's block. */
14403 gimple_bind_set_vars (inner_bind, NULL_TREE);
14404 if (gimple_bind_block (inner_bind))
14405 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
14408 if (gimple_omp_for_combined_into_p (stmt))
14410 extract_omp_for_data (stmt, &fd, NULL);
14411 fdp = &fd;
14413 /* We need two temporaries with fd.loop.v type (istart/iend)
14414 and then (fd.collapse - 1) temporaries with the same
14415 type for count2 ... countN-1 vars if not constant. */
14416 size_t count = 2;
14417 tree type = fd.iter_type;
14418 if (fd.collapse > 1
14419 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14420 count += fd.collapse - 1;
14421 bool taskreg_for
14422 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14423 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
14424 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14425 tree clauses = *pc;
14426 if (taskreg_for)
14427 outerc
14428 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
14429 OMP_CLAUSE__LOOPTEMP_);
14430 for (i = 0; i < count; i++)
14432 tree temp;
14433 if (taskreg_for)
14435 gcc_assert (outerc);
14436 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14437 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14438 OMP_CLAUSE__LOOPTEMP_);
14440 else
14442 temp = create_tmp_var (type);
14443 insert_decl_map (&ctx->outer->cb, temp, temp);
14445 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14446 OMP_CLAUSE_DECL (*pc) = temp;
14447 pc = &OMP_CLAUSE_CHAIN (*pc);
14449 *pc = clauses;
14452 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
14453 dlist = NULL;
14454 body = NULL;
14455 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14456 fdp);
14457 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
14459 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14461 /* Lower the header expressions. At this point, we can assume that
14462 the header is of the form:
14464 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14466 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14467 using the .omp_data_s mapping, if needed. */
14468 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
14470 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
14471 if (!is_gimple_min_invariant (*rhs_p))
14472 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14474 rhs_p = gimple_omp_for_final_ptr (stmt, i);
14475 if (!is_gimple_min_invariant (*rhs_p))
14476 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14478 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
14479 if (!is_gimple_min_invariant (*rhs_p))
14480 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14483 /* Once lowered, extract the bounds and clauses. */
14484 extract_omp_for_data (stmt, &fd, NULL);
14486 if (is_gimple_omp_oacc (ctx->stmt)
14487 && !ctx_in_oacc_kernels_region (ctx))
14488 lower_oacc_head_tail (gimple_location (stmt),
14489 gimple_omp_for_clauses (stmt),
14490 &oacc_head, &oacc_tail, ctx);
14492 /* Add OpenACC partitioning and reduction markers just before the loop */
14493 if (oacc_head)
14494 gimple_seq_add_seq (&body, oacc_head);
14496 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
14498 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14499 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14500 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14501 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14503 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14504 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14505 OMP_CLAUSE_LINEAR_STEP (c)
14506 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14507 ctx);
14510 gimple_seq_add_stmt (&body, stmt);
14511 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
14513 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14514 fd.loop.v));
14516 /* After the loop, add exit clauses. */
14517 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
14519 if (ctx->cancellable)
14520 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14522 gimple_seq_add_seq (&body, dlist);
14524 body = maybe_catch_exception (body);
14526 /* Region exit marker goes at the end of the loop body. */
14527 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
14528 maybe_add_implicit_barrier_cancel (ctx, &body);
14530 /* Add OpenACC joining and reduction markers just after the loop. */
14531 if (oacc_tail)
14532 gimple_seq_add_seq (&body, oacc_tail);
14534 pop_gimplify_context (new_stmt);
14536 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14537 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
14538 if (BLOCK_VARS (block))
14539 TREE_USED (block) = 1;
14541 gimple_bind_set_body (new_stmt, body);
14542 gimple_omp_set_body (stmt, NULL);
14543 gimple_omp_for_set_pre_body (stmt, NULL);
14546 /* Callback for walk_stmts. Check if the current statement only contains
14547 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
14549 static tree
14550 check_combined_parallel (gimple_stmt_iterator *gsi_p,
14551 bool *handled_ops_p,
14552 struct walk_stmt_info *wi)
14554 int *info = (int *) wi->info;
14555 gimple *stmt = gsi_stmt (*gsi_p);
14557 *handled_ops_p = true;
14558 switch (gimple_code (stmt))
14560 WALK_SUBSTMTS;
14562 case GIMPLE_OMP_FOR:
14563 case GIMPLE_OMP_SECTIONS:
14564 *info = *info == 0 ? 1 : -1;
14565 break;
14566 default:
14567 *info = -1;
14568 break;
14570 return NULL;
14573 struct omp_taskcopy_context
14575 /* This field must be at the beginning, as we do "inheritance": Some
14576 callback functions for tree-inline.c (e.g., omp_copy_decl)
14577 receive a copy_body_data pointer that is up-casted to an
14578 omp_context pointer. */
14579 copy_body_data cb;
14580 omp_context *ctx;
14583 static tree
14584 task_copyfn_copy_decl (tree var, copy_body_data *cb)
14586 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14588 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
14589 return create_tmp_var (TREE_TYPE (var));
14591 return var;
14594 static tree
14595 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14597 tree name, new_fields = NULL, type, f;
14599 type = lang_hooks.types.make_type (RECORD_TYPE);
14600 name = DECL_NAME (TYPE_NAME (orig_type));
14601 name = build_decl (gimple_location (tcctx->ctx->stmt),
14602 TYPE_DECL, name, type);
14603 TYPE_NAME (type) = name;
14605 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14607 tree new_f = copy_node (f);
14608 DECL_CONTEXT (new_f) = type;
14609 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14610 TREE_CHAIN (new_f) = new_fields;
14611 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14612 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14613 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14614 &tcctx->cb, NULL);
14615 new_fields = new_f;
14616 tcctx->cb.decl_map->put (f, new_f);
14618 TYPE_FIELDS (type) = nreverse (new_fields);
14619 layout_type (type);
14620 return type;
14623 /* Create task copyfn. */
14625 static void
14626 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
14628 struct function *child_cfun;
14629 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14630 tree record_type, srecord_type, bind, list;
14631 bool record_needs_remap = false, srecord_needs_remap = false;
14632 splay_tree_node n;
14633 struct omp_taskcopy_context tcctx;
14634 location_t loc = gimple_location (task_stmt);
14636 child_fn = gimple_omp_task_copy_fn (task_stmt);
14637 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14638 gcc_assert (child_cfun->cfg == NULL);
14639 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14641 /* Reset DECL_CONTEXT on function arguments. */
14642 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
14643 DECL_CONTEXT (t) = child_fn;
14645 /* Populate the function. */
14646 push_gimplify_context ();
14647 push_cfun (child_cfun);
14649 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14650 TREE_SIDE_EFFECTS (bind) = 1;
14651 list = NULL;
14652 DECL_SAVED_TREE (child_fn) = bind;
14653 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
14655 /* Remap src and dst argument types if needed. */
14656 record_type = ctx->record_type;
14657 srecord_type = ctx->srecord_type;
14658 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
14659 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14661 record_needs_remap = true;
14662 break;
14664 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
14665 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14667 srecord_needs_remap = true;
14668 break;
14671 if (record_needs_remap || srecord_needs_remap)
14673 memset (&tcctx, '\0', sizeof (tcctx));
14674 tcctx.cb.src_fn = ctx->cb.src_fn;
14675 tcctx.cb.dst_fn = child_fn;
14676 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
14677 gcc_checking_assert (tcctx.cb.src_node);
14678 tcctx.cb.dst_node = tcctx.cb.src_node;
14679 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14680 tcctx.cb.copy_decl = task_copyfn_copy_decl;
14681 tcctx.cb.eh_lp_nr = 0;
14682 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
14683 tcctx.cb.decl_map = new hash_map<tree, tree>;
14684 tcctx.ctx = ctx;
14686 if (record_needs_remap)
14687 record_type = task_copyfn_remap_type (&tcctx, record_type);
14688 if (srecord_needs_remap)
14689 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14691 else
14692 tcctx.cb.decl_map = NULL;
14694 arg = DECL_ARGUMENTS (child_fn);
14695 TREE_TYPE (arg) = build_pointer_type (record_type);
14696 sarg = DECL_CHAIN (arg);
14697 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14699 /* First pass: initialize temporaries used in record_type and srecord_type
14700 sizes and field offsets. */
14701 if (tcctx.cb.decl_map)
14702 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14703 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14705 tree *p;
14707 decl = OMP_CLAUSE_DECL (c);
14708 p = tcctx.cb.decl_map->get (decl);
14709 if (p == NULL)
14710 continue;
14711 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14712 sf = (tree) n->value;
14713 sf = *tcctx.cb.decl_map->get (sf);
14714 src = build_simple_mem_ref_loc (loc, sarg);
14715 src = omp_build_component_ref (src, sf);
14716 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
14717 append_to_statement_list (t, &list);
14720 /* Second pass: copy shared var pointers and copy construct non-VLA
14721 firstprivate vars. */
14722 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14723 switch (OMP_CLAUSE_CODE (c))
14725 splay_tree_key key;
14726 case OMP_CLAUSE_SHARED:
14727 decl = OMP_CLAUSE_DECL (c);
14728 key = (splay_tree_key) decl;
14729 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14730 key = (splay_tree_key) &DECL_UID (decl);
14731 n = splay_tree_lookup (ctx->field_map, key);
14732 if (n == NULL)
14733 break;
14734 f = (tree) n->value;
14735 if (tcctx.cb.decl_map)
14736 f = *tcctx.cb.decl_map->get (f);
14737 n = splay_tree_lookup (ctx->sfield_map, key);
14738 sf = (tree) n->value;
14739 if (tcctx.cb.decl_map)
14740 sf = *tcctx.cb.decl_map->get (sf);
14741 src = build_simple_mem_ref_loc (loc, sarg);
14742 src = omp_build_component_ref (src, sf);
14743 dst = build_simple_mem_ref_loc (loc, arg);
14744 dst = omp_build_component_ref (dst, f);
14745 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14746 append_to_statement_list (t, &list);
14747 break;
14748 case OMP_CLAUSE_FIRSTPRIVATE:
14749 decl = OMP_CLAUSE_DECL (c);
14750 if (is_variable_sized (decl))
14751 break;
14752 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14753 if (n == NULL)
14754 break;
14755 f = (tree) n->value;
14756 if (tcctx.cb.decl_map)
14757 f = *tcctx.cb.decl_map->get (f);
14758 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14759 if (n != NULL)
14761 sf = (tree) n->value;
14762 if (tcctx.cb.decl_map)
14763 sf = *tcctx.cb.decl_map->get (sf);
14764 src = build_simple_mem_ref_loc (loc, sarg);
14765 src = omp_build_component_ref (src, sf);
14766 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
14767 src = build_simple_mem_ref_loc (loc, src);
14769 else
14770 src = decl;
14771 dst = build_simple_mem_ref_loc (loc, arg);
14772 dst = omp_build_component_ref (dst, f);
14773 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14774 append_to_statement_list (t, &list);
14775 break;
14776 case OMP_CLAUSE_PRIVATE:
14777 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14778 break;
14779 decl = OMP_CLAUSE_DECL (c);
14780 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14781 f = (tree) n->value;
14782 if (tcctx.cb.decl_map)
14783 f = *tcctx.cb.decl_map->get (f);
14784 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14785 if (n != NULL)
14787 sf = (tree) n->value;
14788 if (tcctx.cb.decl_map)
14789 sf = *tcctx.cb.decl_map->get (sf);
14790 src = build_simple_mem_ref_loc (loc, sarg);
14791 src = omp_build_component_ref (src, sf);
14792 if (use_pointer_for_field (decl, NULL))
14793 src = build_simple_mem_ref_loc (loc, src);
14795 else
14796 src = decl;
14797 dst = build_simple_mem_ref_loc (loc, arg);
14798 dst = omp_build_component_ref (dst, f);
14799 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14800 append_to_statement_list (t, &list);
14801 break;
14802 default:
14803 break;
14806 /* Last pass: handle VLA firstprivates. */
14807 if (tcctx.cb.decl_map)
14808 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14809 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14811 tree ind, ptr, df;
14813 decl = OMP_CLAUSE_DECL (c);
14814 if (!is_variable_sized (decl))
14815 continue;
14816 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14817 if (n == NULL)
14818 continue;
14819 f = (tree) n->value;
14820 f = *tcctx.cb.decl_map->get (f);
14821 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14822 ind = DECL_VALUE_EXPR (decl);
14823 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14824 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14825 n = splay_tree_lookup (ctx->sfield_map,
14826 (splay_tree_key) TREE_OPERAND (ind, 0));
14827 sf = (tree) n->value;
14828 sf = *tcctx.cb.decl_map->get (sf);
14829 src = build_simple_mem_ref_loc (loc, sarg);
14830 src = omp_build_component_ref (src, sf);
14831 src = build_simple_mem_ref_loc (loc, src);
14832 dst = build_simple_mem_ref_loc (loc, arg);
14833 dst = omp_build_component_ref (dst, f);
14834 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14835 append_to_statement_list (t, &list);
14836 n = splay_tree_lookup (ctx->field_map,
14837 (splay_tree_key) TREE_OPERAND (ind, 0));
14838 df = (tree) n->value;
14839 df = *tcctx.cb.decl_map->get (df);
14840 ptr = build_simple_mem_ref_loc (loc, arg);
14841 ptr = omp_build_component_ref (ptr, df);
14842 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
14843 build_fold_addr_expr_loc (loc, dst));
14844 append_to_statement_list (t, &list);
14847 t = build1 (RETURN_EXPR, void_type_node, NULL);
14848 append_to_statement_list (t, &list);
14850 if (tcctx.cb.decl_map)
14851 delete tcctx.cb.decl_map;
14852 pop_gimplify_context (NULL);
14853 BIND_EXPR_BODY (bind) = list;
14854 pop_cfun ();
14857 static void
14858 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
14860 tree c, clauses;
14861 gimple *g;
14862 size_t n_in = 0, n_out = 0, idx = 2, i;
14864 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
14865 gcc_assert (clauses);
14866 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14867 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14868 switch (OMP_CLAUSE_DEPEND_KIND (c))
14870 case OMP_CLAUSE_DEPEND_IN:
14871 n_in++;
14872 break;
14873 case OMP_CLAUSE_DEPEND_OUT:
14874 case OMP_CLAUSE_DEPEND_INOUT:
14875 n_out++;
14876 break;
14877 case OMP_CLAUSE_DEPEND_SOURCE:
14878 case OMP_CLAUSE_DEPEND_SINK:
14879 /* FALLTHRU */
14880 default:
14881 gcc_unreachable ();
14883 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
14884 tree array = create_tmp_var (type);
14885 TREE_ADDRESSABLE (array) = 1;
14886 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14887 NULL_TREE);
14888 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14889 gimple_seq_add_stmt (iseq, g);
14890 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14891 NULL_TREE);
14892 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14893 gimple_seq_add_stmt (iseq, g);
14894 for (i = 0; i < 2; i++)
14896 if ((i ? n_in : n_out) == 0)
14897 continue;
14898 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14899 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14900 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14902 tree t = OMP_CLAUSE_DECL (c);
14903 t = fold_convert (ptr_type_node, t);
14904 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14905 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14906 NULL_TREE, NULL_TREE);
14907 g = gimple_build_assign (r, t);
14908 gimple_seq_add_stmt (iseq, g);
14911 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14912 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
14913 OMP_CLAUSE_CHAIN (c) = *pclauses;
14914 *pclauses = c;
14915 tree clobber = build_constructor (type, NULL);
14916 TREE_THIS_VOLATILE (clobber) = 1;
14917 g = gimple_build_assign (array, clobber);
14918 gimple_seq_add_stmt (oseq, g);
14921 /* Lower the OpenMP parallel or task directive in the current statement
14922 in GSI_P. CTX holds context information for the directive. */
14924 static void
14925 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14927 tree clauses;
14928 tree child_fn, t;
14929 gimple *stmt = gsi_stmt (*gsi_p);
14930 gbind *par_bind, *bind, *dep_bind = NULL;
14931 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
14932 location_t loc = gimple_location (stmt);
14934 clauses = gimple_omp_taskreg_clauses (stmt);
14935 par_bind
14936 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
14937 par_body = gimple_bind_body (par_bind);
14938 child_fn = ctx->cb.dst_fn;
14939 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14940 && !gimple_omp_parallel_combined_p (stmt))
14942 struct walk_stmt_info wi;
14943 int ws_num = 0;
14945 memset (&wi, 0, sizeof (wi));
14946 wi.info = &ws_num;
14947 wi.val_only = true;
14948 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
14949 if (ws_num == 1)
14950 gimple_omp_parallel_set_combined_p (stmt, true);
14952 gimple_seq dep_ilist = NULL;
14953 gimple_seq dep_olist = NULL;
14954 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14955 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14957 push_gimplify_context ();
14958 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14959 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14960 &dep_ilist, &dep_olist);
14963 if (ctx->srecord_type)
14964 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
14966 push_gimplify_context ();
14968 par_olist = NULL;
14969 par_ilist = NULL;
14970 par_rlist = NULL;
14971 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
14972 lower_omp (&par_body, ctx);
14973 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
14974 lower_reduction_clauses (clauses, &par_rlist, ctx);
14976 /* Declare all the variables created by mapping and the variables
14977 declared in the scope of the parallel body. */
14978 record_vars_into (ctx->block_vars, child_fn);
14979 record_vars_into (gimple_bind_vars (par_bind), child_fn);
14981 if (ctx->record_type)
14983 ctx->sender_decl
14984 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14985 : ctx->record_type, ".omp_data_o");
14986 DECL_NAMELESS (ctx->sender_decl) = 1;
14987 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
14988 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
14991 olist = NULL;
14992 ilist = NULL;
14993 lower_send_clauses (clauses, &ilist, &olist, ctx);
14994 lower_send_shared_vars (&ilist, &olist, ctx);
14996 if (ctx->record_type)
14998 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
14999 TREE_THIS_VOLATILE (clobber) = 1;
15000 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15001 clobber));
15004 /* Once all the expansions are done, sequence all the different
15005 fragments inside gimple_omp_body. */
15007 new_body = NULL;
15009 if (ctx->record_type)
15011 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15012 /* fixup_child_record_type might have changed receiver_decl's type. */
15013 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15014 gimple_seq_add_stmt (&new_body,
15015 gimple_build_assign (ctx->receiver_decl, t));
15018 gimple_seq_add_seq (&new_body, par_ilist);
15019 gimple_seq_add_seq (&new_body, par_body);
15020 gimple_seq_add_seq (&new_body, par_rlist);
15021 if (ctx->cancellable)
15022 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15023 gimple_seq_add_seq (&new_body, par_olist);
15024 new_body = maybe_catch_exception (new_body);
15025 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15026 gimple_seq_add_stmt (&new_body,
15027 gimple_build_omp_continue (integer_zero_node,
15028 integer_zero_node));
15029 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15030 gimple_omp_set_body (stmt, new_body);
15032 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15033 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15034 gimple_bind_add_seq (bind, ilist);
15035 gimple_bind_add_stmt (bind, stmt);
15036 gimple_bind_add_seq (bind, olist);
15038 pop_gimplify_context (NULL);
15040 if (dep_bind)
15042 gimple_bind_add_seq (dep_bind, dep_ilist);
15043 gimple_bind_add_stmt (dep_bind, bind);
15044 gimple_bind_add_seq (dep_bind, dep_olist);
15045 pop_gimplify_context (dep_bind);
15049 /* Lower the GIMPLE_OMP_TARGET in the current statement
15050 in GSI_P. CTX holds context information for the directive. */
15052 static void
15053 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15055 tree clauses;
15056 tree child_fn, t, c;
15057 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15058 gbind *tgt_bind, *bind, *dep_bind = NULL;
15059 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15060 location_t loc = gimple_location (stmt);
15061 bool offloaded, data_region;
15062 unsigned int map_cnt = 0;
15063 bool has_depend = false;
15065 offloaded = is_gimple_omp_offloaded (stmt);
15066 switch (gimple_omp_target_kind (stmt))
15068 case GF_OMP_TARGET_KIND_REGION:
15069 case GF_OMP_TARGET_KIND_UPDATE:
15070 case GF_OMP_TARGET_KIND_ENTER_DATA:
15071 case GF_OMP_TARGET_KIND_EXIT_DATA:
15072 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15073 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15074 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15075 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15076 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15077 data_region = false;
15078 break;
15079 case GF_OMP_TARGET_KIND_DATA:
15080 case GF_OMP_TARGET_KIND_OACC_DATA:
15081 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15082 data_region = true;
15083 break;
15084 default:
15085 gcc_unreachable ();
15088 clauses = gimple_omp_target_clauses (stmt);
15090 gimple_seq dep_ilist = NULL;
15091 gimple_seq dep_olist = NULL;
15092 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15094 push_gimplify_context ();
15095 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15096 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15097 &dep_ilist, &dep_olist);
15098 has_depend = true;
15101 tgt_bind = NULL;
15102 tgt_body = NULL;
15103 if (offloaded)
15105 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15106 tgt_body = gimple_bind_body (tgt_bind);
15108 else if (data_region)
15109 tgt_body = gimple_omp_body (stmt);
15110 child_fn = ctx->cb.dst_fn;
15112 push_gimplify_context ();
15113 fplist = NULL;
15115 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15116 switch (OMP_CLAUSE_CODE (c))
15118 tree var, x;
15120 default:
15121 break;
15122 case OMP_CLAUSE_MAP:
15123 #if CHECKING_P
15124 /* First check what we're prepared to handle in the following. */
15125 switch (OMP_CLAUSE_MAP_KIND (c))
15127 case GOMP_MAP_ALLOC:
15128 case GOMP_MAP_TO:
15129 case GOMP_MAP_FROM:
15130 case GOMP_MAP_TOFROM:
15131 case GOMP_MAP_POINTER:
15132 case GOMP_MAP_TO_PSET:
15133 case GOMP_MAP_FORCE_DEALLOC:
15134 case GOMP_MAP_RELEASE:
15135 case GOMP_MAP_ALWAYS_TO:
15136 case GOMP_MAP_ALWAYS_FROM:
15137 case GOMP_MAP_ALWAYS_TOFROM:
15138 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15139 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15140 case GOMP_MAP_STRUCT:
15141 case GOMP_MAP_ALWAYS_POINTER:
15142 break;
15143 case GOMP_MAP_FORCE_ALLOC:
15144 case GOMP_MAP_FORCE_TO:
15145 case GOMP_MAP_FORCE_FROM:
15146 case GOMP_MAP_FORCE_TOFROM:
15147 case GOMP_MAP_FORCE_PRESENT:
15148 case GOMP_MAP_FORCE_DEVICEPTR:
15149 case GOMP_MAP_DEVICE_RESIDENT:
15150 case GOMP_MAP_LINK:
15151 gcc_assert (is_gimple_omp_oacc (stmt));
15152 break;
15153 default:
15154 gcc_unreachable ();
15156 #endif
15157 /* FALLTHRU */
15158 case OMP_CLAUSE_TO:
15159 case OMP_CLAUSE_FROM:
15160 oacc_firstprivate:
15161 var = OMP_CLAUSE_DECL (c);
15162 if (!DECL_P (var))
15164 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15165 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15166 && (OMP_CLAUSE_MAP_KIND (c)
15167 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15168 map_cnt++;
15169 continue;
15172 if (DECL_SIZE (var)
15173 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15175 tree var2 = DECL_VALUE_EXPR (var);
15176 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15177 var2 = TREE_OPERAND (var2, 0);
15178 gcc_assert (DECL_P (var2));
15179 var = var2;
15182 if (offloaded
15183 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15184 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15185 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15187 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15189 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15190 && varpool_node::get_create (var)->offloadable)
15191 continue;
15193 tree type = build_pointer_type (TREE_TYPE (var));
15194 tree new_var = lookup_decl (var, ctx);
15195 x = create_tmp_var_raw (type, get_name (new_var));
15196 gimple_add_tmp_var (x);
15197 x = build_simple_mem_ref (x);
15198 SET_DECL_VALUE_EXPR (new_var, x);
15199 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15201 continue;
15204 if (!maybe_lookup_field (var, ctx))
15205 continue;
15207 if (offloaded)
15209 x = build_receiver_ref (var, true, ctx);
15210 tree new_var = lookup_decl (var, ctx);
15212 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15213 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15214 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15215 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15216 x = build_simple_mem_ref (x);
15217 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15219 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15220 if (is_reference (new_var))
15222 /* Create a local object to hold the instance
15223 value. */
15224 tree type = TREE_TYPE (TREE_TYPE (new_var));
15225 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15226 tree inst = create_tmp_var (type, id);
15227 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15228 x = build_fold_addr_expr (inst);
15230 gimplify_assign (new_var, x, &fplist);
15232 else if (DECL_P (new_var))
15234 SET_DECL_VALUE_EXPR (new_var, x);
15235 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15237 else
15238 gcc_unreachable ();
15240 map_cnt++;
15241 break;
15243 case OMP_CLAUSE_FIRSTPRIVATE:
15244 if (is_oacc_parallel (ctx))
15245 goto oacc_firstprivate;
15246 map_cnt++;
15247 var = OMP_CLAUSE_DECL (c);
15248 if (!is_reference (var)
15249 && !is_gimple_reg_type (TREE_TYPE (var)))
15251 tree new_var = lookup_decl (var, ctx);
15252 if (is_variable_sized (var))
15254 tree pvar = DECL_VALUE_EXPR (var);
15255 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15256 pvar = TREE_OPERAND (pvar, 0);
15257 gcc_assert (DECL_P (pvar));
15258 tree new_pvar = lookup_decl (pvar, ctx);
15259 x = build_fold_indirect_ref (new_pvar);
15260 TREE_THIS_NOTRAP (x) = 1;
15262 else
15263 x = build_receiver_ref (var, true, ctx);
15264 SET_DECL_VALUE_EXPR (new_var, x);
15265 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15267 break;
15269 case OMP_CLAUSE_PRIVATE:
15270 if (is_gimple_omp_oacc (ctx->stmt))
15271 break;
15272 var = OMP_CLAUSE_DECL (c);
15273 if (is_variable_sized (var))
15275 tree new_var = lookup_decl (var, ctx);
15276 tree pvar = DECL_VALUE_EXPR (var);
15277 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15278 pvar = TREE_OPERAND (pvar, 0);
15279 gcc_assert (DECL_P (pvar));
15280 tree new_pvar = lookup_decl (pvar, ctx);
15281 x = build_fold_indirect_ref (new_pvar);
15282 TREE_THIS_NOTRAP (x) = 1;
15283 SET_DECL_VALUE_EXPR (new_var, x);
15284 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15286 break;
15288 case OMP_CLAUSE_USE_DEVICE_PTR:
15289 case OMP_CLAUSE_IS_DEVICE_PTR:
15290 var = OMP_CLAUSE_DECL (c);
15291 map_cnt++;
15292 if (is_variable_sized (var))
15294 tree new_var = lookup_decl (var, ctx);
15295 tree pvar = DECL_VALUE_EXPR (var);
15296 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15297 pvar = TREE_OPERAND (pvar, 0);
15298 gcc_assert (DECL_P (pvar));
15299 tree new_pvar = lookup_decl (pvar, ctx);
15300 x = build_fold_indirect_ref (new_pvar);
15301 TREE_THIS_NOTRAP (x) = 1;
15302 SET_DECL_VALUE_EXPR (new_var, x);
15303 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15305 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15307 tree new_var = lookup_decl (var, ctx);
15308 tree type = build_pointer_type (TREE_TYPE (var));
15309 x = create_tmp_var_raw (type, get_name (new_var));
15310 gimple_add_tmp_var (x);
15311 x = build_simple_mem_ref (x);
15312 SET_DECL_VALUE_EXPR (new_var, x);
15313 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15315 break;
15318 if (offloaded)
15320 target_nesting_level++;
15321 lower_omp (&tgt_body, ctx);
15322 target_nesting_level--;
15324 else if (data_region)
15325 lower_omp (&tgt_body, ctx);
15327 if (offloaded)
15329 /* Declare all the variables created by mapping and the variables
15330 declared in the scope of the target body. */
15331 record_vars_into (ctx->block_vars, child_fn);
15332 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15335 olist = NULL;
15336 ilist = NULL;
15337 if (ctx->record_type)
15339 ctx->sender_decl
15340 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15341 DECL_NAMELESS (ctx->sender_decl) = 1;
15342 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15343 t = make_tree_vec (3);
15344 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15345 TREE_VEC_ELT (t, 1)
15346 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15347 ".omp_data_sizes");
15348 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15349 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15350 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
15351 tree tkind_type = short_unsigned_type_node;
15352 int talign_shift = 8;
15353 TREE_VEC_ELT (t, 2)
15354 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
15355 ".omp_data_kinds");
15356 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15357 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15358 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15359 gimple_omp_target_set_data_arg (stmt, t);
15361 vec<constructor_elt, va_gc> *vsize;
15362 vec<constructor_elt, va_gc> *vkind;
15363 vec_alloc (vsize, map_cnt);
15364 vec_alloc (vkind, map_cnt);
15365 unsigned int map_idx = 0;
15367 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15368 switch (OMP_CLAUSE_CODE (c))
15370 tree ovar, nc, s, purpose, var, x, type;
15371 unsigned int talign;
15373 default:
15374 break;
15376 case OMP_CLAUSE_MAP:
15377 case OMP_CLAUSE_TO:
15378 case OMP_CLAUSE_FROM:
15379 oacc_firstprivate_map:
15380 nc = c;
15381 ovar = OMP_CLAUSE_DECL (c);
15382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15383 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15384 || (OMP_CLAUSE_MAP_KIND (c)
15385 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
15386 break;
15387 if (!DECL_P (ovar))
15389 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15390 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15392 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15393 == get_base_address (ovar));
15394 nc = OMP_CLAUSE_CHAIN (c);
15395 ovar = OMP_CLAUSE_DECL (nc);
15397 else
15399 tree x = build_sender_ref (ovar, ctx);
15400 tree v
15401 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15402 gimplify_assign (x, v, &ilist);
15403 nc = NULL_TREE;
15406 else
15408 if (DECL_SIZE (ovar)
15409 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15411 tree ovar2 = DECL_VALUE_EXPR (ovar);
15412 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15413 ovar2 = TREE_OPERAND (ovar2, 0);
15414 gcc_assert (DECL_P (ovar2));
15415 ovar = ovar2;
15417 if (!maybe_lookup_field (ovar, ctx))
15418 continue;
15421 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
15422 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15423 talign = DECL_ALIGN_UNIT (ovar);
15424 if (nc)
15426 var = lookup_decl_in_outer_ctx (ovar, ctx);
15427 x = build_sender_ref (ovar, ctx);
15429 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15430 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15431 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15432 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
15434 gcc_assert (offloaded);
15435 tree avar
15436 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
15437 mark_addressable (avar);
15438 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
15439 talign = DECL_ALIGN_UNIT (avar);
15440 avar = build_fold_addr_expr (avar);
15441 gimplify_assign (x, avar, &ilist);
15443 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15445 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15446 if (!is_reference (var))
15447 var = build_fold_addr_expr (var);
15448 else
15449 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15450 gimplify_assign (x, var, &ilist);
15452 else if (is_gimple_reg (var))
15454 gcc_assert (offloaded);
15455 tree avar = create_tmp_var (TREE_TYPE (var));
15456 mark_addressable (avar);
15457 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15458 if (GOMP_MAP_COPY_TO_P (map_kind)
15459 || map_kind == GOMP_MAP_POINTER
15460 || map_kind == GOMP_MAP_TO_PSET
15461 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15462 gimplify_assign (avar, var, &ilist);
15463 avar = build_fold_addr_expr (avar);
15464 gimplify_assign (x, avar, &ilist);
15465 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15466 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15467 && !TYPE_READONLY (TREE_TYPE (var)))
15469 x = unshare_expr (x);
15470 x = build_simple_mem_ref (x);
15471 gimplify_assign (var, x, &olist);
15474 else
15476 var = build_fold_addr_expr (var);
15477 gimplify_assign (x, var, &ilist);
15480 s = NULL_TREE;
15481 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15483 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15484 s = TREE_TYPE (ovar);
15485 if (TREE_CODE (s) == REFERENCE_TYPE)
15486 s = TREE_TYPE (s);
15487 s = TYPE_SIZE_UNIT (s);
15489 else
15490 s = OMP_CLAUSE_SIZE (c);
15491 if (s == NULL_TREE)
15492 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15493 s = fold_convert (size_type_node, s);
15494 purpose = size_int (map_idx++);
15495 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15496 if (TREE_CODE (s) != INTEGER_CST)
15497 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15499 unsigned HOST_WIDE_INT tkind, tkind_zero;
15500 switch (OMP_CLAUSE_CODE (c))
15502 case OMP_CLAUSE_MAP:
15503 tkind = OMP_CLAUSE_MAP_KIND (c);
15504 tkind_zero = tkind;
15505 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15506 switch (tkind)
15508 case GOMP_MAP_ALLOC:
15509 case GOMP_MAP_TO:
15510 case GOMP_MAP_FROM:
15511 case GOMP_MAP_TOFROM:
15512 case GOMP_MAP_ALWAYS_TO:
15513 case GOMP_MAP_ALWAYS_FROM:
15514 case GOMP_MAP_ALWAYS_TOFROM:
15515 case GOMP_MAP_RELEASE:
15516 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15517 break;
15518 case GOMP_MAP_DELETE:
15519 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15520 default:
15521 break;
15523 if (tkind_zero != tkind)
15525 if (integer_zerop (s))
15526 tkind = tkind_zero;
15527 else if (integer_nonzerop (s))
15528 tkind_zero = tkind;
15530 break;
15531 case OMP_CLAUSE_FIRSTPRIVATE:
15532 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15533 tkind = GOMP_MAP_TO;
15534 tkind_zero = tkind;
15535 break;
15536 case OMP_CLAUSE_TO:
15537 tkind = GOMP_MAP_TO;
15538 tkind_zero = tkind;
15539 break;
15540 case OMP_CLAUSE_FROM:
15541 tkind = GOMP_MAP_FROM;
15542 tkind_zero = tkind;
15543 break;
15544 default:
15545 gcc_unreachable ();
15547 gcc_checking_assert (tkind
15548 < (HOST_WIDE_INT_C (1U) << talign_shift));
15549 gcc_checking_assert (tkind_zero
15550 < (HOST_WIDE_INT_C (1U) << talign_shift));
15551 talign = ceil_log2 (talign);
15552 tkind |= talign << talign_shift;
15553 tkind_zero |= talign << talign_shift;
15554 gcc_checking_assert (tkind
15555 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15556 gcc_checking_assert (tkind_zero
15557 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15558 if (tkind == tkind_zero)
15559 x = build_int_cstu (tkind_type, tkind);
15560 else
15562 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15563 x = build3 (COND_EXPR, tkind_type,
15564 fold_build2 (EQ_EXPR, boolean_type_node,
15565 unshare_expr (s), size_zero_node),
15566 build_int_cstu (tkind_type, tkind_zero),
15567 build_int_cstu (tkind_type, tkind));
15569 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
15570 if (nc && nc != c)
15571 c = nc;
15572 break;
15574 case OMP_CLAUSE_FIRSTPRIVATE:
15575 if (is_oacc_parallel (ctx))
15576 goto oacc_firstprivate_map;
15577 ovar = OMP_CLAUSE_DECL (c);
15578 if (is_reference (ovar))
15579 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15580 else
15581 talign = DECL_ALIGN_UNIT (ovar);
15582 var = lookup_decl_in_outer_ctx (ovar, ctx);
15583 x = build_sender_ref (ovar, ctx);
15584 tkind = GOMP_MAP_FIRSTPRIVATE;
15585 type = TREE_TYPE (ovar);
15586 if (is_reference (ovar))
15587 type = TREE_TYPE (type);
15588 bool use_firstprivate_int, force_addr;
15589 use_firstprivate_int = false;
15590 force_addr = false;
15591 if ((INTEGRAL_TYPE_P (type)
15592 && TYPE_PRECISION (type) <= POINTER_SIZE)
15593 || TREE_CODE (type) == POINTER_TYPE)
15594 use_firstprivate_int = true;
15595 if (has_depend)
15597 if (is_reference (var))
15598 use_firstprivate_int = false;
15599 else if (is_gimple_reg (var))
15601 if (DECL_HAS_VALUE_EXPR_P (var))
15603 tree v = get_base_address (var);
15604 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15606 use_firstprivate_int = false;
15607 force_addr = true;
15609 else
15610 switch (TREE_CODE (v))
15612 case INDIRECT_REF:
15613 case MEM_REF:
15614 use_firstprivate_int = false;
15615 force_addr = true;
15616 break;
15617 default:
15618 break;
15622 else
15623 use_firstprivate_int = false;
15625 if (use_firstprivate_int)
15627 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15628 tree t = var;
15629 if (is_reference (var))
15630 t = build_simple_mem_ref (var);
15631 if (TREE_CODE (type) != POINTER_TYPE)
15632 t = fold_convert (pointer_sized_int_node, t);
15633 t = fold_convert (TREE_TYPE (x), t);
15634 gimplify_assign (x, t, &ilist);
15636 else if (is_reference (var))
15637 gimplify_assign (x, var, &ilist);
15638 else if (!force_addr && is_gimple_reg (var))
15640 tree avar = create_tmp_var (TREE_TYPE (var));
15641 mark_addressable (avar);
15642 gimplify_assign (avar, var, &ilist);
15643 avar = build_fold_addr_expr (avar);
15644 gimplify_assign (x, avar, &ilist);
15646 else
15648 var = build_fold_addr_expr (var);
15649 gimplify_assign (x, var, &ilist);
15651 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15652 s = size_int (0);
15653 else if (is_reference (var))
15654 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15655 else
15656 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15657 s = fold_convert (size_type_node, s);
15658 purpose = size_int (map_idx++);
15659 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15660 if (TREE_CODE (s) != INTEGER_CST)
15661 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15663 gcc_checking_assert (tkind
15664 < (HOST_WIDE_INT_C (1U) << talign_shift));
15665 talign = ceil_log2 (talign);
15666 tkind |= talign << talign_shift;
15667 gcc_checking_assert (tkind
15668 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15669 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15670 build_int_cstu (tkind_type, tkind));
15671 break;
15673 case OMP_CLAUSE_USE_DEVICE_PTR:
15674 case OMP_CLAUSE_IS_DEVICE_PTR:
15675 ovar = OMP_CLAUSE_DECL (c);
15676 var = lookup_decl_in_outer_ctx (ovar, ctx);
15677 x = build_sender_ref (ovar, ctx);
15678 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15679 tkind = GOMP_MAP_USE_DEVICE_PTR;
15680 else
15681 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15682 type = TREE_TYPE (ovar);
15683 if (TREE_CODE (type) == ARRAY_TYPE)
15684 var = build_fold_addr_expr (var);
15685 else
15687 if (is_reference (ovar))
15689 type = TREE_TYPE (type);
15690 if (TREE_CODE (type) != ARRAY_TYPE)
15691 var = build_simple_mem_ref (var);
15692 var = fold_convert (TREE_TYPE (x), var);
15695 gimplify_assign (x, var, &ilist);
15696 s = size_int (0);
15697 purpose = size_int (map_idx++);
15698 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15699 gcc_checking_assert (tkind
15700 < (HOST_WIDE_INT_C (1U) << talign_shift));
15701 gcc_checking_assert (tkind
15702 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15703 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15704 build_int_cstu (tkind_type, tkind));
15705 break;
15708 gcc_assert (map_idx == map_cnt);
15710 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15711 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15712 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15713 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
15714 for (int i = 1; i <= 2; i++)
15715 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15717 gimple_seq initlist = NULL;
15718 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15719 TREE_VEC_ELT (t, i)),
15720 &initlist, true, NULL_TREE);
15721 gimple_seq_add_seq (&ilist, initlist);
15723 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15724 NULL);
15725 TREE_THIS_VOLATILE (clobber) = 1;
15726 gimple_seq_add_stmt (&olist,
15727 gimple_build_assign (TREE_VEC_ELT (t, i),
15728 clobber));
15731 tree clobber = build_constructor (ctx->record_type, NULL);
15732 TREE_THIS_VOLATILE (clobber) = 1;
15733 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15734 clobber));
15737 /* Once all the expansions are done, sequence all the different
15738 fragments inside gimple_omp_body. */
15740 new_body = NULL;
15742 if (offloaded
15743 && ctx->record_type)
15745 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15746 /* fixup_child_record_type might have changed receiver_decl's type. */
15747 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15748 gimple_seq_add_stmt (&new_body,
15749 gimple_build_assign (ctx->receiver_decl, t));
15751 gimple_seq_add_seq (&new_body, fplist);
15753 if (offloaded || data_region)
15755 tree prev = NULL_TREE;
15756 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15757 switch (OMP_CLAUSE_CODE (c))
15759 tree var, x;
15760 default:
15761 break;
15762 case OMP_CLAUSE_FIRSTPRIVATE:
15763 if (is_gimple_omp_oacc (ctx->stmt))
15764 break;
15765 var = OMP_CLAUSE_DECL (c);
15766 if (is_reference (var)
15767 || is_gimple_reg_type (TREE_TYPE (var)))
15769 tree new_var = lookup_decl (var, ctx);
15770 tree type;
15771 type = TREE_TYPE (var);
15772 if (is_reference (var))
15773 type = TREE_TYPE (type);
15774 bool use_firstprivate_int;
15775 use_firstprivate_int = false;
15776 if ((INTEGRAL_TYPE_P (type)
15777 && TYPE_PRECISION (type) <= POINTER_SIZE)
15778 || TREE_CODE (type) == POINTER_TYPE)
15779 use_firstprivate_int = true;
15780 if (has_depend)
15782 tree v = lookup_decl_in_outer_ctx (var, ctx);
15783 if (is_reference (v))
15784 use_firstprivate_int = false;
15785 else if (is_gimple_reg (v))
15787 if (DECL_HAS_VALUE_EXPR_P (v))
15789 v = get_base_address (v);
15790 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15791 use_firstprivate_int = false;
15792 else
15793 switch (TREE_CODE (v))
15795 case INDIRECT_REF:
15796 case MEM_REF:
15797 use_firstprivate_int = false;
15798 break;
15799 default:
15800 break;
15804 else
15805 use_firstprivate_int = false;
15807 if (use_firstprivate_int)
15809 x = build_receiver_ref (var, false, ctx);
15810 if (TREE_CODE (type) != POINTER_TYPE)
15811 x = fold_convert (pointer_sized_int_node, x);
15812 x = fold_convert (type, x);
15813 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15814 fb_rvalue);
15815 if (is_reference (var))
15817 tree v = create_tmp_var_raw (type, get_name (var));
15818 gimple_add_tmp_var (v);
15819 TREE_ADDRESSABLE (v) = 1;
15820 gimple_seq_add_stmt (&new_body,
15821 gimple_build_assign (v, x));
15822 x = build_fold_addr_expr (v);
15824 gimple_seq_add_stmt (&new_body,
15825 gimple_build_assign (new_var, x));
15827 else
15829 x = build_receiver_ref (var, !is_reference (var), ctx);
15830 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15831 fb_rvalue);
15832 gimple_seq_add_stmt (&new_body,
15833 gimple_build_assign (new_var, x));
15836 else if (is_variable_sized (var))
15838 tree pvar = DECL_VALUE_EXPR (var);
15839 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15840 pvar = TREE_OPERAND (pvar, 0);
15841 gcc_assert (DECL_P (pvar));
15842 tree new_var = lookup_decl (pvar, ctx);
15843 x = build_receiver_ref (var, false, ctx);
15844 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15845 gimple_seq_add_stmt (&new_body,
15846 gimple_build_assign (new_var, x));
15848 break;
15849 case OMP_CLAUSE_PRIVATE:
15850 if (is_gimple_omp_oacc (ctx->stmt))
15851 break;
15852 var = OMP_CLAUSE_DECL (c);
15853 if (is_reference (var))
15855 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15856 tree new_var = lookup_decl (var, ctx);
15857 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15858 if (TREE_CONSTANT (x))
15860 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15861 get_name (var));
15862 gimple_add_tmp_var (x);
15863 TREE_ADDRESSABLE (x) = 1;
15864 x = build_fold_addr_expr_loc (clause_loc, x);
15866 else
15868 tree atmp
15869 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15870 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15871 tree al = size_int (TYPE_ALIGN (rtype));
15872 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15875 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15876 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15877 gimple_seq_add_stmt (&new_body,
15878 gimple_build_assign (new_var, x));
15880 break;
15881 case OMP_CLAUSE_USE_DEVICE_PTR:
15882 case OMP_CLAUSE_IS_DEVICE_PTR:
15883 var = OMP_CLAUSE_DECL (c);
15884 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15885 x = build_sender_ref (var, ctx);
15886 else
15887 x = build_receiver_ref (var, false, ctx);
15888 if (is_variable_sized (var))
15890 tree pvar = DECL_VALUE_EXPR (var);
15891 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15892 pvar = TREE_OPERAND (pvar, 0);
15893 gcc_assert (DECL_P (pvar));
15894 tree new_var = lookup_decl (pvar, ctx);
15895 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15896 gimple_seq_add_stmt (&new_body,
15897 gimple_build_assign (new_var, x));
15899 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15901 tree new_var = lookup_decl (var, ctx);
15902 new_var = DECL_VALUE_EXPR (new_var);
15903 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15904 new_var = TREE_OPERAND (new_var, 0);
15905 gcc_assert (DECL_P (new_var));
15906 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15907 gimple_seq_add_stmt (&new_body,
15908 gimple_build_assign (new_var, x));
15910 else
15912 tree type = TREE_TYPE (var);
15913 tree new_var = lookup_decl (var, ctx);
15914 if (is_reference (var))
15916 type = TREE_TYPE (type);
15917 if (TREE_CODE (type) != ARRAY_TYPE)
15919 tree v = create_tmp_var_raw (type, get_name (var));
15920 gimple_add_tmp_var (v);
15921 TREE_ADDRESSABLE (v) = 1;
15922 x = fold_convert (type, x);
15923 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15924 fb_rvalue);
15925 gimple_seq_add_stmt (&new_body,
15926 gimple_build_assign (v, x));
15927 x = build_fold_addr_expr (v);
15930 x = fold_convert (TREE_TYPE (new_var), x);
15931 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15932 gimple_seq_add_stmt (&new_body,
15933 gimple_build_assign (new_var, x));
15935 break;
15937 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
15938 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15939 are already handled. */
15940 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15941 switch (OMP_CLAUSE_CODE (c))
15943 tree var;
15944 default:
15945 break;
15946 case OMP_CLAUSE_MAP:
15947 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15948 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15950 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15951 HOST_WIDE_INT offset = 0;
15952 gcc_assert (prev);
15953 var = OMP_CLAUSE_DECL (c);
15954 if (DECL_P (var)
15955 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15956 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15957 ctx))
15958 && varpool_node::get_create (var)->offloadable)
15959 break;
15960 if (TREE_CODE (var) == INDIRECT_REF
15961 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15962 var = TREE_OPERAND (var, 0);
15963 if (TREE_CODE (var) == COMPONENT_REF)
15965 var = get_addr_base_and_unit_offset (var, &offset);
15966 gcc_assert (var != NULL_TREE && DECL_P (var));
15968 else if (DECL_SIZE (var)
15969 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15971 tree var2 = DECL_VALUE_EXPR (var);
15972 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15973 var2 = TREE_OPERAND (var2, 0);
15974 gcc_assert (DECL_P (var2));
15975 var = var2;
15977 tree new_var = lookup_decl (var, ctx), x;
15978 tree type = TREE_TYPE (new_var);
15979 bool is_ref;
15980 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15981 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15982 == COMPONENT_REF))
15984 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15985 is_ref = true;
15986 new_var = build2 (MEM_REF, type,
15987 build_fold_addr_expr (new_var),
15988 build_int_cst (build_pointer_type (type),
15989 offset));
15991 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
15993 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
15994 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
15995 new_var = build2 (MEM_REF, type,
15996 build_fold_addr_expr (new_var),
15997 build_int_cst (build_pointer_type (type),
15998 offset));
16000 else
16001 is_ref = is_reference (var);
16002 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16003 is_ref = false;
16004 bool ref_to_array = false;
16005 if (is_ref)
16007 type = TREE_TYPE (type);
16008 if (TREE_CODE (type) == ARRAY_TYPE)
16010 type = build_pointer_type (type);
16011 ref_to_array = true;
16014 else if (TREE_CODE (type) == ARRAY_TYPE)
16016 tree decl2 = DECL_VALUE_EXPR (new_var);
16017 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16018 decl2 = TREE_OPERAND (decl2, 0);
16019 gcc_assert (DECL_P (decl2));
16020 new_var = decl2;
16021 type = TREE_TYPE (new_var);
16023 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16024 x = fold_convert_loc (clause_loc, type, x);
16025 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16027 tree bias = OMP_CLAUSE_SIZE (c);
16028 if (DECL_P (bias))
16029 bias = lookup_decl (bias, ctx);
16030 bias = fold_convert_loc (clause_loc, sizetype, bias);
16031 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16032 bias);
16033 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16034 TREE_TYPE (x), x, bias);
16036 if (ref_to_array)
16037 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16038 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16039 if (is_ref && !ref_to_array)
16041 tree t = create_tmp_var_raw (type, get_name (var));
16042 gimple_add_tmp_var (t);
16043 TREE_ADDRESSABLE (t) = 1;
16044 gimple_seq_add_stmt (&new_body,
16045 gimple_build_assign (t, x));
16046 x = build_fold_addr_expr_loc (clause_loc, t);
16048 gimple_seq_add_stmt (&new_body,
16049 gimple_build_assign (new_var, x));
16050 prev = NULL_TREE;
16052 else if (OMP_CLAUSE_CHAIN (c)
16053 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16054 == OMP_CLAUSE_MAP
16055 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16056 == GOMP_MAP_FIRSTPRIVATE_POINTER
16057 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16058 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16059 prev = c;
16060 break;
16061 case OMP_CLAUSE_PRIVATE:
16062 var = OMP_CLAUSE_DECL (c);
16063 if (is_variable_sized (var))
16065 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16066 tree new_var = lookup_decl (var, ctx);
16067 tree pvar = DECL_VALUE_EXPR (var);
16068 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16069 pvar = TREE_OPERAND (pvar, 0);
16070 gcc_assert (DECL_P (pvar));
16071 tree new_pvar = lookup_decl (pvar, ctx);
16072 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16073 tree al = size_int (DECL_ALIGN (var));
16074 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16075 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16076 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16077 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16078 gimple_seq_add_stmt (&new_body,
16079 gimple_build_assign (new_pvar, x));
16081 break;
16084 gimple_seq fork_seq = NULL;
16085 gimple_seq join_seq = NULL;
16087 if (is_oacc_parallel (ctx))
16089 /* If there are reductions on the offloaded region itself, treat
16090 them as a dummy GANG loop. */
16091 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16093 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16094 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16097 gimple_seq_add_seq (&new_body, fork_seq);
16098 gimple_seq_add_seq (&new_body, tgt_body);
16099 gimple_seq_add_seq (&new_body, join_seq);
16101 if (offloaded)
16102 new_body = maybe_catch_exception (new_body);
16104 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16105 gimple_omp_set_body (stmt, new_body);
16108 bind = gimple_build_bind (NULL, NULL,
16109 tgt_bind ? gimple_bind_block (tgt_bind)
16110 : NULL_TREE);
16111 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16112 gimple_bind_add_seq (bind, ilist);
16113 gimple_bind_add_stmt (bind, stmt);
16114 gimple_bind_add_seq (bind, olist);
16116 pop_gimplify_context (NULL);
16118 if (dep_bind)
16120 gimple_bind_add_seq (dep_bind, dep_ilist);
16121 gimple_bind_add_stmt (dep_bind, bind);
16122 gimple_bind_add_seq (dep_bind, dep_olist);
16123 pop_gimplify_context (dep_bind);
16127 /* Expand code for an OpenMP teams directive. */
16129 static void
16130 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16132 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16133 push_gimplify_context ();
16135 tree block = make_node (BLOCK);
16136 gbind *bind = gimple_build_bind (NULL, NULL, block);
16137 gsi_replace (gsi_p, bind, true);
16138 gimple_seq bind_body = NULL;
16139 gimple_seq dlist = NULL;
16140 gimple_seq olist = NULL;
16142 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16143 OMP_CLAUSE_NUM_TEAMS);
16144 if (num_teams == NULL_TREE)
16145 num_teams = build_int_cst (unsigned_type_node, 0);
16146 else
16148 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16149 num_teams = fold_convert (unsigned_type_node, num_teams);
16150 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16152 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16153 OMP_CLAUSE_THREAD_LIMIT);
16154 if (thread_limit == NULL_TREE)
16155 thread_limit = build_int_cst (unsigned_type_node, 0);
16156 else
16158 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16159 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16160 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16161 fb_rvalue);
16164 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16165 &bind_body, &dlist, ctx, NULL);
16166 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16167 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16168 gimple_seq_add_stmt (&bind_body, teams_stmt);
16170 location_t loc = gimple_location (teams_stmt);
16171 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16172 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16173 gimple_set_location (call, loc);
16174 gimple_seq_add_stmt (&bind_body, call);
16176 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16177 gimple_omp_set_body (teams_stmt, NULL);
16178 gimple_seq_add_seq (&bind_body, olist);
16179 gimple_seq_add_seq (&bind_body, dlist);
16180 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16181 gimple_bind_set_body (bind, bind_body);
16183 pop_gimplify_context (bind);
16185 gimple_bind_append_vars (bind, ctx->block_vars);
16186 BLOCK_VARS (block) = ctx->block_vars;
16187 if (BLOCK_VARS (block))
16188 TREE_USED (block) = 1;
16192 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16193 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16194 of OMP context, but with task_shared_vars set. */
16196 static tree
16197 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16198 void *data)
16200 tree t = *tp;
16202 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16203 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16204 return t;
16206 if (task_shared_vars
16207 && DECL_P (t)
16208 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16209 return t;
16211 /* If a global variable has been privatized, TREE_CONSTANT on
16212 ADDR_EXPR might be wrong. */
16213 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16214 recompute_tree_invariant_for_addr_expr (t);
16216 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16217 return NULL_TREE;
16220 /* Data to be communicated between lower_omp_regimplify_operands and
16221 lower_omp_regimplify_operands_p. */
16223 struct lower_omp_regimplify_operands_data
16225 omp_context *ctx;
16226 vec<tree> *decls;
16229 /* Helper function for lower_omp_regimplify_operands. Find
16230 omp_member_access_dummy_var vars and adjust temporarily their
16231 DECL_VALUE_EXPRs if needed. */
16233 static tree
16234 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16235 void *data)
16237 tree t = omp_member_access_dummy_var (*tp);
16238 if (t)
16240 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16241 lower_omp_regimplify_operands_data *ldata
16242 = (lower_omp_regimplify_operands_data *) wi->info;
16243 tree o = maybe_lookup_decl (t, ldata->ctx);
16244 if (o != t)
16246 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16247 ldata->decls->safe_push (*tp);
16248 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16249 SET_DECL_VALUE_EXPR (*tp, v);
16252 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16253 return NULL_TREE;
16256 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16257 of omp_member_access_dummy_var vars during regimplification. */
16259 static void
16260 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16261 gimple_stmt_iterator *gsi_p)
16263 auto_vec<tree, 10> decls;
16264 if (ctx)
16266 struct walk_stmt_info wi;
16267 memset (&wi, '\0', sizeof (wi));
16268 struct lower_omp_regimplify_operands_data data;
16269 data.ctx = ctx;
16270 data.decls = &decls;
16271 wi.info = &data;
16272 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16274 gimple_regimplify_operands (stmt, gsi_p);
16275 while (!decls.is_empty ())
16277 tree t = decls.pop ();
16278 tree v = decls.pop ();
16279 SET_DECL_VALUE_EXPR (t, v);
16283 static void
16284 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16286 gimple *stmt = gsi_stmt (*gsi_p);
16287 struct walk_stmt_info wi;
16288 gcall *call_stmt;
16290 if (gimple_has_location (stmt))
16291 input_location = gimple_location (stmt);
16293 if (task_shared_vars)
16294 memset (&wi, '\0', sizeof (wi));
16296 /* If we have issued syntax errors, avoid doing any heavy lifting.
16297 Just replace the OMP directives with a NOP to avoid
16298 confusing RTL expansion. */
16299 if (seen_error () && is_gimple_omp (stmt))
16301 gsi_replace (gsi_p, gimple_build_nop (), true);
16302 return;
16305 switch (gimple_code (stmt))
16307 case GIMPLE_COND:
16309 gcond *cond_stmt = as_a <gcond *> (stmt);
16310 if ((ctx || task_shared_vars)
16311 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16312 lower_omp_regimplify_p,
16313 ctx ? NULL : &wi, NULL)
16314 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16315 lower_omp_regimplify_p,
16316 ctx ? NULL : &wi, NULL)))
16317 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16319 break;
16320 case GIMPLE_CATCH:
16321 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16322 break;
16323 case GIMPLE_EH_FILTER:
16324 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16325 break;
16326 case GIMPLE_TRY:
16327 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16328 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16329 break;
16330 case GIMPLE_TRANSACTION:
16331 lower_omp (gimple_transaction_body_ptr (
16332 as_a <gtransaction *> (stmt)),
16333 ctx);
16334 break;
16335 case GIMPLE_BIND:
16336 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
16337 break;
16338 case GIMPLE_OMP_PARALLEL:
16339 case GIMPLE_OMP_TASK:
16340 ctx = maybe_lookup_ctx (stmt);
16341 gcc_assert (ctx);
16342 if (ctx->cancellable)
16343 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16344 lower_omp_taskreg (gsi_p, ctx);
16345 break;
16346 case GIMPLE_OMP_FOR:
16347 ctx = maybe_lookup_ctx (stmt);
16348 gcc_assert (ctx);
16349 if (ctx->cancellable)
16350 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16351 lower_omp_for (gsi_p, ctx);
16352 break;
16353 case GIMPLE_OMP_SECTIONS:
16354 ctx = maybe_lookup_ctx (stmt);
16355 gcc_assert (ctx);
16356 if (ctx->cancellable)
16357 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16358 lower_omp_sections (gsi_p, ctx);
16359 break;
16360 case GIMPLE_OMP_SINGLE:
16361 ctx = maybe_lookup_ctx (stmt);
16362 gcc_assert (ctx);
16363 lower_omp_single (gsi_p, ctx);
16364 break;
16365 case GIMPLE_OMP_MASTER:
16366 ctx = maybe_lookup_ctx (stmt);
16367 gcc_assert (ctx);
16368 lower_omp_master (gsi_p, ctx);
16369 break;
16370 case GIMPLE_OMP_TASKGROUP:
16371 ctx = maybe_lookup_ctx (stmt);
16372 gcc_assert (ctx);
16373 lower_omp_taskgroup (gsi_p, ctx);
16374 break;
16375 case GIMPLE_OMP_ORDERED:
16376 ctx = maybe_lookup_ctx (stmt);
16377 gcc_assert (ctx);
16378 lower_omp_ordered (gsi_p, ctx);
16379 break;
16380 case GIMPLE_OMP_CRITICAL:
16381 ctx = maybe_lookup_ctx (stmt);
16382 gcc_assert (ctx);
16383 lower_omp_critical (gsi_p, ctx);
16384 break;
16385 case GIMPLE_OMP_ATOMIC_LOAD:
16386 if ((ctx || task_shared_vars)
16387 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16388 as_a <gomp_atomic_load *> (stmt)),
16389 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
16390 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16391 break;
16392 case GIMPLE_OMP_TARGET:
16393 ctx = maybe_lookup_ctx (stmt);
16394 gcc_assert (ctx);
16395 lower_omp_target (gsi_p, ctx);
16396 break;
16397 case GIMPLE_OMP_TEAMS:
16398 ctx = maybe_lookup_ctx (stmt);
16399 gcc_assert (ctx);
16400 lower_omp_teams (gsi_p, ctx);
16401 break;
16402 case GIMPLE_CALL:
16403 tree fndecl;
16404 call_stmt = as_a <gcall *> (stmt);
16405 fndecl = gimple_call_fndecl (call_stmt);
16406 if (fndecl
16407 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16408 switch (DECL_FUNCTION_CODE (fndecl))
16410 case BUILT_IN_GOMP_BARRIER:
16411 if (ctx == NULL)
16412 break;
16413 /* FALLTHRU */
16414 case BUILT_IN_GOMP_CANCEL:
16415 case BUILT_IN_GOMP_CANCELLATION_POINT:
16416 omp_context *cctx;
16417 cctx = ctx;
16418 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16419 cctx = cctx->outer;
16420 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
16421 if (!cctx->cancellable)
16423 if (DECL_FUNCTION_CODE (fndecl)
16424 == BUILT_IN_GOMP_CANCELLATION_POINT)
16426 stmt = gimple_build_nop ();
16427 gsi_replace (gsi_p, stmt, false);
16429 break;
16431 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16433 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
16434 gimple_call_set_fndecl (call_stmt, fndecl);
16435 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
16437 tree lhs;
16438 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
16439 gimple_call_set_lhs (call_stmt, lhs);
16440 tree fallthru_label;
16441 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
16442 gimple *g;
16443 g = gimple_build_label (fallthru_label);
16444 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16445 g = gimple_build_cond (NE_EXPR, lhs,
16446 fold_convert (TREE_TYPE (lhs),
16447 boolean_false_node),
16448 cctx->cancel_label, fallthru_label);
16449 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16450 break;
16451 default:
16452 break;
16454 /* FALLTHRU */
16455 default:
16456 if ((ctx || task_shared_vars)
16457 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16458 ctx ? NULL : &wi))
16460 /* Just remove clobbers, this should happen only if we have
16461 "privatized" local addressable variables in SIMD regions,
16462 the clobber isn't needed in that case and gimplifying address
16463 of the ARRAY_REF into a pointer and creating MEM_REF based
16464 clobber would create worse code than we get with the clobber
16465 dropped. */
16466 if (gimple_clobber_p (stmt))
16468 gsi_replace (gsi_p, gimple_build_nop (), true);
16469 break;
16471 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16473 break;
16477 static void
16478 lower_omp (gimple_seq *body, omp_context *ctx)
16480 location_t saved_location = input_location;
16481 gimple_stmt_iterator gsi;
16482 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16483 lower_omp_1 (&gsi, ctx);
16484 /* During gimplification, we haven't folded statments inside offloading
16485 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16486 if (target_nesting_level || taskreg_nesting_level)
16487 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16488 fold_stmt (&gsi);
16489 input_location = saved_location;
16492 /* Main entry point. */
16494 static unsigned int
16495 execute_lower_omp (void)
16497 gimple_seq body;
16498 int i;
16499 omp_context *ctx;
16501 /* This pass always runs, to provide PROP_gimple_lomp.
16502 But often, there is nothing to do. */
16503 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16504 && flag_openmp_simd == 0)
16505 return 0;
16507 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16508 delete_omp_context);
16510 body = gimple_body (current_function_decl);
16511 scan_omp (&body, NULL);
16512 gcc_assert (taskreg_nesting_level == 0);
16513 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16514 finish_taskreg_scan (ctx);
16515 taskreg_contexts.release ();
16517 if (all_contexts->root)
16519 if (task_shared_vars)
16520 push_gimplify_context ();
16521 lower_omp (&body, NULL);
16522 if (task_shared_vars)
16523 pop_gimplify_context (NULL);
16526 if (all_contexts)
16528 splay_tree_delete (all_contexts);
16529 all_contexts = NULL;
16531 BITMAP_FREE (task_shared_vars);
16532 return 0;
16535 namespace {
16537 const pass_data pass_data_lower_omp =
16539 GIMPLE_PASS, /* type */
16540 "omplower", /* name */
16541 OPTGROUP_NONE, /* optinfo_flags */
16542 TV_NONE, /* tv_id */
16543 PROP_gimple_any, /* properties_required */
16544 PROP_gimple_lomp, /* properties_provided */
16545 0, /* properties_destroyed */
16546 0, /* todo_flags_start */
16547 0, /* todo_flags_finish */
16550 class pass_lower_omp : public gimple_opt_pass
16552 public:
16553 pass_lower_omp (gcc::context *ctxt)
16554 : gimple_opt_pass (pass_data_lower_omp, ctxt)
16557 /* opt_pass methods: */
16558 virtual unsigned int execute (function *) { return execute_lower_omp (); }
16560 }; // class pass_lower_omp
16562 } // anon namespace
16564 gimple_opt_pass *
16565 make_pass_lower_omp (gcc::context *ctxt)
16567 return new pass_lower_omp (ctxt);
16570 /* The following is a utility to diagnose structured block violations.
16571 It is not part of the "omplower" pass, as that's invoked too late. It
16572 should be invoked by the respective front ends after gimplification. */
16574 static splay_tree all_labels;
16576 /* Check for mismatched contexts and generate an error if needed. Return
16577 true if an error is detected. */
16579 static bool
16580 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
16581 gimple *branch_ctx, gimple *label_ctx)
16583 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16584 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16586 if (label_ctx == branch_ctx)
16587 return false;
16589 const char* kind = NULL;
16591 if (flag_cilkplus)
16593 if ((branch_ctx
16594 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16595 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16596 || (label_ctx
16597 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16598 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16599 kind = "Cilk Plus";
16601 if (flag_openacc)
16603 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16604 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16606 gcc_checking_assert (kind == NULL);
16607 kind = "OpenACC";
16610 if (kind == NULL)
16612 gcc_checking_assert (flag_openmp);
16613 kind = "OpenMP";
16617 Previously we kept track of the label's entire context in diagnose_sb_[12]
16618 so we could traverse it and issue a correct "exit" or "enter" error
16619 message upon a structured block violation.
16621 We built the context by building a list with tree_cons'ing, but there is
16622 no easy counterpart in gimple tuples. It seems like far too much work
16623 for issuing exit/enter error messages. If someone really misses the
16624 distinct error message... patches welcome.
16627 #if 0
16628 /* Try to avoid confusing the user by producing and error message
16629 with correct "exit" or "enter" verbiage. We prefer "exit"
16630 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16631 if (branch_ctx == NULL)
16632 exit_p = false;
16633 else
16635 while (label_ctx)
16637 if (TREE_VALUE (label_ctx) == branch_ctx)
16639 exit_p = false;
16640 break;
16642 label_ctx = TREE_CHAIN (label_ctx);
16646 if (exit_p)
16647 error ("invalid exit from %s structured block", kind);
16648 else
16649 error ("invalid entry to %s structured block", kind);
16650 #endif
16652 /* If it's obvious we have an invalid entry, be specific about the error. */
16653 if (branch_ctx == NULL)
16654 error ("invalid entry to %s structured block", kind);
16655 else
16657 /* Otherwise, be vague and lazy, but efficient. */
16658 error ("invalid branch to/from %s structured block", kind);
16661 gsi_replace (gsi_p, gimple_build_nop (), false);
16662 return true;
16665 /* Pass 1: Create a minimal tree of structured blocks, and record
16666 where each label is found. */
16668 static tree
16669 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16670 struct walk_stmt_info *wi)
16672 gimple *context = (gimple *) wi->info;
16673 gimple *inner_context;
16674 gimple *stmt = gsi_stmt (*gsi_p);
16676 *handled_ops_p = true;
16678 switch (gimple_code (stmt))
16680 WALK_SUBSTMTS;
16682 case GIMPLE_OMP_PARALLEL:
16683 case GIMPLE_OMP_TASK:
16684 case GIMPLE_OMP_SECTIONS:
16685 case GIMPLE_OMP_SINGLE:
16686 case GIMPLE_OMP_SECTION:
16687 case GIMPLE_OMP_MASTER:
16688 case GIMPLE_OMP_ORDERED:
16689 case GIMPLE_OMP_CRITICAL:
16690 case GIMPLE_OMP_TARGET:
16691 case GIMPLE_OMP_TEAMS:
16692 case GIMPLE_OMP_TASKGROUP:
16693 /* The minimal context here is just the current OMP construct. */
16694 inner_context = stmt;
16695 wi->info = inner_context;
16696 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16697 wi->info = context;
16698 break;
16700 case GIMPLE_OMP_FOR:
16701 inner_context = stmt;
16702 wi->info = inner_context;
16703 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16704 walk them. */
16705 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16706 diagnose_sb_1, NULL, wi);
16707 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16708 wi->info = context;
16709 break;
16711 case GIMPLE_LABEL:
16712 splay_tree_insert (all_labels,
16713 (splay_tree_key) gimple_label_label (
16714 as_a <glabel *> (stmt)),
16715 (splay_tree_value) context);
16716 break;
16718 default:
16719 break;
16722 return NULL_TREE;
16725 /* Pass 2: Check each branch and see if its context differs from that of
16726 the destination label's context. */
16728 static tree
16729 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16730 struct walk_stmt_info *wi)
16732 gimple *context = (gimple *) wi->info;
16733 splay_tree_node n;
16734 gimple *stmt = gsi_stmt (*gsi_p);
16736 *handled_ops_p = true;
16738 switch (gimple_code (stmt))
16740 WALK_SUBSTMTS;
16742 case GIMPLE_OMP_PARALLEL:
16743 case GIMPLE_OMP_TASK:
16744 case GIMPLE_OMP_SECTIONS:
16745 case GIMPLE_OMP_SINGLE:
16746 case GIMPLE_OMP_SECTION:
16747 case GIMPLE_OMP_MASTER:
16748 case GIMPLE_OMP_ORDERED:
16749 case GIMPLE_OMP_CRITICAL:
16750 case GIMPLE_OMP_TARGET:
16751 case GIMPLE_OMP_TEAMS:
16752 case GIMPLE_OMP_TASKGROUP:
16753 wi->info = stmt;
16754 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16755 wi->info = context;
16756 break;
16758 case GIMPLE_OMP_FOR:
16759 wi->info = stmt;
16760 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16761 walk them. */
16762 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16763 diagnose_sb_2, NULL, wi);
16764 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16765 wi->info = context;
16766 break;
16768 case GIMPLE_COND:
16770 gcond *cond_stmt = as_a <gcond *> (stmt);
16771 tree lab = gimple_cond_true_label (cond_stmt);
16772 if (lab)
16774 n = splay_tree_lookup (all_labels,
16775 (splay_tree_key) lab);
16776 diagnose_sb_0 (gsi_p, context,
16777 n ? (gimple *) n->value : NULL);
16779 lab = gimple_cond_false_label (cond_stmt);
16780 if (lab)
16782 n = splay_tree_lookup (all_labels,
16783 (splay_tree_key) lab);
16784 diagnose_sb_0 (gsi_p, context,
16785 n ? (gimple *) n->value : NULL);
16788 break;
16790 case GIMPLE_GOTO:
16792 tree lab = gimple_goto_dest (stmt);
16793 if (TREE_CODE (lab) != LABEL_DECL)
16794 break;
16796 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16797 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
16799 break;
16801 case GIMPLE_SWITCH:
16803 gswitch *switch_stmt = as_a <gswitch *> (stmt);
16804 unsigned int i;
16805 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
16807 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
16808 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16809 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
16810 break;
16813 break;
16815 case GIMPLE_RETURN:
16816 diagnose_sb_0 (gsi_p, context, NULL);
16817 break;
16819 default:
16820 break;
16823 return NULL_TREE;
16826 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16827 GIMPLE_* codes. */
16828 bool
16829 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16830 int *region_idx)
16832 gimple *last = last_stmt (bb);
16833 enum gimple_code code = gimple_code (last);
16834 struct omp_region *cur_region = *region;
16835 bool fallthru = false;
16837 switch (code)
16839 case GIMPLE_OMP_PARALLEL:
16840 case GIMPLE_OMP_TASK:
16841 case GIMPLE_OMP_FOR:
16842 case GIMPLE_OMP_SINGLE:
16843 case GIMPLE_OMP_TEAMS:
16844 case GIMPLE_OMP_MASTER:
16845 case GIMPLE_OMP_TASKGROUP:
16846 case GIMPLE_OMP_CRITICAL:
16847 case GIMPLE_OMP_SECTION:
16848 cur_region = new_omp_region (bb, code, cur_region);
16849 fallthru = true;
16850 break;
16852 case GIMPLE_OMP_ORDERED:
16853 cur_region = new_omp_region (bb, code, cur_region);
16854 fallthru = true;
16855 if (find_omp_clause (gimple_omp_ordered_clauses
16856 (as_a <gomp_ordered *> (last)),
16857 OMP_CLAUSE_DEPEND))
16858 cur_region = cur_region->outer;
16859 break;
16861 case GIMPLE_OMP_TARGET:
16862 cur_region = new_omp_region (bb, code, cur_region);
16863 fallthru = true;
16864 switch (gimple_omp_target_kind (last))
16866 case GF_OMP_TARGET_KIND_REGION:
16867 case GF_OMP_TARGET_KIND_DATA:
16868 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16869 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16870 case GF_OMP_TARGET_KIND_OACC_DATA:
16871 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
16872 break;
16873 case GF_OMP_TARGET_KIND_UPDATE:
16874 case GF_OMP_TARGET_KIND_ENTER_DATA:
16875 case GF_OMP_TARGET_KIND_EXIT_DATA:
16876 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16877 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
16878 case GF_OMP_TARGET_KIND_OACC_DECLARE:
16879 cur_region = cur_region->outer;
16880 break;
16881 default:
16882 gcc_unreachable ();
16884 break;
16886 case GIMPLE_OMP_SECTIONS:
16887 cur_region = new_omp_region (bb, code, cur_region);
16888 fallthru = true;
16889 break;
16891 case GIMPLE_OMP_SECTIONS_SWITCH:
16892 fallthru = false;
16893 break;
16895 case GIMPLE_OMP_ATOMIC_LOAD:
16896 case GIMPLE_OMP_ATOMIC_STORE:
16897 fallthru = true;
16898 break;
16900 case GIMPLE_OMP_RETURN:
16901 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16902 somewhere other than the next block. This will be
16903 created later. */
16904 cur_region->exit = bb;
16905 if (cur_region->type == GIMPLE_OMP_TASK)
16906 /* Add an edge corresponding to not scheduling the task
16907 immediately. */
16908 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
16909 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16910 cur_region = cur_region->outer;
16911 break;
16913 case GIMPLE_OMP_CONTINUE:
16914 cur_region->cont = bb;
16915 switch (cur_region->type)
16917 case GIMPLE_OMP_FOR:
16918 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16919 succs edges as abnormal to prevent splitting
16920 them. */
16921 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16922 /* Make the loopback edge. */
16923 make_edge (bb, single_succ (cur_region->entry),
16924 EDGE_ABNORMAL);
16926 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16927 corresponds to the case that the body of the loop
16928 is not executed at all. */
16929 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16930 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16931 fallthru = false;
16932 break;
16934 case GIMPLE_OMP_SECTIONS:
16935 /* Wire up the edges into and out of the nested sections. */
16937 basic_block switch_bb = single_succ (cur_region->entry);
16939 struct omp_region *i;
16940 for (i = cur_region->inner; i ; i = i->next)
16942 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16943 make_edge (switch_bb, i->entry, 0);
16944 make_edge (i->exit, bb, EDGE_FALLTHRU);
16947 /* Make the loopback edge to the block with
16948 GIMPLE_OMP_SECTIONS_SWITCH. */
16949 make_edge (bb, switch_bb, 0);
16951 /* Make the edge from the switch to exit. */
16952 make_edge (switch_bb, bb->next_bb, 0);
16953 fallthru = false;
16955 break;
16957 case GIMPLE_OMP_TASK:
16958 fallthru = true;
16959 break;
16961 default:
16962 gcc_unreachable ();
16964 break;
16966 default:
16967 gcc_unreachable ();
16970 if (*region != cur_region)
16972 *region = cur_region;
16973 if (cur_region)
16974 *region_idx = cur_region->entry->index;
16975 else
16976 *region_idx = 0;
16979 return fallthru;
16982 static unsigned int
16983 diagnose_omp_structured_block_errors (void)
16985 struct walk_stmt_info wi;
16986 gimple_seq body = gimple_body (current_function_decl);
16988 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16990 memset (&wi, 0, sizeof (wi));
16991 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
16993 memset (&wi, 0, sizeof (wi));
16994 wi.want_locations = true;
16995 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
16997 gimple_set_body (current_function_decl, body);
16999 splay_tree_delete (all_labels);
17000 all_labels = NULL;
17002 return 0;
17005 namespace {
17007 const pass_data pass_data_diagnose_omp_blocks =
17009 GIMPLE_PASS, /* type */
17010 "*diagnose_omp_blocks", /* name */
17011 OPTGROUP_NONE, /* optinfo_flags */
17012 TV_NONE, /* tv_id */
17013 PROP_gimple_any, /* properties_required */
17014 0, /* properties_provided */
17015 0, /* properties_destroyed */
17016 0, /* todo_flags_start */
17017 0, /* todo_flags_finish */
17020 class pass_diagnose_omp_blocks : public gimple_opt_pass
17022 public:
17023 pass_diagnose_omp_blocks (gcc::context *ctxt)
17024 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
17027 /* opt_pass methods: */
17028 virtual bool gate (function *)
17030 return flag_cilkplus || flag_openacc || flag_openmp;
17032 virtual unsigned int execute (function *)
17034 return diagnose_omp_structured_block_errors ();
17037 }; // class pass_diagnose_omp_blocks
17039 } // anon namespace
17041 gimple_opt_pass *
17042 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
17044 return new pass_diagnose_omp_blocks (ctxt);
17047 /* SIMD clone supporting code. */
17049 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
17050 of arguments to reserve space for. */
17052 static struct cgraph_simd_clone *
17053 simd_clone_struct_alloc (int nargs)
17055 struct cgraph_simd_clone *clone_info;
17056 size_t len = (sizeof (struct cgraph_simd_clone)
17057 + nargs * sizeof (struct cgraph_simd_clone_arg));
17058 clone_info = (struct cgraph_simd_clone *)
17059 ggc_internal_cleared_alloc (len);
17060 return clone_info;
17063 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
17065 static inline void
17066 simd_clone_struct_copy (struct cgraph_simd_clone *to,
17067 struct cgraph_simd_clone *from)
17069 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
17070 + ((from->nargs - from->inbranch)
17071 * sizeof (struct cgraph_simd_clone_arg))));
17074 /* Return vector of parameter types of function FNDECL. This uses
17075 TYPE_ARG_TYPES if available, otherwise falls back to types of
17076 DECL_ARGUMENTS types. */
17078 vec<tree>
17079 simd_clone_vector_of_formal_parm_types (tree fndecl)
17081 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
17082 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
17083 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
17084 unsigned int i;
17085 tree arg;
17086 FOR_EACH_VEC_ELT (args, i, arg)
17087 args[i] = TREE_TYPE (args[i]);
17088 return args;
17091 /* Given a simd function in NODE, extract the simd specific
17092 information from the OMP clauses passed in CLAUSES, and return
17093 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
17094 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
17095 otherwise set to FALSE. */
17097 static struct cgraph_simd_clone *
17098 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
17099 bool *inbranch_specified)
17101 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
17102 tree t;
17103 int n;
17104 *inbranch_specified = false;
17106 n = args.length ();
17107 if (n > 0 && args.last () == void_type_node)
17108 n--;
17110 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
17111 be cloned have a distinctive artificial label in addition to "omp
17112 declare simd". */
17113 bool cilk_clone
17114 = (flag_cilkplus
17115 && lookup_attribute ("cilk simd function",
17116 DECL_ATTRIBUTES (node->decl)));
17118 /* Allocate one more than needed just in case this is an in-branch
17119 clone which will require a mask argument. */
17120 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
17121 clone_info->nargs = n;
17122 clone_info->cilk_elemental = cilk_clone;
17124 if (!clauses)
17126 args.release ();
17127 return clone_info;
17129 clauses = TREE_VALUE (clauses);
17130 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
17131 return clone_info;
17133 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
17135 switch (OMP_CLAUSE_CODE (t))
17137 case OMP_CLAUSE_INBRANCH:
17138 clone_info->inbranch = 1;
17139 *inbranch_specified = true;
17140 break;
17141 case OMP_CLAUSE_NOTINBRANCH:
17142 clone_info->inbranch = 0;
17143 *inbranch_specified = true;
17144 break;
17145 case OMP_CLAUSE_SIMDLEN:
17146 clone_info->simdlen
17147 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
17148 break;
17149 case OMP_CLAUSE_LINEAR:
17151 tree decl = OMP_CLAUSE_DECL (t);
17152 tree step = OMP_CLAUSE_LINEAR_STEP (t);
17153 int argno = TREE_INT_CST_LOW (decl);
17154 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
17156 enum cgraph_simd_clone_arg_type arg_type;
17157 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17158 switch (OMP_CLAUSE_LINEAR_KIND (t))
17160 case OMP_CLAUSE_LINEAR_REF:
17161 arg_type
17162 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
17163 break;
17164 case OMP_CLAUSE_LINEAR_UVAL:
17165 arg_type
17166 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
17167 break;
17168 case OMP_CLAUSE_LINEAR_VAL:
17169 case OMP_CLAUSE_LINEAR_DEFAULT:
17170 arg_type
17171 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
17172 break;
17173 default:
17174 gcc_unreachable ();
17176 else
17177 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
17178 clone_info->args[argno].arg_type = arg_type;
17179 clone_info->args[argno].linear_step = tree_to_shwi (step);
17180 gcc_assert (clone_info->args[argno].linear_step >= 0
17181 && clone_info->args[argno].linear_step < n);
17183 else
17185 if (POINTER_TYPE_P (args[argno]))
17186 step = fold_convert (ssizetype, step);
17187 if (!tree_fits_shwi_p (step))
17189 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17190 "ignoring large linear step");
17191 args.release ();
17192 return NULL;
17194 else if (integer_zerop (step))
17196 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17197 "ignoring zero linear step");
17198 args.release ();
17199 return NULL;
17201 else
17203 enum cgraph_simd_clone_arg_type arg_type;
17204 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17205 switch (OMP_CLAUSE_LINEAR_KIND (t))
17207 case OMP_CLAUSE_LINEAR_REF:
17208 arg_type
17209 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17210 break;
17211 case OMP_CLAUSE_LINEAR_UVAL:
17212 arg_type
17213 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17214 break;
17215 case OMP_CLAUSE_LINEAR_VAL:
17216 case OMP_CLAUSE_LINEAR_DEFAULT:
17217 arg_type
17218 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17219 break;
17220 default:
17221 gcc_unreachable ();
17223 else
17224 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17225 clone_info->args[argno].arg_type = arg_type;
17226 clone_info->args[argno].linear_step = tree_to_shwi (step);
17229 break;
17231 case OMP_CLAUSE_UNIFORM:
17233 tree decl = OMP_CLAUSE_DECL (t);
17234 int argno = tree_to_uhwi (decl);
17235 clone_info->args[argno].arg_type
17236 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17237 break;
17239 case OMP_CLAUSE_ALIGNED:
17241 tree decl = OMP_CLAUSE_DECL (t);
17242 int argno = tree_to_uhwi (decl);
17243 clone_info->args[argno].alignment
17244 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17245 break;
17247 default:
17248 break;
17251 args.release ();
17252 return clone_info;
17255 /* Given a SIMD clone in NODE, calculate the characteristic data
17256 type and return the coresponding type. The characteristic data
17257 type is computed as described in the Intel Vector ABI. */
17259 static tree
17260 simd_clone_compute_base_data_type (struct cgraph_node *node,
17261 struct cgraph_simd_clone *clone_info)
17263 tree type = integer_type_node;
17264 tree fndecl = node->decl;
17266 /* a) For non-void function, the characteristic data type is the
17267 return type. */
17268 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17269 type = TREE_TYPE (TREE_TYPE (fndecl));
17271 /* b) If the function has any non-uniform, non-linear parameters,
17272 then the characteristic data type is the type of the first
17273 such parameter. */
17274 else
17276 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17277 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17278 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17280 type = map[i];
17281 break;
17283 map.release ();
17286 /* c) If the characteristic data type determined by a) or b) above
17287 is struct, union, or class type which is pass-by-value (except
17288 for the type that maps to the built-in complex data type), the
17289 characteristic data type is int. */
17290 if (RECORD_OR_UNION_TYPE_P (type)
17291 && !aggregate_value_p (type, NULL)
17292 && TREE_CODE (type) != COMPLEX_TYPE)
17293 return integer_type_node;
17295 /* d) If none of the above three classes is applicable, the
17296 characteristic data type is int. */
17298 return type;
17300 /* e) For Intel Xeon Phi native and offload compilation, if the
17301 resulting characteristic data type is 8-bit or 16-bit integer
17302 data type, the characteristic data type is int. */
17303 /* Well, we don't handle Xeon Phi yet. */
17306 static tree
17307 simd_clone_mangle (struct cgraph_node *node,
17308 struct cgraph_simd_clone *clone_info)
17310 char vecsize_mangle = clone_info->vecsize_mangle;
17311 char mask = clone_info->inbranch ? 'M' : 'N';
17312 unsigned int simdlen = clone_info->simdlen;
17313 unsigned int n;
17314 pretty_printer pp;
17316 gcc_assert (vecsize_mangle && simdlen);
17318 pp_string (&pp, "_ZGV");
17319 pp_character (&pp, vecsize_mangle);
17320 pp_character (&pp, mask);
17321 pp_decimal_int (&pp, simdlen);
17323 for (n = 0; n < clone_info->nargs; ++n)
17325 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17327 switch (arg.arg_type)
17329 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17330 pp_character (&pp, 'u');
17331 break;
17332 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17333 pp_character (&pp, 'l');
17334 goto mangle_linear;
17335 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17336 pp_character (&pp, 'R');
17337 goto mangle_linear;
17338 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17339 pp_character (&pp, 'L');
17340 goto mangle_linear;
17341 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17342 pp_character (&pp, 'U');
17343 goto mangle_linear;
17344 mangle_linear:
17345 gcc_assert (arg.linear_step != 0);
17346 if (arg.linear_step > 1)
17347 pp_unsigned_wide_integer (&pp, arg.linear_step);
17348 else if (arg.linear_step < 0)
17350 pp_character (&pp, 'n');
17351 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17352 arg.linear_step));
17354 break;
17355 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17356 pp_string (&pp, "ls");
17357 pp_unsigned_wide_integer (&pp, arg.linear_step);
17358 break;
17359 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17360 pp_string (&pp, "Rs");
17361 pp_unsigned_wide_integer (&pp, arg.linear_step);
17362 break;
17363 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17364 pp_string (&pp, "Ls");
17365 pp_unsigned_wide_integer (&pp, arg.linear_step);
17366 break;
17367 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17368 pp_string (&pp, "Us");
17369 pp_unsigned_wide_integer (&pp, arg.linear_step);
17370 break;
17371 default:
17372 pp_character (&pp, 'v');
17374 if (arg.alignment)
17376 pp_character (&pp, 'a');
17377 pp_decimal_int (&pp, arg.alignment);
17381 pp_underscore (&pp);
17382 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17383 if (*str == '*')
17384 ++str;
17385 pp_string (&pp, str);
17386 str = pp_formatted_text (&pp);
17388 /* If there already is a SIMD clone with the same mangled name, don't
17389 add another one. This can happen e.g. for
17390 #pragma omp declare simd
17391 #pragma omp declare simd simdlen(8)
17392 int foo (int, int);
17393 if the simdlen is assumed to be 8 for the first one, etc. */
17394 for (struct cgraph_node *clone = node->simd_clones; clone;
17395 clone = clone->simdclone->next_clone)
17396 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17397 str) == 0)
17398 return NULL_TREE;
17400 return get_identifier (str);
17403 /* Create a simd clone of OLD_NODE and return it. */
17405 static struct cgraph_node *
17406 simd_clone_create (struct cgraph_node *old_node)
17408 struct cgraph_node *new_node;
17409 if (old_node->definition)
17411 if (!old_node->has_gimple_body_p ())
17412 return NULL;
17413 old_node->get_body ();
17414 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17415 false, NULL, NULL,
17416 "simdclone");
17418 else
17420 tree old_decl = old_node->decl;
17421 tree new_decl = copy_node (old_node->decl);
17422 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17423 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17424 SET_DECL_RTL (new_decl, NULL);
17425 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17426 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
17427 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
17428 if (old_node->in_other_partition)
17429 new_node->in_other_partition = 1;
17430 symtab->call_cgraph_insertion_hooks (new_node);
17432 if (new_node == NULL)
17433 return new_node;
17435 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17437 /* The function cgraph_function_versioning () will force the new
17438 symbol local. Undo this, and inherit external visability from
17439 the old node. */
17440 new_node->local.local = old_node->local.local;
17441 new_node->externally_visible = old_node->externally_visible;
17443 return new_node;
17446 /* Adjust the return type of the given function to its appropriate
17447 vector counterpart. Returns a simd array to be used throughout the
17448 function as a return value. */
17450 static tree
17451 simd_clone_adjust_return_type (struct cgraph_node *node)
17453 tree fndecl = node->decl;
17454 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17455 unsigned int veclen;
17456 tree t;
17458 /* Adjust the function return type. */
17459 if (orig_rettype == void_type_node)
17460 return NULL_TREE;
17461 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
17462 t = TREE_TYPE (TREE_TYPE (fndecl));
17463 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
17464 veclen = node->simdclone->vecsize_int;
17465 else
17466 veclen = node->simdclone->vecsize_float;
17467 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
17468 if (veclen > node->simdclone->simdlen)
17469 veclen = node->simdclone->simdlen;
17470 if (POINTER_TYPE_P (t))
17471 t = pointer_sized_int_node;
17472 if (veclen == node->simdclone->simdlen)
17473 t = build_vector_type (t, node->simdclone->simdlen);
17474 else
17476 t = build_vector_type (t, veclen);
17477 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
17479 TREE_TYPE (TREE_TYPE (fndecl)) = t;
17480 if (!node->definition)
17481 return NULL_TREE;
17483 t = DECL_RESULT (fndecl);
17484 /* Adjust the DECL_RESULT. */
17485 gcc_assert (TREE_TYPE (t) != void_type_node);
17486 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17487 relayout_decl (t);
17489 tree atype = build_array_type_nelts (orig_rettype,
17490 node->simdclone->simdlen);
17491 if (veclen != node->simdclone->simdlen)
17492 return build1 (VIEW_CONVERT_EXPR, atype, t);
17494 /* Set up a SIMD array to use as the return value. */
17495 tree retval = create_tmp_var_raw (atype, "retval");
17496 gimple_add_tmp_var (retval);
17497 return retval;
17500 /* Each vector argument has a corresponding array to be used locally
17501 as part of the eventual loop. Create such temporary array and
17502 return it.
17504 PREFIX is the prefix to be used for the temporary.
17506 TYPE is the inner element type.
17508 SIMDLEN is the number of elements. */
17510 static tree
17511 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17513 tree atype = build_array_type_nelts (type, simdlen);
17514 tree avar = create_tmp_var_raw (atype, prefix);
17515 gimple_add_tmp_var (avar);
17516 return avar;
17519 /* Modify the function argument types to their corresponding vector
17520 counterparts if appropriate. Also, create one array for each simd
17521 argument to be used locally when using the function arguments as
17522 part of the loop.
17524 NODE is the function whose arguments are to be adjusted.
17526 Returns an adjustment vector that will be filled describing how the
17527 argument types will be adjusted. */
17529 static ipa_parm_adjustment_vec
17530 simd_clone_adjust_argument_types (struct cgraph_node *node)
17532 vec<tree> args;
17533 ipa_parm_adjustment_vec adjustments;
17535 if (node->definition)
17536 args = ipa_get_vector_of_formal_parms (node->decl);
17537 else
17538 args = simd_clone_vector_of_formal_parm_types (node->decl);
17539 adjustments.create (args.length ());
17540 unsigned i, j, veclen;
17541 struct ipa_parm_adjustment adj;
17542 for (i = 0; i < node->simdclone->nargs; ++i)
17544 memset (&adj, 0, sizeof (adj));
17545 tree parm = args[i];
17546 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17547 adj.base_index = i;
17548 adj.base = parm;
17550 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17551 node->simdclone->args[i].orig_type = parm_type;
17553 switch (node->simdclone->args[i].arg_type)
17555 default:
17556 /* No adjustment necessary for scalar arguments. */
17557 adj.op = IPA_PARM_OP_COPY;
17558 break;
17559 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17560 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17561 if (node->definition)
17562 node->simdclone->args[i].simd_array
17563 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17564 TREE_TYPE (parm_type),
17565 node->simdclone->simdlen);
17566 adj.op = IPA_PARM_OP_COPY;
17567 break;
17568 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17569 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17570 case SIMD_CLONE_ARG_TYPE_VECTOR:
17571 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17572 veclen = node->simdclone->vecsize_int;
17573 else
17574 veclen = node->simdclone->vecsize_float;
17575 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17576 if (veclen > node->simdclone->simdlen)
17577 veclen = node->simdclone->simdlen;
17578 adj.arg_prefix = "simd";
17579 if (POINTER_TYPE_P (parm_type))
17580 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17581 else
17582 adj.type = build_vector_type (parm_type, veclen);
17583 node->simdclone->args[i].vector_type = adj.type;
17584 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17586 adjustments.safe_push (adj);
17587 if (j == veclen)
17589 memset (&adj, 0, sizeof (adj));
17590 adj.op = IPA_PARM_OP_NEW;
17591 adj.arg_prefix = "simd";
17592 adj.base_index = i;
17593 adj.type = node->simdclone->args[i].vector_type;
17597 if (node->definition)
17598 node->simdclone->args[i].simd_array
17599 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17600 parm_type, node->simdclone->simdlen);
17602 adjustments.safe_push (adj);
17605 if (node->simdclone->inbranch)
17607 tree base_type
17608 = simd_clone_compute_base_data_type (node->simdclone->origin,
17609 node->simdclone);
17611 memset (&adj, 0, sizeof (adj));
17612 adj.op = IPA_PARM_OP_NEW;
17613 adj.arg_prefix = "mask";
17615 adj.base_index = i;
17616 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17617 veclen = node->simdclone->vecsize_int;
17618 else
17619 veclen = node->simdclone->vecsize_float;
17620 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17621 if (veclen > node->simdclone->simdlen)
17622 veclen = node->simdclone->simdlen;
17623 if (POINTER_TYPE_P (base_type))
17624 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17625 else
17626 adj.type = build_vector_type (base_type, veclen);
17627 adjustments.safe_push (adj);
17629 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17630 adjustments.safe_push (adj);
17632 /* We have previously allocated one extra entry for the mask. Use
17633 it and fill it. */
17634 struct cgraph_simd_clone *sc = node->simdclone;
17635 sc->nargs++;
17636 if (node->definition)
17638 sc->args[i].orig_arg
17639 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17640 sc->args[i].simd_array
17641 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17643 sc->args[i].orig_type = base_type;
17644 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17647 if (node->definition)
17648 ipa_modify_formal_parameters (node->decl, adjustments);
17649 else
17651 tree new_arg_types = NULL_TREE, new_reversed;
17652 bool last_parm_void = false;
17653 if (args.length () > 0 && args.last () == void_type_node)
17654 last_parm_void = true;
17656 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17657 j = adjustments.length ();
17658 for (i = 0; i < j; i++)
17660 struct ipa_parm_adjustment *adj = &adjustments[i];
17661 tree ptype;
17662 if (adj->op == IPA_PARM_OP_COPY)
17663 ptype = args[adj->base_index];
17664 else
17665 ptype = adj->type;
17666 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17668 new_reversed = nreverse (new_arg_types);
17669 if (last_parm_void)
17671 if (new_reversed)
17672 TREE_CHAIN (new_arg_types) = void_list_node;
17673 else
17674 new_reversed = void_list_node;
17677 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17678 TYPE_ARG_TYPES (new_type) = new_reversed;
17679 TREE_TYPE (node->decl) = new_type;
17681 adjustments.release ();
17683 args.release ();
17684 return adjustments;
17687 /* Initialize and copy the function arguments in NODE to their
17688 corresponding local simd arrays. Returns a fresh gimple_seq with
17689 the instruction sequence generated. */
17691 static gimple_seq
17692 simd_clone_init_simd_arrays (struct cgraph_node *node,
17693 ipa_parm_adjustment_vec adjustments)
17695 gimple_seq seq = NULL;
17696 unsigned i = 0, j = 0, k;
17698 for (tree arg = DECL_ARGUMENTS (node->decl);
17699 arg;
17700 arg = DECL_CHAIN (arg), i++, j++)
17702 if (adjustments[j].op == IPA_PARM_OP_COPY
17703 || POINTER_TYPE_P (TREE_TYPE (arg)))
17704 continue;
17706 node->simdclone->args[i].vector_arg = arg;
17708 tree array = node->simdclone->args[i].simd_array;
17709 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17711 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17712 tree ptr = build_fold_addr_expr (array);
17713 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17714 build_int_cst (ptype, 0));
17715 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17716 gimplify_and_add (t, &seq);
17718 else
17720 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17721 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17722 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17724 tree ptr = build_fold_addr_expr (array);
17725 int elemsize;
17726 if (k)
17728 arg = DECL_CHAIN (arg);
17729 j++;
17731 elemsize
17732 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17733 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17734 build_int_cst (ptype, k * elemsize));
17735 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17736 gimplify_and_add (t, &seq);
17740 return seq;
17743 /* Callback info for ipa_simd_modify_stmt_ops below. */
17745 struct modify_stmt_info {
17746 ipa_parm_adjustment_vec adjustments;
17747 gimple *stmt;
17748 /* True if the parent statement was modified by
17749 ipa_simd_modify_stmt_ops. */
17750 bool modified;
17753 /* Callback for walk_gimple_op.
17755 Adjust operands from a given statement as specified in the
17756 adjustments vector in the callback data. */
17758 static tree
17759 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17761 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17762 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17763 tree *orig_tp = tp;
17764 if (TREE_CODE (*tp) == ADDR_EXPR)
17765 tp = &TREE_OPERAND (*tp, 0);
17766 struct ipa_parm_adjustment *cand = NULL;
17767 if (TREE_CODE (*tp) == PARM_DECL)
17768 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17769 else
17771 if (TYPE_P (*tp))
17772 *walk_subtrees = 0;
17775 tree repl = NULL_TREE;
17776 if (cand)
17777 repl = unshare_expr (cand->new_decl);
17778 else
17780 if (tp != orig_tp)
17782 *walk_subtrees = 0;
17783 bool modified = info->modified;
17784 info->modified = false;
17785 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17786 if (!info->modified)
17788 info->modified = modified;
17789 return NULL_TREE;
17791 info->modified = modified;
17792 repl = *tp;
17794 else
17795 return NULL_TREE;
17798 if (tp != orig_tp)
17800 repl = build_fold_addr_expr (repl);
17801 gimple *stmt;
17802 if (is_gimple_debug (info->stmt))
17804 tree vexpr = make_node (DEBUG_EXPR_DECL);
17805 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17806 DECL_ARTIFICIAL (vexpr) = 1;
17807 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17808 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17809 repl = vexpr;
17811 else
17813 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
17814 repl = gimple_assign_lhs (stmt);
17816 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
17817 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17818 *orig_tp = repl;
17820 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
17822 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17823 *tp = vce;
17825 else
17826 *tp = repl;
17828 info->modified = true;
17829 return NULL_TREE;
17832 /* Traverse the function body and perform all modifications as
17833 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17834 modified such that the replacement/reduction value will now be an
17835 offset into the corresponding simd_array.
17837 This function will replace all function argument uses with their
17838 corresponding simd array elements, and ajust the return values
17839 accordingly. */
17841 static void
17842 ipa_simd_modify_function_body (struct cgraph_node *node,
17843 ipa_parm_adjustment_vec adjustments,
17844 tree retval_array, tree iter)
17846 basic_block bb;
17847 unsigned int i, j, l;
17849 /* Re-use the adjustments array, but this time use it to replace
17850 every function argument use to an offset into the corresponding
17851 simd_array. */
17852 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17854 if (!node->simdclone->args[i].vector_arg)
17855 continue;
17857 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17858 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17859 adjustments[j].new_decl
17860 = build4 (ARRAY_REF,
17861 basetype,
17862 node->simdclone->args[i].simd_array,
17863 iter,
17864 NULL_TREE, NULL_TREE);
17865 if (adjustments[j].op == IPA_PARM_OP_NONE
17866 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17867 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17870 l = adjustments.length ();
17871 for (i = 1; i < num_ssa_names; i++)
17873 tree name = ssa_name (i);
17874 if (name
17875 && SSA_NAME_VAR (name)
17876 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17878 for (j = 0; j < l; j++)
17879 if (SSA_NAME_VAR (name) == adjustments[j].base
17880 && adjustments[j].new_decl)
17882 tree base_var;
17883 if (adjustments[j].new_ssa_base == NULL_TREE)
17885 base_var
17886 = copy_var_decl (adjustments[j].base,
17887 DECL_NAME (adjustments[j].base),
17888 TREE_TYPE (adjustments[j].base));
17889 adjustments[j].new_ssa_base = base_var;
17891 else
17892 base_var = adjustments[j].new_ssa_base;
17893 if (SSA_NAME_IS_DEFAULT_DEF (name))
17895 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17896 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17897 tree new_decl = unshare_expr (adjustments[j].new_decl);
17898 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17899 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17900 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
17901 gimple *stmt = gimple_build_assign (name, new_decl);
17902 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17904 else
17905 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17910 struct modify_stmt_info info;
17911 info.adjustments = adjustments;
17913 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17915 gimple_stmt_iterator gsi;
17917 gsi = gsi_start_bb (bb);
17918 while (!gsi_end_p (gsi))
17920 gimple *stmt = gsi_stmt (gsi);
17921 info.stmt = stmt;
17922 struct walk_stmt_info wi;
17924 memset (&wi, 0, sizeof (wi));
17925 info.modified = false;
17926 wi.info = &info;
17927 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17929 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
17931 tree retval = gimple_return_retval (return_stmt);
17932 if (!retval)
17934 gsi_remove (&gsi, true);
17935 continue;
17938 /* Replace `return foo' with `retval_array[iter] = foo'. */
17939 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17940 retval_array, iter, NULL, NULL);
17941 stmt = gimple_build_assign (ref, retval);
17942 gsi_replace (&gsi, stmt, true);
17943 info.modified = true;
17946 if (info.modified)
17948 update_stmt (stmt);
17949 if (maybe_clean_eh_stmt (stmt))
17950 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17952 gsi_next (&gsi);
17957 /* Helper function of simd_clone_adjust, return linear step addend
17958 of Ith argument. */
17960 static tree
17961 simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
17962 tree addtype, basic_block entry_bb)
17964 tree ptype = NULL_TREE;
17965 switch (node->simdclone->args[i].arg_type)
17967 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17968 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17969 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17970 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17971 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
17972 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17973 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17974 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17975 break;
17976 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17977 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17978 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
17979 break;
17980 default:
17981 gcc_unreachable ();
17984 unsigned int idx = node->simdclone->args[i].linear_step;
17985 tree arg = node->simdclone->args[idx].orig_arg;
17986 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
17987 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17988 gimple *g;
17989 tree ret;
17990 if (is_gimple_reg (arg))
17991 ret = get_or_create_ssa_default_def (cfun, arg);
17992 else
17994 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
17995 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17996 ret = gimple_assign_lhs (g);
17998 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
18000 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
18001 build_simple_mem_ref (ret));
18002 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18003 ret = gimple_assign_lhs (g);
18005 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
18007 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
18008 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18009 ret = gimple_assign_lhs (g);
18011 if (POINTER_TYPE_P (ptype))
18013 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
18014 if (size && TREE_CODE (size) == INTEGER_CST)
18016 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
18017 ret, fold_convert (addtype, size));
18018 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18019 ret = gimple_assign_lhs (g);
18022 return ret;
18025 /* Adjust the argument types in NODE to their appropriate vector
18026 counterparts. */
18028 static void
18029 simd_clone_adjust (struct cgraph_node *node)
18031 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
18033 targetm.simd_clone.adjust (node);
18035 tree retval = simd_clone_adjust_return_type (node);
18036 ipa_parm_adjustment_vec adjustments
18037 = simd_clone_adjust_argument_types (node);
18039 push_gimplify_context ();
18041 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
18043 /* Adjust all uses of vector arguments accordingly. Adjust all
18044 return values accordingly. */
18045 tree iter = create_tmp_var (unsigned_type_node, "iter");
18046 tree iter1 = make_ssa_name (iter);
18047 tree iter2 = make_ssa_name (iter);
18048 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
18050 /* Initialize the iteration variable. */
18051 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18052 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
18053 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
18054 /* Insert the SIMD array and iv initialization at function
18055 entry. */
18056 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
18058 pop_gimplify_context (NULL);
18060 /* Create a new BB right before the original exit BB, to hold the
18061 iteration increment and the condition/branch. */
18062 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
18063 basic_block incr_bb = create_empty_bb (orig_exit);
18064 add_bb_to_loop (incr_bb, body_bb->loop_father);
18065 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
18066 flag. Set it now to be a FALLTHRU_EDGE. */
18067 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
18068 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
18069 for (unsigned i = 0;
18070 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
18072 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
18073 redirect_edge_succ (e, incr_bb);
18075 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
18076 e->probability = REG_BR_PROB_BASE;
18077 gsi = gsi_last_bb (incr_bb);
18078 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
18079 build_int_cst (unsigned_type_node, 1));
18080 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18082 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
18083 struct loop *loop = alloc_loop ();
18084 cfun->has_force_vectorize_loops = true;
18085 loop->safelen = node->simdclone->simdlen;
18086 loop->force_vectorize = true;
18087 loop->header = body_bb;
18089 /* Branch around the body if the mask applies. */
18090 if (node->simdclone->inbranch)
18092 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
18093 tree mask_array
18094 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
18095 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
18096 tree aref = build4 (ARRAY_REF,
18097 TREE_TYPE (TREE_TYPE (mask_array)),
18098 mask_array, iter1,
18099 NULL, NULL);
18100 g = gimple_build_assign (mask, aref);
18101 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18102 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
18103 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
18105 aref = build1 (VIEW_CONVERT_EXPR,
18106 build_nonstandard_integer_type (bitsize, 0), mask);
18107 mask = make_ssa_name (TREE_TYPE (aref));
18108 g = gimple_build_assign (mask, aref);
18109 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18112 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
18113 NULL, NULL);
18114 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18115 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
18116 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
18119 /* Generate the condition. */
18120 g = gimple_build_cond (LT_EXPR,
18121 iter2,
18122 build_int_cst (unsigned_type_node,
18123 node->simdclone->simdlen),
18124 NULL, NULL);
18125 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18126 e = split_block (incr_bb, gsi_stmt (gsi));
18127 basic_block latch_bb = e->dest;
18128 basic_block new_exit_bb;
18129 new_exit_bb = split_block_after_labels (latch_bb)->dest;
18130 loop->latch = latch_bb;
18132 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
18134 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
18135 /* The successor of incr_bb is already pointing to latch_bb; just
18136 change the flags.
18137 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
18138 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
18140 gphi *phi = create_phi_node (iter1, body_bb);
18141 edge preheader_edge = find_edge (entry_bb, body_bb);
18142 edge latch_edge = single_succ_edge (latch_bb);
18143 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
18144 UNKNOWN_LOCATION);
18145 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18147 /* Generate the new return. */
18148 gsi = gsi_last_bb (new_exit_bb);
18149 if (retval
18150 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
18151 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
18152 retval = TREE_OPERAND (retval, 0);
18153 else if (retval)
18155 retval = build1 (VIEW_CONVERT_EXPR,
18156 TREE_TYPE (TREE_TYPE (node->decl)),
18157 retval);
18158 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
18159 false, GSI_CONTINUE_LINKING);
18161 g = gimple_build_return (retval);
18162 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18164 /* Handle aligned clauses by replacing default defs of the aligned
18165 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
18166 lhs. Handle linear by adding PHIs. */
18167 for (unsigned i = 0; i < node->simdclone->nargs; i++)
18168 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18169 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
18170 || !is_gimple_reg_type
18171 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18173 tree orig_arg = node->simdclone->args[i].orig_arg;
18174 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
18175 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18176 else
18178 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
18179 gimple_add_tmp_var (iter1);
18181 gsi = gsi_after_labels (entry_bb);
18182 g = gimple_build_assign (iter1, orig_arg);
18183 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18184 gsi = gsi_after_labels (body_bb);
18185 g = gimple_build_assign (orig_arg, iter1);
18186 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18188 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18189 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
18190 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18191 == REFERENCE_TYPE
18192 && TREE_ADDRESSABLE
18193 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18195 tree orig_arg = node->simdclone->args[i].orig_arg;
18196 tree def = ssa_default_def (cfun, orig_arg);
18197 if (def && !has_zero_uses (def))
18199 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
18200 gimple_add_tmp_var (iter1);
18201 gsi = gsi_after_labels (entry_bb);
18202 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
18203 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18204 gsi = gsi_after_labels (body_bb);
18205 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
18206 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18209 else if (node->simdclone->args[i].alignment
18210 && node->simdclone->args[i].arg_type
18211 == SIMD_CLONE_ARG_TYPE_UNIFORM
18212 && (node->simdclone->args[i].alignment
18213 & (node->simdclone->args[i].alignment - 1)) == 0
18214 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18215 == POINTER_TYPE)
18217 unsigned int alignment = node->simdclone->args[i].alignment;
18218 tree orig_arg = node->simdclone->args[i].orig_arg;
18219 tree def = ssa_default_def (cfun, orig_arg);
18220 if (def && !has_zero_uses (def))
18222 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
18223 gimple_seq seq = NULL;
18224 bool need_cvt = false;
18225 gcall *call
18226 = gimple_build_call (fn, 2, def, size_int (alignment));
18227 g = call;
18228 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
18229 ptr_type_node))
18230 need_cvt = true;
18231 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
18232 gimple_call_set_lhs (g, t);
18233 gimple_seq_add_stmt_without_update (&seq, g);
18234 if (need_cvt)
18236 t = make_ssa_name (orig_arg);
18237 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
18238 gimple_seq_add_stmt_without_update (&seq, g);
18240 gsi_insert_seq_on_edge_immediate
18241 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
18243 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18244 int freq = compute_call_stmt_bb_frequency (current_function_decl,
18245 entry_bb);
18246 node->create_edge (cgraph_node::get_create (fn),
18247 call, entry_bb->count, freq);
18249 imm_use_iterator iter;
18250 use_operand_p use_p;
18251 gimple *use_stmt;
18252 tree repl = gimple_get_lhs (g);
18253 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18254 if (is_gimple_debug (use_stmt) || use_stmt == call)
18255 continue;
18256 else
18257 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18258 SET_USE (use_p, repl);
18261 else if ((node->simdclone->args[i].arg_type
18262 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
18263 || (node->simdclone->args[i].arg_type
18264 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
18265 || (node->simdclone->args[i].arg_type
18266 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
18267 || (node->simdclone->args[i].arg_type
18268 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
18270 tree orig_arg = node->simdclone->args[i].orig_arg;
18271 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18272 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
18273 tree def = NULL_TREE;
18274 if (TREE_ADDRESSABLE (orig_arg))
18276 def = make_ssa_name (TREE_TYPE (orig_arg));
18277 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18278 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18279 gsi = gsi_after_labels (entry_bb);
18280 g = gimple_build_assign (def, orig_arg);
18281 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18283 else
18285 def = ssa_default_def (cfun, orig_arg);
18286 if (!def || has_zero_uses (def))
18287 def = NULL_TREE;
18288 else
18290 iter1 = make_ssa_name (orig_arg);
18291 iter2 = make_ssa_name (orig_arg);
18294 if (def)
18296 phi = create_phi_node (iter1, body_bb);
18297 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18298 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18299 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18300 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18301 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18302 ? TREE_TYPE (orig_arg) : sizetype;
18303 tree addcst = simd_clone_linear_addend (node, i, addtype,
18304 entry_bb);
18305 gsi = gsi_last_bb (incr_bb);
18306 g = gimple_build_assign (iter2, code, iter1, addcst);
18307 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18309 imm_use_iterator iter;
18310 use_operand_p use_p;
18311 gimple *use_stmt;
18312 if (TREE_ADDRESSABLE (orig_arg))
18314 gsi = gsi_after_labels (body_bb);
18315 g = gimple_build_assign (orig_arg, iter1);
18316 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18318 else
18319 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18320 if (use_stmt == phi)
18321 continue;
18322 else
18323 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18324 SET_USE (use_p, iter1);
18327 else if (node->simdclone->args[i].arg_type
18328 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
18329 || (node->simdclone->args[i].arg_type
18330 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
18332 tree orig_arg = node->simdclone->args[i].orig_arg;
18333 tree def = ssa_default_def (cfun, orig_arg);
18334 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18335 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18336 if (def && !has_zero_uses (def))
18338 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18339 iter1 = make_ssa_name (orig_arg);
18340 iter2 = make_ssa_name (orig_arg);
18341 tree iter3 = make_ssa_name (rtype);
18342 tree iter4 = make_ssa_name (rtype);
18343 tree iter5 = make_ssa_name (rtype);
18344 gsi = gsi_after_labels (entry_bb);
18345 gimple *load
18346 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18347 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18349 tree array = node->simdclone->args[i].simd_array;
18350 TREE_ADDRESSABLE (array) = 1;
18351 tree ptr = build_fold_addr_expr (array);
18352 phi = create_phi_node (iter1, body_bb);
18353 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18354 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18355 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18356 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18357 gsi = gsi_last_bb (incr_bb);
18358 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18360 phi = create_phi_node (iter4, body_bb);
18361 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18362 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18363 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18364 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18365 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18366 ? TREE_TYPE (iter3) : sizetype;
18367 tree addcst = simd_clone_linear_addend (node, i, addtype,
18368 entry_bb);
18369 g = gimple_build_assign (iter5, code, iter4, addcst);
18370 gsi = gsi_last_bb (incr_bb);
18371 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18373 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18374 gsi = gsi_after_labels (body_bb);
18375 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18377 imm_use_iterator iter;
18378 use_operand_p use_p;
18379 gimple *use_stmt;
18380 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18381 if (use_stmt == load)
18382 continue;
18383 else
18384 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18385 SET_USE (use_p, iter1);
18387 if (!TYPE_READONLY (rtype))
18389 tree v = make_ssa_name (rtype);
18390 tree aref = build4 (ARRAY_REF, rtype, array,
18391 size_zero_node, NULL_TREE,
18392 NULL_TREE);
18393 gsi = gsi_after_labels (new_exit_bb);
18394 g = gimple_build_assign (v, aref);
18395 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18396 g = gimple_build_assign (build_simple_mem_ref (def), v);
18397 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18402 calculate_dominance_info (CDI_DOMINATORS);
18403 add_loop (loop, loop->header->loop_father);
18404 update_ssa (TODO_update_ssa);
18406 pop_cfun ();
18409 /* If the function in NODE is tagged as an elemental SIMD function,
18410 create the appropriate SIMD clones. */
18412 static void
18413 expand_simd_clones (struct cgraph_node *node)
18415 tree attr = lookup_attribute ("omp declare simd",
18416 DECL_ATTRIBUTES (node->decl));
18417 if (attr == NULL_TREE
18418 || node->global.inlined_to
18419 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
18420 return;
18422 /* Ignore
18423 #pragma omp declare simd
18424 extern int foo ();
18425 in C, there we don't know the argument types at all. */
18426 if (!node->definition
18427 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18428 return;
18430 /* Call this before creating clone_info, as it might ggc_collect. */
18431 if (node->definition && node->has_gimple_body_p ())
18432 node->get_body ();
18436 /* Start with parsing the "omp declare simd" attribute(s). */
18437 bool inbranch_clause_specified;
18438 struct cgraph_simd_clone *clone_info
18439 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18440 &inbranch_clause_specified);
18441 if (clone_info == NULL)
18442 continue;
18444 int orig_simdlen = clone_info->simdlen;
18445 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18446 /* The target can return 0 (no simd clones should be created),
18447 1 (just one ISA of simd clones should be created) or higher
18448 count of ISA variants. In that case, clone_info is initialized
18449 for the first ISA variant. */
18450 int count
18451 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18452 base_type, 0);
18453 if (count == 0)
18454 continue;
18456 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18457 also create one inbranch and one !inbranch clone of it. */
18458 for (int i = 0; i < count * 2; i++)
18460 struct cgraph_simd_clone *clone = clone_info;
18461 if (inbranch_clause_specified && (i & 1) != 0)
18462 continue;
18464 if (i != 0)
18466 clone = simd_clone_struct_alloc (clone_info->nargs
18467 + ((i & 1) != 0));
18468 simd_clone_struct_copy (clone, clone_info);
18469 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18470 and simd_clone_adjust_argument_types did to the first
18471 clone's info. */
18472 clone->nargs -= clone_info->inbranch;
18473 clone->simdlen = orig_simdlen;
18474 /* And call the target hook again to get the right ISA. */
18475 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18476 base_type,
18477 i / 2);
18478 if ((i & 1) != 0)
18479 clone->inbranch = 1;
18482 /* simd_clone_mangle might fail if such a clone has been created
18483 already. */
18484 tree id = simd_clone_mangle (node, clone);
18485 if (id == NULL_TREE)
18486 continue;
18488 /* Only when we are sure we want to create the clone actually
18489 clone the function (or definitions) or create another
18490 extern FUNCTION_DECL (for prototypes without definitions). */
18491 struct cgraph_node *n = simd_clone_create (node);
18492 if (n == NULL)
18493 continue;
18495 n->simdclone = clone;
18496 clone->origin = node;
18497 clone->next_clone = NULL;
18498 if (node->simd_clones == NULL)
18500 clone->prev_clone = n;
18501 node->simd_clones = n;
18503 else
18505 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18506 clone->prev_clone->simdclone->next_clone = n;
18507 node->simd_clones->simdclone->prev_clone = n;
18509 symtab->change_decl_assembler_name (n->decl, id);
18510 /* And finally adjust the return type, parameters and for
18511 definitions also function body. */
18512 if (node->definition)
18513 simd_clone_adjust (n);
18514 else
18516 simd_clone_adjust_return_type (n);
18517 simd_clone_adjust_argument_types (n);
18521 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18524 /* Entry point for IPA simd clone creation pass. */
18526 static unsigned int
18527 ipa_omp_simd_clone (void)
18529 struct cgraph_node *node;
18530 FOR_EACH_FUNCTION (node)
18531 expand_simd_clones (node);
18532 return 0;
18535 namespace {
18537 const pass_data pass_data_omp_simd_clone =
18539 SIMPLE_IPA_PASS, /* type */
18540 "simdclone", /* name */
18541 OPTGROUP_NONE, /* optinfo_flags */
18542 TV_NONE, /* tv_id */
18543 ( PROP_ssa | PROP_cfg ), /* properties_required */
18544 0, /* properties_provided */
18545 0, /* properties_destroyed */
18546 0, /* todo_flags_start */
18547 0, /* todo_flags_finish */
18550 class pass_omp_simd_clone : public simple_ipa_opt_pass
18552 public:
18553 pass_omp_simd_clone(gcc::context *ctxt)
18554 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18557 /* opt_pass methods: */
18558 virtual bool gate (function *);
18559 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
18562 bool
18563 pass_omp_simd_clone::gate (function *)
18565 return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
18568 } // anon namespace
18570 simple_ipa_opt_pass *
18571 make_pass_omp_simd_clone (gcc::context *ctxt)
18573 return new pass_omp_simd_clone (ctxt);
18576 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18577 adds their addresses and sizes to constructor-vector V_CTOR. */
18578 static void
18579 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18580 vec<constructor_elt, va_gc> *v_ctor)
18582 unsigned len = vec_safe_length (v_decls);
18583 for (unsigned i = 0; i < len; i++)
18585 tree it = (*v_decls)[i];
18586 bool is_var = TREE_CODE (it) == VAR_DECL;
18587 bool is_link_var
18588 = is_var
18589 #ifdef ACCEL_COMPILER
18590 && DECL_HAS_VALUE_EXPR_P (it)
18591 #endif
18592 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18594 tree size = NULL_TREE;
18595 if (is_var)
18596 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18598 tree addr;
18599 if (!is_link_var)
18600 addr = build_fold_addr_expr (it);
18601 else
18603 #ifdef ACCEL_COMPILER
18604 /* For "omp declare target link" vars add address of the pointer to
18605 the target table, instead of address of the var. */
18606 tree value_expr = DECL_VALUE_EXPR (it);
18607 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18608 varpool_node::finalize_decl (link_ptr_decl);
18609 addr = build_fold_addr_expr (link_ptr_decl);
18610 #else
18611 addr = build_fold_addr_expr (it);
18612 #endif
18614 /* Most significant bit of the size marks "omp declare target link"
18615 vars in host and target tables. */
18616 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18617 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18618 * BITS_PER_UNIT - 1);
18619 size = wide_int_to_tree (const_ptr_type_node, isize);
18622 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18623 if (is_var)
18624 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18628 /* Create new symbols containing (address, size) pairs for global variables,
18629 marked with "omp declare target" attribute, as well as addresses for the
18630 functions, which are outlined offloading regions. */
18631 void
18632 omp_finish_file (void)
18634 unsigned num_funcs = vec_safe_length (offload_funcs);
18635 unsigned num_vars = vec_safe_length (offload_vars);
18637 if (num_funcs == 0 && num_vars == 0)
18638 return;
18640 if (targetm_common.have_named_sections)
18642 vec<constructor_elt, va_gc> *v_f, *v_v;
18643 vec_alloc (v_f, num_funcs);
18644 vec_alloc (v_v, num_vars * 2);
18646 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18647 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18649 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18650 num_vars * 2);
18651 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18652 num_funcs);
18653 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18654 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18655 tree ctor_v = build_constructor (vars_decl_type, v_v);
18656 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18657 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18658 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18659 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18660 get_identifier (".offload_func_table"),
18661 funcs_decl_type);
18662 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18663 get_identifier (".offload_var_table"),
18664 vars_decl_type);
18665 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18666 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18667 otherwise a joint table in a binary will contain padding between
18668 tables from multiple object files. */
18669 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18670 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18671 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18672 DECL_INITIAL (funcs_decl) = ctor_f;
18673 DECL_INITIAL (vars_decl) = ctor_v;
18674 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18675 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18677 varpool_node::finalize_decl (vars_decl);
18678 varpool_node::finalize_decl (funcs_decl);
18680 else
18682 for (unsigned i = 0; i < num_funcs; i++)
18684 tree it = (*offload_funcs)[i];
18685 targetm.record_offload_symbol (it);
18687 for (unsigned i = 0; i < num_vars; i++)
18689 tree it = (*offload_vars)[i];
18690 targetm.record_offload_symbol (it);
18695 /* Find the number of threads (POS = false), or thread number (POS =
18696 true) for an OpenACC region partitioned as MASK. Setup code
18697 required for the calculation is added to SEQ. */
18699 static tree
18700 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18702 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18703 unsigned ix;
18705 /* Start at gang level, and examine relevant dimension indices. */
18706 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18707 if (GOMP_DIM_MASK (ix) & mask)
18709 tree arg = build_int_cst (unsigned_type_node, ix);
18711 if (res)
18713 /* We had an outer index, so scale that by the size of
18714 this dimension. */
18715 tree n = create_tmp_var (integer_type_node);
18716 gimple *call
18717 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18719 gimple_call_set_lhs (call, n);
18720 gimple_seq_add_stmt (seq, call);
18721 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18723 if (pos)
18725 /* Determine index in this dimension. */
18726 tree id = create_tmp_var (integer_type_node);
18727 gimple *call = gimple_build_call_internal
18728 (IFN_GOACC_DIM_POS, 1, arg);
18730 gimple_call_set_lhs (call, id);
18731 gimple_seq_add_stmt (seq, call);
18732 if (res)
18733 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18734 else
18735 res = id;
18739 if (res == NULL_TREE)
18740 res = integer_zero_node;
18742 return res;
18745 /* Transform IFN_GOACC_LOOP calls to actual code. See
18746 expand_oacc_for for where these are generated. At the vector
18747 level, we stride loops, such that each member of a warp will
18748 operate on adjacent iterations. At the worker and gang level,
18749 each gang/warp executes a set of contiguous iterations. Chunking
18750 can override this such that each iteration engine executes a
18751 contiguous chunk, and then moves on to stride to the next chunk. */
18753 static void
18754 oacc_xform_loop (gcall *call)
18756 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18757 enum ifn_goacc_loop_kind code
18758 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18759 tree dir = gimple_call_arg (call, 1);
18760 tree range = gimple_call_arg (call, 2);
18761 tree step = gimple_call_arg (call, 3);
18762 tree chunk_size = NULL_TREE;
18763 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18764 tree lhs = gimple_call_lhs (call);
18765 tree type = TREE_TYPE (lhs);
18766 tree diff_type = TREE_TYPE (range);
18767 tree r = NULL_TREE;
18768 gimple_seq seq = NULL;
18769 bool chunking = false, striding = true;
18770 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18771 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18773 #ifdef ACCEL_COMPILER
18774 chunk_size = gimple_call_arg (call, 4);
18775 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18776 || integer_zerop (chunk_size)) /* Default (also static). */
18778 /* If we're at the gang level, we want each to execute a
18779 contiguous run of iterations. Otherwise we want each element
18780 to stride. */
18781 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18782 chunking = false;
18784 else
18786 /* Chunk of size 1 is striding. */
18787 striding = integer_onep (chunk_size);
18788 chunking = !striding;
18790 #endif
18792 /* striding=true, chunking=true
18793 -> invalid.
18794 striding=true, chunking=false
18795 -> chunks=1
18796 striding=false,chunking=true
18797 -> chunks=ceil (range/(chunksize*threads*step))
18798 striding=false,chunking=false
18799 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18800 push_gimplify_context (true);
18802 switch (code)
18804 default: gcc_unreachable ();
18806 case IFN_GOACC_LOOP_CHUNKS:
18807 if (!chunking)
18808 r = build_int_cst (type, 1);
18809 else
18811 /* chunk_max
18812 = (range - dir) / (chunks * step * num_threads) + dir */
18813 tree per = oacc_thread_numbers (false, mask, &seq);
18814 per = fold_convert (type, per);
18815 chunk_size = fold_convert (type, chunk_size);
18816 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18817 per = fold_build2 (MULT_EXPR, type, per, step);
18818 r = build2 (MINUS_EXPR, type, range, dir);
18819 r = build2 (PLUS_EXPR, type, r, per);
18820 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18822 break;
18824 case IFN_GOACC_LOOP_STEP:
18826 /* If striding, step by the entire compute volume, otherwise
18827 step by the inner volume. */
18828 unsigned volume = striding ? mask : inner_mask;
18830 r = oacc_thread_numbers (false, volume, &seq);
18831 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18833 break;
18835 case IFN_GOACC_LOOP_OFFSET:
18836 if (striding)
18838 r = oacc_thread_numbers (true, mask, &seq);
18839 r = fold_convert (diff_type, r);
18841 else
18843 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18844 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18845 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18846 inner_size, outer_size);
18848 volume = fold_convert (diff_type, volume);
18849 if (chunking)
18850 chunk_size = fold_convert (diff_type, chunk_size);
18851 else
18853 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18855 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18856 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18857 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18860 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18861 fold_convert (diff_type, inner_size));
18862 r = oacc_thread_numbers (true, outer_mask, &seq);
18863 r = fold_convert (diff_type, r);
18864 r = build2 (MULT_EXPR, diff_type, r, span);
18866 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18867 inner = fold_convert (diff_type, inner);
18868 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18870 if (chunking)
18872 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18873 tree per
18874 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18875 per = build2 (MULT_EXPR, diff_type, per, chunk);
18877 r = build2 (PLUS_EXPR, diff_type, r, per);
18880 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18881 if (type != diff_type)
18882 r = fold_convert (type, r);
18883 break;
18885 case IFN_GOACC_LOOP_BOUND:
18886 if (striding)
18887 r = range;
18888 else
18890 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18891 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18892 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18893 inner_size, outer_size);
18895 volume = fold_convert (diff_type, volume);
18896 if (chunking)
18897 chunk_size = fold_convert (diff_type, chunk_size);
18898 else
18900 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18902 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18903 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18904 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18907 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18908 fold_convert (diff_type, inner_size));
18910 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18912 tree offset = gimple_call_arg (call, 6);
18913 r = build2 (PLUS_EXPR, diff_type, r,
18914 fold_convert (diff_type, offset));
18915 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18916 diff_type, r, range);
18918 if (diff_type != type)
18919 r = fold_convert (type, r);
18920 break;
18923 gimplify_assign (lhs, r, &seq);
18925 pop_gimplify_context (NULL);
18927 gsi_replace_with_seq (&gsi, seq, true);
18930 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18931 raw attribute. DIMS is an array of dimensions, which is returned.
18932 Returns the function level dimensionality -- the level at which an
18933 offload routine wishes to partition a loop. */
18935 static int
18936 oacc_validate_dims (tree fn, tree attrs, int *dims)
18938 tree purpose[GOMP_DIM_MAX];
18939 unsigned ix;
18940 tree pos = TREE_VALUE (attrs);
18941 int fn_level = -1;
18943 /* Make sure the attribute creator attached the dimension
18944 information. */
18945 gcc_assert (pos);
18947 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18949 purpose[ix] = TREE_PURPOSE (pos);
18951 if (purpose[ix])
18953 if (integer_zerop (purpose[ix]))
18954 fn_level = ix + 1;
18955 else if (fn_level < 0)
18956 fn_level = ix;
18959 tree val = TREE_VALUE (pos);
18960 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18961 pos = TREE_CHAIN (pos);
18964 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18966 /* Default anything left to 1. */
18967 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18968 if (dims[ix] < 0)
18970 dims[ix] = 1;
18971 changed = true;
18974 if (changed)
18976 /* Replace the attribute with new values. */
18977 pos = NULL_TREE;
18978 for (ix = GOMP_DIM_MAX; ix--;)
18979 pos = tree_cons (purpose[ix],
18980 build_int_cst (integer_type_node, dims[ix]),
18981 pos);
18982 replace_oacc_fn_attrib (fn, pos);
18985 return fn_level;
18988 /* Create an empty OpenACC loop structure at LOC. */
18990 static oacc_loop *
18991 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18993 oacc_loop *loop = XCNEW (oacc_loop);
18995 loop->parent = parent;
18996 loop->child = loop->sibling = NULL;
18998 if (parent)
19000 loop->sibling = parent->child;
19001 parent->child = loop;
19004 loop->loc = loc;
19005 loop->marker = NULL;
19006 memset (loop->heads, 0, sizeof (loop->heads));
19007 memset (loop->tails, 0, sizeof (loop->tails));
19008 loop->routine = NULL_TREE;
19010 loop->mask = loop->flags = 0;
19011 loop->chunk_size = 0;
19012 loop->head_end = NULL;
19014 return loop;
19017 /* Create an outermost, dummy OpenACC loop for offloaded function
19018 DECL. */
19020 static oacc_loop *
19021 new_oacc_loop_outer (tree decl)
19023 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
19026 /* Start a new OpenACC loop structure beginning at head marker HEAD.
19027 Link into PARENT loop. Return the new loop. */
19029 static oacc_loop *
19030 new_oacc_loop (oacc_loop *parent, gcall *marker)
19032 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
19034 loop->marker = marker;
19036 /* TODO: This is where device_type flattening would occur for the loop
19037 flags. */
19039 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
19041 tree chunk_size = integer_zero_node;
19042 if (loop->flags & OLF_GANG_STATIC)
19043 chunk_size = gimple_call_arg (marker, 4);
19044 loop->chunk_size = chunk_size;
19046 return loop;
19049 /* Create a dummy loop encompassing a call to a openACC routine.
19050 Extract the routine's partitioning requirements. */
19052 static void
19053 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
19055 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
19056 int dims[GOMP_DIM_MAX];
19057 int level = oacc_validate_dims (decl, attrs, dims);
19059 gcc_assert (level >= 0);
19061 loop->marker = call;
19062 loop->routine = decl;
19063 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
19064 ^ (GOMP_DIM_MASK (level) - 1));
19067 /* Finish off the current OpenACC loop ending at tail marker TAIL.
19068 Return the parent loop. */
19070 static oacc_loop *
19071 finish_oacc_loop (oacc_loop *loop)
19073 return loop->parent;
19076 /* Free all OpenACC loop structures within LOOP (inclusive). */
19078 static void
19079 free_oacc_loop (oacc_loop *loop)
19081 if (loop->sibling)
19082 free_oacc_loop (loop->sibling);
19083 if (loop->child)
19084 free_oacc_loop (loop->child);
19086 free (loop);
19089 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19091 static void
19092 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19093 const char *title, int level)
19095 enum ifn_unique_kind kind
19096 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19098 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19099 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19101 gimple *stmt = gsi_stmt (gsi);
19103 if (is_gimple_call (stmt)
19104 && gimple_call_internal_p (stmt)
19105 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19107 enum ifn_unique_kind k
19108 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19109 (gimple_call_arg (stmt, 0)));
19111 if (k == kind && stmt != from)
19112 break;
19114 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19116 gsi_next (&gsi);
19117 while (gsi_end_p (gsi))
19118 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19122 /* Dump OpenACC loops LOOP, its siblings and its children. */
19124 static void
19125 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19127 int ix;
19129 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19130 loop->flags, loop->mask,
19131 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19133 if (loop->marker)
19134 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19136 if (loop->routine)
19137 fprintf (file, "%*sRoutine %s:%u:%s\n",
19138 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19139 DECL_SOURCE_LINE (loop->routine),
19140 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19142 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19143 if (loop->heads[ix])
19144 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19145 for (ix = GOMP_DIM_MAX; ix--;)
19146 if (loop->tails[ix])
19147 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19149 if (loop->child)
19150 dump_oacc_loop (file, loop->child, depth + 1);
19151 if (loop->sibling)
19152 dump_oacc_loop (file, loop->sibling, depth);
19155 void debug_oacc_loop (oacc_loop *);
19157 /* Dump loops to stderr. */
19159 DEBUG_FUNCTION void
19160 debug_oacc_loop (oacc_loop *loop)
19162 dump_oacc_loop (stderr, loop, 0);
19165 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19166 structures as we go. By construction these loops are properly
19167 nested. */
19169 static void
19170 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19172 int marker = 0;
19173 int remaining = 0;
19175 if (bb->flags & BB_VISITED)
19176 return;
19178 follow:
19179 bb->flags |= BB_VISITED;
19181 /* Scan for loop markers. */
19182 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19183 gsi_next (&gsi))
19185 gimple *stmt = gsi_stmt (gsi);
19187 if (!is_gimple_call (stmt))
19188 continue;
19190 gcall *call = as_a <gcall *> (stmt);
19192 /* If this is a routine, make a dummy loop for it. */
19193 if (tree decl = gimple_call_fndecl (call))
19194 if (tree attrs = get_oacc_fn_attrib (decl))
19196 gcc_assert (!marker);
19197 new_oacc_loop_routine (loop, call, decl, attrs);
19200 if (!gimple_call_internal_p (call))
19201 continue;
19203 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
19204 continue;
19206 enum ifn_unique_kind kind
19207 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19208 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19209 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19211 if (gimple_call_num_args (call) == 2)
19213 gcc_assert (marker && !remaining);
19214 marker = 0;
19215 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19216 loop = finish_oacc_loop (loop);
19217 else
19218 loop->head_end = call;
19220 else
19222 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19224 if (!marker)
19226 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19227 loop = new_oacc_loop (loop, call);
19228 remaining = count;
19230 gcc_assert (count == remaining);
19231 if (remaining)
19233 remaining--;
19234 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19235 loop->heads[marker] = call;
19236 else
19237 loop->tails[remaining] = call;
19239 marker++;
19243 if (remaining || marker)
19245 bb = single_succ (bb);
19246 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19247 goto follow;
19250 /* Walk successor blocks. */
19251 edge e;
19252 edge_iterator ei;
19254 FOR_EACH_EDGE (e, ei, bb->succs)
19255 oacc_loop_discover_walk (loop, e->dest);
19258 /* LOOP is the first sibling. Reverse the order in place and return
19259 the new first sibling. Recurse to child loops. */
19261 static oacc_loop *
19262 oacc_loop_sibling_nreverse (oacc_loop *loop)
19264 oacc_loop *last = NULL;
19267 if (loop->child)
19268 loop->child = oacc_loop_sibling_nreverse (loop->child);
19270 oacc_loop *next = loop->sibling;
19271 loop->sibling = last;
19272 last = loop;
19273 loop = next;
19275 while (loop);
19277 return last;
19280 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19281 the current function. */
19283 static oacc_loop *
19284 oacc_loop_discovery ()
19286 basic_block bb;
19288 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19289 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19291 /* The siblings were constructed in reverse order, reverse them so
19292 that diagnostics come out in an unsurprising order. */
19293 top = oacc_loop_sibling_nreverse (top);
19295 /* Reset the visited flags. */
19296 FOR_ALL_BB_FN (bb, cfun)
19297 bb->flags &= ~BB_VISITED;
19299 return top;
19302 /* Transform the abstract internal function markers starting at FROM
19303 to be for partitioning level LEVEL. Stop when we meet another HEAD
19304 or TAIL marker. */
19306 static void
19307 oacc_loop_xform_head_tail (gcall *from, int level)
19309 enum ifn_unique_kind kind
19310 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19311 tree replacement = build_int_cst (unsigned_type_node, level);
19313 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19315 gimple *stmt = gsi_stmt (gsi);
19317 if (is_gimple_call (stmt)
19318 && gimple_call_internal_p (stmt)
19319 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19321 enum ifn_unique_kind k
19322 = ((enum ifn_unique_kind)
19323 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19325 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19326 *gimple_call_arg_ptr (stmt, 2) = replacement;
19327 else if (k == kind && stmt != from)
19328 break;
19330 else if (is_gimple_call (stmt)
19331 && gimple_call_internal_p (stmt)
19332 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19333 *gimple_call_arg_ptr (stmt, 3) = replacement;
19335 gsi_next (&gsi);
19336 while (gsi_end_p (gsi))
19337 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19341 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19342 determined partitioning mask and chunking argument. */
19344 static void
19345 oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19347 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19349 for (;;)
19351 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19353 gimple *stmt = gsi_stmt (gsi);
19355 if (!is_gimple_call (stmt))
19356 continue;
19358 gcall *call = as_a <gcall *> (stmt);
19360 if (!gimple_call_internal_p (call))
19361 continue;
19363 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19364 continue;
19366 *gimple_call_arg_ptr (call, 5) = mask_arg;
19367 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19368 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19369 == IFN_GOACC_LOOP_BOUND)
19370 return;
19373 /* If we didn't see LOOP_BOUND, it should be in the single
19374 successor block. */
19375 basic_block bb = single_succ (gsi_bb (gsi));
19376 gsi = gsi_start_bb (bb);
19380 /* Process the discovered OpenACC loops, setting the correct
19381 partitioning level etc. */
19383 static void
19384 oacc_loop_process (oacc_loop *loop)
19386 if (loop->child)
19387 oacc_loop_process (loop->child);
19389 if (loop->mask && !loop->routine)
19391 int ix;
19392 unsigned mask = loop->mask;
19393 unsigned dim = GOMP_DIM_GANG;
19394 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19395 tree chunk_arg = loop->chunk_size;
19397 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19399 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19401 gcc_assert (mask);
19403 while (!(GOMP_DIM_MASK (dim) & mask))
19404 dim++;
19406 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19407 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19409 mask ^= GOMP_DIM_MASK (dim);
19413 if (loop->sibling)
19414 oacc_loop_process (loop->sibling);
19417 /* Walk the OpenACC loop heirarchy checking and assigning the
19418 programmer-specified partitionings. OUTER_MASK is the partitioning
19419 this loop is contained within. Return true if we contain an
19420 auto-partitionable loop. */
19422 static bool
19423 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19425 unsigned this_mask = loop->mask;
19426 bool has_auto = false;
19427 bool noisy = true;
19429 #ifdef ACCEL_COMPILER
19430 /* When device_type is supported, we want the device compiler to be
19431 noisy, if the loop parameters are device_type-specific. */
19432 noisy = false;
19433 #endif
19435 if (!loop->routine)
19437 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19438 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19440 this_mask = ((loop->flags >> OLF_DIM_BASE)
19441 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19443 if ((this_mask != 0) + auto_par + seq_par > 1)
19445 if (noisy)
19446 error_at (loop->loc,
19447 seq_par
19448 ? "%<seq%> overrides other OpenACC loop specifiers"
19449 : "%<auto%> conflicts with other OpenACC loop specifiers");
19450 auto_par = false;
19451 loop->flags &= ~OLF_AUTO;
19452 if (seq_par)
19454 loop->flags &=
19455 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19456 this_mask = 0;
19459 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19460 has_auto = true;
19463 if (this_mask & outer_mask)
19465 const oacc_loop *outer;
19466 for (outer = loop->parent; outer; outer = outer->parent)
19467 if (outer->mask & this_mask)
19468 break;
19470 if (noisy)
19472 if (outer)
19474 error_at (loop->loc,
19475 "%s uses same OpenACC parallelism as containing loop",
19476 loop->routine ? "routine call" : "inner loop");
19477 inform (outer->loc, "containing loop here");
19479 else
19480 error_at (loop->loc,
19481 "%s uses OpenACC parallelism disallowed by containing routine",
19482 loop->routine ? "routine call" : "loop");
19484 if (loop->routine)
19485 inform (DECL_SOURCE_LOCATION (loop->routine),
19486 "routine %qD declared here", loop->routine);
19488 this_mask &= ~outer_mask;
19490 else
19492 unsigned outermost = this_mask & -this_mask;
19494 if (outermost && outermost <= outer_mask)
19496 if (noisy)
19498 error_at (loop->loc,
19499 "incorrectly nested OpenACC loop parallelism");
19501 const oacc_loop *outer;
19502 for (outer = loop->parent;
19503 outer->flags && outer->flags < outermost;
19504 outer = outer->parent)
19505 continue;
19506 inform (outer->loc, "containing loop here");
19509 this_mask &= ~outermost;
19513 loop->mask = this_mask;
19515 if (loop->child
19516 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19517 has_auto = true;
19519 if (loop->sibling
19520 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19521 has_auto = true;
19523 return has_auto;
19526 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19527 OUTER_MASK is the partitioning this loop is contained within.
19528 Return the cumulative partitioning used by this loop, siblings and
19529 children. */
19531 static unsigned
19532 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19534 unsigned inner_mask = 0;
19535 bool noisy = true;
19537 #ifdef ACCEL_COMPILER
19538 /* When device_type is supported, we want the device compiler to be
19539 noisy, if the loop parameters are device_type-specific. */
19540 noisy = false;
19541 #endif
19543 if (loop->child)
19544 inner_mask |= oacc_loop_auto_partitions (loop->child,
19545 outer_mask | loop->mask);
19547 if ((loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT))
19549 unsigned this_mask = 0;
19551 /* Determine the outermost partitioning used within this loop. */
19552 this_mask = inner_mask | GOMP_DIM_MASK (GOMP_DIM_MAX);
19553 this_mask = (this_mask & -this_mask);
19555 /* Pick the partitioning just inside that one. */
19556 this_mask >>= 1;
19558 /* And avoid picking one use by an outer loop. */
19559 this_mask &= ~outer_mask;
19561 if (!this_mask && noisy)
19562 warning_at (loop->loc, 0,
19563 "insufficient partitioning available to parallelize loop");
19565 loop->mask = this_mask;
19567 inner_mask |= loop->mask;
19569 if (loop->sibling)
19570 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19572 return inner_mask;
19575 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19576 axes. */
19578 static void
19579 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19581 if (oacc_loop_fixed_partitions (loop, outer_mask))
19582 oacc_loop_auto_partitions (loop, outer_mask);
19585 /* Default fork/join early expander. Delete the function calls if
19586 there is no RTL expander. */
19588 bool
19589 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19590 const int *ARG_UNUSED (dims), bool is_fork)
19592 if (is_fork)
19593 return targetm.have_oacc_fork ();
19594 else
19595 return targetm.have_oacc_join ();
19598 /* Default goacc.reduction early expander.
19600 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19601 If RES_PTR is not integer-zerop:
19602 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19603 TEARDOWN - emit '*RES_PTR = VAR'
19604 If LHS is not NULL
19605 emit 'LHS = VAR' */
19607 void
19608 default_goacc_reduction (gcall *call)
19610 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19611 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19612 tree lhs = gimple_call_lhs (call);
19613 tree var = gimple_call_arg (call, 2);
19614 gimple_seq seq = NULL;
19616 if (code == IFN_GOACC_REDUCTION_SETUP
19617 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19619 /* Setup and Teardown need to copy from/to the receiver object,
19620 if there is one. */
19621 tree ref_to_res = gimple_call_arg (call, 1);
19623 if (!integer_zerop (ref_to_res))
19625 tree dst = build_simple_mem_ref (ref_to_res);
19626 tree src = var;
19628 if (code == IFN_GOACC_REDUCTION_SETUP)
19630 src = dst;
19631 dst = lhs;
19632 lhs = NULL;
19634 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19638 /* Copy VAR to LHS, if there is an LHS. */
19639 if (lhs)
19640 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19642 gsi_replace_with_seq (&gsi, seq, true);
19645 /* Main entry point for oacc transformations which run on the device
19646 compiler after LTO, so we know what the target device is at this
19647 point (including the host fallback). */
19649 static unsigned int
19650 execute_oacc_device_lower ()
19652 tree attrs = get_oacc_fn_attrib (current_function_decl);
19653 int dims[GOMP_DIM_MAX];
19655 if (!attrs)
19656 /* Not an offloaded function. */
19657 return 0;
19659 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19661 /* Discover, partition and process the loops. */
19662 oacc_loop *loops = oacc_loop_discovery ();
19663 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19664 oacc_loop_partition (loops, outer_mask);
19665 oacc_loop_process (loops);
19666 if (dump_file)
19668 fprintf (dump_file, "OpenACC loops\n");
19669 dump_oacc_loop (dump_file, loops, 0);
19670 fprintf (dump_file, "\n");
19673 /* Offloaded targets may introduce new basic blocks, which require
19674 dominance information to update SSA. */
19675 calculate_dominance_info (CDI_DOMINATORS);
19677 /* Now lower internal loop functions to target-specific code
19678 sequences. */
19679 basic_block bb;
19680 FOR_ALL_BB_FN (bb, cfun)
19681 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19683 gimple *stmt = gsi_stmt (gsi);
19684 if (!is_gimple_call (stmt))
19686 gsi_next (&gsi);
19687 continue;
19690 gcall *call = as_a <gcall *> (stmt);
19691 if (!gimple_call_internal_p (call))
19693 gsi_next (&gsi);
19694 continue;
19697 /* Rewind to allow rescan. */
19698 gsi_prev (&gsi);
19699 bool rescan = false, remove = false;
19700 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19702 switch (ifn_code)
19704 default: break;
19706 case IFN_GOACC_LOOP:
19707 oacc_xform_loop (call);
19708 rescan = true;
19709 break;
19711 case IFN_GOACC_REDUCTION:
19712 /* Mark the function for SSA renaming. */
19713 mark_virtual_operands_for_renaming (cfun);
19715 /* If the level is -1, this ended up being an unused
19716 axis. Handle as a default. */
19717 if (integer_minus_onep (gimple_call_arg (call, 3)))
19718 default_goacc_reduction (call);
19719 else
19720 targetm.goacc.reduction (call);
19721 rescan = true;
19722 break;
19724 case IFN_UNIQUE:
19726 enum ifn_unique_kind kind
19727 = ((enum ifn_unique_kind)
19728 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19730 switch (kind)
19732 default:
19733 gcc_unreachable ();
19735 case IFN_UNIQUE_OACC_FORK:
19736 case IFN_UNIQUE_OACC_JOIN:
19737 if (integer_minus_onep (gimple_call_arg (call, 2)))
19738 remove = true;
19739 else if (!targetm.goacc.fork_join
19740 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19741 remove = true;
19742 break;
19744 case IFN_UNIQUE_OACC_HEAD_MARK:
19745 case IFN_UNIQUE_OACC_TAIL_MARK:
19746 remove = true;
19747 break;
19749 break;
19753 if (gsi_end_p (gsi))
19754 /* We rewound past the beginning of the BB. */
19755 gsi = gsi_start_bb (bb);
19756 else
19757 /* Undo the rewind. */
19758 gsi_next (&gsi);
19760 if (remove)
19762 if (gimple_vdef (call))
19763 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19764 if (gimple_call_lhs (call))
19766 /* Propagate the data dependency var. */
19767 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19768 gimple_call_arg (call, 1));
19769 gsi_replace (&gsi, ass, false);
19771 else
19772 gsi_remove (&gsi, true);
19774 else if (!rescan)
19775 /* If not rescanning, advance over the call. */
19776 gsi_next (&gsi);
19779 free_oacc_loop (loops);
19781 return 0;
19784 /* Default launch dimension validator. Force everything to 1. A
19785 backend that wants to provide larger dimensions must override this
19786 hook. */
19788 bool
19789 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19790 int ARG_UNUSED (fn_level))
19792 bool changed = false;
19794 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19796 if (dims[ix] != 1)
19798 dims[ix] = 1;
19799 changed = true;
19803 return changed;
19806 /* Default dimension bound is unknown on accelerator and 1 on host. */
19809 default_goacc_dim_limit (int ARG_UNUSED (axis))
19811 #ifdef ACCEL_COMPILER
19812 return 0;
19813 #else
19814 return 1;
19815 #endif
19818 namespace {
19820 const pass_data pass_data_oacc_device_lower =
19822 GIMPLE_PASS, /* type */
19823 "oaccdevlow", /* name */
19824 OPTGROUP_NONE, /* optinfo_flags */
19825 TV_NONE, /* tv_id */
19826 PROP_cfg, /* properties_required */
19827 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19828 0, /* properties_destroyed */
19829 0, /* todo_flags_start */
19830 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19833 class pass_oacc_device_lower : public gimple_opt_pass
19835 public:
19836 pass_oacc_device_lower (gcc::context *ctxt)
19837 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19840 /* opt_pass methods: */
19841 virtual unsigned int execute (function *)
19843 bool gate = flag_openacc != 0;
19845 if (!gate)
19846 return 0;
19848 return execute_oacc_device_lower ();
19851 }; // class pass_oacc_device_lower
19853 } // anon namespace
19855 gimple_opt_pass *
19856 make_pass_oacc_device_lower (gcc::context *ctxt)
19858 return new pass_oacc_device_lower (ctxt);
19861 /* "omp declare target link" handling pass. */
19863 namespace {
19865 const pass_data pass_data_omp_target_link =
19867 GIMPLE_PASS, /* type */
19868 "omptargetlink", /* name */
19869 OPTGROUP_NONE, /* optinfo_flags */
19870 TV_NONE, /* tv_id */
19871 PROP_ssa, /* properties_required */
19872 0, /* properties_provided */
19873 0, /* properties_destroyed */
19874 0, /* todo_flags_start */
19875 TODO_update_ssa, /* todo_flags_finish */
19878 class pass_omp_target_link : public gimple_opt_pass
19880 public:
19881 pass_omp_target_link (gcc::context *ctxt)
19882 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19885 /* opt_pass methods: */
19886 virtual bool gate (function *fun)
19888 #ifdef ACCEL_COMPILER
19889 tree attrs = DECL_ATTRIBUTES (fun->decl);
19890 return lookup_attribute ("omp declare target", attrs)
19891 || lookup_attribute ("omp target entrypoint", attrs);
19892 #else
19893 (void) fun;
19894 return false;
19895 #endif
19898 virtual unsigned execute (function *);
19901 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19903 static tree
19904 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19906 tree t = *tp;
19908 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19909 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19911 *walk_subtrees = 0;
19912 return t;
19915 return NULL_TREE;
19918 unsigned
19919 pass_omp_target_link::execute (function *fun)
19921 basic_block bb;
19922 FOR_EACH_BB_FN (bb, fun)
19924 gimple_stmt_iterator gsi;
19925 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19926 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19927 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19930 return 0;
19933 } // anon namespace
19935 gimple_opt_pass *
19936 make_pass_omp_target_link (gcc::context *ctxt)
19938 return new pass_omp_target_link (ctxt);
19941 #include "gt-omp-low.h"