Remove assert in get_def_bb_for_const
[official-gcc.git] / gcc / omp-low.c
bloba11f44b84a7929283352f42b4c66f580ce670edc
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"
83 #include "symbol-summary.h"
84 #include "hsa.h"
85 #include "params.h"
87 /* Lowering of OMP parallel and workshare constructs proceeds in two
88 phases. The first phase scans the function looking for OMP statements
89 and then for variables that must be replaced to satisfy data sharing
90 clauses. The second phase expands code for the constructs, as well as
91 re-gimplifying things when variables have been replaced with complex
92 expressions.
94 Final code generation is done by pass_expand_omp. The flowgraph is
95 scanned for regions which are then moved to a new
96 function, to be invoked by the thread library, or offloaded. */
98 /* OMP region information. Every parallel and workshare
99 directive is enclosed between two markers, the OMP_* directive
100 and a corresponding GIMPLE_OMP_RETURN statement. */
102 struct omp_region
104 /* The enclosing region. */
105 struct omp_region *outer;
107 /* First child region. */
108 struct omp_region *inner;
110 /* Next peer region. */
111 struct omp_region *next;
113 /* Block containing the omp directive as its last stmt. */
114 basic_block entry;
116 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
117 basic_block exit;
119 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
120 basic_block cont;
122 /* If this is a combined parallel+workshare region, this is a list
123 of additional arguments needed by the combined parallel+workshare
124 library call. */
125 vec<tree, va_gc> *ws_args;
127 /* The code for the omp directive of this region. */
128 enum gimple_code type;
130 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
131 enum omp_clause_schedule_kind sched_kind;
133 /* Schedule modifiers. */
134 unsigned char sched_modifiers;
136 /* True if this is a combined parallel+workshare region. */
137 bool is_combined_parallel;
139 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
140 a depend clause. */
141 gomp_ordered *ord_stmt;
144 /* Context structure. Used to store information about each parallel
145 directive in the code. */
147 struct omp_context
149 /* This field must be at the beginning, as we do "inheritance": Some
150 callback functions for tree-inline.c (e.g., omp_copy_decl)
151 receive a copy_body_data pointer that is up-casted to an
152 omp_context pointer. */
153 copy_body_data cb;
155 /* The tree of contexts corresponding to the encountered constructs. */
156 struct omp_context *outer;
157 gimple *stmt;
159 /* Map variables to fields in a structure that allows communication
160 between sending and receiving threads. */
161 splay_tree field_map;
162 tree record_type;
163 tree sender_decl;
164 tree receiver_decl;
166 /* These are used just by task contexts, if task firstprivate fn is
167 needed. srecord_type is used to communicate from the thread
168 that encountered the task construct to task firstprivate fn,
169 record_type is allocated by GOMP_task, initialized by task firstprivate
170 fn and passed to the task body fn. */
171 splay_tree sfield_map;
172 tree srecord_type;
174 /* A chain of variables to add to the top-level block surrounding the
175 construct. In the case of a parallel, this is in the child function. */
176 tree block_vars;
178 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
179 barriers should jump to during omplower pass. */
180 tree cancel_label;
182 /* What to do with variables with implicitly determined sharing
183 attributes. */
184 enum omp_clause_default_kind default_kind;
186 /* Nesting depth of this context. Used to beautify error messages re
187 invalid gotos. The outermost ctx is depth 1, with depth 0 being
188 reserved for the main body of the function. */
189 int depth;
191 /* True if this parallel directive is nested within another. */
192 bool is_nested;
194 /* True if this construct can be cancelled. */
195 bool cancellable;
198 /* A structure holding the elements of:
199 for (V = N1; V cond N2; V += STEP) [...] */
201 struct omp_for_data_loop
203 tree v, n1, n2, step;
204 enum tree_code cond_code;
207 /* A structure describing the main elements of a parallel loop. */
209 struct omp_for_data
211 struct omp_for_data_loop loop;
212 tree chunk_size;
213 gomp_for *for_stmt;
214 tree pre, iter_type;
215 int collapse;
216 int ordered;
217 bool have_nowait, have_ordered, simd_schedule;
218 unsigned char sched_modifiers;
219 enum omp_clause_schedule_kind sched_kind;
220 struct omp_for_data_loop *loops;
223 /* Describe the OpenACC looping structure of a function. The entire
224 function is held in a 'NULL' loop. */
226 struct oacc_loop
228 oacc_loop *parent; /* Containing loop. */
230 oacc_loop *child; /* First inner loop. */
232 oacc_loop *sibling; /* Next loop within same parent. */
234 location_t loc; /* Location of the loop start. */
236 gcall *marker; /* Initial head marker. */
238 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
239 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
241 tree routine; /* Pseudo-loop enclosing a routine. */
243 unsigned mask; /* Partitioning mask. */
244 unsigned inner; /* Partitioning of inner loops. */
245 unsigned flags; /* Partitioning flags. */
246 unsigned ifns; /* Contained loop abstraction functions. */
247 tree chunk_size; /* Chunk size. */
248 gcall *head_end; /* Final marker of head sequence. */
251 /* Flags for an OpenACC loop. */
253 enum oacc_loop_flags {
254 OLF_SEQ = 1u << 0, /* Explicitly sequential */
255 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
256 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
257 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
259 /* Explicitly specified loop axes. */
260 OLF_DIM_BASE = 4,
261 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
262 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
263 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
265 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
269 static splay_tree all_contexts;
270 static int taskreg_nesting_level;
271 static int target_nesting_level;
272 static struct omp_region *root_omp_region;
273 static bitmap task_shared_vars;
274 static vec<omp_context *> taskreg_contexts;
275 static bool omp_any_child_fn_dumped;
277 static void scan_omp (gimple_seq *, omp_context *);
278 static tree scan_omp_1_op (tree *, int *, void *);
279 static gphi *find_phi_with_arg_on_edge (tree, edge);
281 #define WALK_SUBSTMTS \
282 case GIMPLE_BIND: \
283 case GIMPLE_TRY: \
284 case GIMPLE_CATCH: \
285 case GIMPLE_EH_FILTER: \
286 case GIMPLE_TRANSACTION: \
287 /* The sub-statements for these should be walked. */ \
288 *handled_ops_p = false; \
289 break;
291 /* Return true if CTX corresponds to an oacc parallel region. */
293 static bool
294 is_oacc_parallel (omp_context *ctx)
296 enum gimple_code outer_type = gimple_code (ctx->stmt);
297 return ((outer_type == GIMPLE_OMP_TARGET)
298 && (gimple_omp_target_kind (ctx->stmt)
299 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
302 /* Return true if CTX corresponds to an oacc kernels region. */
304 static bool
305 is_oacc_kernels (omp_context *ctx)
307 enum gimple_code outer_type = gimple_code (ctx->stmt);
308 return ((outer_type == GIMPLE_OMP_TARGET)
309 && (gimple_omp_target_kind (ctx->stmt)
310 == GF_OMP_TARGET_KIND_OACC_KERNELS));
313 /* If DECL is the artificial dummy VAR_DECL created for non-static
314 data member privatization, return the underlying "this" parameter,
315 otherwise return NULL. */
317 tree
318 omp_member_access_dummy_var (tree decl)
320 if (!VAR_P (decl)
321 || !DECL_ARTIFICIAL (decl)
322 || !DECL_IGNORED_P (decl)
323 || !DECL_HAS_VALUE_EXPR_P (decl)
324 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
325 return NULL_TREE;
327 tree v = DECL_VALUE_EXPR (decl);
328 if (TREE_CODE (v) != COMPONENT_REF)
329 return NULL_TREE;
331 while (1)
332 switch (TREE_CODE (v))
334 case COMPONENT_REF:
335 case MEM_REF:
336 case INDIRECT_REF:
337 CASE_CONVERT:
338 case POINTER_PLUS_EXPR:
339 v = TREE_OPERAND (v, 0);
340 continue;
341 case PARM_DECL:
342 if (DECL_CONTEXT (v) == current_function_decl
343 && DECL_ARTIFICIAL (v)
344 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
345 return v;
346 return NULL_TREE;
347 default:
348 return NULL_TREE;
352 /* Helper for unshare_and_remap, called through walk_tree. */
354 static tree
355 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
357 tree *pair = (tree *) data;
358 if (*tp == pair[0])
360 *tp = unshare_expr (pair[1]);
361 *walk_subtrees = 0;
363 else if (IS_TYPE_OR_DECL_P (*tp))
364 *walk_subtrees = 0;
365 return NULL_TREE;
368 /* Return unshare_expr (X) with all occurrences of FROM
369 replaced with TO. */
371 static tree
372 unshare_and_remap (tree x, tree from, tree to)
374 tree pair[2] = { from, to };
375 x = unshare_expr (x);
376 walk_tree (&x, unshare_and_remap_1, pair, NULL);
377 return x;
380 /* Holds offload tables with decls. */
381 vec<tree, va_gc> *offload_funcs, *offload_vars;
383 /* Convenience function for calling scan_omp_1_op on tree operands. */
385 static inline tree
386 scan_omp_op (tree *tp, omp_context *ctx)
388 struct walk_stmt_info wi;
390 memset (&wi, 0, sizeof (wi));
391 wi.info = ctx;
392 wi.want_locations = true;
394 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
397 static void lower_omp (gimple_seq *, omp_context *);
398 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
399 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
401 /* Find an OMP clause of type KIND within CLAUSES. */
403 tree
404 find_omp_clause (tree clauses, enum omp_clause_code kind)
406 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
407 if (OMP_CLAUSE_CODE (clauses) == kind)
408 return clauses;
410 return NULL_TREE;
413 /* Return true if CTX is for an omp parallel. */
415 static inline bool
416 is_parallel_ctx (omp_context *ctx)
418 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
422 /* Return true if CTX is for an omp task. */
424 static inline bool
425 is_task_ctx (omp_context *ctx)
427 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
431 /* Return true if CTX is for an omp taskloop. */
433 static inline bool
434 is_taskloop_ctx (omp_context *ctx)
436 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
437 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
441 /* Return true if CTX is for an omp parallel or omp task. */
443 static inline bool
444 is_taskreg_ctx (omp_context *ctx)
446 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
450 /* Return true if REGION is a combined parallel+workshare region. */
452 static inline bool
453 is_combined_parallel (struct omp_region *region)
455 return region->is_combined_parallel;
458 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
459 GT_EXPR. */
461 static void
462 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
464 switch (*cond_code)
466 case LT_EXPR:
467 case GT_EXPR:
468 case NE_EXPR:
469 break;
470 case LE_EXPR:
471 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
472 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
473 else
474 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
475 build_int_cst (TREE_TYPE (*n2), 1));
476 *cond_code = LT_EXPR;
477 break;
478 case GE_EXPR:
479 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
480 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
481 else
482 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
483 build_int_cst (TREE_TYPE (*n2), 1));
484 *cond_code = GT_EXPR;
485 break;
486 default:
487 gcc_unreachable ();
491 /* Return the looping step from INCR, extracted from the step of a gimple omp
492 for statement. */
494 static tree
495 get_omp_for_step_from_incr (location_t loc, tree incr)
497 tree step;
498 switch (TREE_CODE (incr))
500 case PLUS_EXPR:
501 step = TREE_OPERAND (incr, 1);
502 break;
503 case POINTER_PLUS_EXPR:
504 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
505 break;
506 case MINUS_EXPR:
507 step = TREE_OPERAND (incr, 1);
508 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
509 break;
510 default:
511 gcc_unreachable ();
513 return step;
516 /* Extract the header elements of parallel loop FOR_STMT and store
517 them into *FD. */
519 static void
520 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
521 struct omp_for_data_loop *loops)
523 tree t, var, *collapse_iter, *collapse_count;
524 tree count = NULL_TREE, iter_type = long_integer_type_node;
525 struct omp_for_data_loop *loop;
526 int i;
527 struct omp_for_data_loop dummy_loop;
528 location_t loc = gimple_location (for_stmt);
529 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
530 bool distribute = gimple_omp_for_kind (for_stmt)
531 == GF_OMP_FOR_KIND_DISTRIBUTE;
532 bool taskloop = gimple_omp_for_kind (for_stmt)
533 == GF_OMP_FOR_KIND_TASKLOOP;
534 tree iterv, countv;
536 fd->for_stmt = for_stmt;
537 fd->pre = NULL;
538 if (gimple_omp_for_collapse (for_stmt) > 1)
539 fd->loops = loops;
540 else
541 fd->loops = &fd->loop;
543 fd->have_nowait = distribute || simd;
544 fd->have_ordered = false;
545 fd->collapse = 1;
546 fd->ordered = 0;
547 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
548 fd->sched_modifiers = 0;
549 fd->chunk_size = NULL_TREE;
550 fd->simd_schedule = false;
551 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
552 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
553 collapse_iter = NULL;
554 collapse_count = NULL;
556 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
557 switch (OMP_CLAUSE_CODE (t))
559 case OMP_CLAUSE_NOWAIT:
560 fd->have_nowait = true;
561 break;
562 case OMP_CLAUSE_ORDERED:
563 fd->have_ordered = true;
564 if (OMP_CLAUSE_ORDERED_EXPR (t))
565 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
566 break;
567 case OMP_CLAUSE_SCHEDULE:
568 gcc_assert (!distribute && !taskloop);
569 fd->sched_kind
570 = (enum omp_clause_schedule_kind)
571 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
572 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
573 & ~OMP_CLAUSE_SCHEDULE_MASK);
574 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
575 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
576 break;
577 case OMP_CLAUSE_DIST_SCHEDULE:
578 gcc_assert (distribute);
579 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
580 break;
581 case OMP_CLAUSE_COLLAPSE:
582 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
583 if (fd->collapse > 1)
585 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
586 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
588 break;
589 default:
590 break;
592 if (fd->ordered && fd->collapse == 1 && loops != NULL)
594 fd->loops = loops;
595 iterv = NULL_TREE;
596 countv = NULL_TREE;
597 collapse_iter = &iterv;
598 collapse_count = &countv;
601 /* FIXME: for now map schedule(auto) to schedule(static).
602 There should be analysis to determine whether all iterations
603 are approximately the same amount of work (then schedule(static)
604 is best) or if it varies (then schedule(dynamic,N) is better). */
605 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
607 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
608 gcc_assert (fd->chunk_size == NULL);
610 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
611 if (taskloop)
612 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
613 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
614 gcc_assert (fd->chunk_size == NULL);
615 else if (fd->chunk_size == NULL)
617 /* We only need to compute a default chunk size for ordered
618 static loops and dynamic loops. */
619 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
620 || fd->have_ordered)
621 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
622 ? integer_zero_node : integer_one_node;
625 int cnt = fd->ordered ? fd->ordered : fd->collapse;
626 for (i = 0; i < cnt; i++)
628 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
629 loop = &fd->loop;
630 else if (loops != NULL)
631 loop = loops + i;
632 else
633 loop = &dummy_loop;
635 loop->v = gimple_omp_for_index (for_stmt, i);
636 gcc_assert (SSA_VAR_P (loop->v));
637 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
638 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
639 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
640 loop->n1 = gimple_omp_for_initial (for_stmt, i);
642 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
643 loop->n2 = gimple_omp_for_final (for_stmt, i);
644 gcc_assert (loop->cond_code != NE_EXPR
645 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
646 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
647 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
649 t = gimple_omp_for_incr (for_stmt, i);
650 gcc_assert (TREE_OPERAND (t, 0) == var);
651 loop->step = get_omp_for_step_from_incr (loc, t);
653 if (simd
654 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
655 && !fd->have_ordered))
657 if (fd->collapse == 1)
658 iter_type = TREE_TYPE (loop->v);
659 else if (i == 0
660 || TYPE_PRECISION (iter_type)
661 < TYPE_PRECISION (TREE_TYPE (loop->v)))
662 iter_type
663 = build_nonstandard_integer_type
664 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
666 else if (iter_type != long_long_unsigned_type_node)
668 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
669 iter_type = long_long_unsigned_type_node;
670 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
671 && TYPE_PRECISION (TREE_TYPE (loop->v))
672 >= TYPE_PRECISION (iter_type))
674 tree n;
676 if (loop->cond_code == LT_EXPR)
677 n = fold_build2_loc (loc,
678 PLUS_EXPR, TREE_TYPE (loop->v),
679 loop->n2, loop->step);
680 else
681 n = loop->n1;
682 if (TREE_CODE (n) != INTEGER_CST
683 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
684 iter_type = long_long_unsigned_type_node;
686 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
687 > TYPE_PRECISION (iter_type))
689 tree n1, n2;
691 if (loop->cond_code == LT_EXPR)
693 n1 = loop->n1;
694 n2 = fold_build2_loc (loc,
695 PLUS_EXPR, TREE_TYPE (loop->v),
696 loop->n2, loop->step);
698 else
700 n1 = fold_build2_loc (loc,
701 MINUS_EXPR, TREE_TYPE (loop->v),
702 loop->n2, loop->step);
703 n2 = loop->n1;
705 if (TREE_CODE (n1) != INTEGER_CST
706 || TREE_CODE (n2) != INTEGER_CST
707 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
708 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
709 iter_type = long_long_unsigned_type_node;
713 if (i >= fd->collapse)
714 continue;
716 if (collapse_count && *collapse_count == NULL)
718 t = fold_binary (loop->cond_code, boolean_type_node,
719 fold_convert (TREE_TYPE (loop->v), loop->n1),
720 fold_convert (TREE_TYPE (loop->v), loop->n2));
721 if (t && integer_zerop (t))
722 count = build_zero_cst (long_long_unsigned_type_node);
723 else if ((i == 0 || count != NULL_TREE)
724 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
725 && TREE_CONSTANT (loop->n1)
726 && TREE_CONSTANT (loop->n2)
727 && TREE_CODE (loop->step) == INTEGER_CST)
729 tree itype = TREE_TYPE (loop->v);
731 if (POINTER_TYPE_P (itype))
732 itype = signed_type_for (itype);
733 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
734 t = fold_build2_loc (loc,
735 PLUS_EXPR, itype,
736 fold_convert_loc (loc, itype, loop->step), t);
737 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
738 fold_convert_loc (loc, itype, loop->n2));
739 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
740 fold_convert_loc (loc, itype, loop->n1));
741 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
742 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
743 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
744 fold_build1_loc (loc, NEGATE_EXPR, itype,
745 fold_convert_loc (loc, itype,
746 loop->step)));
747 else
748 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
749 fold_convert_loc (loc, itype, loop->step));
750 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
751 if (count != NULL_TREE)
752 count = fold_build2_loc (loc,
753 MULT_EXPR, long_long_unsigned_type_node,
754 count, t);
755 else
756 count = t;
757 if (TREE_CODE (count) != INTEGER_CST)
758 count = NULL_TREE;
760 else if (count && !integer_zerop (count))
761 count = NULL_TREE;
765 if (count
766 && !simd
767 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
768 || fd->have_ordered))
770 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
771 iter_type = long_long_unsigned_type_node;
772 else
773 iter_type = long_integer_type_node;
775 else if (collapse_iter && *collapse_iter != NULL)
776 iter_type = TREE_TYPE (*collapse_iter);
777 fd->iter_type = iter_type;
778 if (collapse_iter && *collapse_iter == NULL)
779 *collapse_iter = create_tmp_var (iter_type, ".iter");
780 if (collapse_count && *collapse_count == NULL)
782 if (count)
783 *collapse_count = fold_convert_loc (loc, iter_type, count);
784 else
785 *collapse_count = create_tmp_var (iter_type, ".count");
788 if (fd->collapse > 1 || (fd->ordered && loops))
790 fd->loop.v = *collapse_iter;
791 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
792 fd->loop.n2 = *collapse_count;
793 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
794 fd->loop.cond_code = LT_EXPR;
796 else if (loops)
797 loops[0] = fd->loop;
801 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
802 is the immediate dominator of PAR_ENTRY_BB, return true if there
803 are no data dependencies that would prevent expanding the parallel
804 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
806 When expanding a combined parallel+workshare region, the call to
807 the child function may need additional arguments in the case of
808 GIMPLE_OMP_FOR regions. In some cases, these arguments are
809 computed out of variables passed in from the parent to the child
810 via 'struct .omp_data_s'. For instance:
812 #pragma omp parallel for schedule (guided, i * 4)
813 for (j ...)
815 Is lowered into:
817 # BLOCK 2 (PAR_ENTRY_BB)
818 .omp_data_o.i = i;
819 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
821 # BLOCK 3 (WS_ENTRY_BB)
822 .omp_data_i = &.omp_data_o;
823 D.1667 = .omp_data_i->i;
824 D.1598 = D.1667 * 4;
825 #pragma omp for schedule (guided, D.1598)
827 When we outline the parallel region, the call to the child function
828 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
829 that value is computed *after* the call site. So, in principle we
830 cannot do the transformation.
832 To see whether the code in WS_ENTRY_BB blocks the combined
833 parallel+workshare call, we collect all the variables used in the
834 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
835 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
836 call.
838 FIXME. If we had the SSA form built at this point, we could merely
839 hoist the code in block 3 into block 2 and be done with it. But at
840 this point we don't have dataflow information and though we could
841 hack something up here, it is really not worth the aggravation. */
843 static bool
844 workshare_safe_to_combine_p (basic_block ws_entry_bb)
846 struct omp_for_data fd;
847 gimple *ws_stmt = last_stmt (ws_entry_bb);
849 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
850 return true;
852 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
854 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
856 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
857 return false;
858 if (fd.iter_type != long_integer_type_node)
859 return false;
861 /* FIXME. We give up too easily here. If any of these arguments
862 are not constants, they will likely involve variables that have
863 been mapped into fields of .omp_data_s for sharing with the child
864 function. With appropriate data flow, it would be possible to
865 see through this. */
866 if (!is_gimple_min_invariant (fd.loop.n1)
867 || !is_gimple_min_invariant (fd.loop.n2)
868 || !is_gimple_min_invariant (fd.loop.step)
869 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
870 return false;
872 return true;
876 static int omp_max_vf (void);
878 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
879 presence (SIMD_SCHEDULE). */
881 static tree
882 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
884 if (!simd_schedule)
885 return chunk_size;
887 int vf = omp_max_vf ();
888 if (vf == 1)
889 return chunk_size;
891 tree type = TREE_TYPE (chunk_size);
892 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
893 build_int_cst (type, vf - 1));
894 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
895 build_int_cst (type, -vf));
899 /* Collect additional arguments needed to emit a combined
900 parallel+workshare call. WS_STMT is the workshare directive being
901 expanded. */
903 static vec<tree, va_gc> *
904 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
906 tree t;
907 location_t loc = gimple_location (ws_stmt);
908 vec<tree, va_gc> *ws_args;
910 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
912 struct omp_for_data fd;
913 tree n1, n2;
915 extract_omp_for_data (for_stmt, &fd, NULL);
916 n1 = fd.loop.n1;
917 n2 = fd.loop.n2;
919 if (gimple_omp_for_combined_into_p (for_stmt))
921 tree innerc
922 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
923 OMP_CLAUSE__LOOPTEMP_);
924 gcc_assert (innerc);
925 n1 = OMP_CLAUSE_DECL (innerc);
926 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
927 OMP_CLAUSE__LOOPTEMP_);
928 gcc_assert (innerc);
929 n2 = OMP_CLAUSE_DECL (innerc);
932 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
934 t = fold_convert_loc (loc, long_integer_type_node, n1);
935 ws_args->quick_push (t);
937 t = fold_convert_loc (loc, long_integer_type_node, n2);
938 ws_args->quick_push (t);
940 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
941 ws_args->quick_push (t);
943 if (fd.chunk_size)
945 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
946 t = omp_adjust_chunk_size (t, fd.simd_schedule);
947 ws_args->quick_push (t);
950 return ws_args;
952 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
954 /* Number of sections is equal to the number of edges from the
955 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
956 the exit of the sections region. */
957 basic_block bb = single_succ (gimple_bb (ws_stmt));
958 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
959 vec_alloc (ws_args, 1);
960 ws_args->quick_push (t);
961 return ws_args;
964 gcc_unreachable ();
968 /* Discover whether REGION is a combined parallel+workshare region. */
970 static void
971 determine_parallel_type (struct omp_region *region)
973 basic_block par_entry_bb, par_exit_bb;
974 basic_block ws_entry_bb, ws_exit_bb;
976 if (region == NULL || region->inner == NULL
977 || region->exit == NULL || region->inner->exit == NULL
978 || region->inner->cont == NULL)
979 return;
981 /* We only support parallel+for and parallel+sections. */
982 if (region->type != GIMPLE_OMP_PARALLEL
983 || (region->inner->type != GIMPLE_OMP_FOR
984 && region->inner->type != GIMPLE_OMP_SECTIONS))
985 return;
987 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
988 WS_EXIT_BB -> PAR_EXIT_BB. */
989 par_entry_bb = region->entry;
990 par_exit_bb = region->exit;
991 ws_entry_bb = region->inner->entry;
992 ws_exit_bb = region->inner->exit;
994 if (single_succ (par_entry_bb) == ws_entry_bb
995 && single_succ (ws_exit_bb) == par_exit_bb
996 && workshare_safe_to_combine_p (ws_entry_bb)
997 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
998 || (last_and_only_stmt (ws_entry_bb)
999 && last_and_only_stmt (par_exit_bb))))
1001 gimple *par_stmt = last_stmt (par_entry_bb);
1002 gimple *ws_stmt = last_stmt (ws_entry_bb);
1004 if (region->inner->type == GIMPLE_OMP_FOR)
1006 /* If this is a combined parallel loop, we need to determine
1007 whether or not to use the combined library calls. There
1008 are two cases where we do not apply the transformation:
1009 static loops and any kind of ordered loop. In the first
1010 case, we already open code the loop so there is no need
1011 to do anything else. In the latter case, the combined
1012 parallel loop call would still need extra synchronization
1013 to implement ordered semantics, so there would not be any
1014 gain in using the combined call. */
1015 tree clauses = gimple_omp_for_clauses (ws_stmt);
1016 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1017 if (c == NULL
1018 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1019 == OMP_CLAUSE_SCHEDULE_STATIC)
1020 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1022 region->is_combined_parallel = false;
1023 region->inner->is_combined_parallel = false;
1024 return;
1028 region->is_combined_parallel = true;
1029 region->inner->is_combined_parallel = true;
1030 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1035 /* Return true if EXPR is variable sized. */
1037 static inline bool
1038 is_variable_sized (const_tree expr)
1040 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1043 /* Return true if DECL is a reference type. */
1045 static inline bool
1046 is_reference (tree decl)
1048 return lang_hooks.decls.omp_privatize_by_reference (decl);
1051 /* Return the type of a decl. If the decl is reference type,
1052 return its base type. */
1053 static inline tree
1054 get_base_type (tree decl)
1056 tree type = TREE_TYPE (decl);
1057 if (is_reference (decl))
1058 type = TREE_TYPE (type);
1059 return type;
1062 /* Lookup variables. The "maybe" form
1063 allows for the variable form to not have been entered, otherwise we
1064 assert that the variable must have been entered. */
1066 static inline tree
1067 lookup_decl (tree var, omp_context *ctx)
1069 tree *n = ctx->cb.decl_map->get (var);
1070 return *n;
1073 static inline tree
1074 maybe_lookup_decl (const_tree var, omp_context *ctx)
1076 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1077 return n ? *n : NULL_TREE;
1080 static inline tree
1081 lookup_field (tree var, omp_context *ctx)
1083 splay_tree_node n;
1084 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1085 return (tree) n->value;
1088 static inline tree
1089 lookup_sfield (splay_tree_key key, omp_context *ctx)
1091 splay_tree_node n;
1092 n = splay_tree_lookup (ctx->sfield_map
1093 ? ctx->sfield_map : ctx->field_map, key);
1094 return (tree) n->value;
1097 static inline tree
1098 lookup_sfield (tree var, omp_context *ctx)
1100 return lookup_sfield ((splay_tree_key) var, ctx);
1103 static inline tree
1104 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1106 splay_tree_node n;
1107 n = splay_tree_lookup (ctx->field_map, key);
1108 return n ? (tree) n->value : NULL_TREE;
1111 static inline tree
1112 maybe_lookup_field (tree var, omp_context *ctx)
1114 return maybe_lookup_field ((splay_tree_key) var, ctx);
1117 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1118 the parallel context if DECL is to be shared. */
1120 static bool
1121 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1123 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1124 return true;
1126 /* We can only use copy-in/copy-out semantics for shared variables
1127 when we know the value is not accessible from an outer scope. */
1128 if (shared_ctx)
1130 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1132 /* ??? Trivially accessible from anywhere. But why would we even
1133 be passing an address in this case? Should we simply assert
1134 this to be false, or should we have a cleanup pass that removes
1135 these from the list of mappings? */
1136 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1137 return true;
1139 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1140 without analyzing the expression whether or not its location
1141 is accessible to anyone else. In the case of nested parallel
1142 regions it certainly may be. */
1143 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1144 return true;
1146 /* Do not use copy-in/copy-out for variables that have their
1147 address taken. */
1148 if (TREE_ADDRESSABLE (decl))
1149 return true;
1151 /* lower_send_shared_vars only uses copy-in, but not copy-out
1152 for these. */
1153 if (TREE_READONLY (decl)
1154 || ((TREE_CODE (decl) == RESULT_DECL
1155 || TREE_CODE (decl) == PARM_DECL)
1156 && DECL_BY_REFERENCE (decl)))
1157 return false;
1159 /* Disallow copy-in/out in nested parallel if
1160 decl is shared in outer parallel, otherwise
1161 each thread could store the shared variable
1162 in its own copy-in location, making the
1163 variable no longer really shared. */
1164 if (shared_ctx->is_nested)
1166 omp_context *up;
1168 for (up = shared_ctx->outer; up; up = up->outer)
1169 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1170 break;
1172 if (up)
1174 tree c;
1176 for (c = gimple_omp_taskreg_clauses (up->stmt);
1177 c; c = OMP_CLAUSE_CHAIN (c))
1178 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1179 && OMP_CLAUSE_DECL (c) == decl)
1180 break;
1182 if (c)
1183 goto maybe_mark_addressable_and_ret;
1187 /* For tasks avoid using copy-in/out. As tasks can be
1188 deferred or executed in different thread, when GOMP_task
1189 returns, the task hasn't necessarily terminated. */
1190 if (is_task_ctx (shared_ctx))
1192 tree outer;
1193 maybe_mark_addressable_and_ret:
1194 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1195 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1197 /* Taking address of OUTER in lower_send_shared_vars
1198 might need regimplification of everything that uses the
1199 variable. */
1200 if (!task_shared_vars)
1201 task_shared_vars = BITMAP_ALLOC (NULL);
1202 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1203 TREE_ADDRESSABLE (outer) = 1;
1205 return true;
1209 return false;
1212 /* Construct a new automatic decl similar to VAR. */
1214 static tree
1215 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1217 tree copy = copy_var_decl (var, name, type);
1219 DECL_CONTEXT (copy) = current_function_decl;
1220 DECL_CHAIN (copy) = ctx->block_vars;
1221 /* If VAR is listed in task_shared_vars, it means it wasn't
1222 originally addressable and is just because task needs to take
1223 it's address. But we don't need to take address of privatizations
1224 from that var. */
1225 if (TREE_ADDRESSABLE (var)
1226 && task_shared_vars
1227 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1228 TREE_ADDRESSABLE (copy) = 0;
1229 ctx->block_vars = copy;
1231 return copy;
1234 static tree
1235 omp_copy_decl_1 (tree var, omp_context *ctx)
1237 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1240 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1241 as appropriate. */
1242 static tree
1243 omp_build_component_ref (tree obj, tree field)
1245 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1246 if (TREE_THIS_VOLATILE (field))
1247 TREE_THIS_VOLATILE (ret) |= 1;
1248 if (TREE_READONLY (field))
1249 TREE_READONLY (ret) |= 1;
1250 return ret;
1253 /* Build tree nodes to access the field for VAR on the receiver side. */
1255 static tree
1256 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1258 tree x, field = lookup_field (var, ctx);
1260 /* If the receiver record type was remapped in the child function,
1261 remap the field into the new record type. */
1262 x = maybe_lookup_field (field, ctx);
1263 if (x != NULL)
1264 field = x;
1266 x = build_simple_mem_ref (ctx->receiver_decl);
1267 TREE_THIS_NOTRAP (x) = 1;
1268 x = omp_build_component_ref (x, field);
1269 if (by_ref)
1271 x = build_simple_mem_ref (x);
1272 TREE_THIS_NOTRAP (x) = 1;
1275 return x;
1278 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1279 of a parallel, this is a component reference; for workshare constructs
1280 this is some variable. */
1282 static tree
1283 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1285 tree x;
1287 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1288 x = var;
1289 else if (is_variable_sized (var))
1291 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1292 x = build_outer_var_ref (x, ctx, lastprivate);
1293 x = build_simple_mem_ref (x);
1295 else if (is_taskreg_ctx (ctx))
1297 bool by_ref = use_pointer_for_field (var, NULL);
1298 x = build_receiver_ref (var, by_ref, ctx);
1300 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1301 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1303 /* #pragma omp simd isn't a worksharing construct, and can reference even
1304 private vars in its linear etc. clauses. */
1305 x = NULL_TREE;
1306 if (ctx->outer && is_taskreg_ctx (ctx))
1307 x = lookup_decl (var, ctx->outer);
1308 else if (ctx->outer)
1309 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1310 if (x == NULL_TREE)
1311 x = var;
1313 else if (lastprivate && is_taskloop_ctx (ctx))
1315 gcc_assert (ctx->outer);
1316 splay_tree_node n
1317 = splay_tree_lookup (ctx->outer->field_map,
1318 (splay_tree_key) &DECL_UID (var));
1319 if (n == NULL)
1321 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1322 x = var;
1323 else
1324 x = lookup_decl (var, ctx->outer);
1326 else
1328 tree field = (tree) n->value;
1329 /* If the receiver record type was remapped in the child function,
1330 remap the field into the new record type. */
1331 x = maybe_lookup_field (field, ctx->outer);
1332 if (x != NULL)
1333 field = x;
1335 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1336 x = omp_build_component_ref (x, field);
1337 if (use_pointer_for_field (var, ctx->outer))
1338 x = build_simple_mem_ref (x);
1341 else if (ctx->outer)
1343 omp_context *outer = ctx->outer;
1344 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1346 outer = outer->outer;
1347 gcc_assert (outer
1348 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1350 x = lookup_decl (var, outer);
1352 else if (is_reference (var))
1353 /* This can happen with orphaned constructs. If var is reference, it is
1354 possible it is shared and as such valid. */
1355 x = var;
1356 else if (omp_member_access_dummy_var (var))
1357 x = var;
1358 else
1359 gcc_unreachable ();
1361 if (x == var)
1363 tree t = omp_member_access_dummy_var (var);
1364 if (t)
1366 x = DECL_VALUE_EXPR (var);
1367 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1368 if (o != t)
1369 x = unshare_and_remap (x, t, o);
1370 else
1371 x = unshare_expr (x);
1375 if (is_reference (var))
1376 x = build_simple_mem_ref (x);
1378 return x;
1381 /* Build tree nodes to access the field for VAR on the sender side. */
1383 static tree
1384 build_sender_ref (splay_tree_key key, omp_context *ctx)
1386 tree field = lookup_sfield (key, ctx);
1387 return omp_build_component_ref (ctx->sender_decl, field);
1390 static tree
1391 build_sender_ref (tree var, omp_context *ctx)
1393 return build_sender_ref ((splay_tree_key) var, ctx);
1396 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1397 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1399 static void
1400 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1401 bool base_pointers_restrict = false)
1403 tree field, type, sfield = NULL_TREE;
1404 splay_tree_key key = (splay_tree_key) var;
1406 if ((mask & 8) != 0)
1408 key = (splay_tree_key) &DECL_UID (var);
1409 gcc_checking_assert (key != (splay_tree_key) var);
1411 gcc_assert ((mask & 1) == 0
1412 || !splay_tree_lookup (ctx->field_map, key));
1413 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1414 || !splay_tree_lookup (ctx->sfield_map, key));
1415 gcc_assert ((mask & 3) == 3
1416 || !is_gimple_omp_oacc (ctx->stmt));
1418 type = TREE_TYPE (var);
1419 /* Prevent redeclaring the var in the split-off function with a restrict
1420 pointer type. Note that we only clear type itself, restrict qualifiers in
1421 the pointed-to type will be ignored by points-to analysis. */
1422 if (POINTER_TYPE_P (type)
1423 && TYPE_RESTRICT (type))
1424 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1426 if (mask & 4)
1428 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1429 type = build_pointer_type (build_pointer_type (type));
1431 else if (by_ref)
1433 type = build_pointer_type (type);
1434 if (base_pointers_restrict)
1435 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1437 else if ((mask & 3) == 1 && is_reference (var))
1438 type = TREE_TYPE (type);
1440 field = build_decl (DECL_SOURCE_LOCATION (var),
1441 FIELD_DECL, DECL_NAME (var), type);
1443 /* Remember what variable this field was created for. This does have a
1444 side effect of making dwarf2out ignore this member, so for helpful
1445 debugging we clear it later in delete_omp_context. */
1446 DECL_ABSTRACT_ORIGIN (field) = var;
1447 if (type == TREE_TYPE (var))
1449 SET_DECL_ALIGN (field, DECL_ALIGN (var));
1450 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1451 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1453 else
1454 SET_DECL_ALIGN (field, TYPE_ALIGN (type));
1456 if ((mask & 3) == 3)
1458 insert_field_into_struct (ctx->record_type, field);
1459 if (ctx->srecord_type)
1461 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1462 FIELD_DECL, DECL_NAME (var), type);
1463 DECL_ABSTRACT_ORIGIN (sfield) = var;
1464 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
1465 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1466 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1467 insert_field_into_struct (ctx->srecord_type, sfield);
1470 else
1472 if (ctx->srecord_type == NULL_TREE)
1474 tree t;
1476 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1477 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1478 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1480 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1481 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1482 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1483 insert_field_into_struct (ctx->srecord_type, sfield);
1484 splay_tree_insert (ctx->sfield_map,
1485 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1486 (splay_tree_value) sfield);
1489 sfield = field;
1490 insert_field_into_struct ((mask & 1) ? ctx->record_type
1491 : ctx->srecord_type, field);
1494 if (mask & 1)
1495 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1496 if ((mask & 2) && ctx->sfield_map)
1497 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1500 static tree
1501 install_var_local (tree var, omp_context *ctx)
1503 tree new_var = omp_copy_decl_1 (var, ctx);
1504 insert_decl_map (&ctx->cb, var, new_var);
1505 return new_var;
1508 /* Adjust the replacement for DECL in CTX for the new context. This means
1509 copying the DECL_VALUE_EXPR, and fixing up the type. */
1511 static void
1512 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1514 tree new_decl, size;
1516 new_decl = lookup_decl (decl, ctx);
1518 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1520 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1521 && DECL_HAS_VALUE_EXPR_P (decl))
1523 tree ve = DECL_VALUE_EXPR (decl);
1524 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1525 SET_DECL_VALUE_EXPR (new_decl, ve);
1526 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1529 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1531 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1532 if (size == error_mark_node)
1533 size = TYPE_SIZE (TREE_TYPE (new_decl));
1534 DECL_SIZE (new_decl) = size;
1536 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1537 if (size == error_mark_node)
1538 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1539 DECL_SIZE_UNIT (new_decl) = size;
1543 /* The callback for remap_decl. Search all containing contexts for a
1544 mapping of the variable; this avoids having to duplicate the splay
1545 tree ahead of time. We know a mapping doesn't already exist in the
1546 given context. Create new mappings to implement default semantics. */
1548 static tree
1549 omp_copy_decl (tree var, copy_body_data *cb)
1551 omp_context *ctx = (omp_context *) cb;
1552 tree new_var;
1554 if (TREE_CODE (var) == LABEL_DECL)
1556 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1557 DECL_CONTEXT (new_var) = current_function_decl;
1558 insert_decl_map (&ctx->cb, var, new_var);
1559 return new_var;
1562 while (!is_taskreg_ctx (ctx))
1564 ctx = ctx->outer;
1565 if (ctx == NULL)
1566 return var;
1567 new_var = maybe_lookup_decl (var, ctx);
1568 if (new_var)
1569 return new_var;
1572 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1573 return var;
1575 return error_mark_node;
1579 /* Debugging dumps for parallel regions. */
1580 void dump_omp_region (FILE *, struct omp_region *, int);
1581 void debug_omp_region (struct omp_region *);
1582 void debug_all_omp_regions (void);
1584 /* Dump the parallel region tree rooted at REGION. */
1586 void
1587 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1589 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1590 gimple_code_name[region->type]);
1592 if (region->inner)
1593 dump_omp_region (file, region->inner, indent + 4);
1595 if (region->cont)
1597 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1598 region->cont->index);
1601 if (region->exit)
1602 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1603 region->exit->index);
1604 else
1605 fprintf (file, "%*s[no exit marker]\n", indent, "");
1607 if (region->next)
1608 dump_omp_region (file, region->next, indent);
1611 DEBUG_FUNCTION void
1612 debug_omp_region (struct omp_region *region)
1614 dump_omp_region (stderr, region, 0);
1617 DEBUG_FUNCTION void
1618 debug_all_omp_regions (void)
1620 dump_omp_region (stderr, root_omp_region, 0);
1624 /* Create a new parallel region starting at STMT inside region PARENT. */
1626 static struct omp_region *
1627 new_omp_region (basic_block bb, enum gimple_code type,
1628 struct omp_region *parent)
1630 struct omp_region *region = XCNEW (struct omp_region);
1632 region->outer = parent;
1633 region->entry = bb;
1634 region->type = type;
1636 if (parent)
1638 /* This is a nested region. Add it to the list of inner
1639 regions in PARENT. */
1640 region->next = parent->inner;
1641 parent->inner = region;
1643 else
1645 /* This is a toplevel region. Add it to the list of toplevel
1646 regions in ROOT_OMP_REGION. */
1647 region->next = root_omp_region;
1648 root_omp_region = region;
1651 return region;
1654 /* Release the memory associated with the region tree rooted at REGION. */
1656 static void
1657 free_omp_region_1 (struct omp_region *region)
1659 struct omp_region *i, *n;
1661 for (i = region->inner; i ; i = n)
1663 n = i->next;
1664 free_omp_region_1 (i);
1667 free (region);
1670 /* Release the memory for the entire omp region tree. */
1672 void
1673 free_omp_regions (void)
1675 struct omp_region *r, *n;
1676 for (r = root_omp_region; r ; r = n)
1678 n = r->next;
1679 free_omp_region_1 (r);
1681 root_omp_region = NULL;
1685 /* Create a new context, with OUTER_CTX being the surrounding context. */
1687 static omp_context *
1688 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1690 omp_context *ctx = XCNEW (omp_context);
1692 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1693 (splay_tree_value) ctx);
1694 ctx->stmt = stmt;
1696 if (outer_ctx)
1698 ctx->outer = outer_ctx;
1699 ctx->cb = outer_ctx->cb;
1700 ctx->cb.block = NULL;
1701 ctx->depth = outer_ctx->depth + 1;
1703 else
1705 ctx->cb.src_fn = current_function_decl;
1706 ctx->cb.dst_fn = current_function_decl;
1707 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1708 gcc_checking_assert (ctx->cb.src_node);
1709 ctx->cb.dst_node = ctx->cb.src_node;
1710 ctx->cb.src_cfun = cfun;
1711 ctx->cb.copy_decl = omp_copy_decl;
1712 ctx->cb.eh_lp_nr = 0;
1713 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1714 ctx->depth = 1;
1717 ctx->cb.decl_map = new hash_map<tree, tree>;
1719 return ctx;
1722 static gimple_seq maybe_catch_exception (gimple_seq);
1724 /* Finalize task copyfn. */
1726 static void
1727 finalize_task_copyfn (gomp_task *task_stmt)
1729 struct function *child_cfun;
1730 tree child_fn;
1731 gimple_seq seq = NULL, new_seq;
1732 gbind *bind;
1734 child_fn = gimple_omp_task_copy_fn (task_stmt);
1735 if (child_fn == NULL_TREE)
1736 return;
1738 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1739 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1741 push_cfun (child_cfun);
1742 bind = gimplify_body (child_fn, false);
1743 gimple_seq_add_stmt (&seq, bind);
1744 new_seq = maybe_catch_exception (seq);
1745 if (new_seq != seq)
1747 bind = gimple_build_bind (NULL, new_seq, NULL);
1748 seq = NULL;
1749 gimple_seq_add_stmt (&seq, bind);
1751 gimple_set_body (child_fn, seq);
1752 pop_cfun ();
1754 /* Inform the callgraph about the new function. */
1755 cgraph_node *node = cgraph_node::get_create (child_fn);
1756 node->parallelized_function = 1;
1757 cgraph_node::add_new_function (child_fn, false);
1760 /* Destroy a omp_context data structures. Called through the splay tree
1761 value delete callback. */
1763 static void
1764 delete_omp_context (splay_tree_value value)
1766 omp_context *ctx = (omp_context *) value;
1768 delete ctx->cb.decl_map;
1770 if (ctx->field_map)
1771 splay_tree_delete (ctx->field_map);
1772 if (ctx->sfield_map)
1773 splay_tree_delete (ctx->sfield_map);
1775 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1776 it produces corrupt debug information. */
1777 if (ctx->record_type)
1779 tree t;
1780 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1781 DECL_ABSTRACT_ORIGIN (t) = NULL;
1783 if (ctx->srecord_type)
1785 tree t;
1786 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1787 DECL_ABSTRACT_ORIGIN (t) = NULL;
1790 if (is_task_ctx (ctx))
1791 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1793 XDELETE (ctx);
1796 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1797 context. */
1799 static void
1800 fixup_child_record_type (omp_context *ctx)
1802 tree f, type = ctx->record_type;
1804 if (!ctx->receiver_decl)
1805 return;
1806 /* ??? It isn't sufficient to just call remap_type here, because
1807 variably_modified_type_p doesn't work the way we expect for
1808 record types. Testing each field for whether it needs remapping
1809 and creating a new record by hand works, however. */
1810 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1811 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1812 break;
1813 if (f)
1815 tree name, new_fields = NULL;
1817 type = lang_hooks.types.make_type (RECORD_TYPE);
1818 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1819 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1820 TYPE_DECL, name, type);
1821 TYPE_NAME (type) = name;
1823 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1825 tree new_f = copy_node (f);
1826 DECL_CONTEXT (new_f) = type;
1827 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1828 DECL_CHAIN (new_f) = new_fields;
1829 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1830 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1831 &ctx->cb, NULL);
1832 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1833 &ctx->cb, NULL);
1834 new_fields = new_f;
1836 /* Arrange to be able to look up the receiver field
1837 given the sender field. */
1838 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1839 (splay_tree_value) new_f);
1841 TYPE_FIELDS (type) = nreverse (new_fields);
1842 layout_type (type);
1845 /* In a target region we never modify any of the pointers in *.omp_data_i,
1846 so attempt to help the optimizers. */
1847 if (is_gimple_omp_offloaded (ctx->stmt))
1848 type = build_qualified_type (type, TYPE_QUAL_CONST);
1850 TREE_TYPE (ctx->receiver_decl)
1851 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1854 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1855 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1856 restrict. */
1858 static void
1859 scan_sharing_clauses (tree clauses, omp_context *ctx,
1860 bool base_pointers_restrict = false)
1862 tree c, decl;
1863 bool scan_array_reductions = false;
1865 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1867 bool by_ref;
1869 switch (OMP_CLAUSE_CODE (c))
1871 case OMP_CLAUSE_PRIVATE:
1872 decl = OMP_CLAUSE_DECL (c);
1873 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1874 goto do_private;
1875 else if (!is_variable_sized (decl))
1876 install_var_local (decl, ctx);
1877 break;
1879 case OMP_CLAUSE_SHARED:
1880 decl = OMP_CLAUSE_DECL (c);
1881 /* Ignore shared directives in teams construct. */
1882 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1884 /* Global variables don't need to be copied,
1885 the receiver side will use them directly. */
1886 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1887 if (is_global_var (odecl))
1888 break;
1889 insert_decl_map (&ctx->cb, decl, odecl);
1890 break;
1892 gcc_assert (is_taskreg_ctx (ctx));
1893 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1894 || !is_variable_sized (decl));
1895 /* Global variables don't need to be copied,
1896 the receiver side will use them directly. */
1897 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1898 break;
1899 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1901 use_pointer_for_field (decl, ctx);
1902 break;
1904 by_ref = use_pointer_for_field (decl, NULL);
1905 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1906 || TREE_ADDRESSABLE (decl)
1907 || by_ref
1908 || is_reference (decl))
1910 by_ref = use_pointer_for_field (decl, ctx);
1911 install_var_field (decl, by_ref, 3, ctx);
1912 install_var_local (decl, ctx);
1913 break;
1915 /* We don't need to copy const scalar vars back. */
1916 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1917 goto do_private;
1919 case OMP_CLAUSE_REDUCTION:
1920 decl = OMP_CLAUSE_DECL (c);
1921 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1922 && TREE_CODE (decl) == MEM_REF)
1924 tree t = TREE_OPERAND (decl, 0);
1925 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1926 t = TREE_OPERAND (t, 0);
1927 if (TREE_CODE (t) == INDIRECT_REF
1928 || TREE_CODE (t) == ADDR_EXPR)
1929 t = TREE_OPERAND (t, 0);
1930 install_var_local (t, ctx);
1931 if (is_taskreg_ctx (ctx)
1932 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1933 && !is_variable_sized (t))
1935 by_ref = use_pointer_for_field (t, ctx);
1936 install_var_field (t, by_ref, 3, ctx);
1938 break;
1940 goto do_private;
1942 case OMP_CLAUSE_LASTPRIVATE:
1943 /* Let the corresponding firstprivate clause create
1944 the variable. */
1945 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1946 break;
1947 /* FALLTHRU */
1949 case OMP_CLAUSE_FIRSTPRIVATE:
1950 case OMP_CLAUSE_LINEAR:
1951 decl = OMP_CLAUSE_DECL (c);
1952 do_private:
1953 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1954 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1955 && is_gimple_omp_offloaded (ctx->stmt))
1957 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1958 install_var_field (decl, !is_reference (decl), 3, ctx);
1959 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1960 install_var_field (decl, true, 3, ctx);
1961 else
1962 install_var_field (decl, false, 3, ctx);
1964 if (is_variable_sized (decl))
1966 if (is_task_ctx (ctx))
1967 install_var_field (decl, false, 1, ctx);
1968 break;
1970 else if (is_taskreg_ctx (ctx))
1972 bool global
1973 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1974 by_ref = use_pointer_for_field (decl, NULL);
1976 if (is_task_ctx (ctx)
1977 && (global || by_ref || is_reference (decl)))
1979 install_var_field (decl, false, 1, ctx);
1980 if (!global)
1981 install_var_field (decl, by_ref, 2, ctx);
1983 else if (!global)
1984 install_var_field (decl, by_ref, 3, ctx);
1986 install_var_local (decl, ctx);
1987 break;
1989 case OMP_CLAUSE_USE_DEVICE_PTR:
1990 decl = OMP_CLAUSE_DECL (c);
1991 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1992 install_var_field (decl, true, 3, ctx);
1993 else
1994 install_var_field (decl, false, 3, ctx);
1995 if (DECL_SIZE (decl)
1996 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1998 tree decl2 = DECL_VALUE_EXPR (decl);
1999 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2000 decl2 = TREE_OPERAND (decl2, 0);
2001 gcc_assert (DECL_P (decl2));
2002 install_var_local (decl2, ctx);
2004 install_var_local (decl, ctx);
2005 break;
2007 case OMP_CLAUSE_IS_DEVICE_PTR:
2008 decl = OMP_CLAUSE_DECL (c);
2009 goto do_private;
2011 case OMP_CLAUSE__LOOPTEMP_:
2012 gcc_assert (is_taskreg_ctx (ctx));
2013 decl = OMP_CLAUSE_DECL (c);
2014 install_var_field (decl, false, 3, ctx);
2015 install_var_local (decl, ctx);
2016 break;
2018 case OMP_CLAUSE_COPYPRIVATE:
2019 case OMP_CLAUSE_COPYIN:
2020 decl = OMP_CLAUSE_DECL (c);
2021 by_ref = use_pointer_for_field (decl, NULL);
2022 install_var_field (decl, by_ref, 3, ctx);
2023 break;
2025 case OMP_CLAUSE_DEFAULT:
2026 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2027 break;
2029 case OMP_CLAUSE_FINAL:
2030 case OMP_CLAUSE_IF:
2031 case OMP_CLAUSE_NUM_THREADS:
2032 case OMP_CLAUSE_NUM_TEAMS:
2033 case OMP_CLAUSE_THREAD_LIMIT:
2034 case OMP_CLAUSE_DEVICE:
2035 case OMP_CLAUSE_SCHEDULE:
2036 case OMP_CLAUSE_DIST_SCHEDULE:
2037 case OMP_CLAUSE_DEPEND:
2038 case OMP_CLAUSE_PRIORITY:
2039 case OMP_CLAUSE_GRAINSIZE:
2040 case OMP_CLAUSE_NUM_TASKS:
2041 case OMP_CLAUSE__CILK_FOR_COUNT_:
2042 case OMP_CLAUSE_NUM_GANGS:
2043 case OMP_CLAUSE_NUM_WORKERS:
2044 case OMP_CLAUSE_VECTOR_LENGTH:
2045 if (ctx->outer)
2046 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2047 break;
2049 case OMP_CLAUSE_TO:
2050 case OMP_CLAUSE_FROM:
2051 case OMP_CLAUSE_MAP:
2052 if (ctx->outer)
2053 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2054 decl = OMP_CLAUSE_DECL (c);
2055 /* Global variables with "omp declare target" attribute
2056 don't need to be copied, the receiver side will use them
2057 directly. However, global variables with "omp declare target link"
2058 attribute need to be copied. */
2059 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2060 && DECL_P (decl)
2061 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2062 && (OMP_CLAUSE_MAP_KIND (c)
2063 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2064 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2065 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2066 && varpool_node::get_create (decl)->offloadable
2067 && !lookup_attribute ("omp declare target link",
2068 DECL_ATTRIBUTES (decl)))
2069 break;
2070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2071 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2073 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2074 not offloaded; there is nothing to map for those. */
2075 if (!is_gimple_omp_offloaded (ctx->stmt)
2076 && !POINTER_TYPE_P (TREE_TYPE (decl))
2077 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2078 break;
2080 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2081 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2082 || (OMP_CLAUSE_MAP_KIND (c)
2083 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2085 if (TREE_CODE (decl) == COMPONENT_REF
2086 || (TREE_CODE (decl) == INDIRECT_REF
2087 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2088 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2089 == REFERENCE_TYPE)))
2090 break;
2091 if (DECL_SIZE (decl)
2092 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2094 tree decl2 = DECL_VALUE_EXPR (decl);
2095 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2096 decl2 = TREE_OPERAND (decl2, 0);
2097 gcc_assert (DECL_P (decl2));
2098 install_var_local (decl2, ctx);
2100 install_var_local (decl, ctx);
2101 break;
2103 if (DECL_P (decl))
2105 if (DECL_SIZE (decl)
2106 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2108 tree decl2 = DECL_VALUE_EXPR (decl);
2109 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2110 decl2 = TREE_OPERAND (decl2, 0);
2111 gcc_assert (DECL_P (decl2));
2112 install_var_field (decl2, true, 3, ctx);
2113 install_var_local (decl2, ctx);
2114 install_var_local (decl, ctx);
2116 else
2118 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2119 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2120 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2121 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2122 install_var_field (decl, true, 7, ctx);
2123 else
2124 install_var_field (decl, true, 3, ctx,
2125 base_pointers_restrict);
2126 if (is_gimple_omp_offloaded (ctx->stmt)
2127 && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
2128 install_var_local (decl, ctx);
2131 else
2133 tree base = get_base_address (decl);
2134 tree nc = OMP_CLAUSE_CHAIN (c);
2135 if (DECL_P (base)
2136 && nc != NULL_TREE
2137 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2138 && OMP_CLAUSE_DECL (nc) == base
2139 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2140 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2142 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2143 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2145 else
2147 if (ctx->outer)
2149 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2150 decl = OMP_CLAUSE_DECL (c);
2152 gcc_assert (!splay_tree_lookup (ctx->field_map,
2153 (splay_tree_key) decl));
2154 tree field
2155 = build_decl (OMP_CLAUSE_LOCATION (c),
2156 FIELD_DECL, NULL_TREE, ptr_type_node);
2157 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2158 insert_field_into_struct (ctx->record_type, field);
2159 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2160 (splay_tree_value) field);
2163 break;
2165 case OMP_CLAUSE__GRIDDIM_:
2166 if (ctx->outer)
2168 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2169 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2171 break;
2173 case OMP_CLAUSE_NOWAIT:
2174 case OMP_CLAUSE_ORDERED:
2175 case OMP_CLAUSE_COLLAPSE:
2176 case OMP_CLAUSE_UNTIED:
2177 case OMP_CLAUSE_MERGEABLE:
2178 case OMP_CLAUSE_PROC_BIND:
2179 case OMP_CLAUSE_SAFELEN:
2180 case OMP_CLAUSE_SIMDLEN:
2181 case OMP_CLAUSE_THREADS:
2182 case OMP_CLAUSE_SIMD:
2183 case OMP_CLAUSE_NOGROUP:
2184 case OMP_CLAUSE_DEFAULTMAP:
2185 case OMP_CLAUSE_ASYNC:
2186 case OMP_CLAUSE_WAIT:
2187 case OMP_CLAUSE_GANG:
2188 case OMP_CLAUSE_WORKER:
2189 case OMP_CLAUSE_VECTOR:
2190 case OMP_CLAUSE_TILE:
2191 case OMP_CLAUSE_INDEPENDENT:
2192 case OMP_CLAUSE_AUTO:
2193 case OMP_CLAUSE_SEQ:
2194 break;
2196 case OMP_CLAUSE_ALIGNED:
2197 decl = OMP_CLAUSE_DECL (c);
2198 if (is_global_var (decl)
2199 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2200 install_var_local (decl, ctx);
2201 break;
2203 case OMP_CLAUSE_DEVICE_RESIDENT:
2204 case OMP_CLAUSE__CACHE_:
2205 sorry ("Clause not supported yet");
2206 break;
2208 default:
2209 gcc_unreachable ();
2213 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2215 switch (OMP_CLAUSE_CODE (c))
2217 case OMP_CLAUSE_LASTPRIVATE:
2218 /* Let the corresponding firstprivate clause create
2219 the variable. */
2220 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2221 scan_array_reductions = true;
2222 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2223 break;
2224 /* FALLTHRU */
2226 case OMP_CLAUSE_FIRSTPRIVATE:
2227 case OMP_CLAUSE_PRIVATE:
2228 case OMP_CLAUSE_LINEAR:
2229 case OMP_CLAUSE_IS_DEVICE_PTR:
2230 decl = OMP_CLAUSE_DECL (c);
2231 if (is_variable_sized (decl))
2233 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2234 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2235 && is_gimple_omp_offloaded (ctx->stmt))
2237 tree decl2 = DECL_VALUE_EXPR (decl);
2238 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2239 decl2 = TREE_OPERAND (decl2, 0);
2240 gcc_assert (DECL_P (decl2));
2241 install_var_local (decl2, ctx);
2242 fixup_remapped_decl (decl2, ctx, false);
2244 install_var_local (decl, ctx);
2246 fixup_remapped_decl (decl, ctx,
2247 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2248 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2249 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2250 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2251 scan_array_reductions = true;
2252 break;
2254 case OMP_CLAUSE_REDUCTION:
2255 decl = OMP_CLAUSE_DECL (c);
2256 if (TREE_CODE (decl) != MEM_REF)
2258 if (is_variable_sized (decl))
2259 install_var_local (decl, ctx);
2260 fixup_remapped_decl (decl, ctx, false);
2262 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2263 scan_array_reductions = true;
2264 break;
2266 case OMP_CLAUSE_SHARED:
2267 /* Ignore shared directives in teams construct. */
2268 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2269 break;
2270 decl = OMP_CLAUSE_DECL (c);
2271 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2272 break;
2273 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2275 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2276 ctx->outer)))
2277 break;
2278 bool by_ref = use_pointer_for_field (decl, ctx);
2279 install_var_field (decl, by_ref, 11, ctx);
2280 break;
2282 fixup_remapped_decl (decl, ctx, false);
2283 break;
2285 case OMP_CLAUSE_MAP:
2286 if (!is_gimple_omp_offloaded (ctx->stmt))
2287 break;
2288 decl = OMP_CLAUSE_DECL (c);
2289 if (DECL_P (decl)
2290 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2291 && (OMP_CLAUSE_MAP_KIND (c)
2292 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2293 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2294 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2295 && varpool_node::get_create (decl)->offloadable)
2296 break;
2297 if (DECL_P (decl))
2299 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2300 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2301 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2302 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2304 tree new_decl = lookup_decl (decl, ctx);
2305 TREE_TYPE (new_decl)
2306 = remap_type (TREE_TYPE (decl), &ctx->cb);
2308 else if (DECL_SIZE (decl)
2309 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2311 tree decl2 = DECL_VALUE_EXPR (decl);
2312 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2313 decl2 = TREE_OPERAND (decl2, 0);
2314 gcc_assert (DECL_P (decl2));
2315 fixup_remapped_decl (decl2, ctx, false);
2316 fixup_remapped_decl (decl, ctx, true);
2318 else
2319 fixup_remapped_decl (decl, ctx, false);
2321 break;
2323 case OMP_CLAUSE_COPYPRIVATE:
2324 case OMP_CLAUSE_COPYIN:
2325 case OMP_CLAUSE_DEFAULT:
2326 case OMP_CLAUSE_IF:
2327 case OMP_CLAUSE_NUM_THREADS:
2328 case OMP_CLAUSE_NUM_TEAMS:
2329 case OMP_CLAUSE_THREAD_LIMIT:
2330 case OMP_CLAUSE_DEVICE:
2331 case OMP_CLAUSE_SCHEDULE:
2332 case OMP_CLAUSE_DIST_SCHEDULE:
2333 case OMP_CLAUSE_NOWAIT:
2334 case OMP_CLAUSE_ORDERED:
2335 case OMP_CLAUSE_COLLAPSE:
2336 case OMP_CLAUSE_UNTIED:
2337 case OMP_CLAUSE_FINAL:
2338 case OMP_CLAUSE_MERGEABLE:
2339 case OMP_CLAUSE_PROC_BIND:
2340 case OMP_CLAUSE_SAFELEN:
2341 case OMP_CLAUSE_SIMDLEN:
2342 case OMP_CLAUSE_ALIGNED:
2343 case OMP_CLAUSE_DEPEND:
2344 case OMP_CLAUSE__LOOPTEMP_:
2345 case OMP_CLAUSE_TO:
2346 case OMP_CLAUSE_FROM:
2347 case OMP_CLAUSE_PRIORITY:
2348 case OMP_CLAUSE_GRAINSIZE:
2349 case OMP_CLAUSE_NUM_TASKS:
2350 case OMP_CLAUSE_THREADS:
2351 case OMP_CLAUSE_SIMD:
2352 case OMP_CLAUSE_NOGROUP:
2353 case OMP_CLAUSE_DEFAULTMAP:
2354 case OMP_CLAUSE_USE_DEVICE_PTR:
2355 case OMP_CLAUSE__CILK_FOR_COUNT_:
2356 case OMP_CLAUSE_ASYNC:
2357 case OMP_CLAUSE_WAIT:
2358 case OMP_CLAUSE_NUM_GANGS:
2359 case OMP_CLAUSE_NUM_WORKERS:
2360 case OMP_CLAUSE_VECTOR_LENGTH:
2361 case OMP_CLAUSE_GANG:
2362 case OMP_CLAUSE_WORKER:
2363 case OMP_CLAUSE_VECTOR:
2364 case OMP_CLAUSE_TILE:
2365 case OMP_CLAUSE_INDEPENDENT:
2366 case OMP_CLAUSE_AUTO:
2367 case OMP_CLAUSE_SEQ:
2368 case OMP_CLAUSE__GRIDDIM_:
2369 break;
2371 case OMP_CLAUSE_DEVICE_RESIDENT:
2372 case OMP_CLAUSE__CACHE_:
2373 sorry ("Clause not supported yet");
2374 break;
2376 default:
2377 gcc_unreachable ();
2381 gcc_checking_assert (!scan_array_reductions
2382 || !is_gimple_omp_oacc (ctx->stmt));
2383 if (scan_array_reductions)
2385 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2386 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2387 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2389 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2390 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2392 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2393 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2394 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2395 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2396 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2397 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2401 /* Create a new name for omp child function. Returns an identifier. If
2402 IS_CILK_FOR is true then the suffix for the child function is
2403 "_cilk_for_fn." */
2405 static tree
2406 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2408 if (is_cilk_for)
2409 return clone_function_name (current_function_decl, "_cilk_for_fn");
2410 return clone_function_name (current_function_decl,
2411 task_copy ? "_omp_cpyfn" : "_omp_fn");
2414 /* Returns the type of the induction variable for the child function for
2415 _Cilk_for and the types for _high and _low variables based on TYPE. */
2417 static tree
2418 cilk_for_check_loop_diff_type (tree type)
2420 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2422 if (TYPE_UNSIGNED (type))
2423 return uint32_type_node;
2424 else
2425 return integer_type_node;
2427 else
2429 if (TYPE_UNSIGNED (type))
2430 return uint64_type_node;
2431 else
2432 return long_long_integer_type_node;
2436 /* Build a decl for the omp child function. It'll not contain a body
2437 yet, just the bare decl. */
2439 static void
2440 create_omp_child_function (omp_context *ctx, bool task_copy)
2442 tree decl, type, name, t;
2444 tree cilk_for_count
2445 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2446 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2447 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2448 tree cilk_var_type = NULL_TREE;
2450 name = create_omp_child_function_name (task_copy,
2451 cilk_for_count != NULL_TREE);
2452 if (task_copy)
2453 type = build_function_type_list (void_type_node, ptr_type_node,
2454 ptr_type_node, NULL_TREE);
2455 else if (cilk_for_count)
2457 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2458 cilk_var_type = cilk_for_check_loop_diff_type (type);
2459 type = build_function_type_list (void_type_node, ptr_type_node,
2460 cilk_var_type, cilk_var_type, NULL_TREE);
2462 else
2463 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2465 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2467 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2468 || !task_copy);
2469 if (!task_copy)
2470 ctx->cb.dst_fn = decl;
2471 else
2472 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2474 TREE_STATIC (decl) = 1;
2475 TREE_USED (decl) = 1;
2476 DECL_ARTIFICIAL (decl) = 1;
2477 DECL_IGNORED_P (decl) = 0;
2478 TREE_PUBLIC (decl) = 0;
2479 DECL_UNINLINABLE (decl) = 1;
2480 DECL_EXTERNAL (decl) = 0;
2481 DECL_CONTEXT (decl) = NULL_TREE;
2482 DECL_INITIAL (decl) = make_node (BLOCK);
2483 if (cgraph_node::get (current_function_decl)->offloadable)
2484 cgraph_node::get_create (decl)->offloadable = 1;
2485 else
2487 omp_context *octx;
2488 for (octx = ctx; octx; octx = octx->outer)
2489 if (is_gimple_omp_offloaded (octx->stmt))
2491 cgraph_node::get_create (decl)->offloadable = 1;
2492 if (ENABLE_OFFLOADING)
2493 g->have_offload = true;
2495 break;
2499 if (cgraph_node::get_create (decl)->offloadable
2500 && !lookup_attribute ("omp declare target",
2501 DECL_ATTRIBUTES (current_function_decl)))
2502 DECL_ATTRIBUTES (decl)
2503 = tree_cons (get_identifier ("omp target entrypoint"),
2504 NULL_TREE, DECL_ATTRIBUTES (decl));
2506 t = build_decl (DECL_SOURCE_LOCATION (decl),
2507 RESULT_DECL, NULL_TREE, void_type_node);
2508 DECL_ARTIFICIAL (t) = 1;
2509 DECL_IGNORED_P (t) = 1;
2510 DECL_CONTEXT (t) = decl;
2511 DECL_RESULT (decl) = t;
2513 /* _Cilk_for's child function requires two extra parameters called
2514 __low and __high that are set the by Cilk runtime when it calls this
2515 function. */
2516 if (cilk_for_count)
2518 t = build_decl (DECL_SOURCE_LOCATION (decl),
2519 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2520 DECL_ARTIFICIAL (t) = 1;
2521 DECL_NAMELESS (t) = 1;
2522 DECL_ARG_TYPE (t) = ptr_type_node;
2523 DECL_CONTEXT (t) = current_function_decl;
2524 TREE_USED (t) = 1;
2525 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2526 DECL_ARGUMENTS (decl) = t;
2528 t = build_decl (DECL_SOURCE_LOCATION (decl),
2529 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2530 DECL_ARTIFICIAL (t) = 1;
2531 DECL_NAMELESS (t) = 1;
2532 DECL_ARG_TYPE (t) = ptr_type_node;
2533 DECL_CONTEXT (t) = current_function_decl;
2534 TREE_USED (t) = 1;
2535 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2536 DECL_ARGUMENTS (decl) = t;
2539 tree data_name = get_identifier (".omp_data_i");
2540 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2541 ptr_type_node);
2542 DECL_ARTIFICIAL (t) = 1;
2543 DECL_NAMELESS (t) = 1;
2544 DECL_ARG_TYPE (t) = ptr_type_node;
2545 DECL_CONTEXT (t) = current_function_decl;
2546 TREE_USED (t) = 1;
2547 TREE_READONLY (t) = 1;
2548 if (cilk_for_count)
2549 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2550 DECL_ARGUMENTS (decl) = t;
2551 if (!task_copy)
2552 ctx->receiver_decl = t;
2553 else
2555 t = build_decl (DECL_SOURCE_LOCATION (decl),
2556 PARM_DECL, get_identifier (".omp_data_o"),
2557 ptr_type_node);
2558 DECL_ARTIFICIAL (t) = 1;
2559 DECL_NAMELESS (t) = 1;
2560 DECL_ARG_TYPE (t) = ptr_type_node;
2561 DECL_CONTEXT (t) = current_function_decl;
2562 TREE_USED (t) = 1;
2563 TREE_ADDRESSABLE (t) = 1;
2564 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2565 DECL_ARGUMENTS (decl) = t;
2568 /* Allocate memory for the function structure. The call to
2569 allocate_struct_function clobbers CFUN, so we need to restore
2570 it afterward. */
2571 push_struct_function (decl);
2572 cfun->function_end_locus = gimple_location (ctx->stmt);
2573 init_tree_ssa (cfun);
2574 pop_cfun ();
2577 /* Callback for walk_gimple_seq. Check if combined parallel
2578 contains gimple_omp_for_combined_into_p OMP_FOR. */
2580 static tree
2581 find_combined_for (gimple_stmt_iterator *gsi_p,
2582 bool *handled_ops_p,
2583 struct walk_stmt_info *wi)
2585 gimple *stmt = gsi_stmt (*gsi_p);
2587 *handled_ops_p = true;
2588 switch (gimple_code (stmt))
2590 WALK_SUBSTMTS;
2592 case GIMPLE_OMP_FOR:
2593 if (gimple_omp_for_combined_into_p (stmt)
2594 && gimple_omp_for_kind (stmt)
2595 == *(const enum gf_mask *) (wi->info))
2597 wi->info = stmt;
2598 return integer_zero_node;
2600 break;
2601 default:
2602 break;
2604 return NULL;
2607 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2609 static void
2610 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2611 omp_context *outer_ctx)
2613 struct walk_stmt_info wi;
2615 memset (&wi, 0, sizeof (wi));
2616 wi.val_only = true;
2617 wi.info = (void *) &msk;
2618 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2619 if (wi.info != (void *) &msk)
2621 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2622 struct omp_for_data fd;
2623 extract_omp_for_data (for_stmt, &fd, NULL);
2624 /* We need two temporaries with fd.loop.v type (istart/iend)
2625 and then (fd.collapse - 1) temporaries with the same
2626 type for count2 ... countN-1 vars if not constant. */
2627 size_t count = 2, i;
2628 tree type = fd.iter_type;
2629 if (fd.collapse > 1
2630 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2632 count += fd.collapse - 1;
2633 /* If there are lastprivate clauses on the inner
2634 GIMPLE_OMP_FOR, add one more temporaries for the total number
2635 of iterations (product of count1 ... countN-1). */
2636 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2637 OMP_CLAUSE_LASTPRIVATE))
2638 count++;
2639 else if (msk == GF_OMP_FOR_KIND_FOR
2640 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2641 OMP_CLAUSE_LASTPRIVATE))
2642 count++;
2644 for (i = 0; i < count; i++)
2646 tree temp = create_tmp_var (type);
2647 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2648 insert_decl_map (&outer_ctx->cb, temp, temp);
2649 OMP_CLAUSE_DECL (c) = temp;
2650 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2651 gimple_omp_taskreg_set_clauses (stmt, c);
2656 /* Scan an OpenMP parallel directive. */
2658 static void
2659 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2661 omp_context *ctx;
2662 tree name;
2663 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2665 /* Ignore parallel directives with empty bodies, unless there
2666 are copyin clauses. */
2667 if (optimize > 0
2668 && empty_body_p (gimple_omp_body (stmt))
2669 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2670 OMP_CLAUSE_COPYIN) == NULL)
2672 gsi_replace (gsi, gimple_build_nop (), false);
2673 return;
2676 if (gimple_omp_parallel_combined_p (stmt))
2677 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2679 ctx = new_omp_context (stmt, outer_ctx);
2680 taskreg_contexts.safe_push (ctx);
2681 if (taskreg_nesting_level > 1)
2682 ctx->is_nested = true;
2683 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2684 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2685 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2686 name = create_tmp_var_name (".omp_data_s");
2687 name = build_decl (gimple_location (stmt),
2688 TYPE_DECL, name, ctx->record_type);
2689 DECL_ARTIFICIAL (name) = 1;
2690 DECL_NAMELESS (name) = 1;
2691 TYPE_NAME (ctx->record_type) = name;
2692 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2693 if (!gimple_omp_parallel_grid_phony (stmt))
2695 create_omp_child_function (ctx, false);
2696 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2699 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2700 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2702 if (TYPE_FIELDS (ctx->record_type) == NULL)
2703 ctx->record_type = ctx->receiver_decl = NULL;
2706 /* Scan an OpenMP task directive. */
2708 static void
2709 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2711 omp_context *ctx;
2712 tree name, t;
2713 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2715 /* Ignore task directives with empty bodies. */
2716 if (optimize > 0
2717 && empty_body_p (gimple_omp_body (stmt)))
2719 gsi_replace (gsi, gimple_build_nop (), false);
2720 return;
2723 if (gimple_omp_task_taskloop_p (stmt))
2724 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2726 ctx = new_omp_context (stmt, outer_ctx);
2727 taskreg_contexts.safe_push (ctx);
2728 if (taskreg_nesting_level > 1)
2729 ctx->is_nested = true;
2730 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2731 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2732 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2733 name = create_tmp_var_name (".omp_data_s");
2734 name = build_decl (gimple_location (stmt),
2735 TYPE_DECL, name, ctx->record_type);
2736 DECL_ARTIFICIAL (name) = 1;
2737 DECL_NAMELESS (name) = 1;
2738 TYPE_NAME (ctx->record_type) = name;
2739 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2740 create_omp_child_function (ctx, false);
2741 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2743 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2745 if (ctx->srecord_type)
2747 name = create_tmp_var_name (".omp_data_a");
2748 name = build_decl (gimple_location (stmt),
2749 TYPE_DECL, name, ctx->srecord_type);
2750 DECL_ARTIFICIAL (name) = 1;
2751 DECL_NAMELESS (name) = 1;
2752 TYPE_NAME (ctx->srecord_type) = name;
2753 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2754 create_omp_child_function (ctx, true);
2757 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2759 if (TYPE_FIELDS (ctx->record_type) == NULL)
2761 ctx->record_type = ctx->receiver_decl = NULL;
2762 t = build_int_cst (long_integer_type_node, 0);
2763 gimple_omp_task_set_arg_size (stmt, t);
2764 t = build_int_cst (long_integer_type_node, 1);
2765 gimple_omp_task_set_arg_align (stmt, t);
2770 /* If any decls have been made addressable during scan_omp,
2771 adjust their fields if needed, and layout record types
2772 of parallel/task constructs. */
2774 static void
2775 finish_taskreg_scan (omp_context *ctx)
2777 if (ctx->record_type == NULL_TREE)
2778 return;
2780 /* If any task_shared_vars were needed, verify all
2781 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2782 statements if use_pointer_for_field hasn't changed
2783 because of that. If it did, update field types now. */
2784 if (task_shared_vars)
2786 tree c;
2788 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2789 c; c = OMP_CLAUSE_CHAIN (c))
2790 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2791 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2793 tree decl = OMP_CLAUSE_DECL (c);
2795 /* Global variables don't need to be copied,
2796 the receiver side will use them directly. */
2797 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2798 continue;
2799 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2800 || !use_pointer_for_field (decl, ctx))
2801 continue;
2802 tree field = lookup_field (decl, ctx);
2803 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2804 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2805 continue;
2806 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2807 TREE_THIS_VOLATILE (field) = 0;
2808 DECL_USER_ALIGN (field) = 0;
2809 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2810 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2811 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2812 if (ctx->srecord_type)
2814 tree sfield = lookup_sfield (decl, ctx);
2815 TREE_TYPE (sfield) = TREE_TYPE (field);
2816 TREE_THIS_VOLATILE (sfield) = 0;
2817 DECL_USER_ALIGN (sfield) = 0;
2818 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2819 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2820 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2825 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2827 layout_type (ctx->record_type);
2828 fixup_child_record_type (ctx);
2830 else
2832 location_t loc = gimple_location (ctx->stmt);
2833 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2834 /* Move VLA fields to the end. */
2835 p = &TYPE_FIELDS (ctx->record_type);
2836 while (*p)
2837 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2838 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2840 *q = *p;
2841 *p = TREE_CHAIN (*p);
2842 TREE_CHAIN (*q) = NULL_TREE;
2843 q = &TREE_CHAIN (*q);
2845 else
2846 p = &DECL_CHAIN (*p);
2847 *p = vla_fields;
2848 if (gimple_omp_task_taskloop_p (ctx->stmt))
2850 /* Move fields corresponding to first and second _looptemp_
2851 clause first. There are filled by GOMP_taskloop
2852 and thus need to be in specific positions. */
2853 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2854 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2855 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2856 OMP_CLAUSE__LOOPTEMP_);
2857 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2858 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2859 p = &TYPE_FIELDS (ctx->record_type);
2860 while (*p)
2861 if (*p == f1 || *p == f2)
2862 *p = DECL_CHAIN (*p);
2863 else
2864 p = &DECL_CHAIN (*p);
2865 DECL_CHAIN (f1) = f2;
2866 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2867 TYPE_FIELDS (ctx->record_type) = f1;
2868 if (ctx->srecord_type)
2870 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2871 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2872 p = &TYPE_FIELDS (ctx->srecord_type);
2873 while (*p)
2874 if (*p == f1 || *p == f2)
2875 *p = DECL_CHAIN (*p);
2876 else
2877 p = &DECL_CHAIN (*p);
2878 DECL_CHAIN (f1) = f2;
2879 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2880 TYPE_FIELDS (ctx->srecord_type) = f1;
2883 layout_type (ctx->record_type);
2884 fixup_child_record_type (ctx);
2885 if (ctx->srecord_type)
2886 layout_type (ctx->srecord_type);
2887 tree t = fold_convert_loc (loc, long_integer_type_node,
2888 TYPE_SIZE_UNIT (ctx->record_type));
2889 gimple_omp_task_set_arg_size (ctx->stmt, t);
2890 t = build_int_cst (long_integer_type_node,
2891 TYPE_ALIGN_UNIT (ctx->record_type));
2892 gimple_omp_task_set_arg_align (ctx->stmt, t);
2896 /* Find the enclosing offload context. */
2898 static omp_context *
2899 enclosing_target_ctx (omp_context *ctx)
2901 for (; ctx; ctx = ctx->outer)
2902 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2903 break;
2905 return ctx;
2908 /* Return true if ctx is part of an oacc kernels region. */
2910 static bool
2911 ctx_in_oacc_kernels_region (omp_context *ctx)
2913 for (;ctx != NULL; ctx = ctx->outer)
2915 gimple *stmt = ctx->stmt;
2916 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2917 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2918 return true;
2921 return false;
2924 /* Check the parallelism clauses inside a kernels regions.
2925 Until kernels handling moves to use the same loop indirection
2926 scheme as parallel, we need to do this checking early. */
2928 static unsigned
2929 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2931 bool checking = true;
2932 unsigned outer_mask = 0;
2933 unsigned this_mask = 0;
2934 bool has_seq = false, has_auto = false;
2936 if (ctx->outer)
2937 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2938 if (!stmt)
2940 checking = false;
2941 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2942 return outer_mask;
2943 stmt = as_a <gomp_for *> (ctx->stmt);
2946 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2948 switch (OMP_CLAUSE_CODE (c))
2950 case OMP_CLAUSE_GANG:
2951 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2952 break;
2953 case OMP_CLAUSE_WORKER:
2954 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2955 break;
2956 case OMP_CLAUSE_VECTOR:
2957 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2958 break;
2959 case OMP_CLAUSE_SEQ:
2960 has_seq = true;
2961 break;
2962 case OMP_CLAUSE_AUTO:
2963 has_auto = true;
2964 break;
2965 default:
2966 break;
2970 if (checking)
2972 if (has_seq && (this_mask || has_auto))
2973 error_at (gimple_location (stmt), "%<seq%> overrides other"
2974 " OpenACC loop specifiers");
2975 else if (has_auto && this_mask)
2976 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2977 " OpenACC loop specifiers");
2979 if (this_mask & outer_mask)
2980 error_at (gimple_location (stmt), "inner loop uses same"
2981 " OpenACC parallelism as containing loop");
2984 return outer_mask | this_mask;
2987 /* Scan a GIMPLE_OMP_FOR. */
2989 static void
2990 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2992 omp_context *ctx;
2993 size_t i;
2994 tree clauses = gimple_omp_for_clauses (stmt);
2996 ctx = new_omp_context (stmt, outer_ctx);
2998 if (is_gimple_omp_oacc (stmt))
3000 omp_context *tgt = enclosing_target_ctx (outer_ctx);
3002 if (!tgt || is_oacc_parallel (tgt))
3003 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3005 char const *check = NULL;
3007 switch (OMP_CLAUSE_CODE (c))
3009 case OMP_CLAUSE_GANG:
3010 check = "gang";
3011 break;
3013 case OMP_CLAUSE_WORKER:
3014 check = "worker";
3015 break;
3017 case OMP_CLAUSE_VECTOR:
3018 check = "vector";
3019 break;
3021 default:
3022 break;
3025 if (check && OMP_CLAUSE_OPERAND (c, 0))
3026 error_at (gimple_location (stmt),
3027 "argument not permitted on %qs clause in"
3028 " OpenACC %<parallel%>", check);
3031 if (tgt && is_oacc_kernels (tgt))
3033 /* Strip out reductions, as they are not handled yet. */
3034 tree *prev_ptr = &clauses;
3036 while (tree probe = *prev_ptr)
3038 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3040 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3041 *prev_ptr = *next_ptr;
3042 else
3043 prev_ptr = next_ptr;
3046 gimple_omp_for_set_clauses (stmt, clauses);
3047 check_oacc_kernel_gwv (stmt, ctx);
3051 scan_sharing_clauses (clauses, ctx);
3053 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3054 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3056 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3057 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3058 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3059 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3061 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3064 /* Scan an OpenMP sections directive. */
3066 static void
3067 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3069 omp_context *ctx;
3071 ctx = new_omp_context (stmt, outer_ctx);
3072 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3073 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3076 /* Scan an OpenMP single directive. */
3078 static void
3079 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3081 omp_context *ctx;
3082 tree name;
3084 ctx = new_omp_context (stmt, outer_ctx);
3085 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3086 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3087 name = create_tmp_var_name (".omp_copy_s");
3088 name = build_decl (gimple_location (stmt),
3089 TYPE_DECL, name, ctx->record_type);
3090 TYPE_NAME (ctx->record_type) = name;
3092 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3093 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3095 if (TYPE_FIELDS (ctx->record_type) == NULL)
3096 ctx->record_type = NULL;
3097 else
3098 layout_type (ctx->record_type);
3101 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3102 used in the corresponding offloaded function are restrict. */
3104 static bool
3105 omp_target_base_pointers_restrict_p (tree clauses)
3107 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3108 used by OpenACC. */
3109 if (flag_openacc == 0)
3110 return false;
3112 /* I. Basic example:
3114 void foo (void)
3116 unsigned int a[2], b[2];
3118 #pragma acc kernels \
3119 copyout (a) \
3120 copyout (b)
3122 a[0] = 0;
3123 b[0] = 1;
3127 After gimplification, we have:
3129 #pragma omp target oacc_kernels \
3130 map(force_from:a [len: 8]) \
3131 map(force_from:b [len: 8])
3133 a[0] = 0;
3134 b[0] = 1;
3137 Because both mappings have the force prefix, we know that they will be
3138 allocated when calling the corresponding offloaded function, which means we
3139 can mark the base pointers for a and b in the offloaded function as
3140 restrict. */
3142 tree c;
3143 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3145 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3146 return false;
3148 switch (OMP_CLAUSE_MAP_KIND (c))
3150 case GOMP_MAP_FORCE_ALLOC:
3151 case GOMP_MAP_FORCE_TO:
3152 case GOMP_MAP_FORCE_FROM:
3153 case GOMP_MAP_FORCE_TOFROM:
3154 break;
3155 default:
3156 return false;
3160 return true;
3163 /* Scan a GIMPLE_OMP_TARGET. */
3165 static void
3166 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3168 omp_context *ctx;
3169 tree name;
3170 bool offloaded = is_gimple_omp_offloaded (stmt);
3171 tree clauses = gimple_omp_target_clauses (stmt);
3173 ctx = new_omp_context (stmt, outer_ctx);
3174 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3175 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3176 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3177 name = create_tmp_var_name (".omp_data_t");
3178 name = build_decl (gimple_location (stmt),
3179 TYPE_DECL, name, ctx->record_type);
3180 DECL_ARTIFICIAL (name) = 1;
3181 DECL_NAMELESS (name) = 1;
3182 TYPE_NAME (ctx->record_type) = name;
3183 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3185 bool base_pointers_restrict = false;
3186 if (offloaded)
3188 create_omp_child_function (ctx, false);
3189 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3191 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3192 if (base_pointers_restrict
3193 && dump_file && (dump_flags & TDF_DETAILS))
3194 fprintf (dump_file,
3195 "Base pointers in offloaded function are restrict\n");
3198 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3199 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3201 if (TYPE_FIELDS (ctx->record_type) == NULL)
3202 ctx->record_type = ctx->receiver_decl = NULL;
3203 else
3205 TYPE_FIELDS (ctx->record_type)
3206 = nreverse (TYPE_FIELDS (ctx->record_type));
3207 if (flag_checking)
3209 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3210 for (tree field = TYPE_FIELDS (ctx->record_type);
3211 field;
3212 field = DECL_CHAIN (field))
3213 gcc_assert (DECL_ALIGN (field) == align);
3215 layout_type (ctx->record_type);
3216 if (offloaded)
3217 fixup_child_record_type (ctx);
3221 /* Scan an OpenMP teams directive. */
3223 static void
3224 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3226 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3227 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3228 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3231 /* Check nesting restrictions. */
3232 static bool
3233 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3235 tree c;
3237 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3238 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3239 the original copy of its contents. */
3240 return true;
3242 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3243 inside an OpenACC CTX. */
3244 if (!(is_gimple_omp (stmt)
3245 && is_gimple_omp_oacc (stmt))
3246 /* Except for atomic codes that we share with OpenMP. */
3247 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3248 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3250 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3252 error_at (gimple_location (stmt),
3253 "non-OpenACC construct inside of OpenACC routine");
3254 return false;
3256 else
3257 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3258 if (is_gimple_omp (octx->stmt)
3259 && is_gimple_omp_oacc (octx->stmt))
3261 error_at (gimple_location (stmt),
3262 "non-OpenACC construct inside of OpenACC region");
3263 return false;
3267 if (ctx != NULL)
3269 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3270 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3272 c = NULL_TREE;
3273 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3275 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3276 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3278 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3279 && (ctx->outer == NULL
3280 || !gimple_omp_for_combined_into_p (ctx->stmt)
3281 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3282 || (gimple_omp_for_kind (ctx->outer->stmt)
3283 != GF_OMP_FOR_KIND_FOR)
3284 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3286 error_at (gimple_location (stmt),
3287 "%<ordered simd threads%> must be closely "
3288 "nested inside of %<for simd%> region");
3289 return false;
3291 return true;
3294 error_at (gimple_location (stmt),
3295 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3296 " may not be nested inside %<simd%> region");
3297 return false;
3299 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3301 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3302 || (gimple_omp_for_kind (stmt)
3303 != GF_OMP_FOR_KIND_DISTRIBUTE))
3304 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3306 error_at (gimple_location (stmt),
3307 "only %<distribute%> or %<parallel%> regions are "
3308 "allowed to be strictly nested inside %<teams%> "
3309 "region");
3310 return false;
3314 switch (gimple_code (stmt))
3316 case GIMPLE_OMP_FOR:
3317 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3318 return true;
3319 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3321 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3323 error_at (gimple_location (stmt),
3324 "%<distribute%> region must be strictly nested "
3325 "inside %<teams%> construct");
3326 return false;
3328 return true;
3330 /* We split taskloop into task and nested taskloop in it. */
3331 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3332 return true;
3333 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3335 bool ok = false;
3337 if (ctx)
3338 switch (gimple_code (ctx->stmt))
3340 case GIMPLE_OMP_FOR:
3341 ok = (gimple_omp_for_kind (ctx->stmt)
3342 == GF_OMP_FOR_KIND_OACC_LOOP);
3343 break;
3345 case GIMPLE_OMP_TARGET:
3346 switch (gimple_omp_target_kind (ctx->stmt))
3348 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3349 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3350 ok = true;
3351 break;
3353 default:
3354 break;
3357 default:
3358 break;
3360 else if (get_oacc_fn_attrib (current_function_decl))
3361 ok = true;
3362 if (!ok)
3364 error_at (gimple_location (stmt),
3365 "OpenACC loop directive must be associated with"
3366 " an OpenACC compute region");
3367 return false;
3370 /* FALLTHRU */
3371 case GIMPLE_CALL:
3372 if (is_gimple_call (stmt)
3373 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 == BUILT_IN_GOMP_CANCEL
3375 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3376 == BUILT_IN_GOMP_CANCELLATION_POINT))
3378 const char *bad = NULL;
3379 const char *kind = NULL;
3380 const char *construct
3381 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3382 == BUILT_IN_GOMP_CANCEL)
3383 ? "#pragma omp cancel"
3384 : "#pragma omp cancellation point";
3385 if (ctx == NULL)
3387 error_at (gimple_location (stmt), "orphaned %qs construct",
3388 construct);
3389 return false;
3391 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3392 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3393 : 0)
3395 case 1:
3396 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3397 bad = "#pragma omp parallel";
3398 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3399 == BUILT_IN_GOMP_CANCEL
3400 && !integer_zerop (gimple_call_arg (stmt, 1)))
3401 ctx->cancellable = true;
3402 kind = "parallel";
3403 break;
3404 case 2:
3405 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3406 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3407 bad = "#pragma omp for";
3408 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3409 == BUILT_IN_GOMP_CANCEL
3410 && !integer_zerop (gimple_call_arg (stmt, 1)))
3412 ctx->cancellable = true;
3413 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3414 OMP_CLAUSE_NOWAIT))
3415 warning_at (gimple_location (stmt), 0,
3416 "%<#pragma omp cancel for%> inside "
3417 "%<nowait%> for construct");
3418 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3419 OMP_CLAUSE_ORDERED))
3420 warning_at (gimple_location (stmt), 0,
3421 "%<#pragma omp cancel for%> inside "
3422 "%<ordered%> for construct");
3424 kind = "for";
3425 break;
3426 case 4:
3427 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3428 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3429 bad = "#pragma omp sections";
3430 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3431 == BUILT_IN_GOMP_CANCEL
3432 && !integer_zerop (gimple_call_arg (stmt, 1)))
3434 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3436 ctx->cancellable = true;
3437 if (find_omp_clause (gimple_omp_sections_clauses
3438 (ctx->stmt),
3439 OMP_CLAUSE_NOWAIT))
3440 warning_at (gimple_location (stmt), 0,
3441 "%<#pragma omp cancel sections%> inside "
3442 "%<nowait%> sections construct");
3444 else
3446 gcc_assert (ctx->outer
3447 && gimple_code (ctx->outer->stmt)
3448 == GIMPLE_OMP_SECTIONS);
3449 ctx->outer->cancellable = true;
3450 if (find_omp_clause (gimple_omp_sections_clauses
3451 (ctx->outer->stmt),
3452 OMP_CLAUSE_NOWAIT))
3453 warning_at (gimple_location (stmt), 0,
3454 "%<#pragma omp cancel sections%> inside "
3455 "%<nowait%> sections construct");
3458 kind = "sections";
3459 break;
3460 case 8:
3461 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3462 bad = "#pragma omp task";
3463 else
3465 for (omp_context *octx = ctx->outer;
3466 octx; octx = octx->outer)
3468 switch (gimple_code (octx->stmt))
3470 case GIMPLE_OMP_TASKGROUP:
3471 break;
3472 case GIMPLE_OMP_TARGET:
3473 if (gimple_omp_target_kind (octx->stmt)
3474 != GF_OMP_TARGET_KIND_REGION)
3475 continue;
3476 /* FALLTHRU */
3477 case GIMPLE_OMP_PARALLEL:
3478 case GIMPLE_OMP_TEAMS:
3479 error_at (gimple_location (stmt),
3480 "%<%s taskgroup%> construct not closely "
3481 "nested inside of %<taskgroup%> region",
3482 construct);
3483 return false;
3484 default:
3485 continue;
3487 break;
3489 ctx->cancellable = true;
3491 kind = "taskgroup";
3492 break;
3493 default:
3494 error_at (gimple_location (stmt), "invalid arguments");
3495 return false;
3497 if (bad)
3499 error_at (gimple_location (stmt),
3500 "%<%s %s%> construct not closely nested inside of %qs",
3501 construct, kind, bad);
3502 return false;
3505 /* FALLTHRU */
3506 case GIMPLE_OMP_SECTIONS:
3507 case GIMPLE_OMP_SINGLE:
3508 for (; ctx != NULL; ctx = ctx->outer)
3509 switch (gimple_code (ctx->stmt))
3511 case GIMPLE_OMP_FOR:
3512 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3513 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3514 break;
3515 /* FALLTHRU */
3516 case GIMPLE_OMP_SECTIONS:
3517 case GIMPLE_OMP_SINGLE:
3518 case GIMPLE_OMP_ORDERED:
3519 case GIMPLE_OMP_MASTER:
3520 case GIMPLE_OMP_TASK:
3521 case GIMPLE_OMP_CRITICAL:
3522 if (is_gimple_call (stmt))
3524 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3525 != BUILT_IN_GOMP_BARRIER)
3526 return true;
3527 error_at (gimple_location (stmt),
3528 "barrier region may not be closely nested inside "
3529 "of work-sharing, %<critical%>, %<ordered%>, "
3530 "%<master%>, explicit %<task%> or %<taskloop%> "
3531 "region");
3532 return false;
3534 error_at (gimple_location (stmt),
3535 "work-sharing region may not be closely nested inside "
3536 "of work-sharing, %<critical%>, %<ordered%>, "
3537 "%<master%>, explicit %<task%> or %<taskloop%> region");
3538 return false;
3539 case GIMPLE_OMP_PARALLEL:
3540 case GIMPLE_OMP_TEAMS:
3541 return true;
3542 case GIMPLE_OMP_TARGET:
3543 if (gimple_omp_target_kind (ctx->stmt)
3544 == GF_OMP_TARGET_KIND_REGION)
3545 return true;
3546 break;
3547 default:
3548 break;
3550 break;
3551 case GIMPLE_OMP_MASTER:
3552 for (; ctx != NULL; ctx = ctx->outer)
3553 switch (gimple_code (ctx->stmt))
3555 case GIMPLE_OMP_FOR:
3556 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3557 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3558 break;
3559 /* FALLTHRU */
3560 case GIMPLE_OMP_SECTIONS:
3561 case GIMPLE_OMP_SINGLE:
3562 case GIMPLE_OMP_TASK:
3563 error_at (gimple_location (stmt),
3564 "%<master%> region may not be closely nested inside "
3565 "of work-sharing, explicit %<task%> or %<taskloop%> "
3566 "region");
3567 return false;
3568 case GIMPLE_OMP_PARALLEL:
3569 case GIMPLE_OMP_TEAMS:
3570 return true;
3571 case GIMPLE_OMP_TARGET:
3572 if (gimple_omp_target_kind (ctx->stmt)
3573 == GF_OMP_TARGET_KIND_REGION)
3574 return true;
3575 break;
3576 default:
3577 break;
3579 break;
3580 case GIMPLE_OMP_TASK:
3581 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3582 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3583 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3584 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3586 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3587 error_at (OMP_CLAUSE_LOCATION (c),
3588 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3589 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3590 return false;
3592 break;
3593 case GIMPLE_OMP_ORDERED:
3594 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3595 c; c = OMP_CLAUSE_CHAIN (c))
3597 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3599 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3600 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3601 continue;
3603 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3604 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3605 || kind == OMP_CLAUSE_DEPEND_SINK)
3607 tree oclause;
3608 /* Look for containing ordered(N) loop. */
3609 if (ctx == NULL
3610 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3611 || (oclause
3612 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3613 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3615 error_at (OMP_CLAUSE_LOCATION (c),
3616 "%<ordered%> construct with %<depend%> clause "
3617 "must be closely nested inside an %<ordered%> "
3618 "loop");
3619 return false;
3621 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3623 error_at (OMP_CLAUSE_LOCATION (c),
3624 "%<ordered%> construct with %<depend%> clause "
3625 "must be closely nested inside a loop with "
3626 "%<ordered%> clause with a parameter");
3627 return false;
3630 else
3632 error_at (OMP_CLAUSE_LOCATION (c),
3633 "invalid depend kind in omp %<ordered%> %<depend%>");
3634 return false;
3637 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3638 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3640 /* ordered simd must be closely nested inside of simd region,
3641 and simd region must not encounter constructs other than
3642 ordered simd, therefore ordered simd may be either orphaned,
3643 or ctx->stmt must be simd. The latter case is handled already
3644 earlier. */
3645 if (ctx != NULL)
3647 error_at (gimple_location (stmt),
3648 "%<ordered%> %<simd%> must be closely nested inside "
3649 "%<simd%> region");
3650 return false;
3653 for (; ctx != NULL; ctx = ctx->outer)
3654 switch (gimple_code (ctx->stmt))
3656 case GIMPLE_OMP_CRITICAL:
3657 case GIMPLE_OMP_TASK:
3658 case GIMPLE_OMP_ORDERED:
3659 ordered_in_taskloop:
3660 error_at (gimple_location (stmt),
3661 "%<ordered%> region may not be closely nested inside "
3662 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3663 "%<taskloop%> region");
3664 return false;
3665 case GIMPLE_OMP_FOR:
3666 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3667 goto ordered_in_taskloop;
3668 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3669 OMP_CLAUSE_ORDERED) == NULL)
3671 error_at (gimple_location (stmt),
3672 "%<ordered%> region must be closely nested inside "
3673 "a loop region with an %<ordered%> clause");
3674 return false;
3676 return true;
3677 case GIMPLE_OMP_TARGET:
3678 if (gimple_omp_target_kind (ctx->stmt)
3679 != GF_OMP_TARGET_KIND_REGION)
3680 break;
3681 /* FALLTHRU */
3682 case GIMPLE_OMP_PARALLEL:
3683 case GIMPLE_OMP_TEAMS:
3684 error_at (gimple_location (stmt),
3685 "%<ordered%> region must be closely nested inside "
3686 "a loop region with an %<ordered%> clause");
3687 return false;
3688 default:
3689 break;
3691 break;
3692 case GIMPLE_OMP_CRITICAL:
3694 tree this_stmt_name
3695 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3696 for (; ctx != NULL; ctx = ctx->outer)
3697 if (gomp_critical *other_crit
3698 = dyn_cast <gomp_critical *> (ctx->stmt))
3699 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3701 error_at (gimple_location (stmt),
3702 "%<critical%> region may not be nested inside "
3703 "a %<critical%> region with the same name");
3704 return false;
3707 break;
3708 case GIMPLE_OMP_TEAMS:
3709 if (ctx == NULL
3710 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3711 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3713 error_at (gimple_location (stmt),
3714 "%<teams%> construct not closely nested inside of "
3715 "%<target%> construct");
3716 return false;
3718 break;
3719 case GIMPLE_OMP_TARGET:
3720 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3721 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3722 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3723 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3725 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3726 error_at (OMP_CLAUSE_LOCATION (c),
3727 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3728 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3729 return false;
3731 if (is_gimple_omp_offloaded (stmt)
3732 && get_oacc_fn_attrib (cfun->decl) != NULL)
3734 error_at (gimple_location (stmt),
3735 "OpenACC region inside of OpenACC routine, nested "
3736 "parallelism not supported yet");
3737 return false;
3739 for (; ctx != NULL; ctx = ctx->outer)
3741 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3743 if (is_gimple_omp (stmt)
3744 && is_gimple_omp_oacc (stmt)
3745 && is_gimple_omp (ctx->stmt))
3747 error_at (gimple_location (stmt),
3748 "OpenACC construct inside of non-OpenACC region");
3749 return false;
3751 continue;
3754 const char *stmt_name, *ctx_stmt_name;
3755 switch (gimple_omp_target_kind (stmt))
3757 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3758 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3759 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3760 case GF_OMP_TARGET_KIND_ENTER_DATA:
3761 stmt_name = "target enter data"; break;
3762 case GF_OMP_TARGET_KIND_EXIT_DATA:
3763 stmt_name = "target exit data"; break;
3764 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3765 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3766 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3767 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3768 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3769 stmt_name = "enter/exit data"; break;
3770 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3771 break;
3772 default: gcc_unreachable ();
3774 switch (gimple_omp_target_kind (ctx->stmt))
3776 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3777 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3778 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3779 ctx_stmt_name = "parallel"; break;
3780 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3781 ctx_stmt_name = "kernels"; break;
3782 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3783 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3784 ctx_stmt_name = "host_data"; break;
3785 default: gcc_unreachable ();
3788 /* OpenACC/OpenMP mismatch? */
3789 if (is_gimple_omp_oacc (stmt)
3790 != is_gimple_omp_oacc (ctx->stmt))
3792 error_at (gimple_location (stmt),
3793 "%s %qs construct inside of %s %qs region",
3794 (is_gimple_omp_oacc (stmt)
3795 ? "OpenACC" : "OpenMP"), stmt_name,
3796 (is_gimple_omp_oacc (ctx->stmt)
3797 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3798 return false;
3800 if (is_gimple_omp_offloaded (ctx->stmt))
3802 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3803 if (is_gimple_omp_oacc (ctx->stmt))
3805 error_at (gimple_location (stmt),
3806 "%qs construct inside of %qs region",
3807 stmt_name, ctx_stmt_name);
3808 return false;
3810 else
3812 warning_at (gimple_location (stmt), 0,
3813 "%qs construct inside of %qs region",
3814 stmt_name, ctx_stmt_name);
3818 break;
3819 default:
3820 break;
3822 return true;
3826 /* Helper function scan_omp.
3828 Callback for walk_tree or operators in walk_gimple_stmt used to
3829 scan for OMP directives in TP. */
3831 static tree
3832 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3834 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3835 omp_context *ctx = (omp_context *) wi->info;
3836 tree t = *tp;
3838 switch (TREE_CODE (t))
3840 case VAR_DECL:
3841 case PARM_DECL:
3842 case LABEL_DECL:
3843 case RESULT_DECL:
3844 if (ctx)
3846 tree repl = remap_decl (t, &ctx->cb);
3847 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3848 *tp = repl;
3850 break;
3852 default:
3853 if (ctx && TYPE_P (t))
3854 *tp = remap_type (t, &ctx->cb);
3855 else if (!DECL_P (t))
3857 *walk_subtrees = 1;
3858 if (ctx)
3860 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3861 if (tem != TREE_TYPE (t))
3863 if (TREE_CODE (t) == INTEGER_CST)
3864 *tp = wide_int_to_tree (tem, t);
3865 else
3866 TREE_TYPE (t) = tem;
3870 break;
3873 return NULL_TREE;
3876 /* Return true if FNDECL is a setjmp or a longjmp. */
3878 static bool
3879 setjmp_or_longjmp_p (const_tree fndecl)
3881 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3882 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3883 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3884 return true;
3886 tree declname = DECL_NAME (fndecl);
3887 if (!declname)
3888 return false;
3889 const char *name = IDENTIFIER_POINTER (declname);
3890 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3894 /* Helper function for scan_omp.
3896 Callback for walk_gimple_stmt used to scan for OMP directives in
3897 the current statement in GSI. */
3899 static tree
3900 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3901 struct walk_stmt_info *wi)
3903 gimple *stmt = gsi_stmt (*gsi);
3904 omp_context *ctx = (omp_context *) wi->info;
3906 if (gimple_has_location (stmt))
3907 input_location = gimple_location (stmt);
3909 /* Check the nesting restrictions. */
3910 bool remove = false;
3911 if (is_gimple_omp (stmt))
3912 remove = !check_omp_nesting_restrictions (stmt, ctx);
3913 else if (is_gimple_call (stmt))
3915 tree fndecl = gimple_call_fndecl (stmt);
3916 if (fndecl)
3918 if (setjmp_or_longjmp_p (fndecl)
3919 && ctx
3920 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3921 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3923 remove = true;
3924 error_at (gimple_location (stmt),
3925 "setjmp/longjmp inside simd construct");
3927 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3928 switch (DECL_FUNCTION_CODE (fndecl))
3930 case BUILT_IN_GOMP_BARRIER:
3931 case BUILT_IN_GOMP_CANCEL:
3932 case BUILT_IN_GOMP_CANCELLATION_POINT:
3933 case BUILT_IN_GOMP_TASKYIELD:
3934 case BUILT_IN_GOMP_TASKWAIT:
3935 case BUILT_IN_GOMP_TASKGROUP_START:
3936 case BUILT_IN_GOMP_TASKGROUP_END:
3937 remove = !check_omp_nesting_restrictions (stmt, ctx);
3938 break;
3939 default:
3940 break;
3944 if (remove)
3946 stmt = gimple_build_nop ();
3947 gsi_replace (gsi, stmt, false);
3950 *handled_ops_p = true;
3952 switch (gimple_code (stmt))
3954 case GIMPLE_OMP_PARALLEL:
3955 taskreg_nesting_level++;
3956 scan_omp_parallel (gsi, ctx);
3957 taskreg_nesting_level--;
3958 break;
3960 case GIMPLE_OMP_TASK:
3961 taskreg_nesting_level++;
3962 scan_omp_task (gsi, ctx);
3963 taskreg_nesting_level--;
3964 break;
3966 case GIMPLE_OMP_FOR:
3967 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3968 break;
3970 case GIMPLE_OMP_SECTIONS:
3971 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3972 break;
3974 case GIMPLE_OMP_SINGLE:
3975 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3976 break;
3978 case GIMPLE_OMP_SECTION:
3979 case GIMPLE_OMP_MASTER:
3980 case GIMPLE_OMP_TASKGROUP:
3981 case GIMPLE_OMP_ORDERED:
3982 case GIMPLE_OMP_CRITICAL:
3983 case GIMPLE_OMP_GRID_BODY:
3984 ctx = new_omp_context (stmt, ctx);
3985 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3986 break;
3988 case GIMPLE_OMP_TARGET:
3989 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3990 break;
3992 case GIMPLE_OMP_TEAMS:
3993 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3994 break;
3996 case GIMPLE_BIND:
3998 tree var;
4000 *handled_ops_p = false;
4001 if (ctx)
4002 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
4003 var ;
4004 var = DECL_CHAIN (var))
4005 insert_decl_map (&ctx->cb, var, var);
4007 break;
4008 default:
4009 *handled_ops_p = false;
4010 break;
4013 return NULL_TREE;
4017 /* Scan all the statements starting at the current statement. CTX
4018 contains context information about the OMP directives and
4019 clauses found during the scan. */
4021 static void
4022 scan_omp (gimple_seq *body_p, omp_context *ctx)
4024 location_t saved_location;
4025 struct walk_stmt_info wi;
4027 memset (&wi, 0, sizeof (wi));
4028 wi.info = ctx;
4029 wi.want_locations = true;
4031 saved_location = input_location;
4032 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4033 input_location = saved_location;
4036 /* Re-gimplification and code generation routines. */
4038 /* Build a call to GOMP_barrier. */
4040 static gimple *
4041 build_omp_barrier (tree lhs)
4043 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4044 : BUILT_IN_GOMP_BARRIER);
4045 gcall *g = gimple_build_call (fndecl, 0);
4046 if (lhs)
4047 gimple_call_set_lhs (g, lhs);
4048 return g;
4051 /* If a context was created for STMT when it was scanned, return it. */
4053 static omp_context *
4054 maybe_lookup_ctx (gimple *stmt)
4056 splay_tree_node n;
4057 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4058 return n ? (omp_context *) n->value : NULL;
4062 /* Find the mapping for DECL in CTX or the immediately enclosing
4063 context that has a mapping for DECL.
4065 If CTX is a nested parallel directive, we may have to use the decl
4066 mappings created in CTX's parent context. Suppose that we have the
4067 following parallel nesting (variable UIDs showed for clarity):
4069 iD.1562 = 0;
4070 #omp parallel shared(iD.1562) -> outer parallel
4071 iD.1562 = iD.1562 + 1;
4073 #omp parallel shared (iD.1562) -> inner parallel
4074 iD.1562 = iD.1562 - 1;
4076 Each parallel structure will create a distinct .omp_data_s structure
4077 for copying iD.1562 in/out of the directive:
4079 outer parallel .omp_data_s.1.i -> iD.1562
4080 inner parallel .omp_data_s.2.i -> iD.1562
4082 A shared variable mapping will produce a copy-out operation before
4083 the parallel directive and a copy-in operation after it. So, in
4084 this case we would have:
4086 iD.1562 = 0;
4087 .omp_data_o.1.i = iD.1562;
4088 #omp parallel shared(iD.1562) -> outer parallel
4089 .omp_data_i.1 = &.omp_data_o.1
4090 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4092 .omp_data_o.2.i = iD.1562; -> **
4093 #omp parallel shared(iD.1562) -> inner parallel
4094 .omp_data_i.2 = &.omp_data_o.2
4095 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4098 ** This is a problem. The symbol iD.1562 cannot be referenced
4099 inside the body of the outer parallel region. But since we are
4100 emitting this copy operation while expanding the inner parallel
4101 directive, we need to access the CTX structure of the outer
4102 parallel directive to get the correct mapping:
4104 .omp_data_o.2.i = .omp_data_i.1->i
4106 Since there may be other workshare or parallel directives enclosing
4107 the parallel directive, it may be necessary to walk up the context
4108 parent chain. This is not a problem in general because nested
4109 parallelism happens only rarely. */
4111 static tree
4112 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4114 tree t;
4115 omp_context *up;
4117 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4118 t = maybe_lookup_decl (decl, up);
4120 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4122 return t ? t : decl;
4126 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4127 in outer contexts. */
4129 static tree
4130 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4132 tree t = NULL;
4133 omp_context *up;
4135 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4136 t = maybe_lookup_decl (decl, up);
4138 return t ? t : decl;
4142 /* Construct the initialization value for reduction operation OP. */
4144 tree
4145 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4147 switch (op)
4149 case PLUS_EXPR:
4150 case MINUS_EXPR:
4151 case BIT_IOR_EXPR:
4152 case BIT_XOR_EXPR:
4153 case TRUTH_OR_EXPR:
4154 case TRUTH_ORIF_EXPR:
4155 case TRUTH_XOR_EXPR:
4156 case NE_EXPR:
4157 return build_zero_cst (type);
4159 case MULT_EXPR:
4160 case TRUTH_AND_EXPR:
4161 case TRUTH_ANDIF_EXPR:
4162 case EQ_EXPR:
4163 return fold_convert_loc (loc, type, integer_one_node);
4165 case BIT_AND_EXPR:
4166 return fold_convert_loc (loc, type, integer_minus_one_node);
4168 case MAX_EXPR:
4169 if (SCALAR_FLOAT_TYPE_P (type))
4171 REAL_VALUE_TYPE max, min;
4172 if (HONOR_INFINITIES (type))
4174 real_inf (&max);
4175 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4177 else
4178 real_maxval (&min, 1, TYPE_MODE (type));
4179 return build_real (type, min);
4181 else if (POINTER_TYPE_P (type))
4183 wide_int min
4184 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4185 return wide_int_to_tree (type, min);
4187 else
4189 gcc_assert (INTEGRAL_TYPE_P (type));
4190 return TYPE_MIN_VALUE (type);
4193 case MIN_EXPR:
4194 if (SCALAR_FLOAT_TYPE_P (type))
4196 REAL_VALUE_TYPE max;
4197 if (HONOR_INFINITIES (type))
4198 real_inf (&max);
4199 else
4200 real_maxval (&max, 0, TYPE_MODE (type));
4201 return build_real (type, max);
4203 else if (POINTER_TYPE_P (type))
4205 wide_int max
4206 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4207 return wide_int_to_tree (type, max);
4209 else
4211 gcc_assert (INTEGRAL_TYPE_P (type));
4212 return TYPE_MAX_VALUE (type);
4215 default:
4216 gcc_unreachable ();
4220 /* Construct the initialization value for reduction CLAUSE. */
4222 tree
4223 omp_reduction_init (tree clause, tree type)
4225 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4226 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4229 /* Return alignment to be assumed for var in CLAUSE, which should be
4230 OMP_CLAUSE_ALIGNED. */
4232 static tree
4233 omp_clause_aligned_alignment (tree clause)
4235 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4236 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4238 /* Otherwise return implementation defined alignment. */
4239 unsigned int al = 1;
4240 machine_mode mode, vmode;
4241 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4242 if (vs)
4243 vs = 1 << floor_log2 (vs);
4244 static enum mode_class classes[]
4245 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4246 for (int i = 0; i < 4; i += 2)
4247 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4248 mode != VOIDmode;
4249 mode = GET_MODE_WIDER_MODE (mode))
4251 vmode = targetm.vectorize.preferred_simd_mode (mode);
4252 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4253 continue;
4254 while (vs
4255 && GET_MODE_SIZE (vmode) < vs
4256 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4257 vmode = GET_MODE_2XWIDER_MODE (vmode);
4259 tree type = lang_hooks.types.type_for_mode (mode, 1);
4260 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4261 continue;
4262 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4263 / GET_MODE_SIZE (mode));
4264 if (TYPE_MODE (type) != vmode)
4265 continue;
4266 if (TYPE_ALIGN_UNIT (type) > al)
4267 al = TYPE_ALIGN_UNIT (type);
4269 return build_int_cst (integer_type_node, al);
4272 /* Return maximum possible vectorization factor for the target. */
4274 static int
4275 omp_max_vf (void)
4277 if (!optimize
4278 || optimize_debug
4279 || !flag_tree_loop_optimize
4280 || (!flag_tree_loop_vectorize
4281 && (global_options_set.x_flag_tree_loop_vectorize
4282 || global_options_set.x_flag_tree_vectorize)))
4283 return 1;
4285 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4286 if (vs)
4288 vs = 1 << floor_log2 (vs);
4289 return vs;
4291 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4292 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4293 return GET_MODE_NUNITS (vqimode);
4294 return 1;
4297 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4298 privatization. */
4300 static bool
4301 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4302 tree &idx, tree &lane, tree &ivar, tree &lvar)
4304 if (max_vf == 0)
4306 max_vf = omp_max_vf ();
4307 if (max_vf > 1)
4309 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4310 OMP_CLAUSE_SAFELEN);
4311 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4312 max_vf = 1;
4313 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4314 max_vf) == -1)
4315 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4317 if (max_vf > 1)
4319 idx = create_tmp_var (unsigned_type_node);
4320 lane = create_tmp_var (unsigned_type_node);
4323 if (max_vf == 1)
4324 return false;
4326 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4327 tree avar = create_tmp_var_raw (atype);
4328 if (TREE_ADDRESSABLE (new_var))
4329 TREE_ADDRESSABLE (avar) = 1;
4330 DECL_ATTRIBUTES (avar)
4331 = tree_cons (get_identifier ("omp simd array"), NULL,
4332 DECL_ATTRIBUTES (avar));
4333 gimple_add_tmp_var (avar);
4334 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4335 NULL_TREE, NULL_TREE);
4336 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4337 NULL_TREE, NULL_TREE);
4338 if (DECL_P (new_var))
4340 SET_DECL_VALUE_EXPR (new_var, lvar);
4341 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4343 return true;
4346 /* Helper function of lower_rec_input_clauses. For a reference
4347 in simd reduction, add an underlying variable it will reference. */
4349 static void
4350 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4352 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4353 if (TREE_CONSTANT (z))
4355 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4356 get_name (new_vard));
4357 gimple_add_tmp_var (z);
4358 TREE_ADDRESSABLE (z) = 1;
4359 z = build_fold_addr_expr_loc (loc, z);
4360 gimplify_assign (new_vard, z, ilist);
4364 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4365 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4366 private variables. Initialization statements go in ILIST, while calls
4367 to destructors go in DLIST. */
4369 static void
4370 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4371 omp_context *ctx, struct omp_for_data *fd)
4373 tree c, dtor, copyin_seq, x, ptr;
4374 bool copyin_by_ref = false;
4375 bool lastprivate_firstprivate = false;
4376 bool reduction_omp_orig_ref = false;
4377 int pass;
4378 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4379 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4380 int max_vf = 0;
4381 tree lane = NULL_TREE, idx = NULL_TREE;
4382 tree ivar = NULL_TREE, lvar = NULL_TREE;
4383 gimple_seq llist[2] = { NULL, NULL };
4385 copyin_seq = NULL;
4387 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4388 with data sharing clauses referencing variable sized vars. That
4389 is unnecessarily hard to support and very unlikely to result in
4390 vectorized code anyway. */
4391 if (is_simd)
4392 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4393 switch (OMP_CLAUSE_CODE (c))
4395 case OMP_CLAUSE_LINEAR:
4396 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4397 max_vf = 1;
4398 /* FALLTHRU */
4399 case OMP_CLAUSE_PRIVATE:
4400 case OMP_CLAUSE_FIRSTPRIVATE:
4401 case OMP_CLAUSE_LASTPRIVATE:
4402 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4403 max_vf = 1;
4404 break;
4405 case OMP_CLAUSE_REDUCTION:
4406 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4407 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4408 max_vf = 1;
4409 break;
4410 default:
4411 continue;
4414 /* Do all the fixed sized types in the first pass, and the variable sized
4415 types in the second pass. This makes sure that the scalar arguments to
4416 the variable sized types are processed before we use them in the
4417 variable sized operations. */
4418 for (pass = 0; pass < 2; ++pass)
4420 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4422 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4423 tree var, new_var;
4424 bool by_ref;
4425 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4427 switch (c_kind)
4429 case OMP_CLAUSE_PRIVATE:
4430 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4431 continue;
4432 break;
4433 case OMP_CLAUSE_SHARED:
4434 /* Ignore shared directives in teams construct. */
4435 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4436 continue;
4437 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4439 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4440 || is_global_var (OMP_CLAUSE_DECL (c)));
4441 continue;
4443 case OMP_CLAUSE_FIRSTPRIVATE:
4444 case OMP_CLAUSE_COPYIN:
4445 break;
4446 case OMP_CLAUSE_LINEAR:
4447 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4448 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4449 lastprivate_firstprivate = true;
4450 break;
4451 case OMP_CLAUSE_REDUCTION:
4452 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4453 reduction_omp_orig_ref = true;
4454 break;
4455 case OMP_CLAUSE__LOOPTEMP_:
4456 /* Handle _looptemp_ clauses only on parallel/task. */
4457 if (fd)
4458 continue;
4459 break;
4460 case OMP_CLAUSE_LASTPRIVATE:
4461 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4463 lastprivate_firstprivate = true;
4464 if (pass != 0 || is_taskloop_ctx (ctx))
4465 continue;
4467 /* Even without corresponding firstprivate, if
4468 decl is Fortran allocatable, it needs outer var
4469 reference. */
4470 else if (pass == 0
4471 && lang_hooks.decls.omp_private_outer_ref
4472 (OMP_CLAUSE_DECL (c)))
4473 lastprivate_firstprivate = true;
4474 break;
4475 case OMP_CLAUSE_ALIGNED:
4476 if (pass == 0)
4477 continue;
4478 var = OMP_CLAUSE_DECL (c);
4479 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4480 && !is_global_var (var))
4482 new_var = maybe_lookup_decl (var, ctx);
4483 if (new_var == NULL_TREE)
4484 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4485 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4486 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4487 omp_clause_aligned_alignment (c));
4488 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4489 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4490 gimplify_and_add (x, ilist);
4492 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4493 && is_global_var (var))
4495 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4496 new_var = lookup_decl (var, ctx);
4497 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4498 t = build_fold_addr_expr_loc (clause_loc, t);
4499 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4500 t = build_call_expr_loc (clause_loc, t2, 2, t,
4501 omp_clause_aligned_alignment (c));
4502 t = fold_convert_loc (clause_loc, ptype, t);
4503 x = create_tmp_var (ptype);
4504 t = build2 (MODIFY_EXPR, ptype, x, t);
4505 gimplify_and_add (t, ilist);
4506 t = build_simple_mem_ref_loc (clause_loc, x);
4507 SET_DECL_VALUE_EXPR (new_var, t);
4508 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4510 continue;
4511 default:
4512 continue;
4515 new_var = var = OMP_CLAUSE_DECL (c);
4516 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4518 var = TREE_OPERAND (var, 0);
4519 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4520 var = TREE_OPERAND (var, 0);
4521 if (TREE_CODE (var) == INDIRECT_REF
4522 || TREE_CODE (var) == ADDR_EXPR)
4523 var = TREE_OPERAND (var, 0);
4524 if (is_variable_sized (var))
4526 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4527 var = DECL_VALUE_EXPR (var);
4528 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4529 var = TREE_OPERAND (var, 0);
4530 gcc_assert (DECL_P (var));
4532 new_var = var;
4534 if (c_kind != OMP_CLAUSE_COPYIN)
4535 new_var = lookup_decl (var, ctx);
4537 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4539 if (pass != 0)
4540 continue;
4542 /* C/C++ array section reductions. */
4543 else if (c_kind == OMP_CLAUSE_REDUCTION
4544 && var != OMP_CLAUSE_DECL (c))
4546 if (pass == 0)
4547 continue;
4549 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4550 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4551 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4553 tree b = TREE_OPERAND (orig_var, 1);
4554 b = maybe_lookup_decl (b, ctx);
4555 if (b == NULL)
4557 b = TREE_OPERAND (orig_var, 1);
4558 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4560 if (integer_zerop (bias))
4561 bias = b;
4562 else
4564 bias = fold_convert_loc (clause_loc,
4565 TREE_TYPE (b), bias);
4566 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4567 TREE_TYPE (b), b, bias);
4569 orig_var = TREE_OPERAND (orig_var, 0);
4571 if (TREE_CODE (orig_var) == INDIRECT_REF
4572 || TREE_CODE (orig_var) == ADDR_EXPR)
4573 orig_var = TREE_OPERAND (orig_var, 0);
4574 tree d = OMP_CLAUSE_DECL (c);
4575 tree type = TREE_TYPE (d);
4576 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4577 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4578 const char *name = get_name (orig_var);
4579 if (TREE_CONSTANT (v))
4581 x = create_tmp_var_raw (type, name);
4582 gimple_add_tmp_var (x);
4583 TREE_ADDRESSABLE (x) = 1;
4584 x = build_fold_addr_expr_loc (clause_loc, x);
4586 else
4588 tree atmp
4589 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4590 tree t = maybe_lookup_decl (v, ctx);
4591 if (t)
4592 v = t;
4593 else
4594 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4595 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4596 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4597 TREE_TYPE (v), v,
4598 build_int_cst (TREE_TYPE (v), 1));
4599 t = fold_build2_loc (clause_loc, MULT_EXPR,
4600 TREE_TYPE (v), t,
4601 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4602 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4603 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4606 tree ptype = build_pointer_type (TREE_TYPE (type));
4607 x = fold_convert_loc (clause_loc, ptype, x);
4608 tree y = create_tmp_var (ptype, name);
4609 gimplify_assign (y, x, ilist);
4610 x = y;
4611 tree yb = y;
4613 if (!integer_zerop (bias))
4615 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4616 bias);
4617 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4619 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4620 pointer_sized_int_node, yb, bias);
4621 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4622 yb = create_tmp_var (ptype, name);
4623 gimplify_assign (yb, x, ilist);
4624 x = yb;
4627 d = TREE_OPERAND (d, 0);
4628 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4629 d = TREE_OPERAND (d, 0);
4630 if (TREE_CODE (d) == ADDR_EXPR)
4632 if (orig_var != var)
4634 gcc_assert (is_variable_sized (orig_var));
4635 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4637 gimplify_assign (new_var, x, ilist);
4638 tree new_orig_var = lookup_decl (orig_var, ctx);
4639 tree t = build_fold_indirect_ref (new_var);
4640 DECL_IGNORED_P (new_var) = 0;
4641 TREE_THIS_NOTRAP (t);
4642 SET_DECL_VALUE_EXPR (new_orig_var, t);
4643 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4645 else
4647 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4648 build_int_cst (ptype, 0));
4649 SET_DECL_VALUE_EXPR (new_var, x);
4650 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4653 else
4655 gcc_assert (orig_var == var);
4656 if (TREE_CODE (d) == INDIRECT_REF)
4658 x = create_tmp_var (ptype, name);
4659 TREE_ADDRESSABLE (x) = 1;
4660 gimplify_assign (x, yb, ilist);
4661 x = build_fold_addr_expr_loc (clause_loc, x);
4663 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4664 gimplify_assign (new_var, x, ilist);
4666 tree y1 = create_tmp_var (ptype, NULL);
4667 gimplify_assign (y1, y, ilist);
4668 tree i2 = NULL_TREE, y2 = NULL_TREE;
4669 tree body2 = NULL_TREE, end2 = NULL_TREE;
4670 tree y3 = NULL_TREE, y4 = NULL_TREE;
4671 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4673 y2 = create_tmp_var (ptype, NULL);
4674 gimplify_assign (y2, y, ilist);
4675 tree ref = build_outer_var_ref (var, ctx);
4676 /* For ref build_outer_var_ref already performs this. */
4677 if (TREE_CODE (d) == INDIRECT_REF)
4678 gcc_assert (is_reference (var));
4679 else if (TREE_CODE (d) == ADDR_EXPR)
4680 ref = build_fold_addr_expr (ref);
4681 else if (is_reference (var))
4682 ref = build_fold_addr_expr (ref);
4683 ref = fold_convert_loc (clause_loc, ptype, ref);
4684 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4685 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4687 y3 = create_tmp_var (ptype, NULL);
4688 gimplify_assign (y3, unshare_expr (ref), ilist);
4690 if (is_simd)
4692 y4 = create_tmp_var (ptype, NULL);
4693 gimplify_assign (y4, ref, dlist);
4696 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4697 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4698 tree body = create_artificial_label (UNKNOWN_LOCATION);
4699 tree end = create_artificial_label (UNKNOWN_LOCATION);
4700 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4701 if (y2)
4703 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4704 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4705 body2 = create_artificial_label (UNKNOWN_LOCATION);
4706 end2 = create_artificial_label (UNKNOWN_LOCATION);
4707 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4709 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4711 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4712 tree decl_placeholder
4713 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4714 SET_DECL_VALUE_EXPR (decl_placeholder,
4715 build_simple_mem_ref (y1));
4716 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4717 SET_DECL_VALUE_EXPR (placeholder,
4718 y3 ? build_simple_mem_ref (y3)
4719 : error_mark_node);
4720 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4721 x = lang_hooks.decls.omp_clause_default_ctor
4722 (c, build_simple_mem_ref (y1),
4723 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4724 if (x)
4725 gimplify_and_add (x, ilist);
4726 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4728 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4729 lower_omp (&tseq, ctx);
4730 gimple_seq_add_seq (ilist, tseq);
4732 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4733 if (is_simd)
4735 SET_DECL_VALUE_EXPR (decl_placeholder,
4736 build_simple_mem_ref (y2));
4737 SET_DECL_VALUE_EXPR (placeholder,
4738 build_simple_mem_ref (y4));
4739 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4740 lower_omp (&tseq, ctx);
4741 gimple_seq_add_seq (dlist, tseq);
4742 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4744 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4745 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4746 x = lang_hooks.decls.omp_clause_dtor
4747 (c, build_simple_mem_ref (y2));
4748 if (x)
4750 gimple_seq tseq = NULL;
4751 dtor = x;
4752 gimplify_stmt (&dtor, &tseq);
4753 gimple_seq_add_seq (dlist, tseq);
4756 else
4758 x = omp_reduction_init (c, TREE_TYPE (type));
4759 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4761 /* reduction(-:var) sums up the partial results, so it
4762 acts identically to reduction(+:var). */
4763 if (code == MINUS_EXPR)
4764 code = PLUS_EXPR;
4766 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4767 if (is_simd)
4769 x = build2 (code, TREE_TYPE (type),
4770 build_simple_mem_ref (y4),
4771 build_simple_mem_ref (y2));
4772 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4775 gimple *g
4776 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4777 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4778 gimple_seq_add_stmt (ilist, g);
4779 if (y3)
4781 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4782 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4783 gimple_seq_add_stmt (ilist, g);
4785 g = gimple_build_assign (i, PLUS_EXPR, i,
4786 build_int_cst (TREE_TYPE (i), 1));
4787 gimple_seq_add_stmt (ilist, g);
4788 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4789 gimple_seq_add_stmt (ilist, g);
4790 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4791 if (y2)
4793 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4794 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4795 gimple_seq_add_stmt (dlist, g);
4796 if (y4)
4798 g = gimple_build_assign
4799 (y4, POINTER_PLUS_EXPR, y4,
4800 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4801 gimple_seq_add_stmt (dlist, g);
4803 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4804 build_int_cst (TREE_TYPE (i2), 1));
4805 gimple_seq_add_stmt (dlist, g);
4806 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4807 gimple_seq_add_stmt (dlist, g);
4808 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4810 continue;
4812 else if (is_variable_sized (var))
4814 /* For variable sized types, we need to allocate the
4815 actual storage here. Call alloca and store the
4816 result in the pointer decl that we created elsewhere. */
4817 if (pass == 0)
4818 continue;
4820 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4822 gcall *stmt;
4823 tree tmp, atmp;
4825 ptr = DECL_VALUE_EXPR (new_var);
4826 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4827 ptr = TREE_OPERAND (ptr, 0);
4828 gcc_assert (DECL_P (ptr));
4829 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4831 /* void *tmp = __builtin_alloca */
4832 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4833 stmt = gimple_build_call (atmp, 2, x,
4834 size_int (DECL_ALIGN (var)));
4835 tmp = create_tmp_var_raw (ptr_type_node);
4836 gimple_add_tmp_var (tmp);
4837 gimple_call_set_lhs (stmt, tmp);
4839 gimple_seq_add_stmt (ilist, stmt);
4841 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4842 gimplify_assign (ptr, x, ilist);
4845 else if (is_reference (var))
4847 /* For references that are being privatized for Fortran,
4848 allocate new backing storage for the new pointer
4849 variable. This allows us to avoid changing all the
4850 code that expects a pointer to something that expects
4851 a direct variable. */
4852 if (pass == 0)
4853 continue;
4855 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4856 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4858 x = build_receiver_ref (var, false, ctx);
4859 x = build_fold_addr_expr_loc (clause_loc, x);
4861 else if (TREE_CONSTANT (x))
4863 /* For reduction in SIMD loop, defer adding the
4864 initialization of the reference, because if we decide
4865 to use SIMD array for it, the initilization could cause
4866 expansion ICE. */
4867 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4868 x = NULL_TREE;
4869 else
4871 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4872 get_name (var));
4873 gimple_add_tmp_var (x);
4874 TREE_ADDRESSABLE (x) = 1;
4875 x = build_fold_addr_expr_loc (clause_loc, x);
4878 else
4880 tree atmp
4881 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4882 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4883 tree al = size_int (TYPE_ALIGN (rtype));
4884 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4887 if (x)
4889 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4890 gimplify_assign (new_var, x, ilist);
4893 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4895 else if (c_kind == OMP_CLAUSE_REDUCTION
4896 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4898 if (pass == 0)
4899 continue;
4901 else if (pass != 0)
4902 continue;
4904 switch (OMP_CLAUSE_CODE (c))
4906 case OMP_CLAUSE_SHARED:
4907 /* Ignore shared directives in teams construct. */
4908 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4909 continue;
4910 /* Shared global vars are just accessed directly. */
4911 if (is_global_var (new_var))
4912 break;
4913 /* For taskloop firstprivate/lastprivate, represented
4914 as firstprivate and shared clause on the task, new_var
4915 is the firstprivate var. */
4916 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4917 break;
4918 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4919 needs to be delayed until after fixup_child_record_type so
4920 that we get the correct type during the dereference. */
4921 by_ref = use_pointer_for_field (var, ctx);
4922 x = build_receiver_ref (var, by_ref, ctx);
4923 SET_DECL_VALUE_EXPR (new_var, x);
4924 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4926 /* ??? If VAR is not passed by reference, and the variable
4927 hasn't been initialized yet, then we'll get a warning for
4928 the store into the omp_data_s structure. Ideally, we'd be
4929 able to notice this and not store anything at all, but
4930 we're generating code too early. Suppress the warning. */
4931 if (!by_ref)
4932 TREE_NO_WARNING (var) = 1;
4933 break;
4935 case OMP_CLAUSE_LASTPRIVATE:
4936 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4937 break;
4938 /* FALLTHRU */
4940 case OMP_CLAUSE_PRIVATE:
4941 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4942 x = build_outer_var_ref (var, ctx);
4943 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4945 if (is_task_ctx (ctx))
4946 x = build_receiver_ref (var, false, ctx);
4947 else
4948 x = build_outer_var_ref (var, ctx);
4950 else
4951 x = NULL;
4952 do_private:
4953 tree nx;
4954 nx = lang_hooks.decls.omp_clause_default_ctor
4955 (c, unshare_expr (new_var), x);
4956 if (is_simd)
4958 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4959 if ((TREE_ADDRESSABLE (new_var) || nx || y
4960 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4961 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4962 idx, lane, ivar, lvar))
4964 if (nx)
4965 x = lang_hooks.decls.omp_clause_default_ctor
4966 (c, unshare_expr (ivar), x);
4967 if (nx && x)
4968 gimplify_and_add (x, &llist[0]);
4969 if (y)
4971 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4972 if (y)
4974 gimple_seq tseq = NULL;
4976 dtor = y;
4977 gimplify_stmt (&dtor, &tseq);
4978 gimple_seq_add_seq (&llist[1], tseq);
4981 break;
4984 if (nx)
4985 gimplify_and_add (nx, ilist);
4986 /* FALLTHRU */
4988 do_dtor:
4989 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4990 if (x)
4992 gimple_seq tseq = NULL;
4994 dtor = x;
4995 gimplify_stmt (&dtor, &tseq);
4996 gimple_seq_add_seq (dlist, tseq);
4998 break;
5000 case OMP_CLAUSE_LINEAR:
5001 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
5002 goto do_firstprivate;
5003 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5004 x = NULL;
5005 else
5006 x = build_outer_var_ref (var, ctx);
5007 goto do_private;
5009 case OMP_CLAUSE_FIRSTPRIVATE:
5010 if (is_task_ctx (ctx))
5012 if (is_reference (var) || is_variable_sized (var))
5013 goto do_dtor;
5014 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5015 ctx))
5016 || use_pointer_for_field (var, NULL))
5018 x = build_receiver_ref (var, false, ctx);
5019 SET_DECL_VALUE_EXPR (new_var, x);
5020 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5021 goto do_dtor;
5024 do_firstprivate:
5025 x = build_outer_var_ref (var, ctx);
5026 if (is_simd)
5028 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5029 && gimple_omp_for_combined_into_p (ctx->stmt))
5031 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5032 tree stept = TREE_TYPE (t);
5033 tree ct = find_omp_clause (clauses,
5034 OMP_CLAUSE__LOOPTEMP_);
5035 gcc_assert (ct);
5036 tree l = OMP_CLAUSE_DECL (ct);
5037 tree n1 = fd->loop.n1;
5038 tree step = fd->loop.step;
5039 tree itype = TREE_TYPE (l);
5040 if (POINTER_TYPE_P (itype))
5041 itype = signed_type_for (itype);
5042 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5043 if (TYPE_UNSIGNED (itype)
5044 && fd->loop.cond_code == GT_EXPR)
5045 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5046 fold_build1 (NEGATE_EXPR, itype, l),
5047 fold_build1 (NEGATE_EXPR,
5048 itype, step));
5049 else
5050 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5051 t = fold_build2 (MULT_EXPR, stept,
5052 fold_convert (stept, l), t);
5054 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5056 x = lang_hooks.decls.omp_clause_linear_ctor
5057 (c, new_var, x, t);
5058 gimplify_and_add (x, ilist);
5059 goto do_dtor;
5062 if (POINTER_TYPE_P (TREE_TYPE (x)))
5063 x = fold_build2 (POINTER_PLUS_EXPR,
5064 TREE_TYPE (x), x, t);
5065 else
5066 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5069 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5070 || TREE_ADDRESSABLE (new_var))
5071 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5072 idx, lane, ivar, lvar))
5074 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5076 tree iv = create_tmp_var (TREE_TYPE (new_var));
5077 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5078 gimplify_and_add (x, ilist);
5079 gimple_stmt_iterator gsi
5080 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5081 gassign *g
5082 = gimple_build_assign (unshare_expr (lvar), iv);
5083 gsi_insert_before_without_update (&gsi, g,
5084 GSI_SAME_STMT);
5085 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5086 enum tree_code code = PLUS_EXPR;
5087 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5088 code = POINTER_PLUS_EXPR;
5089 g = gimple_build_assign (iv, code, iv, t);
5090 gsi_insert_before_without_update (&gsi, g,
5091 GSI_SAME_STMT);
5092 break;
5094 x = lang_hooks.decls.omp_clause_copy_ctor
5095 (c, unshare_expr (ivar), x);
5096 gimplify_and_add (x, &llist[0]);
5097 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5098 if (x)
5100 gimple_seq tseq = NULL;
5102 dtor = x;
5103 gimplify_stmt (&dtor, &tseq);
5104 gimple_seq_add_seq (&llist[1], tseq);
5106 break;
5109 x = lang_hooks.decls.omp_clause_copy_ctor
5110 (c, unshare_expr (new_var), x);
5111 gimplify_and_add (x, ilist);
5112 goto do_dtor;
5114 case OMP_CLAUSE__LOOPTEMP_:
5115 gcc_assert (is_taskreg_ctx (ctx));
5116 x = build_outer_var_ref (var, ctx);
5117 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5118 gimplify_and_add (x, ilist);
5119 break;
5121 case OMP_CLAUSE_COPYIN:
5122 by_ref = use_pointer_for_field (var, NULL);
5123 x = build_receiver_ref (var, by_ref, ctx);
5124 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5125 append_to_statement_list (x, &copyin_seq);
5126 copyin_by_ref |= by_ref;
5127 break;
5129 case OMP_CLAUSE_REDUCTION:
5130 /* OpenACC reductions are initialized using the
5131 GOACC_REDUCTION internal function. */
5132 if (is_gimple_omp_oacc (ctx->stmt))
5133 break;
5134 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5136 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5137 gimple *tseq;
5138 x = build_outer_var_ref (var, ctx);
5140 if (is_reference (var)
5141 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5142 TREE_TYPE (x)))
5143 x = build_fold_addr_expr_loc (clause_loc, x);
5144 SET_DECL_VALUE_EXPR (placeholder, x);
5145 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5146 tree new_vard = new_var;
5147 if (is_reference (var))
5149 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5150 new_vard = TREE_OPERAND (new_var, 0);
5151 gcc_assert (DECL_P (new_vard));
5153 if (is_simd
5154 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5155 idx, lane, ivar, lvar))
5157 if (new_vard == new_var)
5159 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5160 SET_DECL_VALUE_EXPR (new_var, ivar);
5162 else
5164 SET_DECL_VALUE_EXPR (new_vard,
5165 build_fold_addr_expr (ivar));
5166 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5168 x = lang_hooks.decls.omp_clause_default_ctor
5169 (c, unshare_expr (ivar),
5170 build_outer_var_ref (var, ctx));
5171 if (x)
5172 gimplify_and_add (x, &llist[0]);
5173 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5175 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5176 lower_omp (&tseq, ctx);
5177 gimple_seq_add_seq (&llist[0], tseq);
5179 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5180 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5181 lower_omp (&tseq, ctx);
5182 gimple_seq_add_seq (&llist[1], tseq);
5183 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5184 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5185 if (new_vard == new_var)
5186 SET_DECL_VALUE_EXPR (new_var, lvar);
5187 else
5188 SET_DECL_VALUE_EXPR (new_vard,
5189 build_fold_addr_expr (lvar));
5190 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5191 if (x)
5193 tseq = NULL;
5194 dtor = x;
5195 gimplify_stmt (&dtor, &tseq);
5196 gimple_seq_add_seq (&llist[1], tseq);
5198 break;
5200 /* If this is a reference to constant size reduction var
5201 with placeholder, we haven't emitted the initializer
5202 for it because it is undesirable if SIMD arrays are used.
5203 But if they aren't used, we need to emit the deferred
5204 initialization now. */
5205 else if (is_reference (var) && is_simd)
5206 handle_simd_reference (clause_loc, new_vard, ilist);
5207 x = lang_hooks.decls.omp_clause_default_ctor
5208 (c, unshare_expr (new_var),
5209 build_outer_var_ref (var, ctx));
5210 if (x)
5211 gimplify_and_add (x, ilist);
5212 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5214 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5215 lower_omp (&tseq, ctx);
5216 gimple_seq_add_seq (ilist, tseq);
5218 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5219 if (is_simd)
5221 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5222 lower_omp (&tseq, ctx);
5223 gimple_seq_add_seq (dlist, tseq);
5224 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5226 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5227 goto do_dtor;
5229 else
5231 x = omp_reduction_init (c, TREE_TYPE (new_var));
5232 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5233 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5235 /* reduction(-:var) sums up the partial results, so it
5236 acts identically to reduction(+:var). */
5237 if (code == MINUS_EXPR)
5238 code = PLUS_EXPR;
5240 tree new_vard = new_var;
5241 if (is_simd && is_reference (var))
5243 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5244 new_vard = TREE_OPERAND (new_var, 0);
5245 gcc_assert (DECL_P (new_vard));
5247 if (is_simd
5248 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5249 idx, lane, ivar, lvar))
5251 tree ref = build_outer_var_ref (var, ctx);
5253 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5255 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5256 ref = build_outer_var_ref (var, ctx);
5257 gimplify_assign (ref, x, &llist[1]);
5259 if (new_vard != new_var)
5261 SET_DECL_VALUE_EXPR (new_vard,
5262 build_fold_addr_expr (lvar));
5263 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5266 else
5268 if (is_reference (var) && is_simd)
5269 handle_simd_reference (clause_loc, new_vard, ilist);
5270 gimplify_assign (new_var, x, ilist);
5271 if (is_simd)
5273 tree ref = build_outer_var_ref (var, ctx);
5275 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5276 ref = build_outer_var_ref (var, ctx);
5277 gimplify_assign (ref, x, dlist);
5281 break;
5283 default:
5284 gcc_unreachable ();
5289 if (lane)
5291 tree uid = create_tmp_var (ptr_type_node, "simduid");
5292 /* Don't want uninit warnings on simduid, it is always uninitialized,
5293 but we use it not for the value, but for the DECL_UID only. */
5294 TREE_NO_WARNING (uid) = 1;
5295 gimple *g
5296 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5297 gimple_call_set_lhs (g, lane);
5298 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5299 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5300 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5301 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5302 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5303 gimple_omp_for_set_clauses (ctx->stmt, c);
5304 g = gimple_build_assign (lane, INTEGER_CST,
5305 build_int_cst (unsigned_type_node, 0));
5306 gimple_seq_add_stmt (ilist, g);
5307 for (int i = 0; i < 2; i++)
5308 if (llist[i])
5310 tree vf = create_tmp_var (unsigned_type_node);
5311 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5312 gimple_call_set_lhs (g, vf);
5313 gimple_seq *seq = i == 0 ? ilist : dlist;
5314 gimple_seq_add_stmt (seq, g);
5315 tree t = build_int_cst (unsigned_type_node, 0);
5316 g = gimple_build_assign (idx, INTEGER_CST, t);
5317 gimple_seq_add_stmt (seq, g);
5318 tree body = create_artificial_label (UNKNOWN_LOCATION);
5319 tree header = create_artificial_label (UNKNOWN_LOCATION);
5320 tree end = create_artificial_label (UNKNOWN_LOCATION);
5321 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5322 gimple_seq_add_stmt (seq, gimple_build_label (body));
5323 gimple_seq_add_seq (seq, llist[i]);
5324 t = build_int_cst (unsigned_type_node, 1);
5325 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5326 gimple_seq_add_stmt (seq, g);
5327 gimple_seq_add_stmt (seq, gimple_build_label (header));
5328 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5329 gimple_seq_add_stmt (seq, g);
5330 gimple_seq_add_stmt (seq, gimple_build_label (end));
5334 /* The copyin sequence is not to be executed by the main thread, since
5335 that would result in self-copies. Perhaps not visible to scalars,
5336 but it certainly is to C++ operator=. */
5337 if (copyin_seq)
5339 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5341 x = build2 (NE_EXPR, boolean_type_node, x,
5342 build_int_cst (TREE_TYPE (x), 0));
5343 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5344 gimplify_and_add (x, ilist);
5347 /* If any copyin variable is passed by reference, we must ensure the
5348 master thread doesn't modify it before it is copied over in all
5349 threads. Similarly for variables in both firstprivate and
5350 lastprivate clauses we need to ensure the lastprivate copying
5351 happens after firstprivate copying in all threads. And similarly
5352 for UDRs if initializer expression refers to omp_orig. */
5353 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5355 /* Don't add any barrier for #pragma omp simd or
5356 #pragma omp distribute. */
5357 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5358 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5359 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5362 /* If max_vf is non-zero, then we can use only a vectorization factor
5363 up to the max_vf we chose. So stick it into the safelen clause. */
5364 if (max_vf)
5366 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5367 OMP_CLAUSE_SAFELEN);
5368 if (c == NULL_TREE
5369 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5370 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5371 max_vf) == 1))
5373 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5374 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5375 max_vf);
5376 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5377 gimple_omp_for_set_clauses (ctx->stmt, c);
5383 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5384 both parallel and workshare constructs. PREDICATE may be NULL if it's
5385 always true. */
5387 static void
5388 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5389 omp_context *ctx)
5391 tree x, c, label = NULL, orig_clauses = clauses;
5392 bool par_clauses = false;
5393 tree simduid = NULL, lastlane = NULL;
5395 /* Early exit if there are no lastprivate or linear clauses. */
5396 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5397 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5398 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5399 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5400 break;
5401 if (clauses == NULL)
5403 /* If this was a workshare clause, see if it had been combined
5404 with its parallel. In that case, look for the clauses on the
5405 parallel statement itself. */
5406 if (is_parallel_ctx (ctx))
5407 return;
5409 ctx = ctx->outer;
5410 if (ctx == NULL || !is_parallel_ctx (ctx))
5411 return;
5413 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5414 OMP_CLAUSE_LASTPRIVATE);
5415 if (clauses == NULL)
5416 return;
5417 par_clauses = true;
5420 if (predicate)
5422 gcond *stmt;
5423 tree label_true, arm1, arm2;
5425 label = create_artificial_label (UNKNOWN_LOCATION);
5426 label_true = create_artificial_label (UNKNOWN_LOCATION);
5427 arm1 = TREE_OPERAND (predicate, 0);
5428 arm2 = TREE_OPERAND (predicate, 1);
5429 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5430 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5431 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5432 label_true, label);
5433 gimple_seq_add_stmt (stmt_list, stmt);
5434 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5437 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5438 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5440 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5441 if (simduid)
5442 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5445 for (c = clauses; c ;)
5447 tree var, new_var;
5448 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5450 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5451 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5452 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5454 var = OMP_CLAUSE_DECL (c);
5455 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5456 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5457 && is_taskloop_ctx (ctx))
5459 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5460 new_var = lookup_decl (var, ctx->outer);
5462 else
5463 new_var = lookup_decl (var, ctx);
5465 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5467 tree val = DECL_VALUE_EXPR (new_var);
5468 if (TREE_CODE (val) == ARRAY_REF
5469 && VAR_P (TREE_OPERAND (val, 0))
5470 && lookup_attribute ("omp simd array",
5471 DECL_ATTRIBUTES (TREE_OPERAND (val,
5472 0))))
5474 if (lastlane == NULL)
5476 lastlane = create_tmp_var (unsigned_type_node);
5477 gcall *g
5478 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5479 2, simduid,
5480 TREE_OPERAND (val, 1));
5481 gimple_call_set_lhs (g, lastlane);
5482 gimple_seq_add_stmt (stmt_list, g);
5484 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5485 TREE_OPERAND (val, 0), lastlane,
5486 NULL_TREE, NULL_TREE);
5490 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5491 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5493 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5494 gimple_seq_add_seq (stmt_list,
5495 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5496 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5498 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5499 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5501 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5502 gimple_seq_add_seq (stmt_list,
5503 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5504 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5507 x = NULL_TREE;
5508 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5509 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5511 gcc_checking_assert (is_taskloop_ctx (ctx));
5512 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5513 ctx->outer->outer);
5514 if (is_global_var (ovar))
5515 x = ovar;
5517 if (!x)
5518 x = build_outer_var_ref (var, ctx, true);
5519 if (is_reference (var))
5520 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5521 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5522 gimplify_and_add (x, stmt_list);
5524 c = OMP_CLAUSE_CHAIN (c);
5525 if (c == NULL && !par_clauses)
5527 /* If this was a workshare clause, see if it had been combined
5528 with its parallel. In that case, continue looking for the
5529 clauses also on the parallel statement itself. */
5530 if (is_parallel_ctx (ctx))
5531 break;
5533 ctx = ctx->outer;
5534 if (ctx == NULL || !is_parallel_ctx (ctx))
5535 break;
5537 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5538 OMP_CLAUSE_LASTPRIVATE);
5539 par_clauses = true;
5543 if (label)
5544 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5547 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5548 (which might be a placeholder). INNER is true if this is an inner
5549 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5550 join markers. Generate the before-loop forking sequence in
5551 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5552 general form of these sequences is
5554 GOACC_REDUCTION_SETUP
5555 GOACC_FORK
5556 GOACC_REDUCTION_INIT
5558 GOACC_REDUCTION_FINI
5559 GOACC_JOIN
5560 GOACC_REDUCTION_TEARDOWN. */
5562 static void
5563 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5564 gcall *fork, gcall *join, gimple_seq *fork_seq,
5565 gimple_seq *join_seq, omp_context *ctx)
5567 gimple_seq before_fork = NULL;
5568 gimple_seq after_fork = NULL;
5569 gimple_seq before_join = NULL;
5570 gimple_seq after_join = NULL;
5571 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5572 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5573 unsigned offset = 0;
5575 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5576 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5578 tree orig = OMP_CLAUSE_DECL (c);
5579 tree var = maybe_lookup_decl (orig, ctx);
5580 tree ref_to_res = NULL_TREE;
5581 tree incoming, outgoing, v1, v2, v3;
5582 bool is_private = false;
5584 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5585 if (rcode == MINUS_EXPR)
5586 rcode = PLUS_EXPR;
5587 else if (rcode == TRUTH_ANDIF_EXPR)
5588 rcode = BIT_AND_EXPR;
5589 else if (rcode == TRUTH_ORIF_EXPR)
5590 rcode = BIT_IOR_EXPR;
5591 tree op = build_int_cst (unsigned_type_node, rcode);
5593 if (!var)
5594 var = orig;
5596 incoming = outgoing = var;
5598 if (!inner)
5600 /* See if an outer construct also reduces this variable. */
5601 omp_context *outer = ctx;
5603 while (omp_context *probe = outer->outer)
5605 enum gimple_code type = gimple_code (probe->stmt);
5606 tree cls;
5608 switch (type)
5610 case GIMPLE_OMP_FOR:
5611 cls = gimple_omp_for_clauses (probe->stmt);
5612 break;
5614 case GIMPLE_OMP_TARGET:
5615 if (gimple_omp_target_kind (probe->stmt)
5616 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5617 goto do_lookup;
5619 cls = gimple_omp_target_clauses (probe->stmt);
5620 break;
5622 default:
5623 goto do_lookup;
5626 outer = probe;
5627 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5628 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5629 && orig == OMP_CLAUSE_DECL (cls))
5631 incoming = outgoing = lookup_decl (orig, probe);
5632 goto has_outer_reduction;
5634 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5635 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5636 && orig == OMP_CLAUSE_DECL (cls))
5638 is_private = true;
5639 goto do_lookup;
5643 do_lookup:
5644 /* This is the outermost construct with this reduction,
5645 see if there's a mapping for it. */
5646 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5647 && maybe_lookup_field (orig, outer) && !is_private)
5649 ref_to_res = build_receiver_ref (orig, false, outer);
5650 if (is_reference (orig))
5651 ref_to_res = build_simple_mem_ref (ref_to_res);
5653 tree type = TREE_TYPE (var);
5654 if (POINTER_TYPE_P (type))
5655 type = TREE_TYPE (type);
5657 outgoing = var;
5658 incoming = omp_reduction_init_op (loc, rcode, type);
5660 else if (ctx->outer)
5661 incoming = outgoing = lookup_decl (orig, ctx->outer);
5662 else
5663 incoming = outgoing = orig;
5665 has_outer_reduction:;
5668 if (!ref_to_res)
5669 ref_to_res = integer_zero_node;
5671 if (is_reference (orig))
5673 tree type = TREE_TYPE (var);
5674 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5676 if (!inner)
5678 tree x = create_tmp_var (TREE_TYPE (type), id);
5679 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5682 v1 = create_tmp_var (type, id);
5683 v2 = create_tmp_var (type, id);
5684 v3 = create_tmp_var (type, id);
5686 gimplify_assign (v1, var, fork_seq);
5687 gimplify_assign (v2, var, fork_seq);
5688 gimplify_assign (v3, var, fork_seq);
5690 var = build_simple_mem_ref (var);
5691 v1 = build_simple_mem_ref (v1);
5692 v2 = build_simple_mem_ref (v2);
5693 v3 = build_simple_mem_ref (v3);
5694 outgoing = build_simple_mem_ref (outgoing);
5696 if (!TREE_CONSTANT (incoming))
5697 incoming = build_simple_mem_ref (incoming);
5699 else
5700 v1 = v2 = v3 = var;
5702 /* Determine position in reduction buffer, which may be used
5703 by target. */
5704 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5705 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5706 offset = (offset + align - 1) & ~(align - 1);
5707 tree off = build_int_cst (sizetype, offset);
5708 offset += GET_MODE_SIZE (mode);
5710 if (!init_code)
5712 init_code = build_int_cst (integer_type_node,
5713 IFN_GOACC_REDUCTION_INIT);
5714 fini_code = build_int_cst (integer_type_node,
5715 IFN_GOACC_REDUCTION_FINI);
5716 setup_code = build_int_cst (integer_type_node,
5717 IFN_GOACC_REDUCTION_SETUP);
5718 teardown_code = build_int_cst (integer_type_node,
5719 IFN_GOACC_REDUCTION_TEARDOWN);
5722 tree setup_call
5723 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5724 TREE_TYPE (var), 6, setup_code,
5725 unshare_expr (ref_to_res),
5726 incoming, level, op, off);
5727 tree init_call
5728 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5729 TREE_TYPE (var), 6, init_code,
5730 unshare_expr (ref_to_res),
5731 v1, level, op, off);
5732 tree fini_call
5733 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5734 TREE_TYPE (var), 6, fini_code,
5735 unshare_expr (ref_to_res),
5736 v2, level, op, off);
5737 tree teardown_call
5738 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5739 TREE_TYPE (var), 6, teardown_code,
5740 ref_to_res, v3, level, op, off);
5742 gimplify_assign (v1, setup_call, &before_fork);
5743 gimplify_assign (v2, init_call, &after_fork);
5744 gimplify_assign (v3, fini_call, &before_join);
5745 gimplify_assign (outgoing, teardown_call, &after_join);
5748 /* Now stitch things together. */
5749 gimple_seq_add_seq (fork_seq, before_fork);
5750 if (fork)
5751 gimple_seq_add_stmt (fork_seq, fork);
5752 gimple_seq_add_seq (fork_seq, after_fork);
5754 gimple_seq_add_seq (join_seq, before_join);
5755 if (join)
5756 gimple_seq_add_stmt (join_seq, join);
5757 gimple_seq_add_seq (join_seq, after_join);
5760 /* Generate code to implement the REDUCTION clauses. */
5762 static void
5763 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5765 gimple_seq sub_seq = NULL;
5766 gimple *stmt;
5767 tree x, c;
5768 int count = 0;
5770 /* OpenACC loop reductions are handled elsewhere. */
5771 if (is_gimple_omp_oacc (ctx->stmt))
5772 return;
5774 /* SIMD reductions are handled in lower_rec_input_clauses. */
5775 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5776 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5777 return;
5779 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5780 update in that case, otherwise use a lock. */
5781 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5782 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5784 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5785 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5787 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5788 count = -1;
5789 break;
5791 count++;
5794 if (count == 0)
5795 return;
5797 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5799 tree var, ref, new_var, orig_var;
5800 enum tree_code code;
5801 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5803 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5804 continue;
5806 orig_var = var = OMP_CLAUSE_DECL (c);
5807 if (TREE_CODE (var) == MEM_REF)
5809 var = TREE_OPERAND (var, 0);
5810 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5811 var = TREE_OPERAND (var, 0);
5812 if (TREE_CODE (var) == INDIRECT_REF
5813 || TREE_CODE (var) == ADDR_EXPR)
5814 var = TREE_OPERAND (var, 0);
5815 orig_var = var;
5816 if (is_variable_sized (var))
5818 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5819 var = DECL_VALUE_EXPR (var);
5820 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5821 var = TREE_OPERAND (var, 0);
5822 gcc_assert (DECL_P (var));
5825 new_var = lookup_decl (var, ctx);
5826 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5827 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5828 ref = build_outer_var_ref (var, ctx);
5829 code = OMP_CLAUSE_REDUCTION_CODE (c);
5831 /* reduction(-:var) sums up the partial results, so it acts
5832 identically to reduction(+:var). */
5833 if (code == MINUS_EXPR)
5834 code = PLUS_EXPR;
5836 if (count == 1)
5838 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5840 addr = save_expr (addr);
5841 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5842 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5843 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5844 gimplify_and_add (x, stmt_seqp);
5845 return;
5847 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5849 tree d = OMP_CLAUSE_DECL (c);
5850 tree type = TREE_TYPE (d);
5851 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5852 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5853 tree ptype = build_pointer_type (TREE_TYPE (type));
5854 tree bias = TREE_OPERAND (d, 1);
5855 d = TREE_OPERAND (d, 0);
5856 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5858 tree b = TREE_OPERAND (d, 1);
5859 b = maybe_lookup_decl (b, ctx);
5860 if (b == NULL)
5862 b = TREE_OPERAND (d, 1);
5863 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5865 if (integer_zerop (bias))
5866 bias = b;
5867 else
5869 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5870 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5871 TREE_TYPE (b), b, bias);
5873 d = TREE_OPERAND (d, 0);
5875 /* For ref build_outer_var_ref already performs this, so
5876 only new_var needs a dereference. */
5877 if (TREE_CODE (d) == INDIRECT_REF)
5879 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5880 gcc_assert (is_reference (var) && var == orig_var);
5882 else if (TREE_CODE (d) == ADDR_EXPR)
5884 if (orig_var == var)
5886 new_var = build_fold_addr_expr (new_var);
5887 ref = build_fold_addr_expr (ref);
5890 else
5892 gcc_assert (orig_var == var);
5893 if (is_reference (var))
5894 ref = build_fold_addr_expr (ref);
5896 if (DECL_P (v))
5898 tree t = maybe_lookup_decl (v, ctx);
5899 if (t)
5900 v = t;
5901 else
5902 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5903 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5905 if (!integer_zerop (bias))
5907 bias = fold_convert_loc (clause_loc, sizetype, bias);
5908 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5909 TREE_TYPE (new_var), new_var,
5910 unshare_expr (bias));
5911 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5912 TREE_TYPE (ref), ref, bias);
5914 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5915 ref = fold_convert_loc (clause_loc, ptype, ref);
5916 tree m = create_tmp_var (ptype, NULL);
5917 gimplify_assign (m, new_var, stmt_seqp);
5918 new_var = m;
5919 m = create_tmp_var (ptype, NULL);
5920 gimplify_assign (m, ref, stmt_seqp);
5921 ref = m;
5922 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5923 tree body = create_artificial_label (UNKNOWN_LOCATION);
5924 tree end = create_artificial_label (UNKNOWN_LOCATION);
5925 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5926 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5927 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5928 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5930 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5931 tree decl_placeholder
5932 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5933 SET_DECL_VALUE_EXPR (placeholder, out);
5934 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5935 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5936 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5937 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5938 gimple_seq_add_seq (&sub_seq,
5939 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5940 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5941 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5942 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5944 else
5946 x = build2 (code, TREE_TYPE (out), out, priv);
5947 out = unshare_expr (out);
5948 gimplify_assign (out, x, &sub_seq);
5950 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5951 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5952 gimple_seq_add_stmt (&sub_seq, g);
5953 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5954 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5955 gimple_seq_add_stmt (&sub_seq, g);
5956 g = gimple_build_assign (i, PLUS_EXPR, i,
5957 build_int_cst (TREE_TYPE (i), 1));
5958 gimple_seq_add_stmt (&sub_seq, g);
5959 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5960 gimple_seq_add_stmt (&sub_seq, g);
5961 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5963 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5965 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5967 if (is_reference (var)
5968 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5969 TREE_TYPE (ref)))
5970 ref = build_fold_addr_expr_loc (clause_loc, ref);
5971 SET_DECL_VALUE_EXPR (placeholder, ref);
5972 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5973 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5974 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5975 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5976 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5978 else
5980 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5981 ref = build_outer_var_ref (var, ctx);
5982 gimplify_assign (ref, x, &sub_seq);
5986 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5988 gimple_seq_add_stmt (stmt_seqp, stmt);
5990 gimple_seq_add_seq (stmt_seqp, sub_seq);
5992 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5994 gimple_seq_add_stmt (stmt_seqp, stmt);
5998 /* Generate code to implement the COPYPRIVATE clauses. */
6000 static void
6001 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
6002 omp_context *ctx)
6004 tree c;
6006 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6008 tree var, new_var, ref, x;
6009 bool by_ref;
6010 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6012 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6013 continue;
6015 var = OMP_CLAUSE_DECL (c);
6016 by_ref = use_pointer_for_field (var, NULL);
6018 ref = build_sender_ref (var, ctx);
6019 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6020 if (by_ref)
6022 x = build_fold_addr_expr_loc (clause_loc, new_var);
6023 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6025 gimplify_assign (ref, x, slist);
6027 ref = build_receiver_ref (var, false, ctx);
6028 if (by_ref)
6030 ref = fold_convert_loc (clause_loc,
6031 build_pointer_type (TREE_TYPE (new_var)),
6032 ref);
6033 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6035 if (is_reference (var))
6037 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6038 ref = build_simple_mem_ref_loc (clause_loc, ref);
6039 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6041 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6042 gimplify_and_add (x, rlist);
6047 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6048 and REDUCTION from the sender (aka parent) side. */
6050 static void
6051 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6052 omp_context *ctx)
6054 tree c, t;
6055 int ignored_looptemp = 0;
6056 bool is_taskloop = false;
6058 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6059 by GOMP_taskloop. */
6060 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6062 ignored_looptemp = 2;
6063 is_taskloop = true;
6066 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6068 tree val, ref, x, var;
6069 bool by_ref, do_in = false, do_out = false;
6070 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6072 switch (OMP_CLAUSE_CODE (c))
6074 case OMP_CLAUSE_PRIVATE:
6075 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6076 break;
6077 continue;
6078 case OMP_CLAUSE_FIRSTPRIVATE:
6079 case OMP_CLAUSE_COPYIN:
6080 case OMP_CLAUSE_LASTPRIVATE:
6081 case OMP_CLAUSE_REDUCTION:
6082 break;
6083 case OMP_CLAUSE_SHARED:
6084 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6085 break;
6086 continue;
6087 case OMP_CLAUSE__LOOPTEMP_:
6088 if (ignored_looptemp)
6090 ignored_looptemp--;
6091 continue;
6093 break;
6094 default:
6095 continue;
6098 val = OMP_CLAUSE_DECL (c);
6099 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6100 && TREE_CODE (val) == MEM_REF)
6102 val = TREE_OPERAND (val, 0);
6103 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6104 val = TREE_OPERAND (val, 0);
6105 if (TREE_CODE (val) == INDIRECT_REF
6106 || TREE_CODE (val) == ADDR_EXPR)
6107 val = TREE_OPERAND (val, 0);
6108 if (is_variable_sized (val))
6109 continue;
6112 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6113 outer taskloop region. */
6114 omp_context *ctx_for_o = ctx;
6115 if (is_taskloop
6116 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6117 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6118 ctx_for_o = ctx->outer;
6120 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6122 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6123 && is_global_var (var))
6124 continue;
6126 t = omp_member_access_dummy_var (var);
6127 if (t)
6129 var = DECL_VALUE_EXPR (var);
6130 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6131 if (o != t)
6132 var = unshare_and_remap (var, t, o);
6133 else
6134 var = unshare_expr (var);
6137 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6139 /* Handle taskloop firstprivate/lastprivate, where the
6140 lastprivate on GIMPLE_OMP_TASK is represented as
6141 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6142 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6143 x = omp_build_component_ref (ctx->sender_decl, f);
6144 if (use_pointer_for_field (val, ctx))
6145 var = build_fold_addr_expr (var);
6146 gimplify_assign (x, var, ilist);
6147 DECL_ABSTRACT_ORIGIN (f) = NULL;
6148 continue;
6151 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6152 || val == OMP_CLAUSE_DECL (c))
6153 && is_variable_sized (val))
6154 continue;
6155 by_ref = use_pointer_for_field (val, NULL);
6157 switch (OMP_CLAUSE_CODE (c))
6159 case OMP_CLAUSE_FIRSTPRIVATE:
6160 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6161 && !by_ref
6162 && is_task_ctx (ctx))
6163 TREE_NO_WARNING (var) = 1;
6164 do_in = true;
6165 break;
6167 case OMP_CLAUSE_PRIVATE:
6168 case OMP_CLAUSE_COPYIN:
6169 case OMP_CLAUSE__LOOPTEMP_:
6170 do_in = true;
6171 break;
6173 case OMP_CLAUSE_LASTPRIVATE:
6174 if (by_ref || is_reference (val))
6176 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6177 continue;
6178 do_in = true;
6180 else
6182 do_out = true;
6183 if (lang_hooks.decls.omp_private_outer_ref (val))
6184 do_in = true;
6186 break;
6188 case OMP_CLAUSE_REDUCTION:
6189 do_in = true;
6190 if (val == OMP_CLAUSE_DECL (c))
6191 do_out = !(by_ref || is_reference (val));
6192 else
6193 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6194 break;
6196 default:
6197 gcc_unreachable ();
6200 if (do_in)
6202 ref = build_sender_ref (val, ctx);
6203 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6204 gimplify_assign (ref, x, ilist);
6205 if (is_task_ctx (ctx))
6206 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6209 if (do_out)
6211 ref = build_sender_ref (val, ctx);
6212 gimplify_assign (var, ref, olist);
6217 /* Generate code to implement SHARED from the sender (aka parent)
6218 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6219 list things that got automatically shared. */
6221 static void
6222 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6224 tree var, ovar, nvar, t, f, x, record_type;
6226 if (ctx->record_type == NULL)
6227 return;
6229 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6230 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6232 ovar = DECL_ABSTRACT_ORIGIN (f);
6233 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6234 continue;
6236 nvar = maybe_lookup_decl (ovar, ctx);
6237 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6238 continue;
6240 /* If CTX is a nested parallel directive. Find the immediately
6241 enclosing parallel or workshare construct that contains a
6242 mapping for OVAR. */
6243 var = lookup_decl_in_outer_ctx (ovar, ctx);
6245 t = omp_member_access_dummy_var (var);
6246 if (t)
6248 var = DECL_VALUE_EXPR (var);
6249 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6250 if (o != t)
6251 var = unshare_and_remap (var, t, o);
6252 else
6253 var = unshare_expr (var);
6256 if (use_pointer_for_field (ovar, ctx))
6258 x = build_sender_ref (ovar, ctx);
6259 var = build_fold_addr_expr (var);
6260 gimplify_assign (x, var, ilist);
6262 else
6264 x = build_sender_ref (ovar, ctx);
6265 gimplify_assign (x, var, ilist);
6267 if (!TREE_READONLY (var)
6268 /* We don't need to receive a new reference to a result
6269 or parm decl. In fact we may not store to it as we will
6270 invalidate any pending RSO and generate wrong gimple
6271 during inlining. */
6272 && !((TREE_CODE (var) == RESULT_DECL
6273 || TREE_CODE (var) == PARM_DECL)
6274 && DECL_BY_REFERENCE (var)))
6276 x = build_sender_ref (ovar, ctx);
6277 gimplify_assign (var, x, olist);
6283 /* Emit an OpenACC head marker call, encapulating the partitioning and
6284 other information that must be processed by the target compiler.
6285 Return the maximum number of dimensions the associated loop might
6286 be partitioned over. */
6288 static unsigned
6289 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6290 gimple_seq *seq, omp_context *ctx)
6292 unsigned levels = 0;
6293 unsigned tag = 0;
6294 tree gang_static = NULL_TREE;
6295 auto_vec<tree, 5> args;
6297 args.quick_push (build_int_cst
6298 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6299 args.quick_push (ddvar);
6300 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6302 switch (OMP_CLAUSE_CODE (c))
6304 case OMP_CLAUSE_GANG:
6305 tag |= OLF_DIM_GANG;
6306 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6307 /* static:* is represented by -1, and we can ignore it, as
6308 scheduling is always static. */
6309 if (gang_static && integer_minus_onep (gang_static))
6310 gang_static = NULL_TREE;
6311 levels++;
6312 break;
6314 case OMP_CLAUSE_WORKER:
6315 tag |= OLF_DIM_WORKER;
6316 levels++;
6317 break;
6319 case OMP_CLAUSE_VECTOR:
6320 tag |= OLF_DIM_VECTOR;
6321 levels++;
6322 break;
6324 case OMP_CLAUSE_SEQ:
6325 tag |= OLF_SEQ;
6326 break;
6328 case OMP_CLAUSE_AUTO:
6329 tag |= OLF_AUTO;
6330 break;
6332 case OMP_CLAUSE_INDEPENDENT:
6333 tag |= OLF_INDEPENDENT;
6334 break;
6336 default:
6337 continue;
6341 if (gang_static)
6343 if (DECL_P (gang_static))
6344 gang_static = build_outer_var_ref (gang_static, ctx);
6345 tag |= OLF_GANG_STATIC;
6348 /* In a parallel region, loops are implicitly INDEPENDENT. */
6349 omp_context *tgt = enclosing_target_ctx (ctx);
6350 if (!tgt || is_oacc_parallel (tgt))
6351 tag |= OLF_INDEPENDENT;
6353 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6354 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6355 | OLF_SEQ)))
6356 tag |= OLF_AUTO;
6358 /* Ensure at least one level. */
6359 if (!levels)
6360 levels++;
6362 args.quick_push (build_int_cst (integer_type_node, levels));
6363 args.quick_push (build_int_cst (integer_type_node, tag));
6364 if (gang_static)
6365 args.quick_push (gang_static);
6367 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6368 gimple_set_location (call, loc);
6369 gimple_set_lhs (call, ddvar);
6370 gimple_seq_add_stmt (seq, call);
6372 return levels;
6375 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6376 partitioning level of the enclosed region. */
6378 static void
6379 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6380 tree tofollow, gimple_seq *seq)
6382 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6383 : IFN_UNIQUE_OACC_TAIL_MARK);
6384 tree marker = build_int_cst (integer_type_node, marker_kind);
6385 int nargs = 2 + (tofollow != NULL_TREE);
6386 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6387 marker, ddvar, tofollow);
6388 gimple_set_location (call, loc);
6389 gimple_set_lhs (call, ddvar);
6390 gimple_seq_add_stmt (seq, call);
6393 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6394 the loop clauses, from which we extract reductions. Initialize
6395 HEAD and TAIL. */
6397 static void
6398 lower_oacc_head_tail (location_t loc, tree clauses,
6399 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6401 bool inner = false;
6402 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6403 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6405 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6406 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6407 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6409 gcc_assert (count);
6410 for (unsigned done = 1; count; count--, done++)
6412 gimple_seq fork_seq = NULL;
6413 gimple_seq join_seq = NULL;
6415 tree place = build_int_cst (integer_type_node, -1);
6416 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6417 fork_kind, ddvar, place);
6418 gimple_set_location (fork, loc);
6419 gimple_set_lhs (fork, ddvar);
6421 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6422 join_kind, ddvar, place);
6423 gimple_set_location (join, loc);
6424 gimple_set_lhs (join, ddvar);
6426 /* Mark the beginning of this level sequence. */
6427 if (inner)
6428 lower_oacc_loop_marker (loc, ddvar, true,
6429 build_int_cst (integer_type_node, count),
6430 &fork_seq);
6431 lower_oacc_loop_marker (loc, ddvar, false,
6432 build_int_cst (integer_type_node, done),
6433 &join_seq);
6435 lower_oacc_reductions (loc, clauses, place, inner,
6436 fork, join, &fork_seq, &join_seq, ctx);
6438 /* Append this level to head. */
6439 gimple_seq_add_seq (head, fork_seq);
6440 /* Prepend it to tail. */
6441 gimple_seq_add_seq (&join_seq, *tail);
6442 *tail = join_seq;
6444 inner = true;
6447 /* Mark the end of the sequence. */
6448 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6449 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6452 /* A convenience function to build an empty GIMPLE_COND with just the
6453 condition. */
6455 static gcond *
6456 gimple_build_cond_empty (tree cond)
6458 enum tree_code pred_code;
6459 tree lhs, rhs;
6461 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6462 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6465 /* Return true if a parallel REGION is within a declare target function or
6466 within a target region and is not a part of a gridified target. */
6468 static bool
6469 parallel_needs_hsa_kernel_p (struct omp_region *region)
6471 bool indirect = false;
6472 for (region = region->outer; region; region = region->outer)
6474 if (region->type == GIMPLE_OMP_PARALLEL)
6475 indirect = true;
6476 else if (region->type == GIMPLE_OMP_TARGET)
6478 gomp_target *tgt_stmt
6479 = as_a <gomp_target *> (last_stmt (region->entry));
6481 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6482 OMP_CLAUSE__GRIDDIM_))
6483 return indirect;
6484 else
6485 return true;
6489 if (lookup_attribute ("omp declare target",
6490 DECL_ATTRIBUTES (current_function_decl)))
6491 return true;
6493 return false;
6496 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6497 bool = false);
6499 /* Build the function calls to GOMP_parallel_start etc to actually
6500 generate the parallel operation. REGION is the parallel region
6501 being expanded. BB is the block where to insert the code. WS_ARGS
6502 will be set if this is a call to a combined parallel+workshare
6503 construct, it contains the list of additional arguments needed by
6504 the workshare construct. */
6506 static void
6507 expand_parallel_call (struct omp_region *region, basic_block bb,
6508 gomp_parallel *entry_stmt,
6509 vec<tree, va_gc> *ws_args)
6511 tree t, t1, t2, val, cond, c, clauses, flags;
6512 gimple_stmt_iterator gsi;
6513 gimple *stmt;
6514 enum built_in_function start_ix;
6515 int start_ix2;
6516 location_t clause_loc;
6517 vec<tree, va_gc> *args;
6519 clauses = gimple_omp_parallel_clauses (entry_stmt);
6521 /* Determine what flavor of GOMP_parallel we will be
6522 emitting. */
6523 start_ix = BUILT_IN_GOMP_PARALLEL;
6524 if (is_combined_parallel (region))
6526 switch (region->inner->type)
6528 case GIMPLE_OMP_FOR:
6529 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6530 switch (region->inner->sched_kind)
6532 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6533 start_ix2 = 3;
6534 break;
6535 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6536 case OMP_CLAUSE_SCHEDULE_GUIDED:
6537 if (region->inner->sched_modifiers
6538 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6540 start_ix2 = 3 + region->inner->sched_kind;
6541 break;
6543 /* FALLTHRU */
6544 default:
6545 start_ix2 = region->inner->sched_kind;
6546 break;
6548 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6549 start_ix = (enum built_in_function) start_ix2;
6550 break;
6551 case GIMPLE_OMP_SECTIONS:
6552 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6553 break;
6554 default:
6555 gcc_unreachable ();
6559 /* By default, the value of NUM_THREADS is zero (selected at run time)
6560 and there is no conditional. */
6561 cond = NULL_TREE;
6562 val = build_int_cst (unsigned_type_node, 0);
6563 flags = build_int_cst (unsigned_type_node, 0);
6565 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6566 if (c)
6567 cond = OMP_CLAUSE_IF_EXPR (c);
6569 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6570 if (c)
6572 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6573 clause_loc = OMP_CLAUSE_LOCATION (c);
6575 else
6576 clause_loc = gimple_location (entry_stmt);
6578 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6579 if (c)
6580 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6582 /* Ensure 'val' is of the correct type. */
6583 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6585 /* If we found the clause 'if (cond)', build either
6586 (cond != 0) or (cond ? val : 1u). */
6587 if (cond)
6589 cond = gimple_boolify (cond);
6591 if (integer_zerop (val))
6592 val = fold_build2_loc (clause_loc,
6593 EQ_EXPR, unsigned_type_node, cond,
6594 build_int_cst (TREE_TYPE (cond), 0));
6595 else
6597 basic_block cond_bb, then_bb, else_bb;
6598 edge e, e_then, e_else;
6599 tree tmp_then, tmp_else, tmp_join, tmp_var;
6601 tmp_var = create_tmp_var (TREE_TYPE (val));
6602 if (gimple_in_ssa_p (cfun))
6604 tmp_then = make_ssa_name (tmp_var);
6605 tmp_else = make_ssa_name (tmp_var);
6606 tmp_join = make_ssa_name (tmp_var);
6608 else
6610 tmp_then = tmp_var;
6611 tmp_else = tmp_var;
6612 tmp_join = tmp_var;
6615 e = split_block_after_labels (bb);
6616 cond_bb = e->src;
6617 bb = e->dest;
6618 remove_edge (e);
6620 then_bb = create_empty_bb (cond_bb);
6621 else_bb = create_empty_bb (then_bb);
6622 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6623 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6625 stmt = gimple_build_cond_empty (cond);
6626 gsi = gsi_start_bb (cond_bb);
6627 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6629 gsi = gsi_start_bb (then_bb);
6630 expand_omp_build_assign (&gsi, tmp_then, val, true);
6632 gsi = gsi_start_bb (else_bb);
6633 expand_omp_build_assign (&gsi, tmp_else,
6634 build_int_cst (unsigned_type_node, 1),
6635 true);
6637 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6638 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6639 add_bb_to_loop (then_bb, cond_bb->loop_father);
6640 add_bb_to_loop (else_bb, cond_bb->loop_father);
6641 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6642 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6644 if (gimple_in_ssa_p (cfun))
6646 gphi *phi = create_phi_node (tmp_join, bb);
6647 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6648 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6651 val = tmp_join;
6654 gsi = gsi_start_bb (bb);
6655 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6656 false, GSI_CONTINUE_LINKING);
6659 gsi = gsi_last_bb (bb);
6660 t = gimple_omp_parallel_data_arg (entry_stmt);
6661 if (t == NULL)
6662 t1 = null_pointer_node;
6663 else
6664 t1 = build_fold_addr_expr (t);
6665 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6666 t2 = build_fold_addr_expr (child_fndecl);
6668 vec_alloc (args, 4 + vec_safe_length (ws_args));
6669 args->quick_push (t2);
6670 args->quick_push (t1);
6671 args->quick_push (val);
6672 if (ws_args)
6673 args->splice (*ws_args);
6674 args->quick_push (flags);
6676 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6677 builtin_decl_explicit (start_ix), args);
6679 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6680 false, GSI_CONTINUE_LINKING);
6682 if (hsa_gen_requested_p ()
6683 && parallel_needs_hsa_kernel_p (region))
6685 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6686 hsa_register_kernel (child_cnode);
6690 /* Insert a function call whose name is FUNC_NAME with the information from
6691 ENTRY_STMT into the basic_block BB. */
6693 static void
6694 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6695 vec <tree, va_gc> *ws_args)
6697 tree t, t1, t2;
6698 gimple_stmt_iterator gsi;
6699 vec <tree, va_gc> *args;
6701 gcc_assert (vec_safe_length (ws_args) == 2);
6702 tree func_name = (*ws_args)[0];
6703 tree grain = (*ws_args)[1];
6705 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6706 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6707 gcc_assert (count != NULL_TREE);
6708 count = OMP_CLAUSE_OPERAND (count, 0);
6710 gsi = gsi_last_bb (bb);
6711 t = gimple_omp_parallel_data_arg (entry_stmt);
6712 if (t == NULL)
6713 t1 = null_pointer_node;
6714 else
6715 t1 = build_fold_addr_expr (t);
6716 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6718 vec_alloc (args, 4);
6719 args->quick_push (t2);
6720 args->quick_push (t1);
6721 args->quick_push (count);
6722 args->quick_push (grain);
6723 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6725 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6726 GSI_CONTINUE_LINKING);
6729 /* Build the function call to GOMP_task to actually
6730 generate the task operation. BB is the block where to insert the code. */
6732 static void
6733 expand_task_call (struct omp_region *region, basic_block bb,
6734 gomp_task *entry_stmt)
6736 tree t1, t2, t3;
6737 gimple_stmt_iterator gsi;
6738 location_t loc = gimple_location (entry_stmt);
6740 tree clauses = gimple_omp_task_clauses (entry_stmt);
6742 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6743 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6744 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6745 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6746 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6747 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6749 unsigned int iflags
6750 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6751 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6752 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6754 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6755 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6756 tree num_tasks = NULL_TREE;
6757 bool ull = false;
6758 if (taskloop_p)
6760 gimple *g = last_stmt (region->outer->entry);
6761 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6762 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6763 struct omp_for_data fd;
6764 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6765 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6766 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6767 OMP_CLAUSE__LOOPTEMP_);
6768 startvar = OMP_CLAUSE_DECL (startvar);
6769 endvar = OMP_CLAUSE_DECL (endvar);
6770 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6771 if (fd.loop.cond_code == LT_EXPR)
6772 iflags |= GOMP_TASK_FLAG_UP;
6773 tree tclauses = gimple_omp_for_clauses (g);
6774 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6775 if (num_tasks)
6776 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6777 else
6779 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6780 if (num_tasks)
6782 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6783 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6785 else
6786 num_tasks = integer_zero_node;
6788 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6789 if (ifc == NULL_TREE)
6790 iflags |= GOMP_TASK_FLAG_IF;
6791 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6792 iflags |= GOMP_TASK_FLAG_NOGROUP;
6793 ull = fd.iter_type == long_long_unsigned_type_node;
6795 else if (priority)
6796 iflags |= GOMP_TASK_FLAG_PRIORITY;
6798 tree flags = build_int_cst (unsigned_type_node, iflags);
6800 tree cond = boolean_true_node;
6801 if (ifc)
6803 if (taskloop_p)
6805 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6806 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6807 build_int_cst (unsigned_type_node,
6808 GOMP_TASK_FLAG_IF),
6809 build_int_cst (unsigned_type_node, 0));
6810 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6811 flags, t);
6813 else
6814 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6817 if (finalc)
6819 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6820 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6821 build_int_cst (unsigned_type_node,
6822 GOMP_TASK_FLAG_FINAL),
6823 build_int_cst (unsigned_type_node, 0));
6824 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6826 if (depend)
6827 depend = OMP_CLAUSE_DECL (depend);
6828 else
6829 depend = build_int_cst (ptr_type_node, 0);
6830 if (priority)
6831 priority = fold_convert (integer_type_node,
6832 OMP_CLAUSE_PRIORITY_EXPR (priority));
6833 else
6834 priority = integer_zero_node;
6836 gsi = gsi_last_bb (bb);
6837 tree t = gimple_omp_task_data_arg (entry_stmt);
6838 if (t == NULL)
6839 t2 = null_pointer_node;
6840 else
6841 t2 = build_fold_addr_expr_loc (loc, t);
6842 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6843 t = gimple_omp_task_copy_fn (entry_stmt);
6844 if (t == NULL)
6845 t3 = null_pointer_node;
6846 else
6847 t3 = build_fold_addr_expr_loc (loc, t);
6849 if (taskloop_p)
6850 t = build_call_expr (ull
6851 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6852 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6853 11, t1, t2, t3,
6854 gimple_omp_task_arg_size (entry_stmt),
6855 gimple_omp_task_arg_align (entry_stmt), flags,
6856 num_tasks, priority, startvar, endvar, step);
6857 else
6858 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6859 9, t1, t2, t3,
6860 gimple_omp_task_arg_size (entry_stmt),
6861 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6862 depend, priority);
6864 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6865 false, GSI_CONTINUE_LINKING);
6869 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6870 catch handler and return it. This prevents programs from violating the
6871 structured block semantics with throws. */
6873 static gimple_seq
6874 maybe_catch_exception (gimple_seq body)
6876 gimple *g;
6877 tree decl;
6879 if (!flag_exceptions)
6880 return body;
6882 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6883 decl = lang_hooks.eh_protect_cleanup_actions ();
6884 else
6885 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6887 g = gimple_build_eh_must_not_throw (decl);
6888 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6889 GIMPLE_TRY_CATCH);
6891 return gimple_seq_alloc_with_stmt (g);
6894 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6896 static tree
6897 vec2chain (vec<tree, va_gc> *v)
6899 tree chain = NULL_TREE, t;
6900 unsigned ix;
6902 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6904 DECL_CHAIN (t) = chain;
6905 chain = t;
6908 return chain;
6912 /* Remove barriers in REGION->EXIT's block. Note that this is only
6913 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6914 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6915 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6916 removed. */
6918 static void
6919 remove_exit_barrier (struct omp_region *region)
6921 gimple_stmt_iterator gsi;
6922 basic_block exit_bb;
6923 edge_iterator ei;
6924 edge e;
6925 gimple *stmt;
6926 int any_addressable_vars = -1;
6928 exit_bb = region->exit;
6930 /* If the parallel region doesn't return, we don't have REGION->EXIT
6931 block at all. */
6932 if (! exit_bb)
6933 return;
6935 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6936 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6937 statements that can appear in between are extremely limited -- no
6938 memory operations at all. Here, we allow nothing at all, so the
6939 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6940 gsi = gsi_last_bb (exit_bb);
6941 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6942 gsi_prev (&gsi);
6943 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6944 return;
6946 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6948 gsi = gsi_last_bb (e->src);
6949 if (gsi_end_p (gsi))
6950 continue;
6951 stmt = gsi_stmt (gsi);
6952 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6953 && !gimple_omp_return_nowait_p (stmt))
6955 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6956 in many cases. If there could be tasks queued, the barrier
6957 might be needed to let the tasks run before some local
6958 variable of the parallel that the task uses as shared
6959 runs out of scope. The task can be spawned either
6960 from within current function (this would be easy to check)
6961 or from some function it calls and gets passed an address
6962 of such a variable. */
6963 if (any_addressable_vars < 0)
6965 gomp_parallel *parallel_stmt
6966 = as_a <gomp_parallel *> (last_stmt (region->entry));
6967 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6968 tree local_decls, block, decl;
6969 unsigned ix;
6971 any_addressable_vars = 0;
6972 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6973 if (TREE_ADDRESSABLE (decl))
6975 any_addressable_vars = 1;
6976 break;
6978 for (block = gimple_block (stmt);
6979 !any_addressable_vars
6980 && block
6981 && TREE_CODE (block) == BLOCK;
6982 block = BLOCK_SUPERCONTEXT (block))
6984 for (local_decls = BLOCK_VARS (block);
6985 local_decls;
6986 local_decls = DECL_CHAIN (local_decls))
6987 if (TREE_ADDRESSABLE (local_decls))
6989 any_addressable_vars = 1;
6990 break;
6992 if (block == gimple_block (parallel_stmt))
6993 break;
6996 if (!any_addressable_vars)
6997 gimple_omp_return_set_nowait (stmt);
7002 static void
7003 remove_exit_barriers (struct omp_region *region)
7005 if (region->type == GIMPLE_OMP_PARALLEL)
7006 remove_exit_barrier (region);
7008 if (region->inner)
7010 region = region->inner;
7011 remove_exit_barriers (region);
7012 while (region->next)
7014 region = region->next;
7015 remove_exit_barriers (region);
7020 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7021 calls. These can't be declared as const functions, but
7022 within one parallel body they are constant, so they can be
7023 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7024 which are declared const. Similarly for task body, except
7025 that in untied task omp_get_thread_num () can change at any task
7026 scheduling point. */
7028 static void
7029 optimize_omp_library_calls (gimple *entry_stmt)
7031 basic_block bb;
7032 gimple_stmt_iterator gsi;
7033 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7034 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7035 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7036 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7037 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7038 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7039 OMP_CLAUSE_UNTIED) != NULL);
7041 FOR_EACH_BB_FN (bb, cfun)
7042 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7044 gimple *call = gsi_stmt (gsi);
7045 tree decl;
7047 if (is_gimple_call (call)
7048 && (decl = gimple_call_fndecl (call))
7049 && DECL_EXTERNAL (decl)
7050 && TREE_PUBLIC (decl)
7051 && DECL_INITIAL (decl) == NULL)
7053 tree built_in;
7055 if (DECL_NAME (decl) == thr_num_id)
7057 /* In #pragma omp task untied omp_get_thread_num () can change
7058 during the execution of the task region. */
7059 if (untied_task)
7060 continue;
7061 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7063 else if (DECL_NAME (decl) == num_thr_id)
7064 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7065 else
7066 continue;
7068 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7069 || gimple_call_num_args (call) != 0)
7070 continue;
7072 if (flag_exceptions && !TREE_NOTHROW (decl))
7073 continue;
7075 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7076 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7077 TREE_TYPE (TREE_TYPE (built_in))))
7078 continue;
7080 gimple_call_set_fndecl (call, built_in);
7085 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7086 regimplified. */
7088 static tree
7089 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7091 tree t = *tp;
7093 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7094 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7095 return t;
7097 if (TREE_CODE (t) == ADDR_EXPR)
7098 recompute_tree_invariant_for_addr_expr (t);
7100 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7101 return NULL_TREE;
7104 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7106 static void
7107 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7108 bool after)
7110 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7111 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7112 !after, after ? GSI_CONTINUE_LINKING
7113 : GSI_SAME_STMT);
7114 gimple *stmt = gimple_build_assign (to, from);
7115 if (after)
7116 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7117 else
7118 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7119 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7120 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7122 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7123 gimple_regimplify_operands (stmt, &gsi);
7127 /* Expand the OpenMP parallel or task directive starting at REGION. */
7129 static void
7130 expand_omp_taskreg (struct omp_region *region)
7132 basic_block entry_bb, exit_bb, new_bb;
7133 struct function *child_cfun;
7134 tree child_fn, block, t;
7135 gimple_stmt_iterator gsi;
7136 gimple *entry_stmt, *stmt;
7137 edge e;
7138 vec<tree, va_gc> *ws_args;
7140 entry_stmt = last_stmt (region->entry);
7141 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7142 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7144 entry_bb = region->entry;
7145 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7146 exit_bb = region->cont;
7147 else
7148 exit_bb = region->exit;
7150 bool is_cilk_for
7151 = (flag_cilkplus
7152 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7153 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7154 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7156 if (is_cilk_for)
7157 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7158 and the inner statement contains the name of the built-in function
7159 and grain. */
7160 ws_args = region->inner->ws_args;
7161 else if (is_combined_parallel (region))
7162 ws_args = region->ws_args;
7163 else
7164 ws_args = NULL;
7166 if (child_cfun->cfg)
7168 /* Due to inlining, it may happen that we have already outlined
7169 the region, in which case all we need to do is make the
7170 sub-graph unreachable and emit the parallel call. */
7171 edge entry_succ_e, exit_succ_e;
7173 entry_succ_e = single_succ_edge (entry_bb);
7175 gsi = gsi_last_bb (entry_bb);
7176 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7177 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7178 gsi_remove (&gsi, true);
7180 new_bb = entry_bb;
7181 if (exit_bb)
7183 exit_succ_e = single_succ_edge (exit_bb);
7184 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7186 remove_edge_and_dominated_blocks (entry_succ_e);
7188 else
7190 unsigned srcidx, dstidx, num;
7192 /* If the parallel region needs data sent from the parent
7193 function, then the very first statement (except possible
7194 tree profile counter updates) of the parallel body
7195 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7196 &.OMP_DATA_O is passed as an argument to the child function,
7197 we need to replace it with the argument as seen by the child
7198 function.
7200 In most cases, this will end up being the identity assignment
7201 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7202 a function call that has been inlined, the original PARM_DECL
7203 .OMP_DATA_I may have been converted into a different local
7204 variable. In which case, we need to keep the assignment. */
7205 if (gimple_omp_taskreg_data_arg (entry_stmt))
7207 basic_block entry_succ_bb
7208 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7209 : FALLTHRU_EDGE (entry_bb)->dest;
7210 tree arg;
7211 gimple *parcopy_stmt = NULL;
7213 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7215 gimple *stmt;
7217 gcc_assert (!gsi_end_p (gsi));
7218 stmt = gsi_stmt (gsi);
7219 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7220 continue;
7222 if (gimple_num_ops (stmt) == 2)
7224 tree arg = gimple_assign_rhs1 (stmt);
7226 /* We're ignore the subcode because we're
7227 effectively doing a STRIP_NOPS. */
7229 if (TREE_CODE (arg) == ADDR_EXPR
7230 && TREE_OPERAND (arg, 0)
7231 == gimple_omp_taskreg_data_arg (entry_stmt))
7233 parcopy_stmt = stmt;
7234 break;
7239 gcc_assert (parcopy_stmt != NULL);
7240 arg = DECL_ARGUMENTS (child_fn);
7242 if (!gimple_in_ssa_p (cfun))
7244 if (gimple_assign_lhs (parcopy_stmt) == arg)
7245 gsi_remove (&gsi, true);
7246 else
7248 /* ?? Is setting the subcode really necessary ?? */
7249 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7250 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7253 else
7255 tree lhs = gimple_assign_lhs (parcopy_stmt);
7256 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7257 /* We'd like to set the rhs to the default def in the child_fn,
7258 but it's too early to create ssa names in the child_fn.
7259 Instead, we set the rhs to the parm. In
7260 move_sese_region_to_fn, we introduce a default def for the
7261 parm, map the parm to it's default def, and once we encounter
7262 this stmt, replace the parm with the default def. */
7263 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7264 update_stmt (parcopy_stmt);
7268 /* Declare local variables needed in CHILD_CFUN. */
7269 block = DECL_INITIAL (child_fn);
7270 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7271 /* The gimplifier could record temporaries in parallel/task block
7272 rather than in containing function's local_decls chain,
7273 which would mean cgraph missed finalizing them. Do it now. */
7274 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7275 if (TREE_CODE (t) == VAR_DECL
7276 && TREE_STATIC (t)
7277 && !DECL_EXTERNAL (t))
7278 varpool_node::finalize_decl (t);
7279 DECL_SAVED_TREE (child_fn) = NULL;
7280 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7281 gimple_set_body (child_fn, NULL);
7282 TREE_USED (block) = 1;
7284 /* Reset DECL_CONTEXT on function arguments. */
7285 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7286 DECL_CONTEXT (t) = child_fn;
7288 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7289 so that it can be moved to the child function. */
7290 gsi = gsi_last_bb (entry_bb);
7291 stmt = gsi_stmt (gsi);
7292 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7293 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7294 e = split_block (entry_bb, stmt);
7295 gsi_remove (&gsi, true);
7296 entry_bb = e->dest;
7297 edge e2 = NULL;
7298 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7299 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7300 else
7302 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7303 gcc_assert (e2->dest == region->exit);
7304 remove_edge (BRANCH_EDGE (entry_bb));
7305 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7306 gsi = gsi_last_bb (region->exit);
7307 gcc_assert (!gsi_end_p (gsi)
7308 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7309 gsi_remove (&gsi, true);
7312 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7313 if (exit_bb)
7315 gsi = gsi_last_bb (exit_bb);
7316 gcc_assert (!gsi_end_p (gsi)
7317 && (gimple_code (gsi_stmt (gsi))
7318 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7319 stmt = gimple_build_return (NULL);
7320 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7321 gsi_remove (&gsi, true);
7324 /* Move the parallel region into CHILD_CFUN. */
7326 if (gimple_in_ssa_p (cfun))
7328 init_tree_ssa (child_cfun);
7329 init_ssa_operands (child_cfun);
7330 child_cfun->gimple_df->in_ssa_p = true;
7331 block = NULL_TREE;
7333 else
7334 block = gimple_block (entry_stmt);
7336 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7337 if (exit_bb)
7338 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7339 if (e2)
7341 basic_block dest_bb = e2->dest;
7342 if (!exit_bb)
7343 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7344 remove_edge (e2);
7345 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7347 /* When the OMP expansion process cannot guarantee an up-to-date
7348 loop tree arrange for the child function to fixup loops. */
7349 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7350 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7352 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7353 num = vec_safe_length (child_cfun->local_decls);
7354 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7356 t = (*child_cfun->local_decls)[srcidx];
7357 if (DECL_CONTEXT (t) == cfun->decl)
7358 continue;
7359 if (srcidx != dstidx)
7360 (*child_cfun->local_decls)[dstidx] = t;
7361 dstidx++;
7363 if (dstidx != num)
7364 vec_safe_truncate (child_cfun->local_decls, dstidx);
7366 /* Inform the callgraph about the new function. */
7367 child_cfun->curr_properties = cfun->curr_properties;
7368 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7369 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7370 cgraph_node *node = cgraph_node::get_create (child_fn);
7371 node->parallelized_function = 1;
7372 cgraph_node::add_new_function (child_fn, true);
7374 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7375 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7377 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7378 fixed in a following pass. */
7379 push_cfun (child_cfun);
7380 if (need_asm)
7381 assign_assembler_name_if_neeeded (child_fn);
7383 if (optimize)
7384 optimize_omp_library_calls (entry_stmt);
7385 cgraph_edge::rebuild_edges ();
7387 /* Some EH regions might become dead, see PR34608. If
7388 pass_cleanup_cfg isn't the first pass to happen with the
7389 new child, these dead EH edges might cause problems.
7390 Clean them up now. */
7391 if (flag_exceptions)
7393 basic_block bb;
7394 bool changed = false;
7396 FOR_EACH_BB_FN (bb, cfun)
7397 changed |= gimple_purge_dead_eh_edges (bb);
7398 if (changed)
7399 cleanup_tree_cfg ();
7401 if (gimple_in_ssa_p (cfun))
7402 update_ssa (TODO_update_ssa);
7403 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7404 verify_loop_structure ();
7405 pop_cfun ();
7407 if (dump_file && !gimple_in_ssa_p (cfun))
7409 omp_any_child_fn_dumped = true;
7410 dump_function_header (dump_file, child_fn, dump_flags);
7411 dump_function_to_file (child_fn, dump_file, dump_flags);
7415 /* Emit a library call to launch the children threads. */
7416 if (is_cilk_for)
7417 expand_cilk_for_call (new_bb,
7418 as_a <gomp_parallel *> (entry_stmt), ws_args);
7419 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7420 expand_parallel_call (region, new_bb,
7421 as_a <gomp_parallel *> (entry_stmt), ws_args);
7422 else
7423 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7424 if (gimple_in_ssa_p (cfun))
7425 update_ssa (TODO_update_ssa_only_virtuals);
7428 /* Information about members of an OpenACC collapsed loop nest. */
7430 struct oacc_collapse
7432 tree base; /* Base value. */
7433 tree iters; /* Number of steps. */
7434 tree step; /* step size. */
7437 /* Helper for expand_oacc_for. Determine collapsed loop information.
7438 Fill in COUNTS array. Emit any initialization code before GSI.
7439 Return the calculated outer loop bound of BOUND_TYPE. */
7441 static tree
7442 expand_oacc_collapse_init (const struct omp_for_data *fd,
7443 gimple_stmt_iterator *gsi,
7444 oacc_collapse *counts, tree bound_type)
7446 tree total = build_int_cst (bound_type, 1);
7447 int ix;
7449 gcc_assert (integer_onep (fd->loop.step));
7450 gcc_assert (integer_zerop (fd->loop.n1));
7452 for (ix = 0; ix != fd->collapse; ix++)
7454 const omp_for_data_loop *loop = &fd->loops[ix];
7456 tree iter_type = TREE_TYPE (loop->v);
7457 tree diff_type = iter_type;
7458 tree plus_type = iter_type;
7460 gcc_assert (loop->cond_code == fd->loop.cond_code);
7462 if (POINTER_TYPE_P (iter_type))
7463 plus_type = sizetype;
7464 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7465 diff_type = signed_type_for (diff_type);
7467 tree b = loop->n1;
7468 tree e = loop->n2;
7469 tree s = loop->step;
7470 bool up = loop->cond_code == LT_EXPR;
7471 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7472 bool negating;
7473 tree expr;
7475 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7476 true, GSI_SAME_STMT);
7477 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7478 true, GSI_SAME_STMT);
7480 /* Convert the step, avoiding possible unsigned->signed overflow. */
7481 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7482 if (negating)
7483 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7484 s = fold_convert (diff_type, s);
7485 if (negating)
7486 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7487 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7488 true, GSI_SAME_STMT);
7490 /* Determine the range, avoiding possible unsigned->signed overflow. */
7491 negating = !up && TYPE_UNSIGNED (iter_type);
7492 expr = fold_build2 (MINUS_EXPR, plus_type,
7493 fold_convert (plus_type, negating ? b : e),
7494 fold_convert (plus_type, negating ? e : b));
7495 expr = fold_convert (diff_type, expr);
7496 if (negating)
7497 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7498 tree range = force_gimple_operand_gsi
7499 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7501 /* Determine number of iterations. */
7502 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7503 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7504 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7506 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7507 true, GSI_SAME_STMT);
7509 counts[ix].base = b;
7510 counts[ix].iters = iters;
7511 counts[ix].step = s;
7513 total = fold_build2 (MULT_EXPR, bound_type, total,
7514 fold_convert (bound_type, iters));
7517 return total;
7520 /* Emit initializers for collapsed loop members. IVAR is the outer
7521 loop iteration variable, from which collapsed loop iteration values
7522 are calculated. COUNTS array has been initialized by
7523 expand_oacc_collapse_inits. */
7525 static void
7526 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7527 gimple_stmt_iterator *gsi,
7528 const oacc_collapse *counts, tree ivar)
7530 tree ivar_type = TREE_TYPE (ivar);
7532 /* The most rapidly changing iteration variable is the innermost
7533 one. */
7534 for (int ix = fd->collapse; ix--;)
7536 const omp_for_data_loop *loop = &fd->loops[ix];
7537 const oacc_collapse *collapse = &counts[ix];
7538 tree iter_type = TREE_TYPE (loop->v);
7539 tree diff_type = TREE_TYPE (collapse->step);
7540 tree plus_type = iter_type;
7541 enum tree_code plus_code = PLUS_EXPR;
7542 tree expr;
7544 if (POINTER_TYPE_P (iter_type))
7546 plus_code = POINTER_PLUS_EXPR;
7547 plus_type = sizetype;
7550 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7551 fold_convert (ivar_type, collapse->iters));
7552 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7553 collapse->step);
7554 expr = fold_build2 (plus_code, iter_type, collapse->base,
7555 fold_convert (plus_type, expr));
7556 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7557 true, GSI_SAME_STMT);
7558 gassign *ass = gimple_build_assign (loop->v, expr);
7559 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7561 if (ix)
7563 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7564 fold_convert (ivar_type, collapse->iters));
7565 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7566 true, GSI_SAME_STMT);
7572 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7573 of the combined collapse > 1 loop constructs, generate code like:
7574 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7575 if (cond3 is <)
7576 adj = STEP3 - 1;
7577 else
7578 adj = STEP3 + 1;
7579 count3 = (adj + N32 - N31) / STEP3;
7580 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7581 if (cond2 is <)
7582 adj = STEP2 - 1;
7583 else
7584 adj = STEP2 + 1;
7585 count2 = (adj + N22 - N21) / STEP2;
7586 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7587 if (cond1 is <)
7588 adj = STEP1 - 1;
7589 else
7590 adj = STEP1 + 1;
7591 count1 = (adj + N12 - N11) / STEP1;
7592 count = count1 * count2 * count3;
7593 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7594 count = 0;
7595 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7596 of the combined loop constructs, just initialize COUNTS array
7597 from the _looptemp_ clauses. */
7599 /* NOTE: It *could* be better to moosh all of the BBs together,
7600 creating one larger BB with all the computation and the unexpected
7601 jump at the end. I.e.
7603 bool zero3, zero2, zero1, zero;
7605 zero3 = N32 c3 N31;
7606 count3 = (N32 - N31) /[cl] STEP3;
7607 zero2 = N22 c2 N21;
7608 count2 = (N22 - N21) /[cl] STEP2;
7609 zero1 = N12 c1 N11;
7610 count1 = (N12 - N11) /[cl] STEP1;
7611 zero = zero3 || zero2 || zero1;
7612 count = count1 * count2 * count3;
7613 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7615 After all, we expect the zero=false, and thus we expect to have to
7616 evaluate all of the comparison expressions, so short-circuiting
7617 oughtn't be a win. Since the condition isn't protecting a
7618 denominator, we're not concerned about divide-by-zero, so we can
7619 fully evaluate count even if a numerator turned out to be wrong.
7621 It seems like putting this all together would create much better
7622 scheduling opportunities, and less pressure on the chip's branch
7623 predictor. */
7625 static void
7626 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7627 basic_block &entry_bb, tree *counts,
7628 basic_block &zero_iter1_bb, int &first_zero_iter1,
7629 basic_block &zero_iter2_bb, int &first_zero_iter2,
7630 basic_block &l2_dom_bb)
7632 tree t, type = TREE_TYPE (fd->loop.v);
7633 edge e, ne;
7634 int i;
7636 /* Collapsed loops need work for expansion into SSA form. */
7637 gcc_assert (!gimple_in_ssa_p (cfun));
7639 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7640 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7642 gcc_assert (fd->ordered == 0);
7643 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7644 isn't supposed to be handled, as the inner loop doesn't
7645 use it. */
7646 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7647 OMP_CLAUSE__LOOPTEMP_);
7648 gcc_assert (innerc);
7649 for (i = 0; i < fd->collapse; i++)
7651 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7652 OMP_CLAUSE__LOOPTEMP_);
7653 gcc_assert (innerc);
7654 if (i)
7655 counts[i] = OMP_CLAUSE_DECL (innerc);
7656 else
7657 counts[0] = NULL_TREE;
7659 return;
7662 for (i = fd->collapse; i < fd->ordered; i++)
7664 tree itype = TREE_TYPE (fd->loops[i].v);
7665 counts[i] = NULL_TREE;
7666 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7667 fold_convert (itype, fd->loops[i].n1),
7668 fold_convert (itype, fd->loops[i].n2));
7669 if (t && integer_zerop (t))
7671 for (i = fd->collapse; i < fd->ordered; i++)
7672 counts[i] = build_int_cst (type, 0);
7673 break;
7676 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7678 tree itype = TREE_TYPE (fd->loops[i].v);
7680 if (i >= fd->collapse && counts[i])
7681 continue;
7682 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7683 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7684 fold_convert (itype, fd->loops[i].n1),
7685 fold_convert (itype, fd->loops[i].n2)))
7686 == NULL_TREE || !integer_onep (t)))
7688 gcond *cond_stmt;
7689 tree n1, n2;
7690 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7691 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7692 true, GSI_SAME_STMT);
7693 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7694 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7695 true, GSI_SAME_STMT);
7696 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7697 NULL_TREE, NULL_TREE);
7698 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7699 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7700 expand_omp_regimplify_p, NULL, NULL)
7701 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7702 expand_omp_regimplify_p, NULL, NULL))
7704 *gsi = gsi_for_stmt (cond_stmt);
7705 gimple_regimplify_operands (cond_stmt, gsi);
7707 e = split_block (entry_bb, cond_stmt);
7708 basic_block &zero_iter_bb
7709 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7710 int &first_zero_iter
7711 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7712 if (zero_iter_bb == NULL)
7714 gassign *assign_stmt;
7715 first_zero_iter = i;
7716 zero_iter_bb = create_empty_bb (entry_bb);
7717 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7718 *gsi = gsi_after_labels (zero_iter_bb);
7719 if (i < fd->collapse)
7720 assign_stmt = gimple_build_assign (fd->loop.n2,
7721 build_zero_cst (type));
7722 else
7724 counts[i] = create_tmp_reg (type, ".count");
7725 assign_stmt
7726 = gimple_build_assign (counts[i], build_zero_cst (type));
7728 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7729 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7730 entry_bb);
7732 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7733 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7734 e->flags = EDGE_TRUE_VALUE;
7735 e->probability = REG_BR_PROB_BASE - ne->probability;
7736 if (l2_dom_bb == NULL)
7737 l2_dom_bb = entry_bb;
7738 entry_bb = e->dest;
7739 *gsi = gsi_last_bb (entry_bb);
7742 if (POINTER_TYPE_P (itype))
7743 itype = signed_type_for (itype);
7744 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7745 ? -1 : 1));
7746 t = fold_build2 (PLUS_EXPR, itype,
7747 fold_convert (itype, fd->loops[i].step), t);
7748 t = fold_build2 (PLUS_EXPR, itype, t,
7749 fold_convert (itype, fd->loops[i].n2));
7750 t = fold_build2 (MINUS_EXPR, itype, t,
7751 fold_convert (itype, fd->loops[i].n1));
7752 /* ?? We could probably use CEIL_DIV_EXPR instead of
7753 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7754 generate the same code in the end because generically we
7755 don't know that the values involved must be negative for
7756 GT?? */
7757 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7758 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7759 fold_build1 (NEGATE_EXPR, itype, t),
7760 fold_build1 (NEGATE_EXPR, itype,
7761 fold_convert (itype,
7762 fd->loops[i].step)));
7763 else
7764 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7765 fold_convert (itype, fd->loops[i].step));
7766 t = fold_convert (type, t);
7767 if (TREE_CODE (t) == INTEGER_CST)
7768 counts[i] = t;
7769 else
7771 if (i < fd->collapse || i != first_zero_iter2)
7772 counts[i] = create_tmp_reg (type, ".count");
7773 expand_omp_build_assign (gsi, counts[i], t);
7775 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7777 if (i == 0)
7778 t = counts[0];
7779 else
7780 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7781 expand_omp_build_assign (gsi, fd->loop.n2, t);
7787 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7788 T = V;
7789 V3 = N31 + (T % count3) * STEP3;
7790 T = T / count3;
7791 V2 = N21 + (T % count2) * STEP2;
7792 T = T / count2;
7793 V1 = N11 + T * STEP1;
7794 if this loop doesn't have an inner loop construct combined with it.
7795 If it does have an inner loop construct combined with it and the
7796 iteration count isn't known constant, store values from counts array
7797 into its _looptemp_ temporaries instead. */
7799 static void
7800 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7801 tree *counts, gimple *inner_stmt, tree startvar)
7803 int i;
7804 if (gimple_omp_for_combined_p (fd->for_stmt))
7806 /* If fd->loop.n2 is constant, then no propagation of the counts
7807 is needed, they are constant. */
7808 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7809 return;
7811 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7812 ? gimple_omp_taskreg_clauses (inner_stmt)
7813 : gimple_omp_for_clauses (inner_stmt);
7814 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7815 isn't supposed to be handled, as the inner loop doesn't
7816 use it. */
7817 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7818 gcc_assert (innerc);
7819 for (i = 0; i < fd->collapse; i++)
7821 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7822 OMP_CLAUSE__LOOPTEMP_);
7823 gcc_assert (innerc);
7824 if (i)
7826 tree tem = OMP_CLAUSE_DECL (innerc);
7827 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7828 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7829 false, GSI_CONTINUE_LINKING);
7830 gassign *stmt = gimple_build_assign (tem, t);
7831 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7834 return;
7837 tree type = TREE_TYPE (fd->loop.v);
7838 tree tem = create_tmp_reg (type, ".tem");
7839 gassign *stmt = gimple_build_assign (tem, startvar);
7840 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7842 for (i = fd->collapse - 1; i >= 0; i--)
7844 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7845 itype = vtype;
7846 if (POINTER_TYPE_P (vtype))
7847 itype = signed_type_for (vtype);
7848 if (i != 0)
7849 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7850 else
7851 t = tem;
7852 t = fold_convert (itype, t);
7853 t = fold_build2 (MULT_EXPR, itype, t,
7854 fold_convert (itype, fd->loops[i].step));
7855 if (POINTER_TYPE_P (vtype))
7856 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7857 else
7858 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7859 t = force_gimple_operand_gsi (gsi, t,
7860 DECL_P (fd->loops[i].v)
7861 && TREE_ADDRESSABLE (fd->loops[i].v),
7862 NULL_TREE, false,
7863 GSI_CONTINUE_LINKING);
7864 stmt = gimple_build_assign (fd->loops[i].v, t);
7865 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7866 if (i != 0)
7868 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7869 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7870 false, GSI_CONTINUE_LINKING);
7871 stmt = gimple_build_assign (tem, t);
7872 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7878 /* Helper function for expand_omp_for_*. Generate code like:
7879 L10:
7880 V3 += STEP3;
7881 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7882 L11:
7883 V3 = N31;
7884 V2 += STEP2;
7885 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7886 L12:
7887 V2 = N21;
7888 V1 += STEP1;
7889 goto BODY_BB; */
7891 static basic_block
7892 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7893 basic_block body_bb)
7895 basic_block last_bb, bb, collapse_bb = NULL;
7896 int i;
7897 gimple_stmt_iterator gsi;
7898 edge e;
7899 tree t;
7900 gimple *stmt;
7902 last_bb = cont_bb;
7903 for (i = fd->collapse - 1; i >= 0; i--)
7905 tree vtype = TREE_TYPE (fd->loops[i].v);
7907 bb = create_empty_bb (last_bb);
7908 add_bb_to_loop (bb, last_bb->loop_father);
7909 gsi = gsi_start_bb (bb);
7911 if (i < fd->collapse - 1)
7913 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7914 e->probability = REG_BR_PROB_BASE / 8;
7916 t = fd->loops[i + 1].n1;
7917 t = force_gimple_operand_gsi (&gsi, t,
7918 DECL_P (fd->loops[i + 1].v)
7919 && TREE_ADDRESSABLE (fd->loops[i
7920 + 1].v),
7921 NULL_TREE, false,
7922 GSI_CONTINUE_LINKING);
7923 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7924 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7926 else
7927 collapse_bb = bb;
7929 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7931 if (POINTER_TYPE_P (vtype))
7932 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7933 else
7934 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7935 t = force_gimple_operand_gsi (&gsi, t,
7936 DECL_P (fd->loops[i].v)
7937 && TREE_ADDRESSABLE (fd->loops[i].v),
7938 NULL_TREE, false, GSI_CONTINUE_LINKING);
7939 stmt = gimple_build_assign (fd->loops[i].v, t);
7940 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7942 if (i > 0)
7944 t = fd->loops[i].n2;
7945 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7946 false, GSI_CONTINUE_LINKING);
7947 tree v = fd->loops[i].v;
7948 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7949 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7950 false, GSI_CONTINUE_LINKING);
7951 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7952 stmt = gimple_build_cond_empty (t);
7953 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7954 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7955 e->probability = REG_BR_PROB_BASE * 7 / 8;
7957 else
7958 make_edge (bb, body_bb, EDGE_FALLTHRU);
7959 last_bb = bb;
7962 return collapse_bb;
7966 /* Expand #pragma omp ordered depend(source). */
7968 static void
7969 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7970 tree *counts, location_t loc)
7972 enum built_in_function source_ix
7973 = fd->iter_type == long_integer_type_node
7974 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7975 gimple *g
7976 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7977 build_fold_addr_expr (counts[fd->ordered]));
7978 gimple_set_location (g, loc);
7979 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7982 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7984 static void
7985 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7986 tree *counts, tree c, location_t loc)
7988 auto_vec<tree, 10> args;
7989 enum built_in_function sink_ix
7990 = fd->iter_type == long_integer_type_node
7991 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7992 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7993 int i;
7994 gimple_stmt_iterator gsi2 = *gsi;
7995 bool warned_step = false;
7997 for (i = 0; i < fd->ordered; i++)
7999 off = TREE_PURPOSE (deps);
8000 if (!integer_zerop (off))
8002 gcc_assert (fd->loops[i].cond_code == LT_EXPR
8003 || fd->loops[i].cond_code == GT_EXPR);
8004 bool forward = fd->loops[i].cond_code == LT_EXPR;
8005 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8006 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
8007 "lexically later iteration");
8008 break;
8010 deps = TREE_CHAIN (deps);
8012 /* If all offsets corresponding to the collapsed loops are zero,
8013 this depend clause can be ignored. FIXME: but there is still a
8014 flush needed. We need to emit one __sync_synchronize () for it
8015 though (perhaps conditionally)? Solve this together with the
8016 conservative dependence folding optimization.
8017 if (i >= fd->collapse)
8018 return; */
8020 deps = OMP_CLAUSE_DECL (c);
8021 gsi_prev (&gsi2);
8022 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8023 edge e2 = split_block_after_labels (e1->dest);
8025 *gsi = gsi_after_labels (e1->dest);
8026 for (i = 0; i < fd->ordered; i++)
8028 tree itype = TREE_TYPE (fd->loops[i].v);
8029 if (POINTER_TYPE_P (itype))
8030 itype = sizetype;
8031 if (i)
8032 deps = TREE_CHAIN (deps);
8033 off = TREE_PURPOSE (deps);
8034 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8036 if (integer_zerop (off))
8037 t = boolean_true_node;
8038 else
8040 tree a;
8041 tree co = fold_convert_loc (loc, itype, off);
8042 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8044 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8045 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8046 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8047 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8048 co);
8050 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8051 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8052 fd->loops[i].v, co);
8053 else
8054 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8055 fd->loops[i].v, co);
8056 if (fd->loops[i].cond_code == LT_EXPR)
8058 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8059 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8060 fd->loops[i].n1);
8061 else
8062 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8063 fd->loops[i].n2);
8065 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8066 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8067 fd->loops[i].n2);
8068 else
8069 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8070 fd->loops[i].n1);
8072 if (cond)
8073 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8074 else
8075 cond = t;
8077 off = fold_convert_loc (loc, itype, off);
8079 if (fd->loops[i].cond_code == LT_EXPR
8080 ? !integer_onep (fd->loops[i].step)
8081 : !integer_minus_onep (fd->loops[i].step))
8083 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8084 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8085 fold_build1_loc (loc, NEGATE_EXPR, itype,
8086 s));
8087 else
8088 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8089 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8090 build_int_cst (itype, 0));
8091 if (integer_zerop (t) && !warned_step)
8093 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8094 "in the iteration space");
8095 warned_step = true;
8097 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8098 cond, t);
8101 if (i <= fd->collapse - 1 && fd->collapse > 1)
8102 t = fd->loop.v;
8103 else if (counts[i])
8104 t = counts[i];
8105 else
8107 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8108 fd->loops[i].v, fd->loops[i].n1);
8109 t = fold_convert_loc (loc, fd->iter_type, t);
8111 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8112 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8113 fold_build1_loc (loc, NEGATE_EXPR, itype,
8114 s));
8115 else
8116 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8117 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8118 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8119 off = fold_convert_loc (loc, fd->iter_type, off);
8120 if (i <= fd->collapse - 1 && fd->collapse > 1)
8122 if (i)
8123 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8124 off);
8125 if (i < fd->collapse - 1)
8127 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8128 counts[i]);
8129 continue;
8132 off = unshare_expr (off);
8133 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8134 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8135 true, GSI_SAME_STMT);
8136 args.safe_push (t);
8138 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8139 gimple_set_location (g, loc);
8140 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8142 *gsi = gsi_last_bb (e1->src);
8143 cond = unshare_expr (cond);
8144 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8145 GSI_CONTINUE_LINKING);
8146 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8147 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8148 e3->probability = REG_BR_PROB_BASE / 8;
8149 e1->probability = REG_BR_PROB_BASE - e3->probability;
8150 e1->flags = EDGE_TRUE_VALUE;
8151 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8153 *gsi = gsi_after_labels (e2->dest);
8156 /* Expand all #pragma omp ordered depend(source) and
8157 #pragma omp ordered depend(sink:...) constructs in the current
8158 #pragma omp for ordered(n) region. */
8160 static void
8161 expand_omp_ordered_source_sink (struct omp_region *region,
8162 struct omp_for_data *fd, tree *counts,
8163 basic_block cont_bb)
8165 struct omp_region *inner;
8166 int i;
8167 for (i = fd->collapse - 1; i < fd->ordered; i++)
8168 if (i == fd->collapse - 1 && fd->collapse > 1)
8169 counts[i] = NULL_TREE;
8170 else if (i >= fd->collapse && !cont_bb)
8171 counts[i] = build_zero_cst (fd->iter_type);
8172 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8173 && integer_onep (fd->loops[i].step))
8174 counts[i] = NULL_TREE;
8175 else
8176 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8177 tree atype
8178 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8179 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8180 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8182 for (inner = region->inner; inner; inner = inner->next)
8183 if (inner->type == GIMPLE_OMP_ORDERED)
8185 gomp_ordered *ord_stmt = inner->ord_stmt;
8186 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8187 location_t loc = gimple_location (ord_stmt);
8188 tree c;
8189 for (c = gimple_omp_ordered_clauses (ord_stmt);
8190 c; c = OMP_CLAUSE_CHAIN (c))
8191 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8192 break;
8193 if (c)
8194 expand_omp_ordered_source (&gsi, fd, counts, loc);
8195 for (c = gimple_omp_ordered_clauses (ord_stmt);
8196 c; c = OMP_CLAUSE_CHAIN (c))
8197 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8198 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8199 gsi_remove (&gsi, true);
8203 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8204 collapsed. */
8206 static basic_block
8207 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8208 basic_block cont_bb, basic_block body_bb,
8209 bool ordered_lastprivate)
8211 if (fd->ordered == fd->collapse)
8212 return cont_bb;
8214 if (!cont_bb)
8216 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8217 for (int i = fd->collapse; i < fd->ordered; i++)
8219 tree type = TREE_TYPE (fd->loops[i].v);
8220 tree n1 = fold_convert (type, fd->loops[i].n1);
8221 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8222 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8223 size_int (i - fd->collapse + 1),
8224 NULL_TREE, NULL_TREE);
8225 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8227 return NULL;
8230 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8232 tree t, type = TREE_TYPE (fd->loops[i].v);
8233 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8234 expand_omp_build_assign (&gsi, fd->loops[i].v,
8235 fold_convert (type, fd->loops[i].n1));
8236 if (counts[i])
8237 expand_omp_build_assign (&gsi, counts[i],
8238 build_zero_cst (fd->iter_type));
8239 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8240 size_int (i - fd->collapse + 1),
8241 NULL_TREE, NULL_TREE);
8242 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8243 if (!gsi_end_p (gsi))
8244 gsi_prev (&gsi);
8245 else
8246 gsi = gsi_last_bb (body_bb);
8247 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8248 basic_block new_body = e1->dest;
8249 if (body_bb == cont_bb)
8250 cont_bb = new_body;
8251 edge e2 = NULL;
8252 basic_block new_header;
8253 if (EDGE_COUNT (cont_bb->preds) > 0)
8255 gsi = gsi_last_bb (cont_bb);
8256 if (POINTER_TYPE_P (type))
8257 t = fold_build_pointer_plus (fd->loops[i].v,
8258 fold_convert (sizetype,
8259 fd->loops[i].step));
8260 else
8261 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8262 fold_convert (type, fd->loops[i].step));
8263 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8264 if (counts[i])
8266 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8267 build_int_cst (fd->iter_type, 1));
8268 expand_omp_build_assign (&gsi, counts[i], t);
8269 t = counts[i];
8271 else
8273 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8274 fd->loops[i].v, fd->loops[i].n1);
8275 t = fold_convert (fd->iter_type, t);
8276 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8277 true, GSI_SAME_STMT);
8279 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8280 size_int (i - fd->collapse + 1),
8281 NULL_TREE, NULL_TREE);
8282 expand_omp_build_assign (&gsi, aref, t);
8283 gsi_prev (&gsi);
8284 e2 = split_block (cont_bb, gsi_stmt (gsi));
8285 new_header = e2->dest;
8287 else
8288 new_header = cont_bb;
8289 gsi = gsi_after_labels (new_header);
8290 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8291 true, GSI_SAME_STMT);
8292 tree n2
8293 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8294 true, NULL_TREE, true, GSI_SAME_STMT);
8295 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8296 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8297 edge e3 = split_block (new_header, gsi_stmt (gsi));
8298 cont_bb = e3->dest;
8299 remove_edge (e1);
8300 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8301 e3->flags = EDGE_FALSE_VALUE;
8302 e3->probability = REG_BR_PROB_BASE / 8;
8303 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8304 e1->probability = REG_BR_PROB_BASE - e3->probability;
8306 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8307 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8309 if (e2)
8311 struct loop *loop = alloc_loop ();
8312 loop->header = new_header;
8313 loop->latch = e2->src;
8314 add_loop (loop, body_bb->loop_father);
8318 /* If there are any lastprivate clauses and it is possible some loops
8319 might have zero iterations, ensure all the decls are initialized,
8320 otherwise we could crash evaluating C++ class iterators with lastprivate
8321 clauses. */
8322 bool need_inits = false;
8323 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8324 if (need_inits)
8326 tree type = TREE_TYPE (fd->loops[i].v);
8327 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8328 expand_omp_build_assign (&gsi, fd->loops[i].v,
8329 fold_convert (type, fd->loops[i].n1));
8331 else
8333 tree type = TREE_TYPE (fd->loops[i].v);
8334 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8335 boolean_type_node,
8336 fold_convert (type, fd->loops[i].n1),
8337 fold_convert (type, fd->loops[i].n2));
8338 if (!integer_onep (this_cond))
8339 need_inits = true;
8342 return cont_bb;
8346 /* A subroutine of expand_omp_for. Generate code for a parallel
8347 loop with any schedule. Given parameters:
8349 for (V = N1; V cond N2; V += STEP) BODY;
8351 where COND is "<" or ">", we generate pseudocode
8353 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8354 if (more) goto L0; else goto L3;
8356 V = istart0;
8357 iend = iend0;
8359 BODY;
8360 V += STEP;
8361 if (V cond iend) goto L1; else goto L2;
8363 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8366 If this is a combined omp parallel loop, instead of the call to
8367 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8368 If this is gimple_omp_for_combined_p loop, then instead of assigning
8369 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8370 inner GIMPLE_OMP_FOR and V += STEP; and
8371 if (V cond iend) goto L1; else goto L2; are removed.
8373 For collapsed loops, given parameters:
8374 collapse(3)
8375 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8376 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8377 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8378 BODY;
8380 we generate pseudocode
8382 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8383 if (cond3 is <)
8384 adj = STEP3 - 1;
8385 else
8386 adj = STEP3 + 1;
8387 count3 = (adj + N32 - N31) / STEP3;
8388 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8389 if (cond2 is <)
8390 adj = STEP2 - 1;
8391 else
8392 adj = STEP2 + 1;
8393 count2 = (adj + N22 - N21) / STEP2;
8394 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8395 if (cond1 is <)
8396 adj = STEP1 - 1;
8397 else
8398 adj = STEP1 + 1;
8399 count1 = (adj + N12 - N11) / STEP1;
8400 count = count1 * count2 * count3;
8401 goto Z1;
8403 count = 0;
8405 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8406 if (more) goto L0; else goto L3;
8408 V = istart0;
8409 T = V;
8410 V3 = N31 + (T % count3) * STEP3;
8411 T = T / count3;
8412 V2 = N21 + (T % count2) * STEP2;
8413 T = T / count2;
8414 V1 = N11 + T * STEP1;
8415 iend = iend0;
8417 BODY;
8418 V += 1;
8419 if (V < iend) goto L10; else goto L2;
8420 L10:
8421 V3 += STEP3;
8422 if (V3 cond3 N32) goto L1; else goto L11;
8423 L11:
8424 V3 = N31;
8425 V2 += STEP2;
8426 if (V2 cond2 N22) goto L1; else goto L12;
8427 L12:
8428 V2 = N21;
8429 V1 += STEP1;
8430 goto L1;
8432 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8437 static void
8438 expand_omp_for_generic (struct omp_region *region,
8439 struct omp_for_data *fd,
8440 enum built_in_function start_fn,
8441 enum built_in_function next_fn,
8442 gimple *inner_stmt)
8444 tree type, istart0, iend0, iend;
8445 tree t, vmain, vback, bias = NULL_TREE;
8446 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8447 basic_block l2_bb = NULL, l3_bb = NULL;
8448 gimple_stmt_iterator gsi;
8449 gassign *assign_stmt;
8450 bool in_combined_parallel = is_combined_parallel (region);
8451 bool broken_loop = region->cont == NULL;
8452 edge e, ne;
8453 tree *counts = NULL;
8454 int i;
8455 bool ordered_lastprivate = false;
8457 gcc_assert (!broken_loop || !in_combined_parallel);
8458 gcc_assert (fd->iter_type == long_integer_type_node
8459 || !in_combined_parallel);
8461 entry_bb = region->entry;
8462 cont_bb = region->cont;
8463 collapse_bb = NULL;
8464 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8465 gcc_assert (broken_loop
8466 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8467 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8468 l1_bb = single_succ (l0_bb);
8469 if (!broken_loop)
8471 l2_bb = create_empty_bb (cont_bb);
8472 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8473 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8474 == l1_bb));
8475 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8477 else
8478 l2_bb = NULL;
8479 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8480 exit_bb = region->exit;
8482 gsi = gsi_last_bb (entry_bb);
8484 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8485 if (fd->ordered
8486 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8487 OMP_CLAUSE_LASTPRIVATE))
8488 ordered_lastprivate = false;
8489 if (fd->collapse > 1 || fd->ordered)
8491 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8492 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8494 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8495 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8496 zero_iter1_bb, first_zero_iter1,
8497 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8499 if (zero_iter1_bb)
8501 /* Some counts[i] vars might be uninitialized if
8502 some loop has zero iterations. But the body shouldn't
8503 be executed in that case, so just avoid uninit warnings. */
8504 for (i = first_zero_iter1;
8505 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8506 if (SSA_VAR_P (counts[i]))
8507 TREE_NO_WARNING (counts[i]) = 1;
8508 gsi_prev (&gsi);
8509 e = split_block (entry_bb, gsi_stmt (gsi));
8510 entry_bb = e->dest;
8511 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8512 gsi = gsi_last_bb (entry_bb);
8513 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8514 get_immediate_dominator (CDI_DOMINATORS,
8515 zero_iter1_bb));
8517 if (zero_iter2_bb)
8519 /* Some counts[i] vars might be uninitialized if
8520 some loop has zero iterations. But the body shouldn't
8521 be executed in that case, so just avoid uninit warnings. */
8522 for (i = first_zero_iter2; i < fd->ordered; i++)
8523 if (SSA_VAR_P (counts[i]))
8524 TREE_NO_WARNING (counts[i]) = 1;
8525 if (zero_iter1_bb)
8526 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8527 else
8529 gsi_prev (&gsi);
8530 e = split_block (entry_bb, gsi_stmt (gsi));
8531 entry_bb = e->dest;
8532 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8533 gsi = gsi_last_bb (entry_bb);
8534 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8535 get_immediate_dominator
8536 (CDI_DOMINATORS, zero_iter2_bb));
8539 if (fd->collapse == 1)
8541 counts[0] = fd->loop.n2;
8542 fd->loop = fd->loops[0];
8546 type = TREE_TYPE (fd->loop.v);
8547 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8548 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8549 TREE_ADDRESSABLE (istart0) = 1;
8550 TREE_ADDRESSABLE (iend0) = 1;
8552 /* See if we need to bias by LLONG_MIN. */
8553 if (fd->iter_type == long_long_unsigned_type_node
8554 && TREE_CODE (type) == INTEGER_TYPE
8555 && !TYPE_UNSIGNED (type)
8556 && fd->ordered == 0)
8558 tree n1, n2;
8560 if (fd->loop.cond_code == LT_EXPR)
8562 n1 = fd->loop.n1;
8563 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8565 else
8567 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8568 n2 = fd->loop.n1;
8570 if (TREE_CODE (n1) != INTEGER_CST
8571 || TREE_CODE (n2) != INTEGER_CST
8572 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8573 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8576 gimple_stmt_iterator gsif = gsi;
8577 gsi_prev (&gsif);
8579 tree arr = NULL_TREE;
8580 if (in_combined_parallel)
8582 gcc_assert (fd->ordered == 0);
8583 /* In a combined parallel loop, emit a call to
8584 GOMP_loop_foo_next. */
8585 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8586 build_fold_addr_expr (istart0),
8587 build_fold_addr_expr (iend0));
8589 else
8591 tree t0, t1, t2, t3, t4;
8592 /* If this is not a combined parallel loop, emit a call to
8593 GOMP_loop_foo_start in ENTRY_BB. */
8594 t4 = build_fold_addr_expr (iend0);
8595 t3 = build_fold_addr_expr (istart0);
8596 if (fd->ordered)
8598 t0 = build_int_cst (unsigned_type_node,
8599 fd->ordered - fd->collapse + 1);
8600 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8601 fd->ordered
8602 - fd->collapse + 1),
8603 ".omp_counts");
8604 DECL_NAMELESS (arr) = 1;
8605 TREE_ADDRESSABLE (arr) = 1;
8606 TREE_STATIC (arr) = 1;
8607 vec<constructor_elt, va_gc> *v;
8608 vec_alloc (v, fd->ordered - fd->collapse + 1);
8609 int idx;
8611 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8613 tree c;
8614 if (idx == 0 && fd->collapse > 1)
8615 c = fd->loop.n2;
8616 else
8617 c = counts[idx + fd->collapse - 1];
8618 tree purpose = size_int (idx);
8619 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8620 if (TREE_CODE (c) != INTEGER_CST)
8621 TREE_STATIC (arr) = 0;
8624 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8625 if (!TREE_STATIC (arr))
8626 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8627 void_type_node, arr),
8628 true, NULL_TREE, true, GSI_SAME_STMT);
8629 t1 = build_fold_addr_expr (arr);
8630 t2 = NULL_TREE;
8632 else
8634 t2 = fold_convert (fd->iter_type, fd->loop.step);
8635 t1 = fd->loop.n2;
8636 t0 = fd->loop.n1;
8637 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8639 tree innerc
8640 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8641 OMP_CLAUSE__LOOPTEMP_);
8642 gcc_assert (innerc);
8643 t0 = OMP_CLAUSE_DECL (innerc);
8644 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8645 OMP_CLAUSE__LOOPTEMP_);
8646 gcc_assert (innerc);
8647 t1 = OMP_CLAUSE_DECL (innerc);
8649 if (POINTER_TYPE_P (TREE_TYPE (t0))
8650 && TYPE_PRECISION (TREE_TYPE (t0))
8651 != TYPE_PRECISION (fd->iter_type))
8653 /* Avoid casting pointers to integer of a different size. */
8654 tree itype = signed_type_for (type);
8655 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8656 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8658 else
8660 t1 = fold_convert (fd->iter_type, t1);
8661 t0 = fold_convert (fd->iter_type, t0);
8663 if (bias)
8665 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8666 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8669 if (fd->iter_type == long_integer_type_node || fd->ordered)
8671 if (fd->chunk_size)
8673 t = fold_convert (fd->iter_type, fd->chunk_size);
8674 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8675 if (fd->ordered)
8676 t = build_call_expr (builtin_decl_explicit (start_fn),
8677 5, t0, t1, t, t3, t4);
8678 else
8679 t = build_call_expr (builtin_decl_explicit (start_fn),
8680 6, t0, t1, t2, t, t3, t4);
8682 else if (fd->ordered)
8683 t = build_call_expr (builtin_decl_explicit (start_fn),
8684 4, t0, t1, t3, t4);
8685 else
8686 t = build_call_expr (builtin_decl_explicit (start_fn),
8687 5, t0, t1, t2, t3, t4);
8689 else
8691 tree t5;
8692 tree c_bool_type;
8693 tree bfn_decl;
8695 /* The GOMP_loop_ull_*start functions have additional boolean
8696 argument, true for < loops and false for > loops.
8697 In Fortran, the C bool type can be different from
8698 boolean_type_node. */
8699 bfn_decl = builtin_decl_explicit (start_fn);
8700 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8701 t5 = build_int_cst (c_bool_type,
8702 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8703 if (fd->chunk_size)
8705 tree bfn_decl = builtin_decl_explicit (start_fn);
8706 t = fold_convert (fd->iter_type, fd->chunk_size);
8707 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8708 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8710 else
8711 t = build_call_expr (builtin_decl_explicit (start_fn),
8712 6, t5, t0, t1, t2, t3, t4);
8715 if (TREE_TYPE (t) != boolean_type_node)
8716 t = fold_build2 (NE_EXPR, boolean_type_node,
8717 t, build_int_cst (TREE_TYPE (t), 0));
8718 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8719 true, GSI_SAME_STMT);
8720 if (arr && !TREE_STATIC (arr))
8722 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8723 TREE_THIS_VOLATILE (clobber) = 1;
8724 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8725 GSI_SAME_STMT);
8727 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8729 /* Remove the GIMPLE_OMP_FOR statement. */
8730 gsi_remove (&gsi, true);
8732 if (gsi_end_p (gsif))
8733 gsif = gsi_after_labels (gsi_bb (gsif));
8734 gsi_next (&gsif);
8736 /* Iteration setup for sequential loop goes in L0_BB. */
8737 tree startvar = fd->loop.v;
8738 tree endvar = NULL_TREE;
8740 if (gimple_omp_for_combined_p (fd->for_stmt))
8742 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8743 && gimple_omp_for_kind (inner_stmt)
8744 == GF_OMP_FOR_KIND_SIMD);
8745 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8746 OMP_CLAUSE__LOOPTEMP_);
8747 gcc_assert (innerc);
8748 startvar = OMP_CLAUSE_DECL (innerc);
8749 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8750 OMP_CLAUSE__LOOPTEMP_);
8751 gcc_assert (innerc);
8752 endvar = OMP_CLAUSE_DECL (innerc);
8755 gsi = gsi_start_bb (l0_bb);
8756 t = istart0;
8757 if (fd->ordered && fd->collapse == 1)
8758 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8759 fold_convert (fd->iter_type, fd->loop.step));
8760 else if (bias)
8761 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8762 if (fd->ordered && fd->collapse == 1)
8764 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8765 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8766 fd->loop.n1, fold_convert (sizetype, t));
8767 else
8769 t = fold_convert (TREE_TYPE (startvar), t);
8770 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8771 fd->loop.n1, t);
8774 else
8776 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8777 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8778 t = fold_convert (TREE_TYPE (startvar), t);
8780 t = force_gimple_operand_gsi (&gsi, t,
8781 DECL_P (startvar)
8782 && TREE_ADDRESSABLE (startvar),
8783 NULL_TREE, false, GSI_CONTINUE_LINKING);
8784 assign_stmt = gimple_build_assign (startvar, t);
8785 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8787 t = iend0;
8788 if (fd->ordered && fd->collapse == 1)
8789 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8790 fold_convert (fd->iter_type, fd->loop.step));
8791 else if (bias)
8792 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8793 if (fd->ordered && fd->collapse == 1)
8795 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8796 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8797 fd->loop.n1, fold_convert (sizetype, t));
8798 else
8800 t = fold_convert (TREE_TYPE (startvar), t);
8801 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8802 fd->loop.n1, t);
8805 else
8807 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8808 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8809 t = fold_convert (TREE_TYPE (startvar), t);
8811 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8812 false, GSI_CONTINUE_LINKING);
8813 if (endvar)
8815 assign_stmt = gimple_build_assign (endvar, iend);
8816 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8817 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8818 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8819 else
8820 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8821 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8823 /* Handle linear clause adjustments. */
8824 tree itercnt = NULL_TREE;
8825 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8826 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8827 c; c = OMP_CLAUSE_CHAIN (c))
8828 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8829 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8831 tree d = OMP_CLAUSE_DECL (c);
8832 bool is_ref = is_reference (d);
8833 tree t = d, a, dest;
8834 if (is_ref)
8835 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8836 tree type = TREE_TYPE (t);
8837 if (POINTER_TYPE_P (type))
8838 type = sizetype;
8839 dest = unshare_expr (t);
8840 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8841 expand_omp_build_assign (&gsif, v, t);
8842 if (itercnt == NULL_TREE)
8844 itercnt = startvar;
8845 tree n1 = fd->loop.n1;
8846 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8848 itercnt
8849 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8850 itercnt);
8851 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8853 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8854 itercnt, n1);
8855 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8856 itercnt, fd->loop.step);
8857 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8858 NULL_TREE, false,
8859 GSI_CONTINUE_LINKING);
8861 a = fold_build2 (MULT_EXPR, type,
8862 fold_convert (type, itercnt),
8863 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8864 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8865 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8866 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8867 false, GSI_CONTINUE_LINKING);
8868 assign_stmt = gimple_build_assign (dest, t);
8869 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8871 if (fd->collapse > 1)
8872 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8874 if (fd->ordered)
8876 /* Until now, counts array contained number of iterations or
8877 variable containing it for ith loop. From now on, we need
8878 those counts only for collapsed loops, and only for the 2nd
8879 till the last collapsed one. Move those one element earlier,
8880 we'll use counts[fd->collapse - 1] for the first source/sink
8881 iteration counter and so on and counts[fd->ordered]
8882 as the array holding the current counter values for
8883 depend(source). */
8884 if (fd->collapse > 1)
8885 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8886 if (broken_loop)
8888 int i;
8889 for (i = fd->collapse; i < fd->ordered; i++)
8891 tree type = TREE_TYPE (fd->loops[i].v);
8892 tree this_cond
8893 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8894 fold_convert (type, fd->loops[i].n1),
8895 fold_convert (type, fd->loops[i].n2));
8896 if (!integer_onep (this_cond))
8897 break;
8899 if (i < fd->ordered)
8901 cont_bb
8902 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8903 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8904 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8905 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8906 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8907 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8908 make_edge (cont_bb, l1_bb, 0);
8909 l2_bb = create_empty_bb (cont_bb);
8910 broken_loop = false;
8913 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8914 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8915 ordered_lastprivate);
8916 if (counts[fd->collapse - 1])
8918 gcc_assert (fd->collapse == 1);
8919 gsi = gsi_last_bb (l0_bb);
8920 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8921 istart0, true);
8922 gsi = gsi_last_bb (cont_bb);
8923 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8924 build_int_cst (fd->iter_type, 1));
8925 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8926 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8927 size_zero_node, NULL_TREE, NULL_TREE);
8928 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8929 t = counts[fd->collapse - 1];
8931 else if (fd->collapse > 1)
8932 t = fd->loop.v;
8933 else
8935 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8936 fd->loops[0].v, fd->loops[0].n1);
8937 t = fold_convert (fd->iter_type, t);
8939 gsi = gsi_last_bb (l0_bb);
8940 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8941 size_zero_node, NULL_TREE, NULL_TREE);
8942 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8943 false, GSI_CONTINUE_LINKING);
8944 expand_omp_build_assign (&gsi, aref, t, true);
8947 if (!broken_loop)
8949 /* Code to control the increment and predicate for the sequential
8950 loop goes in the CONT_BB. */
8951 gsi = gsi_last_bb (cont_bb);
8952 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8953 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8954 vmain = gimple_omp_continue_control_use (cont_stmt);
8955 vback = gimple_omp_continue_control_def (cont_stmt);
8957 if (!gimple_omp_for_combined_p (fd->for_stmt))
8959 if (POINTER_TYPE_P (type))
8960 t = fold_build_pointer_plus (vmain, fd->loop.step);
8961 else
8962 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8963 t = force_gimple_operand_gsi (&gsi, t,
8964 DECL_P (vback)
8965 && TREE_ADDRESSABLE (vback),
8966 NULL_TREE, true, GSI_SAME_STMT);
8967 assign_stmt = gimple_build_assign (vback, t);
8968 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8970 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8972 if (fd->collapse > 1)
8973 t = fd->loop.v;
8974 else
8976 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8977 fd->loops[0].v, fd->loops[0].n1);
8978 t = fold_convert (fd->iter_type, t);
8980 tree aref = build4 (ARRAY_REF, fd->iter_type,
8981 counts[fd->ordered], size_zero_node,
8982 NULL_TREE, NULL_TREE);
8983 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8984 true, GSI_SAME_STMT);
8985 expand_omp_build_assign (&gsi, aref, t);
8988 t = build2 (fd->loop.cond_code, boolean_type_node,
8989 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8990 iend);
8991 gcond *cond_stmt = gimple_build_cond_empty (t);
8992 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8995 /* Remove GIMPLE_OMP_CONTINUE. */
8996 gsi_remove (&gsi, true);
8998 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8999 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
9001 /* Emit code to get the next parallel iteration in L2_BB. */
9002 gsi = gsi_start_bb (l2_bb);
9004 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
9005 build_fold_addr_expr (istart0),
9006 build_fold_addr_expr (iend0));
9007 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9008 false, GSI_CONTINUE_LINKING);
9009 if (TREE_TYPE (t) != boolean_type_node)
9010 t = fold_build2 (NE_EXPR, boolean_type_node,
9011 t, build_int_cst (TREE_TYPE (t), 0));
9012 gcond *cond_stmt = gimple_build_cond_empty (t);
9013 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9016 /* Add the loop cleanup function. */
9017 gsi = gsi_last_bb (exit_bb);
9018 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9019 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9020 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9021 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9022 else
9023 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9024 gcall *call_stmt = gimple_build_call (t, 0);
9025 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9026 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9027 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9028 if (fd->ordered)
9030 tree arr = counts[fd->ordered];
9031 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9032 TREE_THIS_VOLATILE (clobber) = 1;
9033 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9034 GSI_SAME_STMT);
9036 gsi_remove (&gsi, true);
9038 /* Connect the new blocks. */
9039 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9040 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9042 if (!broken_loop)
9044 gimple_seq phis;
9046 e = find_edge (cont_bb, l3_bb);
9047 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9049 phis = phi_nodes (l3_bb);
9050 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9052 gimple *phi = gsi_stmt (gsi);
9053 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9054 PHI_ARG_DEF_FROM_EDGE (phi, e));
9056 remove_edge (e);
9058 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9059 e = find_edge (cont_bb, l1_bb);
9060 if (e == NULL)
9062 e = BRANCH_EDGE (cont_bb);
9063 gcc_assert (single_succ (e->dest) == l1_bb);
9065 if (gimple_omp_for_combined_p (fd->for_stmt))
9067 remove_edge (e);
9068 e = NULL;
9070 else if (fd->collapse > 1)
9072 remove_edge (e);
9073 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9075 else
9076 e->flags = EDGE_TRUE_VALUE;
9077 if (e)
9079 e->probability = REG_BR_PROB_BASE * 7 / 8;
9080 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9082 else
9084 e = find_edge (cont_bb, l2_bb);
9085 e->flags = EDGE_FALLTHRU;
9087 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9089 if (gimple_in_ssa_p (cfun))
9091 /* Add phis to the outer loop that connect to the phis in the inner,
9092 original loop, and move the loop entry value of the inner phi to
9093 the loop entry value of the outer phi. */
9094 gphi_iterator psi;
9095 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9097 source_location locus;
9098 gphi *nphi;
9099 gphi *exit_phi = psi.phi ();
9101 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9102 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9104 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9105 edge latch_to_l1 = find_edge (latch, l1_bb);
9106 gphi *inner_phi
9107 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9109 tree t = gimple_phi_result (exit_phi);
9110 tree new_res = copy_ssa_name (t, NULL);
9111 nphi = create_phi_node (new_res, l0_bb);
9113 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9114 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9115 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9116 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9117 add_phi_arg (nphi, t, entry_to_l0, locus);
9119 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9120 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9122 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9126 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9127 recompute_dominator (CDI_DOMINATORS, l2_bb));
9128 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9129 recompute_dominator (CDI_DOMINATORS, l3_bb));
9130 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9131 recompute_dominator (CDI_DOMINATORS, l0_bb));
9132 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9133 recompute_dominator (CDI_DOMINATORS, l1_bb));
9135 /* We enter expand_omp_for_generic with a loop. This original loop may
9136 have its own loop struct, or it may be part of an outer loop struct
9137 (which may be the fake loop). */
9138 struct loop *outer_loop = entry_bb->loop_father;
9139 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9141 add_bb_to_loop (l2_bb, outer_loop);
9143 /* We've added a new loop around the original loop. Allocate the
9144 corresponding loop struct. */
9145 struct loop *new_loop = alloc_loop ();
9146 new_loop->header = l0_bb;
9147 new_loop->latch = l2_bb;
9148 add_loop (new_loop, outer_loop);
9150 /* Allocate a loop structure for the original loop unless we already
9151 had one. */
9152 if (!orig_loop_has_loop_struct
9153 && !gimple_omp_for_combined_p (fd->for_stmt))
9155 struct loop *orig_loop = alloc_loop ();
9156 orig_loop->header = l1_bb;
9157 /* The loop may have multiple latches. */
9158 add_loop (orig_loop, new_loop);
9164 /* A subroutine of expand_omp_for. Generate code for a parallel
9165 loop with static schedule and no specified chunk size. Given
9166 parameters:
9168 for (V = N1; V cond N2; V += STEP) BODY;
9170 where COND is "<" or ">", we generate pseudocode
9172 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9173 if (cond is <)
9174 adj = STEP - 1;
9175 else
9176 adj = STEP + 1;
9177 if ((__typeof (V)) -1 > 0 && cond is >)
9178 n = -(adj + N2 - N1) / -STEP;
9179 else
9180 n = (adj + N2 - N1) / STEP;
9181 q = n / nthreads;
9182 tt = n % nthreads;
9183 if (threadid < tt) goto L3; else goto L4;
9185 tt = 0;
9186 q = q + 1;
9188 s0 = q * threadid + tt;
9189 e0 = s0 + q;
9190 V = s0 * STEP + N1;
9191 if (s0 >= e0) goto L2; else goto L0;
9193 e = e0 * STEP + N1;
9195 BODY;
9196 V += STEP;
9197 if (V cond e) goto L1;
9201 static void
9202 expand_omp_for_static_nochunk (struct omp_region *region,
9203 struct omp_for_data *fd,
9204 gimple *inner_stmt)
9206 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9207 tree type, itype, vmain, vback;
9208 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9209 basic_block body_bb, cont_bb, collapse_bb = NULL;
9210 basic_block fin_bb;
9211 gimple_stmt_iterator gsi;
9212 edge ep;
9213 bool broken_loop = region->cont == NULL;
9214 tree *counts = NULL;
9215 tree n1, n2, step;
9217 itype = type = TREE_TYPE (fd->loop.v);
9218 if (POINTER_TYPE_P (type))
9219 itype = signed_type_for (type);
9221 entry_bb = region->entry;
9222 cont_bb = region->cont;
9223 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9224 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9225 gcc_assert (broken_loop
9226 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9227 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9228 body_bb = single_succ (seq_start_bb);
9229 if (!broken_loop)
9231 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9232 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9233 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9235 exit_bb = region->exit;
9237 /* Iteration space partitioning goes in ENTRY_BB. */
9238 gsi = gsi_last_bb (entry_bb);
9239 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9241 if (fd->collapse > 1)
9243 int first_zero_iter = -1, dummy = -1;
9244 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9246 counts = XALLOCAVEC (tree, fd->collapse);
9247 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9248 fin_bb, first_zero_iter,
9249 dummy_bb, dummy, l2_dom_bb);
9250 t = NULL_TREE;
9252 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9253 t = integer_one_node;
9254 else
9255 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9256 fold_convert (type, fd->loop.n1),
9257 fold_convert (type, fd->loop.n2));
9258 if (fd->collapse == 1
9259 && TYPE_UNSIGNED (type)
9260 && (t == NULL_TREE || !integer_onep (t)))
9262 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9263 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9264 true, GSI_SAME_STMT);
9265 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9266 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9267 true, GSI_SAME_STMT);
9268 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9269 NULL_TREE, NULL_TREE);
9270 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9271 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9272 expand_omp_regimplify_p, NULL, NULL)
9273 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9274 expand_omp_regimplify_p, NULL, NULL))
9276 gsi = gsi_for_stmt (cond_stmt);
9277 gimple_regimplify_operands (cond_stmt, &gsi);
9279 ep = split_block (entry_bb, cond_stmt);
9280 ep->flags = EDGE_TRUE_VALUE;
9281 entry_bb = ep->dest;
9282 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9283 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9284 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9285 if (gimple_in_ssa_p (cfun))
9287 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9288 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9289 !gsi_end_p (gpi); gsi_next (&gpi))
9291 gphi *phi = gpi.phi ();
9292 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9293 ep, UNKNOWN_LOCATION);
9296 gsi = gsi_last_bb (entry_bb);
9299 switch (gimple_omp_for_kind (fd->for_stmt))
9301 case GF_OMP_FOR_KIND_FOR:
9302 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9303 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9304 break;
9305 case GF_OMP_FOR_KIND_DISTRIBUTE:
9306 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9307 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9308 break;
9309 default:
9310 gcc_unreachable ();
9312 nthreads = build_call_expr (nthreads, 0);
9313 nthreads = fold_convert (itype, nthreads);
9314 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9315 true, GSI_SAME_STMT);
9316 threadid = build_call_expr (threadid, 0);
9317 threadid = fold_convert (itype, threadid);
9318 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9319 true, GSI_SAME_STMT);
9321 n1 = fd->loop.n1;
9322 n2 = fd->loop.n2;
9323 step = fd->loop.step;
9324 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9326 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9327 OMP_CLAUSE__LOOPTEMP_);
9328 gcc_assert (innerc);
9329 n1 = OMP_CLAUSE_DECL (innerc);
9330 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9331 OMP_CLAUSE__LOOPTEMP_);
9332 gcc_assert (innerc);
9333 n2 = OMP_CLAUSE_DECL (innerc);
9335 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9336 true, NULL_TREE, true, GSI_SAME_STMT);
9337 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9338 true, NULL_TREE, true, GSI_SAME_STMT);
9339 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9340 true, NULL_TREE, true, GSI_SAME_STMT);
9342 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9343 t = fold_build2 (PLUS_EXPR, itype, step, t);
9344 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9345 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9346 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9347 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9348 fold_build1 (NEGATE_EXPR, itype, t),
9349 fold_build1 (NEGATE_EXPR, itype, step));
9350 else
9351 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9352 t = fold_convert (itype, t);
9353 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9355 q = create_tmp_reg (itype, "q");
9356 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9357 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9358 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9360 tt = create_tmp_reg (itype, "tt");
9361 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9362 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9363 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9365 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9366 gcond *cond_stmt = gimple_build_cond_empty (t);
9367 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9369 second_bb = split_block (entry_bb, cond_stmt)->dest;
9370 gsi = gsi_last_bb (second_bb);
9371 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9373 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9374 GSI_SAME_STMT);
9375 gassign *assign_stmt
9376 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9377 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9379 third_bb = split_block (second_bb, assign_stmt)->dest;
9380 gsi = gsi_last_bb (third_bb);
9381 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9383 t = build2 (MULT_EXPR, itype, q, threadid);
9384 t = build2 (PLUS_EXPR, itype, t, tt);
9385 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9387 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9388 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9390 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9391 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9393 /* Remove the GIMPLE_OMP_FOR statement. */
9394 gsi_remove (&gsi, true);
9396 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9397 gsi = gsi_start_bb (seq_start_bb);
9399 tree startvar = fd->loop.v;
9400 tree endvar = NULL_TREE;
9402 if (gimple_omp_for_combined_p (fd->for_stmt))
9404 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9405 ? gimple_omp_parallel_clauses (inner_stmt)
9406 : gimple_omp_for_clauses (inner_stmt);
9407 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9408 gcc_assert (innerc);
9409 startvar = OMP_CLAUSE_DECL (innerc);
9410 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9411 OMP_CLAUSE__LOOPTEMP_);
9412 gcc_assert (innerc);
9413 endvar = OMP_CLAUSE_DECL (innerc);
9414 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9415 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9417 int i;
9418 for (i = 1; i < fd->collapse; i++)
9420 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9421 OMP_CLAUSE__LOOPTEMP_);
9422 gcc_assert (innerc);
9424 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9425 OMP_CLAUSE__LOOPTEMP_);
9426 if (innerc)
9428 /* If needed (distribute parallel for with lastprivate),
9429 propagate down the total number of iterations. */
9430 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9431 fd->loop.n2);
9432 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9433 GSI_CONTINUE_LINKING);
9434 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9435 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9439 t = fold_convert (itype, s0);
9440 t = fold_build2 (MULT_EXPR, itype, t, step);
9441 if (POINTER_TYPE_P (type))
9442 t = fold_build_pointer_plus (n1, t);
9443 else
9444 t = fold_build2 (PLUS_EXPR, type, t, n1);
9445 t = fold_convert (TREE_TYPE (startvar), t);
9446 t = force_gimple_operand_gsi (&gsi, t,
9447 DECL_P (startvar)
9448 && TREE_ADDRESSABLE (startvar),
9449 NULL_TREE, false, GSI_CONTINUE_LINKING);
9450 assign_stmt = gimple_build_assign (startvar, t);
9451 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9453 t = fold_convert (itype, e0);
9454 t = fold_build2 (MULT_EXPR, itype, t, step);
9455 if (POINTER_TYPE_P (type))
9456 t = fold_build_pointer_plus (n1, t);
9457 else
9458 t = fold_build2 (PLUS_EXPR, type, t, n1);
9459 t = fold_convert (TREE_TYPE (startvar), t);
9460 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9461 false, GSI_CONTINUE_LINKING);
9462 if (endvar)
9464 assign_stmt = gimple_build_assign (endvar, e);
9465 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9466 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9467 assign_stmt = gimple_build_assign (fd->loop.v, e);
9468 else
9469 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9470 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9472 /* Handle linear clause adjustments. */
9473 tree itercnt = NULL_TREE;
9474 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9475 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9476 c; c = OMP_CLAUSE_CHAIN (c))
9477 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9478 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9480 tree d = OMP_CLAUSE_DECL (c);
9481 bool is_ref = is_reference (d);
9482 tree t = d, a, dest;
9483 if (is_ref)
9484 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9485 if (itercnt == NULL_TREE)
9487 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9489 itercnt = fold_build2 (MINUS_EXPR, itype,
9490 fold_convert (itype, n1),
9491 fold_convert (itype, fd->loop.n1));
9492 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9493 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9494 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9495 NULL_TREE, false,
9496 GSI_CONTINUE_LINKING);
9498 else
9499 itercnt = s0;
9501 tree type = TREE_TYPE (t);
9502 if (POINTER_TYPE_P (type))
9503 type = sizetype;
9504 a = fold_build2 (MULT_EXPR, type,
9505 fold_convert (type, itercnt),
9506 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9507 dest = unshare_expr (t);
9508 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9509 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9510 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9511 false, GSI_CONTINUE_LINKING);
9512 assign_stmt = gimple_build_assign (dest, t);
9513 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9515 if (fd->collapse > 1)
9516 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9518 if (!broken_loop)
9520 /* The code controlling the sequential loop replaces the
9521 GIMPLE_OMP_CONTINUE. */
9522 gsi = gsi_last_bb (cont_bb);
9523 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9524 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9525 vmain = gimple_omp_continue_control_use (cont_stmt);
9526 vback = gimple_omp_continue_control_def (cont_stmt);
9528 if (!gimple_omp_for_combined_p (fd->for_stmt))
9530 if (POINTER_TYPE_P (type))
9531 t = fold_build_pointer_plus (vmain, step);
9532 else
9533 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9534 t = force_gimple_operand_gsi (&gsi, t,
9535 DECL_P (vback)
9536 && TREE_ADDRESSABLE (vback),
9537 NULL_TREE, true, GSI_SAME_STMT);
9538 assign_stmt = gimple_build_assign (vback, t);
9539 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9541 t = build2 (fd->loop.cond_code, boolean_type_node,
9542 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9543 ? t : vback, e);
9544 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9547 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9548 gsi_remove (&gsi, true);
9550 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9551 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9554 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9555 gsi = gsi_last_bb (exit_bb);
9556 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9558 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9559 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9561 gsi_remove (&gsi, true);
9563 /* Connect all the blocks. */
9564 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9565 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9566 ep = find_edge (entry_bb, second_bb);
9567 ep->flags = EDGE_TRUE_VALUE;
9568 ep->probability = REG_BR_PROB_BASE / 4;
9569 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9570 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9572 if (!broken_loop)
9574 ep = find_edge (cont_bb, body_bb);
9575 if (ep == NULL)
9577 ep = BRANCH_EDGE (cont_bb);
9578 gcc_assert (single_succ (ep->dest) == body_bb);
9580 if (gimple_omp_for_combined_p (fd->for_stmt))
9582 remove_edge (ep);
9583 ep = NULL;
9585 else if (fd->collapse > 1)
9587 remove_edge (ep);
9588 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9590 else
9591 ep->flags = EDGE_TRUE_VALUE;
9592 find_edge (cont_bb, fin_bb)->flags
9593 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9596 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9597 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9598 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9600 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9601 recompute_dominator (CDI_DOMINATORS, body_bb));
9602 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9603 recompute_dominator (CDI_DOMINATORS, fin_bb));
9605 struct loop *loop = body_bb->loop_father;
9606 if (loop != entry_bb->loop_father)
9608 gcc_assert (loop->header == body_bb);
9609 gcc_assert (broken_loop
9610 || loop->latch == region->cont
9611 || single_pred (loop->latch) == region->cont);
9612 return;
9615 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9617 loop = alloc_loop ();
9618 loop->header = body_bb;
9619 if (collapse_bb == NULL)
9620 loop->latch = cont_bb;
9621 add_loop (loop, body_bb->loop_father);
9625 /* Return phi in E->DEST with ARG on edge E. */
9627 static gphi *
9628 find_phi_with_arg_on_edge (tree arg, edge e)
9630 basic_block bb = e->dest;
9632 for (gphi_iterator gpi = gsi_start_phis (bb);
9633 !gsi_end_p (gpi);
9634 gsi_next (&gpi))
9636 gphi *phi = gpi.phi ();
9637 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9638 return phi;
9641 return NULL;
9644 /* A subroutine of expand_omp_for. Generate code for a parallel
9645 loop with static schedule and a specified chunk size. Given
9646 parameters:
9648 for (V = N1; V cond N2; V += STEP) BODY;
9650 where COND is "<" or ">", we generate pseudocode
9652 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9653 if (cond is <)
9654 adj = STEP - 1;
9655 else
9656 adj = STEP + 1;
9657 if ((__typeof (V)) -1 > 0 && cond is >)
9658 n = -(adj + N2 - N1) / -STEP;
9659 else
9660 n = (adj + N2 - N1) / STEP;
9661 trip = 0;
9662 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9663 here so that V is defined
9664 if the loop is not entered
9666 s0 = (trip * nthreads + threadid) * CHUNK;
9667 e0 = min(s0 + CHUNK, n);
9668 if (s0 < n) goto L1; else goto L4;
9670 V = s0 * STEP + N1;
9671 e = e0 * STEP + N1;
9673 BODY;
9674 V += STEP;
9675 if (V cond e) goto L2; else goto L3;
9677 trip += 1;
9678 goto L0;
9682 static void
9683 expand_omp_for_static_chunk (struct omp_region *region,
9684 struct omp_for_data *fd, gimple *inner_stmt)
9686 tree n, s0, e0, e, t;
9687 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9688 tree type, itype, vmain, vback, vextra;
9689 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9690 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9691 gimple_stmt_iterator gsi;
9692 edge se;
9693 bool broken_loop = region->cont == NULL;
9694 tree *counts = NULL;
9695 tree n1, n2, step;
9697 itype = type = TREE_TYPE (fd->loop.v);
9698 if (POINTER_TYPE_P (type))
9699 itype = signed_type_for (type);
9701 entry_bb = region->entry;
9702 se = split_block (entry_bb, last_stmt (entry_bb));
9703 entry_bb = se->src;
9704 iter_part_bb = se->dest;
9705 cont_bb = region->cont;
9706 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9707 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9708 gcc_assert (broken_loop
9709 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9710 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9711 body_bb = single_succ (seq_start_bb);
9712 if (!broken_loop)
9714 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9715 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9716 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9717 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9719 exit_bb = region->exit;
9721 /* Trip and adjustment setup goes in ENTRY_BB. */
9722 gsi = gsi_last_bb (entry_bb);
9723 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9725 if (fd->collapse > 1)
9727 int first_zero_iter = -1, dummy = -1;
9728 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9730 counts = XALLOCAVEC (tree, fd->collapse);
9731 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9732 fin_bb, first_zero_iter,
9733 dummy_bb, dummy, l2_dom_bb);
9734 t = NULL_TREE;
9736 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9737 t = integer_one_node;
9738 else
9739 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9740 fold_convert (type, fd->loop.n1),
9741 fold_convert (type, fd->loop.n2));
9742 if (fd->collapse == 1
9743 && TYPE_UNSIGNED (type)
9744 && (t == NULL_TREE || !integer_onep (t)))
9746 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9747 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9748 true, GSI_SAME_STMT);
9749 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9750 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9751 true, GSI_SAME_STMT);
9752 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9753 NULL_TREE, NULL_TREE);
9754 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9755 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9756 expand_omp_regimplify_p, NULL, NULL)
9757 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9758 expand_omp_regimplify_p, NULL, NULL))
9760 gsi = gsi_for_stmt (cond_stmt);
9761 gimple_regimplify_operands (cond_stmt, &gsi);
9763 se = split_block (entry_bb, cond_stmt);
9764 se->flags = EDGE_TRUE_VALUE;
9765 entry_bb = se->dest;
9766 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9767 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9768 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9769 if (gimple_in_ssa_p (cfun))
9771 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9772 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9773 !gsi_end_p (gpi); gsi_next (&gpi))
9775 gphi *phi = gpi.phi ();
9776 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9777 se, UNKNOWN_LOCATION);
9780 gsi = gsi_last_bb (entry_bb);
9783 switch (gimple_omp_for_kind (fd->for_stmt))
9785 case GF_OMP_FOR_KIND_FOR:
9786 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9787 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9788 break;
9789 case GF_OMP_FOR_KIND_DISTRIBUTE:
9790 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9791 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9792 break;
9793 default:
9794 gcc_unreachable ();
9796 nthreads = build_call_expr (nthreads, 0);
9797 nthreads = fold_convert (itype, nthreads);
9798 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9799 true, GSI_SAME_STMT);
9800 threadid = build_call_expr (threadid, 0);
9801 threadid = fold_convert (itype, threadid);
9802 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9803 true, GSI_SAME_STMT);
9805 n1 = fd->loop.n1;
9806 n2 = fd->loop.n2;
9807 step = fd->loop.step;
9808 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9810 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9811 OMP_CLAUSE__LOOPTEMP_);
9812 gcc_assert (innerc);
9813 n1 = OMP_CLAUSE_DECL (innerc);
9814 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9815 OMP_CLAUSE__LOOPTEMP_);
9816 gcc_assert (innerc);
9817 n2 = OMP_CLAUSE_DECL (innerc);
9819 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9820 true, NULL_TREE, true, GSI_SAME_STMT);
9821 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9822 true, NULL_TREE, true, GSI_SAME_STMT);
9823 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9824 true, NULL_TREE, true, GSI_SAME_STMT);
9825 tree chunk_size = fold_convert (itype, fd->chunk_size);
9826 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9827 chunk_size
9828 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9829 GSI_SAME_STMT);
9831 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9832 t = fold_build2 (PLUS_EXPR, itype, step, t);
9833 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9834 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9835 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9836 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9837 fold_build1 (NEGATE_EXPR, itype, t),
9838 fold_build1 (NEGATE_EXPR, itype, step));
9839 else
9840 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9841 t = fold_convert (itype, t);
9842 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9843 true, GSI_SAME_STMT);
9845 trip_var = create_tmp_reg (itype, ".trip");
9846 if (gimple_in_ssa_p (cfun))
9848 trip_init = make_ssa_name (trip_var);
9849 trip_main = make_ssa_name (trip_var);
9850 trip_back = make_ssa_name (trip_var);
9852 else
9854 trip_init = trip_var;
9855 trip_main = trip_var;
9856 trip_back = trip_var;
9859 gassign *assign_stmt
9860 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9861 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9863 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9864 t = fold_build2 (MULT_EXPR, itype, t, step);
9865 if (POINTER_TYPE_P (type))
9866 t = fold_build_pointer_plus (n1, t);
9867 else
9868 t = fold_build2 (PLUS_EXPR, type, t, n1);
9869 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9870 true, GSI_SAME_STMT);
9872 /* Remove the GIMPLE_OMP_FOR. */
9873 gsi_remove (&gsi, true);
9875 gimple_stmt_iterator gsif = gsi;
9877 /* Iteration space partitioning goes in ITER_PART_BB. */
9878 gsi = gsi_last_bb (iter_part_bb);
9880 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9881 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9882 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9883 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9884 false, GSI_CONTINUE_LINKING);
9886 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9887 t = fold_build2 (MIN_EXPR, itype, t, n);
9888 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9889 false, GSI_CONTINUE_LINKING);
9891 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9892 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9894 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9895 gsi = gsi_start_bb (seq_start_bb);
9897 tree startvar = fd->loop.v;
9898 tree endvar = NULL_TREE;
9900 if (gimple_omp_for_combined_p (fd->for_stmt))
9902 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9903 ? gimple_omp_parallel_clauses (inner_stmt)
9904 : gimple_omp_for_clauses (inner_stmt);
9905 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9906 gcc_assert (innerc);
9907 startvar = OMP_CLAUSE_DECL (innerc);
9908 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9909 OMP_CLAUSE__LOOPTEMP_);
9910 gcc_assert (innerc);
9911 endvar = OMP_CLAUSE_DECL (innerc);
9912 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9913 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9915 int i;
9916 for (i = 1; i < fd->collapse; i++)
9918 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9919 OMP_CLAUSE__LOOPTEMP_);
9920 gcc_assert (innerc);
9922 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9923 OMP_CLAUSE__LOOPTEMP_);
9924 if (innerc)
9926 /* If needed (distribute parallel for with lastprivate),
9927 propagate down the total number of iterations. */
9928 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9929 fd->loop.n2);
9930 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9931 GSI_CONTINUE_LINKING);
9932 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9933 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9938 t = fold_convert (itype, s0);
9939 t = fold_build2 (MULT_EXPR, itype, t, step);
9940 if (POINTER_TYPE_P (type))
9941 t = fold_build_pointer_plus (n1, t);
9942 else
9943 t = fold_build2 (PLUS_EXPR, type, t, n1);
9944 t = fold_convert (TREE_TYPE (startvar), t);
9945 t = force_gimple_operand_gsi (&gsi, t,
9946 DECL_P (startvar)
9947 && TREE_ADDRESSABLE (startvar),
9948 NULL_TREE, false, GSI_CONTINUE_LINKING);
9949 assign_stmt = gimple_build_assign (startvar, t);
9950 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9952 t = fold_convert (itype, e0);
9953 t = fold_build2 (MULT_EXPR, itype, t, step);
9954 if (POINTER_TYPE_P (type))
9955 t = fold_build_pointer_plus (n1, t);
9956 else
9957 t = fold_build2 (PLUS_EXPR, type, t, n1);
9958 t = fold_convert (TREE_TYPE (startvar), t);
9959 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9960 false, GSI_CONTINUE_LINKING);
9961 if (endvar)
9963 assign_stmt = gimple_build_assign (endvar, e);
9964 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9965 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9966 assign_stmt = gimple_build_assign (fd->loop.v, e);
9967 else
9968 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9969 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9971 /* Handle linear clause adjustments. */
9972 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9973 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9974 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9975 c; c = OMP_CLAUSE_CHAIN (c))
9976 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9977 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9979 tree d = OMP_CLAUSE_DECL (c);
9980 bool is_ref = is_reference (d);
9981 tree t = d, a, dest;
9982 if (is_ref)
9983 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9984 tree type = TREE_TYPE (t);
9985 if (POINTER_TYPE_P (type))
9986 type = sizetype;
9987 dest = unshare_expr (t);
9988 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9989 expand_omp_build_assign (&gsif, v, t);
9990 if (itercnt == NULL_TREE)
9992 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9994 itercntbias
9995 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9996 fold_convert (itype, fd->loop.n1));
9997 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9998 itercntbias, step);
9999 itercntbias
10000 = force_gimple_operand_gsi (&gsif, itercntbias, true,
10001 NULL_TREE, true,
10002 GSI_SAME_STMT);
10003 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
10004 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
10005 NULL_TREE, false,
10006 GSI_CONTINUE_LINKING);
10008 else
10009 itercnt = s0;
10011 a = fold_build2 (MULT_EXPR, type,
10012 fold_convert (type, itercnt),
10013 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10014 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10015 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10016 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10017 false, GSI_CONTINUE_LINKING);
10018 assign_stmt = gimple_build_assign (dest, t);
10019 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10021 if (fd->collapse > 1)
10022 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10024 if (!broken_loop)
10026 /* The code controlling the sequential loop goes in CONT_BB,
10027 replacing the GIMPLE_OMP_CONTINUE. */
10028 gsi = gsi_last_bb (cont_bb);
10029 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10030 vmain = gimple_omp_continue_control_use (cont_stmt);
10031 vback = gimple_omp_continue_control_def (cont_stmt);
10033 if (!gimple_omp_for_combined_p (fd->for_stmt))
10035 if (POINTER_TYPE_P (type))
10036 t = fold_build_pointer_plus (vmain, step);
10037 else
10038 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10039 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10040 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10041 true, GSI_SAME_STMT);
10042 assign_stmt = gimple_build_assign (vback, t);
10043 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10045 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10046 t = build2 (EQ_EXPR, boolean_type_node,
10047 build_int_cst (itype, 0),
10048 build_int_cst (itype, 1));
10049 else
10050 t = build2 (fd->loop.cond_code, boolean_type_node,
10051 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10052 ? t : vback, e);
10053 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10056 /* Remove GIMPLE_OMP_CONTINUE. */
10057 gsi_remove (&gsi, true);
10059 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10060 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10062 /* Trip update code goes into TRIP_UPDATE_BB. */
10063 gsi = gsi_start_bb (trip_update_bb);
10065 t = build_int_cst (itype, 1);
10066 t = build2 (PLUS_EXPR, itype, trip_main, t);
10067 assign_stmt = gimple_build_assign (trip_back, t);
10068 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10071 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10072 gsi = gsi_last_bb (exit_bb);
10073 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10075 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10076 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10078 gsi_remove (&gsi, true);
10080 /* Connect the new blocks. */
10081 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10082 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10084 if (!broken_loop)
10086 se = find_edge (cont_bb, body_bb);
10087 if (se == NULL)
10089 se = BRANCH_EDGE (cont_bb);
10090 gcc_assert (single_succ (se->dest) == body_bb);
10092 if (gimple_omp_for_combined_p (fd->for_stmt))
10094 remove_edge (se);
10095 se = NULL;
10097 else if (fd->collapse > 1)
10099 remove_edge (se);
10100 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10102 else
10103 se->flags = EDGE_TRUE_VALUE;
10104 find_edge (cont_bb, trip_update_bb)->flags
10105 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10107 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10110 if (gimple_in_ssa_p (cfun))
10112 gphi_iterator psi;
10113 gphi *phi;
10114 edge re, ene;
10115 edge_var_map *vm;
10116 size_t i;
10118 gcc_assert (fd->collapse == 1 && !broken_loop);
10120 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10121 remove arguments of the phi nodes in fin_bb. We need to create
10122 appropriate phi nodes in iter_part_bb instead. */
10123 se = find_edge (iter_part_bb, fin_bb);
10124 re = single_succ_edge (trip_update_bb);
10125 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10126 ene = single_succ_edge (entry_bb);
10128 psi = gsi_start_phis (fin_bb);
10129 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10130 gsi_next (&psi), ++i)
10132 gphi *nphi;
10133 source_location locus;
10135 phi = psi.phi ();
10136 t = gimple_phi_result (phi);
10137 gcc_assert (t == redirect_edge_var_map_result (vm));
10139 if (!single_pred_p (fin_bb))
10140 t = copy_ssa_name (t, phi);
10142 nphi = create_phi_node (t, iter_part_bb);
10144 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10145 locus = gimple_phi_arg_location_from_edge (phi, se);
10147 /* A special case -- fd->loop.v is not yet computed in
10148 iter_part_bb, we need to use vextra instead. */
10149 if (t == fd->loop.v)
10150 t = vextra;
10151 add_phi_arg (nphi, t, ene, locus);
10152 locus = redirect_edge_var_map_location (vm);
10153 tree back_arg = redirect_edge_var_map_def (vm);
10154 add_phi_arg (nphi, back_arg, re, locus);
10155 edge ce = find_edge (cont_bb, body_bb);
10156 if (ce == NULL)
10158 ce = BRANCH_EDGE (cont_bb);
10159 gcc_assert (single_succ (ce->dest) == body_bb);
10160 ce = single_succ_edge (ce->dest);
10162 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10163 gcc_assert (inner_loop_phi != NULL);
10164 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10165 find_edge (seq_start_bb, body_bb), locus);
10167 if (!single_pred_p (fin_bb))
10168 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10170 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10171 redirect_edge_var_map_clear (re);
10172 if (single_pred_p (fin_bb))
10173 while (1)
10175 psi = gsi_start_phis (fin_bb);
10176 if (gsi_end_p (psi))
10177 break;
10178 remove_phi_node (&psi, false);
10181 /* Make phi node for trip. */
10182 phi = create_phi_node (trip_main, iter_part_bb);
10183 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10184 UNKNOWN_LOCATION);
10185 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10186 UNKNOWN_LOCATION);
10189 if (!broken_loop)
10190 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10191 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10192 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10193 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10194 recompute_dominator (CDI_DOMINATORS, fin_bb));
10195 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10196 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10197 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10198 recompute_dominator (CDI_DOMINATORS, body_bb));
10200 if (!broken_loop)
10202 struct loop *loop = body_bb->loop_father;
10203 struct loop *trip_loop = alloc_loop ();
10204 trip_loop->header = iter_part_bb;
10205 trip_loop->latch = trip_update_bb;
10206 add_loop (trip_loop, iter_part_bb->loop_father);
10208 if (loop != entry_bb->loop_father)
10210 gcc_assert (loop->header == body_bb);
10211 gcc_assert (loop->latch == region->cont
10212 || single_pred (loop->latch) == region->cont);
10213 trip_loop->inner = loop;
10214 return;
10217 if (!gimple_omp_for_combined_p (fd->for_stmt))
10219 loop = alloc_loop ();
10220 loop->header = body_bb;
10221 if (collapse_bb == NULL)
10222 loop->latch = cont_bb;
10223 add_loop (loop, trip_loop);
10228 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10229 Given parameters:
10230 for (V = N1; V cond N2; V += STEP) BODY;
10232 where COND is "<" or ">" or "!=", we generate pseudocode
10234 for (ind_var = low; ind_var < high; ind_var++)
10236 V = n1 + (ind_var * STEP)
10238 <BODY>
10241 In the above pseudocode, low and high are function parameters of the
10242 child function. In the function below, we are inserting a temp.
10243 variable that will be making a call to two OMP functions that will not be
10244 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10245 with _Cilk_for). These functions are replaced with low and high
10246 by the function that handles taskreg. */
10249 static void
10250 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10252 bool broken_loop = region->cont == NULL;
10253 basic_block entry_bb = region->entry;
10254 basic_block cont_bb = region->cont;
10256 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10257 gcc_assert (broken_loop
10258 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10259 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10260 basic_block l1_bb, l2_bb;
10262 if (!broken_loop)
10264 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10265 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10266 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10267 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10269 else
10271 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10272 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10273 l2_bb = single_succ (l1_bb);
10275 basic_block exit_bb = region->exit;
10276 basic_block l2_dom_bb = NULL;
10278 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10280 /* Below statements until the "tree high_val = ..." are pseudo statements
10281 used to pass information to be used by expand_omp_taskreg.
10282 low_val and high_val will be replaced by the __low and __high
10283 parameter from the child function.
10285 The call_exprs part is a place-holder, it is mainly used
10286 to distinctly identify to the top-level part that this is
10287 where we should put low and high (reasoning given in header
10288 comment). */
10290 tree child_fndecl
10291 = gimple_omp_parallel_child_fn (
10292 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10293 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10294 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10296 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10297 high_val = t;
10298 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10299 low_val = t;
10301 gcc_assert (low_val && high_val);
10303 tree type = TREE_TYPE (low_val);
10304 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10305 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10307 /* Not needed in SSA form right now. */
10308 gcc_assert (!gimple_in_ssa_p (cfun));
10309 if (l2_dom_bb == NULL)
10310 l2_dom_bb = l1_bb;
10312 tree n1 = low_val;
10313 tree n2 = high_val;
10315 gimple *stmt = gimple_build_assign (ind_var, n1);
10317 /* Replace the GIMPLE_OMP_FOR statement. */
10318 gsi_replace (&gsi, stmt, true);
10320 if (!broken_loop)
10322 /* Code to control the increment goes in the CONT_BB. */
10323 gsi = gsi_last_bb (cont_bb);
10324 stmt = gsi_stmt (gsi);
10325 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10326 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10327 build_one_cst (type));
10329 /* Replace GIMPLE_OMP_CONTINUE. */
10330 gsi_replace (&gsi, stmt, true);
10333 /* Emit the condition in L1_BB. */
10334 gsi = gsi_after_labels (l1_bb);
10335 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10336 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10337 fd->loop.step);
10338 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10339 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10340 fd->loop.n1, fold_convert (sizetype, t));
10341 else
10342 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10343 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10344 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10345 expand_omp_build_assign (&gsi, fd->loop.v, t);
10347 /* The condition is always '<' since the runtime will fill in the low
10348 and high values. */
10349 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10350 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10352 /* Remove GIMPLE_OMP_RETURN. */
10353 gsi = gsi_last_bb (exit_bb);
10354 gsi_remove (&gsi, true);
10356 /* Connect the new blocks. */
10357 remove_edge (FALLTHRU_EDGE (entry_bb));
10359 edge e, ne;
10360 if (!broken_loop)
10362 remove_edge (BRANCH_EDGE (entry_bb));
10363 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10365 e = BRANCH_EDGE (l1_bb);
10366 ne = FALLTHRU_EDGE (l1_bb);
10367 e->flags = EDGE_TRUE_VALUE;
10369 else
10371 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10373 ne = single_succ_edge (l1_bb);
10374 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10377 ne->flags = EDGE_FALSE_VALUE;
10378 e->probability = REG_BR_PROB_BASE * 7 / 8;
10379 ne->probability = REG_BR_PROB_BASE / 8;
10381 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10382 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10383 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10385 if (!broken_loop)
10387 struct loop *loop = alloc_loop ();
10388 loop->header = l1_bb;
10389 loop->latch = cont_bb;
10390 add_loop (loop, l1_bb->loop_father);
10391 loop->safelen = INT_MAX;
10394 /* Pick the correct library function based on the precision of the
10395 induction variable type. */
10396 tree lib_fun = NULL_TREE;
10397 if (TYPE_PRECISION (type) == 32)
10398 lib_fun = cilk_for_32_fndecl;
10399 else if (TYPE_PRECISION (type) == 64)
10400 lib_fun = cilk_for_64_fndecl;
10401 else
10402 gcc_unreachable ();
10404 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10406 /* WS_ARGS contains the library function flavor to call:
10407 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10408 user-defined grain value. If the user does not define one, then zero
10409 is passed in by the parser. */
10410 vec_alloc (region->ws_args, 2);
10411 region->ws_args->quick_push (lib_fun);
10412 region->ws_args->quick_push (fd->chunk_size);
10415 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10416 loop. Given parameters:
10418 for (V = N1; V cond N2; V += STEP) BODY;
10420 where COND is "<" or ">", we generate pseudocode
10422 V = N1;
10423 goto L1;
10425 BODY;
10426 V += STEP;
10428 if (V cond N2) goto L0; else goto L2;
10431 For collapsed loops, given parameters:
10432 collapse(3)
10433 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10434 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10435 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10436 BODY;
10438 we generate pseudocode
10440 if (cond3 is <)
10441 adj = STEP3 - 1;
10442 else
10443 adj = STEP3 + 1;
10444 count3 = (adj + N32 - N31) / STEP3;
10445 if (cond2 is <)
10446 adj = STEP2 - 1;
10447 else
10448 adj = STEP2 + 1;
10449 count2 = (adj + N22 - N21) / STEP2;
10450 if (cond1 is <)
10451 adj = STEP1 - 1;
10452 else
10453 adj = STEP1 + 1;
10454 count1 = (adj + N12 - N11) / STEP1;
10455 count = count1 * count2 * count3;
10456 V = 0;
10457 V1 = N11;
10458 V2 = N21;
10459 V3 = N31;
10460 goto L1;
10462 BODY;
10463 V += 1;
10464 V3 += STEP3;
10465 V2 += (V3 cond3 N32) ? 0 : STEP2;
10466 V3 = (V3 cond3 N32) ? V3 : N31;
10467 V1 += (V2 cond2 N22) ? 0 : STEP1;
10468 V2 = (V2 cond2 N22) ? V2 : N21;
10470 if (V < count) goto L0; else goto L2;
10475 static void
10476 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10478 tree type, t;
10479 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10480 gimple_stmt_iterator gsi;
10481 gimple *stmt;
10482 gcond *cond_stmt;
10483 bool broken_loop = region->cont == NULL;
10484 edge e, ne;
10485 tree *counts = NULL;
10486 int i;
10487 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10488 OMP_CLAUSE_SAFELEN);
10489 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10490 OMP_CLAUSE__SIMDUID_);
10491 tree n1, n2;
10493 type = TREE_TYPE (fd->loop.v);
10494 entry_bb = region->entry;
10495 cont_bb = region->cont;
10496 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10497 gcc_assert (broken_loop
10498 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10499 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10500 if (!broken_loop)
10502 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10503 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10504 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10505 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10507 else
10509 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10510 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10511 l2_bb = single_succ (l1_bb);
10513 exit_bb = region->exit;
10514 l2_dom_bb = NULL;
10516 gsi = gsi_last_bb (entry_bb);
10518 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10519 /* Not needed in SSA form right now. */
10520 gcc_assert (!gimple_in_ssa_p (cfun));
10521 if (fd->collapse > 1)
10523 int first_zero_iter = -1, dummy = -1;
10524 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10526 counts = XALLOCAVEC (tree, fd->collapse);
10527 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10528 zero_iter_bb, first_zero_iter,
10529 dummy_bb, dummy, l2_dom_bb);
10531 if (l2_dom_bb == NULL)
10532 l2_dom_bb = l1_bb;
10534 n1 = fd->loop.n1;
10535 n2 = fd->loop.n2;
10536 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10538 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10539 OMP_CLAUSE__LOOPTEMP_);
10540 gcc_assert (innerc);
10541 n1 = OMP_CLAUSE_DECL (innerc);
10542 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10543 OMP_CLAUSE__LOOPTEMP_);
10544 gcc_assert (innerc);
10545 n2 = OMP_CLAUSE_DECL (innerc);
10546 expand_omp_build_assign (&gsi, fd->loop.v,
10547 fold_convert (type, n1));
10548 if (fd->collapse > 1)
10550 gsi_prev (&gsi);
10551 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10552 gsi_next (&gsi);
10555 else
10557 expand_omp_build_assign (&gsi, fd->loop.v,
10558 fold_convert (type, fd->loop.n1));
10559 if (fd->collapse > 1)
10560 for (i = 0; i < fd->collapse; i++)
10562 tree itype = TREE_TYPE (fd->loops[i].v);
10563 if (POINTER_TYPE_P (itype))
10564 itype = signed_type_for (itype);
10565 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10566 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10570 /* Remove the GIMPLE_OMP_FOR statement. */
10571 gsi_remove (&gsi, true);
10573 if (!broken_loop)
10575 /* Code to control the increment goes in the CONT_BB. */
10576 gsi = gsi_last_bb (cont_bb);
10577 stmt = gsi_stmt (gsi);
10578 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10580 if (POINTER_TYPE_P (type))
10581 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10582 else
10583 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10584 expand_omp_build_assign (&gsi, fd->loop.v, t);
10586 if (fd->collapse > 1)
10588 i = fd->collapse - 1;
10589 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10591 t = fold_convert (sizetype, fd->loops[i].step);
10592 t = fold_build_pointer_plus (fd->loops[i].v, t);
10594 else
10596 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10597 fd->loops[i].step);
10598 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10599 fd->loops[i].v, t);
10601 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10603 for (i = fd->collapse - 1; i > 0; i--)
10605 tree itype = TREE_TYPE (fd->loops[i].v);
10606 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10607 if (POINTER_TYPE_P (itype2))
10608 itype2 = signed_type_for (itype2);
10609 t = build3 (COND_EXPR, itype2,
10610 build2 (fd->loops[i].cond_code, boolean_type_node,
10611 fd->loops[i].v,
10612 fold_convert (itype, fd->loops[i].n2)),
10613 build_int_cst (itype2, 0),
10614 fold_convert (itype2, fd->loops[i - 1].step));
10615 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10616 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10617 else
10618 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10619 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10621 t = build3 (COND_EXPR, itype,
10622 build2 (fd->loops[i].cond_code, boolean_type_node,
10623 fd->loops[i].v,
10624 fold_convert (itype, fd->loops[i].n2)),
10625 fd->loops[i].v,
10626 fold_convert (itype, fd->loops[i].n1));
10627 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10631 /* Remove GIMPLE_OMP_CONTINUE. */
10632 gsi_remove (&gsi, true);
10635 /* Emit the condition in L1_BB. */
10636 gsi = gsi_start_bb (l1_bb);
10638 t = fold_convert (type, n2);
10639 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10640 false, GSI_CONTINUE_LINKING);
10641 tree v = fd->loop.v;
10642 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10643 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10644 false, GSI_CONTINUE_LINKING);
10645 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10646 cond_stmt = gimple_build_cond_empty (t);
10647 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10648 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10649 NULL, NULL)
10650 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10651 NULL, NULL))
10653 gsi = gsi_for_stmt (cond_stmt);
10654 gimple_regimplify_operands (cond_stmt, &gsi);
10657 /* Remove GIMPLE_OMP_RETURN. */
10658 gsi = gsi_last_bb (exit_bb);
10659 gsi_remove (&gsi, true);
10661 /* Connect the new blocks. */
10662 remove_edge (FALLTHRU_EDGE (entry_bb));
10664 if (!broken_loop)
10666 remove_edge (BRANCH_EDGE (entry_bb));
10667 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10669 e = BRANCH_EDGE (l1_bb);
10670 ne = FALLTHRU_EDGE (l1_bb);
10671 e->flags = EDGE_TRUE_VALUE;
10673 else
10675 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10677 ne = single_succ_edge (l1_bb);
10678 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10681 ne->flags = EDGE_FALSE_VALUE;
10682 e->probability = REG_BR_PROB_BASE * 7 / 8;
10683 ne->probability = REG_BR_PROB_BASE / 8;
10685 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10686 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10687 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10689 if (!broken_loop)
10691 struct loop *loop = alloc_loop ();
10692 loop->header = l1_bb;
10693 loop->latch = cont_bb;
10694 add_loop (loop, l1_bb->loop_father);
10695 if (safelen == NULL_TREE)
10696 loop->safelen = INT_MAX;
10697 else
10699 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10700 if (TREE_CODE (safelen) != INTEGER_CST)
10701 loop->safelen = 0;
10702 else if (!tree_fits_uhwi_p (safelen)
10703 || tree_to_uhwi (safelen) > INT_MAX)
10704 loop->safelen = INT_MAX;
10705 else
10706 loop->safelen = tree_to_uhwi (safelen);
10707 if (loop->safelen == 1)
10708 loop->safelen = 0;
10710 if (simduid)
10712 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10713 cfun->has_simduid_loops = true;
10715 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10716 the loop. */
10717 if ((flag_tree_loop_vectorize
10718 || (!global_options_set.x_flag_tree_loop_vectorize
10719 && !global_options_set.x_flag_tree_vectorize))
10720 && flag_tree_loop_optimize
10721 && loop->safelen > 1)
10723 loop->force_vectorize = true;
10724 cfun->has_force_vectorize_loops = true;
10727 else if (simduid)
10728 cfun->has_simduid_loops = true;
10731 /* Taskloop construct is represented after gimplification with
10732 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10733 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10734 which should just compute all the needed loop temporaries
10735 for GIMPLE_OMP_TASK. */
10737 static void
10738 expand_omp_taskloop_for_outer (struct omp_region *region,
10739 struct omp_for_data *fd,
10740 gimple *inner_stmt)
10742 tree type, bias = NULL_TREE;
10743 basic_block entry_bb, cont_bb, exit_bb;
10744 gimple_stmt_iterator gsi;
10745 gassign *assign_stmt;
10746 tree *counts = NULL;
10747 int i;
10749 gcc_assert (inner_stmt);
10750 gcc_assert (region->cont);
10751 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10752 && gimple_omp_task_taskloop_p (inner_stmt));
10753 type = TREE_TYPE (fd->loop.v);
10755 /* See if we need to bias by LLONG_MIN. */
10756 if (fd->iter_type == long_long_unsigned_type_node
10757 && TREE_CODE (type) == INTEGER_TYPE
10758 && !TYPE_UNSIGNED (type))
10760 tree n1, n2;
10762 if (fd->loop.cond_code == LT_EXPR)
10764 n1 = fd->loop.n1;
10765 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10767 else
10769 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10770 n2 = fd->loop.n1;
10772 if (TREE_CODE (n1) != INTEGER_CST
10773 || TREE_CODE (n2) != INTEGER_CST
10774 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10775 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10778 entry_bb = region->entry;
10779 cont_bb = region->cont;
10780 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10781 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10782 exit_bb = region->exit;
10784 gsi = gsi_last_bb (entry_bb);
10785 gimple *for_stmt = gsi_stmt (gsi);
10786 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10787 if (fd->collapse > 1)
10789 int first_zero_iter = -1, dummy = -1;
10790 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10792 counts = XALLOCAVEC (tree, fd->collapse);
10793 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10794 zero_iter_bb, first_zero_iter,
10795 dummy_bb, dummy, l2_dom_bb);
10797 if (zero_iter_bb)
10799 /* Some counts[i] vars might be uninitialized if
10800 some loop has zero iterations. But the body shouldn't
10801 be executed in that case, so just avoid uninit warnings. */
10802 for (i = first_zero_iter; i < fd->collapse; i++)
10803 if (SSA_VAR_P (counts[i]))
10804 TREE_NO_WARNING (counts[i]) = 1;
10805 gsi_prev (&gsi);
10806 edge e = split_block (entry_bb, gsi_stmt (gsi));
10807 entry_bb = e->dest;
10808 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10809 gsi = gsi_last_bb (entry_bb);
10810 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10811 get_immediate_dominator (CDI_DOMINATORS,
10812 zero_iter_bb));
10816 tree t0, t1;
10817 t1 = fd->loop.n2;
10818 t0 = fd->loop.n1;
10819 if (POINTER_TYPE_P (TREE_TYPE (t0))
10820 && TYPE_PRECISION (TREE_TYPE (t0))
10821 != TYPE_PRECISION (fd->iter_type))
10823 /* Avoid casting pointers to integer of a different size. */
10824 tree itype = signed_type_for (type);
10825 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10826 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10828 else
10830 t1 = fold_convert (fd->iter_type, t1);
10831 t0 = fold_convert (fd->iter_type, t0);
10833 if (bias)
10835 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10836 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10839 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10840 OMP_CLAUSE__LOOPTEMP_);
10841 gcc_assert (innerc);
10842 tree startvar = OMP_CLAUSE_DECL (innerc);
10843 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10844 gcc_assert (innerc);
10845 tree endvar = OMP_CLAUSE_DECL (innerc);
10846 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10848 gcc_assert (innerc);
10849 for (i = 1; i < fd->collapse; i++)
10851 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10852 OMP_CLAUSE__LOOPTEMP_);
10853 gcc_assert (innerc);
10855 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10856 OMP_CLAUSE__LOOPTEMP_);
10857 if (innerc)
10859 /* If needed (inner taskloop has lastprivate clause), propagate
10860 down the total number of iterations. */
10861 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10862 NULL_TREE, false,
10863 GSI_CONTINUE_LINKING);
10864 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10865 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10869 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10870 GSI_CONTINUE_LINKING);
10871 assign_stmt = gimple_build_assign (startvar, t0);
10872 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10874 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10875 GSI_CONTINUE_LINKING);
10876 assign_stmt = gimple_build_assign (endvar, t1);
10877 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10878 if (fd->collapse > 1)
10879 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10881 /* Remove the GIMPLE_OMP_FOR statement. */
10882 gsi = gsi_for_stmt (for_stmt);
10883 gsi_remove (&gsi, true);
10885 gsi = gsi_last_bb (cont_bb);
10886 gsi_remove (&gsi, true);
10888 gsi = gsi_last_bb (exit_bb);
10889 gsi_remove (&gsi, true);
10891 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10892 remove_edge (BRANCH_EDGE (entry_bb));
10893 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10894 remove_edge (BRANCH_EDGE (cont_bb));
10895 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10896 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10897 recompute_dominator (CDI_DOMINATORS, region->entry));
10900 /* Taskloop construct is represented after gimplification with
10901 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10902 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10903 GOMP_taskloop{,_ull} function arranges for each task to be given just
10904 a single range of iterations. */
10906 static void
10907 expand_omp_taskloop_for_inner (struct omp_region *region,
10908 struct omp_for_data *fd,
10909 gimple *inner_stmt)
10911 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10912 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10913 basic_block fin_bb;
10914 gimple_stmt_iterator gsi;
10915 edge ep;
10916 bool broken_loop = region->cont == NULL;
10917 tree *counts = NULL;
10918 tree n1, n2, step;
10920 itype = type = TREE_TYPE (fd->loop.v);
10921 if (POINTER_TYPE_P (type))
10922 itype = signed_type_for (type);
10924 /* See if we need to bias by LLONG_MIN. */
10925 if (fd->iter_type == long_long_unsigned_type_node
10926 && TREE_CODE (type) == INTEGER_TYPE
10927 && !TYPE_UNSIGNED (type))
10929 tree n1, n2;
10931 if (fd->loop.cond_code == LT_EXPR)
10933 n1 = fd->loop.n1;
10934 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10936 else
10938 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10939 n2 = fd->loop.n1;
10941 if (TREE_CODE (n1) != INTEGER_CST
10942 || TREE_CODE (n2) != INTEGER_CST
10943 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10944 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10947 entry_bb = region->entry;
10948 cont_bb = region->cont;
10949 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10950 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10951 gcc_assert (broken_loop
10952 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10953 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10954 if (!broken_loop)
10956 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10957 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10959 exit_bb = region->exit;
10961 /* Iteration space partitioning goes in ENTRY_BB. */
10962 gsi = gsi_last_bb (entry_bb);
10963 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10965 if (fd->collapse > 1)
10967 int first_zero_iter = -1, dummy = -1;
10968 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10970 counts = XALLOCAVEC (tree, fd->collapse);
10971 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10972 fin_bb, first_zero_iter,
10973 dummy_bb, dummy, l2_dom_bb);
10974 t = NULL_TREE;
10976 else
10977 t = integer_one_node;
10979 step = fd->loop.step;
10980 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10981 OMP_CLAUSE__LOOPTEMP_);
10982 gcc_assert (innerc);
10983 n1 = OMP_CLAUSE_DECL (innerc);
10984 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10985 gcc_assert (innerc);
10986 n2 = OMP_CLAUSE_DECL (innerc);
10987 if (bias)
10989 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10990 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10992 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10993 true, NULL_TREE, true, GSI_SAME_STMT);
10994 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10995 true, NULL_TREE, true, GSI_SAME_STMT);
10996 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10997 true, NULL_TREE, true, GSI_SAME_STMT);
10999 tree startvar = fd->loop.v;
11000 tree endvar = NULL_TREE;
11002 if (gimple_omp_for_combined_p (fd->for_stmt))
11004 tree clauses = gimple_omp_for_clauses (inner_stmt);
11005 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
11006 gcc_assert (innerc);
11007 startvar = OMP_CLAUSE_DECL (innerc);
11008 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11009 OMP_CLAUSE__LOOPTEMP_);
11010 gcc_assert (innerc);
11011 endvar = OMP_CLAUSE_DECL (innerc);
11013 t = fold_convert (TREE_TYPE (startvar), n1);
11014 t = force_gimple_operand_gsi (&gsi, t,
11015 DECL_P (startvar)
11016 && TREE_ADDRESSABLE (startvar),
11017 NULL_TREE, false, GSI_CONTINUE_LINKING);
11018 gimple *assign_stmt = gimple_build_assign (startvar, t);
11019 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11021 t = fold_convert (TREE_TYPE (startvar), n2);
11022 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11023 false, GSI_CONTINUE_LINKING);
11024 if (endvar)
11026 assign_stmt = gimple_build_assign (endvar, e);
11027 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11028 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11029 assign_stmt = gimple_build_assign (fd->loop.v, e);
11030 else
11031 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11032 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11034 if (fd->collapse > 1)
11035 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11037 if (!broken_loop)
11039 /* The code controlling the sequential loop replaces the
11040 GIMPLE_OMP_CONTINUE. */
11041 gsi = gsi_last_bb (cont_bb);
11042 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11043 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11044 vmain = gimple_omp_continue_control_use (cont_stmt);
11045 vback = gimple_omp_continue_control_def (cont_stmt);
11047 if (!gimple_omp_for_combined_p (fd->for_stmt))
11049 if (POINTER_TYPE_P (type))
11050 t = fold_build_pointer_plus (vmain, step);
11051 else
11052 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11053 t = force_gimple_operand_gsi (&gsi, t,
11054 DECL_P (vback)
11055 && TREE_ADDRESSABLE (vback),
11056 NULL_TREE, true, GSI_SAME_STMT);
11057 assign_stmt = gimple_build_assign (vback, t);
11058 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11060 t = build2 (fd->loop.cond_code, boolean_type_node,
11061 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11062 ? t : vback, e);
11063 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11066 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11067 gsi_remove (&gsi, true);
11069 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11070 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11073 /* Remove the GIMPLE_OMP_FOR statement. */
11074 gsi = gsi_for_stmt (fd->for_stmt);
11075 gsi_remove (&gsi, true);
11077 /* Remove the GIMPLE_OMP_RETURN statement. */
11078 gsi = gsi_last_bb (exit_bb);
11079 gsi_remove (&gsi, true);
11081 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11082 if (!broken_loop)
11083 remove_edge (BRANCH_EDGE (entry_bb));
11084 else
11086 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11087 region->outer->cont = NULL;
11090 /* Connect all the blocks. */
11091 if (!broken_loop)
11093 ep = find_edge (cont_bb, body_bb);
11094 if (gimple_omp_for_combined_p (fd->for_stmt))
11096 remove_edge (ep);
11097 ep = NULL;
11099 else if (fd->collapse > 1)
11101 remove_edge (ep);
11102 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11104 else
11105 ep->flags = EDGE_TRUE_VALUE;
11106 find_edge (cont_bb, fin_bb)->flags
11107 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11110 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11111 recompute_dominator (CDI_DOMINATORS, body_bb));
11112 if (!broken_loop)
11113 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11114 recompute_dominator (CDI_DOMINATORS, fin_bb));
11116 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11118 struct loop *loop = alloc_loop ();
11119 loop->header = body_bb;
11120 if (collapse_bb == NULL)
11121 loop->latch = cont_bb;
11122 add_loop (loop, body_bb->loop_father);
11126 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11127 partitioned loop. The lowering here is abstracted, in that the
11128 loop parameters are passed through internal functions, which are
11129 further lowered by oacc_device_lower, once we get to the target
11130 compiler. The loop is of the form:
11132 for (V = B; V LTGT E; V += S) {BODY}
11134 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11135 (constant 0 for no chunking) and we will have a GWV partitioning
11136 mask, specifying dimensions over which the loop is to be
11137 partitioned (see note below). We generate code that looks like:
11139 <entry_bb> [incoming FALL->body, BRANCH->exit]
11140 typedef signedintify (typeof (V)) T; // underlying signed integral type
11141 T range = E - B;
11142 T chunk_no = 0;
11143 T DIR = LTGT == '<' ? +1 : -1;
11144 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11145 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11147 <head_bb> [created by splitting end of entry_bb]
11148 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11149 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11150 if (!(offset LTGT bound)) goto bottom_bb;
11152 <body_bb> [incoming]
11153 V = B + offset;
11154 {BODY}
11156 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11157 offset += step;
11158 if (offset LTGT bound) goto body_bb; [*]
11160 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11161 chunk_no++;
11162 if (chunk < chunk_max) goto head_bb;
11164 <exit_bb> [incoming]
11165 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11167 [*] Needed if V live at end of loop
11169 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11170 transition, and will be specified by a more general mechanism shortly.
11173 static void
11174 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11176 tree v = fd->loop.v;
11177 enum tree_code cond_code = fd->loop.cond_code;
11178 enum tree_code plus_code = PLUS_EXPR;
11180 tree chunk_size = integer_minus_one_node;
11181 tree gwv = integer_zero_node;
11182 tree iter_type = TREE_TYPE (v);
11183 tree diff_type = iter_type;
11184 tree plus_type = iter_type;
11185 struct oacc_collapse *counts = NULL;
11187 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11188 == GF_OMP_FOR_KIND_OACC_LOOP);
11189 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11190 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11192 if (POINTER_TYPE_P (iter_type))
11194 plus_code = POINTER_PLUS_EXPR;
11195 plus_type = sizetype;
11197 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11198 diff_type = signed_type_for (diff_type);
11200 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11201 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11202 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11203 basic_block bottom_bb = NULL;
11205 /* entry_bb has two sucessors; the branch edge is to the exit
11206 block, fallthrough edge to body. */
11207 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11208 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11210 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11211 body_bb, or to a block whose only successor is the body_bb. Its
11212 fallthrough successor is the final block (same as the branch
11213 successor of the entry_bb). */
11214 if (cont_bb)
11216 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11217 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11219 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11220 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11222 else
11223 gcc_assert (!gimple_in_ssa_p (cfun));
11225 /* The exit block only has entry_bb and cont_bb as predecessors. */
11226 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11228 tree chunk_no;
11229 tree chunk_max = NULL_TREE;
11230 tree bound, offset;
11231 tree step = create_tmp_var (diff_type, ".step");
11232 bool up = cond_code == LT_EXPR;
11233 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11234 bool chunking = !gimple_in_ssa_p (cfun);;
11235 bool negating;
11237 /* SSA instances. */
11238 tree offset_incr = NULL_TREE;
11239 tree offset_init = NULL_TREE;
11241 gimple_stmt_iterator gsi;
11242 gassign *ass;
11243 gcall *call;
11244 gimple *stmt;
11245 tree expr;
11246 location_t loc;
11247 edge split, be, fte;
11249 /* Split the end of entry_bb to create head_bb. */
11250 split = split_block (entry_bb, last_stmt (entry_bb));
11251 basic_block head_bb = split->dest;
11252 entry_bb = split->src;
11254 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11255 gsi = gsi_last_bb (entry_bb);
11256 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11257 loc = gimple_location (for_stmt);
11259 if (gimple_in_ssa_p (cfun))
11261 offset_init = gimple_omp_for_index (for_stmt, 0);
11262 gcc_assert (integer_zerop (fd->loop.n1));
11263 /* The SSA parallelizer does gang parallelism. */
11264 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11267 if (fd->collapse > 1)
11269 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11270 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11271 TREE_TYPE (fd->loop.n2));
11273 if (SSA_VAR_P (fd->loop.n2))
11275 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11276 true, GSI_SAME_STMT);
11277 ass = gimple_build_assign (fd->loop.n2, total);
11278 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11283 tree b = fd->loop.n1;
11284 tree e = fd->loop.n2;
11285 tree s = fd->loop.step;
11287 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11288 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11290 /* Convert the step, avoiding possible unsigned->signed overflow. */
11291 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11292 if (negating)
11293 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11294 s = fold_convert (diff_type, s);
11295 if (negating)
11296 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11297 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11299 if (!chunking)
11300 chunk_size = integer_zero_node;
11301 expr = fold_convert (diff_type, chunk_size);
11302 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11303 NULL_TREE, true, GSI_SAME_STMT);
11304 /* Determine the range, avoiding possible unsigned->signed overflow. */
11305 negating = !up && TYPE_UNSIGNED (iter_type);
11306 expr = fold_build2 (MINUS_EXPR, plus_type,
11307 fold_convert (plus_type, negating ? b : e),
11308 fold_convert (plus_type, negating ? e : b));
11309 expr = fold_convert (diff_type, expr);
11310 if (negating)
11311 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11312 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11313 NULL_TREE, true, GSI_SAME_STMT);
11315 chunk_no = build_int_cst (diff_type, 0);
11316 if (chunking)
11318 gcc_assert (!gimple_in_ssa_p (cfun));
11320 expr = chunk_no;
11321 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11322 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11324 ass = gimple_build_assign (chunk_no, expr);
11325 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11327 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11328 build_int_cst (integer_type_node,
11329 IFN_GOACC_LOOP_CHUNKS),
11330 dir, range, s, chunk_size, gwv);
11331 gimple_call_set_lhs (call, chunk_max);
11332 gimple_set_location (call, loc);
11333 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11335 else
11336 chunk_size = chunk_no;
11338 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11339 build_int_cst (integer_type_node,
11340 IFN_GOACC_LOOP_STEP),
11341 dir, range, s, chunk_size, gwv);
11342 gimple_call_set_lhs (call, step);
11343 gimple_set_location (call, loc);
11344 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11346 /* Remove the GIMPLE_OMP_FOR. */
11347 gsi_remove (&gsi, true);
11349 /* Fixup edges from head_bb */
11350 be = BRANCH_EDGE (head_bb);
11351 fte = FALLTHRU_EDGE (head_bb);
11352 be->flags |= EDGE_FALSE_VALUE;
11353 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11355 basic_block body_bb = fte->dest;
11357 if (gimple_in_ssa_p (cfun))
11359 gsi = gsi_last_bb (cont_bb);
11360 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11362 offset = gimple_omp_continue_control_use (cont_stmt);
11363 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11365 else
11367 offset = create_tmp_var (diff_type, ".offset");
11368 offset_init = offset_incr = offset;
11370 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11372 /* Loop offset & bound go into head_bb. */
11373 gsi = gsi_start_bb (head_bb);
11375 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11376 build_int_cst (integer_type_node,
11377 IFN_GOACC_LOOP_OFFSET),
11378 dir, range, s,
11379 chunk_size, gwv, chunk_no);
11380 gimple_call_set_lhs (call, offset_init);
11381 gimple_set_location (call, loc);
11382 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11384 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11385 build_int_cst (integer_type_node,
11386 IFN_GOACC_LOOP_BOUND),
11387 dir, range, s,
11388 chunk_size, gwv, offset_init);
11389 gimple_call_set_lhs (call, bound);
11390 gimple_set_location (call, loc);
11391 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11393 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11394 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11395 GSI_CONTINUE_LINKING);
11397 /* V assignment goes into body_bb. */
11398 if (!gimple_in_ssa_p (cfun))
11400 gsi = gsi_start_bb (body_bb);
11402 expr = build2 (plus_code, iter_type, b,
11403 fold_convert (plus_type, offset));
11404 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11405 true, GSI_SAME_STMT);
11406 ass = gimple_build_assign (v, expr);
11407 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11408 if (fd->collapse > 1)
11409 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11412 /* Loop increment goes into cont_bb. If this is not a loop, we
11413 will have spawned threads as if it was, and each one will
11414 execute one iteration. The specification is not explicit about
11415 whether such constructs are ill-formed or not, and they can
11416 occur, especially when noreturn routines are involved. */
11417 if (cont_bb)
11419 gsi = gsi_last_bb (cont_bb);
11420 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11421 loc = gimple_location (cont_stmt);
11423 /* Increment offset. */
11424 if (gimple_in_ssa_p (cfun))
11425 expr= build2 (plus_code, iter_type, offset,
11426 fold_convert (plus_type, step));
11427 else
11428 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11429 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11430 true, GSI_SAME_STMT);
11431 ass = gimple_build_assign (offset_incr, expr);
11432 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11433 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11434 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11436 /* Remove the GIMPLE_OMP_CONTINUE. */
11437 gsi_remove (&gsi, true);
11439 /* Fixup edges from cont_bb */
11440 be = BRANCH_EDGE (cont_bb);
11441 fte = FALLTHRU_EDGE (cont_bb);
11442 be->flags |= EDGE_TRUE_VALUE;
11443 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11445 if (chunking)
11447 /* Split the beginning of exit_bb to make bottom_bb. We
11448 need to insert a nop at the start, because splitting is
11449 after a stmt, not before. */
11450 gsi = gsi_start_bb (exit_bb);
11451 stmt = gimple_build_nop ();
11452 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11453 split = split_block (exit_bb, stmt);
11454 bottom_bb = split->src;
11455 exit_bb = split->dest;
11456 gsi = gsi_last_bb (bottom_bb);
11458 /* Chunk increment and test goes into bottom_bb. */
11459 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11460 build_int_cst (diff_type, 1));
11461 ass = gimple_build_assign (chunk_no, expr);
11462 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11464 /* Chunk test at end of bottom_bb. */
11465 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11466 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11467 GSI_CONTINUE_LINKING);
11469 /* Fixup edges from bottom_bb. */
11470 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11471 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11475 gsi = gsi_last_bb (exit_bb);
11476 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11477 loc = gimple_location (gsi_stmt (gsi));
11479 if (!gimple_in_ssa_p (cfun))
11481 /* Insert the final value of V, in case it is live. This is the
11482 value for the only thread that survives past the join. */
11483 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11484 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11485 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11486 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11487 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11488 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11489 true, GSI_SAME_STMT);
11490 ass = gimple_build_assign (v, expr);
11491 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11494 /* Remove the OMP_RETURN. */
11495 gsi_remove (&gsi, true);
11497 if (cont_bb)
11499 /* We now have one or two nested loops. Update the loop
11500 structures. */
11501 struct loop *parent = entry_bb->loop_father;
11502 struct loop *body = body_bb->loop_father;
11504 if (chunking)
11506 struct loop *chunk_loop = alloc_loop ();
11507 chunk_loop->header = head_bb;
11508 chunk_loop->latch = bottom_bb;
11509 add_loop (chunk_loop, parent);
11510 parent = chunk_loop;
11512 else if (parent != body)
11514 gcc_assert (body->header == body_bb);
11515 gcc_assert (body->latch == cont_bb
11516 || single_pred (body->latch) == cont_bb);
11517 parent = NULL;
11520 if (parent)
11522 struct loop *body_loop = alloc_loop ();
11523 body_loop->header = body_bb;
11524 body_loop->latch = cont_bb;
11525 add_loop (body_loop, parent);
11530 /* Expand the OMP loop defined by REGION. */
11532 static void
11533 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11535 struct omp_for_data fd;
11536 struct omp_for_data_loop *loops;
11538 loops
11539 = (struct omp_for_data_loop *)
11540 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11541 * sizeof (struct omp_for_data_loop));
11542 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11543 &fd, loops);
11544 region->sched_kind = fd.sched_kind;
11545 region->sched_modifiers = fd.sched_modifiers;
11547 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11548 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11549 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11550 if (region->cont)
11552 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11553 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11554 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11556 else
11557 /* If there isn't a continue then this is a degerate case where
11558 the introduction of abnormal edges during lowering will prevent
11559 original loops from being detected. Fix that up. */
11560 loops_state_set (LOOPS_NEED_FIXUP);
11562 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11563 expand_omp_simd (region, &fd);
11564 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11565 expand_cilk_for (region, &fd);
11566 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11568 gcc_assert (!inner_stmt);
11569 expand_oacc_for (region, &fd);
11571 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11573 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11574 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11575 else
11576 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11578 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11579 && !fd.have_ordered)
11581 if (fd.chunk_size == NULL)
11582 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11583 else
11584 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11586 else
11588 int fn_index, start_ix, next_ix;
11590 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11591 == GF_OMP_FOR_KIND_FOR);
11592 if (fd.chunk_size == NULL
11593 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11594 fd.chunk_size = integer_zero_node;
11595 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11596 switch (fd.sched_kind)
11598 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11599 fn_index = 3;
11600 break;
11601 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11602 case OMP_CLAUSE_SCHEDULE_GUIDED:
11603 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11604 && !fd.ordered
11605 && !fd.have_ordered)
11607 fn_index = 3 + fd.sched_kind;
11608 break;
11610 /* FALLTHRU */
11611 default:
11612 fn_index = fd.sched_kind;
11613 break;
11615 if (!fd.ordered)
11616 fn_index += fd.have_ordered * 6;
11617 if (fd.ordered)
11618 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11619 else
11620 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11621 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11622 if (fd.iter_type == long_long_unsigned_type_node)
11624 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11625 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11626 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11627 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11629 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11630 (enum built_in_function) next_ix, inner_stmt);
11633 if (gimple_in_ssa_p (cfun))
11634 update_ssa (TODO_update_ssa_only_virtuals);
11638 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11640 v = GOMP_sections_start (n);
11642 switch (v)
11644 case 0:
11645 goto L2;
11646 case 1:
11647 section 1;
11648 goto L1;
11649 case 2:
11651 case n:
11653 default:
11654 abort ();
11657 v = GOMP_sections_next ();
11658 goto L0;
11660 reduction;
11662 If this is a combined parallel sections, replace the call to
11663 GOMP_sections_start with call to GOMP_sections_next. */
11665 static void
11666 expand_omp_sections (struct omp_region *region)
11668 tree t, u, vin = NULL, vmain, vnext, l2;
11669 unsigned len;
11670 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11671 gimple_stmt_iterator si, switch_si;
11672 gomp_sections *sections_stmt;
11673 gimple *stmt;
11674 gomp_continue *cont;
11675 edge_iterator ei;
11676 edge e;
11677 struct omp_region *inner;
11678 unsigned i, casei;
11679 bool exit_reachable = region->cont != NULL;
11681 gcc_assert (region->exit != NULL);
11682 entry_bb = region->entry;
11683 l0_bb = single_succ (entry_bb);
11684 l1_bb = region->cont;
11685 l2_bb = region->exit;
11686 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11687 l2 = gimple_block_label (l2_bb);
11688 else
11690 /* This can happen if there are reductions. */
11691 len = EDGE_COUNT (l0_bb->succs);
11692 gcc_assert (len > 0);
11693 e = EDGE_SUCC (l0_bb, len - 1);
11694 si = gsi_last_bb (e->dest);
11695 l2 = NULL_TREE;
11696 if (gsi_end_p (si)
11697 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11698 l2 = gimple_block_label (e->dest);
11699 else
11700 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11702 si = gsi_last_bb (e->dest);
11703 if (gsi_end_p (si)
11704 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11706 l2 = gimple_block_label (e->dest);
11707 break;
11711 if (exit_reachable)
11712 default_bb = create_empty_bb (l1_bb->prev_bb);
11713 else
11714 default_bb = create_empty_bb (l0_bb);
11716 /* We will build a switch() with enough cases for all the
11717 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11718 and a default case to abort if something goes wrong. */
11719 len = EDGE_COUNT (l0_bb->succs);
11721 /* Use vec::quick_push on label_vec throughout, since we know the size
11722 in advance. */
11723 auto_vec<tree> label_vec (len);
11725 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11726 GIMPLE_OMP_SECTIONS statement. */
11727 si = gsi_last_bb (entry_bb);
11728 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11729 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11730 vin = gimple_omp_sections_control (sections_stmt);
11731 if (!is_combined_parallel (region))
11733 /* If we are not inside a combined parallel+sections region,
11734 call GOMP_sections_start. */
11735 t = build_int_cst (unsigned_type_node, len - 1);
11736 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11737 stmt = gimple_build_call (u, 1, t);
11739 else
11741 /* Otherwise, call GOMP_sections_next. */
11742 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11743 stmt = gimple_build_call (u, 0);
11745 gimple_call_set_lhs (stmt, vin);
11746 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11747 gsi_remove (&si, true);
11749 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11750 L0_BB. */
11751 switch_si = gsi_last_bb (l0_bb);
11752 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11753 if (exit_reachable)
11755 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11756 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11757 vmain = gimple_omp_continue_control_use (cont);
11758 vnext = gimple_omp_continue_control_def (cont);
11760 else
11762 vmain = vin;
11763 vnext = NULL_TREE;
11766 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11767 label_vec.quick_push (t);
11768 i = 1;
11770 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11771 for (inner = region->inner, casei = 1;
11772 inner;
11773 inner = inner->next, i++, casei++)
11775 basic_block s_entry_bb, s_exit_bb;
11777 /* Skip optional reduction region. */
11778 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11780 --i;
11781 --casei;
11782 continue;
11785 s_entry_bb = inner->entry;
11786 s_exit_bb = inner->exit;
11788 t = gimple_block_label (s_entry_bb);
11789 u = build_int_cst (unsigned_type_node, casei);
11790 u = build_case_label (u, NULL, t);
11791 label_vec.quick_push (u);
11793 si = gsi_last_bb (s_entry_bb);
11794 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11795 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11796 gsi_remove (&si, true);
11797 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11799 if (s_exit_bb == NULL)
11800 continue;
11802 si = gsi_last_bb (s_exit_bb);
11803 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11804 gsi_remove (&si, true);
11806 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11809 /* Error handling code goes in DEFAULT_BB. */
11810 t = gimple_block_label (default_bb);
11811 u = build_case_label (NULL, NULL, t);
11812 make_edge (l0_bb, default_bb, 0);
11813 add_bb_to_loop (default_bb, current_loops->tree_root);
11815 stmt = gimple_build_switch (vmain, u, label_vec);
11816 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11817 gsi_remove (&switch_si, true);
11819 si = gsi_start_bb (default_bb);
11820 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11821 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11823 if (exit_reachable)
11825 tree bfn_decl;
11827 /* Code to get the next section goes in L1_BB. */
11828 si = gsi_last_bb (l1_bb);
11829 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11831 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11832 stmt = gimple_build_call (bfn_decl, 0);
11833 gimple_call_set_lhs (stmt, vnext);
11834 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11835 gsi_remove (&si, true);
11837 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11840 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11841 si = gsi_last_bb (l2_bb);
11842 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11843 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11844 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11845 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11846 else
11847 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11848 stmt = gimple_build_call (t, 0);
11849 if (gimple_omp_return_lhs (gsi_stmt (si)))
11850 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11851 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11852 gsi_remove (&si, true);
11854 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11858 /* Expand code for an OpenMP single directive. We've already expanded
11859 much of the code, here we simply place the GOMP_barrier call. */
11861 static void
11862 expand_omp_single (struct omp_region *region)
11864 basic_block entry_bb, exit_bb;
11865 gimple_stmt_iterator si;
11867 entry_bb = region->entry;
11868 exit_bb = region->exit;
11870 si = gsi_last_bb (entry_bb);
11871 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11872 gsi_remove (&si, true);
11873 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11875 si = gsi_last_bb (exit_bb);
11876 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11878 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11879 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11881 gsi_remove (&si, true);
11882 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11886 /* Generic expansion for OpenMP synchronization directives: master,
11887 ordered and critical. All we need to do here is remove the entry
11888 and exit markers for REGION. */
11890 static void
11891 expand_omp_synch (struct omp_region *region)
11893 basic_block entry_bb, exit_bb;
11894 gimple_stmt_iterator si;
11896 entry_bb = region->entry;
11897 exit_bb = region->exit;
11899 si = gsi_last_bb (entry_bb);
11900 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11901 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11902 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11903 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11904 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11905 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11906 gsi_remove (&si, true);
11907 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11909 if (exit_bb)
11911 si = gsi_last_bb (exit_bb);
11912 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11913 gsi_remove (&si, true);
11914 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11918 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11919 operation as a normal volatile load. */
11921 static bool
11922 expand_omp_atomic_load (basic_block load_bb, tree addr,
11923 tree loaded_val, int index)
11925 enum built_in_function tmpbase;
11926 gimple_stmt_iterator gsi;
11927 basic_block store_bb;
11928 location_t loc;
11929 gimple *stmt;
11930 tree decl, call, type, itype;
11932 gsi = gsi_last_bb (load_bb);
11933 stmt = gsi_stmt (gsi);
11934 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11935 loc = gimple_location (stmt);
11937 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11938 is smaller than word size, then expand_atomic_load assumes that the load
11939 is atomic. We could avoid the builtin entirely in this case. */
11941 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11942 decl = builtin_decl_explicit (tmpbase);
11943 if (decl == NULL_TREE)
11944 return false;
11946 type = TREE_TYPE (loaded_val);
11947 itype = TREE_TYPE (TREE_TYPE (decl));
11949 call = build_call_expr_loc (loc, decl, 2, addr,
11950 build_int_cst (NULL,
11951 gimple_omp_atomic_seq_cst_p (stmt)
11952 ? MEMMODEL_SEQ_CST
11953 : MEMMODEL_RELAXED));
11954 if (!useless_type_conversion_p (type, itype))
11955 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11956 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11958 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11959 gsi_remove (&gsi, true);
11961 store_bb = single_succ (load_bb);
11962 gsi = gsi_last_bb (store_bb);
11963 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11964 gsi_remove (&gsi, true);
11966 if (gimple_in_ssa_p (cfun))
11967 update_ssa (TODO_update_ssa_no_phi);
11969 return true;
11972 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11973 operation as a normal volatile store. */
11975 static bool
11976 expand_omp_atomic_store (basic_block load_bb, tree addr,
11977 tree loaded_val, tree stored_val, int index)
11979 enum built_in_function tmpbase;
11980 gimple_stmt_iterator gsi;
11981 basic_block store_bb = single_succ (load_bb);
11982 location_t loc;
11983 gimple *stmt;
11984 tree decl, call, type, itype;
11985 machine_mode imode;
11986 bool exchange;
11988 gsi = gsi_last_bb (load_bb);
11989 stmt = gsi_stmt (gsi);
11990 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11992 /* If the load value is needed, then this isn't a store but an exchange. */
11993 exchange = gimple_omp_atomic_need_value_p (stmt);
11995 gsi = gsi_last_bb (store_bb);
11996 stmt = gsi_stmt (gsi);
11997 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11998 loc = gimple_location (stmt);
12000 /* ??? If the target does not implement atomic_store_optab[mode], and mode
12001 is smaller than word size, then expand_atomic_store assumes that the store
12002 is atomic. We could avoid the builtin entirely in this case. */
12004 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
12005 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
12006 decl = builtin_decl_explicit (tmpbase);
12007 if (decl == NULL_TREE)
12008 return false;
12010 type = TREE_TYPE (stored_val);
12012 /* Dig out the type of the function's second argument. */
12013 itype = TREE_TYPE (decl);
12014 itype = TYPE_ARG_TYPES (itype);
12015 itype = TREE_CHAIN (itype);
12016 itype = TREE_VALUE (itype);
12017 imode = TYPE_MODE (itype);
12019 if (exchange && !can_atomic_exchange_p (imode, true))
12020 return false;
12022 if (!useless_type_conversion_p (itype, type))
12023 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12024 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12025 build_int_cst (NULL,
12026 gimple_omp_atomic_seq_cst_p (stmt)
12027 ? MEMMODEL_SEQ_CST
12028 : MEMMODEL_RELAXED));
12029 if (exchange)
12031 if (!useless_type_conversion_p (type, itype))
12032 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12033 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12036 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12037 gsi_remove (&gsi, true);
12039 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12040 gsi = gsi_last_bb (load_bb);
12041 gsi_remove (&gsi, true);
12043 if (gimple_in_ssa_p (cfun))
12044 update_ssa (TODO_update_ssa_no_phi);
12046 return true;
12049 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12050 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12051 size of the data type, and thus usable to find the index of the builtin
12052 decl. Returns false if the expression is not of the proper form. */
12054 static bool
12055 expand_omp_atomic_fetch_op (basic_block load_bb,
12056 tree addr, tree loaded_val,
12057 tree stored_val, int index)
12059 enum built_in_function oldbase, newbase, tmpbase;
12060 tree decl, itype, call;
12061 tree lhs, rhs;
12062 basic_block store_bb = single_succ (load_bb);
12063 gimple_stmt_iterator gsi;
12064 gimple *stmt;
12065 location_t loc;
12066 enum tree_code code;
12067 bool need_old, need_new;
12068 machine_mode imode;
12069 bool seq_cst;
12071 /* We expect to find the following sequences:
12073 load_bb:
12074 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12076 store_bb:
12077 val = tmp OP something; (or: something OP tmp)
12078 GIMPLE_OMP_STORE (val)
12080 ???FIXME: Allow a more flexible sequence.
12081 Perhaps use data flow to pick the statements.
12085 gsi = gsi_after_labels (store_bb);
12086 stmt = gsi_stmt (gsi);
12087 loc = gimple_location (stmt);
12088 if (!is_gimple_assign (stmt))
12089 return false;
12090 gsi_next (&gsi);
12091 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12092 return false;
12093 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12094 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12095 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12096 gcc_checking_assert (!need_old || !need_new);
12098 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12099 return false;
12101 /* Check for one of the supported fetch-op operations. */
12102 code = gimple_assign_rhs_code (stmt);
12103 switch (code)
12105 case PLUS_EXPR:
12106 case POINTER_PLUS_EXPR:
12107 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12108 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12109 break;
12110 case MINUS_EXPR:
12111 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12112 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12113 break;
12114 case BIT_AND_EXPR:
12115 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12116 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12117 break;
12118 case BIT_IOR_EXPR:
12119 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12120 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12121 break;
12122 case BIT_XOR_EXPR:
12123 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12124 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12125 break;
12126 default:
12127 return false;
12130 /* Make sure the expression is of the proper form. */
12131 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12132 rhs = gimple_assign_rhs2 (stmt);
12133 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12134 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12135 rhs = gimple_assign_rhs1 (stmt);
12136 else
12137 return false;
12139 tmpbase = ((enum built_in_function)
12140 ((need_new ? newbase : oldbase) + index + 1));
12141 decl = builtin_decl_explicit (tmpbase);
12142 if (decl == NULL_TREE)
12143 return false;
12144 itype = TREE_TYPE (TREE_TYPE (decl));
12145 imode = TYPE_MODE (itype);
12147 /* We could test all of the various optabs involved, but the fact of the
12148 matter is that (with the exception of i486 vs i586 and xadd) all targets
12149 that support any atomic operaton optab also implements compare-and-swap.
12150 Let optabs.c take care of expanding any compare-and-swap loop. */
12151 if (!can_compare_and_swap_p (imode, true))
12152 return false;
12154 gsi = gsi_last_bb (load_bb);
12155 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12157 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12158 It only requires that the operation happen atomically. Thus we can
12159 use the RELAXED memory model. */
12160 call = build_call_expr_loc (loc, decl, 3, addr,
12161 fold_convert_loc (loc, itype, rhs),
12162 build_int_cst (NULL,
12163 seq_cst ? MEMMODEL_SEQ_CST
12164 : MEMMODEL_RELAXED));
12166 if (need_old || need_new)
12168 lhs = need_old ? loaded_val : stored_val;
12169 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12170 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12172 else
12173 call = fold_convert_loc (loc, void_type_node, call);
12174 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12175 gsi_remove (&gsi, true);
12177 gsi = gsi_last_bb (store_bb);
12178 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12179 gsi_remove (&gsi, true);
12180 gsi = gsi_last_bb (store_bb);
12181 stmt = gsi_stmt (gsi);
12182 gsi_remove (&gsi, true);
12184 if (gimple_in_ssa_p (cfun))
12186 release_defs (stmt);
12187 update_ssa (TODO_update_ssa_no_phi);
12190 return true;
12193 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12195 oldval = *addr;
12196 repeat:
12197 newval = rhs; // with oldval replacing *addr in rhs
12198 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12199 if (oldval != newval)
12200 goto repeat;
12202 INDEX is log2 of the size of the data type, and thus usable to find the
12203 index of the builtin decl. */
12205 static bool
12206 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12207 tree addr, tree loaded_val, tree stored_val,
12208 int index)
12210 tree loadedi, storedi, initial, new_storedi, old_vali;
12211 tree type, itype, cmpxchg, iaddr;
12212 gimple_stmt_iterator si;
12213 basic_block loop_header = single_succ (load_bb);
12214 gimple *phi, *stmt;
12215 edge e;
12216 enum built_in_function fncode;
12218 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12219 order to use the RELAXED memory model effectively. */
12220 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12221 + index + 1);
12222 cmpxchg = builtin_decl_explicit (fncode);
12223 if (cmpxchg == NULL_TREE)
12224 return false;
12225 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12226 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12228 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12229 return false;
12231 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12232 si = gsi_last_bb (load_bb);
12233 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12235 /* For floating-point values, we'll need to view-convert them to integers
12236 so that we can perform the atomic compare and swap. Simplify the
12237 following code by always setting up the "i"ntegral variables. */
12238 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12240 tree iaddr_val;
12242 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12243 true));
12244 iaddr_val
12245 = force_gimple_operand_gsi (&si,
12246 fold_convert (TREE_TYPE (iaddr), addr),
12247 false, NULL_TREE, true, GSI_SAME_STMT);
12248 stmt = gimple_build_assign (iaddr, iaddr_val);
12249 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12250 loadedi = create_tmp_var (itype);
12251 if (gimple_in_ssa_p (cfun))
12252 loadedi = make_ssa_name (loadedi);
12254 else
12256 iaddr = addr;
12257 loadedi = loaded_val;
12260 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12261 tree loaddecl = builtin_decl_explicit (fncode);
12262 if (loaddecl)
12263 initial
12264 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12265 build_call_expr (loaddecl, 2, iaddr,
12266 build_int_cst (NULL_TREE,
12267 MEMMODEL_RELAXED)));
12268 else
12269 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12270 build_int_cst (TREE_TYPE (iaddr), 0));
12272 initial
12273 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12274 GSI_SAME_STMT);
12276 /* Move the value to the LOADEDI temporary. */
12277 if (gimple_in_ssa_p (cfun))
12279 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12280 phi = create_phi_node (loadedi, loop_header);
12281 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12282 initial);
12284 else
12285 gsi_insert_before (&si,
12286 gimple_build_assign (loadedi, initial),
12287 GSI_SAME_STMT);
12288 if (loadedi != loaded_val)
12290 gimple_stmt_iterator gsi2;
12291 tree x;
12293 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12294 gsi2 = gsi_start_bb (loop_header);
12295 if (gimple_in_ssa_p (cfun))
12297 gassign *stmt;
12298 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12299 true, GSI_SAME_STMT);
12300 stmt = gimple_build_assign (loaded_val, x);
12301 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12303 else
12305 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12306 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12307 true, GSI_SAME_STMT);
12310 gsi_remove (&si, true);
12312 si = gsi_last_bb (store_bb);
12313 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12315 if (iaddr == addr)
12316 storedi = stored_val;
12317 else
12318 storedi =
12319 force_gimple_operand_gsi (&si,
12320 build1 (VIEW_CONVERT_EXPR, itype,
12321 stored_val), true, NULL_TREE, true,
12322 GSI_SAME_STMT);
12324 /* Build the compare&swap statement. */
12325 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12326 new_storedi = force_gimple_operand_gsi (&si,
12327 fold_convert (TREE_TYPE (loadedi),
12328 new_storedi),
12329 true, NULL_TREE,
12330 true, GSI_SAME_STMT);
12332 if (gimple_in_ssa_p (cfun))
12333 old_vali = loadedi;
12334 else
12336 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12337 stmt = gimple_build_assign (old_vali, loadedi);
12338 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12340 stmt = gimple_build_assign (loadedi, new_storedi);
12341 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12344 /* Note that we always perform the comparison as an integer, even for
12345 floating point. This allows the atomic operation to properly
12346 succeed even with NaNs and -0.0. */
12347 stmt = gimple_build_cond_empty
12348 (build2 (NE_EXPR, boolean_type_node,
12349 new_storedi, old_vali));
12350 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12352 /* Update cfg. */
12353 e = single_succ_edge (store_bb);
12354 e->flags &= ~EDGE_FALLTHRU;
12355 e->flags |= EDGE_FALSE_VALUE;
12357 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12359 /* Copy the new value to loadedi (we already did that before the condition
12360 if we are not in SSA). */
12361 if (gimple_in_ssa_p (cfun))
12363 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12364 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12367 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12368 gsi_remove (&si, true);
12370 struct loop *loop = alloc_loop ();
12371 loop->header = loop_header;
12372 loop->latch = store_bb;
12373 add_loop (loop, loop_header->loop_father);
12375 if (gimple_in_ssa_p (cfun))
12376 update_ssa (TODO_update_ssa_no_phi);
12378 return true;
12381 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12383 GOMP_atomic_start ();
12384 *addr = rhs;
12385 GOMP_atomic_end ();
12387 The result is not globally atomic, but works so long as all parallel
12388 references are within #pragma omp atomic directives. According to
12389 responses received from omp@openmp.org, appears to be within spec.
12390 Which makes sense, since that's how several other compilers handle
12391 this situation as well.
12392 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12393 expanding. STORED_VAL is the operand of the matching
12394 GIMPLE_OMP_ATOMIC_STORE.
12396 We replace
12397 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12398 loaded_val = *addr;
12400 and replace
12401 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12402 *addr = stored_val;
12405 static bool
12406 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12407 tree addr, tree loaded_val, tree stored_val)
12409 gimple_stmt_iterator si;
12410 gassign *stmt;
12411 tree t;
12413 si = gsi_last_bb (load_bb);
12414 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12416 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12417 t = build_call_expr (t, 0);
12418 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12420 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12421 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12422 gsi_remove (&si, true);
12424 si = gsi_last_bb (store_bb);
12425 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12427 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12428 stored_val);
12429 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12431 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12432 t = build_call_expr (t, 0);
12433 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12434 gsi_remove (&si, true);
12436 if (gimple_in_ssa_p (cfun))
12437 update_ssa (TODO_update_ssa_no_phi);
12438 return true;
12441 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12442 using expand_omp_atomic_fetch_op. If it failed, we try to
12443 call expand_omp_atomic_pipeline, and if it fails too, the
12444 ultimate fallback is wrapping the operation in a mutex
12445 (expand_omp_atomic_mutex). REGION is the atomic region built
12446 by build_omp_regions_1(). */
12448 static void
12449 expand_omp_atomic (struct omp_region *region)
12451 basic_block load_bb = region->entry, store_bb = region->exit;
12452 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12453 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12454 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12455 tree addr = gimple_omp_atomic_load_rhs (load);
12456 tree stored_val = gimple_omp_atomic_store_val (store);
12457 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12458 HOST_WIDE_INT index;
12460 /* Make sure the type is one of the supported sizes. */
12461 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12462 index = exact_log2 (index);
12463 if (index >= 0 && index <= 4)
12465 unsigned int align = TYPE_ALIGN_UNIT (type);
12467 /* __sync builtins require strict data alignment. */
12468 if (exact_log2 (align) >= index)
12470 /* Atomic load. */
12471 if (loaded_val == stored_val
12472 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12473 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12474 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12475 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12476 return;
12478 /* Atomic store. */
12479 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12480 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12481 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12482 && store_bb == single_succ (load_bb)
12483 && first_stmt (store_bb) == store
12484 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12485 stored_val, index))
12486 return;
12488 /* When possible, use specialized atomic update functions. */
12489 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12490 && store_bb == single_succ (load_bb)
12491 && expand_omp_atomic_fetch_op (load_bb, addr,
12492 loaded_val, stored_val, index))
12493 return;
12495 /* If we don't have specialized __sync builtins, try and implement
12496 as a compare and swap loop. */
12497 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12498 loaded_val, stored_val, index))
12499 return;
12503 /* The ultimate fallback is wrapping the operation in a mutex. */
12504 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12508 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12509 macro on gomp-constants.h. We do not check for overflow. */
12511 static tree
12512 oacc_launch_pack (unsigned code, tree device, unsigned op)
12514 tree res;
12516 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12517 if (device)
12519 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12520 device, build_int_cst (unsigned_type_node,
12521 GOMP_LAUNCH_DEVICE_SHIFT));
12522 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12524 return res;
12527 /* Look for compute grid dimension clauses and convert to an attribute
12528 attached to FN. This permits the target-side code to (a) massage
12529 the dimensions, (b) emit that data and (c) optimize. Non-constant
12530 dimensions are pushed onto ARGS.
12532 The attribute value is a TREE_LIST. A set of dimensions is
12533 represented as a list of INTEGER_CST. Those that are runtime
12534 exprs are represented as an INTEGER_CST of zero.
12536 TOOO. Normally the attribute will just contain a single such list. If
12537 however it contains a list of lists, this will represent the use of
12538 device_type. Each member of the outer list is an assoc list of
12539 dimensions, keyed by the device type. The first entry will be the
12540 default. Well, that's the plan. */
12542 #define OACC_FN_ATTRIB "oacc function"
12544 /* Replace any existing oacc fn attribute with updated dimensions. */
12546 void
12547 replace_oacc_fn_attrib (tree fn, tree dims)
12549 tree ident = get_identifier (OACC_FN_ATTRIB);
12550 tree attribs = DECL_ATTRIBUTES (fn);
12552 /* If we happen to be present as the first attrib, drop it. */
12553 if (attribs && TREE_PURPOSE (attribs) == ident)
12554 attribs = TREE_CHAIN (attribs);
12555 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12558 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12559 function attribute. Push any that are non-constant onto the ARGS
12560 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12561 true, if these are for a kernels region offload function. */
12563 void
12564 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12566 /* Must match GOMP_DIM ordering. */
12567 static const omp_clause_code ids[]
12568 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12569 OMP_CLAUSE_VECTOR_LENGTH };
12570 unsigned ix;
12571 tree dims[GOMP_DIM_MAX];
12572 tree attr = NULL_TREE;
12573 unsigned non_const = 0;
12575 for (ix = GOMP_DIM_MAX; ix--;)
12577 tree clause = find_omp_clause (clauses, ids[ix]);
12578 tree dim = NULL_TREE;
12580 if (clause)
12581 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12582 dims[ix] = dim;
12583 if (dim && TREE_CODE (dim) != INTEGER_CST)
12585 dim = integer_zero_node;
12586 non_const |= GOMP_DIM_MASK (ix);
12588 attr = tree_cons (NULL_TREE, dim, attr);
12589 /* Note kernelness with TREE_PUBLIC. */
12590 if (is_kernel)
12591 TREE_PUBLIC (attr) = 1;
12594 replace_oacc_fn_attrib (fn, attr);
12596 if (non_const)
12598 /* Push a dynamic argument set. */
12599 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12600 NULL_TREE, non_const));
12601 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12602 if (non_const & GOMP_DIM_MASK (ix))
12603 args->safe_push (dims[ix]);
12607 /* Process the routine's dimension clauess to generate an attribute
12608 value. Issue diagnostics as appropriate. We default to SEQ
12609 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12610 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12611 can have a loop partitioned on it. non-zero indicates
12612 yes, zero indicates no. By construction once a non-zero has been
12613 reached, further inner dimensions must also be non-zero. We set
12614 TREE_VALUE to zero for the dimensions that may be partitioned and
12615 1 for the other ones -- if a loop is (erroneously) spawned at
12616 an outer level, we don't want to try and partition it. */
12618 tree
12619 build_oacc_routine_dims (tree clauses)
12621 /* Must match GOMP_DIM ordering. */
12622 static const omp_clause_code ids[] =
12623 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12624 int ix;
12625 int level = -1;
12627 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12628 for (ix = GOMP_DIM_MAX + 1; ix--;)
12629 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12631 if (level >= 0)
12632 error_at (OMP_CLAUSE_LOCATION (clauses),
12633 "multiple loop axes specified for routine");
12634 level = ix;
12635 break;
12638 /* Default to SEQ. */
12639 if (level < 0)
12640 level = GOMP_DIM_MAX;
12642 tree dims = NULL_TREE;
12644 for (ix = GOMP_DIM_MAX; ix--;)
12645 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12646 build_int_cst (integer_type_node, ix < level), dims);
12648 return dims;
12651 /* Retrieve the oacc function attrib and return it. Non-oacc
12652 functions will return NULL. */
12654 tree
12655 get_oacc_fn_attrib (tree fn)
12657 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12660 /* Return true if this oacc fn attrib is for a kernels offload
12661 region. We use the TREE_PUBLIC flag of each dimension -- only
12662 need to check the first one. */
12664 bool
12665 oacc_fn_attrib_kernels_p (tree attr)
12667 return TREE_PUBLIC (TREE_VALUE (attr));
12670 /* Return level at which oacc routine may spawn a partitioned loop, or
12671 -1 if it is not a routine (i.e. is an offload fn). */
12673 static int
12674 oacc_fn_attrib_level (tree attr)
12676 tree pos = TREE_VALUE (attr);
12678 if (!TREE_PURPOSE (pos))
12679 return -1;
12681 int ix = 0;
12682 for (ix = 0; ix != GOMP_DIM_MAX;
12683 ix++, pos = TREE_CHAIN (pos))
12684 if (!integer_zerop (TREE_PURPOSE (pos)))
12685 break;
12687 return ix;
12690 /* Extract an oacc execution dimension from FN. FN must be an
12691 offloaded function or routine that has already had its execution
12692 dimensions lowered to the target-specific values. */
12695 get_oacc_fn_dim_size (tree fn, int axis)
12697 tree attrs = get_oacc_fn_attrib (fn);
12699 gcc_assert (axis < GOMP_DIM_MAX);
12701 tree dims = TREE_VALUE (attrs);
12702 while (axis--)
12703 dims = TREE_CHAIN (dims);
12705 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12707 return size;
12710 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12711 IFN_GOACC_DIM_SIZE call. */
12714 get_oacc_ifn_dim_arg (const gimple *stmt)
12716 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12717 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12718 tree arg = gimple_call_arg (stmt, 0);
12719 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12721 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12722 return (int) axis;
12725 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12726 at REGION_EXIT. */
12728 static void
12729 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12730 basic_block region_exit)
12732 struct loop *outer = region_entry->loop_father;
12733 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12735 /* Don't parallelize the kernels region if it contains more than one outer
12736 loop. */
12737 unsigned int nr_outer_loops = 0;
12738 struct loop *single_outer = NULL;
12739 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12741 gcc_assert (loop_outer (loop) == outer);
12743 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12744 continue;
12746 if (region_exit != NULL
12747 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12748 continue;
12750 nr_outer_loops++;
12751 single_outer = loop;
12753 if (nr_outer_loops != 1)
12754 return;
12756 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12757 if (loop->next)
12758 return;
12760 /* Mark the loops in the region. */
12761 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12762 loop->in_oacc_kernels_region = true;
12765 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12767 struct GTY(()) grid_launch_attributes_trees
12769 tree kernel_dim_array_type;
12770 tree kernel_lattrs_dimnum_decl;
12771 tree kernel_lattrs_grid_decl;
12772 tree kernel_lattrs_group_decl;
12773 tree kernel_launch_attributes_type;
12776 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12778 /* Create types used to pass kernel launch attributes to target. */
12780 static void
12781 grid_create_kernel_launch_attr_types (void)
12783 if (grid_attr_trees)
12784 return;
12785 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12787 tree dim_arr_index_type
12788 = build_index_type (build_int_cst (integer_type_node, 2));
12789 grid_attr_trees->kernel_dim_array_type
12790 = build_array_type (uint32_type_node, dim_arr_index_type);
12792 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12793 grid_attr_trees->kernel_lattrs_dimnum_decl
12794 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12795 uint32_type_node);
12796 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12798 grid_attr_trees->kernel_lattrs_grid_decl
12799 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12800 grid_attr_trees->kernel_dim_array_type);
12801 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12802 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12803 grid_attr_trees->kernel_lattrs_group_decl
12804 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12805 grid_attr_trees->kernel_dim_array_type);
12806 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12807 = grid_attr_trees->kernel_lattrs_grid_decl;
12808 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12809 "__gomp_kernel_launch_attributes",
12810 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12813 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12814 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12815 of type uint32_type_node. */
12817 static void
12818 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12819 tree fld_decl, int index, tree value)
12821 tree ref = build4 (ARRAY_REF, uint32_type_node,
12822 build3 (COMPONENT_REF,
12823 grid_attr_trees->kernel_dim_array_type,
12824 range_var, fld_decl, NULL_TREE),
12825 build_int_cst (integer_type_node, index),
12826 NULL_TREE, NULL_TREE);
12827 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12830 /* Return a tree representation of a pointer to a structure with grid and
12831 work-group size information. Statements filling that information will be
12832 inserted before GSI, TGT_STMT is the target statement which has the
12833 necessary information in it. */
12835 static tree
12836 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12837 gomp_target *tgt_stmt)
12839 grid_create_kernel_launch_attr_types ();
12840 tree u32_one = build_one_cst (uint32_type_node);
12841 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12842 "__kernel_launch_attrs");
12844 unsigned max_dim = 0;
12845 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12846 clause;
12847 clause = OMP_CLAUSE_CHAIN (clause))
12849 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12850 continue;
12852 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12853 max_dim = MAX (dim, max_dim);
12855 grid_insert_store_range_dim (gsi, lattrs,
12856 grid_attr_trees->kernel_lattrs_grid_decl,
12857 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12858 grid_insert_store_range_dim (gsi, lattrs,
12859 grid_attr_trees->kernel_lattrs_group_decl,
12860 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12863 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12864 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12865 /* At this moment we cannot gridify a loop with a collapse clause. */
12866 /* TODO: Adjust when we support bigger collapse. */
12867 gcc_assert (max_dim == 0);
12868 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12869 TREE_ADDRESSABLE (lattrs) = 1;
12870 return build_fold_addr_expr (lattrs);
12873 /* Build target argument identifier from the DEVICE identifier, value
12874 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12876 static tree
12877 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12879 tree t = build_int_cst (integer_type_node, device);
12880 if (subseqent_param)
12881 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12882 build_int_cst (integer_type_node,
12883 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12884 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12885 build_int_cst (integer_type_node, id));
12886 return t;
12889 /* Like above but return it in type that can be directly stored as an element
12890 of the argument array. */
12892 static tree
12893 get_target_argument_identifier (int device, bool subseqent_param, int id)
12895 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12896 return fold_convert (ptr_type_node, t);
12899 /* Return a target argument consisting of DEVICE identifier, value identifier
12900 ID, and the actual VALUE. */
12902 static tree
12903 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12904 tree value)
12906 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12907 fold_convert (integer_type_node, value),
12908 build_int_cst (unsigned_type_node,
12909 GOMP_TARGET_ARG_VALUE_SHIFT));
12910 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12911 get_target_argument_identifier_1 (device, false, id));
12912 t = fold_convert (ptr_type_node, t);
12913 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12916 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12917 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12918 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12919 arguments. */
12921 static void
12922 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12923 int id, tree value, vec <tree> *args)
12925 if (tree_fits_shwi_p (value)
12926 && tree_to_shwi (value) > -(1 << 15)
12927 && tree_to_shwi (value) < (1 << 15))
12928 args->quick_push (get_target_argument_value (gsi, device, id, value));
12929 else
12931 args->quick_push (get_target_argument_identifier (device, true, id));
12932 value = fold_convert (ptr_type_node, value);
12933 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12934 GSI_SAME_STMT);
12935 args->quick_push (value);
12939 /* Create an array of arguments that is then passed to GOMP_target. */
12941 static tree
12942 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12944 auto_vec <tree, 6> args;
12945 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12946 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12947 if (c)
12948 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12949 else
12950 t = integer_minus_one_node;
12951 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12952 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12954 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12955 if (c)
12956 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12957 else
12958 t = integer_minus_one_node;
12959 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12960 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12961 &args);
12963 /* Add HSA-specific grid sizes, if available. */
12964 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12965 OMP_CLAUSE__GRIDDIM_))
12967 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12968 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12969 args.quick_push (t);
12970 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12973 /* Produce more, perhaps device specific, arguments here. */
12975 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12976 args.length () + 1),
12977 ".omp_target_args");
12978 for (unsigned i = 0; i < args.length (); i++)
12980 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12981 build_int_cst (integer_type_node, i),
12982 NULL_TREE, NULL_TREE);
12983 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12984 GSI_SAME_STMT);
12986 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12987 build_int_cst (integer_type_node, args.length ()),
12988 NULL_TREE, NULL_TREE);
12989 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
12990 GSI_SAME_STMT);
12991 TREE_ADDRESSABLE (argarray) = 1;
12992 return build_fold_addr_expr (argarray);
12995 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12997 static void
12998 expand_omp_target (struct omp_region *region)
13000 basic_block entry_bb, exit_bb, new_bb;
13001 struct function *child_cfun;
13002 tree child_fn, block, t;
13003 gimple_stmt_iterator gsi;
13004 gomp_target *entry_stmt;
13005 gimple *stmt;
13006 edge e;
13007 bool offloaded, data_region;
13009 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13010 new_bb = region->entry;
13012 offloaded = is_gimple_omp_offloaded (entry_stmt);
13013 switch (gimple_omp_target_kind (entry_stmt))
13015 case GF_OMP_TARGET_KIND_REGION:
13016 case GF_OMP_TARGET_KIND_UPDATE:
13017 case GF_OMP_TARGET_KIND_ENTER_DATA:
13018 case GF_OMP_TARGET_KIND_EXIT_DATA:
13019 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13020 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13021 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13022 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13023 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13024 data_region = false;
13025 break;
13026 case GF_OMP_TARGET_KIND_DATA:
13027 case GF_OMP_TARGET_KIND_OACC_DATA:
13028 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13029 data_region = true;
13030 break;
13031 default:
13032 gcc_unreachable ();
13035 child_fn = NULL_TREE;
13036 child_cfun = NULL;
13037 if (offloaded)
13039 child_fn = gimple_omp_target_child_fn (entry_stmt);
13040 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13043 /* Supported by expand_omp_taskreg, but not here. */
13044 if (child_cfun != NULL)
13045 gcc_checking_assert (!child_cfun->cfg);
13046 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13048 entry_bb = region->entry;
13049 exit_bb = region->exit;
13051 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13052 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13054 if (offloaded)
13056 unsigned srcidx, dstidx, num;
13058 /* If the offloading region needs data sent from the parent
13059 function, then the very first statement (except possible
13060 tree profile counter updates) of the offloading body
13061 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13062 &.OMP_DATA_O is passed as an argument to the child function,
13063 we need to replace it with the argument as seen by the child
13064 function.
13066 In most cases, this will end up being the identity assignment
13067 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13068 a function call that has been inlined, the original PARM_DECL
13069 .OMP_DATA_I may have been converted into a different local
13070 variable. In which case, we need to keep the assignment. */
13071 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13072 if (data_arg)
13074 basic_block entry_succ_bb = single_succ (entry_bb);
13075 gimple_stmt_iterator gsi;
13076 tree arg;
13077 gimple *tgtcopy_stmt = NULL;
13078 tree sender = TREE_VEC_ELT (data_arg, 0);
13080 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13082 gcc_assert (!gsi_end_p (gsi));
13083 stmt = gsi_stmt (gsi);
13084 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13085 continue;
13087 if (gimple_num_ops (stmt) == 2)
13089 tree arg = gimple_assign_rhs1 (stmt);
13091 /* We're ignoring the subcode because we're
13092 effectively doing a STRIP_NOPS. */
13094 if (TREE_CODE (arg) == ADDR_EXPR
13095 && TREE_OPERAND (arg, 0) == sender)
13097 tgtcopy_stmt = stmt;
13098 break;
13103 gcc_assert (tgtcopy_stmt != NULL);
13104 arg = DECL_ARGUMENTS (child_fn);
13106 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13107 gsi_remove (&gsi, true);
13110 /* Declare local variables needed in CHILD_CFUN. */
13111 block = DECL_INITIAL (child_fn);
13112 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13113 /* The gimplifier could record temporaries in the offloading block
13114 rather than in containing function's local_decls chain,
13115 which would mean cgraph missed finalizing them. Do it now. */
13116 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13117 if (TREE_CODE (t) == VAR_DECL
13118 && TREE_STATIC (t)
13119 && !DECL_EXTERNAL (t))
13120 varpool_node::finalize_decl (t);
13121 DECL_SAVED_TREE (child_fn) = NULL;
13122 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13123 gimple_set_body (child_fn, NULL);
13124 TREE_USED (block) = 1;
13126 /* Reset DECL_CONTEXT on function arguments. */
13127 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13128 DECL_CONTEXT (t) = child_fn;
13130 /* Split ENTRY_BB at GIMPLE_*,
13131 so that it can be moved to the child function. */
13132 gsi = gsi_last_bb (entry_bb);
13133 stmt = gsi_stmt (gsi);
13134 gcc_assert (stmt
13135 && gimple_code (stmt) == gimple_code (entry_stmt));
13136 e = split_block (entry_bb, stmt);
13137 gsi_remove (&gsi, true);
13138 entry_bb = e->dest;
13139 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13141 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13142 if (exit_bb)
13144 gsi = gsi_last_bb (exit_bb);
13145 gcc_assert (!gsi_end_p (gsi)
13146 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13147 stmt = gimple_build_return (NULL);
13148 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13149 gsi_remove (&gsi, true);
13152 /* Move the offloading region into CHILD_CFUN. */
13154 block = gimple_block (entry_stmt);
13156 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13157 if (exit_bb)
13158 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13159 /* When the OMP expansion process cannot guarantee an up-to-date
13160 loop tree arrange for the child function to fixup loops. */
13161 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13162 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13164 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13165 num = vec_safe_length (child_cfun->local_decls);
13166 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13168 t = (*child_cfun->local_decls)[srcidx];
13169 if (DECL_CONTEXT (t) == cfun->decl)
13170 continue;
13171 if (srcidx != dstidx)
13172 (*child_cfun->local_decls)[dstidx] = t;
13173 dstidx++;
13175 if (dstidx != num)
13176 vec_safe_truncate (child_cfun->local_decls, dstidx);
13178 /* Inform the callgraph about the new function. */
13179 child_cfun->curr_properties = cfun->curr_properties;
13180 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13181 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13182 cgraph_node *node = cgraph_node::get_create (child_fn);
13183 node->parallelized_function = 1;
13184 cgraph_node::add_new_function (child_fn, true);
13186 /* Add the new function to the offload table. */
13187 if (ENABLE_OFFLOADING)
13188 vec_safe_push (offload_funcs, child_fn);
13190 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13191 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13193 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13194 fixed in a following pass. */
13195 push_cfun (child_cfun);
13196 if (need_asm)
13197 assign_assembler_name_if_neeeded (child_fn);
13198 cgraph_edge::rebuild_edges ();
13200 /* Some EH regions might become dead, see PR34608. If
13201 pass_cleanup_cfg isn't the first pass to happen with the
13202 new child, these dead EH edges might cause problems.
13203 Clean them up now. */
13204 if (flag_exceptions)
13206 basic_block bb;
13207 bool changed = false;
13209 FOR_EACH_BB_FN (bb, cfun)
13210 changed |= gimple_purge_dead_eh_edges (bb);
13211 if (changed)
13212 cleanup_tree_cfg ();
13214 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13215 verify_loop_structure ();
13216 pop_cfun ();
13218 if (dump_file && !gimple_in_ssa_p (cfun))
13220 omp_any_child_fn_dumped = true;
13221 dump_function_header (dump_file, child_fn, dump_flags);
13222 dump_function_to_file (child_fn, dump_file, dump_flags);
13226 /* Emit a library call to launch the offloading region, or do data
13227 transfers. */
13228 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13229 enum built_in_function start_ix;
13230 location_t clause_loc;
13231 unsigned int flags_i = 0;
13232 bool oacc_kernels_p = false;
13234 switch (gimple_omp_target_kind (entry_stmt))
13236 case GF_OMP_TARGET_KIND_REGION:
13237 start_ix = BUILT_IN_GOMP_TARGET;
13238 break;
13239 case GF_OMP_TARGET_KIND_DATA:
13240 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13241 break;
13242 case GF_OMP_TARGET_KIND_UPDATE:
13243 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13244 break;
13245 case GF_OMP_TARGET_KIND_ENTER_DATA:
13246 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13247 break;
13248 case GF_OMP_TARGET_KIND_EXIT_DATA:
13249 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13250 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13251 break;
13252 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13253 oacc_kernels_p = true;
13254 /* FALLTHROUGH */
13255 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13256 start_ix = BUILT_IN_GOACC_PARALLEL;
13257 break;
13258 case GF_OMP_TARGET_KIND_OACC_DATA:
13259 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13260 start_ix = BUILT_IN_GOACC_DATA_START;
13261 break;
13262 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13263 start_ix = BUILT_IN_GOACC_UPDATE;
13264 break;
13265 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13266 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13267 break;
13268 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13269 start_ix = BUILT_IN_GOACC_DECLARE;
13270 break;
13271 default:
13272 gcc_unreachable ();
13275 clauses = gimple_omp_target_clauses (entry_stmt);
13277 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13278 library choose) and there is no conditional. */
13279 cond = NULL_TREE;
13280 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13282 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13283 if (c)
13284 cond = OMP_CLAUSE_IF_EXPR (c);
13286 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13287 if (c)
13289 /* Even if we pass it to all library function calls, it is currently only
13290 defined/used for the OpenMP target ones. */
13291 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13292 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13293 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13294 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13296 device = OMP_CLAUSE_DEVICE_ID (c);
13297 clause_loc = OMP_CLAUSE_LOCATION (c);
13299 else
13300 clause_loc = gimple_location (entry_stmt);
13302 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13303 if (c)
13304 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13306 /* Ensure 'device' is of the correct type. */
13307 device = fold_convert_loc (clause_loc, integer_type_node, device);
13309 /* If we found the clause 'if (cond)', build
13310 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13311 if (cond)
13313 cond = gimple_boolify (cond);
13315 basic_block cond_bb, then_bb, else_bb;
13316 edge e;
13317 tree tmp_var;
13319 tmp_var = create_tmp_var (TREE_TYPE (device));
13320 if (offloaded)
13321 e = split_block_after_labels (new_bb);
13322 else
13324 gsi = gsi_last_bb (new_bb);
13325 gsi_prev (&gsi);
13326 e = split_block (new_bb, gsi_stmt (gsi));
13328 cond_bb = e->src;
13329 new_bb = e->dest;
13330 remove_edge (e);
13332 then_bb = create_empty_bb (cond_bb);
13333 else_bb = create_empty_bb (then_bb);
13334 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13335 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13337 stmt = gimple_build_cond_empty (cond);
13338 gsi = gsi_last_bb (cond_bb);
13339 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13341 gsi = gsi_start_bb (then_bb);
13342 stmt = gimple_build_assign (tmp_var, device);
13343 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13345 gsi = gsi_start_bb (else_bb);
13346 stmt = gimple_build_assign (tmp_var,
13347 build_int_cst (integer_type_node,
13348 GOMP_DEVICE_HOST_FALLBACK));
13349 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13351 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13352 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13353 add_bb_to_loop (then_bb, cond_bb->loop_father);
13354 add_bb_to_loop (else_bb, cond_bb->loop_father);
13355 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13356 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13358 device = tmp_var;
13361 gsi = gsi_last_bb (new_bb);
13362 t = gimple_omp_target_data_arg (entry_stmt);
13363 if (t == NULL)
13365 t1 = size_zero_node;
13366 t2 = build_zero_cst (ptr_type_node);
13367 t3 = t2;
13368 t4 = t2;
13370 else
13372 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13373 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13374 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13375 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13376 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13379 gimple *g;
13380 bool tagging = false;
13381 /* The maximum number used by any start_ix, without varargs. */
13382 auto_vec<tree, 11> args;
13383 args.quick_push (device);
13384 if (offloaded)
13385 args.quick_push (build_fold_addr_expr (child_fn));
13386 args.quick_push (t1);
13387 args.quick_push (t2);
13388 args.quick_push (t3);
13389 args.quick_push (t4);
13390 switch (start_ix)
13392 case BUILT_IN_GOACC_DATA_START:
13393 case BUILT_IN_GOACC_DECLARE:
13394 case BUILT_IN_GOMP_TARGET_DATA:
13395 break;
13396 case BUILT_IN_GOMP_TARGET:
13397 case BUILT_IN_GOMP_TARGET_UPDATE:
13398 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13399 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13400 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13401 if (c)
13402 depend = OMP_CLAUSE_DECL (c);
13403 else
13404 depend = build_int_cst (ptr_type_node, 0);
13405 args.quick_push (depend);
13406 if (start_ix == BUILT_IN_GOMP_TARGET)
13407 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13408 break;
13409 case BUILT_IN_GOACC_PARALLEL:
13411 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13412 tagging = true;
13414 /* FALLTHRU */
13415 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13416 case BUILT_IN_GOACC_UPDATE:
13418 tree t_async = NULL_TREE;
13420 /* If present, use the value specified by the respective
13421 clause, making sure that is of the correct type. */
13422 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13423 if (c)
13424 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13425 integer_type_node,
13426 OMP_CLAUSE_ASYNC_EXPR (c));
13427 else if (!tagging)
13428 /* Default values for t_async. */
13429 t_async = fold_convert_loc (gimple_location (entry_stmt),
13430 integer_type_node,
13431 build_int_cst (integer_type_node,
13432 GOMP_ASYNC_SYNC));
13433 if (tagging && t_async)
13435 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13437 if (TREE_CODE (t_async) == INTEGER_CST)
13439 /* See if we can pack the async arg in to the tag's
13440 operand. */
13441 i_async = TREE_INT_CST_LOW (t_async);
13442 if (i_async < GOMP_LAUNCH_OP_MAX)
13443 t_async = NULL_TREE;
13444 else
13445 i_async = GOMP_LAUNCH_OP_MAX;
13447 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13448 i_async));
13450 if (t_async)
13451 args.safe_push (t_async);
13453 /* Save the argument index, and ... */
13454 unsigned t_wait_idx = args.length ();
13455 unsigned num_waits = 0;
13456 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13457 if (!tagging || c)
13458 /* ... push a placeholder. */
13459 args.safe_push (integer_zero_node);
13461 for (; c; c = OMP_CLAUSE_CHAIN (c))
13462 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13464 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13465 integer_type_node,
13466 OMP_CLAUSE_WAIT_EXPR (c)));
13467 num_waits++;
13470 if (!tagging || num_waits)
13472 tree len;
13474 /* Now that we know the number, update the placeholder. */
13475 if (tagging)
13476 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13477 else
13478 len = build_int_cst (integer_type_node, num_waits);
13479 len = fold_convert_loc (gimple_location (entry_stmt),
13480 unsigned_type_node, len);
13481 args[t_wait_idx] = len;
13484 break;
13485 default:
13486 gcc_unreachable ();
13488 if (tagging)
13489 /* Push terminal marker - zero. */
13490 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13492 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13493 gimple_set_location (g, gimple_location (entry_stmt));
13494 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13495 if (!offloaded)
13497 g = gsi_stmt (gsi);
13498 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13499 gsi_remove (&gsi, true);
13501 if (data_region && region->exit)
13503 gsi = gsi_last_bb (region->exit);
13504 g = gsi_stmt (gsi);
13505 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13506 gsi_remove (&gsi, true);
13510 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13511 variable derived from the thread number. */
13513 static void
13514 grid_expand_omp_for_loop (struct omp_region *kfor)
13516 tree t, threadid;
13517 tree type, itype;
13518 gimple_stmt_iterator gsi;
13519 tree n1, step;
13520 struct omp_for_data fd;
13522 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13523 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13524 == GF_OMP_FOR_KIND_GRID_LOOP);
13525 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13527 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13528 gcc_assert (kfor->cont);
13529 extract_omp_for_data (for_stmt, &fd, NULL);
13531 itype = type = TREE_TYPE (fd.loop.v);
13532 if (POINTER_TYPE_P (type))
13533 itype = signed_type_for (type);
13535 gsi = gsi_start_bb (body_bb);
13537 n1 = fd.loop.n1;
13538 step = fd.loop.step;
13539 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13540 true, NULL_TREE, true, GSI_SAME_STMT);
13541 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13542 true, NULL_TREE, true, GSI_SAME_STMT);
13543 threadid = build_call_expr (builtin_decl_explicit
13544 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13545 threadid = fold_convert (itype, threadid);
13546 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13547 true, GSI_SAME_STMT);
13549 tree startvar = fd.loop.v;
13550 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13551 if (POINTER_TYPE_P (type))
13552 t = fold_build_pointer_plus (n1, t);
13553 else
13554 t = fold_build2 (PLUS_EXPR, type, t, n1);
13555 t = fold_convert (type, t);
13556 t = force_gimple_operand_gsi (&gsi, t,
13557 DECL_P (startvar)
13558 && TREE_ADDRESSABLE (startvar),
13559 NULL_TREE, true, GSI_SAME_STMT);
13560 gassign *assign_stmt = gimple_build_assign (startvar, t);
13561 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13563 /* Remove the omp for statement */
13564 gsi = gsi_last_bb (kfor->entry);
13565 gsi_remove (&gsi, true);
13567 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13568 gsi = gsi_last_bb (kfor->cont);
13569 gcc_assert (!gsi_end_p (gsi)
13570 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13571 gsi_remove (&gsi, true);
13573 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13574 gsi = gsi_last_bb (kfor->exit);
13575 gcc_assert (!gsi_end_p (gsi)
13576 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13577 gsi_remove (&gsi, true);
13579 /* Fixup the much simpler CFG. */
13580 remove_edge (find_edge (kfor->cont, body_bb));
13582 if (kfor->cont != body_bb)
13583 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13584 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13587 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13588 argument_decls. */
13590 struct grid_arg_decl_map
13592 tree old_arg;
13593 tree new_arg;
13596 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13597 pertaining to kernel function. */
13599 static tree
13600 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13602 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13603 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13604 tree t = *tp;
13606 if (t == adm->old_arg)
13607 *tp = adm->new_arg;
13608 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13609 return NULL_TREE;
13612 static void expand_omp (struct omp_region *region);
13614 /* If TARGET region contains a kernel body for loop, remove its region from the
13615 TARGET and expand it in GPGPU kernel fashion. */
13617 static void
13618 grid_expand_target_grid_body (struct omp_region *target)
13620 if (!hsa_gen_requested_p ())
13621 return;
13623 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13624 struct omp_region **pp;
13626 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13627 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13628 break;
13630 struct omp_region *gpukernel = *pp;
13632 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13633 if (!gpukernel)
13635 /* HSA cannot handle OACC stuff. */
13636 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13637 return;
13638 gcc_checking_assert (orig_child_fndecl);
13639 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13640 OMP_CLAUSE__GRIDDIM_));
13641 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13643 hsa_register_kernel (n);
13644 return;
13647 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13648 OMP_CLAUSE__GRIDDIM_));
13649 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13650 *pp = gpukernel->next;
13651 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13652 if ((*pp)->type == GIMPLE_OMP_FOR)
13653 break;
13655 struct omp_region *kfor = *pp;
13656 gcc_assert (kfor);
13657 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13658 == GF_OMP_FOR_KIND_GRID_LOOP);
13659 *pp = kfor->next;
13660 if (kfor->inner)
13661 expand_omp (kfor->inner);
13662 if (gpukernel->inner)
13663 expand_omp (gpukernel->inner);
13665 tree kern_fndecl = copy_node (orig_child_fndecl);
13666 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13667 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13668 tree tgtblock = gimple_block (tgt_stmt);
13669 tree fniniblock = make_node (BLOCK);
13670 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13671 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13672 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13673 DECL_INITIAL (kern_fndecl) = fniniblock;
13674 push_struct_function (kern_fndecl);
13675 cfun->function_end_locus = gimple_location (tgt_stmt);
13676 init_tree_ssa (cfun);
13677 pop_cfun ();
13679 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13680 gcc_assert (!DECL_CHAIN (old_parm_decl));
13681 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13682 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13683 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13684 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13685 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13686 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
13687 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13688 kern_cfun->curr_properties = cfun->curr_properties;
13690 remove_edge (BRANCH_EDGE (kfor->entry));
13691 grid_expand_omp_for_loop (kfor);
13693 /* Remove the omp for statement */
13694 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13695 gsi_remove (&gsi, true);
13696 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13697 return. */
13698 gsi = gsi_last_bb (gpukernel->exit);
13699 gcc_assert (!gsi_end_p (gsi)
13700 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13701 gimple *ret_stmt = gimple_build_return (NULL);
13702 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13703 gsi_remove (&gsi, true);
13705 /* Statements in the first BB in the target construct have been produced by
13706 target lowering and must be copied inside the GPUKERNEL, with the two
13707 exceptions of the first OMP statement and the OMP_DATA assignment
13708 statement. */
13709 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13710 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13711 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13712 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13713 !gsi_end_p (tsi); gsi_next (&tsi))
13715 gimple *stmt = gsi_stmt (tsi);
13716 if (is_gimple_omp (stmt))
13717 break;
13718 if (sender
13719 && is_gimple_assign (stmt)
13720 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13721 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13722 continue;
13723 gimple *copy = gimple_copy (stmt);
13724 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13725 gimple_set_block (copy, fniniblock);
13728 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13729 gpukernel->exit, inside_block);
13731 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13732 kcn->mark_force_output ();
13733 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13735 hsa_register_kernel (kcn, orig_child);
13737 cgraph_node::add_new_function (kern_fndecl, true);
13738 push_cfun (kern_cfun);
13739 cgraph_edge::rebuild_edges ();
13741 /* Re-map any mention of the PARM_DECL of the original function to the
13742 PARM_DECL of the new one.
13744 TODO: It would be great if lowering produced references into the GPU
13745 kernel decl straight away and we did not have to do this. */
13746 struct grid_arg_decl_map adm;
13747 adm.old_arg = old_parm_decl;
13748 adm.new_arg = new_parm_decl;
13749 basic_block bb;
13750 FOR_EACH_BB_FN (bb, kern_cfun)
13752 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13754 gimple *stmt = gsi_stmt (gsi);
13755 struct walk_stmt_info wi;
13756 memset (&wi, 0, sizeof (wi));
13757 wi.info = &adm;
13758 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13761 pop_cfun ();
13763 return;
13766 /* Expand the parallel region tree rooted at REGION. Expansion
13767 proceeds in depth-first order. Innermost regions are expanded
13768 first. This way, parallel regions that require a new function to
13769 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13770 internal dependencies in their body. */
13772 static void
13773 expand_omp (struct omp_region *region)
13775 omp_any_child_fn_dumped = false;
13776 while (region)
13778 location_t saved_location;
13779 gimple *inner_stmt = NULL;
13781 /* First, determine whether this is a combined parallel+workshare
13782 region. */
13783 if (region->type == GIMPLE_OMP_PARALLEL)
13784 determine_parallel_type (region);
13785 else if (region->type == GIMPLE_OMP_TARGET)
13786 grid_expand_target_grid_body (region);
13788 if (region->type == GIMPLE_OMP_FOR
13789 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13790 inner_stmt = last_stmt (region->inner->entry);
13792 if (region->inner)
13793 expand_omp (region->inner);
13795 saved_location = input_location;
13796 if (gimple_has_location (last_stmt (region->entry)))
13797 input_location = gimple_location (last_stmt (region->entry));
13799 switch (region->type)
13801 case GIMPLE_OMP_PARALLEL:
13802 case GIMPLE_OMP_TASK:
13803 expand_omp_taskreg (region);
13804 break;
13806 case GIMPLE_OMP_FOR:
13807 expand_omp_for (region, inner_stmt);
13808 break;
13810 case GIMPLE_OMP_SECTIONS:
13811 expand_omp_sections (region);
13812 break;
13814 case GIMPLE_OMP_SECTION:
13815 /* Individual omp sections are handled together with their
13816 parent GIMPLE_OMP_SECTIONS region. */
13817 break;
13819 case GIMPLE_OMP_SINGLE:
13820 expand_omp_single (region);
13821 break;
13823 case GIMPLE_OMP_ORDERED:
13825 gomp_ordered *ord_stmt
13826 = as_a <gomp_ordered *> (last_stmt (region->entry));
13827 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13828 OMP_CLAUSE_DEPEND))
13830 /* We'll expand these when expanding corresponding
13831 worksharing region with ordered(n) clause. */
13832 gcc_assert (region->outer
13833 && region->outer->type == GIMPLE_OMP_FOR);
13834 region->ord_stmt = ord_stmt;
13835 break;
13838 /* FALLTHRU */
13839 case GIMPLE_OMP_MASTER:
13840 case GIMPLE_OMP_TASKGROUP:
13841 case GIMPLE_OMP_CRITICAL:
13842 case GIMPLE_OMP_TEAMS:
13843 expand_omp_synch (region);
13844 break;
13846 case GIMPLE_OMP_ATOMIC_LOAD:
13847 expand_omp_atomic (region);
13848 break;
13850 case GIMPLE_OMP_TARGET:
13851 expand_omp_target (region);
13852 break;
13854 default:
13855 gcc_unreachable ();
13858 input_location = saved_location;
13859 region = region->next;
13861 if (omp_any_child_fn_dumped)
13863 if (dump_file)
13864 dump_function_header (dump_file, current_function_decl, dump_flags);
13865 omp_any_child_fn_dumped = false;
13870 /* Helper for build_omp_regions. Scan the dominator tree starting at
13871 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13872 true, the function ends once a single tree is built (otherwise, whole
13873 forest of OMP constructs may be built). */
13875 static void
13876 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13877 bool single_tree)
13879 gimple_stmt_iterator gsi;
13880 gimple *stmt;
13881 basic_block son;
13883 gsi = gsi_last_bb (bb);
13884 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13886 struct omp_region *region;
13887 enum gimple_code code;
13889 stmt = gsi_stmt (gsi);
13890 code = gimple_code (stmt);
13891 if (code == GIMPLE_OMP_RETURN)
13893 /* STMT is the return point out of region PARENT. Mark it
13894 as the exit point and make PARENT the immediately
13895 enclosing region. */
13896 gcc_assert (parent);
13897 region = parent;
13898 region->exit = bb;
13899 parent = parent->outer;
13901 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13903 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13904 GIMPLE_OMP_RETURN, but matches with
13905 GIMPLE_OMP_ATOMIC_LOAD. */
13906 gcc_assert (parent);
13907 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13908 region = parent;
13909 region->exit = bb;
13910 parent = parent->outer;
13912 else if (code == GIMPLE_OMP_CONTINUE)
13914 gcc_assert (parent);
13915 parent->cont = bb;
13917 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13919 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13920 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13922 else
13924 region = new_omp_region (bb, code, parent);
13925 /* Otherwise... */
13926 if (code == GIMPLE_OMP_TARGET)
13928 switch (gimple_omp_target_kind (stmt))
13930 case GF_OMP_TARGET_KIND_REGION:
13931 case GF_OMP_TARGET_KIND_DATA:
13932 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13933 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13934 case GF_OMP_TARGET_KIND_OACC_DATA:
13935 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13936 break;
13937 case GF_OMP_TARGET_KIND_UPDATE:
13938 case GF_OMP_TARGET_KIND_ENTER_DATA:
13939 case GF_OMP_TARGET_KIND_EXIT_DATA:
13940 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13941 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13942 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13943 /* ..., other than for those stand-alone directives... */
13944 region = NULL;
13945 break;
13946 default:
13947 gcc_unreachable ();
13950 else if (code == GIMPLE_OMP_ORDERED
13951 && find_omp_clause (gimple_omp_ordered_clauses
13952 (as_a <gomp_ordered *> (stmt)),
13953 OMP_CLAUSE_DEPEND))
13954 /* #pragma omp ordered depend is also just a stand-alone
13955 directive. */
13956 region = NULL;
13957 /* ..., this directive becomes the parent for a new region. */
13958 if (region)
13959 parent = region;
13963 if (single_tree && !parent)
13964 return;
13966 for (son = first_dom_son (CDI_DOMINATORS, bb);
13967 son;
13968 son = next_dom_son (CDI_DOMINATORS, son))
13969 build_omp_regions_1 (son, parent, single_tree);
13972 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13973 root_omp_region. */
13975 static void
13976 build_omp_regions_root (basic_block root)
13978 gcc_assert (root_omp_region == NULL);
13979 build_omp_regions_1 (root, NULL, true);
13980 gcc_assert (root_omp_region != NULL);
13983 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13985 void
13986 omp_expand_local (basic_block head)
13988 build_omp_regions_root (head);
13989 if (dump_file && (dump_flags & TDF_DETAILS))
13991 fprintf (dump_file, "\nOMP region tree\n\n");
13992 dump_omp_region (dump_file, root_omp_region, 0);
13993 fprintf (dump_file, "\n");
13996 remove_exit_barriers (root_omp_region);
13997 expand_omp (root_omp_region);
13999 free_omp_regions ();
14002 /* Scan the CFG and build a tree of OMP regions. Return the root of
14003 the OMP region tree. */
14005 static void
14006 build_omp_regions (void)
14008 gcc_assert (root_omp_region == NULL);
14009 calculate_dominance_info (CDI_DOMINATORS);
14010 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14013 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14015 static unsigned int
14016 execute_expand_omp (void)
14018 build_omp_regions ();
14020 if (!root_omp_region)
14021 return 0;
14023 if (dump_file)
14025 fprintf (dump_file, "\nOMP region tree\n\n");
14026 dump_omp_region (dump_file, root_omp_region, 0);
14027 fprintf (dump_file, "\n");
14030 remove_exit_barriers (root_omp_region);
14032 expand_omp (root_omp_region);
14034 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14035 verify_loop_structure ();
14036 cleanup_tree_cfg ();
14038 free_omp_regions ();
14040 return 0;
14043 /* OMP expansion -- the default pass, run before creation of SSA form. */
14045 namespace {
14047 const pass_data pass_data_expand_omp =
14049 GIMPLE_PASS, /* type */
14050 "ompexp", /* name */
14051 OPTGROUP_NONE, /* optinfo_flags */
14052 TV_NONE, /* tv_id */
14053 PROP_gimple_any, /* properties_required */
14054 PROP_gimple_eomp, /* properties_provided */
14055 0, /* properties_destroyed */
14056 0, /* todo_flags_start */
14057 0, /* todo_flags_finish */
14060 class pass_expand_omp : public gimple_opt_pass
14062 public:
14063 pass_expand_omp (gcc::context *ctxt)
14064 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14067 /* opt_pass methods: */
14068 virtual unsigned int execute (function *)
14070 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14071 || flag_openmp_simd != 0)
14072 && !seen_error ());
14074 /* This pass always runs, to provide PROP_gimple_eomp.
14075 But often, there is nothing to do. */
14076 if (!gate)
14077 return 0;
14079 return execute_expand_omp ();
14082 }; // class pass_expand_omp
14084 } // anon namespace
14086 gimple_opt_pass *
14087 make_pass_expand_omp (gcc::context *ctxt)
14089 return new pass_expand_omp (ctxt);
14092 namespace {
14094 const pass_data pass_data_expand_omp_ssa =
14096 GIMPLE_PASS, /* type */
14097 "ompexpssa", /* name */
14098 OPTGROUP_NONE, /* optinfo_flags */
14099 TV_NONE, /* tv_id */
14100 PROP_cfg | PROP_ssa, /* properties_required */
14101 PROP_gimple_eomp, /* properties_provided */
14102 0, /* properties_destroyed */
14103 0, /* todo_flags_start */
14104 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14107 class pass_expand_omp_ssa : public gimple_opt_pass
14109 public:
14110 pass_expand_omp_ssa (gcc::context *ctxt)
14111 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14114 /* opt_pass methods: */
14115 virtual bool gate (function *fun)
14117 return !(fun->curr_properties & PROP_gimple_eomp);
14119 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14120 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14122 }; // class pass_expand_omp_ssa
14124 } // anon namespace
14126 gimple_opt_pass *
14127 make_pass_expand_omp_ssa (gcc::context *ctxt)
14129 return new pass_expand_omp_ssa (ctxt);
14132 /* Routines to lower OMP directives into OMP-GIMPLE. */
14134 /* If ctx is a worksharing context inside of a cancellable parallel
14135 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14136 and conditional branch to parallel's cancel_label to handle
14137 cancellation in the implicit barrier. */
14139 static void
14140 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14142 gimple *omp_return = gimple_seq_last_stmt (*body);
14143 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14144 if (gimple_omp_return_nowait_p (omp_return))
14145 return;
14146 if (ctx->outer
14147 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14148 && ctx->outer->cancellable)
14150 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14151 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14152 tree lhs = create_tmp_var (c_bool_type);
14153 gimple_omp_return_set_lhs (omp_return, lhs);
14154 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14155 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14156 fold_convert (c_bool_type,
14157 boolean_false_node),
14158 ctx->outer->cancel_label, fallthru_label);
14159 gimple_seq_add_stmt (body, g);
14160 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14164 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14165 CTX is the enclosing OMP context for the current statement. */
14167 static void
14168 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14170 tree block, control;
14171 gimple_stmt_iterator tgsi;
14172 gomp_sections *stmt;
14173 gimple *t;
14174 gbind *new_stmt, *bind;
14175 gimple_seq ilist, dlist, olist, new_body;
14177 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14179 push_gimplify_context ();
14181 dlist = NULL;
14182 ilist = NULL;
14183 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14184 &ilist, &dlist, ctx, NULL);
14186 new_body = gimple_omp_body (stmt);
14187 gimple_omp_set_body (stmt, NULL);
14188 tgsi = gsi_start (new_body);
14189 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14191 omp_context *sctx;
14192 gimple *sec_start;
14194 sec_start = gsi_stmt (tgsi);
14195 sctx = maybe_lookup_ctx (sec_start);
14196 gcc_assert (sctx);
14198 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14199 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14200 GSI_CONTINUE_LINKING);
14201 gimple_omp_set_body (sec_start, NULL);
14203 if (gsi_one_before_end_p (tgsi))
14205 gimple_seq l = NULL;
14206 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14207 &l, ctx);
14208 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14209 gimple_omp_section_set_last (sec_start);
14212 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14213 GSI_CONTINUE_LINKING);
14216 block = make_node (BLOCK);
14217 bind = gimple_build_bind (NULL, new_body, block);
14219 olist = NULL;
14220 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14222 block = make_node (BLOCK);
14223 new_stmt = gimple_build_bind (NULL, NULL, block);
14224 gsi_replace (gsi_p, new_stmt, true);
14226 pop_gimplify_context (new_stmt);
14227 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14228 BLOCK_VARS (block) = gimple_bind_vars (bind);
14229 if (BLOCK_VARS (block))
14230 TREE_USED (block) = 1;
14232 new_body = NULL;
14233 gimple_seq_add_seq (&new_body, ilist);
14234 gimple_seq_add_stmt (&new_body, stmt);
14235 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14236 gimple_seq_add_stmt (&new_body, bind);
14238 control = create_tmp_var (unsigned_type_node, ".section");
14239 t = gimple_build_omp_continue (control, control);
14240 gimple_omp_sections_set_control (stmt, control);
14241 gimple_seq_add_stmt (&new_body, t);
14243 gimple_seq_add_seq (&new_body, olist);
14244 if (ctx->cancellable)
14245 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14246 gimple_seq_add_seq (&new_body, dlist);
14248 new_body = maybe_catch_exception (new_body);
14250 t = gimple_build_omp_return
14251 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14252 OMP_CLAUSE_NOWAIT));
14253 gimple_seq_add_stmt (&new_body, t);
14254 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14256 gimple_bind_set_body (new_stmt, new_body);
14260 /* A subroutine of lower_omp_single. Expand the simple form of
14261 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14263 if (GOMP_single_start ())
14264 BODY;
14265 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14267 FIXME. It may be better to delay expanding the logic of this until
14268 pass_expand_omp. The expanded logic may make the job more difficult
14269 to a synchronization analysis pass. */
14271 static void
14272 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14274 location_t loc = gimple_location (single_stmt);
14275 tree tlabel = create_artificial_label (loc);
14276 tree flabel = create_artificial_label (loc);
14277 gimple *call, *cond;
14278 tree lhs, decl;
14280 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14281 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14282 call = gimple_build_call (decl, 0);
14283 gimple_call_set_lhs (call, lhs);
14284 gimple_seq_add_stmt (pre_p, call);
14286 cond = gimple_build_cond (EQ_EXPR, lhs,
14287 fold_convert_loc (loc, TREE_TYPE (lhs),
14288 boolean_true_node),
14289 tlabel, flabel);
14290 gimple_seq_add_stmt (pre_p, cond);
14291 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14292 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14293 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14297 /* A subroutine of lower_omp_single. Expand the simple form of
14298 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14300 #pragma omp single copyprivate (a, b, c)
14302 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14305 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14307 BODY;
14308 copyout.a = a;
14309 copyout.b = b;
14310 copyout.c = c;
14311 GOMP_single_copy_end (&copyout);
14313 else
14315 a = copyout_p->a;
14316 b = copyout_p->b;
14317 c = copyout_p->c;
14319 GOMP_barrier ();
14322 FIXME. It may be better to delay expanding the logic of this until
14323 pass_expand_omp. The expanded logic may make the job more difficult
14324 to a synchronization analysis pass. */
14326 static void
14327 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14328 omp_context *ctx)
14330 tree ptr_type, t, l0, l1, l2, bfn_decl;
14331 gimple_seq copyin_seq;
14332 location_t loc = gimple_location (single_stmt);
14334 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14336 ptr_type = build_pointer_type (ctx->record_type);
14337 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14339 l0 = create_artificial_label (loc);
14340 l1 = create_artificial_label (loc);
14341 l2 = create_artificial_label (loc);
14343 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14344 t = build_call_expr_loc (loc, bfn_decl, 0);
14345 t = fold_convert_loc (loc, ptr_type, t);
14346 gimplify_assign (ctx->receiver_decl, t, pre_p);
14348 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14349 build_int_cst (ptr_type, 0));
14350 t = build3 (COND_EXPR, void_type_node, t,
14351 build_and_jump (&l0), build_and_jump (&l1));
14352 gimplify_and_add (t, pre_p);
14354 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14356 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14358 copyin_seq = NULL;
14359 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14360 &copyin_seq, ctx);
14362 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14363 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14364 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14365 gimplify_and_add (t, pre_p);
14367 t = build_and_jump (&l2);
14368 gimplify_and_add (t, pre_p);
14370 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14372 gimple_seq_add_seq (pre_p, copyin_seq);
14374 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14378 /* Expand code for an OpenMP single directive. */
14380 static void
14381 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14383 tree block;
14384 gimple *t;
14385 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14386 gbind *bind;
14387 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14389 push_gimplify_context ();
14391 block = make_node (BLOCK);
14392 bind = gimple_build_bind (NULL, NULL, block);
14393 gsi_replace (gsi_p, bind, true);
14394 bind_body = NULL;
14395 dlist = NULL;
14396 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14397 &bind_body, &dlist, ctx, NULL);
14398 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14400 gimple_seq_add_stmt (&bind_body, single_stmt);
14402 if (ctx->record_type)
14403 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14404 else
14405 lower_omp_single_simple (single_stmt, &bind_body);
14407 gimple_omp_set_body (single_stmt, NULL);
14409 gimple_seq_add_seq (&bind_body, dlist);
14411 bind_body = maybe_catch_exception (bind_body);
14413 t = gimple_build_omp_return
14414 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14415 OMP_CLAUSE_NOWAIT));
14416 gimple_seq_add_stmt (&bind_body_tail, t);
14417 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14418 if (ctx->record_type)
14420 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14421 tree clobber = build_constructor (ctx->record_type, NULL);
14422 TREE_THIS_VOLATILE (clobber) = 1;
14423 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14424 clobber), GSI_SAME_STMT);
14426 gimple_seq_add_seq (&bind_body, bind_body_tail);
14427 gimple_bind_set_body (bind, bind_body);
14429 pop_gimplify_context (bind);
14431 gimple_bind_append_vars (bind, ctx->block_vars);
14432 BLOCK_VARS (block) = ctx->block_vars;
14433 if (BLOCK_VARS (block))
14434 TREE_USED (block) = 1;
14438 /* Expand code for an OpenMP master directive. */
14440 static void
14441 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14443 tree block, lab = NULL, x, bfn_decl;
14444 gimple *stmt = gsi_stmt (*gsi_p);
14445 gbind *bind;
14446 location_t loc = gimple_location (stmt);
14447 gimple_seq tseq;
14449 push_gimplify_context ();
14451 block = make_node (BLOCK);
14452 bind = gimple_build_bind (NULL, NULL, block);
14453 gsi_replace (gsi_p, bind, true);
14454 gimple_bind_add_stmt (bind, stmt);
14456 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14457 x = build_call_expr_loc (loc, bfn_decl, 0);
14458 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14459 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14460 tseq = NULL;
14461 gimplify_and_add (x, &tseq);
14462 gimple_bind_add_seq (bind, tseq);
14464 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14465 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14466 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14467 gimple_omp_set_body (stmt, NULL);
14469 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14471 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14473 pop_gimplify_context (bind);
14475 gimple_bind_append_vars (bind, ctx->block_vars);
14476 BLOCK_VARS (block) = ctx->block_vars;
14480 /* Expand code for an OpenMP taskgroup directive. */
14482 static void
14483 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14485 gimple *stmt = gsi_stmt (*gsi_p);
14486 gcall *x;
14487 gbind *bind;
14488 tree block = make_node (BLOCK);
14490 bind = gimple_build_bind (NULL, NULL, block);
14491 gsi_replace (gsi_p, bind, true);
14492 gimple_bind_add_stmt (bind, stmt);
14494 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14496 gimple_bind_add_stmt (bind, x);
14498 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14499 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14500 gimple_omp_set_body (stmt, NULL);
14502 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14504 gimple_bind_append_vars (bind, ctx->block_vars);
14505 BLOCK_VARS (block) = ctx->block_vars;
14509 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14511 static void
14512 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14513 omp_context *ctx)
14515 struct omp_for_data fd;
14516 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14517 return;
14519 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14520 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14521 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14522 if (!fd.ordered)
14523 return;
14525 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14526 tree c = gimple_omp_ordered_clauses (ord_stmt);
14527 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14528 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14530 /* Merge depend clauses from multiple adjacent
14531 #pragma omp ordered depend(sink:...) constructs
14532 into one #pragma omp ordered depend(sink:...), so that
14533 we can optimize them together. */
14534 gimple_stmt_iterator gsi = *gsi_p;
14535 gsi_next (&gsi);
14536 while (!gsi_end_p (gsi))
14538 gimple *stmt = gsi_stmt (gsi);
14539 if (is_gimple_debug (stmt)
14540 || gimple_code (stmt) == GIMPLE_NOP)
14542 gsi_next (&gsi);
14543 continue;
14545 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14546 break;
14547 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14548 c = gimple_omp_ordered_clauses (ord_stmt2);
14549 if (c == NULL_TREE
14550 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14551 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14552 break;
14553 while (*list_p)
14554 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14555 *list_p = c;
14556 gsi_remove (&gsi, true);
14560 /* Canonicalize sink dependence clauses into one folded clause if
14561 possible.
14563 The basic algorithm is to create a sink vector whose first
14564 element is the GCD of all the first elements, and whose remaining
14565 elements are the minimum of the subsequent columns.
14567 We ignore dependence vectors whose first element is zero because
14568 such dependencies are known to be executed by the same thread.
14570 We take into account the direction of the loop, so a minimum
14571 becomes a maximum if the loop is iterating forwards. We also
14572 ignore sink clauses where the loop direction is unknown, or where
14573 the offsets are clearly invalid because they are not a multiple
14574 of the loop increment.
14576 For example:
14578 #pragma omp for ordered(2)
14579 for (i=0; i < N; ++i)
14580 for (j=0; j < M; ++j)
14582 #pragma omp ordered \
14583 depend(sink:i-8,j-2) \
14584 depend(sink:i,j-1) \ // Completely ignored because i+0.
14585 depend(sink:i-4,j-3) \
14586 depend(sink:i-6,j-4)
14587 #pragma omp ordered depend(source)
14590 Folded clause is:
14592 depend(sink:-gcd(8,4,6),-min(2,3,4))
14593 -or-
14594 depend(sink:-2,-2)
14597 /* FIXME: Computing GCD's where the first element is zero is
14598 non-trivial in the presence of collapsed loops. Do this later. */
14599 if (fd.collapse > 1)
14600 return;
14602 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14603 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14604 tree folded_dep = NULL_TREE;
14605 /* TRUE if the first dimension's offset is negative. */
14606 bool neg_offset_p = false;
14608 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14609 unsigned int i;
14610 while ((c = *list_p) != NULL)
14612 bool remove = false;
14614 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14615 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14616 goto next_ordered_clause;
14618 tree vec;
14619 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14620 vec && TREE_CODE (vec) == TREE_LIST;
14621 vec = TREE_CHAIN (vec), ++i)
14623 gcc_assert (i < len);
14625 /* extract_omp_for_data has canonicalized the condition. */
14626 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14627 || fd.loops[i].cond_code == GT_EXPR);
14628 bool forward = fd.loops[i].cond_code == LT_EXPR;
14629 bool maybe_lexically_later = true;
14631 /* While the committee makes up its mind, bail if we have any
14632 non-constant steps. */
14633 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14634 goto lower_omp_ordered_ret;
14636 tree itype = TREE_TYPE (TREE_VALUE (vec));
14637 if (POINTER_TYPE_P (itype))
14638 itype = sizetype;
14639 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14640 TYPE_PRECISION (itype),
14641 TYPE_SIGN (itype));
14643 /* Ignore invalid offsets that are not multiples of the step. */
14644 if (!wi::multiple_of_p
14645 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14646 UNSIGNED))
14648 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14649 "ignoring sink clause with offset that is not "
14650 "a multiple of the loop step");
14651 remove = true;
14652 goto next_ordered_clause;
14655 /* Calculate the first dimension. The first dimension of
14656 the folded dependency vector is the GCD of the first
14657 elements, while ignoring any first elements whose offset
14658 is 0. */
14659 if (i == 0)
14661 /* Ignore dependence vectors whose first dimension is 0. */
14662 if (offset == 0)
14664 remove = true;
14665 goto next_ordered_clause;
14667 else
14669 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14671 error_at (OMP_CLAUSE_LOCATION (c),
14672 "first offset must be in opposite direction "
14673 "of loop iterations");
14674 goto lower_omp_ordered_ret;
14676 if (forward)
14677 offset = -offset;
14678 neg_offset_p = forward;
14679 /* Initialize the first time around. */
14680 if (folded_dep == NULL_TREE)
14682 folded_dep = c;
14683 folded_deps[0] = offset;
14685 else
14686 folded_deps[0] = wi::gcd (folded_deps[0],
14687 offset, UNSIGNED);
14690 /* Calculate minimum for the remaining dimensions. */
14691 else
14693 folded_deps[len + i - 1] = offset;
14694 if (folded_dep == c)
14695 folded_deps[i] = offset;
14696 else if (maybe_lexically_later
14697 && !wi::eq_p (folded_deps[i], offset))
14699 if (forward ^ wi::gts_p (folded_deps[i], offset))
14701 unsigned int j;
14702 folded_dep = c;
14703 for (j = 1; j <= i; j++)
14704 folded_deps[j] = folded_deps[len + j - 1];
14706 else
14707 maybe_lexically_later = false;
14711 gcc_assert (i == len);
14713 remove = true;
14715 next_ordered_clause:
14716 if (remove)
14717 *list_p = OMP_CLAUSE_CHAIN (c);
14718 else
14719 list_p = &OMP_CLAUSE_CHAIN (c);
14722 if (folded_dep)
14724 if (neg_offset_p)
14725 folded_deps[0] = -folded_deps[0];
14727 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14728 if (POINTER_TYPE_P (itype))
14729 itype = sizetype;
14731 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14732 = wide_int_to_tree (itype, folded_deps[0]);
14733 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14734 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14737 lower_omp_ordered_ret:
14739 /* Ordered without clauses is #pragma omp threads, while we want
14740 a nop instead if we remove all clauses. */
14741 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14742 gsi_replace (gsi_p, gimple_build_nop (), true);
14746 /* Expand code for an OpenMP ordered directive. */
14748 static void
14749 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14751 tree block;
14752 gimple *stmt = gsi_stmt (*gsi_p);
14753 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14754 gcall *x;
14755 gbind *bind;
14756 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14757 OMP_CLAUSE_SIMD);
14758 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14759 OMP_CLAUSE_THREADS);
14761 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14762 OMP_CLAUSE_DEPEND))
14764 /* FIXME: This is needs to be moved to the expansion to verify various
14765 conditions only testable on cfg with dominators computed, and also
14766 all the depend clauses to be merged still might need to be available
14767 for the runtime checks. */
14768 if (0)
14769 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14770 return;
14773 push_gimplify_context ();
14775 block = make_node (BLOCK);
14776 bind = gimple_build_bind (NULL, NULL, block);
14777 gsi_replace (gsi_p, bind, true);
14778 gimple_bind_add_stmt (bind, stmt);
14780 if (simd)
14782 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14783 build_int_cst (NULL_TREE, threads));
14784 cfun->has_simduid_loops = true;
14786 else
14787 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14789 gimple_bind_add_stmt (bind, x);
14791 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14792 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14793 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14794 gimple_omp_set_body (stmt, NULL);
14796 if (simd)
14797 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14798 build_int_cst (NULL_TREE, threads));
14799 else
14800 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14802 gimple_bind_add_stmt (bind, x);
14804 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14806 pop_gimplify_context (bind);
14808 gimple_bind_append_vars (bind, ctx->block_vars);
14809 BLOCK_VARS (block) = gimple_bind_vars (bind);
14813 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14814 substitution of a couple of function calls. But in the NAMED case,
14815 requires that languages coordinate a symbol name. It is therefore
14816 best put here in common code. */
14818 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14820 static void
14821 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14823 tree block;
14824 tree name, lock, unlock;
14825 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14826 gbind *bind;
14827 location_t loc = gimple_location (stmt);
14828 gimple_seq tbody;
14830 name = gimple_omp_critical_name (stmt);
14831 if (name)
14833 tree decl;
14835 if (!critical_name_mutexes)
14836 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14838 tree *n = critical_name_mutexes->get (name);
14839 if (n == NULL)
14841 char *new_str;
14843 decl = create_tmp_var_raw (ptr_type_node);
14845 new_str = ACONCAT ((".gomp_critical_user_",
14846 IDENTIFIER_POINTER (name), NULL));
14847 DECL_NAME (decl) = get_identifier (new_str);
14848 TREE_PUBLIC (decl) = 1;
14849 TREE_STATIC (decl) = 1;
14850 DECL_COMMON (decl) = 1;
14851 DECL_ARTIFICIAL (decl) = 1;
14852 DECL_IGNORED_P (decl) = 1;
14854 varpool_node::finalize_decl (decl);
14856 critical_name_mutexes->put (name, decl);
14858 else
14859 decl = *n;
14861 /* If '#pragma omp critical' is inside offloaded region or
14862 inside function marked as offloadable, the symbol must be
14863 marked as offloadable too. */
14864 omp_context *octx;
14865 if (cgraph_node::get (current_function_decl)->offloadable)
14866 varpool_node::get_create (decl)->offloadable = 1;
14867 else
14868 for (octx = ctx->outer; octx; octx = octx->outer)
14869 if (is_gimple_omp_offloaded (octx->stmt))
14871 varpool_node::get_create (decl)->offloadable = 1;
14872 break;
14875 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14876 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14878 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14879 unlock = build_call_expr_loc (loc, unlock, 1,
14880 build_fold_addr_expr_loc (loc, decl));
14882 else
14884 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14885 lock = build_call_expr_loc (loc, lock, 0);
14887 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14888 unlock = build_call_expr_loc (loc, unlock, 0);
14891 push_gimplify_context ();
14893 block = make_node (BLOCK);
14894 bind = gimple_build_bind (NULL, NULL, block);
14895 gsi_replace (gsi_p, bind, true);
14896 gimple_bind_add_stmt (bind, stmt);
14898 tbody = gimple_bind_body (bind);
14899 gimplify_and_add (lock, &tbody);
14900 gimple_bind_set_body (bind, tbody);
14902 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14903 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14904 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14905 gimple_omp_set_body (stmt, NULL);
14907 tbody = gimple_bind_body (bind);
14908 gimplify_and_add (unlock, &tbody);
14909 gimple_bind_set_body (bind, tbody);
14911 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14913 pop_gimplify_context (bind);
14914 gimple_bind_append_vars (bind, ctx->block_vars);
14915 BLOCK_VARS (block) = gimple_bind_vars (bind);
14919 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14920 for a lastprivate clause. Given a loop control predicate of (V
14921 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14922 is appended to *DLIST, iterator initialization is appended to
14923 *BODY_P. */
14925 static void
14926 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14927 gimple_seq *dlist, struct omp_context *ctx)
14929 tree clauses, cond, vinit;
14930 enum tree_code cond_code;
14931 gimple_seq stmts;
14933 cond_code = fd->loop.cond_code;
14934 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14936 /* When possible, use a strict equality expression. This can let VRP
14937 type optimizations deduce the value and remove a copy. */
14938 if (tree_fits_shwi_p (fd->loop.step))
14940 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14941 if (step == 1 || step == -1)
14942 cond_code = EQ_EXPR;
14945 tree n2 = fd->loop.n2;
14946 if (fd->collapse > 1
14947 && TREE_CODE (n2) != INTEGER_CST
14948 && gimple_omp_for_combined_into_p (fd->for_stmt))
14950 struct omp_context *taskreg_ctx = NULL;
14951 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14953 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14954 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14955 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14957 if (gimple_omp_for_combined_into_p (gfor))
14959 gcc_assert (ctx->outer->outer
14960 && is_parallel_ctx (ctx->outer->outer));
14961 taskreg_ctx = ctx->outer->outer;
14963 else
14965 struct omp_for_data outer_fd;
14966 extract_omp_for_data (gfor, &outer_fd, NULL);
14967 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14970 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14971 taskreg_ctx = ctx->outer->outer;
14973 else if (is_taskreg_ctx (ctx->outer))
14974 taskreg_ctx = ctx->outer;
14975 if (taskreg_ctx)
14977 int i;
14978 tree innerc
14979 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14980 OMP_CLAUSE__LOOPTEMP_);
14981 gcc_assert (innerc);
14982 for (i = 0; i < fd->collapse; i++)
14984 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14985 OMP_CLAUSE__LOOPTEMP_);
14986 gcc_assert (innerc);
14988 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14989 OMP_CLAUSE__LOOPTEMP_);
14990 if (innerc)
14991 n2 = fold_convert (TREE_TYPE (n2),
14992 lookup_decl (OMP_CLAUSE_DECL (innerc),
14993 taskreg_ctx));
14996 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14998 clauses = gimple_omp_for_clauses (fd->for_stmt);
14999 stmts = NULL;
15000 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
15001 if (!gimple_seq_empty_p (stmts))
15003 gimple_seq_add_seq (&stmts, *dlist);
15004 *dlist = stmts;
15006 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
15007 vinit = fd->loop.n1;
15008 if (cond_code == EQ_EXPR
15009 && tree_fits_shwi_p (fd->loop.n2)
15010 && ! integer_zerop (fd->loop.n2))
15011 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15012 else
15013 vinit = unshare_expr (vinit);
15015 /* Initialize the iterator variable, so that threads that don't execute
15016 any iterations don't execute the lastprivate clauses by accident. */
15017 gimplify_assign (fd->loop.v, vinit, body_p);
15022 /* Lower code for an OMP loop directive. */
15024 static void
15025 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15027 tree *rhs_p, block;
15028 struct omp_for_data fd, *fdp = NULL;
15029 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15030 gbind *new_stmt;
15031 gimple_seq omp_for_body, body, dlist;
15032 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15033 size_t i;
15035 push_gimplify_context ();
15037 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15039 block = make_node (BLOCK);
15040 new_stmt = gimple_build_bind (NULL, NULL, block);
15041 /* Replace at gsi right away, so that 'stmt' is no member
15042 of a sequence anymore as we're going to add to a different
15043 one below. */
15044 gsi_replace (gsi_p, new_stmt, true);
15046 /* Move declaration of temporaries in the loop body before we make
15047 it go away. */
15048 omp_for_body = gimple_omp_body (stmt);
15049 if (!gimple_seq_empty_p (omp_for_body)
15050 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15052 gbind *inner_bind
15053 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15054 tree vars = gimple_bind_vars (inner_bind);
15055 gimple_bind_append_vars (new_stmt, vars);
15056 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15057 keep them on the inner_bind and it's block. */
15058 gimple_bind_set_vars (inner_bind, NULL_TREE);
15059 if (gimple_bind_block (inner_bind))
15060 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15063 if (gimple_omp_for_combined_into_p (stmt))
15065 extract_omp_for_data (stmt, &fd, NULL);
15066 fdp = &fd;
15068 /* We need two temporaries with fd.loop.v type (istart/iend)
15069 and then (fd.collapse - 1) temporaries with the same
15070 type for count2 ... countN-1 vars if not constant. */
15071 size_t count = 2;
15072 tree type = fd.iter_type;
15073 if (fd.collapse > 1
15074 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15075 count += fd.collapse - 1;
15076 bool taskreg_for
15077 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15078 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15079 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15080 tree clauses = *pc;
15081 if (taskreg_for)
15082 outerc
15083 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15084 OMP_CLAUSE__LOOPTEMP_);
15085 for (i = 0; i < count; i++)
15087 tree temp;
15088 if (taskreg_for)
15090 gcc_assert (outerc);
15091 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15092 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15093 OMP_CLAUSE__LOOPTEMP_);
15095 else
15097 temp = create_tmp_var (type);
15098 insert_decl_map (&ctx->outer->cb, temp, temp);
15100 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15101 OMP_CLAUSE_DECL (*pc) = temp;
15102 pc = &OMP_CLAUSE_CHAIN (*pc);
15104 *pc = clauses;
15107 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15108 dlist = NULL;
15109 body = NULL;
15110 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15111 fdp);
15112 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15114 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15116 /* Lower the header expressions. At this point, we can assume that
15117 the header is of the form:
15119 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15121 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15122 using the .omp_data_s mapping, if needed. */
15123 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15125 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15126 if (!is_gimple_min_invariant (*rhs_p))
15127 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15129 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15130 if (!is_gimple_min_invariant (*rhs_p))
15131 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15133 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15134 if (!is_gimple_min_invariant (*rhs_p))
15135 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15138 /* Once lowered, extract the bounds and clauses. */
15139 extract_omp_for_data (stmt, &fd, NULL);
15141 if (is_gimple_omp_oacc (ctx->stmt)
15142 && !ctx_in_oacc_kernels_region (ctx))
15143 lower_oacc_head_tail (gimple_location (stmt),
15144 gimple_omp_for_clauses (stmt),
15145 &oacc_head, &oacc_tail, ctx);
15147 /* Add OpenACC partitioning and reduction markers just before the loop */
15148 if (oacc_head)
15149 gimple_seq_add_seq (&body, oacc_head);
15151 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15153 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15154 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15155 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15156 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15158 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15159 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15160 OMP_CLAUSE_LINEAR_STEP (c)
15161 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15162 ctx);
15165 if (!gimple_omp_for_grid_phony (stmt))
15166 gimple_seq_add_stmt (&body, stmt);
15167 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15169 if (!gimple_omp_for_grid_phony (stmt))
15170 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15171 fd.loop.v));
15173 /* After the loop, add exit clauses. */
15174 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15176 if (ctx->cancellable)
15177 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15179 gimple_seq_add_seq (&body, dlist);
15181 body = maybe_catch_exception (body);
15183 if (!gimple_omp_for_grid_phony (stmt))
15185 /* Region exit marker goes at the end of the loop body. */
15186 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15187 maybe_add_implicit_barrier_cancel (ctx, &body);
15190 /* Add OpenACC joining and reduction markers just after the loop. */
15191 if (oacc_tail)
15192 gimple_seq_add_seq (&body, oacc_tail);
15194 pop_gimplify_context (new_stmt);
15196 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15197 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15198 if (BLOCK_VARS (block))
15199 TREE_USED (block) = 1;
15201 gimple_bind_set_body (new_stmt, body);
15202 gimple_omp_set_body (stmt, NULL);
15203 gimple_omp_for_set_pre_body (stmt, NULL);
15206 /* Callback for walk_stmts. Check if the current statement only contains
15207 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15209 static tree
15210 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15211 bool *handled_ops_p,
15212 struct walk_stmt_info *wi)
15214 int *info = (int *) wi->info;
15215 gimple *stmt = gsi_stmt (*gsi_p);
15217 *handled_ops_p = true;
15218 switch (gimple_code (stmt))
15220 WALK_SUBSTMTS;
15222 case GIMPLE_OMP_FOR:
15223 case GIMPLE_OMP_SECTIONS:
15224 *info = *info == 0 ? 1 : -1;
15225 break;
15226 default:
15227 *info = -1;
15228 break;
15230 return NULL;
15233 struct omp_taskcopy_context
15235 /* This field must be at the beginning, as we do "inheritance": Some
15236 callback functions for tree-inline.c (e.g., omp_copy_decl)
15237 receive a copy_body_data pointer that is up-casted to an
15238 omp_context pointer. */
15239 copy_body_data cb;
15240 omp_context *ctx;
15243 static tree
15244 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15246 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15248 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15249 return create_tmp_var (TREE_TYPE (var));
15251 return var;
15254 static tree
15255 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15257 tree name, new_fields = NULL, type, f;
15259 type = lang_hooks.types.make_type (RECORD_TYPE);
15260 name = DECL_NAME (TYPE_NAME (orig_type));
15261 name = build_decl (gimple_location (tcctx->ctx->stmt),
15262 TYPE_DECL, name, type);
15263 TYPE_NAME (type) = name;
15265 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15267 tree new_f = copy_node (f);
15268 DECL_CONTEXT (new_f) = type;
15269 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15270 TREE_CHAIN (new_f) = new_fields;
15271 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15272 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15273 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15274 &tcctx->cb, NULL);
15275 new_fields = new_f;
15276 tcctx->cb.decl_map->put (f, new_f);
15278 TYPE_FIELDS (type) = nreverse (new_fields);
15279 layout_type (type);
15280 return type;
15283 /* Create task copyfn. */
15285 static void
15286 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15288 struct function *child_cfun;
15289 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15290 tree record_type, srecord_type, bind, list;
15291 bool record_needs_remap = false, srecord_needs_remap = false;
15292 splay_tree_node n;
15293 struct omp_taskcopy_context tcctx;
15294 location_t loc = gimple_location (task_stmt);
15296 child_fn = gimple_omp_task_copy_fn (task_stmt);
15297 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15298 gcc_assert (child_cfun->cfg == NULL);
15299 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15301 /* Reset DECL_CONTEXT on function arguments. */
15302 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15303 DECL_CONTEXT (t) = child_fn;
15305 /* Populate the function. */
15306 push_gimplify_context ();
15307 push_cfun (child_cfun);
15309 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15310 TREE_SIDE_EFFECTS (bind) = 1;
15311 list = NULL;
15312 DECL_SAVED_TREE (child_fn) = bind;
15313 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15315 /* Remap src and dst argument types if needed. */
15316 record_type = ctx->record_type;
15317 srecord_type = ctx->srecord_type;
15318 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15319 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15321 record_needs_remap = true;
15322 break;
15324 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15325 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15327 srecord_needs_remap = true;
15328 break;
15331 if (record_needs_remap || srecord_needs_remap)
15333 memset (&tcctx, '\0', sizeof (tcctx));
15334 tcctx.cb.src_fn = ctx->cb.src_fn;
15335 tcctx.cb.dst_fn = child_fn;
15336 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15337 gcc_checking_assert (tcctx.cb.src_node);
15338 tcctx.cb.dst_node = tcctx.cb.src_node;
15339 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15340 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15341 tcctx.cb.eh_lp_nr = 0;
15342 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15343 tcctx.cb.decl_map = new hash_map<tree, tree>;
15344 tcctx.ctx = ctx;
15346 if (record_needs_remap)
15347 record_type = task_copyfn_remap_type (&tcctx, record_type);
15348 if (srecord_needs_remap)
15349 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15351 else
15352 tcctx.cb.decl_map = NULL;
15354 arg = DECL_ARGUMENTS (child_fn);
15355 TREE_TYPE (arg) = build_pointer_type (record_type);
15356 sarg = DECL_CHAIN (arg);
15357 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15359 /* First pass: initialize temporaries used in record_type and srecord_type
15360 sizes and field offsets. */
15361 if (tcctx.cb.decl_map)
15362 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15363 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15365 tree *p;
15367 decl = OMP_CLAUSE_DECL (c);
15368 p = tcctx.cb.decl_map->get (decl);
15369 if (p == NULL)
15370 continue;
15371 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15372 sf = (tree) n->value;
15373 sf = *tcctx.cb.decl_map->get (sf);
15374 src = build_simple_mem_ref_loc (loc, sarg);
15375 src = omp_build_component_ref (src, sf);
15376 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15377 append_to_statement_list (t, &list);
15380 /* Second pass: copy shared var pointers and copy construct non-VLA
15381 firstprivate vars. */
15382 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15383 switch (OMP_CLAUSE_CODE (c))
15385 splay_tree_key key;
15386 case OMP_CLAUSE_SHARED:
15387 decl = OMP_CLAUSE_DECL (c);
15388 key = (splay_tree_key) decl;
15389 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15390 key = (splay_tree_key) &DECL_UID (decl);
15391 n = splay_tree_lookup (ctx->field_map, key);
15392 if (n == NULL)
15393 break;
15394 f = (tree) n->value;
15395 if (tcctx.cb.decl_map)
15396 f = *tcctx.cb.decl_map->get (f);
15397 n = splay_tree_lookup (ctx->sfield_map, key);
15398 sf = (tree) n->value;
15399 if (tcctx.cb.decl_map)
15400 sf = *tcctx.cb.decl_map->get (sf);
15401 src = build_simple_mem_ref_loc (loc, sarg);
15402 src = omp_build_component_ref (src, sf);
15403 dst = build_simple_mem_ref_loc (loc, arg);
15404 dst = omp_build_component_ref (dst, f);
15405 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15406 append_to_statement_list (t, &list);
15407 break;
15408 case OMP_CLAUSE_FIRSTPRIVATE:
15409 decl = OMP_CLAUSE_DECL (c);
15410 if (is_variable_sized (decl))
15411 break;
15412 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15413 if (n == NULL)
15414 break;
15415 f = (tree) n->value;
15416 if (tcctx.cb.decl_map)
15417 f = *tcctx.cb.decl_map->get (f);
15418 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15419 if (n != NULL)
15421 sf = (tree) n->value;
15422 if (tcctx.cb.decl_map)
15423 sf = *tcctx.cb.decl_map->get (sf);
15424 src = build_simple_mem_ref_loc (loc, sarg);
15425 src = omp_build_component_ref (src, sf);
15426 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15427 src = build_simple_mem_ref_loc (loc, src);
15429 else
15430 src = decl;
15431 dst = build_simple_mem_ref_loc (loc, arg);
15432 dst = omp_build_component_ref (dst, f);
15433 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15434 append_to_statement_list (t, &list);
15435 break;
15436 case OMP_CLAUSE_PRIVATE:
15437 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15438 break;
15439 decl = OMP_CLAUSE_DECL (c);
15440 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15441 f = (tree) n->value;
15442 if (tcctx.cb.decl_map)
15443 f = *tcctx.cb.decl_map->get (f);
15444 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15445 if (n != NULL)
15447 sf = (tree) n->value;
15448 if (tcctx.cb.decl_map)
15449 sf = *tcctx.cb.decl_map->get (sf);
15450 src = build_simple_mem_ref_loc (loc, sarg);
15451 src = omp_build_component_ref (src, sf);
15452 if (use_pointer_for_field (decl, NULL))
15453 src = build_simple_mem_ref_loc (loc, src);
15455 else
15456 src = decl;
15457 dst = build_simple_mem_ref_loc (loc, arg);
15458 dst = omp_build_component_ref (dst, f);
15459 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15460 append_to_statement_list (t, &list);
15461 break;
15462 default:
15463 break;
15466 /* Last pass: handle VLA firstprivates. */
15467 if (tcctx.cb.decl_map)
15468 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15469 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15471 tree ind, ptr, df;
15473 decl = OMP_CLAUSE_DECL (c);
15474 if (!is_variable_sized (decl))
15475 continue;
15476 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15477 if (n == NULL)
15478 continue;
15479 f = (tree) n->value;
15480 f = *tcctx.cb.decl_map->get (f);
15481 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15482 ind = DECL_VALUE_EXPR (decl);
15483 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15484 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15485 n = splay_tree_lookup (ctx->sfield_map,
15486 (splay_tree_key) TREE_OPERAND (ind, 0));
15487 sf = (tree) n->value;
15488 sf = *tcctx.cb.decl_map->get (sf);
15489 src = build_simple_mem_ref_loc (loc, sarg);
15490 src = omp_build_component_ref (src, sf);
15491 src = build_simple_mem_ref_loc (loc, src);
15492 dst = build_simple_mem_ref_loc (loc, arg);
15493 dst = omp_build_component_ref (dst, f);
15494 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15495 append_to_statement_list (t, &list);
15496 n = splay_tree_lookup (ctx->field_map,
15497 (splay_tree_key) TREE_OPERAND (ind, 0));
15498 df = (tree) n->value;
15499 df = *tcctx.cb.decl_map->get (df);
15500 ptr = build_simple_mem_ref_loc (loc, arg);
15501 ptr = omp_build_component_ref (ptr, df);
15502 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15503 build_fold_addr_expr_loc (loc, dst));
15504 append_to_statement_list (t, &list);
15507 t = build1 (RETURN_EXPR, void_type_node, NULL);
15508 append_to_statement_list (t, &list);
15510 if (tcctx.cb.decl_map)
15511 delete tcctx.cb.decl_map;
15512 pop_gimplify_context (NULL);
15513 BIND_EXPR_BODY (bind) = list;
15514 pop_cfun ();
15517 static void
15518 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15520 tree c, clauses;
15521 gimple *g;
15522 size_t n_in = 0, n_out = 0, idx = 2, i;
15524 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15525 gcc_assert (clauses);
15526 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15527 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15528 switch (OMP_CLAUSE_DEPEND_KIND (c))
15530 case OMP_CLAUSE_DEPEND_IN:
15531 n_in++;
15532 break;
15533 case OMP_CLAUSE_DEPEND_OUT:
15534 case OMP_CLAUSE_DEPEND_INOUT:
15535 n_out++;
15536 break;
15537 case OMP_CLAUSE_DEPEND_SOURCE:
15538 case OMP_CLAUSE_DEPEND_SINK:
15539 /* FALLTHRU */
15540 default:
15541 gcc_unreachable ();
15543 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15544 tree array = create_tmp_var (type);
15545 TREE_ADDRESSABLE (array) = 1;
15546 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15547 NULL_TREE);
15548 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15549 gimple_seq_add_stmt (iseq, g);
15550 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15551 NULL_TREE);
15552 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15553 gimple_seq_add_stmt (iseq, g);
15554 for (i = 0; i < 2; i++)
15556 if ((i ? n_in : n_out) == 0)
15557 continue;
15558 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15559 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15560 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15562 tree t = OMP_CLAUSE_DECL (c);
15563 t = fold_convert (ptr_type_node, t);
15564 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15565 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15566 NULL_TREE, NULL_TREE);
15567 g = gimple_build_assign (r, t);
15568 gimple_seq_add_stmt (iseq, g);
15571 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15572 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15573 OMP_CLAUSE_CHAIN (c) = *pclauses;
15574 *pclauses = c;
15575 tree clobber = build_constructor (type, NULL);
15576 TREE_THIS_VOLATILE (clobber) = 1;
15577 g = gimple_build_assign (array, clobber);
15578 gimple_seq_add_stmt (oseq, g);
15581 /* Lower the OpenMP parallel or task directive in the current statement
15582 in GSI_P. CTX holds context information for the directive. */
15584 static void
15585 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15587 tree clauses;
15588 tree child_fn, t;
15589 gimple *stmt = gsi_stmt (*gsi_p);
15590 gbind *par_bind, *bind, *dep_bind = NULL;
15591 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15592 location_t loc = gimple_location (stmt);
15594 clauses = gimple_omp_taskreg_clauses (stmt);
15595 par_bind
15596 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15597 par_body = gimple_bind_body (par_bind);
15598 child_fn = ctx->cb.dst_fn;
15599 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15600 && !gimple_omp_parallel_combined_p (stmt))
15602 struct walk_stmt_info wi;
15603 int ws_num = 0;
15605 memset (&wi, 0, sizeof (wi));
15606 wi.info = &ws_num;
15607 wi.val_only = true;
15608 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15609 if (ws_num == 1)
15610 gimple_omp_parallel_set_combined_p (stmt, true);
15612 gimple_seq dep_ilist = NULL;
15613 gimple_seq dep_olist = NULL;
15614 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15615 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15617 push_gimplify_context ();
15618 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15619 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15620 &dep_ilist, &dep_olist);
15623 if (ctx->srecord_type)
15624 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15626 push_gimplify_context ();
15628 par_olist = NULL;
15629 par_ilist = NULL;
15630 par_rlist = NULL;
15631 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15632 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15633 if (phony_construct && ctx->record_type)
15635 gcc_checking_assert (!ctx->receiver_decl);
15636 ctx->receiver_decl = create_tmp_var
15637 (build_reference_type (ctx->record_type), ".omp_rec");
15639 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15640 lower_omp (&par_body, ctx);
15641 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15642 lower_reduction_clauses (clauses, &par_rlist, ctx);
15644 /* Declare all the variables created by mapping and the variables
15645 declared in the scope of the parallel body. */
15646 record_vars_into (ctx->block_vars, child_fn);
15647 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15649 if (ctx->record_type)
15651 ctx->sender_decl
15652 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15653 : ctx->record_type, ".omp_data_o");
15654 DECL_NAMELESS (ctx->sender_decl) = 1;
15655 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15656 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15659 olist = NULL;
15660 ilist = NULL;
15661 lower_send_clauses (clauses, &ilist, &olist, ctx);
15662 lower_send_shared_vars (&ilist, &olist, ctx);
15664 if (ctx->record_type)
15666 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15667 TREE_THIS_VOLATILE (clobber) = 1;
15668 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15669 clobber));
15672 /* Once all the expansions are done, sequence all the different
15673 fragments inside gimple_omp_body. */
15675 new_body = NULL;
15677 if (ctx->record_type)
15679 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15680 /* fixup_child_record_type might have changed receiver_decl's type. */
15681 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15682 gimple_seq_add_stmt (&new_body,
15683 gimple_build_assign (ctx->receiver_decl, t));
15686 gimple_seq_add_seq (&new_body, par_ilist);
15687 gimple_seq_add_seq (&new_body, par_body);
15688 gimple_seq_add_seq (&new_body, par_rlist);
15689 if (ctx->cancellable)
15690 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15691 gimple_seq_add_seq (&new_body, par_olist);
15692 new_body = maybe_catch_exception (new_body);
15693 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15694 gimple_seq_add_stmt (&new_body,
15695 gimple_build_omp_continue (integer_zero_node,
15696 integer_zero_node));
15697 if (!phony_construct)
15699 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15700 gimple_omp_set_body (stmt, new_body);
15703 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15704 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15705 gimple_bind_add_seq (bind, ilist);
15706 if (!phony_construct)
15707 gimple_bind_add_stmt (bind, stmt);
15708 else
15709 gimple_bind_add_seq (bind, new_body);
15710 gimple_bind_add_seq (bind, olist);
15712 pop_gimplify_context (NULL);
15714 if (dep_bind)
15716 gimple_bind_add_seq (dep_bind, dep_ilist);
15717 gimple_bind_add_stmt (dep_bind, bind);
15718 gimple_bind_add_seq (dep_bind, dep_olist);
15719 pop_gimplify_context (dep_bind);
15723 /* Lower the GIMPLE_OMP_TARGET in the current statement
15724 in GSI_P. CTX holds context information for the directive. */
15726 static void
15727 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15729 tree clauses;
15730 tree child_fn, t, c;
15731 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15732 gbind *tgt_bind, *bind, *dep_bind = NULL;
15733 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15734 location_t loc = gimple_location (stmt);
15735 bool offloaded, data_region;
15736 unsigned int map_cnt = 0;
15738 offloaded = is_gimple_omp_offloaded (stmt);
15739 switch (gimple_omp_target_kind (stmt))
15741 case GF_OMP_TARGET_KIND_REGION:
15742 case GF_OMP_TARGET_KIND_UPDATE:
15743 case GF_OMP_TARGET_KIND_ENTER_DATA:
15744 case GF_OMP_TARGET_KIND_EXIT_DATA:
15745 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15746 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15747 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15748 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15749 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15750 data_region = false;
15751 break;
15752 case GF_OMP_TARGET_KIND_DATA:
15753 case GF_OMP_TARGET_KIND_OACC_DATA:
15754 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15755 data_region = true;
15756 break;
15757 default:
15758 gcc_unreachable ();
15761 clauses = gimple_omp_target_clauses (stmt);
15763 gimple_seq dep_ilist = NULL;
15764 gimple_seq dep_olist = NULL;
15765 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15767 push_gimplify_context ();
15768 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15769 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15770 &dep_ilist, &dep_olist);
15773 tgt_bind = NULL;
15774 tgt_body = NULL;
15775 if (offloaded)
15777 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15778 tgt_body = gimple_bind_body (tgt_bind);
15780 else if (data_region)
15781 tgt_body = gimple_omp_body (stmt);
15782 child_fn = ctx->cb.dst_fn;
15784 push_gimplify_context ();
15785 fplist = NULL;
15787 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15788 switch (OMP_CLAUSE_CODE (c))
15790 tree var, x;
15792 default:
15793 break;
15794 case OMP_CLAUSE_MAP:
15795 #if CHECKING_P
15796 /* First check what we're prepared to handle in the following. */
15797 switch (OMP_CLAUSE_MAP_KIND (c))
15799 case GOMP_MAP_ALLOC:
15800 case GOMP_MAP_TO:
15801 case GOMP_MAP_FROM:
15802 case GOMP_MAP_TOFROM:
15803 case GOMP_MAP_POINTER:
15804 case GOMP_MAP_TO_PSET:
15805 case GOMP_MAP_DELETE:
15806 case GOMP_MAP_RELEASE:
15807 case GOMP_MAP_ALWAYS_TO:
15808 case GOMP_MAP_ALWAYS_FROM:
15809 case GOMP_MAP_ALWAYS_TOFROM:
15810 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15811 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15812 case GOMP_MAP_STRUCT:
15813 case GOMP_MAP_ALWAYS_POINTER:
15814 break;
15815 case GOMP_MAP_FORCE_ALLOC:
15816 case GOMP_MAP_FORCE_TO:
15817 case GOMP_MAP_FORCE_FROM:
15818 case GOMP_MAP_FORCE_TOFROM:
15819 case GOMP_MAP_FORCE_PRESENT:
15820 case GOMP_MAP_FORCE_DEVICEPTR:
15821 case GOMP_MAP_DEVICE_RESIDENT:
15822 case GOMP_MAP_LINK:
15823 gcc_assert (is_gimple_omp_oacc (stmt));
15824 break;
15825 default:
15826 gcc_unreachable ();
15828 #endif
15829 /* FALLTHRU */
15830 case OMP_CLAUSE_TO:
15831 case OMP_CLAUSE_FROM:
15832 oacc_firstprivate:
15833 var = OMP_CLAUSE_DECL (c);
15834 if (!DECL_P (var))
15836 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15837 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15838 && (OMP_CLAUSE_MAP_KIND (c)
15839 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15840 map_cnt++;
15841 continue;
15844 if (DECL_SIZE (var)
15845 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15847 tree var2 = DECL_VALUE_EXPR (var);
15848 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15849 var2 = TREE_OPERAND (var2, 0);
15850 gcc_assert (DECL_P (var2));
15851 var = var2;
15854 if (offloaded
15855 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15856 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15857 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15859 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15861 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15862 && varpool_node::get_create (var)->offloadable)
15863 continue;
15865 tree type = build_pointer_type (TREE_TYPE (var));
15866 tree new_var = lookup_decl (var, ctx);
15867 x = create_tmp_var_raw (type, get_name (new_var));
15868 gimple_add_tmp_var (x);
15869 x = build_simple_mem_ref (x);
15870 SET_DECL_VALUE_EXPR (new_var, x);
15871 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15873 continue;
15876 if (!maybe_lookup_field (var, ctx))
15877 continue;
15879 /* Don't remap oacc parallel reduction variables, because the
15880 intermediate result must be local to each gang. */
15881 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15882 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15884 x = build_receiver_ref (var, true, ctx);
15885 tree new_var = lookup_decl (var, ctx);
15887 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15888 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15889 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15890 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15891 x = build_simple_mem_ref (x);
15892 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15894 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15895 if (is_reference (new_var))
15897 /* Create a local object to hold the instance
15898 value. */
15899 tree type = TREE_TYPE (TREE_TYPE (new_var));
15900 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15901 tree inst = create_tmp_var (type, id);
15902 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15903 x = build_fold_addr_expr (inst);
15905 gimplify_assign (new_var, x, &fplist);
15907 else if (DECL_P (new_var))
15909 SET_DECL_VALUE_EXPR (new_var, x);
15910 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15912 else
15913 gcc_unreachable ();
15915 map_cnt++;
15916 break;
15918 case OMP_CLAUSE_FIRSTPRIVATE:
15919 if (is_oacc_parallel (ctx))
15920 goto oacc_firstprivate;
15921 map_cnt++;
15922 var = OMP_CLAUSE_DECL (c);
15923 if (!is_reference (var)
15924 && !is_gimple_reg_type (TREE_TYPE (var)))
15926 tree new_var = lookup_decl (var, ctx);
15927 if (is_variable_sized (var))
15929 tree pvar = DECL_VALUE_EXPR (var);
15930 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15931 pvar = TREE_OPERAND (pvar, 0);
15932 gcc_assert (DECL_P (pvar));
15933 tree new_pvar = lookup_decl (pvar, ctx);
15934 x = build_fold_indirect_ref (new_pvar);
15935 TREE_THIS_NOTRAP (x) = 1;
15937 else
15938 x = build_receiver_ref (var, true, ctx);
15939 SET_DECL_VALUE_EXPR (new_var, x);
15940 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15942 break;
15944 case OMP_CLAUSE_PRIVATE:
15945 if (is_gimple_omp_oacc (ctx->stmt))
15946 break;
15947 var = OMP_CLAUSE_DECL (c);
15948 if (is_variable_sized (var))
15950 tree new_var = lookup_decl (var, ctx);
15951 tree pvar = DECL_VALUE_EXPR (var);
15952 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15953 pvar = TREE_OPERAND (pvar, 0);
15954 gcc_assert (DECL_P (pvar));
15955 tree new_pvar = lookup_decl (pvar, ctx);
15956 x = build_fold_indirect_ref (new_pvar);
15957 TREE_THIS_NOTRAP (x) = 1;
15958 SET_DECL_VALUE_EXPR (new_var, x);
15959 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15961 break;
15963 case OMP_CLAUSE_USE_DEVICE_PTR:
15964 case OMP_CLAUSE_IS_DEVICE_PTR:
15965 var = OMP_CLAUSE_DECL (c);
15966 map_cnt++;
15967 if (is_variable_sized (var))
15969 tree new_var = lookup_decl (var, ctx);
15970 tree pvar = DECL_VALUE_EXPR (var);
15971 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15972 pvar = TREE_OPERAND (pvar, 0);
15973 gcc_assert (DECL_P (pvar));
15974 tree new_pvar = lookup_decl (pvar, ctx);
15975 x = build_fold_indirect_ref (new_pvar);
15976 TREE_THIS_NOTRAP (x) = 1;
15977 SET_DECL_VALUE_EXPR (new_var, x);
15978 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15980 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15982 tree new_var = lookup_decl (var, ctx);
15983 tree type = build_pointer_type (TREE_TYPE (var));
15984 x = create_tmp_var_raw (type, get_name (new_var));
15985 gimple_add_tmp_var (x);
15986 x = build_simple_mem_ref (x);
15987 SET_DECL_VALUE_EXPR (new_var, x);
15988 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15990 else
15992 tree new_var = lookup_decl (var, ctx);
15993 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
15994 gimple_add_tmp_var (x);
15995 SET_DECL_VALUE_EXPR (new_var, x);
15996 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15998 break;
16001 if (offloaded)
16003 target_nesting_level++;
16004 lower_omp (&tgt_body, ctx);
16005 target_nesting_level--;
16007 else if (data_region)
16008 lower_omp (&tgt_body, ctx);
16010 if (offloaded)
16012 /* Declare all the variables created by mapping and the variables
16013 declared in the scope of the target body. */
16014 record_vars_into (ctx->block_vars, child_fn);
16015 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16018 olist = NULL;
16019 ilist = NULL;
16020 if (ctx->record_type)
16022 ctx->sender_decl
16023 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16024 DECL_NAMELESS (ctx->sender_decl) = 1;
16025 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16026 t = make_tree_vec (3);
16027 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16028 TREE_VEC_ELT (t, 1)
16029 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16030 ".omp_data_sizes");
16031 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16032 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16033 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16034 tree tkind_type = short_unsigned_type_node;
16035 int talign_shift = 8;
16036 TREE_VEC_ELT (t, 2)
16037 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16038 ".omp_data_kinds");
16039 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16040 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16041 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16042 gimple_omp_target_set_data_arg (stmt, t);
16044 vec<constructor_elt, va_gc> *vsize;
16045 vec<constructor_elt, va_gc> *vkind;
16046 vec_alloc (vsize, map_cnt);
16047 vec_alloc (vkind, map_cnt);
16048 unsigned int map_idx = 0;
16050 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16051 switch (OMP_CLAUSE_CODE (c))
16053 tree ovar, nc, s, purpose, var, x, type;
16054 unsigned int talign;
16056 default:
16057 break;
16059 case OMP_CLAUSE_MAP:
16060 case OMP_CLAUSE_TO:
16061 case OMP_CLAUSE_FROM:
16062 oacc_firstprivate_map:
16063 nc = c;
16064 ovar = OMP_CLAUSE_DECL (c);
16065 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16066 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16067 || (OMP_CLAUSE_MAP_KIND (c)
16068 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16069 break;
16070 if (!DECL_P (ovar))
16072 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16073 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16075 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16076 == get_base_address (ovar));
16077 nc = OMP_CLAUSE_CHAIN (c);
16078 ovar = OMP_CLAUSE_DECL (nc);
16080 else
16082 tree x = build_sender_ref (ovar, ctx);
16083 tree v
16084 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16085 gimplify_assign (x, v, &ilist);
16086 nc = NULL_TREE;
16089 else
16091 if (DECL_SIZE (ovar)
16092 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16094 tree ovar2 = DECL_VALUE_EXPR (ovar);
16095 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16096 ovar2 = TREE_OPERAND (ovar2, 0);
16097 gcc_assert (DECL_P (ovar2));
16098 ovar = ovar2;
16100 if (!maybe_lookup_field (ovar, ctx))
16101 continue;
16104 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16105 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16106 talign = DECL_ALIGN_UNIT (ovar);
16107 if (nc)
16109 var = lookup_decl_in_outer_ctx (ovar, ctx);
16110 x = build_sender_ref (ovar, ctx);
16112 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16113 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16114 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16115 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16117 gcc_assert (offloaded);
16118 tree avar
16119 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16120 mark_addressable (avar);
16121 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16122 talign = DECL_ALIGN_UNIT (avar);
16123 avar = build_fold_addr_expr (avar);
16124 gimplify_assign (x, avar, &ilist);
16126 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16128 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16129 if (!is_reference (var))
16131 if (is_gimple_reg (var)
16132 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16133 TREE_NO_WARNING (var) = 1;
16134 var = build_fold_addr_expr (var);
16136 else
16137 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16138 gimplify_assign (x, var, &ilist);
16140 else if (is_gimple_reg (var))
16142 gcc_assert (offloaded);
16143 tree avar = create_tmp_var (TREE_TYPE (var));
16144 mark_addressable (avar);
16145 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16146 if (GOMP_MAP_COPY_TO_P (map_kind)
16147 || map_kind == GOMP_MAP_POINTER
16148 || map_kind == GOMP_MAP_TO_PSET
16149 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16151 /* If we need to initialize a temporary
16152 with VAR because it is not addressable, and
16153 the variable hasn't been initialized yet, then
16154 we'll get a warning for the store to avar.
16155 Don't warn in that case, the mapping might
16156 be implicit. */
16157 TREE_NO_WARNING (var) = 1;
16158 gimplify_assign (avar, var, &ilist);
16160 avar = build_fold_addr_expr (avar);
16161 gimplify_assign (x, avar, &ilist);
16162 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16163 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16164 && !TYPE_READONLY (TREE_TYPE (var)))
16166 x = unshare_expr (x);
16167 x = build_simple_mem_ref (x);
16168 gimplify_assign (var, x, &olist);
16171 else
16173 var = build_fold_addr_expr (var);
16174 gimplify_assign (x, var, &ilist);
16177 s = NULL_TREE;
16178 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16180 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16181 s = TREE_TYPE (ovar);
16182 if (TREE_CODE (s) == REFERENCE_TYPE)
16183 s = TREE_TYPE (s);
16184 s = TYPE_SIZE_UNIT (s);
16186 else
16187 s = OMP_CLAUSE_SIZE (c);
16188 if (s == NULL_TREE)
16189 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16190 s = fold_convert (size_type_node, s);
16191 purpose = size_int (map_idx++);
16192 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16193 if (TREE_CODE (s) != INTEGER_CST)
16194 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16196 unsigned HOST_WIDE_INT tkind, tkind_zero;
16197 switch (OMP_CLAUSE_CODE (c))
16199 case OMP_CLAUSE_MAP:
16200 tkind = OMP_CLAUSE_MAP_KIND (c);
16201 tkind_zero = tkind;
16202 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16203 switch (tkind)
16205 case GOMP_MAP_ALLOC:
16206 case GOMP_MAP_TO:
16207 case GOMP_MAP_FROM:
16208 case GOMP_MAP_TOFROM:
16209 case GOMP_MAP_ALWAYS_TO:
16210 case GOMP_MAP_ALWAYS_FROM:
16211 case GOMP_MAP_ALWAYS_TOFROM:
16212 case GOMP_MAP_RELEASE:
16213 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16214 break;
16215 case GOMP_MAP_DELETE:
16216 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16217 default:
16218 break;
16220 if (tkind_zero != tkind)
16222 if (integer_zerop (s))
16223 tkind = tkind_zero;
16224 else if (integer_nonzerop (s))
16225 tkind_zero = tkind;
16227 break;
16228 case OMP_CLAUSE_FIRSTPRIVATE:
16229 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16230 tkind = GOMP_MAP_TO;
16231 tkind_zero = tkind;
16232 break;
16233 case OMP_CLAUSE_TO:
16234 tkind = GOMP_MAP_TO;
16235 tkind_zero = tkind;
16236 break;
16237 case OMP_CLAUSE_FROM:
16238 tkind = GOMP_MAP_FROM;
16239 tkind_zero = tkind;
16240 break;
16241 default:
16242 gcc_unreachable ();
16244 gcc_checking_assert (tkind
16245 < (HOST_WIDE_INT_C (1U) << talign_shift));
16246 gcc_checking_assert (tkind_zero
16247 < (HOST_WIDE_INT_C (1U) << talign_shift));
16248 talign = ceil_log2 (talign);
16249 tkind |= talign << talign_shift;
16250 tkind_zero |= talign << talign_shift;
16251 gcc_checking_assert (tkind
16252 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16253 gcc_checking_assert (tkind_zero
16254 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16255 if (tkind == tkind_zero)
16256 x = build_int_cstu (tkind_type, tkind);
16257 else
16259 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16260 x = build3 (COND_EXPR, tkind_type,
16261 fold_build2 (EQ_EXPR, boolean_type_node,
16262 unshare_expr (s), size_zero_node),
16263 build_int_cstu (tkind_type, tkind_zero),
16264 build_int_cstu (tkind_type, tkind));
16266 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16267 if (nc && nc != c)
16268 c = nc;
16269 break;
16271 case OMP_CLAUSE_FIRSTPRIVATE:
16272 if (is_oacc_parallel (ctx))
16273 goto oacc_firstprivate_map;
16274 ovar = OMP_CLAUSE_DECL (c);
16275 if (is_reference (ovar))
16276 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16277 else
16278 talign = DECL_ALIGN_UNIT (ovar);
16279 var = lookup_decl_in_outer_ctx (ovar, ctx);
16280 x = build_sender_ref (ovar, ctx);
16281 tkind = GOMP_MAP_FIRSTPRIVATE;
16282 type = TREE_TYPE (ovar);
16283 if (is_reference (ovar))
16284 type = TREE_TYPE (type);
16285 if ((INTEGRAL_TYPE_P (type)
16286 && TYPE_PRECISION (type) <= POINTER_SIZE)
16287 || TREE_CODE (type) == POINTER_TYPE)
16289 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16290 tree t = var;
16291 if (is_reference (var))
16292 t = build_simple_mem_ref (var);
16293 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16294 TREE_NO_WARNING (var) = 1;
16295 if (TREE_CODE (type) != POINTER_TYPE)
16296 t = fold_convert (pointer_sized_int_node, t);
16297 t = fold_convert (TREE_TYPE (x), t);
16298 gimplify_assign (x, t, &ilist);
16300 else if (is_reference (var))
16301 gimplify_assign (x, var, &ilist);
16302 else if (is_gimple_reg (var))
16304 tree avar = create_tmp_var (TREE_TYPE (var));
16305 mark_addressable (avar);
16306 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16307 TREE_NO_WARNING (var) = 1;
16308 gimplify_assign (avar, var, &ilist);
16309 avar = build_fold_addr_expr (avar);
16310 gimplify_assign (x, avar, &ilist);
16312 else
16314 var = build_fold_addr_expr (var);
16315 gimplify_assign (x, var, &ilist);
16317 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16318 s = size_int (0);
16319 else if (is_reference (var))
16320 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16321 else
16322 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16323 s = fold_convert (size_type_node, s);
16324 purpose = size_int (map_idx++);
16325 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16326 if (TREE_CODE (s) != INTEGER_CST)
16327 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16329 gcc_checking_assert (tkind
16330 < (HOST_WIDE_INT_C (1U) << talign_shift));
16331 talign = ceil_log2 (talign);
16332 tkind |= talign << talign_shift;
16333 gcc_checking_assert (tkind
16334 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16335 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16336 build_int_cstu (tkind_type, tkind));
16337 break;
16339 case OMP_CLAUSE_USE_DEVICE_PTR:
16340 case OMP_CLAUSE_IS_DEVICE_PTR:
16341 ovar = OMP_CLAUSE_DECL (c);
16342 var = lookup_decl_in_outer_ctx (ovar, ctx);
16343 x = build_sender_ref (ovar, ctx);
16344 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16345 tkind = GOMP_MAP_USE_DEVICE_PTR;
16346 else
16347 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16348 type = TREE_TYPE (ovar);
16349 if (TREE_CODE (type) == ARRAY_TYPE)
16350 var = build_fold_addr_expr (var);
16351 else
16353 if (is_reference (ovar))
16355 type = TREE_TYPE (type);
16356 if (TREE_CODE (type) != ARRAY_TYPE)
16357 var = build_simple_mem_ref (var);
16358 var = fold_convert (TREE_TYPE (x), var);
16361 gimplify_assign (x, var, &ilist);
16362 s = size_int (0);
16363 purpose = size_int (map_idx++);
16364 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16365 gcc_checking_assert (tkind
16366 < (HOST_WIDE_INT_C (1U) << talign_shift));
16367 gcc_checking_assert (tkind
16368 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16369 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16370 build_int_cstu (tkind_type, tkind));
16371 break;
16374 gcc_assert (map_idx == map_cnt);
16376 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16377 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16378 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16379 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16380 for (int i = 1; i <= 2; i++)
16381 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16383 gimple_seq initlist = NULL;
16384 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16385 TREE_VEC_ELT (t, i)),
16386 &initlist, true, NULL_TREE);
16387 gimple_seq_add_seq (&ilist, initlist);
16389 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16390 NULL);
16391 TREE_THIS_VOLATILE (clobber) = 1;
16392 gimple_seq_add_stmt (&olist,
16393 gimple_build_assign (TREE_VEC_ELT (t, i),
16394 clobber));
16397 tree clobber = build_constructor (ctx->record_type, NULL);
16398 TREE_THIS_VOLATILE (clobber) = 1;
16399 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16400 clobber));
16403 /* Once all the expansions are done, sequence all the different
16404 fragments inside gimple_omp_body. */
16406 new_body = NULL;
16408 if (offloaded
16409 && ctx->record_type)
16411 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16412 /* fixup_child_record_type might have changed receiver_decl's type. */
16413 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16414 gimple_seq_add_stmt (&new_body,
16415 gimple_build_assign (ctx->receiver_decl, t));
16417 gimple_seq_add_seq (&new_body, fplist);
16419 if (offloaded || data_region)
16421 tree prev = NULL_TREE;
16422 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16423 switch (OMP_CLAUSE_CODE (c))
16425 tree var, x;
16426 default:
16427 break;
16428 case OMP_CLAUSE_FIRSTPRIVATE:
16429 if (is_gimple_omp_oacc (ctx->stmt))
16430 break;
16431 var = OMP_CLAUSE_DECL (c);
16432 if (is_reference (var)
16433 || is_gimple_reg_type (TREE_TYPE (var)))
16435 tree new_var = lookup_decl (var, ctx);
16436 tree type;
16437 type = TREE_TYPE (var);
16438 if (is_reference (var))
16439 type = TREE_TYPE (type);
16440 if ((INTEGRAL_TYPE_P (type)
16441 && TYPE_PRECISION (type) <= POINTER_SIZE)
16442 || TREE_CODE (type) == POINTER_TYPE)
16444 x = build_receiver_ref (var, false, ctx);
16445 if (TREE_CODE (type) != POINTER_TYPE)
16446 x = fold_convert (pointer_sized_int_node, x);
16447 x = fold_convert (type, x);
16448 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16449 fb_rvalue);
16450 if (is_reference (var))
16452 tree v = create_tmp_var_raw (type, get_name (var));
16453 gimple_add_tmp_var (v);
16454 TREE_ADDRESSABLE (v) = 1;
16455 gimple_seq_add_stmt (&new_body,
16456 gimple_build_assign (v, x));
16457 x = build_fold_addr_expr (v);
16459 gimple_seq_add_stmt (&new_body,
16460 gimple_build_assign (new_var, x));
16462 else
16464 x = build_receiver_ref (var, !is_reference (var), ctx);
16465 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16466 fb_rvalue);
16467 gimple_seq_add_stmt (&new_body,
16468 gimple_build_assign (new_var, x));
16471 else if (is_variable_sized (var))
16473 tree pvar = DECL_VALUE_EXPR (var);
16474 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16475 pvar = TREE_OPERAND (pvar, 0);
16476 gcc_assert (DECL_P (pvar));
16477 tree new_var = lookup_decl (pvar, ctx);
16478 x = build_receiver_ref (var, false, ctx);
16479 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16480 gimple_seq_add_stmt (&new_body,
16481 gimple_build_assign (new_var, x));
16483 break;
16484 case OMP_CLAUSE_PRIVATE:
16485 if (is_gimple_omp_oacc (ctx->stmt))
16486 break;
16487 var = OMP_CLAUSE_DECL (c);
16488 if (is_reference (var))
16490 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16491 tree new_var = lookup_decl (var, ctx);
16492 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16493 if (TREE_CONSTANT (x))
16495 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16496 get_name (var));
16497 gimple_add_tmp_var (x);
16498 TREE_ADDRESSABLE (x) = 1;
16499 x = build_fold_addr_expr_loc (clause_loc, x);
16501 else
16502 break;
16504 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16505 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16506 gimple_seq_add_stmt (&new_body,
16507 gimple_build_assign (new_var, x));
16509 break;
16510 case OMP_CLAUSE_USE_DEVICE_PTR:
16511 case OMP_CLAUSE_IS_DEVICE_PTR:
16512 var = OMP_CLAUSE_DECL (c);
16513 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16514 x = build_sender_ref (var, ctx);
16515 else
16516 x = build_receiver_ref (var, false, ctx);
16517 if (is_variable_sized (var))
16519 tree pvar = DECL_VALUE_EXPR (var);
16520 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16521 pvar = TREE_OPERAND (pvar, 0);
16522 gcc_assert (DECL_P (pvar));
16523 tree new_var = lookup_decl (pvar, ctx);
16524 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16525 gimple_seq_add_stmt (&new_body,
16526 gimple_build_assign (new_var, x));
16528 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16530 tree new_var = lookup_decl (var, ctx);
16531 new_var = DECL_VALUE_EXPR (new_var);
16532 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16533 new_var = TREE_OPERAND (new_var, 0);
16534 gcc_assert (DECL_P (new_var));
16535 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16536 gimple_seq_add_stmt (&new_body,
16537 gimple_build_assign (new_var, x));
16539 else
16541 tree type = TREE_TYPE (var);
16542 tree new_var = lookup_decl (var, ctx);
16543 if (is_reference (var))
16545 type = TREE_TYPE (type);
16546 if (TREE_CODE (type) != ARRAY_TYPE)
16548 tree v = create_tmp_var_raw (type, get_name (var));
16549 gimple_add_tmp_var (v);
16550 TREE_ADDRESSABLE (v) = 1;
16551 x = fold_convert (type, x);
16552 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16553 fb_rvalue);
16554 gimple_seq_add_stmt (&new_body,
16555 gimple_build_assign (v, x));
16556 x = build_fold_addr_expr (v);
16559 new_var = DECL_VALUE_EXPR (new_var);
16560 x = fold_convert (TREE_TYPE (new_var), x);
16561 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16562 gimple_seq_add_stmt (&new_body,
16563 gimple_build_assign (new_var, x));
16565 break;
16567 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16568 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16569 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16570 or references to VLAs. */
16571 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16572 switch (OMP_CLAUSE_CODE (c))
16574 tree var;
16575 default:
16576 break;
16577 case OMP_CLAUSE_MAP:
16578 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16579 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16581 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16582 HOST_WIDE_INT offset = 0;
16583 gcc_assert (prev);
16584 var = OMP_CLAUSE_DECL (c);
16585 if (DECL_P (var)
16586 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16587 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16588 ctx))
16589 && varpool_node::get_create (var)->offloadable)
16590 break;
16591 if (TREE_CODE (var) == INDIRECT_REF
16592 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16593 var = TREE_OPERAND (var, 0);
16594 if (TREE_CODE (var) == COMPONENT_REF)
16596 var = get_addr_base_and_unit_offset (var, &offset);
16597 gcc_assert (var != NULL_TREE && DECL_P (var));
16599 else if (DECL_SIZE (var)
16600 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16602 tree var2 = DECL_VALUE_EXPR (var);
16603 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16604 var2 = TREE_OPERAND (var2, 0);
16605 gcc_assert (DECL_P (var2));
16606 var = var2;
16608 tree new_var = lookup_decl (var, ctx), x;
16609 tree type = TREE_TYPE (new_var);
16610 bool is_ref;
16611 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16612 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16613 == COMPONENT_REF))
16615 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16616 is_ref = true;
16617 new_var = build2 (MEM_REF, type,
16618 build_fold_addr_expr (new_var),
16619 build_int_cst (build_pointer_type (type),
16620 offset));
16622 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16624 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16625 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16626 new_var = build2 (MEM_REF, type,
16627 build_fold_addr_expr (new_var),
16628 build_int_cst (build_pointer_type (type),
16629 offset));
16631 else
16632 is_ref = is_reference (var);
16633 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16634 is_ref = false;
16635 bool ref_to_array = false;
16636 if (is_ref)
16638 type = TREE_TYPE (type);
16639 if (TREE_CODE (type) == ARRAY_TYPE)
16641 type = build_pointer_type (type);
16642 ref_to_array = true;
16645 else if (TREE_CODE (type) == ARRAY_TYPE)
16647 tree decl2 = DECL_VALUE_EXPR (new_var);
16648 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16649 decl2 = TREE_OPERAND (decl2, 0);
16650 gcc_assert (DECL_P (decl2));
16651 new_var = decl2;
16652 type = TREE_TYPE (new_var);
16654 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16655 x = fold_convert_loc (clause_loc, type, x);
16656 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16658 tree bias = OMP_CLAUSE_SIZE (c);
16659 if (DECL_P (bias))
16660 bias = lookup_decl (bias, ctx);
16661 bias = fold_convert_loc (clause_loc, sizetype, bias);
16662 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16663 bias);
16664 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16665 TREE_TYPE (x), x, bias);
16667 if (ref_to_array)
16668 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16669 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16670 if (is_ref && !ref_to_array)
16672 tree t = create_tmp_var_raw (type, get_name (var));
16673 gimple_add_tmp_var (t);
16674 TREE_ADDRESSABLE (t) = 1;
16675 gimple_seq_add_stmt (&new_body,
16676 gimple_build_assign (t, x));
16677 x = build_fold_addr_expr_loc (clause_loc, t);
16679 gimple_seq_add_stmt (&new_body,
16680 gimple_build_assign (new_var, x));
16681 prev = NULL_TREE;
16683 else if (OMP_CLAUSE_CHAIN (c)
16684 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16685 == OMP_CLAUSE_MAP
16686 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16687 == GOMP_MAP_FIRSTPRIVATE_POINTER
16688 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16689 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16690 prev = c;
16691 break;
16692 case OMP_CLAUSE_PRIVATE:
16693 var = OMP_CLAUSE_DECL (c);
16694 if (is_variable_sized (var))
16696 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16697 tree new_var = lookup_decl (var, ctx);
16698 tree pvar = DECL_VALUE_EXPR (var);
16699 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16700 pvar = TREE_OPERAND (pvar, 0);
16701 gcc_assert (DECL_P (pvar));
16702 tree new_pvar = lookup_decl (pvar, ctx);
16703 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16704 tree al = size_int (DECL_ALIGN (var));
16705 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16706 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16707 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16708 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16709 gimple_seq_add_stmt (&new_body,
16710 gimple_build_assign (new_pvar, x));
16712 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16714 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16715 tree new_var = lookup_decl (var, ctx);
16716 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16717 if (TREE_CONSTANT (x))
16718 break;
16719 else
16721 tree atmp
16722 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16723 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16724 tree al = size_int (TYPE_ALIGN (rtype));
16725 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16728 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16729 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16730 gimple_seq_add_stmt (&new_body,
16731 gimple_build_assign (new_var, x));
16733 break;
16736 gimple_seq fork_seq = NULL;
16737 gimple_seq join_seq = NULL;
16739 if (is_oacc_parallel (ctx))
16741 /* If there are reductions on the offloaded region itself, treat
16742 them as a dummy GANG loop. */
16743 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16745 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16746 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16749 gimple_seq_add_seq (&new_body, fork_seq);
16750 gimple_seq_add_seq (&new_body, tgt_body);
16751 gimple_seq_add_seq (&new_body, join_seq);
16753 if (offloaded)
16754 new_body = maybe_catch_exception (new_body);
16756 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16757 gimple_omp_set_body (stmt, new_body);
16760 bind = gimple_build_bind (NULL, NULL,
16761 tgt_bind ? gimple_bind_block (tgt_bind)
16762 : NULL_TREE);
16763 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16764 gimple_bind_add_seq (bind, ilist);
16765 gimple_bind_add_stmt (bind, stmt);
16766 gimple_bind_add_seq (bind, olist);
16768 pop_gimplify_context (NULL);
16770 if (dep_bind)
16772 gimple_bind_add_seq (dep_bind, dep_ilist);
16773 gimple_bind_add_stmt (dep_bind, bind);
16774 gimple_bind_add_seq (dep_bind, dep_olist);
16775 pop_gimplify_context (dep_bind);
16779 /* Expand code for an OpenMP teams directive. */
16781 static void
16782 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16784 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16785 push_gimplify_context ();
16787 tree block = make_node (BLOCK);
16788 gbind *bind = gimple_build_bind (NULL, NULL, block);
16789 gsi_replace (gsi_p, bind, true);
16790 gimple_seq bind_body = NULL;
16791 gimple_seq dlist = NULL;
16792 gimple_seq olist = NULL;
16794 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16795 OMP_CLAUSE_NUM_TEAMS);
16796 if (num_teams == NULL_TREE)
16797 num_teams = build_int_cst (unsigned_type_node, 0);
16798 else
16800 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16801 num_teams = fold_convert (unsigned_type_node, num_teams);
16802 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16804 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16805 OMP_CLAUSE_THREAD_LIMIT);
16806 if (thread_limit == NULL_TREE)
16807 thread_limit = build_int_cst (unsigned_type_node, 0);
16808 else
16810 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16811 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16812 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16813 fb_rvalue);
16816 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16817 &bind_body, &dlist, ctx, NULL);
16818 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16819 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16820 if (!gimple_omp_teams_grid_phony (teams_stmt))
16822 gimple_seq_add_stmt (&bind_body, teams_stmt);
16823 location_t loc = gimple_location (teams_stmt);
16824 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16825 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16826 gimple_set_location (call, loc);
16827 gimple_seq_add_stmt (&bind_body, call);
16830 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16831 gimple_omp_set_body (teams_stmt, NULL);
16832 gimple_seq_add_seq (&bind_body, olist);
16833 gimple_seq_add_seq (&bind_body, dlist);
16834 if (!gimple_omp_teams_grid_phony (teams_stmt))
16835 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16836 gimple_bind_set_body (bind, bind_body);
16838 pop_gimplify_context (bind);
16840 gimple_bind_append_vars (bind, ctx->block_vars);
16841 BLOCK_VARS (block) = ctx->block_vars;
16842 if (BLOCK_VARS (block))
16843 TREE_USED (block) = 1;
16846 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16848 static void
16849 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16851 gimple *stmt = gsi_stmt (*gsi_p);
16852 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16853 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16854 gimple_build_omp_return (false));
16858 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16859 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16860 of OMP context, but with task_shared_vars set. */
16862 static tree
16863 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16864 void *data)
16866 tree t = *tp;
16868 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16869 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16870 return t;
16872 if (task_shared_vars
16873 && DECL_P (t)
16874 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16875 return t;
16877 /* If a global variable has been privatized, TREE_CONSTANT on
16878 ADDR_EXPR might be wrong. */
16879 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16880 recompute_tree_invariant_for_addr_expr (t);
16882 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16883 return NULL_TREE;
16886 /* Data to be communicated between lower_omp_regimplify_operands and
16887 lower_omp_regimplify_operands_p. */
16889 struct lower_omp_regimplify_operands_data
16891 omp_context *ctx;
16892 vec<tree> *decls;
16895 /* Helper function for lower_omp_regimplify_operands. Find
16896 omp_member_access_dummy_var vars and adjust temporarily their
16897 DECL_VALUE_EXPRs if needed. */
16899 static tree
16900 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16901 void *data)
16903 tree t = omp_member_access_dummy_var (*tp);
16904 if (t)
16906 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16907 lower_omp_regimplify_operands_data *ldata
16908 = (lower_omp_regimplify_operands_data *) wi->info;
16909 tree o = maybe_lookup_decl (t, ldata->ctx);
16910 if (o != t)
16912 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16913 ldata->decls->safe_push (*tp);
16914 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16915 SET_DECL_VALUE_EXPR (*tp, v);
16918 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16919 return NULL_TREE;
16922 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16923 of omp_member_access_dummy_var vars during regimplification. */
16925 static void
16926 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16927 gimple_stmt_iterator *gsi_p)
16929 auto_vec<tree, 10> decls;
16930 if (ctx)
16932 struct walk_stmt_info wi;
16933 memset (&wi, '\0', sizeof (wi));
16934 struct lower_omp_regimplify_operands_data data;
16935 data.ctx = ctx;
16936 data.decls = &decls;
16937 wi.info = &data;
16938 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16940 gimple_regimplify_operands (stmt, gsi_p);
16941 while (!decls.is_empty ())
16943 tree t = decls.pop ();
16944 tree v = decls.pop ();
16945 SET_DECL_VALUE_EXPR (t, v);
16949 static void
16950 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16952 gimple *stmt = gsi_stmt (*gsi_p);
16953 struct walk_stmt_info wi;
16954 gcall *call_stmt;
16956 if (gimple_has_location (stmt))
16957 input_location = gimple_location (stmt);
16959 if (task_shared_vars)
16960 memset (&wi, '\0', sizeof (wi));
16962 /* If we have issued syntax errors, avoid doing any heavy lifting.
16963 Just replace the OMP directives with a NOP to avoid
16964 confusing RTL expansion. */
16965 if (seen_error () && is_gimple_omp (stmt))
16967 gsi_replace (gsi_p, gimple_build_nop (), true);
16968 return;
16971 switch (gimple_code (stmt))
16973 case GIMPLE_COND:
16975 gcond *cond_stmt = as_a <gcond *> (stmt);
16976 if ((ctx || task_shared_vars)
16977 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16978 lower_omp_regimplify_p,
16979 ctx ? NULL : &wi, NULL)
16980 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16981 lower_omp_regimplify_p,
16982 ctx ? NULL : &wi, NULL)))
16983 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16985 break;
16986 case GIMPLE_CATCH:
16987 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16988 break;
16989 case GIMPLE_EH_FILTER:
16990 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16991 break;
16992 case GIMPLE_TRY:
16993 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16994 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16995 break;
16996 case GIMPLE_TRANSACTION:
16997 lower_omp (gimple_transaction_body_ptr (
16998 as_a <gtransaction *> (stmt)),
16999 ctx);
17000 break;
17001 case GIMPLE_BIND:
17002 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
17003 break;
17004 case GIMPLE_OMP_PARALLEL:
17005 case GIMPLE_OMP_TASK:
17006 ctx = maybe_lookup_ctx (stmt);
17007 gcc_assert (ctx);
17008 if (ctx->cancellable)
17009 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17010 lower_omp_taskreg (gsi_p, ctx);
17011 break;
17012 case GIMPLE_OMP_FOR:
17013 ctx = maybe_lookup_ctx (stmt);
17014 gcc_assert (ctx);
17015 if (ctx->cancellable)
17016 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17017 lower_omp_for (gsi_p, ctx);
17018 break;
17019 case GIMPLE_OMP_SECTIONS:
17020 ctx = maybe_lookup_ctx (stmt);
17021 gcc_assert (ctx);
17022 if (ctx->cancellable)
17023 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17024 lower_omp_sections (gsi_p, ctx);
17025 break;
17026 case GIMPLE_OMP_SINGLE:
17027 ctx = maybe_lookup_ctx (stmt);
17028 gcc_assert (ctx);
17029 lower_omp_single (gsi_p, ctx);
17030 break;
17031 case GIMPLE_OMP_MASTER:
17032 ctx = maybe_lookup_ctx (stmt);
17033 gcc_assert (ctx);
17034 lower_omp_master (gsi_p, ctx);
17035 break;
17036 case GIMPLE_OMP_TASKGROUP:
17037 ctx = maybe_lookup_ctx (stmt);
17038 gcc_assert (ctx);
17039 lower_omp_taskgroup (gsi_p, ctx);
17040 break;
17041 case GIMPLE_OMP_ORDERED:
17042 ctx = maybe_lookup_ctx (stmt);
17043 gcc_assert (ctx);
17044 lower_omp_ordered (gsi_p, ctx);
17045 break;
17046 case GIMPLE_OMP_CRITICAL:
17047 ctx = maybe_lookup_ctx (stmt);
17048 gcc_assert (ctx);
17049 lower_omp_critical (gsi_p, ctx);
17050 break;
17051 case GIMPLE_OMP_ATOMIC_LOAD:
17052 if ((ctx || task_shared_vars)
17053 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17054 as_a <gomp_atomic_load *> (stmt)),
17055 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17056 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17057 break;
17058 case GIMPLE_OMP_TARGET:
17059 ctx = maybe_lookup_ctx (stmt);
17060 gcc_assert (ctx);
17061 lower_omp_target (gsi_p, ctx);
17062 break;
17063 case GIMPLE_OMP_TEAMS:
17064 ctx = maybe_lookup_ctx (stmt);
17065 gcc_assert (ctx);
17066 lower_omp_teams (gsi_p, ctx);
17067 break;
17068 case GIMPLE_OMP_GRID_BODY:
17069 ctx = maybe_lookup_ctx (stmt);
17070 gcc_assert (ctx);
17071 lower_omp_grid_body (gsi_p, ctx);
17072 break;
17073 case GIMPLE_CALL:
17074 tree fndecl;
17075 call_stmt = as_a <gcall *> (stmt);
17076 fndecl = gimple_call_fndecl (call_stmt);
17077 if (fndecl
17078 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17079 switch (DECL_FUNCTION_CODE (fndecl))
17081 case BUILT_IN_GOMP_BARRIER:
17082 if (ctx == NULL)
17083 break;
17084 /* FALLTHRU */
17085 case BUILT_IN_GOMP_CANCEL:
17086 case BUILT_IN_GOMP_CANCELLATION_POINT:
17087 omp_context *cctx;
17088 cctx = ctx;
17089 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17090 cctx = cctx->outer;
17091 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17092 if (!cctx->cancellable)
17094 if (DECL_FUNCTION_CODE (fndecl)
17095 == BUILT_IN_GOMP_CANCELLATION_POINT)
17097 stmt = gimple_build_nop ();
17098 gsi_replace (gsi_p, stmt, false);
17100 break;
17102 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17104 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17105 gimple_call_set_fndecl (call_stmt, fndecl);
17106 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17108 tree lhs;
17109 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17110 gimple_call_set_lhs (call_stmt, lhs);
17111 tree fallthru_label;
17112 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17113 gimple *g;
17114 g = gimple_build_label (fallthru_label);
17115 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17116 g = gimple_build_cond (NE_EXPR, lhs,
17117 fold_convert (TREE_TYPE (lhs),
17118 boolean_false_node),
17119 cctx->cancel_label, fallthru_label);
17120 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17121 break;
17122 default:
17123 break;
17125 /* FALLTHRU */
17126 default:
17127 if ((ctx || task_shared_vars)
17128 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17129 ctx ? NULL : &wi))
17131 /* Just remove clobbers, this should happen only if we have
17132 "privatized" local addressable variables in SIMD regions,
17133 the clobber isn't needed in that case and gimplifying address
17134 of the ARRAY_REF into a pointer and creating MEM_REF based
17135 clobber would create worse code than we get with the clobber
17136 dropped. */
17137 if (gimple_clobber_p (stmt))
17139 gsi_replace (gsi_p, gimple_build_nop (), true);
17140 break;
17142 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17144 break;
17148 static void
17149 lower_omp (gimple_seq *body, omp_context *ctx)
17151 location_t saved_location = input_location;
17152 gimple_stmt_iterator gsi;
17153 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17154 lower_omp_1 (&gsi, ctx);
17155 /* During gimplification, we haven't folded statments inside offloading
17156 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17157 if (target_nesting_level || taskreg_nesting_level)
17158 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17159 fold_stmt (&gsi);
17160 input_location = saved_location;
17163 /* Returen true if STMT is an assignment of a register-type into a local
17164 VAR_DECL. */
17166 static bool
17167 grid_reg_assignment_to_local_var_p (gimple *stmt)
17169 gassign *assign = dyn_cast <gassign *> (stmt);
17170 if (!assign)
17171 return false;
17172 tree lhs = gimple_assign_lhs (assign);
17173 if (TREE_CODE (lhs) != VAR_DECL
17174 || !is_gimple_reg_type (TREE_TYPE (lhs))
17175 || is_global_var (lhs))
17176 return false;
17177 return true;
17180 /* Return true if all statements in SEQ are assignments to local register-type
17181 variables. */
17183 static bool
17184 grid_seq_only_contains_local_assignments (gimple_seq seq)
17186 if (!seq)
17187 return true;
17189 gimple_stmt_iterator gsi;
17190 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17191 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17192 return false;
17193 return true;
17196 /* Scan statements in SEQ and call itself recursively on any bind. If during
17197 whole search only assignments to register-type local variables and one
17198 single OMP statement is encountered, return true, otherwise return false.
17199 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17200 are used for dumping a note about a failure. */
17202 static bool
17203 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17204 const char *name, gimple **ret)
17206 gimple_stmt_iterator gsi;
17207 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17209 gimple *stmt = gsi_stmt (gsi);
17211 if (grid_reg_assignment_to_local_var_p (stmt))
17212 continue;
17213 if (gbind *bind = dyn_cast <gbind *> (stmt))
17215 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17216 target_loc, name, ret))
17217 return false;
17219 else if (is_gimple_omp (stmt))
17221 if (*ret)
17223 if (dump_enabled_p ())
17224 dump_printf_loc (MSG_NOTE, target_loc,
17225 "Will not turn target construct into a simple "
17226 "GPGPU kernel because %s construct contains "
17227 "multiple OpenMP constructs\n", name);
17228 return false;
17230 *ret = stmt;
17232 else
17234 if (dump_enabled_p ())
17235 dump_printf_loc (MSG_NOTE, target_loc,
17236 "Will not turn target construct into a simple "
17237 "GPGPU kernel because %s construct contains "
17238 "a complex statement\n", name);
17239 return false;
17242 return true;
17245 /* Scan statements in SEQ and make sure that it and any binds in it contain
17246 only assignments to local register-type variables and one OMP construct. If
17247 so, return that construct, otherwise return NULL. If dumping is enabled and
17248 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17249 failure. */
17251 static gimple *
17252 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17253 const char *name)
17255 if (!seq)
17257 if (dump_enabled_p ())
17258 dump_printf_loc (MSG_NOTE, target_loc,
17259 "Will not turn target construct into a simple "
17260 "GPGPU kernel because %s construct has empty "
17261 "body\n",
17262 name);
17263 return NULL;
17266 gimple *ret = NULL;
17267 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17269 if (!ret && dump_enabled_p ())
17270 dump_printf_loc (MSG_NOTE, target_loc,
17271 "Will not turn target construct into a simple "
17272 "GPGPU kernel because %s construct does not contain"
17273 "any other OpenMP construct\n", name);
17274 return ret;
17276 else
17277 return NULL;
17280 /* Walker function looking for statements there is no point gridifying (and for
17281 noreturn function calls which we cannot do). Return non-NULL if such a
17282 function is found. */
17284 static tree
17285 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17286 bool *handled_ops_p,
17287 struct walk_stmt_info *wi)
17289 *handled_ops_p = false;
17290 gimple *stmt = gsi_stmt (*gsi);
17291 switch (gimple_code (stmt))
17293 case GIMPLE_CALL:
17294 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17296 *handled_ops_p = true;
17297 wi->info = stmt;
17298 return error_mark_node;
17300 break;
17302 /* We may reduce the following list if we find a way to implement the
17303 clauses, but now there is no point trying further. */
17304 case GIMPLE_OMP_CRITICAL:
17305 case GIMPLE_OMP_TASKGROUP:
17306 case GIMPLE_OMP_TASK:
17307 case GIMPLE_OMP_SECTION:
17308 case GIMPLE_OMP_SECTIONS:
17309 case GIMPLE_OMP_SECTIONS_SWITCH:
17310 case GIMPLE_OMP_TARGET:
17311 case GIMPLE_OMP_ORDERED:
17312 *handled_ops_p = true;
17313 wi->info = stmt;
17314 return error_mark_node;
17316 case GIMPLE_OMP_FOR:
17317 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17318 && gimple_omp_for_combined_into_p (stmt))
17320 *handled_ops_p = true;
17321 wi->info = stmt;
17322 return error_mark_node;
17324 break;
17326 default:
17327 break;
17329 return NULL;
17333 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17334 kernel, return true, otherwise return false. In the case of success, also
17335 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17336 none. */
17338 static bool
17339 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17341 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17342 return false;
17344 location_t tloc = gimple_location (target);
17345 gimple *stmt
17346 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17347 tloc, "target");
17348 if (!stmt)
17349 return false;
17350 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17351 tree group_size = NULL;
17352 if (!teams)
17354 dump_printf_loc (MSG_NOTE, tloc,
17355 "Will not turn target construct into a simple "
17356 "GPGPU kernel because it does not have a sole teams "
17357 "construct in it.\n");
17358 return false;
17361 tree clauses = gimple_omp_teams_clauses (teams);
17362 while (clauses)
17364 switch (OMP_CLAUSE_CODE (clauses))
17366 case OMP_CLAUSE_NUM_TEAMS:
17367 if (dump_enabled_p ())
17368 dump_printf_loc (MSG_NOTE, tloc,
17369 "Will not turn target construct into a "
17370 "gridified GPGPU kernel because we cannot "
17371 "handle num_teams clause of teams "
17372 "construct\n ");
17373 return false;
17375 case OMP_CLAUSE_REDUCTION:
17376 if (dump_enabled_p ())
17377 dump_printf_loc (MSG_NOTE, tloc,
17378 "Will not turn target construct into a "
17379 "gridified GPGPU kernel because a reduction "
17380 "clause is present\n ");
17381 return false;
17383 case OMP_CLAUSE_LASTPRIVATE:
17384 if (dump_enabled_p ())
17385 dump_printf_loc (MSG_NOTE, tloc,
17386 "Will not turn target construct into a "
17387 "gridified GPGPU kernel because a lastprivate "
17388 "clause is present\n ");
17389 return false;
17391 case OMP_CLAUSE_THREAD_LIMIT:
17392 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17393 break;
17395 default:
17396 break;
17398 clauses = OMP_CLAUSE_CHAIN (clauses);
17401 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17402 "teams");
17403 if (!stmt)
17404 return false;
17405 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17406 if (!dist)
17408 dump_printf_loc (MSG_NOTE, tloc,
17409 "Will not turn target construct into a simple "
17410 "GPGPU kernel because the teams construct does not have "
17411 "a sole distribute construct in it.\n");
17412 return false;
17415 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17416 if (!gimple_omp_for_combined_p (dist))
17418 if (dump_enabled_p ())
17419 dump_printf_loc (MSG_NOTE, tloc,
17420 "Will not turn target construct into a gridified GPGPU "
17421 "kernel because we cannot handle a standalone "
17422 "distribute construct\n ");
17423 return false;
17425 if (dist->collapse > 1)
17427 if (dump_enabled_p ())
17428 dump_printf_loc (MSG_NOTE, tloc,
17429 "Will not turn target construct into a gridified GPGPU "
17430 "kernel because the distribute construct contains "
17431 "collapse clause\n");
17432 return false;
17434 struct omp_for_data fd;
17435 extract_omp_for_data (dist, &fd, NULL);
17436 if (fd.chunk_size)
17438 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17440 if (dump_enabled_p ())
17441 dump_printf_loc (MSG_NOTE, tloc,
17442 "Will not turn target construct into a "
17443 "gridified GPGPU kernel because the teams "
17444 "thread limit is different from distribute "
17445 "schedule chunk\n");
17446 return false;
17448 group_size = fd.chunk_size;
17450 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17451 "distribute");
17452 gomp_parallel *par;
17453 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17454 return false;
17456 clauses = gimple_omp_parallel_clauses (par);
17457 while (clauses)
17459 switch (OMP_CLAUSE_CODE (clauses))
17461 case OMP_CLAUSE_NUM_THREADS:
17462 if (dump_enabled_p ())
17463 dump_printf_loc (MSG_NOTE, tloc,
17464 "Will not turn target construct into a gridified"
17465 "GPGPU kernel because there is a num_threads "
17466 "clause of the parallel construct\n");
17467 return false;
17469 case OMP_CLAUSE_REDUCTION:
17470 if (dump_enabled_p ())
17471 dump_printf_loc (MSG_NOTE, tloc,
17472 "Will not turn target construct into a "
17473 "gridified GPGPU kernel because a reduction "
17474 "clause is present\n ");
17475 return false;
17477 case OMP_CLAUSE_LASTPRIVATE:
17478 if (dump_enabled_p ())
17479 dump_printf_loc (MSG_NOTE, tloc,
17480 "Will not turn target construct into a "
17481 "gridified GPGPU kernel because a lastprivate "
17482 "clause is present\n ");
17483 return false;
17485 default:
17486 break;
17488 clauses = OMP_CLAUSE_CHAIN (clauses);
17491 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17492 "parallel");
17493 gomp_for *gfor;
17494 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17495 return false;
17497 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17499 if (dump_enabled_p ())
17500 dump_printf_loc (MSG_NOTE, tloc,
17501 "Will not turn target construct into a gridified GPGPU "
17502 "kernel because the inner loop is not a simple for "
17503 "loop\n");
17504 return false;
17506 if (gfor->collapse > 1)
17508 if (dump_enabled_p ())
17509 dump_printf_loc (MSG_NOTE, tloc,
17510 "Will not turn target construct into a gridified GPGPU "
17511 "kernel because the inner loop contains collapse "
17512 "clause\n");
17513 return false;
17516 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17518 if (dump_enabled_p ())
17519 dump_printf_loc (MSG_NOTE, tloc,
17520 "Will not turn target construct into a gridified GPGPU "
17521 "kernel because the inner loop pre_body contains"
17522 "a complex instruction\n");
17523 return false;
17526 clauses = gimple_omp_for_clauses (gfor);
17527 while (clauses)
17529 switch (OMP_CLAUSE_CODE (clauses))
17531 case OMP_CLAUSE_SCHEDULE:
17532 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17534 if (dump_enabled_p ())
17535 dump_printf_loc (MSG_NOTE, tloc,
17536 "Will not turn target construct into a "
17537 "gridified GPGPU kernel because the inner "
17538 "loop has a non-automatic scheduling clause\n");
17539 return false;
17541 break;
17543 case OMP_CLAUSE_REDUCTION:
17544 if (dump_enabled_p ())
17545 dump_printf_loc (MSG_NOTE, tloc,
17546 "Will not turn target construct into a "
17547 "gridified GPGPU kernel because a reduction "
17548 "clause is present\n ");
17549 return false;
17551 case OMP_CLAUSE_LASTPRIVATE:
17552 if (dump_enabled_p ())
17553 dump_printf_loc (MSG_NOTE, tloc,
17554 "Will not turn target construct into a "
17555 "gridified GPGPU kernel because a lastprivate "
17556 "clause is present\n ");
17557 return false;
17559 default:
17560 break;
17562 clauses = OMP_CLAUSE_CHAIN (clauses);
17565 struct walk_stmt_info wi;
17566 memset (&wi, 0, sizeof (wi));
17567 if (walk_gimple_seq (gimple_omp_body (gfor),
17568 grid_find_ungridifiable_statement,
17569 NULL, &wi))
17571 gimple *bad = (gimple *) wi.info;
17572 if (dump_enabled_p ())
17574 if (is_gimple_call (bad))
17575 dump_printf_loc (MSG_NOTE, tloc,
17576 "Will not turn target construct into a gridified "
17577 " GPGPU kernel because the inner loop contains "
17578 "call to a noreturn function\n");
17579 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17580 dump_printf_loc (MSG_NOTE, tloc,
17581 "Will not turn target construct into a gridified "
17582 " GPGPU kernel because the inner loop contains "
17583 "a simd construct\n");
17584 else
17585 dump_printf_loc (MSG_NOTE, tloc,
17586 "Will not turn target construct into a gridified "
17587 "GPGPU kernel because the inner loop contains "
17588 "statement %s which cannot be transformed\n",
17589 gimple_code_name[(int) gimple_code (bad)]);
17591 return false;
17594 *group_size_p = group_size;
17595 return true;
17598 /* Operand walker, used to remap pre-body declarations according to a hash map
17599 provided in DATA. */
17601 static tree
17602 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17604 tree t = *tp;
17606 if (DECL_P (t) || TYPE_P (t))
17607 *walk_subtrees = 0;
17608 else
17609 *walk_subtrees = 1;
17611 if (TREE_CODE (t) == VAR_DECL)
17613 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17614 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17615 tree *repl = declmap->get (t);
17616 if (repl)
17617 *tp = *repl;
17619 return NULL_TREE;
17622 /* Copy leading register-type assignments to local variables in SRC to just
17623 before DST, Creating temporaries, adjusting mapping of operands in WI and
17624 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17625 Return the first statement that does not conform to
17626 grid_reg_assignment_to_local_var_p or NULL. */
17628 static gimple *
17629 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17630 gbind *tgt_bind, struct walk_stmt_info *wi)
17632 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17633 gimple_stmt_iterator gsi;
17634 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17636 gimple *stmt = gsi_stmt (gsi);
17637 if (gbind *bind = dyn_cast <gbind *> (stmt))
17639 gimple *r = grid_copy_leading_local_assignments
17640 (gimple_bind_body (bind), dst, tgt_bind, wi);
17641 if (r)
17642 return r;
17643 else
17644 continue;
17646 if (!grid_reg_assignment_to_local_var_p (stmt))
17647 return stmt;
17648 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17649 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17650 TREE_TYPE (lhs));
17651 DECL_CONTEXT (repl) = current_function_decl;
17652 gimple_bind_append_vars (tgt_bind, repl);
17654 declmap->put (lhs, repl);
17655 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17656 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17657 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17659 return NULL;
17662 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17663 components, mark them as part of kernel and return the inner loop, and copy
17664 assignment leading to them just before DST, remapping them using WI and
17665 adding new temporaries to TGT_BIND. */
17667 static gomp_for *
17668 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17669 gbind *tgt_bind, struct walk_stmt_info *wi)
17671 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17672 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17673 gcc_assert (teams);
17674 gimple_omp_teams_set_grid_phony (teams, true);
17675 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17676 tgt_bind, wi);
17677 gcc_checking_assert (stmt);
17678 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17679 gcc_assert (dist);
17680 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17681 if (prebody)
17682 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17683 gimple_omp_for_set_grid_phony (dist, true);
17684 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17685 tgt_bind, wi);
17686 gcc_checking_assert (stmt);
17688 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17689 gimple_omp_parallel_set_grid_phony (parallel, true);
17690 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17691 tgt_bind, wi);
17692 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17693 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17694 prebody = gimple_omp_for_pre_body (inner_loop);
17695 if (prebody)
17696 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17698 return inner_loop;
17701 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17702 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17703 is the bind into which temporaries inserted before TARGET should be
17704 added. */
17706 static void
17707 grid_attempt_target_gridification (gomp_target *target,
17708 gimple_stmt_iterator *gsi,
17709 gbind *tgt_bind)
17711 tree group_size;
17712 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17713 return;
17715 location_t loc = gimple_location (target);
17716 if (dump_enabled_p ())
17717 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17718 "Target construct will be turned into a gridified GPGPU "
17719 "kernel\n");
17721 /* Copy target body to a GPUKERNEL construct: */
17722 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17723 (gimple_omp_body (target));
17725 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17726 struct walk_stmt_info wi;
17727 memset (&wi, 0, sizeof (struct walk_stmt_info));
17728 wi.info = declmap;
17730 /* Copy assignments in between OMP statements before target, mark OMP
17731 statements within copy appropriatly. */
17732 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17733 tgt_bind, &wi);
17735 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17736 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17737 tree new_block = gimple_bind_block (new_bind);
17738 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17739 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17740 BLOCK_SUBBLOCKS (enc_block) = new_block;
17741 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17742 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17743 gimple_seq_add_stmt
17744 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17745 gpukernel);
17747 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17748 push_gimplify_context ();
17749 size_t collapse = gimple_omp_for_collapse (inner_loop);
17750 for (size_t i = 0; i < collapse; i++)
17752 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17753 if (POINTER_TYPE_P (type))
17754 itype = signed_type_for (type);
17755 else
17756 itype = type;
17758 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17759 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17760 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17761 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17762 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17763 adjust_for_condition (loc, &cond_code, &n2);
17764 tree step;
17765 step = get_omp_for_step_from_incr (loc,
17766 gimple_omp_for_incr (inner_loop, i));
17767 gimple_seq tmpseq = NULL;
17768 n1 = fold_convert (itype, n1);
17769 n2 = fold_convert (itype, n2);
17770 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17771 t = fold_build2 (PLUS_EXPR, itype, step, t);
17772 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17773 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17774 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17775 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17776 fold_build1 (NEGATE_EXPR, itype, t),
17777 fold_build1 (NEGATE_EXPR, itype, step));
17778 else
17779 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17780 tree gs = fold_convert (uint32_type_node, t);
17781 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17782 if (!gimple_seq_empty_p (tmpseq))
17783 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17785 tree ws;
17786 if (i == 0 && group_size)
17788 ws = fold_convert (uint32_type_node, group_size);
17789 tmpseq = NULL;
17790 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17791 if (!gimple_seq_empty_p (tmpseq))
17792 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17794 else
17795 ws = build_zero_cst (uint32_type_node);
17797 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17798 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17799 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17800 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17801 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17802 gimple_omp_target_set_clauses (target, c);
17804 pop_gimplify_context (tgt_bind);
17805 delete declmap;
17806 return;
17809 /* Walker function doing all the work for create_target_kernels. */
17811 static tree
17812 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17813 bool *handled_ops_p,
17814 struct walk_stmt_info *incoming)
17816 *handled_ops_p = false;
17818 gimple *stmt = gsi_stmt (*gsi);
17819 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17820 if (target)
17822 gbind *tgt_bind = (gbind *) incoming->info;
17823 gcc_checking_assert (tgt_bind);
17824 grid_attempt_target_gridification (target, gsi, tgt_bind);
17825 return NULL_TREE;
17827 gbind *bind = dyn_cast <gbind *> (stmt);
17828 if (bind)
17830 *handled_ops_p = true;
17831 struct walk_stmt_info wi;
17832 memset (&wi, 0, sizeof (wi));
17833 wi.info = bind;
17834 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17835 grid_gridify_all_targets_stmt, NULL, &wi);
17837 return NULL_TREE;
17840 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17841 have their bodies duplicated, with the new copy being put into a
17842 gimple_omp_grid_body statement. All kernel-related construct within the
17843 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17844 re-structuring is often needed, such as copying pre-bodies before the target
17845 construct so that kernel grid sizes can be computed. */
17847 static void
17848 grid_gridify_all_targets (gimple_seq *body_p)
17850 struct walk_stmt_info wi;
17851 memset (&wi, 0, sizeof (wi));
17852 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17856 /* Main entry point. */
17858 static unsigned int
17859 execute_lower_omp (void)
17861 gimple_seq body;
17862 int i;
17863 omp_context *ctx;
17865 /* This pass always runs, to provide PROP_gimple_lomp.
17866 But often, there is nothing to do. */
17867 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17868 && flag_openmp_simd == 0)
17869 return 0;
17871 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17872 delete_omp_context);
17874 body = gimple_body (current_function_decl);
17876 if (hsa_gen_requested_p ())
17877 grid_gridify_all_targets (&body);
17879 scan_omp (&body, NULL);
17880 gcc_assert (taskreg_nesting_level == 0);
17881 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17882 finish_taskreg_scan (ctx);
17883 taskreg_contexts.release ();
17885 if (all_contexts->root)
17887 if (task_shared_vars)
17888 push_gimplify_context ();
17889 lower_omp (&body, NULL);
17890 if (task_shared_vars)
17891 pop_gimplify_context (NULL);
17894 if (all_contexts)
17896 splay_tree_delete (all_contexts);
17897 all_contexts = NULL;
17899 BITMAP_FREE (task_shared_vars);
17900 return 0;
17903 namespace {
17905 const pass_data pass_data_lower_omp =
17907 GIMPLE_PASS, /* type */
17908 "omplower", /* name */
17909 OPTGROUP_NONE, /* optinfo_flags */
17910 TV_NONE, /* tv_id */
17911 PROP_gimple_any, /* properties_required */
17912 PROP_gimple_lomp, /* properties_provided */
17913 0, /* properties_destroyed */
17914 0, /* todo_flags_start */
17915 0, /* todo_flags_finish */
17918 class pass_lower_omp : public gimple_opt_pass
17920 public:
17921 pass_lower_omp (gcc::context *ctxt)
17922 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17925 /* opt_pass methods: */
17926 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17928 }; // class pass_lower_omp
17930 } // anon namespace
17932 gimple_opt_pass *
17933 make_pass_lower_omp (gcc::context *ctxt)
17935 return new pass_lower_omp (ctxt);
17938 /* The following is a utility to diagnose structured block violations.
17939 It is not part of the "omplower" pass, as that's invoked too late. It
17940 should be invoked by the respective front ends after gimplification. */
17942 static splay_tree all_labels;
17944 /* Check for mismatched contexts and generate an error if needed. Return
17945 true if an error is detected. */
17947 static bool
17948 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17949 gimple *branch_ctx, gimple *label_ctx)
17951 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17952 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17954 if (label_ctx == branch_ctx)
17955 return false;
17957 const char* kind = NULL;
17959 if (flag_cilkplus)
17961 if ((branch_ctx
17962 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17963 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17964 || (label_ctx
17965 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17966 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17967 kind = "Cilk Plus";
17969 if (flag_openacc)
17971 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17972 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17974 gcc_checking_assert (kind == NULL);
17975 kind = "OpenACC";
17978 if (kind == NULL)
17980 gcc_checking_assert (flag_openmp);
17981 kind = "OpenMP";
17985 Previously we kept track of the label's entire context in diagnose_sb_[12]
17986 so we could traverse it and issue a correct "exit" or "enter" error
17987 message upon a structured block violation.
17989 We built the context by building a list with tree_cons'ing, but there is
17990 no easy counterpart in gimple tuples. It seems like far too much work
17991 for issuing exit/enter error messages. If someone really misses the
17992 distinct error message... patches welcome.
17995 #if 0
17996 /* Try to avoid confusing the user by producing and error message
17997 with correct "exit" or "enter" verbiage. We prefer "exit"
17998 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
17999 if (branch_ctx == NULL)
18000 exit_p = false;
18001 else
18003 while (label_ctx)
18005 if (TREE_VALUE (label_ctx) == branch_ctx)
18007 exit_p = false;
18008 break;
18010 label_ctx = TREE_CHAIN (label_ctx);
18014 if (exit_p)
18015 error ("invalid exit from %s structured block", kind);
18016 else
18017 error ("invalid entry to %s structured block", kind);
18018 #endif
18020 /* If it's obvious we have an invalid entry, be specific about the error. */
18021 if (branch_ctx == NULL)
18022 error ("invalid entry to %s structured block", kind);
18023 else
18025 /* Otherwise, be vague and lazy, but efficient. */
18026 error ("invalid branch to/from %s structured block", kind);
18029 gsi_replace (gsi_p, gimple_build_nop (), false);
18030 return true;
18033 /* Pass 1: Create a minimal tree of structured blocks, and record
18034 where each label is found. */
18036 static tree
18037 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18038 struct walk_stmt_info *wi)
18040 gimple *context = (gimple *) wi->info;
18041 gimple *inner_context;
18042 gimple *stmt = gsi_stmt (*gsi_p);
18044 *handled_ops_p = true;
18046 switch (gimple_code (stmt))
18048 WALK_SUBSTMTS;
18050 case GIMPLE_OMP_PARALLEL:
18051 case GIMPLE_OMP_TASK:
18052 case GIMPLE_OMP_SECTIONS:
18053 case GIMPLE_OMP_SINGLE:
18054 case GIMPLE_OMP_SECTION:
18055 case GIMPLE_OMP_MASTER:
18056 case GIMPLE_OMP_ORDERED:
18057 case GIMPLE_OMP_CRITICAL:
18058 case GIMPLE_OMP_TARGET:
18059 case GIMPLE_OMP_TEAMS:
18060 case GIMPLE_OMP_TASKGROUP:
18061 /* The minimal context here is just the current OMP construct. */
18062 inner_context = stmt;
18063 wi->info = inner_context;
18064 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18065 wi->info = context;
18066 break;
18068 case GIMPLE_OMP_FOR:
18069 inner_context = stmt;
18070 wi->info = inner_context;
18071 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18072 walk them. */
18073 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18074 diagnose_sb_1, NULL, wi);
18075 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18076 wi->info = context;
18077 break;
18079 case GIMPLE_LABEL:
18080 splay_tree_insert (all_labels,
18081 (splay_tree_key) gimple_label_label (
18082 as_a <glabel *> (stmt)),
18083 (splay_tree_value) context);
18084 break;
18086 default:
18087 break;
18090 return NULL_TREE;
18093 /* Pass 2: Check each branch and see if its context differs from that of
18094 the destination label's context. */
18096 static tree
18097 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18098 struct walk_stmt_info *wi)
18100 gimple *context = (gimple *) wi->info;
18101 splay_tree_node n;
18102 gimple *stmt = gsi_stmt (*gsi_p);
18104 *handled_ops_p = true;
18106 switch (gimple_code (stmt))
18108 WALK_SUBSTMTS;
18110 case GIMPLE_OMP_PARALLEL:
18111 case GIMPLE_OMP_TASK:
18112 case GIMPLE_OMP_SECTIONS:
18113 case GIMPLE_OMP_SINGLE:
18114 case GIMPLE_OMP_SECTION:
18115 case GIMPLE_OMP_MASTER:
18116 case GIMPLE_OMP_ORDERED:
18117 case GIMPLE_OMP_CRITICAL:
18118 case GIMPLE_OMP_TARGET:
18119 case GIMPLE_OMP_TEAMS:
18120 case GIMPLE_OMP_TASKGROUP:
18121 wi->info = stmt;
18122 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18123 wi->info = context;
18124 break;
18126 case GIMPLE_OMP_FOR:
18127 wi->info = stmt;
18128 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18129 walk them. */
18130 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18131 diagnose_sb_2, NULL, wi);
18132 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18133 wi->info = context;
18134 break;
18136 case GIMPLE_COND:
18138 gcond *cond_stmt = as_a <gcond *> (stmt);
18139 tree lab = gimple_cond_true_label (cond_stmt);
18140 if (lab)
18142 n = splay_tree_lookup (all_labels,
18143 (splay_tree_key) lab);
18144 diagnose_sb_0 (gsi_p, context,
18145 n ? (gimple *) n->value : NULL);
18147 lab = gimple_cond_false_label (cond_stmt);
18148 if (lab)
18150 n = splay_tree_lookup (all_labels,
18151 (splay_tree_key) lab);
18152 diagnose_sb_0 (gsi_p, context,
18153 n ? (gimple *) n->value : NULL);
18156 break;
18158 case GIMPLE_GOTO:
18160 tree lab = gimple_goto_dest (stmt);
18161 if (TREE_CODE (lab) != LABEL_DECL)
18162 break;
18164 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18165 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18167 break;
18169 case GIMPLE_SWITCH:
18171 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18172 unsigned int i;
18173 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18175 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18176 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18177 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18178 break;
18181 break;
18183 case GIMPLE_RETURN:
18184 diagnose_sb_0 (gsi_p, context, NULL);
18185 break;
18187 default:
18188 break;
18191 return NULL_TREE;
18194 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18195 GIMPLE_* codes. */
18196 bool
18197 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18198 int *region_idx)
18200 gimple *last = last_stmt (bb);
18201 enum gimple_code code = gimple_code (last);
18202 struct omp_region *cur_region = *region;
18203 bool fallthru = false;
18205 switch (code)
18207 case GIMPLE_OMP_PARALLEL:
18208 case GIMPLE_OMP_TASK:
18209 case GIMPLE_OMP_FOR:
18210 case GIMPLE_OMP_SINGLE:
18211 case GIMPLE_OMP_TEAMS:
18212 case GIMPLE_OMP_MASTER:
18213 case GIMPLE_OMP_TASKGROUP:
18214 case GIMPLE_OMP_CRITICAL:
18215 case GIMPLE_OMP_SECTION:
18216 case GIMPLE_OMP_GRID_BODY:
18217 cur_region = new_omp_region (bb, code, cur_region);
18218 fallthru = true;
18219 break;
18221 case GIMPLE_OMP_ORDERED:
18222 cur_region = new_omp_region (bb, code, cur_region);
18223 fallthru = true;
18224 if (find_omp_clause (gimple_omp_ordered_clauses
18225 (as_a <gomp_ordered *> (last)),
18226 OMP_CLAUSE_DEPEND))
18227 cur_region = cur_region->outer;
18228 break;
18230 case GIMPLE_OMP_TARGET:
18231 cur_region = new_omp_region (bb, code, cur_region);
18232 fallthru = true;
18233 switch (gimple_omp_target_kind (last))
18235 case GF_OMP_TARGET_KIND_REGION:
18236 case GF_OMP_TARGET_KIND_DATA:
18237 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18238 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18239 case GF_OMP_TARGET_KIND_OACC_DATA:
18240 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18241 break;
18242 case GF_OMP_TARGET_KIND_UPDATE:
18243 case GF_OMP_TARGET_KIND_ENTER_DATA:
18244 case GF_OMP_TARGET_KIND_EXIT_DATA:
18245 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18246 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18247 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18248 cur_region = cur_region->outer;
18249 break;
18250 default:
18251 gcc_unreachable ();
18253 break;
18255 case GIMPLE_OMP_SECTIONS:
18256 cur_region = new_omp_region (bb, code, cur_region);
18257 fallthru = true;
18258 break;
18260 case GIMPLE_OMP_SECTIONS_SWITCH:
18261 fallthru = false;
18262 break;
18264 case GIMPLE_OMP_ATOMIC_LOAD:
18265 case GIMPLE_OMP_ATOMIC_STORE:
18266 fallthru = true;
18267 break;
18269 case GIMPLE_OMP_RETURN:
18270 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18271 somewhere other than the next block. This will be
18272 created later. */
18273 cur_region->exit = bb;
18274 if (cur_region->type == GIMPLE_OMP_TASK)
18275 /* Add an edge corresponding to not scheduling the task
18276 immediately. */
18277 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18278 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18279 cur_region = cur_region->outer;
18280 break;
18282 case GIMPLE_OMP_CONTINUE:
18283 cur_region->cont = bb;
18284 switch (cur_region->type)
18286 case GIMPLE_OMP_FOR:
18287 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18288 succs edges as abnormal to prevent splitting
18289 them. */
18290 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18291 /* Make the loopback edge. */
18292 make_edge (bb, single_succ (cur_region->entry),
18293 EDGE_ABNORMAL);
18295 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18296 corresponds to the case that the body of the loop
18297 is not executed at all. */
18298 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18299 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18300 fallthru = false;
18301 break;
18303 case GIMPLE_OMP_SECTIONS:
18304 /* Wire up the edges into and out of the nested sections. */
18306 basic_block switch_bb = single_succ (cur_region->entry);
18308 struct omp_region *i;
18309 for (i = cur_region->inner; i ; i = i->next)
18311 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18312 make_edge (switch_bb, i->entry, 0);
18313 make_edge (i->exit, bb, EDGE_FALLTHRU);
18316 /* Make the loopback edge to the block with
18317 GIMPLE_OMP_SECTIONS_SWITCH. */
18318 make_edge (bb, switch_bb, 0);
18320 /* Make the edge from the switch to exit. */
18321 make_edge (switch_bb, bb->next_bb, 0);
18322 fallthru = false;
18324 break;
18326 case GIMPLE_OMP_TASK:
18327 fallthru = true;
18328 break;
18330 default:
18331 gcc_unreachable ();
18333 break;
18335 default:
18336 gcc_unreachable ();
18339 if (*region != cur_region)
18341 *region = cur_region;
18342 if (cur_region)
18343 *region_idx = cur_region->entry->index;
18344 else
18345 *region_idx = 0;
18348 return fallthru;
18351 static unsigned int
18352 diagnose_omp_structured_block_errors (void)
18354 struct walk_stmt_info wi;
18355 gimple_seq body = gimple_body (current_function_decl);
18357 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18359 memset (&wi, 0, sizeof (wi));
18360 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18362 memset (&wi, 0, sizeof (wi));
18363 wi.want_locations = true;
18364 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18366 gimple_set_body (current_function_decl, body);
18368 splay_tree_delete (all_labels);
18369 all_labels = NULL;
18371 return 0;
18374 namespace {
18376 const pass_data pass_data_diagnose_omp_blocks =
18378 GIMPLE_PASS, /* type */
18379 "*diagnose_omp_blocks", /* name */
18380 OPTGROUP_NONE, /* optinfo_flags */
18381 TV_NONE, /* tv_id */
18382 PROP_gimple_any, /* properties_required */
18383 0, /* properties_provided */
18384 0, /* properties_destroyed */
18385 0, /* todo_flags_start */
18386 0, /* todo_flags_finish */
18389 class pass_diagnose_omp_blocks : public gimple_opt_pass
18391 public:
18392 pass_diagnose_omp_blocks (gcc::context *ctxt)
18393 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18396 /* opt_pass methods: */
18397 virtual bool gate (function *)
18399 return flag_cilkplus || flag_openacc || flag_openmp;
18401 virtual unsigned int execute (function *)
18403 return diagnose_omp_structured_block_errors ();
18406 }; // class pass_diagnose_omp_blocks
18408 } // anon namespace
18410 gimple_opt_pass *
18411 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18413 return new pass_diagnose_omp_blocks (ctxt);
18416 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18417 adds their addresses and sizes to constructor-vector V_CTOR. */
18418 static void
18419 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18420 vec<constructor_elt, va_gc> *v_ctor)
18422 unsigned len = vec_safe_length (v_decls);
18423 for (unsigned i = 0; i < len; i++)
18425 tree it = (*v_decls)[i];
18426 bool is_var = TREE_CODE (it) == VAR_DECL;
18427 bool is_link_var
18428 = is_var
18429 #ifdef ACCEL_COMPILER
18430 && DECL_HAS_VALUE_EXPR_P (it)
18431 #endif
18432 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18434 tree size = NULL_TREE;
18435 if (is_var)
18436 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18438 tree addr;
18439 if (!is_link_var)
18440 addr = build_fold_addr_expr (it);
18441 else
18443 #ifdef ACCEL_COMPILER
18444 /* For "omp declare target link" vars add address of the pointer to
18445 the target table, instead of address of the var. */
18446 tree value_expr = DECL_VALUE_EXPR (it);
18447 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18448 varpool_node::finalize_decl (link_ptr_decl);
18449 addr = build_fold_addr_expr (link_ptr_decl);
18450 #else
18451 addr = build_fold_addr_expr (it);
18452 #endif
18454 /* Most significant bit of the size marks "omp declare target link"
18455 vars in host and target tables. */
18456 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18457 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18458 * BITS_PER_UNIT - 1);
18459 size = wide_int_to_tree (const_ptr_type_node, isize);
18462 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18463 if (is_var)
18464 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18468 /* Create new symbols containing (address, size) pairs for global variables,
18469 marked with "omp declare target" attribute, as well as addresses for the
18470 functions, which are outlined offloading regions. */
18471 void
18472 omp_finish_file (void)
18474 unsigned num_funcs = vec_safe_length (offload_funcs);
18475 unsigned num_vars = vec_safe_length (offload_vars);
18477 if (num_funcs == 0 && num_vars == 0)
18478 return;
18480 if (targetm_common.have_named_sections)
18482 vec<constructor_elt, va_gc> *v_f, *v_v;
18483 vec_alloc (v_f, num_funcs);
18484 vec_alloc (v_v, num_vars * 2);
18486 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18487 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18489 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18490 num_vars * 2);
18491 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18492 num_funcs);
18493 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18494 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18495 tree ctor_v = build_constructor (vars_decl_type, v_v);
18496 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18497 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18498 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18499 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18500 get_identifier (".offload_func_table"),
18501 funcs_decl_type);
18502 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18503 get_identifier (".offload_var_table"),
18504 vars_decl_type);
18505 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18506 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18507 otherwise a joint table in a binary will contain padding between
18508 tables from multiple object files. */
18509 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18510 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18511 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18512 DECL_INITIAL (funcs_decl) = ctor_f;
18513 DECL_INITIAL (vars_decl) = ctor_v;
18514 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18515 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18517 varpool_node::finalize_decl (vars_decl);
18518 varpool_node::finalize_decl (funcs_decl);
18520 else
18522 for (unsigned i = 0; i < num_funcs; i++)
18524 tree it = (*offload_funcs)[i];
18525 targetm.record_offload_symbol (it);
18527 for (unsigned i = 0; i < num_vars; i++)
18529 tree it = (*offload_vars)[i];
18530 targetm.record_offload_symbol (it);
18535 /* Find the number of threads (POS = false), or thread number (POS =
18536 true) for an OpenACC region partitioned as MASK. Setup code
18537 required for the calculation is added to SEQ. */
18539 static tree
18540 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18542 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18543 unsigned ix;
18545 /* Start at gang level, and examine relevant dimension indices. */
18546 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18547 if (GOMP_DIM_MASK (ix) & mask)
18549 tree arg = build_int_cst (unsigned_type_node, ix);
18551 if (res)
18553 /* We had an outer index, so scale that by the size of
18554 this dimension. */
18555 tree n = create_tmp_var (integer_type_node);
18556 gimple *call
18557 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18559 gimple_call_set_lhs (call, n);
18560 gimple_seq_add_stmt (seq, call);
18561 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18563 if (pos)
18565 /* Determine index in this dimension. */
18566 tree id = create_tmp_var (integer_type_node);
18567 gimple *call = gimple_build_call_internal
18568 (IFN_GOACC_DIM_POS, 1, arg);
18570 gimple_call_set_lhs (call, id);
18571 gimple_seq_add_stmt (seq, call);
18572 if (res)
18573 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18574 else
18575 res = id;
18579 if (res == NULL_TREE)
18580 res = integer_zero_node;
18582 return res;
18585 /* Transform IFN_GOACC_LOOP calls to actual code. See
18586 expand_oacc_for for where these are generated. At the vector
18587 level, we stride loops, such that each member of a warp will
18588 operate on adjacent iterations. At the worker and gang level,
18589 each gang/warp executes a set of contiguous iterations. Chunking
18590 can override this such that each iteration engine executes a
18591 contiguous chunk, and then moves on to stride to the next chunk. */
18593 static void
18594 oacc_xform_loop (gcall *call)
18596 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18597 enum ifn_goacc_loop_kind code
18598 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18599 tree dir = gimple_call_arg (call, 1);
18600 tree range = gimple_call_arg (call, 2);
18601 tree step = gimple_call_arg (call, 3);
18602 tree chunk_size = NULL_TREE;
18603 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18604 tree lhs = gimple_call_lhs (call);
18605 tree type = TREE_TYPE (lhs);
18606 tree diff_type = TREE_TYPE (range);
18607 tree r = NULL_TREE;
18608 gimple_seq seq = NULL;
18609 bool chunking = false, striding = true;
18610 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18611 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18613 #ifdef ACCEL_COMPILER
18614 chunk_size = gimple_call_arg (call, 4);
18615 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18616 || integer_zerop (chunk_size)) /* Default (also static). */
18618 /* If we're at the gang level, we want each to execute a
18619 contiguous run of iterations. Otherwise we want each element
18620 to stride. */
18621 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18622 chunking = false;
18624 else
18626 /* Chunk of size 1 is striding. */
18627 striding = integer_onep (chunk_size);
18628 chunking = !striding;
18630 #endif
18632 /* striding=true, chunking=true
18633 -> invalid.
18634 striding=true, chunking=false
18635 -> chunks=1
18636 striding=false,chunking=true
18637 -> chunks=ceil (range/(chunksize*threads*step))
18638 striding=false,chunking=false
18639 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18640 push_gimplify_context (true);
18642 switch (code)
18644 default: gcc_unreachable ();
18646 case IFN_GOACC_LOOP_CHUNKS:
18647 if (!chunking)
18648 r = build_int_cst (type, 1);
18649 else
18651 /* chunk_max
18652 = (range - dir) / (chunks * step * num_threads) + dir */
18653 tree per = oacc_thread_numbers (false, mask, &seq);
18654 per = fold_convert (type, per);
18655 chunk_size = fold_convert (type, chunk_size);
18656 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18657 per = fold_build2 (MULT_EXPR, type, per, step);
18658 r = build2 (MINUS_EXPR, type, range, dir);
18659 r = build2 (PLUS_EXPR, type, r, per);
18660 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18662 break;
18664 case IFN_GOACC_LOOP_STEP:
18666 /* If striding, step by the entire compute volume, otherwise
18667 step by the inner volume. */
18668 unsigned volume = striding ? mask : inner_mask;
18670 r = oacc_thread_numbers (false, volume, &seq);
18671 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18673 break;
18675 case IFN_GOACC_LOOP_OFFSET:
18676 if (striding)
18678 r = oacc_thread_numbers (true, mask, &seq);
18679 r = fold_convert (diff_type, r);
18681 else
18683 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18684 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18685 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18686 inner_size, outer_size);
18688 volume = fold_convert (diff_type, volume);
18689 if (chunking)
18690 chunk_size = fold_convert (diff_type, chunk_size);
18691 else
18693 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18695 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18696 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18697 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18700 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18701 fold_convert (diff_type, inner_size));
18702 r = oacc_thread_numbers (true, outer_mask, &seq);
18703 r = fold_convert (diff_type, r);
18704 r = build2 (MULT_EXPR, diff_type, r, span);
18706 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18707 inner = fold_convert (diff_type, inner);
18708 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18710 if (chunking)
18712 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18713 tree per
18714 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18715 per = build2 (MULT_EXPR, diff_type, per, chunk);
18717 r = build2 (PLUS_EXPR, diff_type, r, per);
18720 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18721 if (type != diff_type)
18722 r = fold_convert (type, r);
18723 break;
18725 case IFN_GOACC_LOOP_BOUND:
18726 if (striding)
18727 r = range;
18728 else
18730 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18731 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18732 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18733 inner_size, outer_size);
18735 volume = fold_convert (diff_type, volume);
18736 if (chunking)
18737 chunk_size = fold_convert (diff_type, chunk_size);
18738 else
18740 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18742 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18743 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18744 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18747 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18748 fold_convert (diff_type, inner_size));
18750 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18752 tree offset = gimple_call_arg (call, 6);
18753 r = build2 (PLUS_EXPR, diff_type, r,
18754 fold_convert (diff_type, offset));
18755 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18756 diff_type, r, range);
18758 if (diff_type != type)
18759 r = fold_convert (type, r);
18760 break;
18763 gimplify_assign (lhs, r, &seq);
18765 pop_gimplify_context (NULL);
18767 gsi_replace_with_seq (&gsi, seq, true);
18770 /* Default partitioned and minimum partitioned dimensions. */
18772 static int oacc_default_dims[GOMP_DIM_MAX];
18773 static int oacc_min_dims[GOMP_DIM_MAX];
18775 /* Parse the default dimension parameter. This is a set of
18776 :-separated optional compute dimensions. Each specified dimension
18777 is a positive integer. When device type support is added, it is
18778 planned to be a comma separated list of such compute dimensions,
18779 with all but the first prefixed by the colon-terminated device
18780 type. */
18782 static void
18783 oacc_parse_default_dims (const char *dims)
18785 int ix;
18787 for (ix = GOMP_DIM_MAX; ix--;)
18789 oacc_default_dims[ix] = -1;
18790 oacc_min_dims[ix] = 1;
18793 #ifndef ACCEL_COMPILER
18794 /* Cannot be overridden on the host. */
18795 dims = NULL;
18796 #endif
18797 if (dims)
18799 const char *pos = dims;
18801 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18803 if (ix)
18805 if (*pos != ':')
18806 goto malformed;
18807 pos++;
18810 if (*pos != ':')
18812 long val;
18813 const char *eptr;
18815 errno = 0;
18816 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18817 if (errno || val <= 0 || (int) val != val)
18818 goto malformed;
18819 pos = eptr;
18820 oacc_default_dims[ix] = (int) val;
18823 if (*pos)
18825 malformed:
18826 error_at (UNKNOWN_LOCATION,
18827 "-fopenacc-dim operand is malformed at '%s'", pos);
18831 /* Allow the backend to validate the dimensions. */
18832 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18833 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18836 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18837 raw attribute. DIMS is an array of dimensions, which is filled in.
18838 LEVEL is the partitioning level of a routine, or -1 for an offload
18839 region itself. USED is the mask of partitioned execution in the
18840 function. */
18842 static void
18843 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18845 tree purpose[GOMP_DIM_MAX];
18846 unsigned ix;
18847 tree pos = TREE_VALUE (attrs);
18848 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18850 /* Make sure the attribute creator attached the dimension
18851 information. */
18852 gcc_assert (pos);
18854 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18856 purpose[ix] = TREE_PURPOSE (pos);
18857 tree val = TREE_VALUE (pos);
18858 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18859 pos = TREE_CHAIN (pos);
18862 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18864 /* Default anything left to 1 or a partitioned default. */
18865 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18866 if (dims[ix] < 0)
18868 /* The OpenACC spec says 'If the [num_gangs] clause is not
18869 specified, an implementation-defined default will be used;
18870 the default may depend on the code within the construct.'
18871 (2.5.6). Thus an implementation is free to choose
18872 non-unity default for a parallel region that doesn't have
18873 any gang-partitioned loops. However, it appears that there
18874 is a sufficient body of user code that expects non-gang
18875 partitioned regions to not execute in gang-redundant mode.
18876 So we (a) don't warn about the non-portability and (b) pick
18877 the minimum permissible dimension size when there is no
18878 partitioned execution. Otherwise we pick the global
18879 default for the dimension, which the user can control. The
18880 same wording and logic applies to num_workers and
18881 vector_length, however the worker- or vector- single
18882 execution doesn't have the same impact as gang-redundant
18883 execution. (If the minimum gang-level partioning is not 1,
18884 the target is probably too confusing.) */
18885 dims[ix] = (used & GOMP_DIM_MASK (ix)
18886 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18887 changed = true;
18890 if (changed)
18892 /* Replace the attribute with new values. */
18893 pos = NULL_TREE;
18894 for (ix = GOMP_DIM_MAX; ix--;)
18896 pos = tree_cons (purpose[ix],
18897 build_int_cst (integer_type_node, dims[ix]),
18898 pos);
18899 if (is_kernel)
18900 TREE_PUBLIC (pos) = 1;
18902 replace_oacc_fn_attrib (fn, pos);
18906 /* Create an empty OpenACC loop structure at LOC. */
18908 static oacc_loop *
18909 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18911 oacc_loop *loop = XCNEW (oacc_loop);
18913 loop->parent = parent;
18914 loop->child = loop->sibling = NULL;
18916 if (parent)
18918 loop->sibling = parent->child;
18919 parent->child = loop;
18922 loop->loc = loc;
18923 loop->marker = NULL;
18924 memset (loop->heads, 0, sizeof (loop->heads));
18925 memset (loop->tails, 0, sizeof (loop->tails));
18926 loop->routine = NULL_TREE;
18928 loop->mask = loop->flags = loop->inner = 0;
18929 loop->ifns = 0;
18930 loop->chunk_size = 0;
18931 loop->head_end = NULL;
18933 return loop;
18936 /* Create an outermost, dummy OpenACC loop for offloaded function
18937 DECL. */
18939 static oacc_loop *
18940 new_oacc_loop_outer (tree decl)
18942 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18945 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18946 Link into PARENT loop. Return the new loop. */
18948 static oacc_loop *
18949 new_oacc_loop (oacc_loop *parent, gcall *marker)
18951 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18953 loop->marker = marker;
18955 /* TODO: This is where device_type flattening would occur for the loop
18956 flags. */
18958 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18960 tree chunk_size = integer_zero_node;
18961 if (loop->flags & OLF_GANG_STATIC)
18962 chunk_size = gimple_call_arg (marker, 4);
18963 loop->chunk_size = chunk_size;
18965 return loop;
18968 /* Create a dummy loop encompassing a call to a openACC routine.
18969 Extract the routine's partitioning requirements. */
18971 static void
18972 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18974 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18975 int level = oacc_fn_attrib_level (attrs);
18977 gcc_assert (level >= 0);
18979 loop->marker = call;
18980 loop->routine = decl;
18981 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18982 ^ (GOMP_DIM_MASK (level) - 1));
18985 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18986 Return the parent loop. */
18988 static oacc_loop *
18989 finish_oacc_loop (oacc_loop *loop)
18991 /* If the loop has been collapsed, don't partition it. */
18992 if (!loop->ifns)
18993 loop->mask = loop->flags = 0;
18994 return loop->parent;
18997 /* Free all OpenACC loop structures within LOOP (inclusive). */
18999 static void
19000 free_oacc_loop (oacc_loop *loop)
19002 if (loop->sibling)
19003 free_oacc_loop (loop->sibling);
19004 if (loop->child)
19005 free_oacc_loop (loop->child);
19007 free (loop);
19010 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19012 static void
19013 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19014 const char *title, int level)
19016 enum ifn_unique_kind kind
19017 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19019 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19020 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19022 gimple *stmt = gsi_stmt (gsi);
19024 if (is_gimple_call (stmt)
19025 && gimple_call_internal_p (stmt)
19026 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19028 enum ifn_unique_kind k
19029 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19030 (gimple_call_arg (stmt, 0)));
19032 if (k == kind && stmt != from)
19033 break;
19035 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19037 gsi_next (&gsi);
19038 while (gsi_end_p (gsi))
19039 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19043 /* Dump OpenACC loops LOOP, its siblings and its children. */
19045 static void
19046 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19048 int ix;
19050 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19051 loop->flags, loop->mask,
19052 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19054 if (loop->marker)
19055 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19057 if (loop->routine)
19058 fprintf (file, "%*sRoutine %s:%u:%s\n",
19059 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19060 DECL_SOURCE_LINE (loop->routine),
19061 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19063 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19064 if (loop->heads[ix])
19065 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19066 for (ix = GOMP_DIM_MAX; ix--;)
19067 if (loop->tails[ix])
19068 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19070 if (loop->child)
19071 dump_oacc_loop (file, loop->child, depth + 1);
19072 if (loop->sibling)
19073 dump_oacc_loop (file, loop->sibling, depth);
19076 void debug_oacc_loop (oacc_loop *);
19078 /* Dump loops to stderr. */
19080 DEBUG_FUNCTION void
19081 debug_oacc_loop (oacc_loop *loop)
19083 dump_oacc_loop (stderr, loop, 0);
19086 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19087 structures as we go. By construction these loops are properly
19088 nested. */
19090 static void
19091 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19093 int marker = 0;
19094 int remaining = 0;
19096 if (bb->flags & BB_VISITED)
19097 return;
19099 follow:
19100 bb->flags |= BB_VISITED;
19102 /* Scan for loop markers. */
19103 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19104 gsi_next (&gsi))
19106 gimple *stmt = gsi_stmt (gsi);
19108 if (!is_gimple_call (stmt))
19109 continue;
19111 gcall *call = as_a <gcall *> (stmt);
19113 /* If this is a routine, make a dummy loop for it. */
19114 if (tree decl = gimple_call_fndecl (call))
19115 if (tree attrs = get_oacc_fn_attrib (decl))
19117 gcc_assert (!marker);
19118 new_oacc_loop_routine (loop, call, decl, attrs);
19121 if (!gimple_call_internal_p (call))
19122 continue;
19124 switch (gimple_call_internal_fn (call))
19126 default:
19127 break;
19129 case IFN_GOACC_LOOP:
19130 /* Count the goacc loop abstraction fns, to determine if the
19131 loop was collapsed already. */
19132 loop->ifns++;
19133 break;
19135 case IFN_UNIQUE:
19136 enum ifn_unique_kind kind
19137 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19138 (gimple_call_arg (call, 0)));
19139 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19140 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19142 if (gimple_call_num_args (call) == 2)
19144 gcc_assert (marker && !remaining);
19145 marker = 0;
19146 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19147 loop = finish_oacc_loop (loop);
19148 else
19149 loop->head_end = call;
19151 else
19153 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19155 if (!marker)
19157 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19158 loop = new_oacc_loop (loop, call);
19159 remaining = count;
19161 gcc_assert (count == remaining);
19162 if (remaining)
19164 remaining--;
19165 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19166 loop->heads[marker] = call;
19167 else
19168 loop->tails[remaining] = call;
19170 marker++;
19175 if (remaining || marker)
19177 bb = single_succ (bb);
19178 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19179 goto follow;
19182 /* Walk successor blocks. */
19183 edge e;
19184 edge_iterator ei;
19186 FOR_EACH_EDGE (e, ei, bb->succs)
19187 oacc_loop_discover_walk (loop, e->dest);
19190 /* LOOP is the first sibling. Reverse the order in place and return
19191 the new first sibling. Recurse to child loops. */
19193 static oacc_loop *
19194 oacc_loop_sibling_nreverse (oacc_loop *loop)
19196 oacc_loop *last = NULL;
19199 if (loop->child)
19200 loop->child = oacc_loop_sibling_nreverse (loop->child);
19202 oacc_loop *next = loop->sibling;
19203 loop->sibling = last;
19204 last = loop;
19205 loop = next;
19207 while (loop);
19209 return last;
19212 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19213 the current function. */
19215 static oacc_loop *
19216 oacc_loop_discovery ()
19218 basic_block bb;
19220 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19221 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19223 /* The siblings were constructed in reverse order, reverse them so
19224 that diagnostics come out in an unsurprising order. */
19225 top = oacc_loop_sibling_nreverse (top);
19227 /* Reset the visited flags. */
19228 FOR_ALL_BB_FN (bb, cfun)
19229 bb->flags &= ~BB_VISITED;
19231 return top;
19234 /* Transform the abstract internal function markers starting at FROM
19235 to be for partitioning level LEVEL. Stop when we meet another HEAD
19236 or TAIL marker. */
19238 static void
19239 oacc_loop_xform_head_tail (gcall *from, int level)
19241 enum ifn_unique_kind kind
19242 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19243 tree replacement = build_int_cst (unsigned_type_node, level);
19245 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19247 gimple *stmt = gsi_stmt (gsi);
19249 if (is_gimple_call (stmt)
19250 && gimple_call_internal_p (stmt)
19251 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19253 enum ifn_unique_kind k
19254 = ((enum ifn_unique_kind)
19255 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19257 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19258 *gimple_call_arg_ptr (stmt, 2) = replacement;
19259 else if (k == kind && stmt != from)
19260 break;
19262 else if (is_gimple_call (stmt)
19263 && gimple_call_internal_p (stmt)
19264 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19265 *gimple_call_arg_ptr (stmt, 3) = replacement;
19267 gsi_next (&gsi);
19268 while (gsi_end_p (gsi))
19269 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19273 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19274 determined partitioning mask and chunking argument. END_MARKER
19275 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19276 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19277 the replacement partitioning mask and CHUNK_ARG is the replacement
19278 chunking arg. */
19280 static void
19281 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19282 tree mask_arg, tree chunk_arg)
19284 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19286 gcc_checking_assert (ifns);
19287 for (;;)
19289 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19291 gimple *stmt = gsi_stmt (gsi);
19293 if (!is_gimple_call (stmt))
19294 continue;
19296 gcall *call = as_a <gcall *> (stmt);
19298 if (!gimple_call_internal_p (call))
19299 continue;
19301 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19302 continue;
19304 *gimple_call_arg_ptr (call, 5) = mask_arg;
19305 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19306 ifns--;
19307 if (!ifns)
19308 return;
19311 /* The LOOP_BOUND ifn could be in the single successor
19312 block. */
19313 basic_block bb = single_succ (gsi_bb (gsi));
19314 gsi = gsi_start_bb (bb);
19318 /* Process the discovered OpenACC loops, setting the correct
19319 partitioning level etc. */
19321 static void
19322 oacc_loop_process (oacc_loop *loop)
19324 if (loop->child)
19325 oacc_loop_process (loop->child);
19327 if (loop->mask && !loop->routine)
19329 int ix;
19330 unsigned mask = loop->mask;
19331 unsigned dim = GOMP_DIM_GANG;
19332 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19333 tree chunk_arg = loop->chunk_size;
19335 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19337 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19339 while (!(GOMP_DIM_MASK (dim) & mask))
19340 dim++;
19342 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19343 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19345 mask ^= GOMP_DIM_MASK (dim);
19349 if (loop->sibling)
19350 oacc_loop_process (loop->sibling);
19353 /* Walk the OpenACC loop heirarchy checking and assigning the
19354 programmer-specified partitionings. OUTER_MASK is the partitioning
19355 this loop is contained within. Return mask of partitioning
19356 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19357 bit. */
19359 static unsigned
19360 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19362 unsigned this_mask = loop->mask;
19363 unsigned mask_all = 0;
19364 bool noisy = true;
19366 #ifdef ACCEL_COMPILER
19367 /* When device_type is supported, we want the device compiler to be
19368 noisy, if the loop parameters are device_type-specific. */
19369 noisy = false;
19370 #endif
19372 if (!loop->routine)
19374 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19375 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19377 this_mask = ((loop->flags >> OLF_DIM_BASE)
19378 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19380 if ((this_mask != 0) + auto_par + seq_par > 1)
19382 if (noisy)
19383 error_at (loop->loc,
19384 seq_par
19385 ? "%<seq%> overrides other OpenACC loop specifiers"
19386 : "%<auto%> conflicts with other OpenACC loop specifiers");
19387 auto_par = false;
19388 loop->flags &= ~OLF_AUTO;
19389 if (seq_par)
19391 loop->flags &=
19392 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19393 this_mask = 0;
19396 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19397 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19400 if (this_mask & outer_mask)
19402 const oacc_loop *outer;
19403 for (outer = loop->parent; outer; outer = outer->parent)
19404 if (outer->mask & this_mask)
19405 break;
19407 if (noisy)
19409 if (outer)
19411 error_at (loop->loc,
19412 "%s uses same OpenACC parallelism as containing loop",
19413 loop->routine ? "routine call" : "inner loop");
19414 inform (outer->loc, "containing loop here");
19416 else
19417 error_at (loop->loc,
19418 "%s uses OpenACC parallelism disallowed by containing routine",
19419 loop->routine ? "routine call" : "loop");
19421 if (loop->routine)
19422 inform (DECL_SOURCE_LOCATION (loop->routine),
19423 "routine %qD declared here", loop->routine);
19425 this_mask &= ~outer_mask;
19427 else
19429 unsigned outermost = this_mask & -this_mask;
19431 if (outermost && outermost <= outer_mask)
19433 if (noisy)
19435 error_at (loop->loc,
19436 "incorrectly nested OpenACC loop parallelism");
19438 const oacc_loop *outer;
19439 for (outer = loop->parent;
19440 outer->flags && outer->flags < outermost;
19441 outer = outer->parent)
19442 continue;
19443 inform (outer->loc, "containing loop here");
19446 this_mask &= ~outermost;
19450 loop->mask = this_mask;
19451 mask_all |= this_mask;
19453 if (loop->child)
19455 loop->inner = oacc_loop_fixed_partitions (loop->child,
19456 outer_mask | this_mask);
19457 mask_all |= loop->inner;
19460 if (loop->sibling)
19461 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19463 return mask_all;
19466 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19467 OUTER_MASK is the partitioning this loop is contained within.
19468 Return the cumulative partitioning used by this loop, siblings and
19469 children. */
19471 static unsigned
19472 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19474 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19475 bool noisy = true;
19477 #ifdef ACCEL_COMPILER
19478 /* When device_type is supported, we want the device compiler to be
19479 noisy, if the loop parameters are device_type-specific. */
19480 noisy = false;
19481 #endif
19483 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19485 /* Allocate the outermost loop at the outermost available
19486 level. */
19487 unsigned this_mask = outer_mask + 1;
19489 if (!(this_mask & loop->inner))
19490 loop->mask = this_mask;
19493 if (loop->child)
19495 unsigned child_mask = outer_mask | loop->mask;
19497 if (loop->mask || assign)
19498 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19500 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19503 if (assign && !loop->mask)
19505 /* Allocate the loop at the innermost available level. */
19506 unsigned this_mask = 0;
19508 /* Determine the outermost partitioning used within this loop. */
19509 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19510 this_mask = (this_mask & -this_mask);
19512 /* Pick the partitioning just inside that one. */
19513 this_mask >>= 1;
19515 /* And avoid picking one use by an outer loop. */
19516 this_mask &= ~outer_mask;
19518 if (!this_mask && noisy)
19519 warning_at (loop->loc, 0,
19520 "insufficient partitioning available to parallelize loop");
19522 loop->mask = this_mask;
19525 if (assign && dump_file)
19526 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19527 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19528 loop->mask);
19530 unsigned inner_mask = 0;
19532 if (loop->sibling)
19533 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19535 inner_mask |= loop->inner | loop->mask;
19537 return inner_mask;
19540 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19541 axes. Return mask of partitioning. */
19543 static unsigned
19544 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19546 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19548 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19550 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19551 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19553 return mask_all;
19556 /* Default fork/join early expander. Delete the function calls if
19557 there is no RTL expander. */
19559 bool
19560 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19561 const int *ARG_UNUSED (dims), bool is_fork)
19563 if (is_fork)
19564 return targetm.have_oacc_fork ();
19565 else
19566 return targetm.have_oacc_join ();
19569 /* Default goacc.reduction early expander.
19571 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19572 If RES_PTR is not integer-zerop:
19573 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19574 TEARDOWN - emit '*RES_PTR = VAR'
19575 If LHS is not NULL
19576 emit 'LHS = VAR' */
19578 void
19579 default_goacc_reduction (gcall *call)
19581 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19582 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19583 tree lhs = gimple_call_lhs (call);
19584 tree var = gimple_call_arg (call, 2);
19585 gimple_seq seq = NULL;
19587 if (code == IFN_GOACC_REDUCTION_SETUP
19588 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19590 /* Setup and Teardown need to copy from/to the receiver object,
19591 if there is one. */
19592 tree ref_to_res = gimple_call_arg (call, 1);
19594 if (!integer_zerop (ref_to_res))
19596 tree dst = build_simple_mem_ref (ref_to_res);
19597 tree src = var;
19599 if (code == IFN_GOACC_REDUCTION_SETUP)
19601 src = dst;
19602 dst = lhs;
19603 lhs = NULL;
19605 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19609 /* Copy VAR to LHS, if there is an LHS. */
19610 if (lhs)
19611 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19613 gsi_replace_with_seq (&gsi, seq, true);
19616 /* Main entry point for oacc transformations which run on the device
19617 compiler after LTO, so we know what the target device is at this
19618 point (including the host fallback). */
19620 static unsigned int
19621 execute_oacc_device_lower ()
19623 tree attrs = get_oacc_fn_attrib (current_function_decl);
19625 if (!attrs)
19626 /* Not an offloaded function. */
19627 return 0;
19629 /* Parse the default dim argument exactly once. */
19630 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19632 oacc_parse_default_dims (flag_openacc_dims);
19633 flag_openacc_dims = (char *)&flag_openacc_dims;
19636 /* Discover, partition and process the loops. */
19637 oacc_loop *loops = oacc_loop_discovery ();
19638 int fn_level = oacc_fn_attrib_level (attrs);
19640 if (dump_file)
19641 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19642 ? "Function is kernels offload\n"
19643 : fn_level < 0 ? "Function is parallel offload\n"
19644 : "Function is routine level %d\n", fn_level);
19646 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19647 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19648 int dims[GOMP_DIM_MAX];
19650 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19652 if (dump_file)
19654 const char *comma = "Compute dimensions [";
19655 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19656 fprintf (dump_file, "%s%d", comma, dims[ix]);
19657 fprintf (dump_file, "]\n");
19660 oacc_loop_process (loops);
19661 if (dump_file)
19663 fprintf (dump_file, "OpenACC loops\n");
19664 dump_oacc_loop (dump_file, loops, 0);
19665 fprintf (dump_file, "\n");
19668 /* Offloaded targets may introduce new basic blocks, which require
19669 dominance information to update SSA. */
19670 calculate_dominance_info (CDI_DOMINATORS);
19672 /* Now lower internal loop functions to target-specific code
19673 sequences. */
19674 basic_block bb;
19675 FOR_ALL_BB_FN (bb, cfun)
19676 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19678 gimple *stmt = gsi_stmt (gsi);
19679 if (!is_gimple_call (stmt))
19681 gsi_next (&gsi);
19682 continue;
19685 gcall *call = as_a <gcall *> (stmt);
19686 if (!gimple_call_internal_p (call))
19688 gsi_next (&gsi);
19689 continue;
19692 /* Rewind to allow rescan. */
19693 gsi_prev (&gsi);
19694 bool rescan = false, remove = false;
19695 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19697 switch (ifn_code)
19699 default: break;
19701 case IFN_GOACC_LOOP:
19702 oacc_xform_loop (call);
19703 rescan = true;
19704 break;
19706 case IFN_GOACC_REDUCTION:
19707 /* Mark the function for SSA renaming. */
19708 mark_virtual_operands_for_renaming (cfun);
19710 /* If the level is -1, this ended up being an unused
19711 axis. Handle as a default. */
19712 if (integer_minus_onep (gimple_call_arg (call, 3)))
19713 default_goacc_reduction (call);
19714 else
19715 targetm.goacc.reduction (call);
19716 rescan = true;
19717 break;
19719 case IFN_UNIQUE:
19721 enum ifn_unique_kind kind
19722 = ((enum ifn_unique_kind)
19723 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19725 switch (kind)
19727 default:
19728 gcc_unreachable ();
19730 case IFN_UNIQUE_OACC_FORK:
19731 case IFN_UNIQUE_OACC_JOIN:
19732 if (integer_minus_onep (gimple_call_arg (call, 2)))
19733 remove = true;
19734 else if (!targetm.goacc.fork_join
19735 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19736 remove = true;
19737 break;
19739 case IFN_UNIQUE_OACC_HEAD_MARK:
19740 case IFN_UNIQUE_OACC_TAIL_MARK:
19741 remove = true;
19742 break;
19744 break;
19748 if (gsi_end_p (gsi))
19749 /* We rewound past the beginning of the BB. */
19750 gsi = gsi_start_bb (bb);
19751 else
19752 /* Undo the rewind. */
19753 gsi_next (&gsi);
19755 if (remove)
19757 if (gimple_vdef (call))
19758 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19759 if (gimple_call_lhs (call))
19761 /* Propagate the data dependency var. */
19762 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19763 gimple_call_arg (call, 1));
19764 gsi_replace (&gsi, ass, false);
19766 else
19767 gsi_remove (&gsi, true);
19769 else if (!rescan)
19770 /* If not rescanning, advance over the call. */
19771 gsi_next (&gsi);
19774 free_oacc_loop (loops);
19776 return 0;
19779 /* Default launch dimension validator. Force everything to 1. A
19780 backend that wants to provide larger dimensions must override this
19781 hook. */
19783 bool
19784 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19785 int ARG_UNUSED (fn_level))
19787 bool changed = false;
19789 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19791 if (dims[ix] != 1)
19793 dims[ix] = 1;
19794 changed = true;
19798 return changed;
19801 /* Default dimension bound is unknown on accelerator and 1 on host. */
19804 default_goacc_dim_limit (int ARG_UNUSED (axis))
19806 #ifdef ACCEL_COMPILER
19807 return 0;
19808 #else
19809 return 1;
19810 #endif
19813 namespace {
19815 const pass_data pass_data_oacc_device_lower =
19817 GIMPLE_PASS, /* type */
19818 "oaccdevlow", /* name */
19819 OPTGROUP_NONE, /* optinfo_flags */
19820 TV_NONE, /* tv_id */
19821 PROP_cfg, /* properties_required */
19822 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19823 0, /* properties_destroyed */
19824 0, /* todo_flags_start */
19825 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19828 class pass_oacc_device_lower : public gimple_opt_pass
19830 public:
19831 pass_oacc_device_lower (gcc::context *ctxt)
19832 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19835 /* opt_pass methods: */
19836 virtual unsigned int execute (function *)
19838 bool gate = flag_openacc != 0;
19840 if (!gate)
19841 return 0;
19843 return execute_oacc_device_lower ();
19846 }; // class pass_oacc_device_lower
19848 } // anon namespace
19850 gimple_opt_pass *
19851 make_pass_oacc_device_lower (gcc::context *ctxt)
19853 return new pass_oacc_device_lower (ctxt);
19856 /* "omp declare target link" handling pass. */
19858 namespace {
19860 const pass_data pass_data_omp_target_link =
19862 GIMPLE_PASS, /* type */
19863 "omptargetlink", /* name */
19864 OPTGROUP_NONE, /* optinfo_flags */
19865 TV_NONE, /* tv_id */
19866 PROP_ssa, /* properties_required */
19867 0, /* properties_provided */
19868 0, /* properties_destroyed */
19869 0, /* todo_flags_start */
19870 TODO_update_ssa, /* todo_flags_finish */
19873 class pass_omp_target_link : public gimple_opt_pass
19875 public:
19876 pass_omp_target_link (gcc::context *ctxt)
19877 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19880 /* opt_pass methods: */
19881 virtual bool gate (function *fun)
19883 #ifdef ACCEL_COMPILER
19884 tree attrs = DECL_ATTRIBUTES (fun->decl);
19885 return lookup_attribute ("omp declare target", attrs)
19886 || lookup_attribute ("omp target entrypoint", attrs);
19887 #else
19888 (void) fun;
19889 return false;
19890 #endif
19893 virtual unsigned execute (function *);
19896 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19898 static tree
19899 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19901 tree t = *tp;
19903 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19904 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19906 *walk_subtrees = 0;
19907 return t;
19910 return NULL_TREE;
19913 unsigned
19914 pass_omp_target_link::execute (function *fun)
19916 basic_block bb;
19917 FOR_EACH_BB_FN (bb, fun)
19919 gimple_stmt_iterator gsi;
19920 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19921 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19922 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19925 return 0;
19928 } // anon namespace
19930 gimple_opt_pass *
19931 make_pass_omp_target_link (gcc::context *ctxt)
19933 return new pass_omp_target_link (ctxt);
19936 #include "gt-omp-low.h"