Allow the use of ad-hoc locations for fix-it hints
[official-gcc.git] / gcc / omp-low.c
blob3f7debf1fd1e9c5b5d5e9bf32390e4299a7f977a
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_INDEPENDENT:
2191 case OMP_CLAUSE_AUTO:
2192 case OMP_CLAUSE_SEQ:
2193 break;
2195 case OMP_CLAUSE_ALIGNED:
2196 decl = OMP_CLAUSE_DECL (c);
2197 if (is_global_var (decl)
2198 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2199 install_var_local (decl, ctx);
2200 break;
2202 case OMP_CLAUSE_TILE:
2203 case OMP_CLAUSE__CACHE_:
2204 default:
2205 gcc_unreachable ();
2209 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2211 switch (OMP_CLAUSE_CODE (c))
2213 case OMP_CLAUSE_LASTPRIVATE:
2214 /* Let the corresponding firstprivate clause create
2215 the variable. */
2216 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2217 scan_array_reductions = true;
2218 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2219 break;
2220 /* FALLTHRU */
2222 case OMP_CLAUSE_FIRSTPRIVATE:
2223 case OMP_CLAUSE_PRIVATE:
2224 case OMP_CLAUSE_LINEAR:
2225 case OMP_CLAUSE_IS_DEVICE_PTR:
2226 decl = OMP_CLAUSE_DECL (c);
2227 if (is_variable_sized (decl))
2229 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2230 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2231 && is_gimple_omp_offloaded (ctx->stmt))
2233 tree decl2 = DECL_VALUE_EXPR (decl);
2234 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2235 decl2 = TREE_OPERAND (decl2, 0);
2236 gcc_assert (DECL_P (decl2));
2237 install_var_local (decl2, ctx);
2238 fixup_remapped_decl (decl2, ctx, false);
2240 install_var_local (decl, ctx);
2242 fixup_remapped_decl (decl, ctx,
2243 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2244 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2245 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2246 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2247 scan_array_reductions = true;
2248 break;
2250 case OMP_CLAUSE_REDUCTION:
2251 decl = OMP_CLAUSE_DECL (c);
2252 if (TREE_CODE (decl) != MEM_REF)
2254 if (is_variable_sized (decl))
2255 install_var_local (decl, ctx);
2256 fixup_remapped_decl (decl, ctx, false);
2258 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2259 scan_array_reductions = true;
2260 break;
2262 case OMP_CLAUSE_SHARED:
2263 /* Ignore shared directives in teams construct. */
2264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2265 break;
2266 decl = OMP_CLAUSE_DECL (c);
2267 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2268 break;
2269 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2271 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2272 ctx->outer)))
2273 break;
2274 bool by_ref = use_pointer_for_field (decl, ctx);
2275 install_var_field (decl, by_ref, 11, ctx);
2276 break;
2278 fixup_remapped_decl (decl, ctx, false);
2279 break;
2281 case OMP_CLAUSE_MAP:
2282 if (!is_gimple_omp_offloaded (ctx->stmt))
2283 break;
2284 decl = OMP_CLAUSE_DECL (c);
2285 if (DECL_P (decl)
2286 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2287 && (OMP_CLAUSE_MAP_KIND (c)
2288 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2289 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2290 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2291 && varpool_node::get_create (decl)->offloadable)
2292 break;
2293 if (DECL_P (decl))
2295 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2296 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2297 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2298 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2300 tree new_decl = lookup_decl (decl, ctx);
2301 TREE_TYPE (new_decl)
2302 = remap_type (TREE_TYPE (decl), &ctx->cb);
2304 else if (DECL_SIZE (decl)
2305 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2307 tree decl2 = DECL_VALUE_EXPR (decl);
2308 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2309 decl2 = TREE_OPERAND (decl2, 0);
2310 gcc_assert (DECL_P (decl2));
2311 fixup_remapped_decl (decl2, ctx, false);
2312 fixup_remapped_decl (decl, ctx, true);
2314 else
2315 fixup_remapped_decl (decl, ctx, false);
2317 break;
2319 case OMP_CLAUSE_COPYPRIVATE:
2320 case OMP_CLAUSE_COPYIN:
2321 case OMP_CLAUSE_DEFAULT:
2322 case OMP_CLAUSE_IF:
2323 case OMP_CLAUSE_NUM_THREADS:
2324 case OMP_CLAUSE_NUM_TEAMS:
2325 case OMP_CLAUSE_THREAD_LIMIT:
2326 case OMP_CLAUSE_DEVICE:
2327 case OMP_CLAUSE_SCHEDULE:
2328 case OMP_CLAUSE_DIST_SCHEDULE:
2329 case OMP_CLAUSE_NOWAIT:
2330 case OMP_CLAUSE_ORDERED:
2331 case OMP_CLAUSE_COLLAPSE:
2332 case OMP_CLAUSE_UNTIED:
2333 case OMP_CLAUSE_FINAL:
2334 case OMP_CLAUSE_MERGEABLE:
2335 case OMP_CLAUSE_PROC_BIND:
2336 case OMP_CLAUSE_SAFELEN:
2337 case OMP_CLAUSE_SIMDLEN:
2338 case OMP_CLAUSE_ALIGNED:
2339 case OMP_CLAUSE_DEPEND:
2340 case OMP_CLAUSE__LOOPTEMP_:
2341 case OMP_CLAUSE_TO:
2342 case OMP_CLAUSE_FROM:
2343 case OMP_CLAUSE_PRIORITY:
2344 case OMP_CLAUSE_GRAINSIZE:
2345 case OMP_CLAUSE_NUM_TASKS:
2346 case OMP_CLAUSE_THREADS:
2347 case OMP_CLAUSE_SIMD:
2348 case OMP_CLAUSE_NOGROUP:
2349 case OMP_CLAUSE_DEFAULTMAP:
2350 case OMP_CLAUSE_USE_DEVICE_PTR:
2351 case OMP_CLAUSE__CILK_FOR_COUNT_:
2352 case OMP_CLAUSE_ASYNC:
2353 case OMP_CLAUSE_WAIT:
2354 case OMP_CLAUSE_NUM_GANGS:
2355 case OMP_CLAUSE_NUM_WORKERS:
2356 case OMP_CLAUSE_VECTOR_LENGTH:
2357 case OMP_CLAUSE_GANG:
2358 case OMP_CLAUSE_WORKER:
2359 case OMP_CLAUSE_VECTOR:
2360 case OMP_CLAUSE_INDEPENDENT:
2361 case OMP_CLAUSE_AUTO:
2362 case OMP_CLAUSE_SEQ:
2363 case OMP_CLAUSE__GRIDDIM_:
2364 break;
2366 case OMP_CLAUSE_TILE:
2367 case OMP_CLAUSE__CACHE_:
2368 default:
2369 gcc_unreachable ();
2373 gcc_checking_assert (!scan_array_reductions
2374 || !is_gimple_omp_oacc (ctx->stmt));
2375 if (scan_array_reductions)
2377 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2378 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2379 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2381 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2382 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2384 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2385 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2386 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2387 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2388 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2389 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2393 /* Create a new name for omp child function. Returns an identifier. If
2394 IS_CILK_FOR is true then the suffix for the child function is
2395 "_cilk_for_fn." */
2397 static tree
2398 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2400 if (is_cilk_for)
2401 return clone_function_name (current_function_decl, "_cilk_for_fn");
2402 return clone_function_name (current_function_decl,
2403 task_copy ? "_omp_cpyfn" : "_omp_fn");
2406 /* Returns the type of the induction variable for the child function for
2407 _Cilk_for and the types for _high and _low variables based on TYPE. */
2409 static tree
2410 cilk_for_check_loop_diff_type (tree type)
2412 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2414 if (TYPE_UNSIGNED (type))
2415 return uint32_type_node;
2416 else
2417 return integer_type_node;
2419 else
2421 if (TYPE_UNSIGNED (type))
2422 return uint64_type_node;
2423 else
2424 return long_long_integer_type_node;
2428 /* Build a decl for the omp child function. It'll not contain a body
2429 yet, just the bare decl. */
2431 static void
2432 create_omp_child_function (omp_context *ctx, bool task_copy)
2434 tree decl, type, name, t;
2436 tree cilk_for_count
2437 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2438 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2439 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2440 tree cilk_var_type = NULL_TREE;
2442 name = create_omp_child_function_name (task_copy,
2443 cilk_for_count != NULL_TREE);
2444 if (task_copy)
2445 type = build_function_type_list (void_type_node, ptr_type_node,
2446 ptr_type_node, NULL_TREE);
2447 else if (cilk_for_count)
2449 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2450 cilk_var_type = cilk_for_check_loop_diff_type (type);
2451 type = build_function_type_list (void_type_node, ptr_type_node,
2452 cilk_var_type, cilk_var_type, NULL_TREE);
2454 else
2455 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2457 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2459 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2460 || !task_copy);
2461 if (!task_copy)
2462 ctx->cb.dst_fn = decl;
2463 else
2464 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2466 TREE_STATIC (decl) = 1;
2467 TREE_USED (decl) = 1;
2468 DECL_ARTIFICIAL (decl) = 1;
2469 DECL_IGNORED_P (decl) = 0;
2470 TREE_PUBLIC (decl) = 0;
2471 DECL_UNINLINABLE (decl) = 1;
2472 DECL_EXTERNAL (decl) = 0;
2473 DECL_CONTEXT (decl) = NULL_TREE;
2474 DECL_INITIAL (decl) = make_node (BLOCK);
2475 BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
2476 if (cgraph_node::get (current_function_decl)->offloadable)
2477 cgraph_node::get_create (decl)->offloadable = 1;
2478 else
2480 omp_context *octx;
2481 for (octx = ctx; octx; octx = octx->outer)
2482 if (is_gimple_omp_offloaded (octx->stmt))
2484 cgraph_node::get_create (decl)->offloadable = 1;
2485 if (ENABLE_OFFLOADING)
2486 g->have_offload = true;
2488 break;
2492 if (cgraph_node::get_create (decl)->offloadable
2493 && !lookup_attribute ("omp declare target",
2494 DECL_ATTRIBUTES (current_function_decl)))
2495 DECL_ATTRIBUTES (decl)
2496 = tree_cons (get_identifier ("omp target entrypoint"),
2497 NULL_TREE, DECL_ATTRIBUTES (decl));
2499 t = build_decl (DECL_SOURCE_LOCATION (decl),
2500 RESULT_DECL, NULL_TREE, void_type_node);
2501 DECL_ARTIFICIAL (t) = 1;
2502 DECL_IGNORED_P (t) = 1;
2503 DECL_CONTEXT (t) = decl;
2504 DECL_RESULT (decl) = t;
2506 /* _Cilk_for's child function requires two extra parameters called
2507 __low and __high that are set the by Cilk runtime when it calls this
2508 function. */
2509 if (cilk_for_count)
2511 t = build_decl (DECL_SOURCE_LOCATION (decl),
2512 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2513 DECL_ARTIFICIAL (t) = 1;
2514 DECL_NAMELESS (t) = 1;
2515 DECL_ARG_TYPE (t) = ptr_type_node;
2516 DECL_CONTEXT (t) = current_function_decl;
2517 TREE_USED (t) = 1;
2518 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2519 DECL_ARGUMENTS (decl) = t;
2521 t = build_decl (DECL_SOURCE_LOCATION (decl),
2522 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2523 DECL_ARTIFICIAL (t) = 1;
2524 DECL_NAMELESS (t) = 1;
2525 DECL_ARG_TYPE (t) = ptr_type_node;
2526 DECL_CONTEXT (t) = current_function_decl;
2527 TREE_USED (t) = 1;
2528 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2529 DECL_ARGUMENTS (decl) = t;
2532 tree data_name = get_identifier (".omp_data_i");
2533 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2534 ptr_type_node);
2535 DECL_ARTIFICIAL (t) = 1;
2536 DECL_NAMELESS (t) = 1;
2537 DECL_ARG_TYPE (t) = ptr_type_node;
2538 DECL_CONTEXT (t) = current_function_decl;
2539 TREE_USED (t) = 1;
2540 TREE_READONLY (t) = 1;
2541 if (cilk_for_count)
2542 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2543 DECL_ARGUMENTS (decl) = t;
2544 if (!task_copy)
2545 ctx->receiver_decl = t;
2546 else
2548 t = build_decl (DECL_SOURCE_LOCATION (decl),
2549 PARM_DECL, get_identifier (".omp_data_o"),
2550 ptr_type_node);
2551 DECL_ARTIFICIAL (t) = 1;
2552 DECL_NAMELESS (t) = 1;
2553 DECL_ARG_TYPE (t) = ptr_type_node;
2554 DECL_CONTEXT (t) = current_function_decl;
2555 TREE_USED (t) = 1;
2556 TREE_ADDRESSABLE (t) = 1;
2557 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2558 DECL_ARGUMENTS (decl) = t;
2561 /* Allocate memory for the function structure. The call to
2562 allocate_struct_function clobbers CFUN, so we need to restore
2563 it afterward. */
2564 push_struct_function (decl);
2565 cfun->function_end_locus = gimple_location (ctx->stmt);
2566 init_tree_ssa (cfun);
2567 pop_cfun ();
2570 /* Callback for walk_gimple_seq. Check if combined parallel
2571 contains gimple_omp_for_combined_into_p OMP_FOR. */
2573 static tree
2574 find_combined_for (gimple_stmt_iterator *gsi_p,
2575 bool *handled_ops_p,
2576 struct walk_stmt_info *wi)
2578 gimple *stmt = gsi_stmt (*gsi_p);
2580 *handled_ops_p = true;
2581 switch (gimple_code (stmt))
2583 WALK_SUBSTMTS;
2585 case GIMPLE_OMP_FOR:
2586 if (gimple_omp_for_combined_into_p (stmt)
2587 && gimple_omp_for_kind (stmt)
2588 == *(const enum gf_mask *) (wi->info))
2590 wi->info = stmt;
2591 return integer_zero_node;
2593 break;
2594 default:
2595 break;
2597 return NULL;
2600 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2602 static void
2603 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2604 omp_context *outer_ctx)
2606 struct walk_stmt_info wi;
2608 memset (&wi, 0, sizeof (wi));
2609 wi.val_only = true;
2610 wi.info = (void *) &msk;
2611 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2612 if (wi.info != (void *) &msk)
2614 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2615 struct omp_for_data fd;
2616 extract_omp_for_data (for_stmt, &fd, NULL);
2617 /* We need two temporaries with fd.loop.v type (istart/iend)
2618 and then (fd.collapse - 1) temporaries with the same
2619 type for count2 ... countN-1 vars if not constant. */
2620 size_t count = 2, i;
2621 tree type = fd.iter_type;
2622 if (fd.collapse > 1
2623 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2625 count += fd.collapse - 1;
2626 /* If there are lastprivate clauses on the inner
2627 GIMPLE_OMP_FOR, add one more temporaries for the total number
2628 of iterations (product of count1 ... countN-1). */
2629 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2630 OMP_CLAUSE_LASTPRIVATE))
2631 count++;
2632 else if (msk == GF_OMP_FOR_KIND_FOR
2633 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2634 OMP_CLAUSE_LASTPRIVATE))
2635 count++;
2637 for (i = 0; i < count; i++)
2639 tree temp = create_tmp_var (type);
2640 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2641 insert_decl_map (&outer_ctx->cb, temp, temp);
2642 OMP_CLAUSE_DECL (c) = temp;
2643 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2644 gimple_omp_taskreg_set_clauses (stmt, c);
2649 /* Scan an OpenMP parallel directive. */
2651 static void
2652 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2654 omp_context *ctx;
2655 tree name;
2656 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2658 /* Ignore parallel directives with empty bodies, unless there
2659 are copyin clauses. */
2660 if (optimize > 0
2661 && empty_body_p (gimple_omp_body (stmt))
2662 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2663 OMP_CLAUSE_COPYIN) == NULL)
2665 gsi_replace (gsi, gimple_build_nop (), false);
2666 return;
2669 if (gimple_omp_parallel_combined_p (stmt))
2670 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2672 ctx = new_omp_context (stmt, outer_ctx);
2673 taskreg_contexts.safe_push (ctx);
2674 if (taskreg_nesting_level > 1)
2675 ctx->is_nested = true;
2676 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2677 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2678 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2679 name = create_tmp_var_name (".omp_data_s");
2680 name = build_decl (gimple_location (stmt),
2681 TYPE_DECL, name, ctx->record_type);
2682 DECL_ARTIFICIAL (name) = 1;
2683 DECL_NAMELESS (name) = 1;
2684 TYPE_NAME (ctx->record_type) = name;
2685 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2686 if (!gimple_omp_parallel_grid_phony (stmt))
2688 create_omp_child_function (ctx, false);
2689 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2692 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2693 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2695 if (TYPE_FIELDS (ctx->record_type) == NULL)
2696 ctx->record_type = ctx->receiver_decl = NULL;
2699 /* Scan an OpenMP task directive. */
2701 static void
2702 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2704 omp_context *ctx;
2705 tree name, t;
2706 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2708 /* Ignore task directives with empty bodies. */
2709 if (optimize > 0
2710 && empty_body_p (gimple_omp_body (stmt)))
2712 gsi_replace (gsi, gimple_build_nop (), false);
2713 return;
2716 if (gimple_omp_task_taskloop_p (stmt))
2717 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2719 ctx = new_omp_context (stmt, outer_ctx);
2720 taskreg_contexts.safe_push (ctx);
2721 if (taskreg_nesting_level > 1)
2722 ctx->is_nested = true;
2723 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2724 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2725 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2726 name = create_tmp_var_name (".omp_data_s");
2727 name = build_decl (gimple_location (stmt),
2728 TYPE_DECL, name, ctx->record_type);
2729 DECL_ARTIFICIAL (name) = 1;
2730 DECL_NAMELESS (name) = 1;
2731 TYPE_NAME (ctx->record_type) = name;
2732 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2733 create_omp_child_function (ctx, false);
2734 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2736 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2738 if (ctx->srecord_type)
2740 name = create_tmp_var_name (".omp_data_a");
2741 name = build_decl (gimple_location (stmt),
2742 TYPE_DECL, name, ctx->srecord_type);
2743 DECL_ARTIFICIAL (name) = 1;
2744 DECL_NAMELESS (name) = 1;
2745 TYPE_NAME (ctx->srecord_type) = name;
2746 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2747 create_omp_child_function (ctx, true);
2750 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2752 if (TYPE_FIELDS (ctx->record_type) == NULL)
2754 ctx->record_type = ctx->receiver_decl = NULL;
2755 t = build_int_cst (long_integer_type_node, 0);
2756 gimple_omp_task_set_arg_size (stmt, t);
2757 t = build_int_cst (long_integer_type_node, 1);
2758 gimple_omp_task_set_arg_align (stmt, t);
2763 /* If any decls have been made addressable during scan_omp,
2764 adjust their fields if needed, and layout record types
2765 of parallel/task constructs. */
2767 static void
2768 finish_taskreg_scan (omp_context *ctx)
2770 if (ctx->record_type == NULL_TREE)
2771 return;
2773 /* If any task_shared_vars were needed, verify all
2774 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2775 statements if use_pointer_for_field hasn't changed
2776 because of that. If it did, update field types now. */
2777 if (task_shared_vars)
2779 tree c;
2781 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2782 c; c = OMP_CLAUSE_CHAIN (c))
2783 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2784 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2786 tree decl = OMP_CLAUSE_DECL (c);
2788 /* Global variables don't need to be copied,
2789 the receiver side will use them directly. */
2790 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2791 continue;
2792 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2793 || !use_pointer_for_field (decl, ctx))
2794 continue;
2795 tree field = lookup_field (decl, ctx);
2796 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2797 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2798 continue;
2799 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2800 TREE_THIS_VOLATILE (field) = 0;
2801 DECL_USER_ALIGN (field) = 0;
2802 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2803 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2804 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2805 if (ctx->srecord_type)
2807 tree sfield = lookup_sfield (decl, ctx);
2808 TREE_TYPE (sfield) = TREE_TYPE (field);
2809 TREE_THIS_VOLATILE (sfield) = 0;
2810 DECL_USER_ALIGN (sfield) = 0;
2811 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2812 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2813 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2818 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2820 layout_type (ctx->record_type);
2821 fixup_child_record_type (ctx);
2823 else
2825 location_t loc = gimple_location (ctx->stmt);
2826 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2827 /* Move VLA fields to the end. */
2828 p = &TYPE_FIELDS (ctx->record_type);
2829 while (*p)
2830 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2831 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2833 *q = *p;
2834 *p = TREE_CHAIN (*p);
2835 TREE_CHAIN (*q) = NULL_TREE;
2836 q = &TREE_CHAIN (*q);
2838 else
2839 p = &DECL_CHAIN (*p);
2840 *p = vla_fields;
2841 if (gimple_omp_task_taskloop_p (ctx->stmt))
2843 /* Move fields corresponding to first and second _looptemp_
2844 clause first. There are filled by GOMP_taskloop
2845 and thus need to be in specific positions. */
2846 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2847 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2848 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2849 OMP_CLAUSE__LOOPTEMP_);
2850 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2851 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2852 p = &TYPE_FIELDS (ctx->record_type);
2853 while (*p)
2854 if (*p == f1 || *p == f2)
2855 *p = DECL_CHAIN (*p);
2856 else
2857 p = &DECL_CHAIN (*p);
2858 DECL_CHAIN (f1) = f2;
2859 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2860 TYPE_FIELDS (ctx->record_type) = f1;
2861 if (ctx->srecord_type)
2863 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2864 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2865 p = &TYPE_FIELDS (ctx->srecord_type);
2866 while (*p)
2867 if (*p == f1 || *p == f2)
2868 *p = DECL_CHAIN (*p);
2869 else
2870 p = &DECL_CHAIN (*p);
2871 DECL_CHAIN (f1) = f2;
2872 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2873 TYPE_FIELDS (ctx->srecord_type) = f1;
2876 layout_type (ctx->record_type);
2877 fixup_child_record_type (ctx);
2878 if (ctx->srecord_type)
2879 layout_type (ctx->srecord_type);
2880 tree t = fold_convert_loc (loc, long_integer_type_node,
2881 TYPE_SIZE_UNIT (ctx->record_type));
2882 gimple_omp_task_set_arg_size (ctx->stmt, t);
2883 t = build_int_cst (long_integer_type_node,
2884 TYPE_ALIGN_UNIT (ctx->record_type));
2885 gimple_omp_task_set_arg_align (ctx->stmt, t);
2889 /* Find the enclosing offload context. */
2891 static omp_context *
2892 enclosing_target_ctx (omp_context *ctx)
2894 for (; ctx; ctx = ctx->outer)
2895 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2896 break;
2898 return ctx;
2901 /* Return true if ctx is part of an oacc kernels region. */
2903 static bool
2904 ctx_in_oacc_kernels_region (omp_context *ctx)
2906 for (;ctx != NULL; ctx = ctx->outer)
2908 gimple *stmt = ctx->stmt;
2909 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2910 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2911 return true;
2914 return false;
2917 /* Check the parallelism clauses inside a kernels regions.
2918 Until kernels handling moves to use the same loop indirection
2919 scheme as parallel, we need to do this checking early. */
2921 static unsigned
2922 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2924 bool checking = true;
2925 unsigned outer_mask = 0;
2926 unsigned this_mask = 0;
2927 bool has_seq = false, has_auto = false;
2929 if (ctx->outer)
2930 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2931 if (!stmt)
2933 checking = false;
2934 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2935 return outer_mask;
2936 stmt = as_a <gomp_for *> (ctx->stmt);
2939 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2941 switch (OMP_CLAUSE_CODE (c))
2943 case OMP_CLAUSE_GANG:
2944 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2945 break;
2946 case OMP_CLAUSE_WORKER:
2947 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2948 break;
2949 case OMP_CLAUSE_VECTOR:
2950 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2951 break;
2952 case OMP_CLAUSE_SEQ:
2953 has_seq = true;
2954 break;
2955 case OMP_CLAUSE_AUTO:
2956 has_auto = true;
2957 break;
2958 default:
2959 break;
2963 if (checking)
2965 if (has_seq && (this_mask || has_auto))
2966 error_at (gimple_location (stmt), "%<seq%> overrides other"
2967 " OpenACC loop specifiers");
2968 else if (has_auto && this_mask)
2969 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2970 " OpenACC loop specifiers");
2972 if (this_mask & outer_mask)
2973 error_at (gimple_location (stmt), "inner loop uses same"
2974 " OpenACC parallelism as containing loop");
2977 return outer_mask | this_mask;
2980 /* Scan a GIMPLE_OMP_FOR. */
2982 static void
2983 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2985 omp_context *ctx;
2986 size_t i;
2987 tree clauses = gimple_omp_for_clauses (stmt);
2989 ctx = new_omp_context (stmt, outer_ctx);
2991 if (is_gimple_omp_oacc (stmt))
2993 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2995 if (!tgt || is_oacc_parallel (tgt))
2996 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2998 char const *check = NULL;
3000 switch (OMP_CLAUSE_CODE (c))
3002 case OMP_CLAUSE_GANG:
3003 check = "gang";
3004 break;
3006 case OMP_CLAUSE_WORKER:
3007 check = "worker";
3008 break;
3010 case OMP_CLAUSE_VECTOR:
3011 check = "vector";
3012 break;
3014 default:
3015 break;
3018 if (check && OMP_CLAUSE_OPERAND (c, 0))
3019 error_at (gimple_location (stmt),
3020 "argument not permitted on %qs clause in"
3021 " OpenACC %<parallel%>", check);
3024 if (tgt && is_oacc_kernels (tgt))
3026 /* Strip out reductions, as they are not handled yet. */
3027 tree *prev_ptr = &clauses;
3029 while (tree probe = *prev_ptr)
3031 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3033 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3034 *prev_ptr = *next_ptr;
3035 else
3036 prev_ptr = next_ptr;
3039 gimple_omp_for_set_clauses (stmt, clauses);
3040 check_oacc_kernel_gwv (stmt, ctx);
3044 scan_sharing_clauses (clauses, ctx);
3046 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3047 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3049 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3050 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3051 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3052 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3054 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3057 /* Scan an OpenMP sections directive. */
3059 static void
3060 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3062 omp_context *ctx;
3064 ctx = new_omp_context (stmt, outer_ctx);
3065 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3066 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3069 /* Scan an OpenMP single directive. */
3071 static void
3072 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3074 omp_context *ctx;
3075 tree name;
3077 ctx = new_omp_context (stmt, outer_ctx);
3078 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3079 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3080 name = create_tmp_var_name (".omp_copy_s");
3081 name = build_decl (gimple_location (stmt),
3082 TYPE_DECL, name, ctx->record_type);
3083 TYPE_NAME (ctx->record_type) = name;
3085 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3086 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3088 if (TYPE_FIELDS (ctx->record_type) == NULL)
3089 ctx->record_type = NULL;
3090 else
3091 layout_type (ctx->record_type);
3094 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3095 used in the corresponding offloaded function are restrict. */
3097 static bool
3098 omp_target_base_pointers_restrict_p (tree clauses)
3100 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3101 used by OpenACC. */
3102 if (flag_openacc == 0)
3103 return false;
3105 /* I. Basic example:
3107 void foo (void)
3109 unsigned int a[2], b[2];
3111 #pragma acc kernels \
3112 copyout (a) \
3113 copyout (b)
3115 a[0] = 0;
3116 b[0] = 1;
3120 After gimplification, we have:
3122 #pragma omp target oacc_kernels \
3123 map(force_from:a [len: 8]) \
3124 map(force_from:b [len: 8])
3126 a[0] = 0;
3127 b[0] = 1;
3130 Because both mappings have the force prefix, we know that they will be
3131 allocated when calling the corresponding offloaded function, which means we
3132 can mark the base pointers for a and b in the offloaded function as
3133 restrict. */
3135 tree c;
3136 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3138 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3139 return false;
3141 switch (OMP_CLAUSE_MAP_KIND (c))
3143 case GOMP_MAP_FORCE_ALLOC:
3144 case GOMP_MAP_FORCE_TO:
3145 case GOMP_MAP_FORCE_FROM:
3146 case GOMP_MAP_FORCE_TOFROM:
3147 break;
3148 default:
3149 return false;
3153 return true;
3156 /* Scan a GIMPLE_OMP_TARGET. */
3158 static void
3159 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3161 omp_context *ctx;
3162 tree name;
3163 bool offloaded = is_gimple_omp_offloaded (stmt);
3164 tree clauses = gimple_omp_target_clauses (stmt);
3166 ctx = new_omp_context (stmt, outer_ctx);
3167 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3168 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3169 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3170 name = create_tmp_var_name (".omp_data_t");
3171 name = build_decl (gimple_location (stmt),
3172 TYPE_DECL, name, ctx->record_type);
3173 DECL_ARTIFICIAL (name) = 1;
3174 DECL_NAMELESS (name) = 1;
3175 TYPE_NAME (ctx->record_type) = name;
3176 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3178 bool base_pointers_restrict = false;
3179 if (offloaded)
3181 create_omp_child_function (ctx, false);
3182 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3184 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3185 if (base_pointers_restrict
3186 && dump_file && (dump_flags & TDF_DETAILS))
3187 fprintf (dump_file,
3188 "Base pointers in offloaded function are restrict\n");
3191 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3192 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3194 if (TYPE_FIELDS (ctx->record_type) == NULL)
3195 ctx->record_type = ctx->receiver_decl = NULL;
3196 else
3198 TYPE_FIELDS (ctx->record_type)
3199 = nreverse (TYPE_FIELDS (ctx->record_type));
3200 if (flag_checking)
3202 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3203 for (tree field = TYPE_FIELDS (ctx->record_type);
3204 field;
3205 field = DECL_CHAIN (field))
3206 gcc_assert (DECL_ALIGN (field) == align);
3208 layout_type (ctx->record_type);
3209 if (offloaded)
3210 fixup_child_record_type (ctx);
3214 /* Scan an OpenMP teams directive. */
3216 static void
3217 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3219 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3220 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3221 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3224 /* Check nesting restrictions. */
3225 static bool
3226 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3228 tree c;
3230 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3231 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3232 the original copy of its contents. */
3233 return true;
3235 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3236 inside an OpenACC CTX. */
3237 if (!(is_gimple_omp (stmt)
3238 && is_gimple_omp_oacc (stmt))
3239 /* Except for atomic codes that we share with OpenMP. */
3240 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3241 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3243 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3245 error_at (gimple_location (stmt),
3246 "non-OpenACC construct inside of OpenACC routine");
3247 return false;
3249 else
3250 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3251 if (is_gimple_omp (octx->stmt)
3252 && is_gimple_omp_oacc (octx->stmt))
3254 error_at (gimple_location (stmt),
3255 "non-OpenACC construct inside of OpenACC region");
3256 return false;
3260 if (ctx != NULL)
3262 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3263 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3265 c = NULL_TREE;
3266 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3268 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3269 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3271 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3272 && (ctx->outer == NULL
3273 || !gimple_omp_for_combined_into_p (ctx->stmt)
3274 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3275 || (gimple_omp_for_kind (ctx->outer->stmt)
3276 != GF_OMP_FOR_KIND_FOR)
3277 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3279 error_at (gimple_location (stmt),
3280 "%<ordered simd threads%> must be closely "
3281 "nested inside of %<for simd%> region");
3282 return false;
3284 return true;
3287 error_at (gimple_location (stmt),
3288 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3289 " may not be nested inside %<simd%> region");
3290 return false;
3292 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3294 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3295 || (gimple_omp_for_kind (stmt)
3296 != GF_OMP_FOR_KIND_DISTRIBUTE))
3297 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3299 error_at (gimple_location (stmt),
3300 "only %<distribute%> or %<parallel%> regions are "
3301 "allowed to be strictly nested inside %<teams%> "
3302 "region");
3303 return false;
3307 switch (gimple_code (stmt))
3309 case GIMPLE_OMP_FOR:
3310 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3311 return true;
3312 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3314 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3316 error_at (gimple_location (stmt),
3317 "%<distribute%> region must be strictly nested "
3318 "inside %<teams%> construct");
3319 return false;
3321 return true;
3323 /* We split taskloop into task and nested taskloop in it. */
3324 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3325 return true;
3326 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3328 bool ok = false;
3330 if (ctx)
3331 switch (gimple_code (ctx->stmt))
3333 case GIMPLE_OMP_FOR:
3334 ok = (gimple_omp_for_kind (ctx->stmt)
3335 == GF_OMP_FOR_KIND_OACC_LOOP);
3336 break;
3338 case GIMPLE_OMP_TARGET:
3339 switch (gimple_omp_target_kind (ctx->stmt))
3341 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3342 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3343 ok = true;
3344 break;
3346 default:
3347 break;
3350 default:
3351 break;
3353 else if (get_oacc_fn_attrib (current_function_decl))
3354 ok = true;
3355 if (!ok)
3357 error_at (gimple_location (stmt),
3358 "OpenACC loop directive must be associated with"
3359 " an OpenACC compute region");
3360 return false;
3363 /* FALLTHRU */
3364 case GIMPLE_CALL:
3365 if (is_gimple_call (stmt)
3366 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3367 == BUILT_IN_GOMP_CANCEL
3368 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3369 == BUILT_IN_GOMP_CANCELLATION_POINT))
3371 const char *bad = NULL;
3372 const char *kind = NULL;
3373 const char *construct
3374 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3375 == BUILT_IN_GOMP_CANCEL)
3376 ? "#pragma omp cancel"
3377 : "#pragma omp cancellation point";
3378 if (ctx == NULL)
3380 error_at (gimple_location (stmt), "orphaned %qs construct",
3381 construct);
3382 return false;
3384 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3385 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3386 : 0)
3388 case 1:
3389 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3390 bad = "#pragma omp parallel";
3391 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3392 == BUILT_IN_GOMP_CANCEL
3393 && !integer_zerop (gimple_call_arg (stmt, 1)))
3394 ctx->cancellable = true;
3395 kind = "parallel";
3396 break;
3397 case 2:
3398 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3399 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3400 bad = "#pragma omp for";
3401 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3402 == BUILT_IN_GOMP_CANCEL
3403 && !integer_zerop (gimple_call_arg (stmt, 1)))
3405 ctx->cancellable = true;
3406 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3407 OMP_CLAUSE_NOWAIT))
3408 warning_at (gimple_location (stmt), 0,
3409 "%<#pragma omp cancel for%> inside "
3410 "%<nowait%> for construct");
3411 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3412 OMP_CLAUSE_ORDERED))
3413 warning_at (gimple_location (stmt), 0,
3414 "%<#pragma omp cancel for%> inside "
3415 "%<ordered%> for construct");
3417 kind = "for";
3418 break;
3419 case 4:
3420 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3421 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3422 bad = "#pragma omp sections";
3423 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3424 == BUILT_IN_GOMP_CANCEL
3425 && !integer_zerop (gimple_call_arg (stmt, 1)))
3427 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3429 ctx->cancellable = true;
3430 if (find_omp_clause (gimple_omp_sections_clauses
3431 (ctx->stmt),
3432 OMP_CLAUSE_NOWAIT))
3433 warning_at (gimple_location (stmt), 0,
3434 "%<#pragma omp cancel sections%> inside "
3435 "%<nowait%> sections construct");
3437 else
3439 gcc_assert (ctx->outer
3440 && gimple_code (ctx->outer->stmt)
3441 == GIMPLE_OMP_SECTIONS);
3442 ctx->outer->cancellable = true;
3443 if (find_omp_clause (gimple_omp_sections_clauses
3444 (ctx->outer->stmt),
3445 OMP_CLAUSE_NOWAIT))
3446 warning_at (gimple_location (stmt), 0,
3447 "%<#pragma omp cancel sections%> inside "
3448 "%<nowait%> sections construct");
3451 kind = "sections";
3452 break;
3453 case 8:
3454 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3455 bad = "#pragma omp task";
3456 else
3458 for (omp_context *octx = ctx->outer;
3459 octx; octx = octx->outer)
3461 switch (gimple_code (octx->stmt))
3463 case GIMPLE_OMP_TASKGROUP:
3464 break;
3465 case GIMPLE_OMP_TARGET:
3466 if (gimple_omp_target_kind (octx->stmt)
3467 != GF_OMP_TARGET_KIND_REGION)
3468 continue;
3469 /* FALLTHRU */
3470 case GIMPLE_OMP_PARALLEL:
3471 case GIMPLE_OMP_TEAMS:
3472 error_at (gimple_location (stmt),
3473 "%<%s taskgroup%> construct not closely "
3474 "nested inside of %<taskgroup%> region",
3475 construct);
3476 return false;
3477 default:
3478 continue;
3480 break;
3482 ctx->cancellable = true;
3484 kind = "taskgroup";
3485 break;
3486 default:
3487 error_at (gimple_location (stmt), "invalid arguments");
3488 return false;
3490 if (bad)
3492 error_at (gimple_location (stmt),
3493 "%<%s %s%> construct not closely nested inside of %qs",
3494 construct, kind, bad);
3495 return false;
3498 /* FALLTHRU */
3499 case GIMPLE_OMP_SECTIONS:
3500 case GIMPLE_OMP_SINGLE:
3501 for (; ctx != NULL; ctx = ctx->outer)
3502 switch (gimple_code (ctx->stmt))
3504 case GIMPLE_OMP_FOR:
3505 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3506 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3507 break;
3508 /* FALLTHRU */
3509 case GIMPLE_OMP_SECTIONS:
3510 case GIMPLE_OMP_SINGLE:
3511 case GIMPLE_OMP_ORDERED:
3512 case GIMPLE_OMP_MASTER:
3513 case GIMPLE_OMP_TASK:
3514 case GIMPLE_OMP_CRITICAL:
3515 if (is_gimple_call (stmt))
3517 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3518 != BUILT_IN_GOMP_BARRIER)
3519 return true;
3520 error_at (gimple_location (stmt),
3521 "barrier region may not be closely nested inside "
3522 "of work-sharing, %<critical%>, %<ordered%>, "
3523 "%<master%>, explicit %<task%> or %<taskloop%> "
3524 "region");
3525 return false;
3527 error_at (gimple_location (stmt),
3528 "work-sharing region may not be closely nested inside "
3529 "of work-sharing, %<critical%>, %<ordered%>, "
3530 "%<master%>, explicit %<task%> or %<taskloop%> region");
3531 return false;
3532 case GIMPLE_OMP_PARALLEL:
3533 case GIMPLE_OMP_TEAMS:
3534 return true;
3535 case GIMPLE_OMP_TARGET:
3536 if (gimple_omp_target_kind (ctx->stmt)
3537 == GF_OMP_TARGET_KIND_REGION)
3538 return true;
3539 break;
3540 default:
3541 break;
3543 break;
3544 case GIMPLE_OMP_MASTER:
3545 for (; ctx != NULL; ctx = ctx->outer)
3546 switch (gimple_code (ctx->stmt))
3548 case GIMPLE_OMP_FOR:
3549 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3550 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3551 break;
3552 /* FALLTHRU */
3553 case GIMPLE_OMP_SECTIONS:
3554 case GIMPLE_OMP_SINGLE:
3555 case GIMPLE_OMP_TASK:
3556 error_at (gimple_location (stmt),
3557 "%<master%> region may not be closely nested inside "
3558 "of work-sharing, explicit %<task%> or %<taskloop%> "
3559 "region");
3560 return false;
3561 case GIMPLE_OMP_PARALLEL:
3562 case GIMPLE_OMP_TEAMS:
3563 return true;
3564 case GIMPLE_OMP_TARGET:
3565 if (gimple_omp_target_kind (ctx->stmt)
3566 == GF_OMP_TARGET_KIND_REGION)
3567 return true;
3568 break;
3569 default:
3570 break;
3572 break;
3573 case GIMPLE_OMP_TASK:
3574 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3575 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3576 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3577 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3579 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3580 error_at (OMP_CLAUSE_LOCATION (c),
3581 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3582 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3583 return false;
3585 break;
3586 case GIMPLE_OMP_ORDERED:
3587 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3588 c; c = OMP_CLAUSE_CHAIN (c))
3590 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3592 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3593 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3594 continue;
3596 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3597 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3598 || kind == OMP_CLAUSE_DEPEND_SINK)
3600 tree oclause;
3601 /* Look for containing ordered(N) loop. */
3602 if (ctx == NULL
3603 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3604 || (oclause
3605 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3606 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3608 error_at (OMP_CLAUSE_LOCATION (c),
3609 "%<ordered%> construct with %<depend%> clause "
3610 "must be closely nested inside an %<ordered%> "
3611 "loop");
3612 return false;
3614 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3616 error_at (OMP_CLAUSE_LOCATION (c),
3617 "%<ordered%> construct with %<depend%> clause "
3618 "must be closely nested inside a loop with "
3619 "%<ordered%> clause with a parameter");
3620 return false;
3623 else
3625 error_at (OMP_CLAUSE_LOCATION (c),
3626 "invalid depend kind in omp %<ordered%> %<depend%>");
3627 return false;
3630 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3631 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3633 /* ordered simd must be closely nested inside of simd region,
3634 and simd region must not encounter constructs other than
3635 ordered simd, therefore ordered simd may be either orphaned,
3636 or ctx->stmt must be simd. The latter case is handled already
3637 earlier. */
3638 if (ctx != NULL)
3640 error_at (gimple_location (stmt),
3641 "%<ordered%> %<simd%> must be closely nested inside "
3642 "%<simd%> region");
3643 return false;
3646 for (; ctx != NULL; ctx = ctx->outer)
3647 switch (gimple_code (ctx->stmt))
3649 case GIMPLE_OMP_CRITICAL:
3650 case GIMPLE_OMP_TASK:
3651 case GIMPLE_OMP_ORDERED:
3652 ordered_in_taskloop:
3653 error_at (gimple_location (stmt),
3654 "%<ordered%> region may not be closely nested inside "
3655 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3656 "%<taskloop%> region");
3657 return false;
3658 case GIMPLE_OMP_FOR:
3659 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3660 goto ordered_in_taskloop;
3661 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3662 OMP_CLAUSE_ORDERED) == NULL)
3664 error_at (gimple_location (stmt),
3665 "%<ordered%> region must be closely nested inside "
3666 "a loop region with an %<ordered%> clause");
3667 return false;
3669 return true;
3670 case GIMPLE_OMP_TARGET:
3671 if (gimple_omp_target_kind (ctx->stmt)
3672 != GF_OMP_TARGET_KIND_REGION)
3673 break;
3674 /* FALLTHRU */
3675 case GIMPLE_OMP_PARALLEL:
3676 case GIMPLE_OMP_TEAMS:
3677 error_at (gimple_location (stmt),
3678 "%<ordered%> region must be closely nested inside "
3679 "a loop region with an %<ordered%> clause");
3680 return false;
3681 default:
3682 break;
3684 break;
3685 case GIMPLE_OMP_CRITICAL:
3687 tree this_stmt_name
3688 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3689 for (; ctx != NULL; ctx = ctx->outer)
3690 if (gomp_critical *other_crit
3691 = dyn_cast <gomp_critical *> (ctx->stmt))
3692 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3694 error_at (gimple_location (stmt),
3695 "%<critical%> region may not be nested inside "
3696 "a %<critical%> region with the same name");
3697 return false;
3700 break;
3701 case GIMPLE_OMP_TEAMS:
3702 if (ctx == NULL
3703 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3704 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3706 error_at (gimple_location (stmt),
3707 "%<teams%> construct not closely nested inside of "
3708 "%<target%> construct");
3709 return false;
3711 break;
3712 case GIMPLE_OMP_TARGET:
3713 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3714 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3715 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3716 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3718 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3719 error_at (OMP_CLAUSE_LOCATION (c),
3720 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3721 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3722 return false;
3724 if (is_gimple_omp_offloaded (stmt)
3725 && get_oacc_fn_attrib (cfun->decl) != NULL)
3727 error_at (gimple_location (stmt),
3728 "OpenACC region inside of OpenACC routine, nested "
3729 "parallelism not supported yet");
3730 return false;
3732 for (; ctx != NULL; ctx = ctx->outer)
3734 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3736 if (is_gimple_omp (stmt)
3737 && is_gimple_omp_oacc (stmt)
3738 && is_gimple_omp (ctx->stmt))
3740 error_at (gimple_location (stmt),
3741 "OpenACC construct inside of non-OpenACC region");
3742 return false;
3744 continue;
3747 const char *stmt_name, *ctx_stmt_name;
3748 switch (gimple_omp_target_kind (stmt))
3750 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3751 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3752 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3753 case GF_OMP_TARGET_KIND_ENTER_DATA:
3754 stmt_name = "target enter data"; break;
3755 case GF_OMP_TARGET_KIND_EXIT_DATA:
3756 stmt_name = "target exit data"; break;
3757 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3758 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3759 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3760 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3761 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3762 stmt_name = "enter/exit data"; break;
3763 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3764 break;
3765 default: gcc_unreachable ();
3767 switch (gimple_omp_target_kind (ctx->stmt))
3769 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3770 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3771 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3772 ctx_stmt_name = "parallel"; break;
3773 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3774 ctx_stmt_name = "kernels"; break;
3775 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3776 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3777 ctx_stmt_name = "host_data"; break;
3778 default: gcc_unreachable ();
3781 /* OpenACC/OpenMP mismatch? */
3782 if (is_gimple_omp_oacc (stmt)
3783 != is_gimple_omp_oacc (ctx->stmt))
3785 error_at (gimple_location (stmt),
3786 "%s %qs construct inside of %s %qs region",
3787 (is_gimple_omp_oacc (stmt)
3788 ? "OpenACC" : "OpenMP"), stmt_name,
3789 (is_gimple_omp_oacc (ctx->stmt)
3790 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3791 return false;
3793 if (is_gimple_omp_offloaded (ctx->stmt))
3795 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3796 if (is_gimple_omp_oacc (ctx->stmt))
3798 error_at (gimple_location (stmt),
3799 "%qs construct inside of %qs region",
3800 stmt_name, ctx_stmt_name);
3801 return false;
3803 else
3805 warning_at (gimple_location (stmt), 0,
3806 "%qs construct inside of %qs region",
3807 stmt_name, ctx_stmt_name);
3811 break;
3812 default:
3813 break;
3815 return true;
3819 /* Helper function scan_omp.
3821 Callback for walk_tree or operators in walk_gimple_stmt used to
3822 scan for OMP directives in TP. */
3824 static tree
3825 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3827 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3828 omp_context *ctx = (omp_context *) wi->info;
3829 tree t = *tp;
3831 switch (TREE_CODE (t))
3833 case VAR_DECL:
3834 case PARM_DECL:
3835 case LABEL_DECL:
3836 case RESULT_DECL:
3837 if (ctx)
3839 tree repl = remap_decl (t, &ctx->cb);
3840 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3841 *tp = repl;
3843 break;
3845 default:
3846 if (ctx && TYPE_P (t))
3847 *tp = remap_type (t, &ctx->cb);
3848 else if (!DECL_P (t))
3850 *walk_subtrees = 1;
3851 if (ctx)
3853 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3854 if (tem != TREE_TYPE (t))
3856 if (TREE_CODE (t) == INTEGER_CST)
3857 *tp = wide_int_to_tree (tem, t);
3858 else
3859 TREE_TYPE (t) = tem;
3863 break;
3866 return NULL_TREE;
3869 /* Return true if FNDECL is a setjmp or a longjmp. */
3871 static bool
3872 setjmp_or_longjmp_p (const_tree fndecl)
3874 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3875 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3876 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3877 return true;
3879 tree declname = DECL_NAME (fndecl);
3880 if (!declname)
3881 return false;
3882 const char *name = IDENTIFIER_POINTER (declname);
3883 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3887 /* Helper function for scan_omp.
3889 Callback for walk_gimple_stmt used to scan for OMP directives in
3890 the current statement in GSI. */
3892 static tree
3893 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3894 struct walk_stmt_info *wi)
3896 gimple *stmt = gsi_stmt (*gsi);
3897 omp_context *ctx = (omp_context *) wi->info;
3899 if (gimple_has_location (stmt))
3900 input_location = gimple_location (stmt);
3902 /* Check the nesting restrictions. */
3903 bool remove = false;
3904 if (is_gimple_omp (stmt))
3905 remove = !check_omp_nesting_restrictions (stmt, ctx);
3906 else if (is_gimple_call (stmt))
3908 tree fndecl = gimple_call_fndecl (stmt);
3909 if (fndecl)
3911 if (setjmp_or_longjmp_p (fndecl)
3912 && ctx
3913 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3914 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3916 remove = true;
3917 error_at (gimple_location (stmt),
3918 "setjmp/longjmp inside simd construct");
3920 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3921 switch (DECL_FUNCTION_CODE (fndecl))
3923 case BUILT_IN_GOMP_BARRIER:
3924 case BUILT_IN_GOMP_CANCEL:
3925 case BUILT_IN_GOMP_CANCELLATION_POINT:
3926 case BUILT_IN_GOMP_TASKYIELD:
3927 case BUILT_IN_GOMP_TASKWAIT:
3928 case BUILT_IN_GOMP_TASKGROUP_START:
3929 case BUILT_IN_GOMP_TASKGROUP_END:
3930 remove = !check_omp_nesting_restrictions (stmt, ctx);
3931 break;
3932 default:
3933 break;
3937 if (remove)
3939 stmt = gimple_build_nop ();
3940 gsi_replace (gsi, stmt, false);
3943 *handled_ops_p = true;
3945 switch (gimple_code (stmt))
3947 case GIMPLE_OMP_PARALLEL:
3948 taskreg_nesting_level++;
3949 scan_omp_parallel (gsi, ctx);
3950 taskreg_nesting_level--;
3951 break;
3953 case GIMPLE_OMP_TASK:
3954 taskreg_nesting_level++;
3955 scan_omp_task (gsi, ctx);
3956 taskreg_nesting_level--;
3957 break;
3959 case GIMPLE_OMP_FOR:
3960 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3961 break;
3963 case GIMPLE_OMP_SECTIONS:
3964 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3965 break;
3967 case GIMPLE_OMP_SINGLE:
3968 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3969 break;
3971 case GIMPLE_OMP_SECTION:
3972 case GIMPLE_OMP_MASTER:
3973 case GIMPLE_OMP_TASKGROUP:
3974 case GIMPLE_OMP_ORDERED:
3975 case GIMPLE_OMP_CRITICAL:
3976 case GIMPLE_OMP_GRID_BODY:
3977 ctx = new_omp_context (stmt, ctx);
3978 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3979 break;
3981 case GIMPLE_OMP_TARGET:
3982 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3983 break;
3985 case GIMPLE_OMP_TEAMS:
3986 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3987 break;
3989 case GIMPLE_BIND:
3991 tree var;
3993 *handled_ops_p = false;
3994 if (ctx)
3995 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3996 var ;
3997 var = DECL_CHAIN (var))
3998 insert_decl_map (&ctx->cb, var, var);
4000 break;
4001 default:
4002 *handled_ops_p = false;
4003 break;
4006 return NULL_TREE;
4010 /* Scan all the statements starting at the current statement. CTX
4011 contains context information about the OMP directives and
4012 clauses found during the scan. */
4014 static void
4015 scan_omp (gimple_seq *body_p, omp_context *ctx)
4017 location_t saved_location;
4018 struct walk_stmt_info wi;
4020 memset (&wi, 0, sizeof (wi));
4021 wi.info = ctx;
4022 wi.want_locations = true;
4024 saved_location = input_location;
4025 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4026 input_location = saved_location;
4029 /* Re-gimplification and code generation routines. */
4031 /* Build a call to GOMP_barrier. */
4033 static gimple *
4034 build_omp_barrier (tree lhs)
4036 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4037 : BUILT_IN_GOMP_BARRIER);
4038 gcall *g = gimple_build_call (fndecl, 0);
4039 if (lhs)
4040 gimple_call_set_lhs (g, lhs);
4041 return g;
4044 /* If a context was created for STMT when it was scanned, return it. */
4046 static omp_context *
4047 maybe_lookup_ctx (gimple *stmt)
4049 splay_tree_node n;
4050 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4051 return n ? (omp_context *) n->value : NULL;
4055 /* Find the mapping for DECL in CTX or the immediately enclosing
4056 context that has a mapping for DECL.
4058 If CTX is a nested parallel directive, we may have to use the decl
4059 mappings created in CTX's parent context. Suppose that we have the
4060 following parallel nesting (variable UIDs showed for clarity):
4062 iD.1562 = 0;
4063 #omp parallel shared(iD.1562) -> outer parallel
4064 iD.1562 = iD.1562 + 1;
4066 #omp parallel shared (iD.1562) -> inner parallel
4067 iD.1562 = iD.1562 - 1;
4069 Each parallel structure will create a distinct .omp_data_s structure
4070 for copying iD.1562 in/out of the directive:
4072 outer parallel .omp_data_s.1.i -> iD.1562
4073 inner parallel .omp_data_s.2.i -> iD.1562
4075 A shared variable mapping will produce a copy-out operation before
4076 the parallel directive and a copy-in operation after it. So, in
4077 this case we would have:
4079 iD.1562 = 0;
4080 .omp_data_o.1.i = iD.1562;
4081 #omp parallel shared(iD.1562) -> outer parallel
4082 .omp_data_i.1 = &.omp_data_o.1
4083 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4085 .omp_data_o.2.i = iD.1562; -> **
4086 #omp parallel shared(iD.1562) -> inner parallel
4087 .omp_data_i.2 = &.omp_data_o.2
4088 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4091 ** This is a problem. The symbol iD.1562 cannot be referenced
4092 inside the body of the outer parallel region. But since we are
4093 emitting this copy operation while expanding the inner parallel
4094 directive, we need to access the CTX structure of the outer
4095 parallel directive to get the correct mapping:
4097 .omp_data_o.2.i = .omp_data_i.1->i
4099 Since there may be other workshare or parallel directives enclosing
4100 the parallel directive, it may be necessary to walk up the context
4101 parent chain. This is not a problem in general because nested
4102 parallelism happens only rarely. */
4104 static tree
4105 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4107 tree t;
4108 omp_context *up;
4110 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4111 t = maybe_lookup_decl (decl, up);
4113 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4115 return t ? t : decl;
4119 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4120 in outer contexts. */
4122 static tree
4123 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4125 tree t = NULL;
4126 omp_context *up;
4128 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4129 t = maybe_lookup_decl (decl, up);
4131 return t ? t : decl;
4135 /* Construct the initialization value for reduction operation OP. */
4137 tree
4138 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4140 switch (op)
4142 case PLUS_EXPR:
4143 case MINUS_EXPR:
4144 case BIT_IOR_EXPR:
4145 case BIT_XOR_EXPR:
4146 case TRUTH_OR_EXPR:
4147 case TRUTH_ORIF_EXPR:
4148 case TRUTH_XOR_EXPR:
4149 case NE_EXPR:
4150 return build_zero_cst (type);
4152 case MULT_EXPR:
4153 case TRUTH_AND_EXPR:
4154 case TRUTH_ANDIF_EXPR:
4155 case EQ_EXPR:
4156 return fold_convert_loc (loc, type, integer_one_node);
4158 case BIT_AND_EXPR:
4159 return fold_convert_loc (loc, type, integer_minus_one_node);
4161 case MAX_EXPR:
4162 if (SCALAR_FLOAT_TYPE_P (type))
4164 REAL_VALUE_TYPE max, min;
4165 if (HONOR_INFINITIES (type))
4167 real_inf (&max);
4168 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4170 else
4171 real_maxval (&min, 1, TYPE_MODE (type));
4172 return build_real (type, min);
4174 else if (POINTER_TYPE_P (type))
4176 wide_int min
4177 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4178 return wide_int_to_tree (type, min);
4180 else
4182 gcc_assert (INTEGRAL_TYPE_P (type));
4183 return TYPE_MIN_VALUE (type);
4186 case MIN_EXPR:
4187 if (SCALAR_FLOAT_TYPE_P (type))
4189 REAL_VALUE_TYPE max;
4190 if (HONOR_INFINITIES (type))
4191 real_inf (&max);
4192 else
4193 real_maxval (&max, 0, TYPE_MODE (type));
4194 return build_real (type, max);
4196 else if (POINTER_TYPE_P (type))
4198 wide_int max
4199 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4200 return wide_int_to_tree (type, max);
4202 else
4204 gcc_assert (INTEGRAL_TYPE_P (type));
4205 return TYPE_MAX_VALUE (type);
4208 default:
4209 gcc_unreachable ();
4213 /* Construct the initialization value for reduction CLAUSE. */
4215 tree
4216 omp_reduction_init (tree clause, tree type)
4218 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4219 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4222 /* Return alignment to be assumed for var in CLAUSE, which should be
4223 OMP_CLAUSE_ALIGNED. */
4225 static tree
4226 omp_clause_aligned_alignment (tree clause)
4228 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4229 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4231 /* Otherwise return implementation defined alignment. */
4232 unsigned int al = 1;
4233 machine_mode mode, vmode;
4234 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4235 if (vs)
4236 vs = 1 << floor_log2 (vs);
4237 static enum mode_class classes[]
4238 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4239 for (int i = 0; i < 4; i += 2)
4240 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4241 mode != VOIDmode;
4242 mode = GET_MODE_WIDER_MODE (mode))
4244 vmode = targetm.vectorize.preferred_simd_mode (mode);
4245 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4246 continue;
4247 while (vs
4248 && GET_MODE_SIZE (vmode) < vs
4249 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4250 vmode = GET_MODE_2XWIDER_MODE (vmode);
4252 tree type = lang_hooks.types.type_for_mode (mode, 1);
4253 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4254 continue;
4255 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4256 / GET_MODE_SIZE (mode));
4257 if (TYPE_MODE (type) != vmode)
4258 continue;
4259 if (TYPE_ALIGN_UNIT (type) > al)
4260 al = TYPE_ALIGN_UNIT (type);
4262 return build_int_cst (integer_type_node, al);
4265 /* Return maximum possible vectorization factor for the target. */
4267 static int
4268 omp_max_vf (void)
4270 if (!optimize
4271 || optimize_debug
4272 || !flag_tree_loop_optimize
4273 || (!flag_tree_loop_vectorize
4274 && (global_options_set.x_flag_tree_loop_vectorize
4275 || global_options_set.x_flag_tree_vectorize)))
4276 return 1;
4278 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4279 if (vs)
4281 vs = 1 << floor_log2 (vs);
4282 return vs;
4284 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4285 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4286 return GET_MODE_NUNITS (vqimode);
4287 return 1;
4290 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4291 privatization. */
4293 static bool
4294 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4295 tree &idx, tree &lane, tree &ivar, tree &lvar)
4297 if (max_vf == 0)
4299 max_vf = omp_max_vf ();
4300 if (max_vf > 1)
4302 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4303 OMP_CLAUSE_SAFELEN);
4304 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4305 max_vf = 1;
4306 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4307 max_vf) == -1)
4308 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4310 if (max_vf > 1)
4312 idx = create_tmp_var (unsigned_type_node);
4313 lane = create_tmp_var (unsigned_type_node);
4316 if (max_vf == 1)
4317 return false;
4319 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4320 tree avar = create_tmp_var_raw (atype);
4321 if (TREE_ADDRESSABLE (new_var))
4322 TREE_ADDRESSABLE (avar) = 1;
4323 DECL_ATTRIBUTES (avar)
4324 = tree_cons (get_identifier ("omp simd array"), NULL,
4325 DECL_ATTRIBUTES (avar));
4326 gimple_add_tmp_var (avar);
4327 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4328 NULL_TREE, NULL_TREE);
4329 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4330 NULL_TREE, NULL_TREE);
4331 if (DECL_P (new_var))
4333 SET_DECL_VALUE_EXPR (new_var, lvar);
4334 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4336 return true;
4339 /* Helper function of lower_rec_input_clauses. For a reference
4340 in simd reduction, add an underlying variable it will reference. */
4342 static void
4343 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4345 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4346 if (TREE_CONSTANT (z))
4348 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4349 get_name (new_vard));
4350 gimple_add_tmp_var (z);
4351 TREE_ADDRESSABLE (z) = 1;
4352 z = build_fold_addr_expr_loc (loc, z);
4353 gimplify_assign (new_vard, z, ilist);
4357 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4358 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4359 private variables. Initialization statements go in ILIST, while calls
4360 to destructors go in DLIST. */
4362 static void
4363 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4364 omp_context *ctx, struct omp_for_data *fd)
4366 tree c, dtor, copyin_seq, x, ptr;
4367 bool copyin_by_ref = false;
4368 bool lastprivate_firstprivate = false;
4369 bool reduction_omp_orig_ref = false;
4370 int pass;
4371 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4372 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4373 int max_vf = 0;
4374 tree lane = NULL_TREE, idx = NULL_TREE;
4375 tree ivar = NULL_TREE, lvar = NULL_TREE;
4376 gimple_seq llist[2] = { NULL, NULL };
4378 copyin_seq = NULL;
4380 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4381 with data sharing clauses referencing variable sized vars. That
4382 is unnecessarily hard to support and very unlikely to result in
4383 vectorized code anyway. */
4384 if (is_simd)
4385 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4386 switch (OMP_CLAUSE_CODE (c))
4388 case OMP_CLAUSE_LINEAR:
4389 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4390 max_vf = 1;
4391 /* FALLTHRU */
4392 case OMP_CLAUSE_PRIVATE:
4393 case OMP_CLAUSE_FIRSTPRIVATE:
4394 case OMP_CLAUSE_LASTPRIVATE:
4395 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4396 max_vf = 1;
4397 break;
4398 case OMP_CLAUSE_REDUCTION:
4399 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4400 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4401 max_vf = 1;
4402 break;
4403 default:
4404 continue;
4407 /* Do all the fixed sized types in the first pass, and the variable sized
4408 types in the second pass. This makes sure that the scalar arguments to
4409 the variable sized types are processed before we use them in the
4410 variable sized operations. */
4411 for (pass = 0; pass < 2; ++pass)
4413 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4415 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4416 tree var, new_var;
4417 bool by_ref;
4418 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4420 switch (c_kind)
4422 case OMP_CLAUSE_PRIVATE:
4423 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4424 continue;
4425 break;
4426 case OMP_CLAUSE_SHARED:
4427 /* Ignore shared directives in teams construct. */
4428 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4429 continue;
4430 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4432 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4433 || is_global_var (OMP_CLAUSE_DECL (c)));
4434 continue;
4436 case OMP_CLAUSE_FIRSTPRIVATE:
4437 case OMP_CLAUSE_COPYIN:
4438 break;
4439 case OMP_CLAUSE_LINEAR:
4440 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4441 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4442 lastprivate_firstprivate = true;
4443 break;
4444 case OMP_CLAUSE_REDUCTION:
4445 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4446 reduction_omp_orig_ref = true;
4447 break;
4448 case OMP_CLAUSE__LOOPTEMP_:
4449 /* Handle _looptemp_ clauses only on parallel/task. */
4450 if (fd)
4451 continue;
4452 break;
4453 case OMP_CLAUSE_LASTPRIVATE:
4454 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4456 lastprivate_firstprivate = true;
4457 if (pass != 0 || is_taskloop_ctx (ctx))
4458 continue;
4460 /* Even without corresponding firstprivate, if
4461 decl is Fortran allocatable, it needs outer var
4462 reference. */
4463 else if (pass == 0
4464 && lang_hooks.decls.omp_private_outer_ref
4465 (OMP_CLAUSE_DECL (c)))
4466 lastprivate_firstprivate = true;
4467 break;
4468 case OMP_CLAUSE_ALIGNED:
4469 if (pass == 0)
4470 continue;
4471 var = OMP_CLAUSE_DECL (c);
4472 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4473 && !is_global_var (var))
4475 new_var = maybe_lookup_decl (var, ctx);
4476 if (new_var == NULL_TREE)
4477 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4478 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4479 tree alarg = omp_clause_aligned_alignment (c);
4480 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4481 x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
4482 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4483 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4484 gimplify_and_add (x, ilist);
4486 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4487 && is_global_var (var))
4489 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4490 new_var = lookup_decl (var, ctx);
4491 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4492 t = build_fold_addr_expr_loc (clause_loc, t);
4493 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4494 tree alarg = omp_clause_aligned_alignment (c);
4495 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4496 t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
4497 t = fold_convert_loc (clause_loc, ptype, t);
4498 x = create_tmp_var (ptype);
4499 t = build2 (MODIFY_EXPR, ptype, x, t);
4500 gimplify_and_add (t, ilist);
4501 t = build_simple_mem_ref_loc (clause_loc, x);
4502 SET_DECL_VALUE_EXPR (new_var, t);
4503 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4505 continue;
4506 default:
4507 continue;
4510 new_var = var = OMP_CLAUSE_DECL (c);
4511 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4513 var = TREE_OPERAND (var, 0);
4514 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4515 var = TREE_OPERAND (var, 0);
4516 if (TREE_CODE (var) == INDIRECT_REF
4517 || TREE_CODE (var) == ADDR_EXPR)
4518 var = TREE_OPERAND (var, 0);
4519 if (is_variable_sized (var))
4521 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4522 var = DECL_VALUE_EXPR (var);
4523 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4524 var = TREE_OPERAND (var, 0);
4525 gcc_assert (DECL_P (var));
4527 new_var = var;
4529 if (c_kind != OMP_CLAUSE_COPYIN)
4530 new_var = lookup_decl (var, ctx);
4532 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4534 if (pass != 0)
4535 continue;
4537 /* C/C++ array section reductions. */
4538 else if (c_kind == OMP_CLAUSE_REDUCTION
4539 && var != OMP_CLAUSE_DECL (c))
4541 if (pass == 0)
4542 continue;
4544 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4545 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4546 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4548 tree b = TREE_OPERAND (orig_var, 1);
4549 b = maybe_lookup_decl (b, ctx);
4550 if (b == NULL)
4552 b = TREE_OPERAND (orig_var, 1);
4553 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4555 if (integer_zerop (bias))
4556 bias = b;
4557 else
4559 bias = fold_convert_loc (clause_loc,
4560 TREE_TYPE (b), bias);
4561 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4562 TREE_TYPE (b), b, bias);
4564 orig_var = TREE_OPERAND (orig_var, 0);
4566 if (TREE_CODE (orig_var) == INDIRECT_REF
4567 || TREE_CODE (orig_var) == ADDR_EXPR)
4568 orig_var = TREE_OPERAND (orig_var, 0);
4569 tree d = OMP_CLAUSE_DECL (c);
4570 tree type = TREE_TYPE (d);
4571 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4572 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4573 const char *name = get_name (orig_var);
4574 if (TREE_CONSTANT (v))
4576 x = create_tmp_var_raw (type, name);
4577 gimple_add_tmp_var (x);
4578 TREE_ADDRESSABLE (x) = 1;
4579 x = build_fold_addr_expr_loc (clause_loc, x);
4581 else
4583 tree atmp
4584 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4585 tree t = maybe_lookup_decl (v, ctx);
4586 if (t)
4587 v = t;
4588 else
4589 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4590 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4591 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4592 TREE_TYPE (v), v,
4593 build_int_cst (TREE_TYPE (v), 1));
4594 t = fold_build2_loc (clause_loc, MULT_EXPR,
4595 TREE_TYPE (v), t,
4596 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4597 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4598 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4601 tree ptype = build_pointer_type (TREE_TYPE (type));
4602 x = fold_convert_loc (clause_loc, ptype, x);
4603 tree y = create_tmp_var (ptype, name);
4604 gimplify_assign (y, x, ilist);
4605 x = y;
4606 tree yb = y;
4608 if (!integer_zerop (bias))
4610 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4611 bias);
4612 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4614 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4615 pointer_sized_int_node, yb, bias);
4616 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4617 yb = create_tmp_var (ptype, name);
4618 gimplify_assign (yb, x, ilist);
4619 x = yb;
4622 d = TREE_OPERAND (d, 0);
4623 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4624 d = TREE_OPERAND (d, 0);
4625 if (TREE_CODE (d) == ADDR_EXPR)
4627 if (orig_var != var)
4629 gcc_assert (is_variable_sized (orig_var));
4630 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4632 gimplify_assign (new_var, x, ilist);
4633 tree new_orig_var = lookup_decl (orig_var, ctx);
4634 tree t = build_fold_indirect_ref (new_var);
4635 DECL_IGNORED_P (new_var) = 0;
4636 TREE_THIS_NOTRAP (t);
4637 SET_DECL_VALUE_EXPR (new_orig_var, t);
4638 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4640 else
4642 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4643 build_int_cst (ptype, 0));
4644 SET_DECL_VALUE_EXPR (new_var, x);
4645 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4648 else
4650 gcc_assert (orig_var == var);
4651 if (TREE_CODE (d) == INDIRECT_REF)
4653 x = create_tmp_var (ptype, name);
4654 TREE_ADDRESSABLE (x) = 1;
4655 gimplify_assign (x, yb, ilist);
4656 x = build_fold_addr_expr_loc (clause_loc, x);
4658 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4659 gimplify_assign (new_var, x, ilist);
4661 tree y1 = create_tmp_var (ptype, NULL);
4662 gimplify_assign (y1, y, ilist);
4663 tree i2 = NULL_TREE, y2 = NULL_TREE;
4664 tree body2 = NULL_TREE, end2 = NULL_TREE;
4665 tree y3 = NULL_TREE, y4 = NULL_TREE;
4666 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4668 y2 = create_tmp_var (ptype, NULL);
4669 gimplify_assign (y2, y, ilist);
4670 tree ref = build_outer_var_ref (var, ctx);
4671 /* For ref build_outer_var_ref already performs this. */
4672 if (TREE_CODE (d) == INDIRECT_REF)
4673 gcc_assert (is_reference (var));
4674 else if (TREE_CODE (d) == ADDR_EXPR)
4675 ref = build_fold_addr_expr (ref);
4676 else if (is_reference (var))
4677 ref = build_fold_addr_expr (ref);
4678 ref = fold_convert_loc (clause_loc, ptype, ref);
4679 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4680 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4682 y3 = create_tmp_var (ptype, NULL);
4683 gimplify_assign (y3, unshare_expr (ref), ilist);
4685 if (is_simd)
4687 y4 = create_tmp_var (ptype, NULL);
4688 gimplify_assign (y4, ref, dlist);
4691 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4692 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4693 tree body = create_artificial_label (UNKNOWN_LOCATION);
4694 tree end = create_artificial_label (UNKNOWN_LOCATION);
4695 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4696 if (y2)
4698 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4699 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4700 body2 = create_artificial_label (UNKNOWN_LOCATION);
4701 end2 = create_artificial_label (UNKNOWN_LOCATION);
4702 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4704 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4706 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4707 tree decl_placeholder
4708 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4709 SET_DECL_VALUE_EXPR (decl_placeholder,
4710 build_simple_mem_ref (y1));
4711 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4712 SET_DECL_VALUE_EXPR (placeholder,
4713 y3 ? build_simple_mem_ref (y3)
4714 : error_mark_node);
4715 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4716 x = lang_hooks.decls.omp_clause_default_ctor
4717 (c, build_simple_mem_ref (y1),
4718 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4719 if (x)
4720 gimplify_and_add (x, ilist);
4721 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4723 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4724 lower_omp (&tseq, ctx);
4725 gimple_seq_add_seq (ilist, tseq);
4727 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4728 if (is_simd)
4730 SET_DECL_VALUE_EXPR (decl_placeholder,
4731 build_simple_mem_ref (y2));
4732 SET_DECL_VALUE_EXPR (placeholder,
4733 build_simple_mem_ref (y4));
4734 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4735 lower_omp (&tseq, ctx);
4736 gimple_seq_add_seq (dlist, tseq);
4737 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4739 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4740 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4741 x = lang_hooks.decls.omp_clause_dtor
4742 (c, build_simple_mem_ref (y2));
4743 if (x)
4745 gimple_seq tseq = NULL;
4746 dtor = x;
4747 gimplify_stmt (&dtor, &tseq);
4748 gimple_seq_add_seq (dlist, tseq);
4751 else
4753 x = omp_reduction_init (c, TREE_TYPE (type));
4754 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4756 /* reduction(-:var) sums up the partial results, so it
4757 acts identically to reduction(+:var). */
4758 if (code == MINUS_EXPR)
4759 code = PLUS_EXPR;
4761 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4762 if (is_simd)
4764 x = build2 (code, TREE_TYPE (type),
4765 build_simple_mem_ref (y4),
4766 build_simple_mem_ref (y2));
4767 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4770 gimple *g
4771 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4772 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4773 gimple_seq_add_stmt (ilist, g);
4774 if (y3)
4776 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4777 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4778 gimple_seq_add_stmt (ilist, g);
4780 g = gimple_build_assign (i, PLUS_EXPR, i,
4781 build_int_cst (TREE_TYPE (i), 1));
4782 gimple_seq_add_stmt (ilist, g);
4783 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4784 gimple_seq_add_stmt (ilist, g);
4785 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4786 if (y2)
4788 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4789 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4790 gimple_seq_add_stmt (dlist, g);
4791 if (y4)
4793 g = gimple_build_assign
4794 (y4, POINTER_PLUS_EXPR, y4,
4795 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4796 gimple_seq_add_stmt (dlist, g);
4798 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4799 build_int_cst (TREE_TYPE (i2), 1));
4800 gimple_seq_add_stmt (dlist, g);
4801 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4802 gimple_seq_add_stmt (dlist, g);
4803 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4805 continue;
4807 else if (is_variable_sized (var))
4809 /* For variable sized types, we need to allocate the
4810 actual storage here. Call alloca and store the
4811 result in the pointer decl that we created elsewhere. */
4812 if (pass == 0)
4813 continue;
4815 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4817 gcall *stmt;
4818 tree tmp, atmp;
4820 ptr = DECL_VALUE_EXPR (new_var);
4821 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4822 ptr = TREE_OPERAND (ptr, 0);
4823 gcc_assert (DECL_P (ptr));
4824 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4826 /* void *tmp = __builtin_alloca */
4827 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4828 stmt = gimple_build_call (atmp, 2, x,
4829 size_int (DECL_ALIGN (var)));
4830 tmp = create_tmp_var_raw (ptr_type_node);
4831 gimple_add_tmp_var (tmp);
4832 gimple_call_set_lhs (stmt, tmp);
4834 gimple_seq_add_stmt (ilist, stmt);
4836 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4837 gimplify_assign (ptr, x, ilist);
4840 else if (is_reference (var))
4842 /* For references that are being privatized for Fortran,
4843 allocate new backing storage for the new pointer
4844 variable. This allows us to avoid changing all the
4845 code that expects a pointer to something that expects
4846 a direct variable. */
4847 if (pass == 0)
4848 continue;
4850 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4851 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4853 x = build_receiver_ref (var, false, ctx);
4854 x = build_fold_addr_expr_loc (clause_loc, x);
4856 else if (TREE_CONSTANT (x))
4858 /* For reduction in SIMD loop, defer adding the
4859 initialization of the reference, because if we decide
4860 to use SIMD array for it, the initilization could cause
4861 expansion ICE. */
4862 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4863 x = NULL_TREE;
4864 else
4866 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4867 get_name (var));
4868 gimple_add_tmp_var (x);
4869 TREE_ADDRESSABLE (x) = 1;
4870 x = build_fold_addr_expr_loc (clause_loc, x);
4873 else
4875 tree atmp
4876 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4877 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4878 tree al = size_int (TYPE_ALIGN (rtype));
4879 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4882 if (x)
4884 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4885 gimplify_assign (new_var, x, ilist);
4888 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4890 else if (c_kind == OMP_CLAUSE_REDUCTION
4891 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4893 if (pass == 0)
4894 continue;
4896 else if (pass != 0)
4897 continue;
4899 switch (OMP_CLAUSE_CODE (c))
4901 case OMP_CLAUSE_SHARED:
4902 /* Ignore shared directives in teams construct. */
4903 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4904 continue;
4905 /* Shared global vars are just accessed directly. */
4906 if (is_global_var (new_var))
4907 break;
4908 /* For taskloop firstprivate/lastprivate, represented
4909 as firstprivate and shared clause on the task, new_var
4910 is the firstprivate var. */
4911 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4912 break;
4913 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4914 needs to be delayed until after fixup_child_record_type so
4915 that we get the correct type during the dereference. */
4916 by_ref = use_pointer_for_field (var, ctx);
4917 x = build_receiver_ref (var, by_ref, ctx);
4918 SET_DECL_VALUE_EXPR (new_var, x);
4919 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4921 /* ??? If VAR is not passed by reference, and the variable
4922 hasn't been initialized yet, then we'll get a warning for
4923 the store into the omp_data_s structure. Ideally, we'd be
4924 able to notice this and not store anything at all, but
4925 we're generating code too early. Suppress the warning. */
4926 if (!by_ref)
4927 TREE_NO_WARNING (var) = 1;
4928 break;
4930 case OMP_CLAUSE_LASTPRIVATE:
4931 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4932 break;
4933 /* FALLTHRU */
4935 case OMP_CLAUSE_PRIVATE:
4936 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4937 x = build_outer_var_ref (var, ctx);
4938 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4940 if (is_task_ctx (ctx))
4941 x = build_receiver_ref (var, false, ctx);
4942 else
4943 x = build_outer_var_ref (var, ctx);
4945 else
4946 x = NULL;
4947 do_private:
4948 tree nx;
4949 nx = lang_hooks.decls.omp_clause_default_ctor
4950 (c, unshare_expr (new_var), x);
4951 if (is_simd)
4953 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4954 if ((TREE_ADDRESSABLE (new_var) || nx || y
4955 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4956 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4957 idx, lane, ivar, lvar))
4959 if (nx)
4960 x = lang_hooks.decls.omp_clause_default_ctor
4961 (c, unshare_expr (ivar), x);
4962 if (nx && x)
4963 gimplify_and_add (x, &llist[0]);
4964 if (y)
4966 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4967 if (y)
4969 gimple_seq tseq = NULL;
4971 dtor = y;
4972 gimplify_stmt (&dtor, &tseq);
4973 gimple_seq_add_seq (&llist[1], tseq);
4976 break;
4979 if (nx)
4980 gimplify_and_add (nx, ilist);
4981 /* FALLTHRU */
4983 do_dtor:
4984 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4985 if (x)
4987 gimple_seq tseq = NULL;
4989 dtor = x;
4990 gimplify_stmt (&dtor, &tseq);
4991 gimple_seq_add_seq (dlist, tseq);
4993 break;
4995 case OMP_CLAUSE_LINEAR:
4996 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4997 goto do_firstprivate;
4998 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4999 x = NULL;
5000 else
5001 x = build_outer_var_ref (var, ctx);
5002 goto do_private;
5004 case OMP_CLAUSE_FIRSTPRIVATE:
5005 if (is_task_ctx (ctx))
5007 if (is_reference (var) || is_variable_sized (var))
5008 goto do_dtor;
5009 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5010 ctx))
5011 || use_pointer_for_field (var, NULL))
5013 x = build_receiver_ref (var, false, ctx);
5014 SET_DECL_VALUE_EXPR (new_var, x);
5015 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5016 goto do_dtor;
5019 do_firstprivate:
5020 x = build_outer_var_ref (var, ctx);
5021 if (is_simd)
5023 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5024 && gimple_omp_for_combined_into_p (ctx->stmt))
5026 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5027 tree stept = TREE_TYPE (t);
5028 tree ct = find_omp_clause (clauses,
5029 OMP_CLAUSE__LOOPTEMP_);
5030 gcc_assert (ct);
5031 tree l = OMP_CLAUSE_DECL (ct);
5032 tree n1 = fd->loop.n1;
5033 tree step = fd->loop.step;
5034 tree itype = TREE_TYPE (l);
5035 if (POINTER_TYPE_P (itype))
5036 itype = signed_type_for (itype);
5037 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5038 if (TYPE_UNSIGNED (itype)
5039 && fd->loop.cond_code == GT_EXPR)
5040 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5041 fold_build1 (NEGATE_EXPR, itype, l),
5042 fold_build1 (NEGATE_EXPR,
5043 itype, step));
5044 else
5045 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5046 t = fold_build2 (MULT_EXPR, stept,
5047 fold_convert (stept, l), t);
5049 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5051 x = lang_hooks.decls.omp_clause_linear_ctor
5052 (c, new_var, x, t);
5053 gimplify_and_add (x, ilist);
5054 goto do_dtor;
5057 if (POINTER_TYPE_P (TREE_TYPE (x)))
5058 x = fold_build2 (POINTER_PLUS_EXPR,
5059 TREE_TYPE (x), x, t);
5060 else
5061 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5064 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5065 || TREE_ADDRESSABLE (new_var))
5066 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5067 idx, lane, ivar, lvar))
5069 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5071 tree iv = create_tmp_var (TREE_TYPE (new_var));
5072 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5073 gimplify_and_add (x, ilist);
5074 gimple_stmt_iterator gsi
5075 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5076 gassign *g
5077 = gimple_build_assign (unshare_expr (lvar), iv);
5078 gsi_insert_before_without_update (&gsi, g,
5079 GSI_SAME_STMT);
5080 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5081 enum tree_code code = PLUS_EXPR;
5082 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5083 code = POINTER_PLUS_EXPR;
5084 g = gimple_build_assign (iv, code, iv, t);
5085 gsi_insert_before_without_update (&gsi, g,
5086 GSI_SAME_STMT);
5087 break;
5089 x = lang_hooks.decls.omp_clause_copy_ctor
5090 (c, unshare_expr (ivar), x);
5091 gimplify_and_add (x, &llist[0]);
5092 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5093 if (x)
5095 gimple_seq tseq = NULL;
5097 dtor = x;
5098 gimplify_stmt (&dtor, &tseq);
5099 gimple_seq_add_seq (&llist[1], tseq);
5101 break;
5104 x = lang_hooks.decls.omp_clause_copy_ctor
5105 (c, unshare_expr (new_var), x);
5106 gimplify_and_add (x, ilist);
5107 goto do_dtor;
5109 case OMP_CLAUSE__LOOPTEMP_:
5110 gcc_assert (is_taskreg_ctx (ctx));
5111 x = build_outer_var_ref (var, ctx);
5112 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5113 gimplify_and_add (x, ilist);
5114 break;
5116 case OMP_CLAUSE_COPYIN:
5117 by_ref = use_pointer_for_field (var, NULL);
5118 x = build_receiver_ref (var, by_ref, ctx);
5119 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5120 append_to_statement_list (x, &copyin_seq);
5121 copyin_by_ref |= by_ref;
5122 break;
5124 case OMP_CLAUSE_REDUCTION:
5125 /* OpenACC reductions are initialized using the
5126 GOACC_REDUCTION internal function. */
5127 if (is_gimple_omp_oacc (ctx->stmt))
5128 break;
5129 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5131 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5132 gimple *tseq;
5133 x = build_outer_var_ref (var, ctx);
5135 if (is_reference (var)
5136 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5137 TREE_TYPE (x)))
5138 x = build_fold_addr_expr_loc (clause_loc, x);
5139 SET_DECL_VALUE_EXPR (placeholder, x);
5140 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5141 tree new_vard = new_var;
5142 if (is_reference (var))
5144 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5145 new_vard = TREE_OPERAND (new_var, 0);
5146 gcc_assert (DECL_P (new_vard));
5148 if (is_simd
5149 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5150 idx, lane, ivar, lvar))
5152 if (new_vard == new_var)
5154 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5155 SET_DECL_VALUE_EXPR (new_var, ivar);
5157 else
5159 SET_DECL_VALUE_EXPR (new_vard,
5160 build_fold_addr_expr (ivar));
5161 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5163 x = lang_hooks.decls.omp_clause_default_ctor
5164 (c, unshare_expr (ivar),
5165 build_outer_var_ref (var, ctx));
5166 if (x)
5167 gimplify_and_add (x, &llist[0]);
5168 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5170 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5171 lower_omp (&tseq, ctx);
5172 gimple_seq_add_seq (&llist[0], tseq);
5174 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5175 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5176 lower_omp (&tseq, ctx);
5177 gimple_seq_add_seq (&llist[1], tseq);
5178 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5179 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5180 if (new_vard == new_var)
5181 SET_DECL_VALUE_EXPR (new_var, lvar);
5182 else
5183 SET_DECL_VALUE_EXPR (new_vard,
5184 build_fold_addr_expr (lvar));
5185 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5186 if (x)
5188 tseq = NULL;
5189 dtor = x;
5190 gimplify_stmt (&dtor, &tseq);
5191 gimple_seq_add_seq (&llist[1], tseq);
5193 break;
5195 /* If this is a reference to constant size reduction var
5196 with placeholder, we haven't emitted the initializer
5197 for it because it is undesirable if SIMD arrays are used.
5198 But if they aren't used, we need to emit the deferred
5199 initialization now. */
5200 else if (is_reference (var) && is_simd)
5201 handle_simd_reference (clause_loc, new_vard, ilist);
5202 x = lang_hooks.decls.omp_clause_default_ctor
5203 (c, unshare_expr (new_var),
5204 build_outer_var_ref (var, ctx));
5205 if (x)
5206 gimplify_and_add (x, ilist);
5207 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5209 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5210 lower_omp (&tseq, ctx);
5211 gimple_seq_add_seq (ilist, tseq);
5213 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5214 if (is_simd)
5216 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5217 lower_omp (&tseq, ctx);
5218 gimple_seq_add_seq (dlist, tseq);
5219 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5221 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5222 goto do_dtor;
5224 else
5226 x = omp_reduction_init (c, TREE_TYPE (new_var));
5227 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5228 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5230 /* reduction(-:var) sums up the partial results, so it
5231 acts identically to reduction(+:var). */
5232 if (code == MINUS_EXPR)
5233 code = PLUS_EXPR;
5235 tree new_vard = new_var;
5236 if (is_simd && is_reference (var))
5238 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5239 new_vard = TREE_OPERAND (new_var, 0);
5240 gcc_assert (DECL_P (new_vard));
5242 if (is_simd
5243 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5244 idx, lane, ivar, lvar))
5246 tree ref = build_outer_var_ref (var, ctx);
5248 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5250 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5251 ref = build_outer_var_ref (var, ctx);
5252 gimplify_assign (ref, x, &llist[1]);
5254 if (new_vard != new_var)
5256 SET_DECL_VALUE_EXPR (new_vard,
5257 build_fold_addr_expr (lvar));
5258 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5261 else
5263 if (is_reference (var) && is_simd)
5264 handle_simd_reference (clause_loc, new_vard, ilist);
5265 gimplify_assign (new_var, x, ilist);
5266 if (is_simd)
5268 tree ref = build_outer_var_ref (var, ctx);
5270 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5271 ref = build_outer_var_ref (var, ctx);
5272 gimplify_assign (ref, x, dlist);
5276 break;
5278 default:
5279 gcc_unreachable ();
5284 if (lane)
5286 tree uid = create_tmp_var (ptr_type_node, "simduid");
5287 /* Don't want uninit warnings on simduid, it is always uninitialized,
5288 but we use it not for the value, but for the DECL_UID only. */
5289 TREE_NO_WARNING (uid) = 1;
5290 gimple *g
5291 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5292 gimple_call_set_lhs (g, lane);
5293 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5294 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5295 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5296 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5297 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5298 gimple_omp_for_set_clauses (ctx->stmt, c);
5299 g = gimple_build_assign (lane, INTEGER_CST,
5300 build_int_cst (unsigned_type_node, 0));
5301 gimple_seq_add_stmt (ilist, g);
5302 for (int i = 0; i < 2; i++)
5303 if (llist[i])
5305 tree vf = create_tmp_var (unsigned_type_node);
5306 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5307 gimple_call_set_lhs (g, vf);
5308 gimple_seq *seq = i == 0 ? ilist : dlist;
5309 gimple_seq_add_stmt (seq, g);
5310 tree t = build_int_cst (unsigned_type_node, 0);
5311 g = gimple_build_assign (idx, INTEGER_CST, t);
5312 gimple_seq_add_stmt (seq, g);
5313 tree body = create_artificial_label (UNKNOWN_LOCATION);
5314 tree header = create_artificial_label (UNKNOWN_LOCATION);
5315 tree end = create_artificial_label (UNKNOWN_LOCATION);
5316 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5317 gimple_seq_add_stmt (seq, gimple_build_label (body));
5318 gimple_seq_add_seq (seq, llist[i]);
5319 t = build_int_cst (unsigned_type_node, 1);
5320 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5321 gimple_seq_add_stmt (seq, g);
5322 gimple_seq_add_stmt (seq, gimple_build_label (header));
5323 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5324 gimple_seq_add_stmt (seq, g);
5325 gimple_seq_add_stmt (seq, gimple_build_label (end));
5329 /* The copyin sequence is not to be executed by the main thread, since
5330 that would result in self-copies. Perhaps not visible to scalars,
5331 but it certainly is to C++ operator=. */
5332 if (copyin_seq)
5334 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5336 x = build2 (NE_EXPR, boolean_type_node, x,
5337 build_int_cst (TREE_TYPE (x), 0));
5338 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5339 gimplify_and_add (x, ilist);
5342 /* If any copyin variable is passed by reference, we must ensure the
5343 master thread doesn't modify it before it is copied over in all
5344 threads. Similarly for variables in both firstprivate and
5345 lastprivate clauses we need to ensure the lastprivate copying
5346 happens after firstprivate copying in all threads. And similarly
5347 for UDRs if initializer expression refers to omp_orig. */
5348 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5350 /* Don't add any barrier for #pragma omp simd or
5351 #pragma omp distribute. */
5352 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5353 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5354 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5357 /* If max_vf is non-zero, then we can use only a vectorization factor
5358 up to the max_vf we chose. So stick it into the safelen clause. */
5359 if (max_vf)
5361 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5362 OMP_CLAUSE_SAFELEN);
5363 if (c == NULL_TREE
5364 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5365 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5366 max_vf) == 1))
5368 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5369 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5370 max_vf);
5371 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5372 gimple_omp_for_set_clauses (ctx->stmt, c);
5378 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5379 both parallel and workshare constructs. PREDICATE may be NULL if it's
5380 always true. */
5382 static void
5383 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5384 omp_context *ctx)
5386 tree x, c, label = NULL, orig_clauses = clauses;
5387 bool par_clauses = false;
5388 tree simduid = NULL, lastlane = NULL;
5390 /* Early exit if there are no lastprivate or linear clauses. */
5391 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5392 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5393 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5394 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5395 break;
5396 if (clauses == NULL)
5398 /* If this was a workshare clause, see if it had been combined
5399 with its parallel. In that case, look for the clauses on the
5400 parallel statement itself. */
5401 if (is_parallel_ctx (ctx))
5402 return;
5404 ctx = ctx->outer;
5405 if (ctx == NULL || !is_parallel_ctx (ctx))
5406 return;
5408 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5409 OMP_CLAUSE_LASTPRIVATE);
5410 if (clauses == NULL)
5411 return;
5412 par_clauses = true;
5415 if (predicate)
5417 gcond *stmt;
5418 tree label_true, arm1, arm2;
5420 label = create_artificial_label (UNKNOWN_LOCATION);
5421 label_true = create_artificial_label (UNKNOWN_LOCATION);
5422 arm1 = TREE_OPERAND (predicate, 0);
5423 arm2 = TREE_OPERAND (predicate, 1);
5424 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5425 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5426 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5427 label_true, label);
5428 gimple_seq_add_stmt (stmt_list, stmt);
5429 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5432 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5433 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5435 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5436 if (simduid)
5437 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5440 for (c = clauses; c ;)
5442 tree var, new_var;
5443 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5445 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5446 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5447 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5449 var = OMP_CLAUSE_DECL (c);
5450 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5451 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5452 && is_taskloop_ctx (ctx))
5454 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5455 new_var = lookup_decl (var, ctx->outer);
5457 else
5459 new_var = lookup_decl (var, ctx);
5460 /* Avoid uninitialized warnings for lastprivate and
5461 for linear iterators. */
5462 if (predicate
5463 && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5464 || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
5465 TREE_NO_WARNING (new_var) = 1;
5468 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5470 tree val = DECL_VALUE_EXPR (new_var);
5471 if (TREE_CODE (val) == ARRAY_REF
5472 && VAR_P (TREE_OPERAND (val, 0))
5473 && lookup_attribute ("omp simd array",
5474 DECL_ATTRIBUTES (TREE_OPERAND (val,
5475 0))))
5477 if (lastlane == NULL)
5479 lastlane = create_tmp_var (unsigned_type_node);
5480 gcall *g
5481 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5482 2, simduid,
5483 TREE_OPERAND (val, 1));
5484 gimple_call_set_lhs (g, lastlane);
5485 gimple_seq_add_stmt (stmt_list, g);
5487 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5488 TREE_OPERAND (val, 0), lastlane,
5489 NULL_TREE, NULL_TREE);
5493 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5494 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5496 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5497 gimple_seq_add_seq (stmt_list,
5498 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5499 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5501 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5502 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5504 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5505 gimple_seq_add_seq (stmt_list,
5506 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5507 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5510 x = NULL_TREE;
5511 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5512 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5514 gcc_checking_assert (is_taskloop_ctx (ctx));
5515 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5516 ctx->outer->outer);
5517 if (is_global_var (ovar))
5518 x = ovar;
5520 if (!x)
5521 x = build_outer_var_ref (var, ctx, true);
5522 if (is_reference (var))
5523 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5524 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5525 gimplify_and_add (x, stmt_list);
5527 c = OMP_CLAUSE_CHAIN (c);
5528 if (c == NULL && !par_clauses)
5530 /* If this was a workshare clause, see if it had been combined
5531 with its parallel. In that case, continue looking for the
5532 clauses also on the parallel statement itself. */
5533 if (is_parallel_ctx (ctx))
5534 break;
5536 ctx = ctx->outer;
5537 if (ctx == NULL || !is_parallel_ctx (ctx))
5538 break;
5540 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5541 OMP_CLAUSE_LASTPRIVATE);
5542 par_clauses = true;
5546 if (label)
5547 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5550 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5551 (which might be a placeholder). INNER is true if this is an inner
5552 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5553 join markers. Generate the before-loop forking sequence in
5554 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5555 general form of these sequences is
5557 GOACC_REDUCTION_SETUP
5558 GOACC_FORK
5559 GOACC_REDUCTION_INIT
5561 GOACC_REDUCTION_FINI
5562 GOACC_JOIN
5563 GOACC_REDUCTION_TEARDOWN. */
5565 static void
5566 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5567 gcall *fork, gcall *join, gimple_seq *fork_seq,
5568 gimple_seq *join_seq, omp_context *ctx)
5570 gimple_seq before_fork = NULL;
5571 gimple_seq after_fork = NULL;
5572 gimple_seq before_join = NULL;
5573 gimple_seq after_join = NULL;
5574 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5575 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5576 unsigned offset = 0;
5578 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5579 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5581 tree orig = OMP_CLAUSE_DECL (c);
5582 tree var = maybe_lookup_decl (orig, ctx);
5583 tree ref_to_res = NULL_TREE;
5584 tree incoming, outgoing, v1, v2, v3;
5585 bool is_private = false;
5587 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5588 if (rcode == MINUS_EXPR)
5589 rcode = PLUS_EXPR;
5590 else if (rcode == TRUTH_ANDIF_EXPR)
5591 rcode = BIT_AND_EXPR;
5592 else if (rcode == TRUTH_ORIF_EXPR)
5593 rcode = BIT_IOR_EXPR;
5594 tree op = build_int_cst (unsigned_type_node, rcode);
5596 if (!var)
5597 var = orig;
5599 incoming = outgoing = var;
5601 if (!inner)
5603 /* See if an outer construct also reduces this variable. */
5604 omp_context *outer = ctx;
5606 while (omp_context *probe = outer->outer)
5608 enum gimple_code type = gimple_code (probe->stmt);
5609 tree cls;
5611 switch (type)
5613 case GIMPLE_OMP_FOR:
5614 cls = gimple_omp_for_clauses (probe->stmt);
5615 break;
5617 case GIMPLE_OMP_TARGET:
5618 if (gimple_omp_target_kind (probe->stmt)
5619 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5620 goto do_lookup;
5622 cls = gimple_omp_target_clauses (probe->stmt);
5623 break;
5625 default:
5626 goto do_lookup;
5629 outer = probe;
5630 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5631 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5632 && orig == OMP_CLAUSE_DECL (cls))
5634 incoming = outgoing = lookup_decl (orig, probe);
5635 goto has_outer_reduction;
5637 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5638 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5639 && orig == OMP_CLAUSE_DECL (cls))
5641 is_private = true;
5642 goto do_lookup;
5646 do_lookup:
5647 /* This is the outermost construct with this reduction,
5648 see if there's a mapping for it. */
5649 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5650 && maybe_lookup_field (orig, outer) && !is_private)
5652 ref_to_res = build_receiver_ref (orig, false, outer);
5653 if (is_reference (orig))
5654 ref_to_res = build_simple_mem_ref (ref_to_res);
5656 tree type = TREE_TYPE (var);
5657 if (POINTER_TYPE_P (type))
5658 type = TREE_TYPE (type);
5660 outgoing = var;
5661 incoming = omp_reduction_init_op (loc, rcode, type);
5663 else
5665 /* Try to look at enclosing contexts for reduction var,
5666 use original if no mapping found. */
5667 tree t = NULL_TREE;
5668 omp_context *c = ctx->outer;
5669 while (c && !t)
5671 t = maybe_lookup_decl (orig, c);
5672 c = c->outer;
5674 incoming = outgoing = (t ? t : orig);
5677 has_outer_reduction:;
5680 if (!ref_to_res)
5681 ref_to_res = integer_zero_node;
5683 if (is_reference (orig))
5685 tree type = TREE_TYPE (var);
5686 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5688 if (!inner)
5690 tree x = create_tmp_var (TREE_TYPE (type), id);
5691 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5694 v1 = create_tmp_var (type, id);
5695 v2 = create_tmp_var (type, id);
5696 v3 = create_tmp_var (type, id);
5698 gimplify_assign (v1, var, fork_seq);
5699 gimplify_assign (v2, var, fork_seq);
5700 gimplify_assign (v3, var, fork_seq);
5702 var = build_simple_mem_ref (var);
5703 v1 = build_simple_mem_ref (v1);
5704 v2 = build_simple_mem_ref (v2);
5705 v3 = build_simple_mem_ref (v3);
5706 outgoing = build_simple_mem_ref (outgoing);
5708 if (!TREE_CONSTANT (incoming))
5709 incoming = build_simple_mem_ref (incoming);
5711 else
5712 v1 = v2 = v3 = var;
5714 /* Determine position in reduction buffer, which may be used
5715 by target. */
5716 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5717 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5718 offset = (offset + align - 1) & ~(align - 1);
5719 tree off = build_int_cst (sizetype, offset);
5720 offset += GET_MODE_SIZE (mode);
5722 if (!init_code)
5724 init_code = build_int_cst (integer_type_node,
5725 IFN_GOACC_REDUCTION_INIT);
5726 fini_code = build_int_cst (integer_type_node,
5727 IFN_GOACC_REDUCTION_FINI);
5728 setup_code = build_int_cst (integer_type_node,
5729 IFN_GOACC_REDUCTION_SETUP);
5730 teardown_code = build_int_cst (integer_type_node,
5731 IFN_GOACC_REDUCTION_TEARDOWN);
5734 tree setup_call
5735 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5736 TREE_TYPE (var), 6, setup_code,
5737 unshare_expr (ref_to_res),
5738 incoming, level, op, off);
5739 tree init_call
5740 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5741 TREE_TYPE (var), 6, init_code,
5742 unshare_expr (ref_to_res),
5743 v1, level, op, off);
5744 tree fini_call
5745 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5746 TREE_TYPE (var), 6, fini_code,
5747 unshare_expr (ref_to_res),
5748 v2, level, op, off);
5749 tree teardown_call
5750 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5751 TREE_TYPE (var), 6, teardown_code,
5752 ref_to_res, v3, level, op, off);
5754 gimplify_assign (v1, setup_call, &before_fork);
5755 gimplify_assign (v2, init_call, &after_fork);
5756 gimplify_assign (v3, fini_call, &before_join);
5757 gimplify_assign (outgoing, teardown_call, &after_join);
5760 /* Now stitch things together. */
5761 gimple_seq_add_seq (fork_seq, before_fork);
5762 if (fork)
5763 gimple_seq_add_stmt (fork_seq, fork);
5764 gimple_seq_add_seq (fork_seq, after_fork);
5766 gimple_seq_add_seq (join_seq, before_join);
5767 if (join)
5768 gimple_seq_add_stmt (join_seq, join);
5769 gimple_seq_add_seq (join_seq, after_join);
5772 /* Generate code to implement the REDUCTION clauses. */
5774 static void
5775 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5777 gimple_seq sub_seq = NULL;
5778 gimple *stmt;
5779 tree x, c;
5780 int count = 0;
5782 /* OpenACC loop reductions are handled elsewhere. */
5783 if (is_gimple_omp_oacc (ctx->stmt))
5784 return;
5786 /* SIMD reductions are handled in lower_rec_input_clauses. */
5787 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5788 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5789 return;
5791 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5792 update in that case, otherwise use a lock. */
5793 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5794 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5796 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5797 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5799 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5800 count = -1;
5801 break;
5803 count++;
5806 if (count == 0)
5807 return;
5809 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5811 tree var, ref, new_var, orig_var;
5812 enum tree_code code;
5813 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5815 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5816 continue;
5818 orig_var = var = OMP_CLAUSE_DECL (c);
5819 if (TREE_CODE (var) == MEM_REF)
5821 var = TREE_OPERAND (var, 0);
5822 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5823 var = TREE_OPERAND (var, 0);
5824 if (TREE_CODE (var) == INDIRECT_REF
5825 || TREE_CODE (var) == ADDR_EXPR)
5826 var = TREE_OPERAND (var, 0);
5827 orig_var = var;
5828 if (is_variable_sized (var))
5830 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5831 var = DECL_VALUE_EXPR (var);
5832 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5833 var = TREE_OPERAND (var, 0);
5834 gcc_assert (DECL_P (var));
5837 new_var = lookup_decl (var, ctx);
5838 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5839 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5840 ref = build_outer_var_ref (var, ctx);
5841 code = OMP_CLAUSE_REDUCTION_CODE (c);
5843 /* reduction(-:var) sums up the partial results, so it acts
5844 identically to reduction(+:var). */
5845 if (code == MINUS_EXPR)
5846 code = PLUS_EXPR;
5848 if (count == 1)
5850 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5852 addr = save_expr (addr);
5853 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5854 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5855 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5856 gimplify_and_add (x, stmt_seqp);
5857 return;
5859 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5861 tree d = OMP_CLAUSE_DECL (c);
5862 tree type = TREE_TYPE (d);
5863 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5864 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5865 tree ptype = build_pointer_type (TREE_TYPE (type));
5866 tree bias = TREE_OPERAND (d, 1);
5867 d = TREE_OPERAND (d, 0);
5868 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5870 tree b = TREE_OPERAND (d, 1);
5871 b = maybe_lookup_decl (b, ctx);
5872 if (b == NULL)
5874 b = TREE_OPERAND (d, 1);
5875 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5877 if (integer_zerop (bias))
5878 bias = b;
5879 else
5881 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5882 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5883 TREE_TYPE (b), b, bias);
5885 d = TREE_OPERAND (d, 0);
5887 /* For ref build_outer_var_ref already performs this, so
5888 only new_var needs a dereference. */
5889 if (TREE_CODE (d) == INDIRECT_REF)
5891 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5892 gcc_assert (is_reference (var) && var == orig_var);
5894 else if (TREE_CODE (d) == ADDR_EXPR)
5896 if (orig_var == var)
5898 new_var = build_fold_addr_expr (new_var);
5899 ref = build_fold_addr_expr (ref);
5902 else
5904 gcc_assert (orig_var == var);
5905 if (is_reference (var))
5906 ref = build_fold_addr_expr (ref);
5908 if (DECL_P (v))
5910 tree t = maybe_lookup_decl (v, ctx);
5911 if (t)
5912 v = t;
5913 else
5914 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5915 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5917 if (!integer_zerop (bias))
5919 bias = fold_convert_loc (clause_loc, sizetype, bias);
5920 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5921 TREE_TYPE (new_var), new_var,
5922 unshare_expr (bias));
5923 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5924 TREE_TYPE (ref), ref, bias);
5926 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5927 ref = fold_convert_loc (clause_loc, ptype, ref);
5928 tree m = create_tmp_var (ptype, NULL);
5929 gimplify_assign (m, new_var, stmt_seqp);
5930 new_var = m;
5931 m = create_tmp_var (ptype, NULL);
5932 gimplify_assign (m, ref, stmt_seqp);
5933 ref = m;
5934 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5935 tree body = create_artificial_label (UNKNOWN_LOCATION);
5936 tree end = create_artificial_label (UNKNOWN_LOCATION);
5937 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5938 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5939 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5940 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5942 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5943 tree decl_placeholder
5944 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5945 SET_DECL_VALUE_EXPR (placeholder, out);
5946 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5947 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5948 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5949 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5950 gimple_seq_add_seq (&sub_seq,
5951 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5952 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5953 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5954 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5956 else
5958 x = build2 (code, TREE_TYPE (out), out, priv);
5959 out = unshare_expr (out);
5960 gimplify_assign (out, x, &sub_seq);
5962 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5963 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5964 gimple_seq_add_stmt (&sub_seq, g);
5965 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5966 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5967 gimple_seq_add_stmt (&sub_seq, g);
5968 g = gimple_build_assign (i, PLUS_EXPR, i,
5969 build_int_cst (TREE_TYPE (i), 1));
5970 gimple_seq_add_stmt (&sub_seq, g);
5971 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5972 gimple_seq_add_stmt (&sub_seq, g);
5973 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5975 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5977 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5979 if (is_reference (var)
5980 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5981 TREE_TYPE (ref)))
5982 ref = build_fold_addr_expr_loc (clause_loc, ref);
5983 SET_DECL_VALUE_EXPR (placeholder, ref);
5984 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5985 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5986 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5987 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5988 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5990 else
5992 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5993 ref = build_outer_var_ref (var, ctx);
5994 gimplify_assign (ref, x, &sub_seq);
5998 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
6000 gimple_seq_add_stmt (stmt_seqp, stmt);
6002 gimple_seq_add_seq (stmt_seqp, sub_seq);
6004 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
6006 gimple_seq_add_stmt (stmt_seqp, stmt);
6010 /* Generate code to implement the COPYPRIVATE clauses. */
6012 static void
6013 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
6014 omp_context *ctx)
6016 tree c;
6018 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6020 tree var, new_var, ref, x;
6021 bool by_ref;
6022 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6024 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6025 continue;
6027 var = OMP_CLAUSE_DECL (c);
6028 by_ref = use_pointer_for_field (var, NULL);
6030 ref = build_sender_ref (var, ctx);
6031 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6032 if (by_ref)
6034 x = build_fold_addr_expr_loc (clause_loc, new_var);
6035 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6037 gimplify_assign (ref, x, slist);
6039 ref = build_receiver_ref (var, false, ctx);
6040 if (by_ref)
6042 ref = fold_convert_loc (clause_loc,
6043 build_pointer_type (TREE_TYPE (new_var)),
6044 ref);
6045 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6047 if (is_reference (var))
6049 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6050 ref = build_simple_mem_ref_loc (clause_loc, ref);
6051 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6053 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6054 gimplify_and_add (x, rlist);
6059 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6060 and REDUCTION from the sender (aka parent) side. */
6062 static void
6063 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6064 omp_context *ctx)
6066 tree c, t;
6067 int ignored_looptemp = 0;
6068 bool is_taskloop = false;
6070 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6071 by GOMP_taskloop. */
6072 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6074 ignored_looptemp = 2;
6075 is_taskloop = true;
6078 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6080 tree val, ref, x, var;
6081 bool by_ref, do_in = false, do_out = false;
6082 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6084 switch (OMP_CLAUSE_CODE (c))
6086 case OMP_CLAUSE_PRIVATE:
6087 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6088 break;
6089 continue;
6090 case OMP_CLAUSE_FIRSTPRIVATE:
6091 case OMP_CLAUSE_COPYIN:
6092 case OMP_CLAUSE_LASTPRIVATE:
6093 case OMP_CLAUSE_REDUCTION:
6094 break;
6095 case OMP_CLAUSE_SHARED:
6096 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6097 break;
6098 continue;
6099 case OMP_CLAUSE__LOOPTEMP_:
6100 if (ignored_looptemp)
6102 ignored_looptemp--;
6103 continue;
6105 break;
6106 default:
6107 continue;
6110 val = OMP_CLAUSE_DECL (c);
6111 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6112 && TREE_CODE (val) == MEM_REF)
6114 val = TREE_OPERAND (val, 0);
6115 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6116 val = TREE_OPERAND (val, 0);
6117 if (TREE_CODE (val) == INDIRECT_REF
6118 || TREE_CODE (val) == ADDR_EXPR)
6119 val = TREE_OPERAND (val, 0);
6120 if (is_variable_sized (val))
6121 continue;
6124 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6125 outer taskloop region. */
6126 omp_context *ctx_for_o = ctx;
6127 if (is_taskloop
6128 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6129 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6130 ctx_for_o = ctx->outer;
6132 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6134 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6135 && is_global_var (var))
6136 continue;
6138 t = omp_member_access_dummy_var (var);
6139 if (t)
6141 var = DECL_VALUE_EXPR (var);
6142 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6143 if (o != t)
6144 var = unshare_and_remap (var, t, o);
6145 else
6146 var = unshare_expr (var);
6149 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6151 /* Handle taskloop firstprivate/lastprivate, where the
6152 lastprivate on GIMPLE_OMP_TASK is represented as
6153 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6154 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6155 x = omp_build_component_ref (ctx->sender_decl, f);
6156 if (use_pointer_for_field (val, ctx))
6157 var = build_fold_addr_expr (var);
6158 gimplify_assign (x, var, ilist);
6159 DECL_ABSTRACT_ORIGIN (f) = NULL;
6160 continue;
6163 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6164 || val == OMP_CLAUSE_DECL (c))
6165 && is_variable_sized (val))
6166 continue;
6167 by_ref = use_pointer_for_field (val, NULL);
6169 switch (OMP_CLAUSE_CODE (c))
6171 case OMP_CLAUSE_FIRSTPRIVATE:
6172 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6173 && !by_ref
6174 && is_task_ctx (ctx))
6175 TREE_NO_WARNING (var) = 1;
6176 do_in = true;
6177 break;
6179 case OMP_CLAUSE_PRIVATE:
6180 case OMP_CLAUSE_COPYIN:
6181 case OMP_CLAUSE__LOOPTEMP_:
6182 do_in = true;
6183 break;
6185 case OMP_CLAUSE_LASTPRIVATE:
6186 if (by_ref || is_reference (val))
6188 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6189 continue;
6190 do_in = true;
6192 else
6194 do_out = true;
6195 if (lang_hooks.decls.omp_private_outer_ref (val))
6196 do_in = true;
6198 break;
6200 case OMP_CLAUSE_REDUCTION:
6201 do_in = true;
6202 if (val == OMP_CLAUSE_DECL (c))
6203 do_out = !(by_ref || is_reference (val));
6204 else
6205 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6206 break;
6208 default:
6209 gcc_unreachable ();
6212 if (do_in)
6214 ref = build_sender_ref (val, ctx);
6215 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6216 gimplify_assign (ref, x, ilist);
6217 if (is_task_ctx (ctx))
6218 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6221 if (do_out)
6223 ref = build_sender_ref (val, ctx);
6224 gimplify_assign (var, ref, olist);
6229 /* Generate code to implement SHARED from the sender (aka parent)
6230 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6231 list things that got automatically shared. */
6233 static void
6234 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6236 tree var, ovar, nvar, t, f, x, record_type;
6238 if (ctx->record_type == NULL)
6239 return;
6241 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6242 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6244 ovar = DECL_ABSTRACT_ORIGIN (f);
6245 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6246 continue;
6248 nvar = maybe_lookup_decl (ovar, ctx);
6249 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6250 continue;
6252 /* If CTX is a nested parallel directive. Find the immediately
6253 enclosing parallel or workshare construct that contains a
6254 mapping for OVAR. */
6255 var = lookup_decl_in_outer_ctx (ovar, ctx);
6257 t = omp_member_access_dummy_var (var);
6258 if (t)
6260 var = DECL_VALUE_EXPR (var);
6261 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6262 if (o != t)
6263 var = unshare_and_remap (var, t, o);
6264 else
6265 var = unshare_expr (var);
6268 if (use_pointer_for_field (ovar, ctx))
6270 x = build_sender_ref (ovar, ctx);
6271 var = build_fold_addr_expr (var);
6272 gimplify_assign (x, var, ilist);
6274 else
6276 x = build_sender_ref (ovar, ctx);
6277 gimplify_assign (x, var, ilist);
6279 if (!TREE_READONLY (var)
6280 /* We don't need to receive a new reference to a result
6281 or parm decl. In fact we may not store to it as we will
6282 invalidate any pending RSO and generate wrong gimple
6283 during inlining. */
6284 && !((TREE_CODE (var) == RESULT_DECL
6285 || TREE_CODE (var) == PARM_DECL)
6286 && DECL_BY_REFERENCE (var)))
6288 x = build_sender_ref (ovar, ctx);
6289 gimplify_assign (var, x, olist);
6295 /* Emit an OpenACC head marker call, encapulating the partitioning and
6296 other information that must be processed by the target compiler.
6297 Return the maximum number of dimensions the associated loop might
6298 be partitioned over. */
6300 static unsigned
6301 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6302 gimple_seq *seq, omp_context *ctx)
6304 unsigned levels = 0;
6305 unsigned tag = 0;
6306 tree gang_static = NULL_TREE;
6307 auto_vec<tree, 5> args;
6309 args.quick_push (build_int_cst
6310 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6311 args.quick_push (ddvar);
6312 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6314 switch (OMP_CLAUSE_CODE (c))
6316 case OMP_CLAUSE_GANG:
6317 tag |= OLF_DIM_GANG;
6318 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6319 /* static:* is represented by -1, and we can ignore it, as
6320 scheduling is always static. */
6321 if (gang_static && integer_minus_onep (gang_static))
6322 gang_static = NULL_TREE;
6323 levels++;
6324 break;
6326 case OMP_CLAUSE_WORKER:
6327 tag |= OLF_DIM_WORKER;
6328 levels++;
6329 break;
6331 case OMP_CLAUSE_VECTOR:
6332 tag |= OLF_DIM_VECTOR;
6333 levels++;
6334 break;
6336 case OMP_CLAUSE_SEQ:
6337 tag |= OLF_SEQ;
6338 break;
6340 case OMP_CLAUSE_AUTO:
6341 tag |= OLF_AUTO;
6342 break;
6344 case OMP_CLAUSE_INDEPENDENT:
6345 tag |= OLF_INDEPENDENT;
6346 break;
6348 default:
6349 continue;
6353 if (gang_static)
6355 if (DECL_P (gang_static))
6356 gang_static = build_outer_var_ref (gang_static, ctx);
6357 tag |= OLF_GANG_STATIC;
6360 /* In a parallel region, loops are implicitly INDEPENDENT. */
6361 omp_context *tgt = enclosing_target_ctx (ctx);
6362 if (!tgt || is_oacc_parallel (tgt))
6363 tag |= OLF_INDEPENDENT;
6365 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6366 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6367 | OLF_SEQ)))
6368 tag |= OLF_AUTO;
6370 /* Ensure at least one level. */
6371 if (!levels)
6372 levels++;
6374 args.quick_push (build_int_cst (integer_type_node, levels));
6375 args.quick_push (build_int_cst (integer_type_node, tag));
6376 if (gang_static)
6377 args.quick_push (gang_static);
6379 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6380 gimple_set_location (call, loc);
6381 gimple_set_lhs (call, ddvar);
6382 gimple_seq_add_stmt (seq, call);
6384 return levels;
6387 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6388 partitioning level of the enclosed region. */
6390 static void
6391 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6392 tree tofollow, gimple_seq *seq)
6394 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6395 : IFN_UNIQUE_OACC_TAIL_MARK);
6396 tree marker = build_int_cst (integer_type_node, marker_kind);
6397 int nargs = 2 + (tofollow != NULL_TREE);
6398 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6399 marker, ddvar, tofollow);
6400 gimple_set_location (call, loc);
6401 gimple_set_lhs (call, ddvar);
6402 gimple_seq_add_stmt (seq, call);
6405 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6406 the loop clauses, from which we extract reductions. Initialize
6407 HEAD and TAIL. */
6409 static void
6410 lower_oacc_head_tail (location_t loc, tree clauses,
6411 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6413 bool inner = false;
6414 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6415 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6417 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6418 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6419 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6421 gcc_assert (count);
6422 for (unsigned done = 1; count; count--, done++)
6424 gimple_seq fork_seq = NULL;
6425 gimple_seq join_seq = NULL;
6427 tree place = build_int_cst (integer_type_node, -1);
6428 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6429 fork_kind, ddvar, place);
6430 gimple_set_location (fork, loc);
6431 gimple_set_lhs (fork, ddvar);
6433 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6434 join_kind, ddvar, place);
6435 gimple_set_location (join, loc);
6436 gimple_set_lhs (join, ddvar);
6438 /* Mark the beginning of this level sequence. */
6439 if (inner)
6440 lower_oacc_loop_marker (loc, ddvar, true,
6441 build_int_cst (integer_type_node, count),
6442 &fork_seq);
6443 lower_oacc_loop_marker (loc, ddvar, false,
6444 build_int_cst (integer_type_node, done),
6445 &join_seq);
6447 lower_oacc_reductions (loc, clauses, place, inner,
6448 fork, join, &fork_seq, &join_seq, ctx);
6450 /* Append this level to head. */
6451 gimple_seq_add_seq (head, fork_seq);
6452 /* Prepend it to tail. */
6453 gimple_seq_add_seq (&join_seq, *tail);
6454 *tail = join_seq;
6456 inner = true;
6459 /* Mark the end of the sequence. */
6460 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6461 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6464 /* A convenience function to build an empty GIMPLE_COND with just the
6465 condition. */
6467 static gcond *
6468 gimple_build_cond_empty (tree cond)
6470 enum tree_code pred_code;
6471 tree lhs, rhs;
6473 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6474 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6477 /* Return true if a parallel REGION is within a declare target function or
6478 within a target region and is not a part of a gridified target. */
6480 static bool
6481 parallel_needs_hsa_kernel_p (struct omp_region *region)
6483 bool indirect = false;
6484 for (region = region->outer; region; region = region->outer)
6486 if (region->type == GIMPLE_OMP_PARALLEL)
6487 indirect = true;
6488 else if (region->type == GIMPLE_OMP_TARGET)
6490 gomp_target *tgt_stmt
6491 = as_a <gomp_target *> (last_stmt (region->entry));
6493 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6494 OMP_CLAUSE__GRIDDIM_))
6495 return indirect;
6496 else
6497 return true;
6501 if (lookup_attribute ("omp declare target",
6502 DECL_ATTRIBUTES (current_function_decl)))
6503 return true;
6505 return false;
6508 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6509 bool = false);
6511 /* Build the function calls to GOMP_parallel_start etc to actually
6512 generate the parallel operation. REGION is the parallel region
6513 being expanded. BB is the block where to insert the code. WS_ARGS
6514 will be set if this is a call to a combined parallel+workshare
6515 construct, it contains the list of additional arguments needed by
6516 the workshare construct. */
6518 static void
6519 expand_parallel_call (struct omp_region *region, basic_block bb,
6520 gomp_parallel *entry_stmt,
6521 vec<tree, va_gc> *ws_args)
6523 tree t, t1, t2, val, cond, c, clauses, flags;
6524 gimple_stmt_iterator gsi;
6525 gimple *stmt;
6526 enum built_in_function start_ix;
6527 int start_ix2;
6528 location_t clause_loc;
6529 vec<tree, va_gc> *args;
6531 clauses = gimple_omp_parallel_clauses (entry_stmt);
6533 /* Determine what flavor of GOMP_parallel we will be
6534 emitting. */
6535 start_ix = BUILT_IN_GOMP_PARALLEL;
6536 if (is_combined_parallel (region))
6538 switch (region->inner->type)
6540 case GIMPLE_OMP_FOR:
6541 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6542 switch (region->inner->sched_kind)
6544 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6545 start_ix2 = 3;
6546 break;
6547 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6548 case OMP_CLAUSE_SCHEDULE_GUIDED:
6549 if (region->inner->sched_modifiers
6550 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6552 start_ix2 = 3 + region->inner->sched_kind;
6553 break;
6555 /* FALLTHRU */
6556 default:
6557 start_ix2 = region->inner->sched_kind;
6558 break;
6560 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6561 start_ix = (enum built_in_function) start_ix2;
6562 break;
6563 case GIMPLE_OMP_SECTIONS:
6564 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6565 break;
6566 default:
6567 gcc_unreachable ();
6571 /* By default, the value of NUM_THREADS is zero (selected at run time)
6572 and there is no conditional. */
6573 cond = NULL_TREE;
6574 val = build_int_cst (unsigned_type_node, 0);
6575 flags = build_int_cst (unsigned_type_node, 0);
6577 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6578 if (c)
6579 cond = OMP_CLAUSE_IF_EXPR (c);
6581 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6582 if (c)
6584 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6585 clause_loc = OMP_CLAUSE_LOCATION (c);
6587 else
6588 clause_loc = gimple_location (entry_stmt);
6590 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6591 if (c)
6592 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6594 /* Ensure 'val' is of the correct type. */
6595 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6597 /* If we found the clause 'if (cond)', build either
6598 (cond != 0) or (cond ? val : 1u). */
6599 if (cond)
6601 cond = gimple_boolify (cond);
6603 if (integer_zerop (val))
6604 val = fold_build2_loc (clause_loc,
6605 EQ_EXPR, unsigned_type_node, cond,
6606 build_int_cst (TREE_TYPE (cond), 0));
6607 else
6609 basic_block cond_bb, then_bb, else_bb;
6610 edge e, e_then, e_else;
6611 tree tmp_then, tmp_else, tmp_join, tmp_var;
6613 tmp_var = create_tmp_var (TREE_TYPE (val));
6614 if (gimple_in_ssa_p (cfun))
6616 tmp_then = make_ssa_name (tmp_var);
6617 tmp_else = make_ssa_name (tmp_var);
6618 tmp_join = make_ssa_name (tmp_var);
6620 else
6622 tmp_then = tmp_var;
6623 tmp_else = tmp_var;
6624 tmp_join = tmp_var;
6627 e = split_block_after_labels (bb);
6628 cond_bb = e->src;
6629 bb = e->dest;
6630 remove_edge (e);
6632 then_bb = create_empty_bb (cond_bb);
6633 else_bb = create_empty_bb (then_bb);
6634 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6635 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6637 stmt = gimple_build_cond_empty (cond);
6638 gsi = gsi_start_bb (cond_bb);
6639 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6641 gsi = gsi_start_bb (then_bb);
6642 expand_omp_build_assign (&gsi, tmp_then, val, true);
6644 gsi = gsi_start_bb (else_bb);
6645 expand_omp_build_assign (&gsi, tmp_else,
6646 build_int_cst (unsigned_type_node, 1),
6647 true);
6649 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6650 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6651 add_bb_to_loop (then_bb, cond_bb->loop_father);
6652 add_bb_to_loop (else_bb, cond_bb->loop_father);
6653 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6654 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6656 if (gimple_in_ssa_p (cfun))
6658 gphi *phi = create_phi_node (tmp_join, bb);
6659 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6660 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6663 val = tmp_join;
6666 gsi = gsi_start_bb (bb);
6667 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6668 false, GSI_CONTINUE_LINKING);
6671 gsi = gsi_last_bb (bb);
6672 t = gimple_omp_parallel_data_arg (entry_stmt);
6673 if (t == NULL)
6674 t1 = null_pointer_node;
6675 else
6676 t1 = build_fold_addr_expr (t);
6677 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6678 t2 = build_fold_addr_expr (child_fndecl);
6680 vec_alloc (args, 4 + vec_safe_length (ws_args));
6681 args->quick_push (t2);
6682 args->quick_push (t1);
6683 args->quick_push (val);
6684 if (ws_args)
6685 args->splice (*ws_args);
6686 args->quick_push (flags);
6688 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6689 builtin_decl_explicit (start_ix), args);
6691 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6692 false, GSI_CONTINUE_LINKING);
6694 if (hsa_gen_requested_p ()
6695 && parallel_needs_hsa_kernel_p (region))
6697 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6698 hsa_register_kernel (child_cnode);
6702 /* Insert a function call whose name is FUNC_NAME with the information from
6703 ENTRY_STMT into the basic_block BB. */
6705 static void
6706 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6707 vec <tree, va_gc> *ws_args)
6709 tree t, t1, t2;
6710 gimple_stmt_iterator gsi;
6711 vec <tree, va_gc> *args;
6713 gcc_assert (vec_safe_length (ws_args) == 2);
6714 tree func_name = (*ws_args)[0];
6715 tree grain = (*ws_args)[1];
6717 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6718 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6719 gcc_assert (count != NULL_TREE);
6720 count = OMP_CLAUSE_OPERAND (count, 0);
6722 gsi = gsi_last_bb (bb);
6723 t = gimple_omp_parallel_data_arg (entry_stmt);
6724 if (t == NULL)
6725 t1 = null_pointer_node;
6726 else
6727 t1 = build_fold_addr_expr (t);
6728 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6730 vec_alloc (args, 4);
6731 args->quick_push (t2);
6732 args->quick_push (t1);
6733 args->quick_push (count);
6734 args->quick_push (grain);
6735 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6737 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6738 GSI_CONTINUE_LINKING);
6741 /* Build the function call to GOMP_task to actually
6742 generate the task operation. BB is the block where to insert the code. */
6744 static void
6745 expand_task_call (struct omp_region *region, basic_block bb,
6746 gomp_task *entry_stmt)
6748 tree t1, t2, t3;
6749 gimple_stmt_iterator gsi;
6750 location_t loc = gimple_location (entry_stmt);
6752 tree clauses = gimple_omp_task_clauses (entry_stmt);
6754 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6755 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6756 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6757 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6758 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6759 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6761 unsigned int iflags
6762 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6763 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6764 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6766 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6767 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6768 tree num_tasks = NULL_TREE;
6769 bool ull = false;
6770 if (taskloop_p)
6772 gimple *g = last_stmt (region->outer->entry);
6773 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6774 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6775 struct omp_for_data fd;
6776 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6777 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6778 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6779 OMP_CLAUSE__LOOPTEMP_);
6780 startvar = OMP_CLAUSE_DECL (startvar);
6781 endvar = OMP_CLAUSE_DECL (endvar);
6782 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6783 if (fd.loop.cond_code == LT_EXPR)
6784 iflags |= GOMP_TASK_FLAG_UP;
6785 tree tclauses = gimple_omp_for_clauses (g);
6786 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6787 if (num_tasks)
6788 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6789 else
6791 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6792 if (num_tasks)
6794 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6795 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6797 else
6798 num_tasks = integer_zero_node;
6800 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6801 if (ifc == NULL_TREE)
6802 iflags |= GOMP_TASK_FLAG_IF;
6803 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6804 iflags |= GOMP_TASK_FLAG_NOGROUP;
6805 ull = fd.iter_type == long_long_unsigned_type_node;
6807 else if (priority)
6808 iflags |= GOMP_TASK_FLAG_PRIORITY;
6810 tree flags = build_int_cst (unsigned_type_node, iflags);
6812 tree cond = boolean_true_node;
6813 if (ifc)
6815 if (taskloop_p)
6817 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6818 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6819 build_int_cst (unsigned_type_node,
6820 GOMP_TASK_FLAG_IF),
6821 build_int_cst (unsigned_type_node, 0));
6822 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6823 flags, t);
6825 else
6826 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6829 if (finalc)
6831 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6832 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6833 build_int_cst (unsigned_type_node,
6834 GOMP_TASK_FLAG_FINAL),
6835 build_int_cst (unsigned_type_node, 0));
6836 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6838 if (depend)
6839 depend = OMP_CLAUSE_DECL (depend);
6840 else
6841 depend = build_int_cst (ptr_type_node, 0);
6842 if (priority)
6843 priority = fold_convert (integer_type_node,
6844 OMP_CLAUSE_PRIORITY_EXPR (priority));
6845 else
6846 priority = integer_zero_node;
6848 gsi = gsi_last_bb (bb);
6849 tree t = gimple_omp_task_data_arg (entry_stmt);
6850 if (t == NULL)
6851 t2 = null_pointer_node;
6852 else
6853 t2 = build_fold_addr_expr_loc (loc, t);
6854 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6855 t = gimple_omp_task_copy_fn (entry_stmt);
6856 if (t == NULL)
6857 t3 = null_pointer_node;
6858 else
6859 t3 = build_fold_addr_expr_loc (loc, t);
6861 if (taskloop_p)
6862 t = build_call_expr (ull
6863 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6864 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6865 11, t1, t2, t3,
6866 gimple_omp_task_arg_size (entry_stmt),
6867 gimple_omp_task_arg_align (entry_stmt), flags,
6868 num_tasks, priority, startvar, endvar, step);
6869 else
6870 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6871 9, t1, t2, t3,
6872 gimple_omp_task_arg_size (entry_stmt),
6873 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6874 depend, priority);
6876 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6877 false, GSI_CONTINUE_LINKING);
6881 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6882 catch handler and return it. This prevents programs from violating the
6883 structured block semantics with throws. */
6885 static gimple_seq
6886 maybe_catch_exception (gimple_seq body)
6888 gimple *g;
6889 tree decl;
6891 if (!flag_exceptions)
6892 return body;
6894 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6895 decl = lang_hooks.eh_protect_cleanup_actions ();
6896 else
6897 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6899 g = gimple_build_eh_must_not_throw (decl);
6900 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6901 GIMPLE_TRY_CATCH);
6903 return gimple_seq_alloc_with_stmt (g);
6906 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6908 static tree
6909 vec2chain (vec<tree, va_gc> *v)
6911 tree chain = NULL_TREE, t;
6912 unsigned ix;
6914 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6916 DECL_CHAIN (t) = chain;
6917 chain = t;
6920 return chain;
6924 /* Remove barriers in REGION->EXIT's block. Note that this is only
6925 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6926 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6927 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6928 removed. */
6930 static void
6931 remove_exit_barrier (struct omp_region *region)
6933 gimple_stmt_iterator gsi;
6934 basic_block exit_bb;
6935 edge_iterator ei;
6936 edge e;
6937 gimple *stmt;
6938 int any_addressable_vars = -1;
6940 exit_bb = region->exit;
6942 /* If the parallel region doesn't return, we don't have REGION->EXIT
6943 block at all. */
6944 if (! exit_bb)
6945 return;
6947 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6948 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6949 statements that can appear in between are extremely limited -- no
6950 memory operations at all. Here, we allow nothing at all, so the
6951 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6952 gsi = gsi_last_bb (exit_bb);
6953 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6954 gsi_prev (&gsi);
6955 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6956 return;
6958 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6960 gsi = gsi_last_bb (e->src);
6961 if (gsi_end_p (gsi))
6962 continue;
6963 stmt = gsi_stmt (gsi);
6964 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6965 && !gimple_omp_return_nowait_p (stmt))
6967 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6968 in many cases. If there could be tasks queued, the barrier
6969 might be needed to let the tasks run before some local
6970 variable of the parallel that the task uses as shared
6971 runs out of scope. The task can be spawned either
6972 from within current function (this would be easy to check)
6973 or from some function it calls and gets passed an address
6974 of such a variable. */
6975 if (any_addressable_vars < 0)
6977 gomp_parallel *parallel_stmt
6978 = as_a <gomp_parallel *> (last_stmt (region->entry));
6979 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6980 tree local_decls, block, decl;
6981 unsigned ix;
6983 any_addressable_vars = 0;
6984 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6985 if (TREE_ADDRESSABLE (decl))
6987 any_addressable_vars = 1;
6988 break;
6990 for (block = gimple_block (stmt);
6991 !any_addressable_vars
6992 && block
6993 && TREE_CODE (block) == BLOCK;
6994 block = BLOCK_SUPERCONTEXT (block))
6996 for (local_decls = BLOCK_VARS (block);
6997 local_decls;
6998 local_decls = DECL_CHAIN (local_decls))
6999 if (TREE_ADDRESSABLE (local_decls))
7001 any_addressable_vars = 1;
7002 break;
7004 if (block == gimple_block (parallel_stmt))
7005 break;
7008 if (!any_addressable_vars)
7009 gimple_omp_return_set_nowait (stmt);
7014 static void
7015 remove_exit_barriers (struct omp_region *region)
7017 if (region->type == GIMPLE_OMP_PARALLEL)
7018 remove_exit_barrier (region);
7020 if (region->inner)
7022 region = region->inner;
7023 remove_exit_barriers (region);
7024 while (region->next)
7026 region = region->next;
7027 remove_exit_barriers (region);
7032 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7033 calls. These can't be declared as const functions, but
7034 within one parallel body they are constant, so they can be
7035 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7036 which are declared const. Similarly for task body, except
7037 that in untied task omp_get_thread_num () can change at any task
7038 scheduling point. */
7040 static void
7041 optimize_omp_library_calls (gimple *entry_stmt)
7043 basic_block bb;
7044 gimple_stmt_iterator gsi;
7045 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7046 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7047 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7048 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7049 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7050 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7051 OMP_CLAUSE_UNTIED) != NULL);
7053 FOR_EACH_BB_FN (bb, cfun)
7054 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7056 gimple *call = gsi_stmt (gsi);
7057 tree decl;
7059 if (is_gimple_call (call)
7060 && (decl = gimple_call_fndecl (call))
7061 && DECL_EXTERNAL (decl)
7062 && TREE_PUBLIC (decl)
7063 && DECL_INITIAL (decl) == NULL)
7065 tree built_in;
7067 if (DECL_NAME (decl) == thr_num_id)
7069 /* In #pragma omp task untied omp_get_thread_num () can change
7070 during the execution of the task region. */
7071 if (untied_task)
7072 continue;
7073 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7075 else if (DECL_NAME (decl) == num_thr_id)
7076 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7077 else
7078 continue;
7080 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7081 || gimple_call_num_args (call) != 0)
7082 continue;
7084 if (flag_exceptions && !TREE_NOTHROW (decl))
7085 continue;
7087 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7088 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7089 TREE_TYPE (TREE_TYPE (built_in))))
7090 continue;
7092 gimple_call_set_fndecl (call, built_in);
7097 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7098 regimplified. */
7100 static tree
7101 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7103 tree t = *tp;
7105 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7106 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
7107 return t;
7109 if (TREE_CODE (t) == ADDR_EXPR)
7110 recompute_tree_invariant_for_addr_expr (t);
7112 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7113 return NULL_TREE;
7116 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7118 static void
7119 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7120 bool after)
7122 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7123 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7124 !after, after ? GSI_CONTINUE_LINKING
7125 : GSI_SAME_STMT);
7126 gimple *stmt = gimple_build_assign (to, from);
7127 if (after)
7128 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7129 else
7130 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7131 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7132 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7134 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7135 gimple_regimplify_operands (stmt, &gsi);
7139 /* Expand the OpenMP parallel or task directive starting at REGION. */
7141 static void
7142 expand_omp_taskreg (struct omp_region *region)
7144 basic_block entry_bb, exit_bb, new_bb;
7145 struct function *child_cfun;
7146 tree child_fn, block, t;
7147 gimple_stmt_iterator gsi;
7148 gimple *entry_stmt, *stmt;
7149 edge e;
7150 vec<tree, va_gc> *ws_args;
7152 entry_stmt = last_stmt (region->entry);
7153 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7154 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7156 entry_bb = region->entry;
7157 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7158 exit_bb = region->cont;
7159 else
7160 exit_bb = region->exit;
7162 bool is_cilk_for
7163 = (flag_cilkplus
7164 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7165 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7166 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7168 if (is_cilk_for)
7169 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7170 and the inner statement contains the name of the built-in function
7171 and grain. */
7172 ws_args = region->inner->ws_args;
7173 else if (is_combined_parallel (region))
7174 ws_args = region->ws_args;
7175 else
7176 ws_args = NULL;
7178 if (child_cfun->cfg)
7180 /* Due to inlining, it may happen that we have already outlined
7181 the region, in which case all we need to do is make the
7182 sub-graph unreachable and emit the parallel call. */
7183 edge entry_succ_e, exit_succ_e;
7185 entry_succ_e = single_succ_edge (entry_bb);
7187 gsi = gsi_last_bb (entry_bb);
7188 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7189 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7190 gsi_remove (&gsi, true);
7192 new_bb = entry_bb;
7193 if (exit_bb)
7195 exit_succ_e = single_succ_edge (exit_bb);
7196 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7198 remove_edge_and_dominated_blocks (entry_succ_e);
7200 else
7202 unsigned srcidx, dstidx, num;
7204 /* If the parallel region needs data sent from the parent
7205 function, then the very first statement (except possible
7206 tree profile counter updates) of the parallel body
7207 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7208 &.OMP_DATA_O is passed as an argument to the child function,
7209 we need to replace it with the argument as seen by the child
7210 function.
7212 In most cases, this will end up being the identity assignment
7213 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7214 a function call that has been inlined, the original PARM_DECL
7215 .OMP_DATA_I may have been converted into a different local
7216 variable. In which case, we need to keep the assignment. */
7217 if (gimple_omp_taskreg_data_arg (entry_stmt))
7219 basic_block entry_succ_bb
7220 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7221 : FALLTHRU_EDGE (entry_bb)->dest;
7222 tree arg;
7223 gimple *parcopy_stmt = NULL;
7225 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7227 gimple *stmt;
7229 gcc_assert (!gsi_end_p (gsi));
7230 stmt = gsi_stmt (gsi);
7231 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7232 continue;
7234 if (gimple_num_ops (stmt) == 2)
7236 tree arg = gimple_assign_rhs1 (stmt);
7238 /* We're ignore the subcode because we're
7239 effectively doing a STRIP_NOPS. */
7241 if (TREE_CODE (arg) == ADDR_EXPR
7242 && TREE_OPERAND (arg, 0)
7243 == gimple_omp_taskreg_data_arg (entry_stmt))
7245 parcopy_stmt = stmt;
7246 break;
7251 gcc_assert (parcopy_stmt != NULL);
7252 arg = DECL_ARGUMENTS (child_fn);
7254 if (!gimple_in_ssa_p (cfun))
7256 if (gimple_assign_lhs (parcopy_stmt) == arg)
7257 gsi_remove (&gsi, true);
7258 else
7260 /* ?? Is setting the subcode really necessary ?? */
7261 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7262 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7265 else
7267 tree lhs = gimple_assign_lhs (parcopy_stmt);
7268 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7269 /* We'd like to set the rhs to the default def in the child_fn,
7270 but it's too early to create ssa names in the child_fn.
7271 Instead, we set the rhs to the parm. In
7272 move_sese_region_to_fn, we introduce a default def for the
7273 parm, map the parm to it's default def, and once we encounter
7274 this stmt, replace the parm with the default def. */
7275 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7276 update_stmt (parcopy_stmt);
7280 /* Declare local variables needed in CHILD_CFUN. */
7281 block = DECL_INITIAL (child_fn);
7282 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7283 /* The gimplifier could record temporaries in parallel/task block
7284 rather than in containing function's local_decls chain,
7285 which would mean cgraph missed finalizing them. Do it now. */
7286 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7287 if (TREE_CODE (t) == VAR_DECL
7288 && TREE_STATIC (t)
7289 && !DECL_EXTERNAL (t))
7290 varpool_node::finalize_decl (t);
7291 DECL_SAVED_TREE (child_fn) = NULL;
7292 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7293 gimple_set_body (child_fn, NULL);
7294 TREE_USED (block) = 1;
7296 /* Reset DECL_CONTEXT on function arguments. */
7297 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7298 DECL_CONTEXT (t) = child_fn;
7300 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7301 so that it can be moved to the child function. */
7302 gsi = gsi_last_bb (entry_bb);
7303 stmt = gsi_stmt (gsi);
7304 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7305 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7306 e = split_block (entry_bb, stmt);
7307 gsi_remove (&gsi, true);
7308 entry_bb = e->dest;
7309 edge e2 = NULL;
7310 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7311 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7312 else
7314 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7315 gcc_assert (e2->dest == region->exit);
7316 remove_edge (BRANCH_EDGE (entry_bb));
7317 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7318 gsi = gsi_last_bb (region->exit);
7319 gcc_assert (!gsi_end_p (gsi)
7320 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7321 gsi_remove (&gsi, true);
7324 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7325 if (exit_bb)
7327 gsi = gsi_last_bb (exit_bb);
7328 gcc_assert (!gsi_end_p (gsi)
7329 && (gimple_code (gsi_stmt (gsi))
7330 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7331 stmt = gimple_build_return (NULL);
7332 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7333 gsi_remove (&gsi, true);
7336 /* Move the parallel region into CHILD_CFUN. */
7338 if (gimple_in_ssa_p (cfun))
7340 init_tree_ssa (child_cfun);
7341 init_ssa_operands (child_cfun);
7342 child_cfun->gimple_df->in_ssa_p = true;
7343 block = NULL_TREE;
7345 else
7346 block = gimple_block (entry_stmt);
7348 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7349 if (exit_bb)
7350 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7351 if (e2)
7353 basic_block dest_bb = e2->dest;
7354 if (!exit_bb)
7355 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7356 remove_edge (e2);
7357 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7359 /* When the OMP expansion process cannot guarantee an up-to-date
7360 loop tree arrange for the child function to fixup loops. */
7361 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7362 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7364 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7365 num = vec_safe_length (child_cfun->local_decls);
7366 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7368 t = (*child_cfun->local_decls)[srcidx];
7369 if (DECL_CONTEXT (t) == cfun->decl)
7370 continue;
7371 if (srcidx != dstidx)
7372 (*child_cfun->local_decls)[dstidx] = t;
7373 dstidx++;
7375 if (dstidx != num)
7376 vec_safe_truncate (child_cfun->local_decls, dstidx);
7378 /* Inform the callgraph about the new function. */
7379 child_cfun->curr_properties = cfun->curr_properties;
7380 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7381 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7382 cgraph_node *node = cgraph_node::get_create (child_fn);
7383 node->parallelized_function = 1;
7384 cgraph_node::add_new_function (child_fn, true);
7386 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7387 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7389 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7390 fixed in a following pass. */
7391 push_cfun (child_cfun);
7392 if (need_asm)
7393 assign_assembler_name_if_neeeded (child_fn);
7395 if (optimize)
7396 optimize_omp_library_calls (entry_stmt);
7397 cgraph_edge::rebuild_edges ();
7399 /* Some EH regions might become dead, see PR34608. If
7400 pass_cleanup_cfg isn't the first pass to happen with the
7401 new child, these dead EH edges might cause problems.
7402 Clean them up now. */
7403 if (flag_exceptions)
7405 basic_block bb;
7406 bool changed = false;
7408 FOR_EACH_BB_FN (bb, cfun)
7409 changed |= gimple_purge_dead_eh_edges (bb);
7410 if (changed)
7411 cleanup_tree_cfg ();
7413 if (gimple_in_ssa_p (cfun))
7414 update_ssa (TODO_update_ssa);
7415 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7416 verify_loop_structure ();
7417 pop_cfun ();
7419 if (dump_file && !gimple_in_ssa_p (cfun))
7421 omp_any_child_fn_dumped = true;
7422 dump_function_header (dump_file, child_fn, dump_flags);
7423 dump_function_to_file (child_fn, dump_file, dump_flags);
7427 /* Emit a library call to launch the children threads. */
7428 if (is_cilk_for)
7429 expand_cilk_for_call (new_bb,
7430 as_a <gomp_parallel *> (entry_stmt), ws_args);
7431 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7432 expand_parallel_call (region, new_bb,
7433 as_a <gomp_parallel *> (entry_stmt), ws_args);
7434 else
7435 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7436 if (gimple_in_ssa_p (cfun))
7437 update_ssa (TODO_update_ssa_only_virtuals);
7440 /* Information about members of an OpenACC collapsed loop nest. */
7442 struct oacc_collapse
7444 tree base; /* Base value. */
7445 tree iters; /* Number of steps. */
7446 tree step; /* step size. */
7449 /* Helper for expand_oacc_for. Determine collapsed loop information.
7450 Fill in COUNTS array. Emit any initialization code before GSI.
7451 Return the calculated outer loop bound of BOUND_TYPE. */
7453 static tree
7454 expand_oacc_collapse_init (const struct omp_for_data *fd,
7455 gimple_stmt_iterator *gsi,
7456 oacc_collapse *counts, tree bound_type)
7458 tree total = build_int_cst (bound_type, 1);
7459 int ix;
7461 gcc_assert (integer_onep (fd->loop.step));
7462 gcc_assert (integer_zerop (fd->loop.n1));
7464 for (ix = 0; ix != fd->collapse; ix++)
7466 const omp_for_data_loop *loop = &fd->loops[ix];
7468 tree iter_type = TREE_TYPE (loop->v);
7469 tree diff_type = iter_type;
7470 tree plus_type = iter_type;
7472 gcc_assert (loop->cond_code == fd->loop.cond_code);
7474 if (POINTER_TYPE_P (iter_type))
7475 plus_type = sizetype;
7476 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7477 diff_type = signed_type_for (diff_type);
7479 tree b = loop->n1;
7480 tree e = loop->n2;
7481 tree s = loop->step;
7482 bool up = loop->cond_code == LT_EXPR;
7483 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7484 bool negating;
7485 tree expr;
7487 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7488 true, GSI_SAME_STMT);
7489 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7490 true, GSI_SAME_STMT);
7492 /* Convert the step, avoiding possible unsigned->signed overflow. */
7493 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7494 if (negating)
7495 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7496 s = fold_convert (diff_type, s);
7497 if (negating)
7498 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7499 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7500 true, GSI_SAME_STMT);
7502 /* Determine the range, avoiding possible unsigned->signed overflow. */
7503 negating = !up && TYPE_UNSIGNED (iter_type);
7504 expr = fold_build2 (MINUS_EXPR, plus_type,
7505 fold_convert (plus_type, negating ? b : e),
7506 fold_convert (plus_type, negating ? e : b));
7507 expr = fold_convert (diff_type, expr);
7508 if (negating)
7509 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7510 tree range = force_gimple_operand_gsi
7511 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7513 /* Determine number of iterations. */
7514 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7515 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7516 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7518 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7519 true, GSI_SAME_STMT);
7521 counts[ix].base = b;
7522 counts[ix].iters = iters;
7523 counts[ix].step = s;
7525 total = fold_build2 (MULT_EXPR, bound_type, total,
7526 fold_convert (bound_type, iters));
7529 return total;
7532 /* Emit initializers for collapsed loop members. IVAR is the outer
7533 loop iteration variable, from which collapsed loop iteration values
7534 are calculated. COUNTS array has been initialized by
7535 expand_oacc_collapse_inits. */
7537 static void
7538 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7539 gimple_stmt_iterator *gsi,
7540 const oacc_collapse *counts, tree ivar)
7542 tree ivar_type = TREE_TYPE (ivar);
7544 /* The most rapidly changing iteration variable is the innermost
7545 one. */
7546 for (int ix = fd->collapse; ix--;)
7548 const omp_for_data_loop *loop = &fd->loops[ix];
7549 const oacc_collapse *collapse = &counts[ix];
7550 tree iter_type = TREE_TYPE (loop->v);
7551 tree diff_type = TREE_TYPE (collapse->step);
7552 tree plus_type = iter_type;
7553 enum tree_code plus_code = PLUS_EXPR;
7554 tree expr;
7556 if (POINTER_TYPE_P (iter_type))
7558 plus_code = POINTER_PLUS_EXPR;
7559 plus_type = sizetype;
7562 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7563 fold_convert (ivar_type, collapse->iters));
7564 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7565 collapse->step);
7566 expr = fold_build2 (plus_code, iter_type, collapse->base,
7567 fold_convert (plus_type, expr));
7568 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7569 true, GSI_SAME_STMT);
7570 gassign *ass = gimple_build_assign (loop->v, expr);
7571 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7573 if (ix)
7575 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7576 fold_convert (ivar_type, collapse->iters));
7577 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7578 true, GSI_SAME_STMT);
7584 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7585 of the combined collapse > 1 loop constructs, generate code like:
7586 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7587 if (cond3 is <)
7588 adj = STEP3 - 1;
7589 else
7590 adj = STEP3 + 1;
7591 count3 = (adj + N32 - N31) / STEP3;
7592 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7593 if (cond2 is <)
7594 adj = STEP2 - 1;
7595 else
7596 adj = STEP2 + 1;
7597 count2 = (adj + N22 - N21) / STEP2;
7598 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7599 if (cond1 is <)
7600 adj = STEP1 - 1;
7601 else
7602 adj = STEP1 + 1;
7603 count1 = (adj + N12 - N11) / STEP1;
7604 count = count1 * count2 * count3;
7605 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7606 count = 0;
7607 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7608 of the combined loop constructs, just initialize COUNTS array
7609 from the _looptemp_ clauses. */
7611 /* NOTE: It *could* be better to moosh all of the BBs together,
7612 creating one larger BB with all the computation and the unexpected
7613 jump at the end. I.e.
7615 bool zero3, zero2, zero1, zero;
7617 zero3 = N32 c3 N31;
7618 count3 = (N32 - N31) /[cl] STEP3;
7619 zero2 = N22 c2 N21;
7620 count2 = (N22 - N21) /[cl] STEP2;
7621 zero1 = N12 c1 N11;
7622 count1 = (N12 - N11) /[cl] STEP1;
7623 zero = zero3 || zero2 || zero1;
7624 count = count1 * count2 * count3;
7625 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7627 After all, we expect the zero=false, and thus we expect to have to
7628 evaluate all of the comparison expressions, so short-circuiting
7629 oughtn't be a win. Since the condition isn't protecting a
7630 denominator, we're not concerned about divide-by-zero, so we can
7631 fully evaluate count even if a numerator turned out to be wrong.
7633 It seems like putting this all together would create much better
7634 scheduling opportunities, and less pressure on the chip's branch
7635 predictor. */
7637 static void
7638 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7639 basic_block &entry_bb, tree *counts,
7640 basic_block &zero_iter1_bb, int &first_zero_iter1,
7641 basic_block &zero_iter2_bb, int &first_zero_iter2,
7642 basic_block &l2_dom_bb)
7644 tree t, type = TREE_TYPE (fd->loop.v);
7645 edge e, ne;
7646 int i;
7648 /* Collapsed loops need work for expansion into SSA form. */
7649 gcc_assert (!gimple_in_ssa_p (cfun));
7651 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7652 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7654 gcc_assert (fd->ordered == 0);
7655 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7656 isn't supposed to be handled, as the inner loop doesn't
7657 use it. */
7658 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7659 OMP_CLAUSE__LOOPTEMP_);
7660 gcc_assert (innerc);
7661 for (i = 0; i < fd->collapse; i++)
7663 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7664 OMP_CLAUSE__LOOPTEMP_);
7665 gcc_assert (innerc);
7666 if (i)
7667 counts[i] = OMP_CLAUSE_DECL (innerc);
7668 else
7669 counts[0] = NULL_TREE;
7671 return;
7674 for (i = fd->collapse; i < fd->ordered; i++)
7676 tree itype = TREE_TYPE (fd->loops[i].v);
7677 counts[i] = NULL_TREE;
7678 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7679 fold_convert (itype, fd->loops[i].n1),
7680 fold_convert (itype, fd->loops[i].n2));
7681 if (t && integer_zerop (t))
7683 for (i = fd->collapse; i < fd->ordered; i++)
7684 counts[i] = build_int_cst (type, 0);
7685 break;
7688 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7690 tree itype = TREE_TYPE (fd->loops[i].v);
7692 if (i >= fd->collapse && counts[i])
7693 continue;
7694 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7695 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7696 fold_convert (itype, fd->loops[i].n1),
7697 fold_convert (itype, fd->loops[i].n2)))
7698 == NULL_TREE || !integer_onep (t)))
7700 gcond *cond_stmt;
7701 tree n1, n2;
7702 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7703 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7704 true, GSI_SAME_STMT);
7705 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7706 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7707 true, GSI_SAME_STMT);
7708 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7709 NULL_TREE, NULL_TREE);
7710 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7711 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7712 expand_omp_regimplify_p, NULL, NULL)
7713 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7714 expand_omp_regimplify_p, NULL, NULL))
7716 *gsi = gsi_for_stmt (cond_stmt);
7717 gimple_regimplify_operands (cond_stmt, gsi);
7719 e = split_block (entry_bb, cond_stmt);
7720 basic_block &zero_iter_bb
7721 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7722 int &first_zero_iter
7723 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7724 if (zero_iter_bb == NULL)
7726 gassign *assign_stmt;
7727 first_zero_iter = i;
7728 zero_iter_bb = create_empty_bb (entry_bb);
7729 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7730 *gsi = gsi_after_labels (zero_iter_bb);
7731 if (i < fd->collapse)
7732 assign_stmt = gimple_build_assign (fd->loop.n2,
7733 build_zero_cst (type));
7734 else
7736 counts[i] = create_tmp_reg (type, ".count");
7737 assign_stmt
7738 = gimple_build_assign (counts[i], build_zero_cst (type));
7740 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7741 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7742 entry_bb);
7744 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7745 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7746 e->flags = EDGE_TRUE_VALUE;
7747 e->probability = REG_BR_PROB_BASE - ne->probability;
7748 if (l2_dom_bb == NULL)
7749 l2_dom_bb = entry_bb;
7750 entry_bb = e->dest;
7751 *gsi = gsi_last_bb (entry_bb);
7754 if (POINTER_TYPE_P (itype))
7755 itype = signed_type_for (itype);
7756 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7757 ? -1 : 1));
7758 t = fold_build2 (PLUS_EXPR, itype,
7759 fold_convert (itype, fd->loops[i].step), t);
7760 t = fold_build2 (PLUS_EXPR, itype, t,
7761 fold_convert (itype, fd->loops[i].n2));
7762 t = fold_build2 (MINUS_EXPR, itype, t,
7763 fold_convert (itype, fd->loops[i].n1));
7764 /* ?? We could probably use CEIL_DIV_EXPR instead of
7765 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7766 generate the same code in the end because generically we
7767 don't know that the values involved must be negative for
7768 GT?? */
7769 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7770 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7771 fold_build1 (NEGATE_EXPR, itype, t),
7772 fold_build1 (NEGATE_EXPR, itype,
7773 fold_convert (itype,
7774 fd->loops[i].step)));
7775 else
7776 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7777 fold_convert (itype, fd->loops[i].step));
7778 t = fold_convert (type, t);
7779 if (TREE_CODE (t) == INTEGER_CST)
7780 counts[i] = t;
7781 else
7783 if (i < fd->collapse || i != first_zero_iter2)
7784 counts[i] = create_tmp_reg (type, ".count");
7785 expand_omp_build_assign (gsi, counts[i], t);
7787 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7789 if (i == 0)
7790 t = counts[0];
7791 else
7792 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7793 expand_omp_build_assign (gsi, fd->loop.n2, t);
7799 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7800 T = V;
7801 V3 = N31 + (T % count3) * STEP3;
7802 T = T / count3;
7803 V2 = N21 + (T % count2) * STEP2;
7804 T = T / count2;
7805 V1 = N11 + T * STEP1;
7806 if this loop doesn't have an inner loop construct combined with it.
7807 If it does have an inner loop construct combined with it and the
7808 iteration count isn't known constant, store values from counts array
7809 into its _looptemp_ temporaries instead. */
7811 static void
7812 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7813 tree *counts, gimple *inner_stmt, tree startvar)
7815 int i;
7816 if (gimple_omp_for_combined_p (fd->for_stmt))
7818 /* If fd->loop.n2 is constant, then no propagation of the counts
7819 is needed, they are constant. */
7820 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7821 return;
7823 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7824 ? gimple_omp_taskreg_clauses (inner_stmt)
7825 : gimple_omp_for_clauses (inner_stmt);
7826 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7827 isn't supposed to be handled, as the inner loop doesn't
7828 use it. */
7829 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7830 gcc_assert (innerc);
7831 for (i = 0; i < fd->collapse; i++)
7833 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7834 OMP_CLAUSE__LOOPTEMP_);
7835 gcc_assert (innerc);
7836 if (i)
7838 tree tem = OMP_CLAUSE_DECL (innerc);
7839 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7840 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7841 false, GSI_CONTINUE_LINKING);
7842 gassign *stmt = gimple_build_assign (tem, t);
7843 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7846 return;
7849 tree type = TREE_TYPE (fd->loop.v);
7850 tree tem = create_tmp_reg (type, ".tem");
7851 gassign *stmt = gimple_build_assign (tem, startvar);
7852 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7854 for (i = fd->collapse - 1; i >= 0; i--)
7856 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7857 itype = vtype;
7858 if (POINTER_TYPE_P (vtype))
7859 itype = signed_type_for (vtype);
7860 if (i != 0)
7861 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7862 else
7863 t = tem;
7864 t = fold_convert (itype, t);
7865 t = fold_build2 (MULT_EXPR, itype, t,
7866 fold_convert (itype, fd->loops[i].step));
7867 if (POINTER_TYPE_P (vtype))
7868 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7869 else
7870 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7871 t = force_gimple_operand_gsi (gsi, t,
7872 DECL_P (fd->loops[i].v)
7873 && TREE_ADDRESSABLE (fd->loops[i].v),
7874 NULL_TREE, false,
7875 GSI_CONTINUE_LINKING);
7876 stmt = gimple_build_assign (fd->loops[i].v, t);
7877 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7878 if (i != 0)
7880 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7881 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7882 false, GSI_CONTINUE_LINKING);
7883 stmt = gimple_build_assign (tem, t);
7884 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7890 /* Helper function for expand_omp_for_*. Generate code like:
7891 L10:
7892 V3 += STEP3;
7893 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7894 L11:
7895 V3 = N31;
7896 V2 += STEP2;
7897 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7898 L12:
7899 V2 = N21;
7900 V1 += STEP1;
7901 goto BODY_BB; */
7903 static basic_block
7904 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7905 basic_block body_bb)
7907 basic_block last_bb, bb, collapse_bb = NULL;
7908 int i;
7909 gimple_stmt_iterator gsi;
7910 edge e;
7911 tree t;
7912 gimple *stmt;
7914 last_bb = cont_bb;
7915 for (i = fd->collapse - 1; i >= 0; i--)
7917 tree vtype = TREE_TYPE (fd->loops[i].v);
7919 bb = create_empty_bb (last_bb);
7920 add_bb_to_loop (bb, last_bb->loop_father);
7921 gsi = gsi_start_bb (bb);
7923 if (i < fd->collapse - 1)
7925 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7926 e->probability = REG_BR_PROB_BASE / 8;
7928 t = fd->loops[i + 1].n1;
7929 t = force_gimple_operand_gsi (&gsi, t,
7930 DECL_P (fd->loops[i + 1].v)
7931 && TREE_ADDRESSABLE (fd->loops[i
7932 + 1].v),
7933 NULL_TREE, false,
7934 GSI_CONTINUE_LINKING);
7935 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7936 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7938 else
7939 collapse_bb = bb;
7941 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7943 if (POINTER_TYPE_P (vtype))
7944 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7945 else
7946 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7947 t = force_gimple_operand_gsi (&gsi, t,
7948 DECL_P (fd->loops[i].v)
7949 && TREE_ADDRESSABLE (fd->loops[i].v),
7950 NULL_TREE, false, GSI_CONTINUE_LINKING);
7951 stmt = gimple_build_assign (fd->loops[i].v, t);
7952 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7954 if (i > 0)
7956 t = fd->loops[i].n2;
7957 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7958 false, GSI_CONTINUE_LINKING);
7959 tree v = fd->loops[i].v;
7960 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7961 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7962 false, GSI_CONTINUE_LINKING);
7963 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7964 stmt = gimple_build_cond_empty (t);
7965 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7966 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7967 e->probability = REG_BR_PROB_BASE * 7 / 8;
7969 else
7970 make_edge (bb, body_bb, EDGE_FALLTHRU);
7971 last_bb = bb;
7974 return collapse_bb;
7978 /* Expand #pragma omp ordered depend(source). */
7980 static void
7981 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7982 tree *counts, location_t loc)
7984 enum built_in_function source_ix
7985 = fd->iter_type == long_integer_type_node
7986 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7987 gimple *g
7988 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7989 build_fold_addr_expr (counts[fd->ordered]));
7990 gimple_set_location (g, loc);
7991 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7994 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7996 static void
7997 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7998 tree *counts, tree c, location_t loc)
8000 auto_vec<tree, 10> args;
8001 enum built_in_function sink_ix
8002 = fd->iter_type == long_integer_type_node
8003 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
8004 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
8005 int i;
8006 gimple_stmt_iterator gsi2 = *gsi;
8007 bool warned_step = false;
8009 for (i = 0; i < fd->ordered; i++)
8011 off = TREE_PURPOSE (deps);
8012 if (!integer_zerop (off))
8014 gcc_assert (fd->loops[i].cond_code == LT_EXPR
8015 || fd->loops[i].cond_code == GT_EXPR);
8016 bool forward = fd->loops[i].cond_code == LT_EXPR;
8017 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8018 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
8019 "lexically later iteration");
8020 break;
8022 deps = TREE_CHAIN (deps);
8024 /* If all offsets corresponding to the collapsed loops are zero,
8025 this depend clause can be ignored. FIXME: but there is still a
8026 flush needed. We need to emit one __sync_synchronize () for it
8027 though (perhaps conditionally)? Solve this together with the
8028 conservative dependence folding optimization.
8029 if (i >= fd->collapse)
8030 return; */
8032 deps = OMP_CLAUSE_DECL (c);
8033 gsi_prev (&gsi2);
8034 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8035 edge e2 = split_block_after_labels (e1->dest);
8037 *gsi = gsi_after_labels (e1->dest);
8038 for (i = 0; i < fd->ordered; i++)
8040 tree itype = TREE_TYPE (fd->loops[i].v);
8041 if (POINTER_TYPE_P (itype))
8042 itype = sizetype;
8043 if (i)
8044 deps = TREE_CHAIN (deps);
8045 off = TREE_PURPOSE (deps);
8046 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8048 if (integer_zerop (off))
8049 t = boolean_true_node;
8050 else
8052 tree a;
8053 tree co = fold_convert_loc (loc, itype, off);
8054 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8056 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8057 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8058 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8059 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8060 co);
8062 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8063 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8064 fd->loops[i].v, co);
8065 else
8066 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8067 fd->loops[i].v, co);
8068 if (fd->loops[i].cond_code == LT_EXPR)
8070 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8071 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8072 fd->loops[i].n1);
8073 else
8074 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8075 fd->loops[i].n2);
8077 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8078 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8079 fd->loops[i].n2);
8080 else
8081 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8082 fd->loops[i].n1);
8084 if (cond)
8085 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8086 else
8087 cond = t;
8089 off = fold_convert_loc (loc, itype, off);
8091 if (fd->loops[i].cond_code == LT_EXPR
8092 ? !integer_onep (fd->loops[i].step)
8093 : !integer_minus_onep (fd->loops[i].step))
8095 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8096 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8097 fold_build1_loc (loc, NEGATE_EXPR, itype,
8098 s));
8099 else
8100 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8101 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8102 build_int_cst (itype, 0));
8103 if (integer_zerop (t) && !warned_step)
8105 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8106 "in the iteration space");
8107 warned_step = true;
8109 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8110 cond, t);
8113 if (i <= fd->collapse - 1 && fd->collapse > 1)
8114 t = fd->loop.v;
8115 else if (counts[i])
8116 t = counts[i];
8117 else
8119 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8120 fd->loops[i].v, fd->loops[i].n1);
8121 t = fold_convert_loc (loc, fd->iter_type, t);
8123 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8124 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8125 fold_build1_loc (loc, NEGATE_EXPR, itype,
8126 s));
8127 else
8128 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8129 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8130 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8131 off = fold_convert_loc (loc, fd->iter_type, off);
8132 if (i <= fd->collapse - 1 && fd->collapse > 1)
8134 if (i)
8135 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8136 off);
8137 if (i < fd->collapse - 1)
8139 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8140 counts[i]);
8141 continue;
8144 off = unshare_expr (off);
8145 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8146 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8147 true, GSI_SAME_STMT);
8148 args.safe_push (t);
8150 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8151 gimple_set_location (g, loc);
8152 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8154 *gsi = gsi_last_bb (e1->src);
8155 cond = unshare_expr (cond);
8156 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8157 GSI_CONTINUE_LINKING);
8158 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8159 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8160 e3->probability = REG_BR_PROB_BASE / 8;
8161 e1->probability = REG_BR_PROB_BASE - e3->probability;
8162 e1->flags = EDGE_TRUE_VALUE;
8163 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8165 *gsi = gsi_after_labels (e2->dest);
8168 /* Expand all #pragma omp ordered depend(source) and
8169 #pragma omp ordered depend(sink:...) constructs in the current
8170 #pragma omp for ordered(n) region. */
8172 static void
8173 expand_omp_ordered_source_sink (struct omp_region *region,
8174 struct omp_for_data *fd, tree *counts,
8175 basic_block cont_bb)
8177 struct omp_region *inner;
8178 int i;
8179 for (i = fd->collapse - 1; i < fd->ordered; i++)
8180 if (i == fd->collapse - 1 && fd->collapse > 1)
8181 counts[i] = NULL_TREE;
8182 else if (i >= fd->collapse && !cont_bb)
8183 counts[i] = build_zero_cst (fd->iter_type);
8184 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8185 && integer_onep (fd->loops[i].step))
8186 counts[i] = NULL_TREE;
8187 else
8188 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8189 tree atype
8190 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8191 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8192 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8194 for (inner = region->inner; inner; inner = inner->next)
8195 if (inner->type == GIMPLE_OMP_ORDERED)
8197 gomp_ordered *ord_stmt = inner->ord_stmt;
8198 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8199 location_t loc = gimple_location (ord_stmt);
8200 tree c;
8201 for (c = gimple_omp_ordered_clauses (ord_stmt);
8202 c; c = OMP_CLAUSE_CHAIN (c))
8203 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8204 break;
8205 if (c)
8206 expand_omp_ordered_source (&gsi, fd, counts, loc);
8207 for (c = gimple_omp_ordered_clauses (ord_stmt);
8208 c; c = OMP_CLAUSE_CHAIN (c))
8209 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8210 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8211 gsi_remove (&gsi, true);
8215 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8216 collapsed. */
8218 static basic_block
8219 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8220 basic_block cont_bb, basic_block body_bb,
8221 bool ordered_lastprivate)
8223 if (fd->ordered == fd->collapse)
8224 return cont_bb;
8226 if (!cont_bb)
8228 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8229 for (int i = fd->collapse; i < fd->ordered; i++)
8231 tree type = TREE_TYPE (fd->loops[i].v);
8232 tree n1 = fold_convert (type, fd->loops[i].n1);
8233 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8234 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8235 size_int (i - fd->collapse + 1),
8236 NULL_TREE, NULL_TREE);
8237 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8239 return NULL;
8242 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8244 tree t, type = TREE_TYPE (fd->loops[i].v);
8245 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8246 expand_omp_build_assign (&gsi, fd->loops[i].v,
8247 fold_convert (type, fd->loops[i].n1));
8248 if (counts[i])
8249 expand_omp_build_assign (&gsi, counts[i],
8250 build_zero_cst (fd->iter_type));
8251 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8252 size_int (i - fd->collapse + 1),
8253 NULL_TREE, NULL_TREE);
8254 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8255 if (!gsi_end_p (gsi))
8256 gsi_prev (&gsi);
8257 else
8258 gsi = gsi_last_bb (body_bb);
8259 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8260 basic_block new_body = e1->dest;
8261 if (body_bb == cont_bb)
8262 cont_bb = new_body;
8263 edge e2 = NULL;
8264 basic_block new_header;
8265 if (EDGE_COUNT (cont_bb->preds) > 0)
8267 gsi = gsi_last_bb (cont_bb);
8268 if (POINTER_TYPE_P (type))
8269 t = fold_build_pointer_plus (fd->loops[i].v,
8270 fold_convert (sizetype,
8271 fd->loops[i].step));
8272 else
8273 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8274 fold_convert (type, fd->loops[i].step));
8275 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8276 if (counts[i])
8278 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8279 build_int_cst (fd->iter_type, 1));
8280 expand_omp_build_assign (&gsi, counts[i], t);
8281 t = counts[i];
8283 else
8285 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8286 fd->loops[i].v, fd->loops[i].n1);
8287 t = fold_convert (fd->iter_type, t);
8288 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8289 true, GSI_SAME_STMT);
8291 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8292 size_int (i - fd->collapse + 1),
8293 NULL_TREE, NULL_TREE);
8294 expand_omp_build_assign (&gsi, aref, t);
8295 gsi_prev (&gsi);
8296 e2 = split_block (cont_bb, gsi_stmt (gsi));
8297 new_header = e2->dest;
8299 else
8300 new_header = cont_bb;
8301 gsi = gsi_after_labels (new_header);
8302 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8303 true, GSI_SAME_STMT);
8304 tree n2
8305 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8306 true, NULL_TREE, true, GSI_SAME_STMT);
8307 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8308 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8309 edge e3 = split_block (new_header, gsi_stmt (gsi));
8310 cont_bb = e3->dest;
8311 remove_edge (e1);
8312 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8313 e3->flags = EDGE_FALSE_VALUE;
8314 e3->probability = REG_BR_PROB_BASE / 8;
8315 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8316 e1->probability = REG_BR_PROB_BASE - e3->probability;
8318 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8319 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8321 if (e2)
8323 struct loop *loop = alloc_loop ();
8324 loop->header = new_header;
8325 loop->latch = e2->src;
8326 add_loop (loop, body_bb->loop_father);
8330 /* If there are any lastprivate clauses and it is possible some loops
8331 might have zero iterations, ensure all the decls are initialized,
8332 otherwise we could crash evaluating C++ class iterators with lastprivate
8333 clauses. */
8334 bool need_inits = false;
8335 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8336 if (need_inits)
8338 tree type = TREE_TYPE (fd->loops[i].v);
8339 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8340 expand_omp_build_assign (&gsi, fd->loops[i].v,
8341 fold_convert (type, fd->loops[i].n1));
8343 else
8345 tree type = TREE_TYPE (fd->loops[i].v);
8346 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8347 boolean_type_node,
8348 fold_convert (type, fd->loops[i].n1),
8349 fold_convert (type, fd->loops[i].n2));
8350 if (!integer_onep (this_cond))
8351 need_inits = true;
8354 return cont_bb;
8358 /* A subroutine of expand_omp_for. Generate code for a parallel
8359 loop with any schedule. Given parameters:
8361 for (V = N1; V cond N2; V += STEP) BODY;
8363 where COND is "<" or ">", we generate pseudocode
8365 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8366 if (more) goto L0; else goto L3;
8368 V = istart0;
8369 iend = iend0;
8371 BODY;
8372 V += STEP;
8373 if (V cond iend) goto L1; else goto L2;
8375 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8378 If this is a combined omp parallel loop, instead of the call to
8379 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8380 If this is gimple_omp_for_combined_p loop, then instead of assigning
8381 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8382 inner GIMPLE_OMP_FOR and V += STEP; and
8383 if (V cond iend) goto L1; else goto L2; are removed.
8385 For collapsed loops, given parameters:
8386 collapse(3)
8387 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8388 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8389 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8390 BODY;
8392 we generate pseudocode
8394 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8395 if (cond3 is <)
8396 adj = STEP3 - 1;
8397 else
8398 adj = STEP3 + 1;
8399 count3 = (adj + N32 - N31) / STEP3;
8400 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8401 if (cond2 is <)
8402 adj = STEP2 - 1;
8403 else
8404 adj = STEP2 + 1;
8405 count2 = (adj + N22 - N21) / STEP2;
8406 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8407 if (cond1 is <)
8408 adj = STEP1 - 1;
8409 else
8410 adj = STEP1 + 1;
8411 count1 = (adj + N12 - N11) / STEP1;
8412 count = count1 * count2 * count3;
8413 goto Z1;
8415 count = 0;
8417 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8418 if (more) goto L0; else goto L3;
8420 V = istart0;
8421 T = V;
8422 V3 = N31 + (T % count3) * STEP3;
8423 T = T / count3;
8424 V2 = N21 + (T % count2) * STEP2;
8425 T = T / count2;
8426 V1 = N11 + T * STEP1;
8427 iend = iend0;
8429 BODY;
8430 V += 1;
8431 if (V < iend) goto L10; else goto L2;
8432 L10:
8433 V3 += STEP3;
8434 if (V3 cond3 N32) goto L1; else goto L11;
8435 L11:
8436 V3 = N31;
8437 V2 += STEP2;
8438 if (V2 cond2 N22) goto L1; else goto L12;
8439 L12:
8440 V2 = N21;
8441 V1 += STEP1;
8442 goto L1;
8444 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8449 static void
8450 expand_omp_for_generic (struct omp_region *region,
8451 struct omp_for_data *fd,
8452 enum built_in_function start_fn,
8453 enum built_in_function next_fn,
8454 gimple *inner_stmt)
8456 tree type, istart0, iend0, iend;
8457 tree t, vmain, vback, bias = NULL_TREE;
8458 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8459 basic_block l2_bb = NULL, l3_bb = NULL;
8460 gimple_stmt_iterator gsi;
8461 gassign *assign_stmt;
8462 bool in_combined_parallel = is_combined_parallel (region);
8463 bool broken_loop = region->cont == NULL;
8464 edge e, ne;
8465 tree *counts = NULL;
8466 int i;
8467 bool ordered_lastprivate = false;
8469 gcc_assert (!broken_loop || !in_combined_parallel);
8470 gcc_assert (fd->iter_type == long_integer_type_node
8471 || !in_combined_parallel);
8473 entry_bb = region->entry;
8474 cont_bb = region->cont;
8475 collapse_bb = NULL;
8476 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8477 gcc_assert (broken_loop
8478 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8479 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8480 l1_bb = single_succ (l0_bb);
8481 if (!broken_loop)
8483 l2_bb = create_empty_bb (cont_bb);
8484 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8485 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8486 == l1_bb));
8487 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8489 else
8490 l2_bb = NULL;
8491 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8492 exit_bb = region->exit;
8494 gsi = gsi_last_bb (entry_bb);
8496 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8497 if (fd->ordered
8498 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8499 OMP_CLAUSE_LASTPRIVATE))
8500 ordered_lastprivate = false;
8501 if (fd->collapse > 1 || fd->ordered)
8503 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8504 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8506 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8507 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8508 zero_iter1_bb, first_zero_iter1,
8509 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8511 if (zero_iter1_bb)
8513 /* Some counts[i] vars might be uninitialized if
8514 some loop has zero iterations. But the body shouldn't
8515 be executed in that case, so just avoid uninit warnings. */
8516 for (i = first_zero_iter1;
8517 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8518 if (SSA_VAR_P (counts[i]))
8519 TREE_NO_WARNING (counts[i]) = 1;
8520 gsi_prev (&gsi);
8521 e = split_block (entry_bb, gsi_stmt (gsi));
8522 entry_bb = e->dest;
8523 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8524 gsi = gsi_last_bb (entry_bb);
8525 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8526 get_immediate_dominator (CDI_DOMINATORS,
8527 zero_iter1_bb));
8529 if (zero_iter2_bb)
8531 /* Some counts[i] vars might be uninitialized if
8532 some loop has zero iterations. But the body shouldn't
8533 be executed in that case, so just avoid uninit warnings. */
8534 for (i = first_zero_iter2; i < fd->ordered; i++)
8535 if (SSA_VAR_P (counts[i]))
8536 TREE_NO_WARNING (counts[i]) = 1;
8537 if (zero_iter1_bb)
8538 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8539 else
8541 gsi_prev (&gsi);
8542 e = split_block (entry_bb, gsi_stmt (gsi));
8543 entry_bb = e->dest;
8544 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8545 gsi = gsi_last_bb (entry_bb);
8546 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8547 get_immediate_dominator
8548 (CDI_DOMINATORS, zero_iter2_bb));
8551 if (fd->collapse == 1)
8553 counts[0] = fd->loop.n2;
8554 fd->loop = fd->loops[0];
8558 type = TREE_TYPE (fd->loop.v);
8559 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8560 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8561 TREE_ADDRESSABLE (istart0) = 1;
8562 TREE_ADDRESSABLE (iend0) = 1;
8564 /* See if we need to bias by LLONG_MIN. */
8565 if (fd->iter_type == long_long_unsigned_type_node
8566 && TREE_CODE (type) == INTEGER_TYPE
8567 && !TYPE_UNSIGNED (type)
8568 && fd->ordered == 0)
8570 tree n1, n2;
8572 if (fd->loop.cond_code == LT_EXPR)
8574 n1 = fd->loop.n1;
8575 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8577 else
8579 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8580 n2 = fd->loop.n1;
8582 if (TREE_CODE (n1) != INTEGER_CST
8583 || TREE_CODE (n2) != INTEGER_CST
8584 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8585 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8588 gimple_stmt_iterator gsif = gsi;
8589 gsi_prev (&gsif);
8591 tree arr = NULL_TREE;
8592 if (in_combined_parallel)
8594 gcc_assert (fd->ordered == 0);
8595 /* In a combined parallel loop, emit a call to
8596 GOMP_loop_foo_next. */
8597 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8598 build_fold_addr_expr (istart0),
8599 build_fold_addr_expr (iend0));
8601 else
8603 tree t0, t1, t2, t3, t4;
8604 /* If this is not a combined parallel loop, emit a call to
8605 GOMP_loop_foo_start in ENTRY_BB. */
8606 t4 = build_fold_addr_expr (iend0);
8607 t3 = build_fold_addr_expr (istart0);
8608 if (fd->ordered)
8610 t0 = build_int_cst (unsigned_type_node,
8611 fd->ordered - fd->collapse + 1);
8612 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8613 fd->ordered
8614 - fd->collapse + 1),
8615 ".omp_counts");
8616 DECL_NAMELESS (arr) = 1;
8617 TREE_ADDRESSABLE (arr) = 1;
8618 TREE_STATIC (arr) = 1;
8619 vec<constructor_elt, va_gc> *v;
8620 vec_alloc (v, fd->ordered - fd->collapse + 1);
8621 int idx;
8623 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8625 tree c;
8626 if (idx == 0 && fd->collapse > 1)
8627 c = fd->loop.n2;
8628 else
8629 c = counts[idx + fd->collapse - 1];
8630 tree purpose = size_int (idx);
8631 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8632 if (TREE_CODE (c) != INTEGER_CST)
8633 TREE_STATIC (arr) = 0;
8636 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8637 if (!TREE_STATIC (arr))
8638 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8639 void_type_node, arr),
8640 true, NULL_TREE, true, GSI_SAME_STMT);
8641 t1 = build_fold_addr_expr (arr);
8642 t2 = NULL_TREE;
8644 else
8646 t2 = fold_convert (fd->iter_type, fd->loop.step);
8647 t1 = fd->loop.n2;
8648 t0 = fd->loop.n1;
8649 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8651 tree innerc
8652 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8653 OMP_CLAUSE__LOOPTEMP_);
8654 gcc_assert (innerc);
8655 t0 = OMP_CLAUSE_DECL (innerc);
8656 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8657 OMP_CLAUSE__LOOPTEMP_);
8658 gcc_assert (innerc);
8659 t1 = OMP_CLAUSE_DECL (innerc);
8661 if (POINTER_TYPE_P (TREE_TYPE (t0))
8662 && TYPE_PRECISION (TREE_TYPE (t0))
8663 != TYPE_PRECISION (fd->iter_type))
8665 /* Avoid casting pointers to integer of a different size. */
8666 tree itype = signed_type_for (type);
8667 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8668 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8670 else
8672 t1 = fold_convert (fd->iter_type, t1);
8673 t0 = fold_convert (fd->iter_type, t0);
8675 if (bias)
8677 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8678 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8681 if (fd->iter_type == long_integer_type_node || fd->ordered)
8683 if (fd->chunk_size)
8685 t = fold_convert (fd->iter_type, fd->chunk_size);
8686 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8687 if (fd->ordered)
8688 t = build_call_expr (builtin_decl_explicit (start_fn),
8689 5, t0, t1, t, t3, t4);
8690 else
8691 t = build_call_expr (builtin_decl_explicit (start_fn),
8692 6, t0, t1, t2, t, t3, t4);
8694 else if (fd->ordered)
8695 t = build_call_expr (builtin_decl_explicit (start_fn),
8696 4, t0, t1, t3, t4);
8697 else
8698 t = build_call_expr (builtin_decl_explicit (start_fn),
8699 5, t0, t1, t2, t3, t4);
8701 else
8703 tree t5;
8704 tree c_bool_type;
8705 tree bfn_decl;
8707 /* The GOMP_loop_ull_*start functions have additional boolean
8708 argument, true for < loops and false for > loops.
8709 In Fortran, the C bool type can be different from
8710 boolean_type_node. */
8711 bfn_decl = builtin_decl_explicit (start_fn);
8712 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8713 t5 = build_int_cst (c_bool_type,
8714 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8715 if (fd->chunk_size)
8717 tree bfn_decl = builtin_decl_explicit (start_fn);
8718 t = fold_convert (fd->iter_type, fd->chunk_size);
8719 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8720 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8722 else
8723 t = build_call_expr (builtin_decl_explicit (start_fn),
8724 6, t5, t0, t1, t2, t3, t4);
8727 if (TREE_TYPE (t) != boolean_type_node)
8728 t = fold_build2 (NE_EXPR, boolean_type_node,
8729 t, build_int_cst (TREE_TYPE (t), 0));
8730 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8731 true, GSI_SAME_STMT);
8732 if (arr && !TREE_STATIC (arr))
8734 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8735 TREE_THIS_VOLATILE (clobber) = 1;
8736 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8737 GSI_SAME_STMT);
8739 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8741 /* Remove the GIMPLE_OMP_FOR statement. */
8742 gsi_remove (&gsi, true);
8744 if (gsi_end_p (gsif))
8745 gsif = gsi_after_labels (gsi_bb (gsif));
8746 gsi_next (&gsif);
8748 /* Iteration setup for sequential loop goes in L0_BB. */
8749 tree startvar = fd->loop.v;
8750 tree endvar = NULL_TREE;
8752 if (gimple_omp_for_combined_p (fd->for_stmt))
8754 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8755 && gimple_omp_for_kind (inner_stmt)
8756 == GF_OMP_FOR_KIND_SIMD);
8757 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8758 OMP_CLAUSE__LOOPTEMP_);
8759 gcc_assert (innerc);
8760 startvar = OMP_CLAUSE_DECL (innerc);
8761 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8762 OMP_CLAUSE__LOOPTEMP_);
8763 gcc_assert (innerc);
8764 endvar = OMP_CLAUSE_DECL (innerc);
8767 gsi = gsi_start_bb (l0_bb);
8768 t = istart0;
8769 if (fd->ordered && fd->collapse == 1)
8770 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8771 fold_convert (fd->iter_type, fd->loop.step));
8772 else if (bias)
8773 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8774 if (fd->ordered && fd->collapse == 1)
8776 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8777 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8778 fd->loop.n1, fold_convert (sizetype, t));
8779 else
8781 t = fold_convert (TREE_TYPE (startvar), t);
8782 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8783 fd->loop.n1, t);
8786 else
8788 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8789 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8790 t = fold_convert (TREE_TYPE (startvar), t);
8792 t = force_gimple_operand_gsi (&gsi, t,
8793 DECL_P (startvar)
8794 && TREE_ADDRESSABLE (startvar),
8795 NULL_TREE, false, GSI_CONTINUE_LINKING);
8796 assign_stmt = gimple_build_assign (startvar, t);
8797 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8799 t = iend0;
8800 if (fd->ordered && fd->collapse == 1)
8801 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8802 fold_convert (fd->iter_type, fd->loop.step));
8803 else if (bias)
8804 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8805 if (fd->ordered && fd->collapse == 1)
8807 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8808 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8809 fd->loop.n1, fold_convert (sizetype, t));
8810 else
8812 t = fold_convert (TREE_TYPE (startvar), t);
8813 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8814 fd->loop.n1, t);
8817 else
8819 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8820 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8821 t = fold_convert (TREE_TYPE (startvar), t);
8823 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8824 false, GSI_CONTINUE_LINKING);
8825 if (endvar)
8827 assign_stmt = gimple_build_assign (endvar, iend);
8828 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8829 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8830 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8831 else
8832 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8833 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8835 /* Handle linear clause adjustments. */
8836 tree itercnt = NULL_TREE;
8837 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8838 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8839 c; c = OMP_CLAUSE_CHAIN (c))
8840 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8841 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8843 tree d = OMP_CLAUSE_DECL (c);
8844 bool is_ref = is_reference (d);
8845 tree t = d, a, dest;
8846 if (is_ref)
8847 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8848 tree type = TREE_TYPE (t);
8849 if (POINTER_TYPE_P (type))
8850 type = sizetype;
8851 dest = unshare_expr (t);
8852 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8853 expand_omp_build_assign (&gsif, v, t);
8854 if (itercnt == NULL_TREE)
8856 itercnt = startvar;
8857 tree n1 = fd->loop.n1;
8858 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8860 itercnt
8861 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8862 itercnt);
8863 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8865 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8866 itercnt, n1);
8867 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8868 itercnt, fd->loop.step);
8869 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8870 NULL_TREE, false,
8871 GSI_CONTINUE_LINKING);
8873 a = fold_build2 (MULT_EXPR, type,
8874 fold_convert (type, itercnt),
8875 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8876 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8877 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8878 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8879 false, GSI_CONTINUE_LINKING);
8880 assign_stmt = gimple_build_assign (dest, t);
8881 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8883 if (fd->collapse > 1)
8884 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8886 if (fd->ordered)
8888 /* Until now, counts array contained number of iterations or
8889 variable containing it for ith loop. From now on, we need
8890 those counts only for collapsed loops, and only for the 2nd
8891 till the last collapsed one. Move those one element earlier,
8892 we'll use counts[fd->collapse - 1] for the first source/sink
8893 iteration counter and so on and counts[fd->ordered]
8894 as the array holding the current counter values for
8895 depend(source). */
8896 if (fd->collapse > 1)
8897 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8898 if (broken_loop)
8900 int i;
8901 for (i = fd->collapse; i < fd->ordered; i++)
8903 tree type = TREE_TYPE (fd->loops[i].v);
8904 tree this_cond
8905 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8906 fold_convert (type, fd->loops[i].n1),
8907 fold_convert (type, fd->loops[i].n2));
8908 if (!integer_onep (this_cond))
8909 break;
8911 if (i < fd->ordered)
8913 cont_bb
8914 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8915 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8916 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8917 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8918 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8919 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8920 make_edge (cont_bb, l1_bb, 0);
8921 l2_bb = create_empty_bb (cont_bb);
8922 broken_loop = false;
8925 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8926 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8927 ordered_lastprivate);
8928 if (counts[fd->collapse - 1])
8930 gcc_assert (fd->collapse == 1);
8931 gsi = gsi_last_bb (l0_bb);
8932 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8933 istart0, true);
8934 gsi = gsi_last_bb (cont_bb);
8935 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8936 build_int_cst (fd->iter_type, 1));
8937 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8938 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8939 size_zero_node, NULL_TREE, NULL_TREE);
8940 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8941 t = counts[fd->collapse - 1];
8943 else if (fd->collapse > 1)
8944 t = fd->loop.v;
8945 else
8947 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8948 fd->loops[0].v, fd->loops[0].n1);
8949 t = fold_convert (fd->iter_type, t);
8951 gsi = gsi_last_bb (l0_bb);
8952 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8953 size_zero_node, NULL_TREE, NULL_TREE);
8954 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8955 false, GSI_CONTINUE_LINKING);
8956 expand_omp_build_assign (&gsi, aref, t, true);
8959 if (!broken_loop)
8961 /* Code to control the increment and predicate for the sequential
8962 loop goes in the CONT_BB. */
8963 gsi = gsi_last_bb (cont_bb);
8964 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8965 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8966 vmain = gimple_omp_continue_control_use (cont_stmt);
8967 vback = gimple_omp_continue_control_def (cont_stmt);
8969 if (!gimple_omp_for_combined_p (fd->for_stmt))
8971 if (POINTER_TYPE_P (type))
8972 t = fold_build_pointer_plus (vmain, fd->loop.step);
8973 else
8974 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8975 t = force_gimple_operand_gsi (&gsi, t,
8976 DECL_P (vback)
8977 && TREE_ADDRESSABLE (vback),
8978 NULL_TREE, true, GSI_SAME_STMT);
8979 assign_stmt = gimple_build_assign (vback, t);
8980 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8982 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8984 if (fd->collapse > 1)
8985 t = fd->loop.v;
8986 else
8988 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8989 fd->loops[0].v, fd->loops[0].n1);
8990 t = fold_convert (fd->iter_type, t);
8992 tree aref = build4 (ARRAY_REF, fd->iter_type,
8993 counts[fd->ordered], size_zero_node,
8994 NULL_TREE, NULL_TREE);
8995 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8996 true, GSI_SAME_STMT);
8997 expand_omp_build_assign (&gsi, aref, t);
9000 t = build2 (fd->loop.cond_code, boolean_type_node,
9001 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
9002 iend);
9003 gcond *cond_stmt = gimple_build_cond_empty (t);
9004 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9007 /* Remove GIMPLE_OMP_CONTINUE. */
9008 gsi_remove (&gsi, true);
9010 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9011 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
9013 /* Emit code to get the next parallel iteration in L2_BB. */
9014 gsi = gsi_start_bb (l2_bb);
9016 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
9017 build_fold_addr_expr (istart0),
9018 build_fold_addr_expr (iend0));
9019 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9020 false, GSI_CONTINUE_LINKING);
9021 if (TREE_TYPE (t) != boolean_type_node)
9022 t = fold_build2 (NE_EXPR, boolean_type_node,
9023 t, build_int_cst (TREE_TYPE (t), 0));
9024 gcond *cond_stmt = gimple_build_cond_empty (t);
9025 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9028 /* Add the loop cleanup function. */
9029 gsi = gsi_last_bb (exit_bb);
9030 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9031 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9032 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9033 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9034 else
9035 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9036 gcall *call_stmt = gimple_build_call (t, 0);
9037 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9038 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9039 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9040 if (fd->ordered)
9042 tree arr = counts[fd->ordered];
9043 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9044 TREE_THIS_VOLATILE (clobber) = 1;
9045 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9046 GSI_SAME_STMT);
9048 gsi_remove (&gsi, true);
9050 /* Connect the new blocks. */
9051 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9052 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9054 if (!broken_loop)
9056 gimple_seq phis;
9058 e = find_edge (cont_bb, l3_bb);
9059 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9061 phis = phi_nodes (l3_bb);
9062 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9064 gimple *phi = gsi_stmt (gsi);
9065 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9066 PHI_ARG_DEF_FROM_EDGE (phi, e));
9068 remove_edge (e);
9070 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9071 e = find_edge (cont_bb, l1_bb);
9072 if (e == NULL)
9074 e = BRANCH_EDGE (cont_bb);
9075 gcc_assert (single_succ (e->dest) == l1_bb);
9077 if (gimple_omp_for_combined_p (fd->for_stmt))
9079 remove_edge (e);
9080 e = NULL;
9082 else if (fd->collapse > 1)
9084 remove_edge (e);
9085 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9087 else
9088 e->flags = EDGE_TRUE_VALUE;
9089 if (e)
9091 e->probability = REG_BR_PROB_BASE * 7 / 8;
9092 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9094 else
9096 e = find_edge (cont_bb, l2_bb);
9097 e->flags = EDGE_FALLTHRU;
9099 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9101 if (gimple_in_ssa_p (cfun))
9103 /* Add phis to the outer loop that connect to the phis in the inner,
9104 original loop, and move the loop entry value of the inner phi to
9105 the loop entry value of the outer phi. */
9106 gphi_iterator psi;
9107 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9109 source_location locus;
9110 gphi *nphi;
9111 gphi *exit_phi = psi.phi ();
9113 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9114 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9116 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9117 edge latch_to_l1 = find_edge (latch, l1_bb);
9118 gphi *inner_phi
9119 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9121 tree t = gimple_phi_result (exit_phi);
9122 tree new_res = copy_ssa_name (t, NULL);
9123 nphi = create_phi_node (new_res, l0_bb);
9125 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9126 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9127 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9128 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9129 add_phi_arg (nphi, t, entry_to_l0, locus);
9131 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9132 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9134 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9138 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9139 recompute_dominator (CDI_DOMINATORS, l2_bb));
9140 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9141 recompute_dominator (CDI_DOMINATORS, l3_bb));
9142 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9143 recompute_dominator (CDI_DOMINATORS, l0_bb));
9144 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9145 recompute_dominator (CDI_DOMINATORS, l1_bb));
9147 /* We enter expand_omp_for_generic with a loop. This original loop may
9148 have its own loop struct, or it may be part of an outer loop struct
9149 (which may be the fake loop). */
9150 struct loop *outer_loop = entry_bb->loop_father;
9151 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9153 add_bb_to_loop (l2_bb, outer_loop);
9155 /* We've added a new loop around the original loop. Allocate the
9156 corresponding loop struct. */
9157 struct loop *new_loop = alloc_loop ();
9158 new_loop->header = l0_bb;
9159 new_loop->latch = l2_bb;
9160 add_loop (new_loop, outer_loop);
9162 /* Allocate a loop structure for the original loop unless we already
9163 had one. */
9164 if (!orig_loop_has_loop_struct
9165 && !gimple_omp_for_combined_p (fd->for_stmt))
9167 struct loop *orig_loop = alloc_loop ();
9168 orig_loop->header = l1_bb;
9169 /* The loop may have multiple latches. */
9170 add_loop (orig_loop, new_loop);
9176 /* A subroutine of expand_omp_for. Generate code for a parallel
9177 loop with static schedule and no specified chunk size. Given
9178 parameters:
9180 for (V = N1; V cond N2; V += STEP) BODY;
9182 where COND is "<" or ">", we generate pseudocode
9184 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9185 if (cond is <)
9186 adj = STEP - 1;
9187 else
9188 adj = STEP + 1;
9189 if ((__typeof (V)) -1 > 0 && cond is >)
9190 n = -(adj + N2 - N1) / -STEP;
9191 else
9192 n = (adj + N2 - N1) / STEP;
9193 q = n / nthreads;
9194 tt = n % nthreads;
9195 if (threadid < tt) goto L3; else goto L4;
9197 tt = 0;
9198 q = q + 1;
9200 s0 = q * threadid + tt;
9201 e0 = s0 + q;
9202 V = s0 * STEP + N1;
9203 if (s0 >= e0) goto L2; else goto L0;
9205 e = e0 * STEP + N1;
9207 BODY;
9208 V += STEP;
9209 if (V cond e) goto L1;
9213 static void
9214 expand_omp_for_static_nochunk (struct omp_region *region,
9215 struct omp_for_data *fd,
9216 gimple *inner_stmt)
9218 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9219 tree type, itype, vmain, vback;
9220 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9221 basic_block body_bb, cont_bb, collapse_bb = NULL;
9222 basic_block fin_bb;
9223 gimple_stmt_iterator gsi;
9224 edge ep;
9225 bool broken_loop = region->cont == NULL;
9226 tree *counts = NULL;
9227 tree n1, n2, step;
9229 itype = type = TREE_TYPE (fd->loop.v);
9230 if (POINTER_TYPE_P (type))
9231 itype = signed_type_for (type);
9233 entry_bb = region->entry;
9234 cont_bb = region->cont;
9235 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9236 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9237 gcc_assert (broken_loop
9238 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9239 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9240 body_bb = single_succ (seq_start_bb);
9241 if (!broken_loop)
9243 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9244 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9245 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9247 exit_bb = region->exit;
9249 /* Iteration space partitioning goes in ENTRY_BB. */
9250 gsi = gsi_last_bb (entry_bb);
9251 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9253 if (fd->collapse > 1)
9255 int first_zero_iter = -1, dummy = -1;
9256 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9258 counts = XALLOCAVEC (tree, fd->collapse);
9259 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9260 fin_bb, first_zero_iter,
9261 dummy_bb, dummy, l2_dom_bb);
9262 t = NULL_TREE;
9264 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9265 t = integer_one_node;
9266 else
9267 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9268 fold_convert (type, fd->loop.n1),
9269 fold_convert (type, fd->loop.n2));
9270 if (fd->collapse == 1
9271 && TYPE_UNSIGNED (type)
9272 && (t == NULL_TREE || !integer_onep (t)))
9274 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9275 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9276 true, GSI_SAME_STMT);
9277 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9278 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9279 true, GSI_SAME_STMT);
9280 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9281 NULL_TREE, NULL_TREE);
9282 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9283 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9284 expand_omp_regimplify_p, NULL, NULL)
9285 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9286 expand_omp_regimplify_p, NULL, NULL))
9288 gsi = gsi_for_stmt (cond_stmt);
9289 gimple_regimplify_operands (cond_stmt, &gsi);
9291 ep = split_block (entry_bb, cond_stmt);
9292 ep->flags = EDGE_TRUE_VALUE;
9293 entry_bb = ep->dest;
9294 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9295 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9296 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9297 if (gimple_in_ssa_p (cfun))
9299 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9300 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9301 !gsi_end_p (gpi); gsi_next (&gpi))
9303 gphi *phi = gpi.phi ();
9304 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9305 ep, UNKNOWN_LOCATION);
9308 gsi = gsi_last_bb (entry_bb);
9311 switch (gimple_omp_for_kind (fd->for_stmt))
9313 case GF_OMP_FOR_KIND_FOR:
9314 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9315 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9316 break;
9317 case GF_OMP_FOR_KIND_DISTRIBUTE:
9318 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9319 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9320 break;
9321 default:
9322 gcc_unreachable ();
9324 nthreads = build_call_expr (nthreads, 0);
9325 nthreads = fold_convert (itype, nthreads);
9326 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9327 true, GSI_SAME_STMT);
9328 threadid = build_call_expr (threadid, 0);
9329 threadid = fold_convert (itype, threadid);
9330 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9331 true, GSI_SAME_STMT);
9333 n1 = fd->loop.n1;
9334 n2 = fd->loop.n2;
9335 step = fd->loop.step;
9336 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9338 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9339 OMP_CLAUSE__LOOPTEMP_);
9340 gcc_assert (innerc);
9341 n1 = OMP_CLAUSE_DECL (innerc);
9342 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9343 OMP_CLAUSE__LOOPTEMP_);
9344 gcc_assert (innerc);
9345 n2 = OMP_CLAUSE_DECL (innerc);
9347 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9348 true, NULL_TREE, true, GSI_SAME_STMT);
9349 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9350 true, NULL_TREE, true, GSI_SAME_STMT);
9351 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9352 true, NULL_TREE, true, GSI_SAME_STMT);
9354 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9355 t = fold_build2 (PLUS_EXPR, itype, step, t);
9356 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9357 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9358 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9359 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9360 fold_build1 (NEGATE_EXPR, itype, t),
9361 fold_build1 (NEGATE_EXPR, itype, step));
9362 else
9363 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9364 t = fold_convert (itype, t);
9365 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9367 q = create_tmp_reg (itype, "q");
9368 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9369 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9370 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9372 tt = create_tmp_reg (itype, "tt");
9373 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9374 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9375 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9377 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9378 gcond *cond_stmt = gimple_build_cond_empty (t);
9379 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9381 second_bb = split_block (entry_bb, cond_stmt)->dest;
9382 gsi = gsi_last_bb (second_bb);
9383 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9385 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9386 GSI_SAME_STMT);
9387 gassign *assign_stmt
9388 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9389 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9391 third_bb = split_block (second_bb, assign_stmt)->dest;
9392 gsi = gsi_last_bb (third_bb);
9393 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9395 t = build2 (MULT_EXPR, itype, q, threadid);
9396 t = build2 (PLUS_EXPR, itype, t, tt);
9397 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9399 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9400 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9402 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9403 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9405 /* Remove the GIMPLE_OMP_FOR statement. */
9406 gsi_remove (&gsi, true);
9408 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9409 gsi = gsi_start_bb (seq_start_bb);
9411 tree startvar = fd->loop.v;
9412 tree endvar = NULL_TREE;
9414 if (gimple_omp_for_combined_p (fd->for_stmt))
9416 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9417 ? gimple_omp_parallel_clauses (inner_stmt)
9418 : gimple_omp_for_clauses (inner_stmt);
9419 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9420 gcc_assert (innerc);
9421 startvar = OMP_CLAUSE_DECL (innerc);
9422 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9423 OMP_CLAUSE__LOOPTEMP_);
9424 gcc_assert (innerc);
9425 endvar = OMP_CLAUSE_DECL (innerc);
9426 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9427 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9429 int i;
9430 for (i = 1; i < fd->collapse; i++)
9432 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9433 OMP_CLAUSE__LOOPTEMP_);
9434 gcc_assert (innerc);
9436 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9437 OMP_CLAUSE__LOOPTEMP_);
9438 if (innerc)
9440 /* If needed (distribute parallel for with lastprivate),
9441 propagate down the total number of iterations. */
9442 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9443 fd->loop.n2);
9444 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9445 GSI_CONTINUE_LINKING);
9446 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9447 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9451 t = fold_convert (itype, s0);
9452 t = fold_build2 (MULT_EXPR, itype, t, step);
9453 if (POINTER_TYPE_P (type))
9454 t = fold_build_pointer_plus (n1, t);
9455 else
9456 t = fold_build2 (PLUS_EXPR, type, t, n1);
9457 t = fold_convert (TREE_TYPE (startvar), t);
9458 t = force_gimple_operand_gsi (&gsi, t,
9459 DECL_P (startvar)
9460 && TREE_ADDRESSABLE (startvar),
9461 NULL_TREE, false, GSI_CONTINUE_LINKING);
9462 assign_stmt = gimple_build_assign (startvar, t);
9463 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9465 t = fold_convert (itype, e0);
9466 t = fold_build2 (MULT_EXPR, itype, t, step);
9467 if (POINTER_TYPE_P (type))
9468 t = fold_build_pointer_plus (n1, t);
9469 else
9470 t = fold_build2 (PLUS_EXPR, type, t, n1);
9471 t = fold_convert (TREE_TYPE (startvar), t);
9472 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9473 false, GSI_CONTINUE_LINKING);
9474 if (endvar)
9476 assign_stmt = gimple_build_assign (endvar, e);
9477 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9478 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9479 assign_stmt = gimple_build_assign (fd->loop.v, e);
9480 else
9481 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9482 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9484 /* Handle linear clause adjustments. */
9485 tree itercnt = NULL_TREE;
9486 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9487 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9488 c; c = OMP_CLAUSE_CHAIN (c))
9489 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9490 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9492 tree d = OMP_CLAUSE_DECL (c);
9493 bool is_ref = is_reference (d);
9494 tree t = d, a, dest;
9495 if (is_ref)
9496 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9497 if (itercnt == NULL_TREE)
9499 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9501 itercnt = fold_build2 (MINUS_EXPR, itype,
9502 fold_convert (itype, n1),
9503 fold_convert (itype, fd->loop.n1));
9504 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9505 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9506 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9507 NULL_TREE, false,
9508 GSI_CONTINUE_LINKING);
9510 else
9511 itercnt = s0;
9513 tree type = TREE_TYPE (t);
9514 if (POINTER_TYPE_P (type))
9515 type = sizetype;
9516 a = fold_build2 (MULT_EXPR, type,
9517 fold_convert (type, itercnt),
9518 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9519 dest = unshare_expr (t);
9520 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9521 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9522 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9523 false, GSI_CONTINUE_LINKING);
9524 assign_stmt = gimple_build_assign (dest, t);
9525 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9527 if (fd->collapse > 1)
9528 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9530 if (!broken_loop)
9532 /* The code controlling the sequential loop replaces the
9533 GIMPLE_OMP_CONTINUE. */
9534 gsi = gsi_last_bb (cont_bb);
9535 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9536 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9537 vmain = gimple_omp_continue_control_use (cont_stmt);
9538 vback = gimple_omp_continue_control_def (cont_stmt);
9540 if (!gimple_omp_for_combined_p (fd->for_stmt))
9542 if (POINTER_TYPE_P (type))
9543 t = fold_build_pointer_plus (vmain, step);
9544 else
9545 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9546 t = force_gimple_operand_gsi (&gsi, t,
9547 DECL_P (vback)
9548 && TREE_ADDRESSABLE (vback),
9549 NULL_TREE, true, GSI_SAME_STMT);
9550 assign_stmt = gimple_build_assign (vback, t);
9551 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9553 t = build2 (fd->loop.cond_code, boolean_type_node,
9554 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9555 ? t : vback, e);
9556 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9559 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9560 gsi_remove (&gsi, true);
9562 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9563 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9566 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9567 gsi = gsi_last_bb (exit_bb);
9568 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9570 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9571 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9573 gsi_remove (&gsi, true);
9575 /* Connect all the blocks. */
9576 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9577 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9578 ep = find_edge (entry_bb, second_bb);
9579 ep->flags = EDGE_TRUE_VALUE;
9580 ep->probability = REG_BR_PROB_BASE / 4;
9581 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9582 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9584 if (!broken_loop)
9586 ep = find_edge (cont_bb, body_bb);
9587 if (ep == NULL)
9589 ep = BRANCH_EDGE (cont_bb);
9590 gcc_assert (single_succ (ep->dest) == body_bb);
9592 if (gimple_omp_for_combined_p (fd->for_stmt))
9594 remove_edge (ep);
9595 ep = NULL;
9597 else if (fd->collapse > 1)
9599 remove_edge (ep);
9600 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9602 else
9603 ep->flags = EDGE_TRUE_VALUE;
9604 find_edge (cont_bb, fin_bb)->flags
9605 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9608 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9609 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9610 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9612 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9613 recompute_dominator (CDI_DOMINATORS, body_bb));
9614 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9615 recompute_dominator (CDI_DOMINATORS, fin_bb));
9617 struct loop *loop = body_bb->loop_father;
9618 if (loop != entry_bb->loop_father)
9620 gcc_assert (loop->header == body_bb);
9621 gcc_assert (broken_loop
9622 || loop->latch == region->cont
9623 || single_pred (loop->latch) == region->cont);
9624 return;
9627 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9629 loop = alloc_loop ();
9630 loop->header = body_bb;
9631 if (collapse_bb == NULL)
9632 loop->latch = cont_bb;
9633 add_loop (loop, body_bb->loop_father);
9637 /* Return phi in E->DEST with ARG on edge E. */
9639 static gphi *
9640 find_phi_with_arg_on_edge (tree arg, edge e)
9642 basic_block bb = e->dest;
9644 for (gphi_iterator gpi = gsi_start_phis (bb);
9645 !gsi_end_p (gpi);
9646 gsi_next (&gpi))
9648 gphi *phi = gpi.phi ();
9649 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9650 return phi;
9653 return NULL;
9656 /* A subroutine of expand_omp_for. Generate code for a parallel
9657 loop with static schedule and a specified chunk size. Given
9658 parameters:
9660 for (V = N1; V cond N2; V += STEP) BODY;
9662 where COND is "<" or ">", we generate pseudocode
9664 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9665 if (cond is <)
9666 adj = STEP - 1;
9667 else
9668 adj = STEP + 1;
9669 if ((__typeof (V)) -1 > 0 && cond is >)
9670 n = -(adj + N2 - N1) / -STEP;
9671 else
9672 n = (adj + N2 - N1) / STEP;
9673 trip = 0;
9674 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9675 here so that V is defined
9676 if the loop is not entered
9678 s0 = (trip * nthreads + threadid) * CHUNK;
9679 e0 = min(s0 + CHUNK, n);
9680 if (s0 < n) goto L1; else goto L4;
9682 V = s0 * STEP + N1;
9683 e = e0 * STEP + N1;
9685 BODY;
9686 V += STEP;
9687 if (V cond e) goto L2; else goto L3;
9689 trip += 1;
9690 goto L0;
9694 static void
9695 expand_omp_for_static_chunk (struct omp_region *region,
9696 struct omp_for_data *fd, gimple *inner_stmt)
9698 tree n, s0, e0, e, t;
9699 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9700 tree type, itype, vmain, vback, vextra;
9701 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9702 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9703 gimple_stmt_iterator gsi;
9704 edge se;
9705 bool broken_loop = region->cont == NULL;
9706 tree *counts = NULL;
9707 tree n1, n2, step;
9709 itype = type = TREE_TYPE (fd->loop.v);
9710 if (POINTER_TYPE_P (type))
9711 itype = signed_type_for (type);
9713 entry_bb = region->entry;
9714 se = split_block (entry_bb, last_stmt (entry_bb));
9715 entry_bb = se->src;
9716 iter_part_bb = se->dest;
9717 cont_bb = region->cont;
9718 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9719 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9720 gcc_assert (broken_loop
9721 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9722 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9723 body_bb = single_succ (seq_start_bb);
9724 if (!broken_loop)
9726 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9727 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9728 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9729 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9731 exit_bb = region->exit;
9733 /* Trip and adjustment setup goes in ENTRY_BB. */
9734 gsi = gsi_last_bb (entry_bb);
9735 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9737 if (fd->collapse > 1)
9739 int first_zero_iter = -1, dummy = -1;
9740 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9742 counts = XALLOCAVEC (tree, fd->collapse);
9743 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9744 fin_bb, first_zero_iter,
9745 dummy_bb, dummy, l2_dom_bb);
9746 t = NULL_TREE;
9748 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9749 t = integer_one_node;
9750 else
9751 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9752 fold_convert (type, fd->loop.n1),
9753 fold_convert (type, fd->loop.n2));
9754 if (fd->collapse == 1
9755 && TYPE_UNSIGNED (type)
9756 && (t == NULL_TREE || !integer_onep (t)))
9758 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9759 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9760 true, GSI_SAME_STMT);
9761 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9762 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9763 true, GSI_SAME_STMT);
9764 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9765 NULL_TREE, NULL_TREE);
9766 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9767 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9768 expand_omp_regimplify_p, NULL, NULL)
9769 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9770 expand_omp_regimplify_p, NULL, NULL))
9772 gsi = gsi_for_stmt (cond_stmt);
9773 gimple_regimplify_operands (cond_stmt, &gsi);
9775 se = split_block (entry_bb, cond_stmt);
9776 se->flags = EDGE_TRUE_VALUE;
9777 entry_bb = se->dest;
9778 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9779 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9780 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9781 if (gimple_in_ssa_p (cfun))
9783 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9784 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9785 !gsi_end_p (gpi); gsi_next (&gpi))
9787 gphi *phi = gpi.phi ();
9788 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9789 se, UNKNOWN_LOCATION);
9792 gsi = gsi_last_bb (entry_bb);
9795 switch (gimple_omp_for_kind (fd->for_stmt))
9797 case GF_OMP_FOR_KIND_FOR:
9798 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9799 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9800 break;
9801 case GF_OMP_FOR_KIND_DISTRIBUTE:
9802 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9803 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9804 break;
9805 default:
9806 gcc_unreachable ();
9808 nthreads = build_call_expr (nthreads, 0);
9809 nthreads = fold_convert (itype, nthreads);
9810 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9811 true, GSI_SAME_STMT);
9812 threadid = build_call_expr (threadid, 0);
9813 threadid = fold_convert (itype, threadid);
9814 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9815 true, GSI_SAME_STMT);
9817 n1 = fd->loop.n1;
9818 n2 = fd->loop.n2;
9819 step = fd->loop.step;
9820 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9822 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9823 OMP_CLAUSE__LOOPTEMP_);
9824 gcc_assert (innerc);
9825 n1 = OMP_CLAUSE_DECL (innerc);
9826 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9827 OMP_CLAUSE__LOOPTEMP_);
9828 gcc_assert (innerc);
9829 n2 = OMP_CLAUSE_DECL (innerc);
9831 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9832 true, NULL_TREE, true, GSI_SAME_STMT);
9833 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9834 true, NULL_TREE, true, GSI_SAME_STMT);
9835 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9836 true, NULL_TREE, true, GSI_SAME_STMT);
9837 tree chunk_size = fold_convert (itype, fd->chunk_size);
9838 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9839 chunk_size
9840 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9841 GSI_SAME_STMT);
9843 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9844 t = fold_build2 (PLUS_EXPR, itype, step, t);
9845 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9846 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9847 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9848 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9849 fold_build1 (NEGATE_EXPR, itype, t),
9850 fold_build1 (NEGATE_EXPR, itype, step));
9851 else
9852 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9853 t = fold_convert (itype, t);
9854 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9855 true, GSI_SAME_STMT);
9857 trip_var = create_tmp_reg (itype, ".trip");
9858 if (gimple_in_ssa_p (cfun))
9860 trip_init = make_ssa_name (trip_var);
9861 trip_main = make_ssa_name (trip_var);
9862 trip_back = make_ssa_name (trip_var);
9864 else
9866 trip_init = trip_var;
9867 trip_main = trip_var;
9868 trip_back = trip_var;
9871 gassign *assign_stmt
9872 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9873 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9875 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9876 t = fold_build2 (MULT_EXPR, itype, t, step);
9877 if (POINTER_TYPE_P (type))
9878 t = fold_build_pointer_plus (n1, t);
9879 else
9880 t = fold_build2 (PLUS_EXPR, type, t, n1);
9881 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9882 true, GSI_SAME_STMT);
9884 /* Remove the GIMPLE_OMP_FOR. */
9885 gsi_remove (&gsi, true);
9887 gimple_stmt_iterator gsif = gsi;
9889 /* Iteration space partitioning goes in ITER_PART_BB. */
9890 gsi = gsi_last_bb (iter_part_bb);
9892 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9893 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9894 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9895 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9896 false, GSI_CONTINUE_LINKING);
9898 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9899 t = fold_build2 (MIN_EXPR, itype, t, n);
9900 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9901 false, GSI_CONTINUE_LINKING);
9903 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9904 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9906 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9907 gsi = gsi_start_bb (seq_start_bb);
9909 tree startvar = fd->loop.v;
9910 tree endvar = NULL_TREE;
9912 if (gimple_omp_for_combined_p (fd->for_stmt))
9914 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9915 ? gimple_omp_parallel_clauses (inner_stmt)
9916 : gimple_omp_for_clauses (inner_stmt);
9917 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9918 gcc_assert (innerc);
9919 startvar = OMP_CLAUSE_DECL (innerc);
9920 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9921 OMP_CLAUSE__LOOPTEMP_);
9922 gcc_assert (innerc);
9923 endvar = OMP_CLAUSE_DECL (innerc);
9924 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9925 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9927 int i;
9928 for (i = 1; i < fd->collapse; i++)
9930 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9931 OMP_CLAUSE__LOOPTEMP_);
9932 gcc_assert (innerc);
9934 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9935 OMP_CLAUSE__LOOPTEMP_);
9936 if (innerc)
9938 /* If needed (distribute parallel for with lastprivate),
9939 propagate down the total number of iterations. */
9940 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9941 fd->loop.n2);
9942 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9943 GSI_CONTINUE_LINKING);
9944 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9945 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9950 t = fold_convert (itype, s0);
9951 t = fold_build2 (MULT_EXPR, itype, t, step);
9952 if (POINTER_TYPE_P (type))
9953 t = fold_build_pointer_plus (n1, t);
9954 else
9955 t = fold_build2 (PLUS_EXPR, type, t, n1);
9956 t = fold_convert (TREE_TYPE (startvar), t);
9957 t = force_gimple_operand_gsi (&gsi, t,
9958 DECL_P (startvar)
9959 && TREE_ADDRESSABLE (startvar),
9960 NULL_TREE, false, GSI_CONTINUE_LINKING);
9961 assign_stmt = gimple_build_assign (startvar, t);
9962 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9964 t = fold_convert (itype, e0);
9965 t = fold_build2 (MULT_EXPR, itype, t, step);
9966 if (POINTER_TYPE_P (type))
9967 t = fold_build_pointer_plus (n1, t);
9968 else
9969 t = fold_build2 (PLUS_EXPR, type, t, n1);
9970 t = fold_convert (TREE_TYPE (startvar), t);
9971 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9972 false, GSI_CONTINUE_LINKING);
9973 if (endvar)
9975 assign_stmt = gimple_build_assign (endvar, e);
9976 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9977 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9978 assign_stmt = gimple_build_assign (fd->loop.v, e);
9979 else
9980 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9981 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9983 /* Handle linear clause adjustments. */
9984 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9985 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9986 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9987 c; c = OMP_CLAUSE_CHAIN (c))
9988 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9989 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9991 tree d = OMP_CLAUSE_DECL (c);
9992 bool is_ref = is_reference (d);
9993 tree t = d, a, dest;
9994 if (is_ref)
9995 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9996 tree type = TREE_TYPE (t);
9997 if (POINTER_TYPE_P (type))
9998 type = sizetype;
9999 dest = unshare_expr (t);
10000 tree v = create_tmp_var (TREE_TYPE (t), NULL);
10001 expand_omp_build_assign (&gsif, v, t);
10002 if (itercnt == NULL_TREE)
10004 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10006 itercntbias
10007 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
10008 fold_convert (itype, fd->loop.n1));
10009 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
10010 itercntbias, step);
10011 itercntbias
10012 = force_gimple_operand_gsi (&gsif, itercntbias, true,
10013 NULL_TREE, true,
10014 GSI_SAME_STMT);
10015 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
10016 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
10017 NULL_TREE, false,
10018 GSI_CONTINUE_LINKING);
10020 else
10021 itercnt = s0;
10023 a = fold_build2 (MULT_EXPR, type,
10024 fold_convert (type, itercnt),
10025 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10026 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10027 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10028 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10029 false, GSI_CONTINUE_LINKING);
10030 assign_stmt = gimple_build_assign (dest, t);
10031 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10033 if (fd->collapse > 1)
10034 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10036 if (!broken_loop)
10038 /* The code controlling the sequential loop goes in CONT_BB,
10039 replacing the GIMPLE_OMP_CONTINUE. */
10040 gsi = gsi_last_bb (cont_bb);
10041 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10042 vmain = gimple_omp_continue_control_use (cont_stmt);
10043 vback = gimple_omp_continue_control_def (cont_stmt);
10045 if (!gimple_omp_for_combined_p (fd->for_stmt))
10047 if (POINTER_TYPE_P (type))
10048 t = fold_build_pointer_plus (vmain, step);
10049 else
10050 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10051 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10052 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10053 true, GSI_SAME_STMT);
10054 assign_stmt = gimple_build_assign (vback, t);
10055 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10057 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10058 t = build2 (EQ_EXPR, boolean_type_node,
10059 build_int_cst (itype, 0),
10060 build_int_cst (itype, 1));
10061 else
10062 t = build2 (fd->loop.cond_code, boolean_type_node,
10063 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10064 ? t : vback, e);
10065 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10068 /* Remove GIMPLE_OMP_CONTINUE. */
10069 gsi_remove (&gsi, true);
10071 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10072 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10074 /* Trip update code goes into TRIP_UPDATE_BB. */
10075 gsi = gsi_start_bb (trip_update_bb);
10077 t = build_int_cst (itype, 1);
10078 t = build2 (PLUS_EXPR, itype, trip_main, t);
10079 assign_stmt = gimple_build_assign (trip_back, t);
10080 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10083 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10084 gsi = gsi_last_bb (exit_bb);
10085 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10087 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10088 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10090 gsi_remove (&gsi, true);
10092 /* Connect the new blocks. */
10093 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10094 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10096 if (!broken_loop)
10098 se = find_edge (cont_bb, body_bb);
10099 if (se == NULL)
10101 se = BRANCH_EDGE (cont_bb);
10102 gcc_assert (single_succ (se->dest) == body_bb);
10104 if (gimple_omp_for_combined_p (fd->for_stmt))
10106 remove_edge (se);
10107 se = NULL;
10109 else if (fd->collapse > 1)
10111 remove_edge (se);
10112 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10114 else
10115 se->flags = EDGE_TRUE_VALUE;
10116 find_edge (cont_bb, trip_update_bb)->flags
10117 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10119 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10122 if (gimple_in_ssa_p (cfun))
10124 gphi_iterator psi;
10125 gphi *phi;
10126 edge re, ene;
10127 edge_var_map *vm;
10128 size_t i;
10130 gcc_assert (fd->collapse == 1 && !broken_loop);
10132 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10133 remove arguments of the phi nodes in fin_bb. We need to create
10134 appropriate phi nodes in iter_part_bb instead. */
10135 se = find_edge (iter_part_bb, fin_bb);
10136 re = single_succ_edge (trip_update_bb);
10137 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10138 ene = single_succ_edge (entry_bb);
10140 psi = gsi_start_phis (fin_bb);
10141 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10142 gsi_next (&psi), ++i)
10144 gphi *nphi;
10145 source_location locus;
10147 phi = psi.phi ();
10148 t = gimple_phi_result (phi);
10149 gcc_assert (t == redirect_edge_var_map_result (vm));
10151 if (!single_pred_p (fin_bb))
10152 t = copy_ssa_name (t, phi);
10154 nphi = create_phi_node (t, iter_part_bb);
10156 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10157 locus = gimple_phi_arg_location_from_edge (phi, se);
10159 /* A special case -- fd->loop.v is not yet computed in
10160 iter_part_bb, we need to use vextra instead. */
10161 if (t == fd->loop.v)
10162 t = vextra;
10163 add_phi_arg (nphi, t, ene, locus);
10164 locus = redirect_edge_var_map_location (vm);
10165 tree back_arg = redirect_edge_var_map_def (vm);
10166 add_phi_arg (nphi, back_arg, re, locus);
10167 edge ce = find_edge (cont_bb, body_bb);
10168 if (ce == NULL)
10170 ce = BRANCH_EDGE (cont_bb);
10171 gcc_assert (single_succ (ce->dest) == body_bb);
10172 ce = single_succ_edge (ce->dest);
10174 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10175 gcc_assert (inner_loop_phi != NULL);
10176 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10177 find_edge (seq_start_bb, body_bb), locus);
10179 if (!single_pred_p (fin_bb))
10180 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10182 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10183 redirect_edge_var_map_clear (re);
10184 if (single_pred_p (fin_bb))
10185 while (1)
10187 psi = gsi_start_phis (fin_bb);
10188 if (gsi_end_p (psi))
10189 break;
10190 remove_phi_node (&psi, false);
10193 /* Make phi node for trip. */
10194 phi = create_phi_node (trip_main, iter_part_bb);
10195 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10196 UNKNOWN_LOCATION);
10197 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10198 UNKNOWN_LOCATION);
10201 if (!broken_loop)
10202 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10203 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10204 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10205 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10206 recompute_dominator (CDI_DOMINATORS, fin_bb));
10207 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10208 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10209 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10210 recompute_dominator (CDI_DOMINATORS, body_bb));
10212 if (!broken_loop)
10214 struct loop *loop = body_bb->loop_father;
10215 struct loop *trip_loop = alloc_loop ();
10216 trip_loop->header = iter_part_bb;
10217 trip_loop->latch = trip_update_bb;
10218 add_loop (trip_loop, iter_part_bb->loop_father);
10220 if (loop != entry_bb->loop_father)
10222 gcc_assert (loop->header == body_bb);
10223 gcc_assert (loop->latch == region->cont
10224 || single_pred (loop->latch) == region->cont);
10225 trip_loop->inner = loop;
10226 return;
10229 if (!gimple_omp_for_combined_p (fd->for_stmt))
10231 loop = alloc_loop ();
10232 loop->header = body_bb;
10233 if (collapse_bb == NULL)
10234 loop->latch = cont_bb;
10235 add_loop (loop, trip_loop);
10240 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10241 Given parameters:
10242 for (V = N1; V cond N2; V += STEP) BODY;
10244 where COND is "<" or ">" or "!=", we generate pseudocode
10246 for (ind_var = low; ind_var < high; ind_var++)
10248 V = n1 + (ind_var * STEP)
10250 <BODY>
10253 In the above pseudocode, low and high are function parameters of the
10254 child function. In the function below, we are inserting a temp.
10255 variable that will be making a call to two OMP functions that will not be
10256 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10257 with _Cilk_for). These functions are replaced with low and high
10258 by the function that handles taskreg. */
10261 static void
10262 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10264 bool broken_loop = region->cont == NULL;
10265 basic_block entry_bb = region->entry;
10266 basic_block cont_bb = region->cont;
10268 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10269 gcc_assert (broken_loop
10270 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10271 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10272 basic_block l1_bb, l2_bb;
10274 if (!broken_loop)
10276 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10277 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10278 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10279 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10281 else
10283 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10284 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10285 l2_bb = single_succ (l1_bb);
10287 basic_block exit_bb = region->exit;
10288 basic_block l2_dom_bb = NULL;
10290 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10292 /* Below statements until the "tree high_val = ..." are pseudo statements
10293 used to pass information to be used by expand_omp_taskreg.
10294 low_val and high_val will be replaced by the __low and __high
10295 parameter from the child function.
10297 The call_exprs part is a place-holder, it is mainly used
10298 to distinctly identify to the top-level part that this is
10299 where we should put low and high (reasoning given in header
10300 comment). */
10302 tree child_fndecl
10303 = gimple_omp_parallel_child_fn (
10304 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10305 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10306 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10308 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10309 high_val = t;
10310 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10311 low_val = t;
10313 gcc_assert (low_val && high_val);
10315 tree type = TREE_TYPE (low_val);
10316 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10317 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10319 /* Not needed in SSA form right now. */
10320 gcc_assert (!gimple_in_ssa_p (cfun));
10321 if (l2_dom_bb == NULL)
10322 l2_dom_bb = l1_bb;
10324 tree n1 = low_val;
10325 tree n2 = high_val;
10327 gimple *stmt = gimple_build_assign (ind_var, n1);
10329 /* Replace the GIMPLE_OMP_FOR statement. */
10330 gsi_replace (&gsi, stmt, true);
10332 if (!broken_loop)
10334 /* Code to control the increment goes in the CONT_BB. */
10335 gsi = gsi_last_bb (cont_bb);
10336 stmt = gsi_stmt (gsi);
10337 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10338 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10339 build_one_cst (type));
10341 /* Replace GIMPLE_OMP_CONTINUE. */
10342 gsi_replace (&gsi, stmt, true);
10345 /* Emit the condition in L1_BB. */
10346 gsi = gsi_after_labels (l1_bb);
10347 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10348 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10349 fd->loop.step);
10350 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10351 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10352 fd->loop.n1, fold_convert (sizetype, t));
10353 else
10354 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10355 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10356 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10357 expand_omp_build_assign (&gsi, fd->loop.v, t);
10359 /* The condition is always '<' since the runtime will fill in the low
10360 and high values. */
10361 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10362 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10364 /* Remove GIMPLE_OMP_RETURN. */
10365 gsi = gsi_last_bb (exit_bb);
10366 gsi_remove (&gsi, true);
10368 /* Connect the new blocks. */
10369 remove_edge (FALLTHRU_EDGE (entry_bb));
10371 edge e, ne;
10372 if (!broken_loop)
10374 remove_edge (BRANCH_EDGE (entry_bb));
10375 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10377 e = BRANCH_EDGE (l1_bb);
10378 ne = FALLTHRU_EDGE (l1_bb);
10379 e->flags = EDGE_TRUE_VALUE;
10381 else
10383 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10385 ne = single_succ_edge (l1_bb);
10386 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10389 ne->flags = EDGE_FALSE_VALUE;
10390 e->probability = REG_BR_PROB_BASE * 7 / 8;
10391 ne->probability = REG_BR_PROB_BASE / 8;
10393 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10394 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10395 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10397 if (!broken_loop)
10399 struct loop *loop = alloc_loop ();
10400 loop->header = l1_bb;
10401 loop->latch = cont_bb;
10402 add_loop (loop, l1_bb->loop_father);
10403 loop->safelen = INT_MAX;
10406 /* Pick the correct library function based on the precision of the
10407 induction variable type. */
10408 tree lib_fun = NULL_TREE;
10409 if (TYPE_PRECISION (type) == 32)
10410 lib_fun = cilk_for_32_fndecl;
10411 else if (TYPE_PRECISION (type) == 64)
10412 lib_fun = cilk_for_64_fndecl;
10413 else
10414 gcc_unreachable ();
10416 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10418 /* WS_ARGS contains the library function flavor to call:
10419 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10420 user-defined grain value. If the user does not define one, then zero
10421 is passed in by the parser. */
10422 vec_alloc (region->ws_args, 2);
10423 region->ws_args->quick_push (lib_fun);
10424 region->ws_args->quick_push (fd->chunk_size);
10427 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10428 loop. Given parameters:
10430 for (V = N1; V cond N2; V += STEP) BODY;
10432 where COND is "<" or ">", we generate pseudocode
10434 V = N1;
10435 goto L1;
10437 BODY;
10438 V += STEP;
10440 if (V cond N2) goto L0; else goto L2;
10443 For collapsed loops, given parameters:
10444 collapse(3)
10445 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10446 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10447 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10448 BODY;
10450 we generate pseudocode
10452 if (cond3 is <)
10453 adj = STEP3 - 1;
10454 else
10455 adj = STEP3 + 1;
10456 count3 = (adj + N32 - N31) / STEP3;
10457 if (cond2 is <)
10458 adj = STEP2 - 1;
10459 else
10460 adj = STEP2 + 1;
10461 count2 = (adj + N22 - N21) / STEP2;
10462 if (cond1 is <)
10463 adj = STEP1 - 1;
10464 else
10465 adj = STEP1 + 1;
10466 count1 = (adj + N12 - N11) / STEP1;
10467 count = count1 * count2 * count3;
10468 V = 0;
10469 V1 = N11;
10470 V2 = N21;
10471 V3 = N31;
10472 goto L1;
10474 BODY;
10475 V += 1;
10476 V3 += STEP3;
10477 V2 += (V3 cond3 N32) ? 0 : STEP2;
10478 V3 = (V3 cond3 N32) ? V3 : N31;
10479 V1 += (V2 cond2 N22) ? 0 : STEP1;
10480 V2 = (V2 cond2 N22) ? V2 : N21;
10482 if (V < count) goto L0; else goto L2;
10487 static void
10488 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10490 tree type, t;
10491 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10492 gimple_stmt_iterator gsi;
10493 gimple *stmt;
10494 gcond *cond_stmt;
10495 bool broken_loop = region->cont == NULL;
10496 edge e, ne;
10497 tree *counts = NULL;
10498 int i;
10499 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10500 OMP_CLAUSE_SAFELEN);
10501 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10502 OMP_CLAUSE__SIMDUID_);
10503 tree n1, n2;
10505 type = TREE_TYPE (fd->loop.v);
10506 entry_bb = region->entry;
10507 cont_bb = region->cont;
10508 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10509 gcc_assert (broken_loop
10510 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10511 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10512 if (!broken_loop)
10514 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10515 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10516 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10517 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10519 else
10521 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10522 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10523 l2_bb = single_succ (l1_bb);
10525 exit_bb = region->exit;
10526 l2_dom_bb = NULL;
10528 gsi = gsi_last_bb (entry_bb);
10530 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10531 /* Not needed in SSA form right now. */
10532 gcc_assert (!gimple_in_ssa_p (cfun));
10533 if (fd->collapse > 1)
10535 int first_zero_iter = -1, dummy = -1;
10536 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10538 counts = XALLOCAVEC (tree, fd->collapse);
10539 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10540 zero_iter_bb, first_zero_iter,
10541 dummy_bb, dummy, l2_dom_bb);
10543 if (l2_dom_bb == NULL)
10544 l2_dom_bb = l1_bb;
10546 n1 = fd->loop.n1;
10547 n2 = fd->loop.n2;
10548 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10550 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10551 OMP_CLAUSE__LOOPTEMP_);
10552 gcc_assert (innerc);
10553 n1 = OMP_CLAUSE_DECL (innerc);
10554 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10555 OMP_CLAUSE__LOOPTEMP_);
10556 gcc_assert (innerc);
10557 n2 = OMP_CLAUSE_DECL (innerc);
10558 expand_omp_build_assign (&gsi, fd->loop.v,
10559 fold_convert (type, n1));
10560 if (fd->collapse > 1)
10562 gsi_prev (&gsi);
10563 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10564 gsi_next (&gsi);
10567 else
10569 expand_omp_build_assign (&gsi, fd->loop.v,
10570 fold_convert (type, fd->loop.n1));
10571 if (fd->collapse > 1)
10572 for (i = 0; i < fd->collapse; i++)
10574 tree itype = TREE_TYPE (fd->loops[i].v);
10575 if (POINTER_TYPE_P (itype))
10576 itype = signed_type_for (itype);
10577 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10578 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10582 /* Remove the GIMPLE_OMP_FOR statement. */
10583 gsi_remove (&gsi, true);
10585 if (!broken_loop)
10587 /* Code to control the increment goes in the CONT_BB. */
10588 gsi = gsi_last_bb (cont_bb);
10589 stmt = gsi_stmt (gsi);
10590 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10592 if (POINTER_TYPE_P (type))
10593 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10594 else
10595 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10596 expand_omp_build_assign (&gsi, fd->loop.v, t);
10598 if (fd->collapse > 1)
10600 i = fd->collapse - 1;
10601 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10603 t = fold_convert (sizetype, fd->loops[i].step);
10604 t = fold_build_pointer_plus (fd->loops[i].v, t);
10606 else
10608 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10609 fd->loops[i].step);
10610 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10611 fd->loops[i].v, t);
10613 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10615 for (i = fd->collapse - 1; i > 0; i--)
10617 tree itype = TREE_TYPE (fd->loops[i].v);
10618 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10619 if (POINTER_TYPE_P (itype2))
10620 itype2 = signed_type_for (itype2);
10621 t = build3 (COND_EXPR, itype2,
10622 build2 (fd->loops[i].cond_code, boolean_type_node,
10623 fd->loops[i].v,
10624 fold_convert (itype, fd->loops[i].n2)),
10625 build_int_cst (itype2, 0),
10626 fold_convert (itype2, fd->loops[i - 1].step));
10627 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10628 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10629 else
10630 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10631 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10633 t = build3 (COND_EXPR, itype,
10634 build2 (fd->loops[i].cond_code, boolean_type_node,
10635 fd->loops[i].v,
10636 fold_convert (itype, fd->loops[i].n2)),
10637 fd->loops[i].v,
10638 fold_convert (itype, fd->loops[i].n1));
10639 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10643 /* Remove GIMPLE_OMP_CONTINUE. */
10644 gsi_remove (&gsi, true);
10647 /* Emit the condition in L1_BB. */
10648 gsi = gsi_start_bb (l1_bb);
10650 t = fold_convert (type, n2);
10651 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10652 false, GSI_CONTINUE_LINKING);
10653 tree v = fd->loop.v;
10654 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10655 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10656 false, GSI_CONTINUE_LINKING);
10657 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10658 cond_stmt = gimple_build_cond_empty (t);
10659 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10660 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10661 NULL, NULL)
10662 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10663 NULL, NULL))
10665 gsi = gsi_for_stmt (cond_stmt);
10666 gimple_regimplify_operands (cond_stmt, &gsi);
10669 /* Remove GIMPLE_OMP_RETURN. */
10670 gsi = gsi_last_bb (exit_bb);
10671 gsi_remove (&gsi, true);
10673 /* Connect the new blocks. */
10674 remove_edge (FALLTHRU_EDGE (entry_bb));
10676 if (!broken_loop)
10678 remove_edge (BRANCH_EDGE (entry_bb));
10679 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10681 e = BRANCH_EDGE (l1_bb);
10682 ne = FALLTHRU_EDGE (l1_bb);
10683 e->flags = EDGE_TRUE_VALUE;
10685 else
10687 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10689 ne = single_succ_edge (l1_bb);
10690 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10693 ne->flags = EDGE_FALSE_VALUE;
10694 e->probability = REG_BR_PROB_BASE * 7 / 8;
10695 ne->probability = REG_BR_PROB_BASE / 8;
10697 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10698 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10699 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10701 if (!broken_loop)
10703 struct loop *loop = alloc_loop ();
10704 loop->header = l1_bb;
10705 loop->latch = cont_bb;
10706 add_loop (loop, l1_bb->loop_father);
10707 if (safelen == NULL_TREE)
10708 loop->safelen = INT_MAX;
10709 else
10711 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10712 if (TREE_CODE (safelen) != INTEGER_CST)
10713 loop->safelen = 0;
10714 else if (!tree_fits_uhwi_p (safelen)
10715 || tree_to_uhwi (safelen) > INT_MAX)
10716 loop->safelen = INT_MAX;
10717 else
10718 loop->safelen = tree_to_uhwi (safelen);
10719 if (loop->safelen == 1)
10720 loop->safelen = 0;
10722 if (simduid)
10724 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10725 cfun->has_simduid_loops = true;
10727 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10728 the loop. */
10729 if ((flag_tree_loop_vectorize
10730 || (!global_options_set.x_flag_tree_loop_vectorize
10731 && !global_options_set.x_flag_tree_vectorize))
10732 && flag_tree_loop_optimize
10733 && loop->safelen > 1)
10735 loop->force_vectorize = true;
10736 cfun->has_force_vectorize_loops = true;
10739 else if (simduid)
10740 cfun->has_simduid_loops = true;
10743 /* Taskloop construct is represented after gimplification with
10744 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10745 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10746 which should just compute all the needed loop temporaries
10747 for GIMPLE_OMP_TASK. */
10749 static void
10750 expand_omp_taskloop_for_outer (struct omp_region *region,
10751 struct omp_for_data *fd,
10752 gimple *inner_stmt)
10754 tree type, bias = NULL_TREE;
10755 basic_block entry_bb, cont_bb, exit_bb;
10756 gimple_stmt_iterator gsi;
10757 gassign *assign_stmt;
10758 tree *counts = NULL;
10759 int i;
10761 gcc_assert (inner_stmt);
10762 gcc_assert (region->cont);
10763 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10764 && gimple_omp_task_taskloop_p (inner_stmt));
10765 type = TREE_TYPE (fd->loop.v);
10767 /* See if we need to bias by LLONG_MIN. */
10768 if (fd->iter_type == long_long_unsigned_type_node
10769 && TREE_CODE (type) == INTEGER_TYPE
10770 && !TYPE_UNSIGNED (type))
10772 tree n1, n2;
10774 if (fd->loop.cond_code == LT_EXPR)
10776 n1 = fd->loop.n1;
10777 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10779 else
10781 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10782 n2 = fd->loop.n1;
10784 if (TREE_CODE (n1) != INTEGER_CST
10785 || TREE_CODE (n2) != INTEGER_CST
10786 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10787 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10790 entry_bb = region->entry;
10791 cont_bb = region->cont;
10792 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10793 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10794 exit_bb = region->exit;
10796 gsi = gsi_last_bb (entry_bb);
10797 gimple *for_stmt = gsi_stmt (gsi);
10798 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10799 if (fd->collapse > 1)
10801 int first_zero_iter = -1, dummy = -1;
10802 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10804 counts = XALLOCAVEC (tree, fd->collapse);
10805 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10806 zero_iter_bb, first_zero_iter,
10807 dummy_bb, dummy, l2_dom_bb);
10809 if (zero_iter_bb)
10811 /* Some counts[i] vars might be uninitialized if
10812 some loop has zero iterations. But the body shouldn't
10813 be executed in that case, so just avoid uninit warnings. */
10814 for (i = first_zero_iter; i < fd->collapse; i++)
10815 if (SSA_VAR_P (counts[i]))
10816 TREE_NO_WARNING (counts[i]) = 1;
10817 gsi_prev (&gsi);
10818 edge e = split_block (entry_bb, gsi_stmt (gsi));
10819 entry_bb = e->dest;
10820 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10821 gsi = gsi_last_bb (entry_bb);
10822 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10823 get_immediate_dominator (CDI_DOMINATORS,
10824 zero_iter_bb));
10828 tree t0, t1;
10829 t1 = fd->loop.n2;
10830 t0 = fd->loop.n1;
10831 if (POINTER_TYPE_P (TREE_TYPE (t0))
10832 && TYPE_PRECISION (TREE_TYPE (t0))
10833 != TYPE_PRECISION (fd->iter_type))
10835 /* Avoid casting pointers to integer of a different size. */
10836 tree itype = signed_type_for (type);
10837 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10838 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10840 else
10842 t1 = fold_convert (fd->iter_type, t1);
10843 t0 = fold_convert (fd->iter_type, t0);
10845 if (bias)
10847 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10848 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10851 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10852 OMP_CLAUSE__LOOPTEMP_);
10853 gcc_assert (innerc);
10854 tree startvar = OMP_CLAUSE_DECL (innerc);
10855 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10856 gcc_assert (innerc);
10857 tree endvar = OMP_CLAUSE_DECL (innerc);
10858 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10860 gcc_assert (innerc);
10861 for (i = 1; i < fd->collapse; i++)
10863 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10864 OMP_CLAUSE__LOOPTEMP_);
10865 gcc_assert (innerc);
10867 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10868 OMP_CLAUSE__LOOPTEMP_);
10869 if (innerc)
10871 /* If needed (inner taskloop has lastprivate clause), propagate
10872 down the total number of iterations. */
10873 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10874 NULL_TREE, false,
10875 GSI_CONTINUE_LINKING);
10876 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10877 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10881 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10882 GSI_CONTINUE_LINKING);
10883 assign_stmt = gimple_build_assign (startvar, t0);
10884 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10886 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10887 GSI_CONTINUE_LINKING);
10888 assign_stmt = gimple_build_assign (endvar, t1);
10889 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10890 if (fd->collapse > 1)
10891 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10893 /* Remove the GIMPLE_OMP_FOR statement. */
10894 gsi = gsi_for_stmt (for_stmt);
10895 gsi_remove (&gsi, true);
10897 gsi = gsi_last_bb (cont_bb);
10898 gsi_remove (&gsi, true);
10900 gsi = gsi_last_bb (exit_bb);
10901 gsi_remove (&gsi, true);
10903 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10904 remove_edge (BRANCH_EDGE (entry_bb));
10905 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10906 remove_edge (BRANCH_EDGE (cont_bb));
10907 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10908 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10909 recompute_dominator (CDI_DOMINATORS, region->entry));
10912 /* Taskloop construct is represented after gimplification with
10913 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10914 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10915 GOMP_taskloop{,_ull} function arranges for each task to be given just
10916 a single range of iterations. */
10918 static void
10919 expand_omp_taskloop_for_inner (struct omp_region *region,
10920 struct omp_for_data *fd,
10921 gimple *inner_stmt)
10923 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10924 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10925 basic_block fin_bb;
10926 gimple_stmt_iterator gsi;
10927 edge ep;
10928 bool broken_loop = region->cont == NULL;
10929 tree *counts = NULL;
10930 tree n1, n2, step;
10932 itype = type = TREE_TYPE (fd->loop.v);
10933 if (POINTER_TYPE_P (type))
10934 itype = signed_type_for (type);
10936 /* See if we need to bias by LLONG_MIN. */
10937 if (fd->iter_type == long_long_unsigned_type_node
10938 && TREE_CODE (type) == INTEGER_TYPE
10939 && !TYPE_UNSIGNED (type))
10941 tree n1, n2;
10943 if (fd->loop.cond_code == LT_EXPR)
10945 n1 = fd->loop.n1;
10946 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10948 else
10950 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10951 n2 = fd->loop.n1;
10953 if (TREE_CODE (n1) != INTEGER_CST
10954 || TREE_CODE (n2) != INTEGER_CST
10955 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10956 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10959 entry_bb = region->entry;
10960 cont_bb = region->cont;
10961 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10962 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10963 gcc_assert (broken_loop
10964 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10965 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10966 if (!broken_loop)
10968 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10969 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10971 exit_bb = region->exit;
10973 /* Iteration space partitioning goes in ENTRY_BB. */
10974 gsi = gsi_last_bb (entry_bb);
10975 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10977 if (fd->collapse > 1)
10979 int first_zero_iter = -1, dummy = -1;
10980 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10982 counts = XALLOCAVEC (tree, fd->collapse);
10983 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10984 fin_bb, first_zero_iter,
10985 dummy_bb, dummy, l2_dom_bb);
10986 t = NULL_TREE;
10988 else
10989 t = integer_one_node;
10991 step = fd->loop.step;
10992 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10993 OMP_CLAUSE__LOOPTEMP_);
10994 gcc_assert (innerc);
10995 n1 = OMP_CLAUSE_DECL (innerc);
10996 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10997 gcc_assert (innerc);
10998 n2 = OMP_CLAUSE_DECL (innerc);
10999 if (bias)
11001 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
11002 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
11004 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
11005 true, NULL_TREE, true, GSI_SAME_STMT);
11006 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
11007 true, NULL_TREE, true, GSI_SAME_STMT);
11008 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
11009 true, NULL_TREE, true, GSI_SAME_STMT);
11011 tree startvar = fd->loop.v;
11012 tree endvar = NULL_TREE;
11014 if (gimple_omp_for_combined_p (fd->for_stmt))
11016 tree clauses = gimple_omp_for_clauses (inner_stmt);
11017 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
11018 gcc_assert (innerc);
11019 startvar = OMP_CLAUSE_DECL (innerc);
11020 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11021 OMP_CLAUSE__LOOPTEMP_);
11022 gcc_assert (innerc);
11023 endvar = OMP_CLAUSE_DECL (innerc);
11025 t = fold_convert (TREE_TYPE (startvar), n1);
11026 t = force_gimple_operand_gsi (&gsi, t,
11027 DECL_P (startvar)
11028 && TREE_ADDRESSABLE (startvar),
11029 NULL_TREE, false, GSI_CONTINUE_LINKING);
11030 gimple *assign_stmt = gimple_build_assign (startvar, t);
11031 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11033 t = fold_convert (TREE_TYPE (startvar), n2);
11034 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11035 false, GSI_CONTINUE_LINKING);
11036 if (endvar)
11038 assign_stmt = gimple_build_assign (endvar, e);
11039 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11040 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11041 assign_stmt = gimple_build_assign (fd->loop.v, e);
11042 else
11043 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11044 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11046 if (fd->collapse > 1)
11047 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11049 if (!broken_loop)
11051 /* The code controlling the sequential loop replaces the
11052 GIMPLE_OMP_CONTINUE. */
11053 gsi = gsi_last_bb (cont_bb);
11054 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11055 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11056 vmain = gimple_omp_continue_control_use (cont_stmt);
11057 vback = gimple_omp_continue_control_def (cont_stmt);
11059 if (!gimple_omp_for_combined_p (fd->for_stmt))
11061 if (POINTER_TYPE_P (type))
11062 t = fold_build_pointer_plus (vmain, step);
11063 else
11064 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11065 t = force_gimple_operand_gsi (&gsi, t,
11066 DECL_P (vback)
11067 && TREE_ADDRESSABLE (vback),
11068 NULL_TREE, true, GSI_SAME_STMT);
11069 assign_stmt = gimple_build_assign (vback, t);
11070 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11072 t = build2 (fd->loop.cond_code, boolean_type_node,
11073 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11074 ? t : vback, e);
11075 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11078 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11079 gsi_remove (&gsi, true);
11081 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11082 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11085 /* Remove the GIMPLE_OMP_FOR statement. */
11086 gsi = gsi_for_stmt (fd->for_stmt);
11087 gsi_remove (&gsi, true);
11089 /* Remove the GIMPLE_OMP_RETURN statement. */
11090 gsi = gsi_last_bb (exit_bb);
11091 gsi_remove (&gsi, true);
11093 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11094 if (!broken_loop)
11095 remove_edge (BRANCH_EDGE (entry_bb));
11096 else
11098 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11099 region->outer->cont = NULL;
11102 /* Connect all the blocks. */
11103 if (!broken_loop)
11105 ep = find_edge (cont_bb, body_bb);
11106 if (gimple_omp_for_combined_p (fd->for_stmt))
11108 remove_edge (ep);
11109 ep = NULL;
11111 else if (fd->collapse > 1)
11113 remove_edge (ep);
11114 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11116 else
11117 ep->flags = EDGE_TRUE_VALUE;
11118 find_edge (cont_bb, fin_bb)->flags
11119 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11122 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11123 recompute_dominator (CDI_DOMINATORS, body_bb));
11124 if (!broken_loop)
11125 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11126 recompute_dominator (CDI_DOMINATORS, fin_bb));
11128 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11130 struct loop *loop = alloc_loop ();
11131 loop->header = body_bb;
11132 if (collapse_bb == NULL)
11133 loop->latch = cont_bb;
11134 add_loop (loop, body_bb->loop_father);
11138 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11139 partitioned loop. The lowering here is abstracted, in that the
11140 loop parameters are passed through internal functions, which are
11141 further lowered by oacc_device_lower, once we get to the target
11142 compiler. The loop is of the form:
11144 for (V = B; V LTGT E; V += S) {BODY}
11146 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11147 (constant 0 for no chunking) and we will have a GWV partitioning
11148 mask, specifying dimensions over which the loop is to be
11149 partitioned (see note below). We generate code that looks like:
11151 <entry_bb> [incoming FALL->body, BRANCH->exit]
11152 typedef signedintify (typeof (V)) T; // underlying signed integral type
11153 T range = E - B;
11154 T chunk_no = 0;
11155 T DIR = LTGT == '<' ? +1 : -1;
11156 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11157 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11159 <head_bb> [created by splitting end of entry_bb]
11160 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11161 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11162 if (!(offset LTGT bound)) goto bottom_bb;
11164 <body_bb> [incoming]
11165 V = B + offset;
11166 {BODY}
11168 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11169 offset += step;
11170 if (offset LTGT bound) goto body_bb; [*]
11172 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11173 chunk_no++;
11174 if (chunk < chunk_max) goto head_bb;
11176 <exit_bb> [incoming]
11177 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11179 [*] Needed if V live at end of loop
11181 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11182 transition, and will be specified by a more general mechanism shortly.
11185 static void
11186 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11188 tree v = fd->loop.v;
11189 enum tree_code cond_code = fd->loop.cond_code;
11190 enum tree_code plus_code = PLUS_EXPR;
11192 tree chunk_size = integer_minus_one_node;
11193 tree gwv = integer_zero_node;
11194 tree iter_type = TREE_TYPE (v);
11195 tree diff_type = iter_type;
11196 tree plus_type = iter_type;
11197 struct oacc_collapse *counts = NULL;
11199 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11200 == GF_OMP_FOR_KIND_OACC_LOOP);
11201 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11202 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11204 if (POINTER_TYPE_P (iter_type))
11206 plus_code = POINTER_PLUS_EXPR;
11207 plus_type = sizetype;
11209 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11210 diff_type = signed_type_for (diff_type);
11212 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11213 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11214 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11215 basic_block bottom_bb = NULL;
11217 /* entry_bb has two sucessors; the branch edge is to the exit
11218 block, fallthrough edge to body. */
11219 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11220 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11222 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11223 body_bb, or to a block whose only successor is the body_bb. Its
11224 fallthrough successor is the final block (same as the branch
11225 successor of the entry_bb). */
11226 if (cont_bb)
11228 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11229 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11231 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11232 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11234 else
11235 gcc_assert (!gimple_in_ssa_p (cfun));
11237 /* The exit block only has entry_bb and cont_bb as predecessors. */
11238 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11240 tree chunk_no;
11241 tree chunk_max = NULL_TREE;
11242 tree bound, offset;
11243 tree step = create_tmp_var (diff_type, ".step");
11244 bool up = cond_code == LT_EXPR;
11245 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11246 bool chunking = !gimple_in_ssa_p (cfun);;
11247 bool negating;
11249 /* SSA instances. */
11250 tree offset_incr = NULL_TREE;
11251 tree offset_init = NULL_TREE;
11253 gimple_stmt_iterator gsi;
11254 gassign *ass;
11255 gcall *call;
11256 gimple *stmt;
11257 tree expr;
11258 location_t loc;
11259 edge split, be, fte;
11261 /* Split the end of entry_bb to create head_bb. */
11262 split = split_block (entry_bb, last_stmt (entry_bb));
11263 basic_block head_bb = split->dest;
11264 entry_bb = split->src;
11266 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11267 gsi = gsi_last_bb (entry_bb);
11268 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11269 loc = gimple_location (for_stmt);
11271 if (gimple_in_ssa_p (cfun))
11273 offset_init = gimple_omp_for_index (for_stmt, 0);
11274 gcc_assert (integer_zerop (fd->loop.n1));
11275 /* The SSA parallelizer does gang parallelism. */
11276 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11279 if (fd->collapse > 1)
11281 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11282 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11283 TREE_TYPE (fd->loop.n2));
11285 if (SSA_VAR_P (fd->loop.n2))
11287 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11288 true, GSI_SAME_STMT);
11289 ass = gimple_build_assign (fd->loop.n2, total);
11290 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11295 tree b = fd->loop.n1;
11296 tree e = fd->loop.n2;
11297 tree s = fd->loop.step;
11299 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11300 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11302 /* Convert the step, avoiding possible unsigned->signed overflow. */
11303 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11304 if (negating)
11305 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11306 s = fold_convert (diff_type, s);
11307 if (negating)
11308 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11309 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11311 if (!chunking)
11312 chunk_size = integer_zero_node;
11313 expr = fold_convert (diff_type, chunk_size);
11314 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11315 NULL_TREE, true, GSI_SAME_STMT);
11316 /* Determine the range, avoiding possible unsigned->signed overflow. */
11317 negating = !up && TYPE_UNSIGNED (iter_type);
11318 expr = fold_build2 (MINUS_EXPR, plus_type,
11319 fold_convert (plus_type, negating ? b : e),
11320 fold_convert (plus_type, negating ? e : b));
11321 expr = fold_convert (diff_type, expr);
11322 if (negating)
11323 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11324 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11325 NULL_TREE, true, GSI_SAME_STMT);
11327 chunk_no = build_int_cst (diff_type, 0);
11328 if (chunking)
11330 gcc_assert (!gimple_in_ssa_p (cfun));
11332 expr = chunk_no;
11333 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11334 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11336 ass = gimple_build_assign (chunk_no, expr);
11337 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11339 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11340 build_int_cst (integer_type_node,
11341 IFN_GOACC_LOOP_CHUNKS),
11342 dir, range, s, chunk_size, gwv);
11343 gimple_call_set_lhs (call, chunk_max);
11344 gimple_set_location (call, loc);
11345 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11347 else
11348 chunk_size = chunk_no;
11350 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11351 build_int_cst (integer_type_node,
11352 IFN_GOACC_LOOP_STEP),
11353 dir, range, s, chunk_size, gwv);
11354 gimple_call_set_lhs (call, step);
11355 gimple_set_location (call, loc);
11356 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11358 /* Remove the GIMPLE_OMP_FOR. */
11359 gsi_remove (&gsi, true);
11361 /* Fixup edges from head_bb */
11362 be = BRANCH_EDGE (head_bb);
11363 fte = FALLTHRU_EDGE (head_bb);
11364 be->flags |= EDGE_FALSE_VALUE;
11365 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11367 basic_block body_bb = fte->dest;
11369 if (gimple_in_ssa_p (cfun))
11371 gsi = gsi_last_bb (cont_bb);
11372 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11374 offset = gimple_omp_continue_control_use (cont_stmt);
11375 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11377 else
11379 offset = create_tmp_var (diff_type, ".offset");
11380 offset_init = offset_incr = offset;
11382 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11384 /* Loop offset & bound go into head_bb. */
11385 gsi = gsi_start_bb (head_bb);
11387 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11388 build_int_cst (integer_type_node,
11389 IFN_GOACC_LOOP_OFFSET),
11390 dir, range, s,
11391 chunk_size, gwv, chunk_no);
11392 gimple_call_set_lhs (call, offset_init);
11393 gimple_set_location (call, loc);
11394 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11396 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11397 build_int_cst (integer_type_node,
11398 IFN_GOACC_LOOP_BOUND),
11399 dir, range, s,
11400 chunk_size, gwv, offset_init);
11401 gimple_call_set_lhs (call, bound);
11402 gimple_set_location (call, loc);
11403 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11405 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11406 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11407 GSI_CONTINUE_LINKING);
11409 /* V assignment goes into body_bb. */
11410 if (!gimple_in_ssa_p (cfun))
11412 gsi = gsi_start_bb (body_bb);
11414 expr = build2 (plus_code, iter_type, b,
11415 fold_convert (plus_type, offset));
11416 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11417 true, GSI_SAME_STMT);
11418 ass = gimple_build_assign (v, expr);
11419 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11420 if (fd->collapse > 1)
11421 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11424 /* Loop increment goes into cont_bb. If this is not a loop, we
11425 will have spawned threads as if it was, and each one will
11426 execute one iteration. The specification is not explicit about
11427 whether such constructs are ill-formed or not, and they can
11428 occur, especially when noreturn routines are involved. */
11429 if (cont_bb)
11431 gsi = gsi_last_bb (cont_bb);
11432 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11433 loc = gimple_location (cont_stmt);
11435 /* Increment offset. */
11436 if (gimple_in_ssa_p (cfun))
11437 expr= build2 (plus_code, iter_type, offset,
11438 fold_convert (plus_type, step));
11439 else
11440 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11441 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11442 true, GSI_SAME_STMT);
11443 ass = gimple_build_assign (offset_incr, expr);
11444 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11445 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11446 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11448 /* Remove the GIMPLE_OMP_CONTINUE. */
11449 gsi_remove (&gsi, true);
11451 /* Fixup edges from cont_bb */
11452 be = BRANCH_EDGE (cont_bb);
11453 fte = FALLTHRU_EDGE (cont_bb);
11454 be->flags |= EDGE_TRUE_VALUE;
11455 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11457 if (chunking)
11459 /* Split the beginning of exit_bb to make bottom_bb. We
11460 need to insert a nop at the start, because splitting is
11461 after a stmt, not before. */
11462 gsi = gsi_start_bb (exit_bb);
11463 stmt = gimple_build_nop ();
11464 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11465 split = split_block (exit_bb, stmt);
11466 bottom_bb = split->src;
11467 exit_bb = split->dest;
11468 gsi = gsi_last_bb (bottom_bb);
11470 /* Chunk increment and test goes into bottom_bb. */
11471 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11472 build_int_cst (diff_type, 1));
11473 ass = gimple_build_assign (chunk_no, expr);
11474 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11476 /* Chunk test at end of bottom_bb. */
11477 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11478 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11479 GSI_CONTINUE_LINKING);
11481 /* Fixup edges from bottom_bb. */
11482 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11483 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11487 gsi = gsi_last_bb (exit_bb);
11488 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11489 loc = gimple_location (gsi_stmt (gsi));
11491 if (!gimple_in_ssa_p (cfun))
11493 /* Insert the final value of V, in case it is live. This is the
11494 value for the only thread that survives past the join. */
11495 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11496 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11497 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11498 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11499 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11500 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11501 true, GSI_SAME_STMT);
11502 ass = gimple_build_assign (v, expr);
11503 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11506 /* Remove the OMP_RETURN. */
11507 gsi_remove (&gsi, true);
11509 if (cont_bb)
11511 /* We now have one or two nested loops. Update the loop
11512 structures. */
11513 struct loop *parent = entry_bb->loop_father;
11514 struct loop *body = body_bb->loop_father;
11516 if (chunking)
11518 struct loop *chunk_loop = alloc_loop ();
11519 chunk_loop->header = head_bb;
11520 chunk_loop->latch = bottom_bb;
11521 add_loop (chunk_loop, parent);
11522 parent = chunk_loop;
11524 else if (parent != body)
11526 gcc_assert (body->header == body_bb);
11527 gcc_assert (body->latch == cont_bb
11528 || single_pred (body->latch) == cont_bb);
11529 parent = NULL;
11532 if (parent)
11534 struct loop *body_loop = alloc_loop ();
11535 body_loop->header = body_bb;
11536 body_loop->latch = cont_bb;
11537 add_loop (body_loop, parent);
11542 /* Expand the OMP loop defined by REGION. */
11544 static void
11545 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11547 struct omp_for_data fd;
11548 struct omp_for_data_loop *loops;
11550 loops
11551 = (struct omp_for_data_loop *)
11552 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11553 * sizeof (struct omp_for_data_loop));
11554 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11555 &fd, loops);
11556 region->sched_kind = fd.sched_kind;
11557 region->sched_modifiers = fd.sched_modifiers;
11559 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11560 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11561 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11562 if (region->cont)
11564 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11565 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11566 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11568 else
11569 /* If there isn't a continue then this is a degerate case where
11570 the introduction of abnormal edges during lowering will prevent
11571 original loops from being detected. Fix that up. */
11572 loops_state_set (LOOPS_NEED_FIXUP);
11574 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11575 expand_omp_simd (region, &fd);
11576 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11577 expand_cilk_for (region, &fd);
11578 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11580 gcc_assert (!inner_stmt);
11581 expand_oacc_for (region, &fd);
11583 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11585 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11586 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11587 else
11588 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11590 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11591 && !fd.have_ordered)
11593 if (fd.chunk_size == NULL)
11594 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11595 else
11596 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11598 else
11600 int fn_index, start_ix, next_ix;
11602 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11603 == GF_OMP_FOR_KIND_FOR);
11604 if (fd.chunk_size == NULL
11605 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11606 fd.chunk_size = integer_zero_node;
11607 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11608 switch (fd.sched_kind)
11610 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11611 fn_index = 3;
11612 break;
11613 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11614 case OMP_CLAUSE_SCHEDULE_GUIDED:
11615 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11616 && !fd.ordered
11617 && !fd.have_ordered)
11619 fn_index = 3 + fd.sched_kind;
11620 break;
11622 /* FALLTHRU */
11623 default:
11624 fn_index = fd.sched_kind;
11625 break;
11627 if (!fd.ordered)
11628 fn_index += fd.have_ordered * 6;
11629 if (fd.ordered)
11630 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11631 else
11632 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11633 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11634 if (fd.iter_type == long_long_unsigned_type_node)
11636 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11637 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11638 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11639 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11641 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11642 (enum built_in_function) next_ix, inner_stmt);
11645 if (gimple_in_ssa_p (cfun))
11646 update_ssa (TODO_update_ssa_only_virtuals);
11650 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11652 v = GOMP_sections_start (n);
11654 switch (v)
11656 case 0:
11657 goto L2;
11658 case 1:
11659 section 1;
11660 goto L1;
11661 case 2:
11663 case n:
11665 default:
11666 abort ();
11669 v = GOMP_sections_next ();
11670 goto L0;
11672 reduction;
11674 If this is a combined parallel sections, replace the call to
11675 GOMP_sections_start with call to GOMP_sections_next. */
11677 static void
11678 expand_omp_sections (struct omp_region *region)
11680 tree t, u, vin = NULL, vmain, vnext, l2;
11681 unsigned len;
11682 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11683 gimple_stmt_iterator si, switch_si;
11684 gomp_sections *sections_stmt;
11685 gimple *stmt;
11686 gomp_continue *cont;
11687 edge_iterator ei;
11688 edge e;
11689 struct omp_region *inner;
11690 unsigned i, casei;
11691 bool exit_reachable = region->cont != NULL;
11693 gcc_assert (region->exit != NULL);
11694 entry_bb = region->entry;
11695 l0_bb = single_succ (entry_bb);
11696 l1_bb = region->cont;
11697 l2_bb = region->exit;
11698 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11699 l2 = gimple_block_label (l2_bb);
11700 else
11702 /* This can happen if there are reductions. */
11703 len = EDGE_COUNT (l0_bb->succs);
11704 gcc_assert (len > 0);
11705 e = EDGE_SUCC (l0_bb, len - 1);
11706 si = gsi_last_bb (e->dest);
11707 l2 = NULL_TREE;
11708 if (gsi_end_p (si)
11709 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11710 l2 = gimple_block_label (e->dest);
11711 else
11712 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11714 si = gsi_last_bb (e->dest);
11715 if (gsi_end_p (si)
11716 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11718 l2 = gimple_block_label (e->dest);
11719 break;
11723 if (exit_reachable)
11724 default_bb = create_empty_bb (l1_bb->prev_bb);
11725 else
11726 default_bb = create_empty_bb (l0_bb);
11728 /* We will build a switch() with enough cases for all the
11729 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11730 and a default case to abort if something goes wrong. */
11731 len = EDGE_COUNT (l0_bb->succs);
11733 /* Use vec::quick_push on label_vec throughout, since we know the size
11734 in advance. */
11735 auto_vec<tree> label_vec (len);
11737 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11738 GIMPLE_OMP_SECTIONS statement. */
11739 si = gsi_last_bb (entry_bb);
11740 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11741 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11742 vin = gimple_omp_sections_control (sections_stmt);
11743 if (!is_combined_parallel (region))
11745 /* If we are not inside a combined parallel+sections region,
11746 call GOMP_sections_start. */
11747 t = build_int_cst (unsigned_type_node, len - 1);
11748 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11749 stmt = gimple_build_call (u, 1, t);
11751 else
11753 /* Otherwise, call GOMP_sections_next. */
11754 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11755 stmt = gimple_build_call (u, 0);
11757 gimple_call_set_lhs (stmt, vin);
11758 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11759 gsi_remove (&si, true);
11761 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11762 L0_BB. */
11763 switch_si = gsi_last_bb (l0_bb);
11764 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11765 if (exit_reachable)
11767 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11768 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11769 vmain = gimple_omp_continue_control_use (cont);
11770 vnext = gimple_omp_continue_control_def (cont);
11772 else
11774 vmain = vin;
11775 vnext = NULL_TREE;
11778 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11779 label_vec.quick_push (t);
11780 i = 1;
11782 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11783 for (inner = region->inner, casei = 1;
11784 inner;
11785 inner = inner->next, i++, casei++)
11787 basic_block s_entry_bb, s_exit_bb;
11789 /* Skip optional reduction region. */
11790 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11792 --i;
11793 --casei;
11794 continue;
11797 s_entry_bb = inner->entry;
11798 s_exit_bb = inner->exit;
11800 t = gimple_block_label (s_entry_bb);
11801 u = build_int_cst (unsigned_type_node, casei);
11802 u = build_case_label (u, NULL, t);
11803 label_vec.quick_push (u);
11805 si = gsi_last_bb (s_entry_bb);
11806 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11807 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11808 gsi_remove (&si, true);
11809 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11811 if (s_exit_bb == NULL)
11812 continue;
11814 si = gsi_last_bb (s_exit_bb);
11815 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11816 gsi_remove (&si, true);
11818 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11821 /* Error handling code goes in DEFAULT_BB. */
11822 t = gimple_block_label (default_bb);
11823 u = build_case_label (NULL, NULL, t);
11824 make_edge (l0_bb, default_bb, 0);
11825 add_bb_to_loop (default_bb, current_loops->tree_root);
11827 stmt = gimple_build_switch (vmain, u, label_vec);
11828 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11829 gsi_remove (&switch_si, true);
11831 si = gsi_start_bb (default_bb);
11832 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11833 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11835 if (exit_reachable)
11837 tree bfn_decl;
11839 /* Code to get the next section goes in L1_BB. */
11840 si = gsi_last_bb (l1_bb);
11841 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11843 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11844 stmt = gimple_build_call (bfn_decl, 0);
11845 gimple_call_set_lhs (stmt, vnext);
11846 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11847 gsi_remove (&si, true);
11849 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11852 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11853 si = gsi_last_bb (l2_bb);
11854 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11855 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11856 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11857 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11858 else
11859 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11860 stmt = gimple_build_call (t, 0);
11861 if (gimple_omp_return_lhs (gsi_stmt (si)))
11862 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11863 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11864 gsi_remove (&si, true);
11866 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11870 /* Expand code for an OpenMP single directive. We've already expanded
11871 much of the code, here we simply place the GOMP_barrier call. */
11873 static void
11874 expand_omp_single (struct omp_region *region)
11876 basic_block entry_bb, exit_bb;
11877 gimple_stmt_iterator si;
11879 entry_bb = region->entry;
11880 exit_bb = region->exit;
11882 si = gsi_last_bb (entry_bb);
11883 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11884 gsi_remove (&si, true);
11885 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11887 si = gsi_last_bb (exit_bb);
11888 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11890 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11891 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11893 gsi_remove (&si, true);
11894 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11898 /* Generic expansion for OpenMP synchronization directives: master,
11899 ordered and critical. All we need to do here is remove the entry
11900 and exit markers for REGION. */
11902 static void
11903 expand_omp_synch (struct omp_region *region)
11905 basic_block entry_bb, exit_bb;
11906 gimple_stmt_iterator si;
11908 entry_bb = region->entry;
11909 exit_bb = region->exit;
11911 si = gsi_last_bb (entry_bb);
11912 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11913 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11914 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11915 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11916 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11917 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11918 gsi_remove (&si, true);
11919 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11921 if (exit_bb)
11923 si = gsi_last_bb (exit_bb);
11924 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11925 gsi_remove (&si, true);
11926 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11930 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11931 operation as a normal volatile load. */
11933 static bool
11934 expand_omp_atomic_load (basic_block load_bb, tree addr,
11935 tree loaded_val, int index)
11937 enum built_in_function tmpbase;
11938 gimple_stmt_iterator gsi;
11939 basic_block store_bb;
11940 location_t loc;
11941 gimple *stmt;
11942 tree decl, call, type, itype;
11944 gsi = gsi_last_bb (load_bb);
11945 stmt = gsi_stmt (gsi);
11946 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11947 loc = gimple_location (stmt);
11949 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11950 is smaller than word size, then expand_atomic_load assumes that the load
11951 is atomic. We could avoid the builtin entirely in this case. */
11953 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11954 decl = builtin_decl_explicit (tmpbase);
11955 if (decl == NULL_TREE)
11956 return false;
11958 type = TREE_TYPE (loaded_val);
11959 itype = TREE_TYPE (TREE_TYPE (decl));
11961 call = build_call_expr_loc (loc, decl, 2, addr,
11962 build_int_cst (NULL,
11963 gimple_omp_atomic_seq_cst_p (stmt)
11964 ? MEMMODEL_SEQ_CST
11965 : MEMMODEL_RELAXED));
11966 if (!useless_type_conversion_p (type, itype))
11967 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11968 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11970 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11971 gsi_remove (&gsi, true);
11973 store_bb = single_succ (load_bb);
11974 gsi = gsi_last_bb (store_bb);
11975 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11976 gsi_remove (&gsi, true);
11978 if (gimple_in_ssa_p (cfun))
11979 update_ssa (TODO_update_ssa_no_phi);
11981 return true;
11984 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11985 operation as a normal volatile store. */
11987 static bool
11988 expand_omp_atomic_store (basic_block load_bb, tree addr,
11989 tree loaded_val, tree stored_val, int index)
11991 enum built_in_function tmpbase;
11992 gimple_stmt_iterator gsi;
11993 basic_block store_bb = single_succ (load_bb);
11994 location_t loc;
11995 gimple *stmt;
11996 tree decl, call, type, itype;
11997 machine_mode imode;
11998 bool exchange;
12000 gsi = gsi_last_bb (load_bb);
12001 stmt = gsi_stmt (gsi);
12002 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
12004 /* If the load value is needed, then this isn't a store but an exchange. */
12005 exchange = gimple_omp_atomic_need_value_p (stmt);
12007 gsi = gsi_last_bb (store_bb);
12008 stmt = gsi_stmt (gsi);
12009 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
12010 loc = gimple_location (stmt);
12012 /* ??? If the target does not implement atomic_store_optab[mode], and mode
12013 is smaller than word size, then expand_atomic_store assumes that the store
12014 is atomic. We could avoid the builtin entirely in this case. */
12016 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
12017 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
12018 decl = builtin_decl_explicit (tmpbase);
12019 if (decl == NULL_TREE)
12020 return false;
12022 type = TREE_TYPE (stored_val);
12024 /* Dig out the type of the function's second argument. */
12025 itype = TREE_TYPE (decl);
12026 itype = TYPE_ARG_TYPES (itype);
12027 itype = TREE_CHAIN (itype);
12028 itype = TREE_VALUE (itype);
12029 imode = TYPE_MODE (itype);
12031 if (exchange && !can_atomic_exchange_p (imode, true))
12032 return false;
12034 if (!useless_type_conversion_p (itype, type))
12035 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12036 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12037 build_int_cst (NULL,
12038 gimple_omp_atomic_seq_cst_p (stmt)
12039 ? MEMMODEL_SEQ_CST
12040 : MEMMODEL_RELAXED));
12041 if (exchange)
12043 if (!useless_type_conversion_p (type, itype))
12044 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12045 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12048 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12049 gsi_remove (&gsi, true);
12051 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12052 gsi = gsi_last_bb (load_bb);
12053 gsi_remove (&gsi, true);
12055 if (gimple_in_ssa_p (cfun))
12056 update_ssa (TODO_update_ssa_no_phi);
12058 return true;
12061 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12062 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12063 size of the data type, and thus usable to find the index of the builtin
12064 decl. Returns false if the expression is not of the proper form. */
12066 static bool
12067 expand_omp_atomic_fetch_op (basic_block load_bb,
12068 tree addr, tree loaded_val,
12069 tree stored_val, int index)
12071 enum built_in_function oldbase, newbase, tmpbase;
12072 tree decl, itype, call;
12073 tree lhs, rhs;
12074 basic_block store_bb = single_succ (load_bb);
12075 gimple_stmt_iterator gsi;
12076 gimple *stmt;
12077 location_t loc;
12078 enum tree_code code;
12079 bool need_old, need_new;
12080 machine_mode imode;
12081 bool seq_cst;
12083 /* We expect to find the following sequences:
12085 load_bb:
12086 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12088 store_bb:
12089 val = tmp OP something; (or: something OP tmp)
12090 GIMPLE_OMP_STORE (val)
12092 ???FIXME: Allow a more flexible sequence.
12093 Perhaps use data flow to pick the statements.
12097 gsi = gsi_after_labels (store_bb);
12098 stmt = gsi_stmt (gsi);
12099 loc = gimple_location (stmt);
12100 if (!is_gimple_assign (stmt))
12101 return false;
12102 gsi_next (&gsi);
12103 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12104 return false;
12105 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12106 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12107 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12108 gcc_checking_assert (!need_old || !need_new);
12110 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12111 return false;
12113 /* Check for one of the supported fetch-op operations. */
12114 code = gimple_assign_rhs_code (stmt);
12115 switch (code)
12117 case PLUS_EXPR:
12118 case POINTER_PLUS_EXPR:
12119 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12120 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12121 break;
12122 case MINUS_EXPR:
12123 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12124 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12125 break;
12126 case BIT_AND_EXPR:
12127 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12128 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12129 break;
12130 case BIT_IOR_EXPR:
12131 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12132 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12133 break;
12134 case BIT_XOR_EXPR:
12135 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12136 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12137 break;
12138 default:
12139 return false;
12142 /* Make sure the expression is of the proper form. */
12143 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12144 rhs = gimple_assign_rhs2 (stmt);
12145 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12146 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12147 rhs = gimple_assign_rhs1 (stmt);
12148 else
12149 return false;
12151 tmpbase = ((enum built_in_function)
12152 ((need_new ? newbase : oldbase) + index + 1));
12153 decl = builtin_decl_explicit (tmpbase);
12154 if (decl == NULL_TREE)
12155 return false;
12156 itype = TREE_TYPE (TREE_TYPE (decl));
12157 imode = TYPE_MODE (itype);
12159 /* We could test all of the various optabs involved, but the fact of the
12160 matter is that (with the exception of i486 vs i586 and xadd) all targets
12161 that support any atomic operaton optab also implements compare-and-swap.
12162 Let optabs.c take care of expanding any compare-and-swap loop. */
12163 if (!can_compare_and_swap_p (imode, true))
12164 return false;
12166 gsi = gsi_last_bb (load_bb);
12167 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12169 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12170 It only requires that the operation happen atomically. Thus we can
12171 use the RELAXED memory model. */
12172 call = build_call_expr_loc (loc, decl, 3, addr,
12173 fold_convert_loc (loc, itype, rhs),
12174 build_int_cst (NULL,
12175 seq_cst ? MEMMODEL_SEQ_CST
12176 : MEMMODEL_RELAXED));
12178 if (need_old || need_new)
12180 lhs = need_old ? loaded_val : stored_val;
12181 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12182 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12184 else
12185 call = fold_convert_loc (loc, void_type_node, call);
12186 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12187 gsi_remove (&gsi, true);
12189 gsi = gsi_last_bb (store_bb);
12190 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12191 gsi_remove (&gsi, true);
12192 gsi = gsi_last_bb (store_bb);
12193 stmt = gsi_stmt (gsi);
12194 gsi_remove (&gsi, true);
12196 if (gimple_in_ssa_p (cfun))
12198 release_defs (stmt);
12199 update_ssa (TODO_update_ssa_no_phi);
12202 return true;
12205 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12207 oldval = *addr;
12208 repeat:
12209 newval = rhs; // with oldval replacing *addr in rhs
12210 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12211 if (oldval != newval)
12212 goto repeat;
12214 INDEX is log2 of the size of the data type, and thus usable to find the
12215 index of the builtin decl. */
12217 static bool
12218 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12219 tree addr, tree loaded_val, tree stored_val,
12220 int index)
12222 tree loadedi, storedi, initial, new_storedi, old_vali;
12223 tree type, itype, cmpxchg, iaddr;
12224 gimple_stmt_iterator si;
12225 basic_block loop_header = single_succ (load_bb);
12226 gimple *phi, *stmt;
12227 edge e;
12228 enum built_in_function fncode;
12230 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12231 order to use the RELAXED memory model effectively. */
12232 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12233 + index + 1);
12234 cmpxchg = builtin_decl_explicit (fncode);
12235 if (cmpxchg == NULL_TREE)
12236 return false;
12237 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12238 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12240 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12241 return false;
12243 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12244 si = gsi_last_bb (load_bb);
12245 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12247 /* For floating-point values, we'll need to view-convert them to integers
12248 so that we can perform the atomic compare and swap. Simplify the
12249 following code by always setting up the "i"ntegral variables. */
12250 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12252 tree iaddr_val;
12254 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12255 true));
12256 iaddr_val
12257 = force_gimple_operand_gsi (&si,
12258 fold_convert (TREE_TYPE (iaddr), addr),
12259 false, NULL_TREE, true, GSI_SAME_STMT);
12260 stmt = gimple_build_assign (iaddr, iaddr_val);
12261 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12262 loadedi = create_tmp_var (itype);
12263 if (gimple_in_ssa_p (cfun))
12264 loadedi = make_ssa_name (loadedi);
12266 else
12268 iaddr = addr;
12269 loadedi = loaded_val;
12272 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12273 tree loaddecl = builtin_decl_explicit (fncode);
12274 if (loaddecl)
12275 initial
12276 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12277 build_call_expr (loaddecl, 2, iaddr,
12278 build_int_cst (NULL_TREE,
12279 MEMMODEL_RELAXED)));
12280 else
12281 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12282 build_int_cst (TREE_TYPE (iaddr), 0));
12284 initial
12285 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12286 GSI_SAME_STMT);
12288 /* Move the value to the LOADEDI temporary. */
12289 if (gimple_in_ssa_p (cfun))
12291 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12292 phi = create_phi_node (loadedi, loop_header);
12293 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12294 initial);
12296 else
12297 gsi_insert_before (&si,
12298 gimple_build_assign (loadedi, initial),
12299 GSI_SAME_STMT);
12300 if (loadedi != loaded_val)
12302 gimple_stmt_iterator gsi2;
12303 tree x;
12305 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12306 gsi2 = gsi_start_bb (loop_header);
12307 if (gimple_in_ssa_p (cfun))
12309 gassign *stmt;
12310 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12311 true, GSI_SAME_STMT);
12312 stmt = gimple_build_assign (loaded_val, x);
12313 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12315 else
12317 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12318 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12319 true, GSI_SAME_STMT);
12322 gsi_remove (&si, true);
12324 si = gsi_last_bb (store_bb);
12325 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12327 if (iaddr == addr)
12328 storedi = stored_val;
12329 else
12330 storedi =
12331 force_gimple_operand_gsi (&si,
12332 build1 (VIEW_CONVERT_EXPR, itype,
12333 stored_val), true, NULL_TREE, true,
12334 GSI_SAME_STMT);
12336 /* Build the compare&swap statement. */
12337 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12338 new_storedi = force_gimple_operand_gsi (&si,
12339 fold_convert (TREE_TYPE (loadedi),
12340 new_storedi),
12341 true, NULL_TREE,
12342 true, GSI_SAME_STMT);
12344 if (gimple_in_ssa_p (cfun))
12345 old_vali = loadedi;
12346 else
12348 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12349 stmt = gimple_build_assign (old_vali, loadedi);
12350 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12352 stmt = gimple_build_assign (loadedi, new_storedi);
12353 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12356 /* Note that we always perform the comparison as an integer, even for
12357 floating point. This allows the atomic operation to properly
12358 succeed even with NaNs and -0.0. */
12359 stmt = gimple_build_cond_empty
12360 (build2 (NE_EXPR, boolean_type_node,
12361 new_storedi, old_vali));
12362 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12364 /* Update cfg. */
12365 e = single_succ_edge (store_bb);
12366 e->flags &= ~EDGE_FALLTHRU;
12367 e->flags |= EDGE_FALSE_VALUE;
12369 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12371 /* Copy the new value to loadedi (we already did that before the condition
12372 if we are not in SSA). */
12373 if (gimple_in_ssa_p (cfun))
12375 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12376 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12379 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12380 gsi_remove (&si, true);
12382 struct loop *loop = alloc_loop ();
12383 loop->header = loop_header;
12384 loop->latch = store_bb;
12385 add_loop (loop, loop_header->loop_father);
12387 if (gimple_in_ssa_p (cfun))
12388 update_ssa (TODO_update_ssa_no_phi);
12390 return true;
12393 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12395 GOMP_atomic_start ();
12396 *addr = rhs;
12397 GOMP_atomic_end ();
12399 The result is not globally atomic, but works so long as all parallel
12400 references are within #pragma omp atomic directives. According to
12401 responses received from omp@openmp.org, appears to be within spec.
12402 Which makes sense, since that's how several other compilers handle
12403 this situation as well.
12404 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12405 expanding. STORED_VAL is the operand of the matching
12406 GIMPLE_OMP_ATOMIC_STORE.
12408 We replace
12409 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12410 loaded_val = *addr;
12412 and replace
12413 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12414 *addr = stored_val;
12417 static bool
12418 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12419 tree addr, tree loaded_val, tree stored_val)
12421 gimple_stmt_iterator si;
12422 gassign *stmt;
12423 tree t;
12425 si = gsi_last_bb (load_bb);
12426 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12428 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12429 t = build_call_expr (t, 0);
12430 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12432 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12433 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12434 gsi_remove (&si, true);
12436 si = gsi_last_bb (store_bb);
12437 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12439 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12440 stored_val);
12441 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12443 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12444 t = build_call_expr (t, 0);
12445 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12446 gsi_remove (&si, true);
12448 if (gimple_in_ssa_p (cfun))
12449 update_ssa (TODO_update_ssa_no_phi);
12450 return true;
12453 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12454 using expand_omp_atomic_fetch_op. If it failed, we try to
12455 call expand_omp_atomic_pipeline, and if it fails too, the
12456 ultimate fallback is wrapping the operation in a mutex
12457 (expand_omp_atomic_mutex). REGION is the atomic region built
12458 by build_omp_regions_1(). */
12460 static void
12461 expand_omp_atomic (struct omp_region *region)
12463 basic_block load_bb = region->entry, store_bb = region->exit;
12464 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12465 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12466 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12467 tree addr = gimple_omp_atomic_load_rhs (load);
12468 tree stored_val = gimple_omp_atomic_store_val (store);
12469 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12470 HOST_WIDE_INT index;
12472 /* Make sure the type is one of the supported sizes. */
12473 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12474 index = exact_log2 (index);
12475 if (index >= 0 && index <= 4)
12477 unsigned int align = TYPE_ALIGN_UNIT (type);
12479 /* __sync builtins require strict data alignment. */
12480 if (exact_log2 (align) >= index)
12482 /* Atomic load. */
12483 if (loaded_val == stored_val
12484 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12485 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12486 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12487 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12488 return;
12490 /* Atomic store. */
12491 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12492 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12493 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12494 && store_bb == single_succ (load_bb)
12495 && first_stmt (store_bb) == store
12496 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12497 stored_val, index))
12498 return;
12500 /* When possible, use specialized atomic update functions. */
12501 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12502 && store_bb == single_succ (load_bb)
12503 && expand_omp_atomic_fetch_op (load_bb, addr,
12504 loaded_val, stored_val, index))
12505 return;
12507 /* If we don't have specialized __sync builtins, try and implement
12508 as a compare and swap loop. */
12509 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12510 loaded_val, stored_val, index))
12511 return;
12515 /* The ultimate fallback is wrapping the operation in a mutex. */
12516 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12520 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12521 macro on gomp-constants.h. We do not check for overflow. */
12523 static tree
12524 oacc_launch_pack (unsigned code, tree device, unsigned op)
12526 tree res;
12528 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12529 if (device)
12531 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12532 device, build_int_cst (unsigned_type_node,
12533 GOMP_LAUNCH_DEVICE_SHIFT));
12534 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12536 return res;
12539 /* Look for compute grid dimension clauses and convert to an attribute
12540 attached to FN. This permits the target-side code to (a) massage
12541 the dimensions, (b) emit that data and (c) optimize. Non-constant
12542 dimensions are pushed onto ARGS.
12544 The attribute value is a TREE_LIST. A set of dimensions is
12545 represented as a list of INTEGER_CST. Those that are runtime
12546 exprs are represented as an INTEGER_CST of zero.
12548 TOOO. Normally the attribute will just contain a single such list. If
12549 however it contains a list of lists, this will represent the use of
12550 device_type. Each member of the outer list is an assoc list of
12551 dimensions, keyed by the device type. The first entry will be the
12552 default. Well, that's the plan. */
12554 #define OACC_FN_ATTRIB "oacc function"
12556 /* Replace any existing oacc fn attribute with updated dimensions. */
12558 void
12559 replace_oacc_fn_attrib (tree fn, tree dims)
12561 tree ident = get_identifier (OACC_FN_ATTRIB);
12562 tree attribs = DECL_ATTRIBUTES (fn);
12564 /* If we happen to be present as the first attrib, drop it. */
12565 if (attribs && TREE_PURPOSE (attribs) == ident)
12566 attribs = TREE_CHAIN (attribs);
12567 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12570 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12571 function attribute. Push any that are non-constant onto the ARGS
12572 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12573 true, if these are for a kernels region offload function. */
12575 void
12576 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12578 /* Must match GOMP_DIM ordering. */
12579 static const omp_clause_code ids[]
12580 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12581 OMP_CLAUSE_VECTOR_LENGTH };
12582 unsigned ix;
12583 tree dims[GOMP_DIM_MAX];
12584 tree attr = NULL_TREE;
12585 unsigned non_const = 0;
12587 for (ix = GOMP_DIM_MAX; ix--;)
12589 tree clause = find_omp_clause (clauses, ids[ix]);
12590 tree dim = NULL_TREE;
12592 if (clause)
12593 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12594 dims[ix] = dim;
12595 if (dim && TREE_CODE (dim) != INTEGER_CST)
12597 dim = integer_zero_node;
12598 non_const |= GOMP_DIM_MASK (ix);
12600 attr = tree_cons (NULL_TREE, dim, attr);
12601 /* Note kernelness with TREE_PUBLIC. */
12602 if (is_kernel)
12603 TREE_PUBLIC (attr) = 1;
12606 replace_oacc_fn_attrib (fn, attr);
12608 if (non_const)
12610 /* Push a dynamic argument set. */
12611 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12612 NULL_TREE, non_const));
12613 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12614 if (non_const & GOMP_DIM_MASK (ix))
12615 args->safe_push (dims[ix]);
12619 /* Process the routine's dimension clauess to generate an attribute
12620 value. Issue diagnostics as appropriate. We default to SEQ
12621 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12622 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12623 can have a loop partitioned on it. non-zero indicates
12624 yes, zero indicates no. By construction once a non-zero has been
12625 reached, further inner dimensions must also be non-zero. We set
12626 TREE_VALUE to zero for the dimensions that may be partitioned and
12627 1 for the other ones -- if a loop is (erroneously) spawned at
12628 an outer level, we don't want to try and partition it. */
12630 tree
12631 build_oacc_routine_dims (tree clauses)
12633 /* Must match GOMP_DIM ordering. */
12634 static const omp_clause_code ids[] =
12635 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12636 int ix;
12637 int level = -1;
12639 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12640 for (ix = GOMP_DIM_MAX + 1; ix--;)
12641 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12643 if (level >= 0)
12644 error_at (OMP_CLAUSE_LOCATION (clauses),
12645 "multiple loop axes specified for routine");
12646 level = ix;
12647 break;
12650 /* Default to SEQ. */
12651 if (level < 0)
12652 level = GOMP_DIM_MAX;
12654 tree dims = NULL_TREE;
12656 for (ix = GOMP_DIM_MAX; ix--;)
12657 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12658 build_int_cst (integer_type_node, ix < level), dims);
12660 return dims;
12663 /* Retrieve the oacc function attrib and return it. Non-oacc
12664 functions will return NULL. */
12666 tree
12667 get_oacc_fn_attrib (tree fn)
12669 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12672 /* Return true if this oacc fn attrib is for a kernels offload
12673 region. We use the TREE_PUBLIC flag of each dimension -- only
12674 need to check the first one. */
12676 bool
12677 oacc_fn_attrib_kernels_p (tree attr)
12679 return TREE_PUBLIC (TREE_VALUE (attr));
12682 /* Return level at which oacc routine may spawn a partitioned loop, or
12683 -1 if it is not a routine (i.e. is an offload fn). */
12685 static int
12686 oacc_fn_attrib_level (tree attr)
12688 tree pos = TREE_VALUE (attr);
12690 if (!TREE_PURPOSE (pos))
12691 return -1;
12693 int ix = 0;
12694 for (ix = 0; ix != GOMP_DIM_MAX;
12695 ix++, pos = TREE_CHAIN (pos))
12696 if (!integer_zerop (TREE_PURPOSE (pos)))
12697 break;
12699 return ix;
12702 /* Extract an oacc execution dimension from FN. FN must be an
12703 offloaded function or routine that has already had its execution
12704 dimensions lowered to the target-specific values. */
12707 get_oacc_fn_dim_size (tree fn, int axis)
12709 tree attrs = get_oacc_fn_attrib (fn);
12711 gcc_assert (axis < GOMP_DIM_MAX);
12713 tree dims = TREE_VALUE (attrs);
12714 while (axis--)
12715 dims = TREE_CHAIN (dims);
12717 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12719 return size;
12722 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12723 IFN_GOACC_DIM_SIZE call. */
12726 get_oacc_ifn_dim_arg (const gimple *stmt)
12728 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12729 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12730 tree arg = gimple_call_arg (stmt, 0);
12731 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12733 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12734 return (int) axis;
12737 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12738 at REGION_EXIT. */
12740 static void
12741 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12742 basic_block region_exit)
12744 struct loop *outer = region_entry->loop_father;
12745 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12747 /* Don't parallelize the kernels region if it contains more than one outer
12748 loop. */
12749 unsigned int nr_outer_loops = 0;
12750 struct loop *single_outer = NULL;
12751 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12753 gcc_assert (loop_outer (loop) == outer);
12755 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12756 continue;
12758 if (region_exit != NULL
12759 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12760 continue;
12762 nr_outer_loops++;
12763 single_outer = loop;
12765 if (nr_outer_loops != 1)
12766 return;
12768 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12769 if (loop->next)
12770 return;
12772 /* Mark the loops in the region. */
12773 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12774 loop->in_oacc_kernels_region = true;
12777 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12779 struct GTY(()) grid_launch_attributes_trees
12781 tree kernel_dim_array_type;
12782 tree kernel_lattrs_dimnum_decl;
12783 tree kernel_lattrs_grid_decl;
12784 tree kernel_lattrs_group_decl;
12785 tree kernel_launch_attributes_type;
12788 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12790 /* Create types used to pass kernel launch attributes to target. */
12792 static void
12793 grid_create_kernel_launch_attr_types (void)
12795 if (grid_attr_trees)
12796 return;
12797 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12799 tree dim_arr_index_type
12800 = build_index_type (build_int_cst (integer_type_node, 2));
12801 grid_attr_trees->kernel_dim_array_type
12802 = build_array_type (uint32_type_node, dim_arr_index_type);
12804 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12805 grid_attr_trees->kernel_lattrs_dimnum_decl
12806 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12807 uint32_type_node);
12808 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12810 grid_attr_trees->kernel_lattrs_grid_decl
12811 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12812 grid_attr_trees->kernel_dim_array_type);
12813 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12814 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12815 grid_attr_trees->kernel_lattrs_group_decl
12816 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12817 grid_attr_trees->kernel_dim_array_type);
12818 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12819 = grid_attr_trees->kernel_lattrs_grid_decl;
12820 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12821 "__gomp_kernel_launch_attributes",
12822 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12825 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12826 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12827 of type uint32_type_node. */
12829 static void
12830 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12831 tree fld_decl, int index, tree value)
12833 tree ref = build4 (ARRAY_REF, uint32_type_node,
12834 build3 (COMPONENT_REF,
12835 grid_attr_trees->kernel_dim_array_type,
12836 range_var, fld_decl, NULL_TREE),
12837 build_int_cst (integer_type_node, index),
12838 NULL_TREE, NULL_TREE);
12839 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12842 /* Return a tree representation of a pointer to a structure with grid and
12843 work-group size information. Statements filling that information will be
12844 inserted before GSI, TGT_STMT is the target statement which has the
12845 necessary information in it. */
12847 static tree
12848 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12849 gomp_target *tgt_stmt)
12851 grid_create_kernel_launch_attr_types ();
12852 tree u32_one = build_one_cst (uint32_type_node);
12853 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12854 "__kernel_launch_attrs");
12856 unsigned max_dim = 0;
12857 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12858 clause;
12859 clause = OMP_CLAUSE_CHAIN (clause))
12861 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12862 continue;
12864 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12865 max_dim = MAX (dim, max_dim);
12867 grid_insert_store_range_dim (gsi, lattrs,
12868 grid_attr_trees->kernel_lattrs_grid_decl,
12869 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12870 grid_insert_store_range_dim (gsi, lattrs,
12871 grid_attr_trees->kernel_lattrs_group_decl,
12872 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12875 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12876 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12877 /* At this moment we cannot gridify a loop with a collapse clause. */
12878 /* TODO: Adjust when we support bigger collapse. */
12879 gcc_assert (max_dim == 0);
12880 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12881 TREE_ADDRESSABLE (lattrs) = 1;
12882 return build_fold_addr_expr (lattrs);
12885 /* Build target argument identifier from the DEVICE identifier, value
12886 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12888 static tree
12889 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12891 tree t = build_int_cst (integer_type_node, device);
12892 if (subseqent_param)
12893 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12894 build_int_cst (integer_type_node,
12895 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12896 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12897 build_int_cst (integer_type_node, id));
12898 return t;
12901 /* Like above but return it in type that can be directly stored as an element
12902 of the argument array. */
12904 static tree
12905 get_target_argument_identifier (int device, bool subseqent_param, int id)
12907 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12908 return fold_convert (ptr_type_node, t);
12911 /* Return a target argument consisting of DEVICE identifier, value identifier
12912 ID, and the actual VALUE. */
12914 static tree
12915 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12916 tree value)
12918 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12919 fold_convert (integer_type_node, value),
12920 build_int_cst (unsigned_type_node,
12921 GOMP_TARGET_ARG_VALUE_SHIFT));
12922 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12923 get_target_argument_identifier_1 (device, false, id));
12924 t = fold_convert (ptr_type_node, t);
12925 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12928 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12929 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12930 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12931 arguments. */
12933 static void
12934 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12935 int id, tree value, vec <tree> *args)
12937 if (tree_fits_shwi_p (value)
12938 && tree_to_shwi (value) > -(1 << 15)
12939 && tree_to_shwi (value) < (1 << 15))
12940 args->quick_push (get_target_argument_value (gsi, device, id, value));
12941 else
12943 args->quick_push (get_target_argument_identifier (device, true, id));
12944 value = fold_convert (ptr_type_node, value);
12945 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12946 GSI_SAME_STMT);
12947 args->quick_push (value);
12951 /* Create an array of arguments that is then passed to GOMP_target. */
12953 static tree
12954 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12956 auto_vec <tree, 6> args;
12957 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12958 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12959 if (c)
12960 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12961 else
12962 t = integer_minus_one_node;
12963 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12964 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12966 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12967 if (c)
12968 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12969 else
12970 t = integer_minus_one_node;
12971 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12972 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12973 &args);
12975 /* Add HSA-specific grid sizes, if available. */
12976 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12977 OMP_CLAUSE__GRIDDIM_))
12979 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12980 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12981 args.quick_push (t);
12982 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12985 /* Produce more, perhaps device specific, arguments here. */
12987 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12988 args.length () + 1),
12989 ".omp_target_args");
12990 for (unsigned i = 0; i < args.length (); i++)
12992 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12993 build_int_cst (integer_type_node, i),
12994 NULL_TREE, NULL_TREE);
12995 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12996 GSI_SAME_STMT);
12998 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12999 build_int_cst (integer_type_node, args.length ()),
13000 NULL_TREE, NULL_TREE);
13001 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
13002 GSI_SAME_STMT);
13003 TREE_ADDRESSABLE (argarray) = 1;
13004 return build_fold_addr_expr (argarray);
13007 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
13009 static void
13010 expand_omp_target (struct omp_region *region)
13012 basic_block entry_bb, exit_bb, new_bb;
13013 struct function *child_cfun;
13014 tree child_fn, block, t;
13015 gimple_stmt_iterator gsi;
13016 gomp_target *entry_stmt;
13017 gimple *stmt;
13018 edge e;
13019 bool offloaded, data_region;
13021 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13022 new_bb = region->entry;
13024 offloaded = is_gimple_omp_offloaded (entry_stmt);
13025 switch (gimple_omp_target_kind (entry_stmt))
13027 case GF_OMP_TARGET_KIND_REGION:
13028 case GF_OMP_TARGET_KIND_UPDATE:
13029 case GF_OMP_TARGET_KIND_ENTER_DATA:
13030 case GF_OMP_TARGET_KIND_EXIT_DATA:
13031 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13032 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13033 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13034 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13035 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13036 data_region = false;
13037 break;
13038 case GF_OMP_TARGET_KIND_DATA:
13039 case GF_OMP_TARGET_KIND_OACC_DATA:
13040 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13041 data_region = true;
13042 break;
13043 default:
13044 gcc_unreachable ();
13047 child_fn = NULL_TREE;
13048 child_cfun = NULL;
13049 if (offloaded)
13051 child_fn = gimple_omp_target_child_fn (entry_stmt);
13052 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13055 /* Supported by expand_omp_taskreg, but not here. */
13056 if (child_cfun != NULL)
13057 gcc_checking_assert (!child_cfun->cfg);
13058 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13060 entry_bb = region->entry;
13061 exit_bb = region->exit;
13063 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13064 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13066 if (offloaded)
13068 unsigned srcidx, dstidx, num;
13070 /* If the offloading region needs data sent from the parent
13071 function, then the very first statement (except possible
13072 tree profile counter updates) of the offloading body
13073 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13074 &.OMP_DATA_O is passed as an argument to the child function,
13075 we need to replace it with the argument as seen by the child
13076 function.
13078 In most cases, this will end up being the identity assignment
13079 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13080 a function call that has been inlined, the original PARM_DECL
13081 .OMP_DATA_I may have been converted into a different local
13082 variable. In which case, we need to keep the assignment. */
13083 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13084 if (data_arg)
13086 basic_block entry_succ_bb = single_succ (entry_bb);
13087 gimple_stmt_iterator gsi;
13088 tree arg;
13089 gimple *tgtcopy_stmt = NULL;
13090 tree sender = TREE_VEC_ELT (data_arg, 0);
13092 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13094 gcc_assert (!gsi_end_p (gsi));
13095 stmt = gsi_stmt (gsi);
13096 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13097 continue;
13099 if (gimple_num_ops (stmt) == 2)
13101 tree arg = gimple_assign_rhs1 (stmt);
13103 /* We're ignoring the subcode because we're
13104 effectively doing a STRIP_NOPS. */
13106 if (TREE_CODE (arg) == ADDR_EXPR
13107 && TREE_OPERAND (arg, 0) == sender)
13109 tgtcopy_stmt = stmt;
13110 break;
13115 gcc_assert (tgtcopy_stmt != NULL);
13116 arg = DECL_ARGUMENTS (child_fn);
13118 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13119 gsi_remove (&gsi, true);
13122 /* Declare local variables needed in CHILD_CFUN. */
13123 block = DECL_INITIAL (child_fn);
13124 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13125 /* The gimplifier could record temporaries in the offloading block
13126 rather than in containing function's local_decls chain,
13127 which would mean cgraph missed finalizing them. Do it now. */
13128 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13129 if (TREE_CODE (t) == VAR_DECL
13130 && TREE_STATIC (t)
13131 && !DECL_EXTERNAL (t))
13132 varpool_node::finalize_decl (t);
13133 DECL_SAVED_TREE (child_fn) = NULL;
13134 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13135 gimple_set_body (child_fn, NULL);
13136 TREE_USED (block) = 1;
13138 /* Reset DECL_CONTEXT on function arguments. */
13139 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13140 DECL_CONTEXT (t) = child_fn;
13142 /* Split ENTRY_BB at GIMPLE_*,
13143 so that it can be moved to the child function. */
13144 gsi = gsi_last_bb (entry_bb);
13145 stmt = gsi_stmt (gsi);
13146 gcc_assert (stmt
13147 && gimple_code (stmt) == gimple_code (entry_stmt));
13148 e = split_block (entry_bb, stmt);
13149 gsi_remove (&gsi, true);
13150 entry_bb = e->dest;
13151 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13153 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13154 if (exit_bb)
13156 gsi = gsi_last_bb (exit_bb);
13157 gcc_assert (!gsi_end_p (gsi)
13158 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13159 stmt = gimple_build_return (NULL);
13160 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13161 gsi_remove (&gsi, true);
13164 /* Move the offloading region into CHILD_CFUN. */
13166 block = gimple_block (entry_stmt);
13168 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13169 if (exit_bb)
13170 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13171 /* When the OMP expansion process cannot guarantee an up-to-date
13172 loop tree arrange for the child function to fixup loops. */
13173 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13174 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13176 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13177 num = vec_safe_length (child_cfun->local_decls);
13178 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13180 t = (*child_cfun->local_decls)[srcidx];
13181 if (DECL_CONTEXT (t) == cfun->decl)
13182 continue;
13183 if (srcidx != dstidx)
13184 (*child_cfun->local_decls)[dstidx] = t;
13185 dstidx++;
13187 if (dstidx != num)
13188 vec_safe_truncate (child_cfun->local_decls, dstidx);
13190 /* Inform the callgraph about the new function. */
13191 child_cfun->curr_properties = cfun->curr_properties;
13192 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13193 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13194 cgraph_node *node = cgraph_node::get_create (child_fn);
13195 node->parallelized_function = 1;
13196 cgraph_node::add_new_function (child_fn, true);
13198 /* Add the new function to the offload table. */
13199 if (ENABLE_OFFLOADING)
13200 vec_safe_push (offload_funcs, child_fn);
13202 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13203 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13205 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13206 fixed in a following pass. */
13207 push_cfun (child_cfun);
13208 if (need_asm)
13209 assign_assembler_name_if_neeeded (child_fn);
13210 cgraph_edge::rebuild_edges ();
13212 /* Some EH regions might become dead, see PR34608. If
13213 pass_cleanup_cfg isn't the first pass to happen with the
13214 new child, these dead EH edges might cause problems.
13215 Clean them up now. */
13216 if (flag_exceptions)
13218 basic_block bb;
13219 bool changed = false;
13221 FOR_EACH_BB_FN (bb, cfun)
13222 changed |= gimple_purge_dead_eh_edges (bb);
13223 if (changed)
13224 cleanup_tree_cfg ();
13226 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13227 verify_loop_structure ();
13228 pop_cfun ();
13230 if (dump_file && !gimple_in_ssa_p (cfun))
13232 omp_any_child_fn_dumped = true;
13233 dump_function_header (dump_file, child_fn, dump_flags);
13234 dump_function_to_file (child_fn, dump_file, dump_flags);
13238 /* Emit a library call to launch the offloading region, or do data
13239 transfers. */
13240 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13241 enum built_in_function start_ix;
13242 location_t clause_loc;
13243 unsigned int flags_i = 0;
13244 bool oacc_kernels_p = false;
13246 switch (gimple_omp_target_kind (entry_stmt))
13248 case GF_OMP_TARGET_KIND_REGION:
13249 start_ix = BUILT_IN_GOMP_TARGET;
13250 break;
13251 case GF_OMP_TARGET_KIND_DATA:
13252 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13253 break;
13254 case GF_OMP_TARGET_KIND_UPDATE:
13255 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13256 break;
13257 case GF_OMP_TARGET_KIND_ENTER_DATA:
13258 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13259 break;
13260 case GF_OMP_TARGET_KIND_EXIT_DATA:
13261 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13262 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13263 break;
13264 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13265 oacc_kernels_p = true;
13266 /* FALLTHROUGH */
13267 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13268 start_ix = BUILT_IN_GOACC_PARALLEL;
13269 break;
13270 case GF_OMP_TARGET_KIND_OACC_DATA:
13271 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13272 start_ix = BUILT_IN_GOACC_DATA_START;
13273 break;
13274 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13275 start_ix = BUILT_IN_GOACC_UPDATE;
13276 break;
13277 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13278 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13279 break;
13280 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13281 start_ix = BUILT_IN_GOACC_DECLARE;
13282 break;
13283 default:
13284 gcc_unreachable ();
13287 clauses = gimple_omp_target_clauses (entry_stmt);
13289 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13290 library choose) and there is no conditional. */
13291 cond = NULL_TREE;
13292 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13294 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13295 if (c)
13296 cond = OMP_CLAUSE_IF_EXPR (c);
13298 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13299 if (c)
13301 /* Even if we pass it to all library function calls, it is currently only
13302 defined/used for the OpenMP target ones. */
13303 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13304 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13305 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13306 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13308 device = OMP_CLAUSE_DEVICE_ID (c);
13309 clause_loc = OMP_CLAUSE_LOCATION (c);
13311 else
13312 clause_loc = gimple_location (entry_stmt);
13314 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13315 if (c)
13316 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13318 /* Ensure 'device' is of the correct type. */
13319 device = fold_convert_loc (clause_loc, integer_type_node, device);
13321 /* If we found the clause 'if (cond)', build
13322 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13323 if (cond)
13325 cond = gimple_boolify (cond);
13327 basic_block cond_bb, then_bb, else_bb;
13328 edge e;
13329 tree tmp_var;
13331 tmp_var = create_tmp_var (TREE_TYPE (device));
13332 if (offloaded)
13333 e = split_block_after_labels (new_bb);
13334 else
13336 gsi = gsi_last_bb (new_bb);
13337 gsi_prev (&gsi);
13338 e = split_block (new_bb, gsi_stmt (gsi));
13340 cond_bb = e->src;
13341 new_bb = e->dest;
13342 remove_edge (e);
13344 then_bb = create_empty_bb (cond_bb);
13345 else_bb = create_empty_bb (then_bb);
13346 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13347 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13349 stmt = gimple_build_cond_empty (cond);
13350 gsi = gsi_last_bb (cond_bb);
13351 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13353 gsi = gsi_start_bb (then_bb);
13354 stmt = gimple_build_assign (tmp_var, device);
13355 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13357 gsi = gsi_start_bb (else_bb);
13358 stmt = gimple_build_assign (tmp_var,
13359 build_int_cst (integer_type_node,
13360 GOMP_DEVICE_HOST_FALLBACK));
13361 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13363 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13364 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13365 add_bb_to_loop (then_bb, cond_bb->loop_father);
13366 add_bb_to_loop (else_bb, cond_bb->loop_father);
13367 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13368 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13370 device = tmp_var;
13371 gsi = gsi_last_bb (new_bb);
13373 else
13375 gsi = gsi_last_bb (new_bb);
13376 device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
13377 true, GSI_SAME_STMT);
13380 t = gimple_omp_target_data_arg (entry_stmt);
13381 if (t == NULL)
13383 t1 = size_zero_node;
13384 t2 = build_zero_cst (ptr_type_node);
13385 t3 = t2;
13386 t4 = t2;
13388 else
13390 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13391 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13392 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13393 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13394 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13397 gimple *g;
13398 bool tagging = false;
13399 /* The maximum number used by any start_ix, without varargs. */
13400 auto_vec<tree, 11> args;
13401 args.quick_push (device);
13402 if (offloaded)
13403 args.quick_push (build_fold_addr_expr (child_fn));
13404 args.quick_push (t1);
13405 args.quick_push (t2);
13406 args.quick_push (t3);
13407 args.quick_push (t4);
13408 switch (start_ix)
13410 case BUILT_IN_GOACC_DATA_START:
13411 case BUILT_IN_GOACC_DECLARE:
13412 case BUILT_IN_GOMP_TARGET_DATA:
13413 break;
13414 case BUILT_IN_GOMP_TARGET:
13415 case BUILT_IN_GOMP_TARGET_UPDATE:
13416 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13417 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13418 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13419 if (c)
13420 depend = OMP_CLAUSE_DECL (c);
13421 else
13422 depend = build_int_cst (ptr_type_node, 0);
13423 args.quick_push (depend);
13424 if (start_ix == BUILT_IN_GOMP_TARGET)
13425 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13426 break;
13427 case BUILT_IN_GOACC_PARALLEL:
13429 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13430 tagging = true;
13432 /* FALLTHRU */
13433 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13434 case BUILT_IN_GOACC_UPDATE:
13436 tree t_async = NULL_TREE;
13438 /* If present, use the value specified by the respective
13439 clause, making sure that is of the correct type. */
13440 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13441 if (c)
13442 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13443 integer_type_node,
13444 OMP_CLAUSE_ASYNC_EXPR (c));
13445 else if (!tagging)
13446 /* Default values for t_async. */
13447 t_async = fold_convert_loc (gimple_location (entry_stmt),
13448 integer_type_node,
13449 build_int_cst (integer_type_node,
13450 GOMP_ASYNC_SYNC));
13451 if (tagging && t_async)
13453 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13455 if (TREE_CODE (t_async) == INTEGER_CST)
13457 /* See if we can pack the async arg in to the tag's
13458 operand. */
13459 i_async = TREE_INT_CST_LOW (t_async);
13460 if (i_async < GOMP_LAUNCH_OP_MAX)
13461 t_async = NULL_TREE;
13462 else
13463 i_async = GOMP_LAUNCH_OP_MAX;
13465 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13466 i_async));
13468 if (t_async)
13469 args.safe_push (t_async);
13471 /* Save the argument index, and ... */
13472 unsigned t_wait_idx = args.length ();
13473 unsigned num_waits = 0;
13474 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13475 if (!tagging || c)
13476 /* ... push a placeholder. */
13477 args.safe_push (integer_zero_node);
13479 for (; c; c = OMP_CLAUSE_CHAIN (c))
13480 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13482 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13483 integer_type_node,
13484 OMP_CLAUSE_WAIT_EXPR (c)));
13485 num_waits++;
13488 if (!tagging || num_waits)
13490 tree len;
13492 /* Now that we know the number, update the placeholder. */
13493 if (tagging)
13494 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13495 else
13496 len = build_int_cst (integer_type_node, num_waits);
13497 len = fold_convert_loc (gimple_location (entry_stmt),
13498 unsigned_type_node, len);
13499 args[t_wait_idx] = len;
13502 break;
13503 default:
13504 gcc_unreachable ();
13506 if (tagging)
13507 /* Push terminal marker - zero. */
13508 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13510 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13511 gimple_set_location (g, gimple_location (entry_stmt));
13512 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13513 if (!offloaded)
13515 g = gsi_stmt (gsi);
13516 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13517 gsi_remove (&gsi, true);
13519 if (data_region && region->exit)
13521 gsi = gsi_last_bb (region->exit);
13522 g = gsi_stmt (gsi);
13523 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13524 gsi_remove (&gsi, true);
13528 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13529 variable derived from the thread number. */
13531 static void
13532 grid_expand_omp_for_loop (struct omp_region *kfor)
13534 tree t, threadid;
13535 tree type, itype;
13536 gimple_stmt_iterator gsi;
13537 tree n1, step;
13538 struct omp_for_data fd;
13540 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13541 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13542 == GF_OMP_FOR_KIND_GRID_LOOP);
13543 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13545 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13546 gcc_assert (kfor->cont);
13547 extract_omp_for_data (for_stmt, &fd, NULL);
13549 itype = type = TREE_TYPE (fd.loop.v);
13550 if (POINTER_TYPE_P (type))
13551 itype = signed_type_for (type);
13553 gsi = gsi_start_bb (body_bb);
13555 n1 = fd.loop.n1;
13556 step = fd.loop.step;
13557 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13558 true, NULL_TREE, true, GSI_SAME_STMT);
13559 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13560 true, NULL_TREE, true, GSI_SAME_STMT);
13561 threadid = build_call_expr (builtin_decl_explicit
13562 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13563 threadid = fold_convert (itype, threadid);
13564 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13565 true, GSI_SAME_STMT);
13567 tree startvar = fd.loop.v;
13568 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13569 if (POINTER_TYPE_P (type))
13570 t = fold_build_pointer_plus (n1, t);
13571 else
13572 t = fold_build2 (PLUS_EXPR, type, t, n1);
13573 t = fold_convert (type, t);
13574 t = force_gimple_operand_gsi (&gsi, t,
13575 DECL_P (startvar)
13576 && TREE_ADDRESSABLE (startvar),
13577 NULL_TREE, true, GSI_SAME_STMT);
13578 gassign *assign_stmt = gimple_build_assign (startvar, t);
13579 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13581 /* Remove the omp for statement */
13582 gsi = gsi_last_bb (kfor->entry);
13583 gsi_remove (&gsi, true);
13585 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13586 gsi = gsi_last_bb (kfor->cont);
13587 gcc_assert (!gsi_end_p (gsi)
13588 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13589 gsi_remove (&gsi, true);
13591 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13592 gsi = gsi_last_bb (kfor->exit);
13593 gcc_assert (!gsi_end_p (gsi)
13594 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13595 gsi_remove (&gsi, true);
13597 /* Fixup the much simpler CFG. */
13598 remove_edge (find_edge (kfor->cont, body_bb));
13600 if (kfor->cont != body_bb)
13601 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13602 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13605 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13606 argument_decls. */
13608 struct grid_arg_decl_map
13610 tree old_arg;
13611 tree new_arg;
13614 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13615 pertaining to kernel function. */
13617 static tree
13618 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13620 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13621 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13622 tree t = *tp;
13624 if (t == adm->old_arg)
13625 *tp = adm->new_arg;
13626 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13627 return NULL_TREE;
13630 static void expand_omp (struct omp_region *region);
13632 /* If TARGET region contains a kernel body for loop, remove its region from the
13633 TARGET and expand it in GPGPU kernel fashion. */
13635 static void
13636 grid_expand_target_grid_body (struct omp_region *target)
13638 if (!hsa_gen_requested_p ())
13639 return;
13641 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13642 struct omp_region **pp;
13644 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13645 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13646 break;
13648 struct omp_region *gpukernel = *pp;
13650 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13651 if (!gpukernel)
13653 /* HSA cannot handle OACC stuff. */
13654 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13655 return;
13656 gcc_checking_assert (orig_child_fndecl);
13657 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13658 OMP_CLAUSE__GRIDDIM_));
13659 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13661 hsa_register_kernel (n);
13662 return;
13665 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13666 OMP_CLAUSE__GRIDDIM_));
13667 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13668 *pp = gpukernel->next;
13669 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13670 if ((*pp)->type == GIMPLE_OMP_FOR)
13671 break;
13673 struct omp_region *kfor = *pp;
13674 gcc_assert (kfor);
13675 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13676 == GF_OMP_FOR_KIND_GRID_LOOP);
13677 *pp = kfor->next;
13678 if (kfor->inner)
13679 expand_omp (kfor->inner);
13680 if (gpukernel->inner)
13681 expand_omp (gpukernel->inner);
13683 tree kern_fndecl = copy_node (orig_child_fndecl);
13684 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13685 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13686 tree tgtblock = gimple_block (tgt_stmt);
13687 tree fniniblock = make_node (BLOCK);
13688 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13689 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13690 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13691 BLOCK_SUPERCONTEXT (fniniblock) = kern_fndecl;
13692 DECL_INITIAL (kern_fndecl) = fniniblock;
13693 push_struct_function (kern_fndecl);
13694 cfun->function_end_locus = gimple_location (tgt_stmt);
13695 init_tree_ssa (cfun);
13696 pop_cfun ();
13698 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13699 gcc_assert (!DECL_CHAIN (old_parm_decl));
13700 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13701 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13702 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13703 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13704 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13705 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
13706 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13707 kern_cfun->curr_properties = cfun->curr_properties;
13709 remove_edge (BRANCH_EDGE (kfor->entry));
13710 grid_expand_omp_for_loop (kfor);
13712 /* Remove the omp for statement */
13713 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13714 gsi_remove (&gsi, true);
13715 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13716 return. */
13717 gsi = gsi_last_bb (gpukernel->exit);
13718 gcc_assert (!gsi_end_p (gsi)
13719 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13720 gimple *ret_stmt = gimple_build_return (NULL);
13721 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13722 gsi_remove (&gsi, true);
13724 /* Statements in the first BB in the target construct have been produced by
13725 target lowering and must be copied inside the GPUKERNEL, with the two
13726 exceptions of the first OMP statement and the OMP_DATA assignment
13727 statement. */
13728 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13729 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13730 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13731 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13732 !gsi_end_p (tsi); gsi_next (&tsi))
13734 gimple *stmt = gsi_stmt (tsi);
13735 if (is_gimple_omp (stmt))
13736 break;
13737 if (sender
13738 && is_gimple_assign (stmt)
13739 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13740 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13741 continue;
13742 gimple *copy = gimple_copy (stmt);
13743 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13744 gimple_set_block (copy, fniniblock);
13747 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13748 gpukernel->exit, inside_block);
13750 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13751 kcn->mark_force_output ();
13752 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13754 hsa_register_kernel (kcn, orig_child);
13756 cgraph_node::add_new_function (kern_fndecl, true);
13757 push_cfun (kern_cfun);
13758 cgraph_edge::rebuild_edges ();
13760 /* Re-map any mention of the PARM_DECL of the original function to the
13761 PARM_DECL of the new one.
13763 TODO: It would be great if lowering produced references into the GPU
13764 kernel decl straight away and we did not have to do this. */
13765 struct grid_arg_decl_map adm;
13766 adm.old_arg = old_parm_decl;
13767 adm.new_arg = new_parm_decl;
13768 basic_block bb;
13769 FOR_EACH_BB_FN (bb, kern_cfun)
13771 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13773 gimple *stmt = gsi_stmt (gsi);
13774 struct walk_stmt_info wi;
13775 memset (&wi, 0, sizeof (wi));
13776 wi.info = &adm;
13777 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13780 pop_cfun ();
13782 return;
13785 /* Expand the parallel region tree rooted at REGION. Expansion
13786 proceeds in depth-first order. Innermost regions are expanded
13787 first. This way, parallel regions that require a new function to
13788 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13789 internal dependencies in their body. */
13791 static void
13792 expand_omp (struct omp_region *region)
13794 omp_any_child_fn_dumped = false;
13795 while (region)
13797 location_t saved_location;
13798 gimple *inner_stmt = NULL;
13800 /* First, determine whether this is a combined parallel+workshare
13801 region. */
13802 if (region->type == GIMPLE_OMP_PARALLEL)
13803 determine_parallel_type (region);
13804 else if (region->type == GIMPLE_OMP_TARGET)
13805 grid_expand_target_grid_body (region);
13807 if (region->type == GIMPLE_OMP_FOR
13808 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13809 inner_stmt = last_stmt (region->inner->entry);
13811 if (region->inner)
13812 expand_omp (region->inner);
13814 saved_location = input_location;
13815 if (gimple_has_location (last_stmt (region->entry)))
13816 input_location = gimple_location (last_stmt (region->entry));
13818 switch (region->type)
13820 case GIMPLE_OMP_PARALLEL:
13821 case GIMPLE_OMP_TASK:
13822 expand_omp_taskreg (region);
13823 break;
13825 case GIMPLE_OMP_FOR:
13826 expand_omp_for (region, inner_stmt);
13827 break;
13829 case GIMPLE_OMP_SECTIONS:
13830 expand_omp_sections (region);
13831 break;
13833 case GIMPLE_OMP_SECTION:
13834 /* Individual omp sections are handled together with their
13835 parent GIMPLE_OMP_SECTIONS region. */
13836 break;
13838 case GIMPLE_OMP_SINGLE:
13839 expand_omp_single (region);
13840 break;
13842 case GIMPLE_OMP_ORDERED:
13844 gomp_ordered *ord_stmt
13845 = as_a <gomp_ordered *> (last_stmt (region->entry));
13846 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13847 OMP_CLAUSE_DEPEND))
13849 /* We'll expand these when expanding corresponding
13850 worksharing region with ordered(n) clause. */
13851 gcc_assert (region->outer
13852 && region->outer->type == GIMPLE_OMP_FOR);
13853 region->ord_stmt = ord_stmt;
13854 break;
13857 /* FALLTHRU */
13858 case GIMPLE_OMP_MASTER:
13859 case GIMPLE_OMP_TASKGROUP:
13860 case GIMPLE_OMP_CRITICAL:
13861 case GIMPLE_OMP_TEAMS:
13862 expand_omp_synch (region);
13863 break;
13865 case GIMPLE_OMP_ATOMIC_LOAD:
13866 expand_omp_atomic (region);
13867 break;
13869 case GIMPLE_OMP_TARGET:
13870 expand_omp_target (region);
13871 break;
13873 default:
13874 gcc_unreachable ();
13877 input_location = saved_location;
13878 region = region->next;
13880 if (omp_any_child_fn_dumped)
13882 if (dump_file)
13883 dump_function_header (dump_file, current_function_decl, dump_flags);
13884 omp_any_child_fn_dumped = false;
13889 /* Helper for build_omp_regions. Scan the dominator tree starting at
13890 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13891 true, the function ends once a single tree is built (otherwise, whole
13892 forest of OMP constructs may be built). */
13894 static void
13895 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13896 bool single_tree)
13898 gimple_stmt_iterator gsi;
13899 gimple *stmt;
13900 basic_block son;
13902 gsi = gsi_last_bb (bb);
13903 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13905 struct omp_region *region;
13906 enum gimple_code code;
13908 stmt = gsi_stmt (gsi);
13909 code = gimple_code (stmt);
13910 if (code == GIMPLE_OMP_RETURN)
13912 /* STMT is the return point out of region PARENT. Mark it
13913 as the exit point and make PARENT the immediately
13914 enclosing region. */
13915 gcc_assert (parent);
13916 region = parent;
13917 region->exit = bb;
13918 parent = parent->outer;
13920 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13922 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13923 GIMPLE_OMP_RETURN, but matches with
13924 GIMPLE_OMP_ATOMIC_LOAD. */
13925 gcc_assert (parent);
13926 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13927 region = parent;
13928 region->exit = bb;
13929 parent = parent->outer;
13931 else if (code == GIMPLE_OMP_CONTINUE)
13933 gcc_assert (parent);
13934 parent->cont = bb;
13936 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13938 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13939 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13941 else
13943 region = new_omp_region (bb, code, parent);
13944 /* Otherwise... */
13945 if (code == GIMPLE_OMP_TARGET)
13947 switch (gimple_omp_target_kind (stmt))
13949 case GF_OMP_TARGET_KIND_REGION:
13950 case GF_OMP_TARGET_KIND_DATA:
13951 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13952 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13953 case GF_OMP_TARGET_KIND_OACC_DATA:
13954 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13955 break;
13956 case GF_OMP_TARGET_KIND_UPDATE:
13957 case GF_OMP_TARGET_KIND_ENTER_DATA:
13958 case GF_OMP_TARGET_KIND_EXIT_DATA:
13959 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13960 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13961 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13962 /* ..., other than for those stand-alone directives... */
13963 region = NULL;
13964 break;
13965 default:
13966 gcc_unreachable ();
13969 else if (code == GIMPLE_OMP_ORDERED
13970 && find_omp_clause (gimple_omp_ordered_clauses
13971 (as_a <gomp_ordered *> (stmt)),
13972 OMP_CLAUSE_DEPEND))
13973 /* #pragma omp ordered depend is also just a stand-alone
13974 directive. */
13975 region = NULL;
13976 /* ..., this directive becomes the parent for a new region. */
13977 if (region)
13978 parent = region;
13982 if (single_tree && !parent)
13983 return;
13985 for (son = first_dom_son (CDI_DOMINATORS, bb);
13986 son;
13987 son = next_dom_son (CDI_DOMINATORS, son))
13988 build_omp_regions_1 (son, parent, single_tree);
13991 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13992 root_omp_region. */
13994 static void
13995 build_omp_regions_root (basic_block root)
13997 gcc_assert (root_omp_region == NULL);
13998 build_omp_regions_1 (root, NULL, true);
13999 gcc_assert (root_omp_region != NULL);
14002 /* Expands omp construct (and its subconstructs) starting in HEAD. */
14004 void
14005 omp_expand_local (basic_block head)
14007 build_omp_regions_root (head);
14008 if (dump_file && (dump_flags & TDF_DETAILS))
14010 fprintf (dump_file, "\nOMP region tree\n\n");
14011 dump_omp_region (dump_file, root_omp_region, 0);
14012 fprintf (dump_file, "\n");
14015 remove_exit_barriers (root_omp_region);
14016 expand_omp (root_omp_region);
14018 free_omp_regions ();
14021 /* Scan the CFG and build a tree of OMP regions. Return the root of
14022 the OMP region tree. */
14024 static void
14025 build_omp_regions (void)
14027 gcc_assert (root_omp_region == NULL);
14028 calculate_dominance_info (CDI_DOMINATORS);
14029 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14032 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14034 static unsigned int
14035 execute_expand_omp (void)
14037 build_omp_regions ();
14039 if (!root_omp_region)
14040 return 0;
14042 if (dump_file)
14044 fprintf (dump_file, "\nOMP region tree\n\n");
14045 dump_omp_region (dump_file, root_omp_region, 0);
14046 fprintf (dump_file, "\n");
14049 remove_exit_barriers (root_omp_region);
14051 expand_omp (root_omp_region);
14053 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14054 verify_loop_structure ();
14055 cleanup_tree_cfg ();
14057 free_omp_regions ();
14059 return 0;
14062 /* OMP expansion -- the default pass, run before creation of SSA form. */
14064 namespace {
14066 const pass_data pass_data_expand_omp =
14068 GIMPLE_PASS, /* type */
14069 "ompexp", /* name */
14070 OPTGROUP_NONE, /* optinfo_flags */
14071 TV_NONE, /* tv_id */
14072 PROP_gimple_any, /* properties_required */
14073 PROP_gimple_eomp, /* properties_provided */
14074 0, /* properties_destroyed */
14075 0, /* todo_flags_start */
14076 0, /* todo_flags_finish */
14079 class pass_expand_omp : public gimple_opt_pass
14081 public:
14082 pass_expand_omp (gcc::context *ctxt)
14083 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14086 /* opt_pass methods: */
14087 virtual unsigned int execute (function *)
14089 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14090 || flag_openmp_simd != 0)
14091 && !seen_error ());
14093 /* This pass always runs, to provide PROP_gimple_eomp.
14094 But often, there is nothing to do. */
14095 if (!gate)
14096 return 0;
14098 return execute_expand_omp ();
14101 }; // class pass_expand_omp
14103 } // anon namespace
14105 gimple_opt_pass *
14106 make_pass_expand_omp (gcc::context *ctxt)
14108 return new pass_expand_omp (ctxt);
14111 namespace {
14113 const pass_data pass_data_expand_omp_ssa =
14115 GIMPLE_PASS, /* type */
14116 "ompexpssa", /* name */
14117 OPTGROUP_NONE, /* optinfo_flags */
14118 TV_NONE, /* tv_id */
14119 PROP_cfg | PROP_ssa, /* properties_required */
14120 PROP_gimple_eomp, /* properties_provided */
14121 0, /* properties_destroyed */
14122 0, /* todo_flags_start */
14123 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14126 class pass_expand_omp_ssa : public gimple_opt_pass
14128 public:
14129 pass_expand_omp_ssa (gcc::context *ctxt)
14130 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14133 /* opt_pass methods: */
14134 virtual bool gate (function *fun)
14136 return !(fun->curr_properties & PROP_gimple_eomp);
14138 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14139 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14141 }; // class pass_expand_omp_ssa
14143 } // anon namespace
14145 gimple_opt_pass *
14146 make_pass_expand_omp_ssa (gcc::context *ctxt)
14148 return new pass_expand_omp_ssa (ctxt);
14151 /* Routines to lower OMP directives into OMP-GIMPLE. */
14153 /* If ctx is a worksharing context inside of a cancellable parallel
14154 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14155 and conditional branch to parallel's cancel_label to handle
14156 cancellation in the implicit barrier. */
14158 static void
14159 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14161 gimple *omp_return = gimple_seq_last_stmt (*body);
14162 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14163 if (gimple_omp_return_nowait_p (omp_return))
14164 return;
14165 if (ctx->outer
14166 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14167 && ctx->outer->cancellable)
14169 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14170 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14171 tree lhs = create_tmp_var (c_bool_type);
14172 gimple_omp_return_set_lhs (omp_return, lhs);
14173 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14174 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14175 fold_convert (c_bool_type,
14176 boolean_false_node),
14177 ctx->outer->cancel_label, fallthru_label);
14178 gimple_seq_add_stmt (body, g);
14179 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14183 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14184 CTX is the enclosing OMP context for the current statement. */
14186 static void
14187 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14189 tree block, control;
14190 gimple_stmt_iterator tgsi;
14191 gomp_sections *stmt;
14192 gimple *t;
14193 gbind *new_stmt, *bind;
14194 gimple_seq ilist, dlist, olist, new_body;
14196 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14198 push_gimplify_context ();
14200 dlist = NULL;
14201 ilist = NULL;
14202 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14203 &ilist, &dlist, ctx, NULL);
14205 new_body = gimple_omp_body (stmt);
14206 gimple_omp_set_body (stmt, NULL);
14207 tgsi = gsi_start (new_body);
14208 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14210 omp_context *sctx;
14211 gimple *sec_start;
14213 sec_start = gsi_stmt (tgsi);
14214 sctx = maybe_lookup_ctx (sec_start);
14215 gcc_assert (sctx);
14217 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14218 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14219 GSI_CONTINUE_LINKING);
14220 gimple_omp_set_body (sec_start, NULL);
14222 if (gsi_one_before_end_p (tgsi))
14224 gimple_seq l = NULL;
14225 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14226 &l, ctx);
14227 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14228 gimple_omp_section_set_last (sec_start);
14231 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14232 GSI_CONTINUE_LINKING);
14235 block = make_node (BLOCK);
14236 bind = gimple_build_bind (NULL, new_body, block);
14238 olist = NULL;
14239 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14241 block = make_node (BLOCK);
14242 new_stmt = gimple_build_bind (NULL, NULL, block);
14243 gsi_replace (gsi_p, new_stmt, true);
14245 pop_gimplify_context (new_stmt);
14246 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14247 BLOCK_VARS (block) = gimple_bind_vars (bind);
14248 if (BLOCK_VARS (block))
14249 TREE_USED (block) = 1;
14251 new_body = NULL;
14252 gimple_seq_add_seq (&new_body, ilist);
14253 gimple_seq_add_stmt (&new_body, stmt);
14254 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14255 gimple_seq_add_stmt (&new_body, bind);
14257 control = create_tmp_var (unsigned_type_node, ".section");
14258 t = gimple_build_omp_continue (control, control);
14259 gimple_omp_sections_set_control (stmt, control);
14260 gimple_seq_add_stmt (&new_body, t);
14262 gimple_seq_add_seq (&new_body, olist);
14263 if (ctx->cancellable)
14264 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14265 gimple_seq_add_seq (&new_body, dlist);
14267 new_body = maybe_catch_exception (new_body);
14269 t = gimple_build_omp_return
14270 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14271 OMP_CLAUSE_NOWAIT));
14272 gimple_seq_add_stmt (&new_body, t);
14273 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14275 gimple_bind_set_body (new_stmt, new_body);
14279 /* A subroutine of lower_omp_single. Expand the simple form of
14280 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14282 if (GOMP_single_start ())
14283 BODY;
14284 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14286 FIXME. It may be better to delay expanding the logic of this until
14287 pass_expand_omp. The expanded logic may make the job more difficult
14288 to a synchronization analysis pass. */
14290 static void
14291 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14293 location_t loc = gimple_location (single_stmt);
14294 tree tlabel = create_artificial_label (loc);
14295 tree flabel = create_artificial_label (loc);
14296 gimple *call, *cond;
14297 tree lhs, decl;
14299 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14300 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14301 call = gimple_build_call (decl, 0);
14302 gimple_call_set_lhs (call, lhs);
14303 gimple_seq_add_stmt (pre_p, call);
14305 cond = gimple_build_cond (EQ_EXPR, lhs,
14306 fold_convert_loc (loc, TREE_TYPE (lhs),
14307 boolean_true_node),
14308 tlabel, flabel);
14309 gimple_seq_add_stmt (pre_p, cond);
14310 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14311 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14312 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14316 /* A subroutine of lower_omp_single. Expand the simple form of
14317 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14319 #pragma omp single copyprivate (a, b, c)
14321 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14324 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14326 BODY;
14327 copyout.a = a;
14328 copyout.b = b;
14329 copyout.c = c;
14330 GOMP_single_copy_end (&copyout);
14332 else
14334 a = copyout_p->a;
14335 b = copyout_p->b;
14336 c = copyout_p->c;
14338 GOMP_barrier ();
14341 FIXME. It may be better to delay expanding the logic of this until
14342 pass_expand_omp. The expanded logic may make the job more difficult
14343 to a synchronization analysis pass. */
14345 static void
14346 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14347 omp_context *ctx)
14349 tree ptr_type, t, l0, l1, l2, bfn_decl;
14350 gimple_seq copyin_seq;
14351 location_t loc = gimple_location (single_stmt);
14353 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14355 ptr_type = build_pointer_type (ctx->record_type);
14356 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14358 l0 = create_artificial_label (loc);
14359 l1 = create_artificial_label (loc);
14360 l2 = create_artificial_label (loc);
14362 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14363 t = build_call_expr_loc (loc, bfn_decl, 0);
14364 t = fold_convert_loc (loc, ptr_type, t);
14365 gimplify_assign (ctx->receiver_decl, t, pre_p);
14367 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14368 build_int_cst (ptr_type, 0));
14369 t = build3 (COND_EXPR, void_type_node, t,
14370 build_and_jump (&l0), build_and_jump (&l1));
14371 gimplify_and_add (t, pre_p);
14373 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14375 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14377 copyin_seq = NULL;
14378 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14379 &copyin_seq, ctx);
14381 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14382 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14383 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14384 gimplify_and_add (t, pre_p);
14386 t = build_and_jump (&l2);
14387 gimplify_and_add (t, pre_p);
14389 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14391 gimple_seq_add_seq (pre_p, copyin_seq);
14393 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14397 /* Expand code for an OpenMP single directive. */
14399 static void
14400 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14402 tree block;
14403 gimple *t;
14404 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14405 gbind *bind;
14406 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14408 push_gimplify_context ();
14410 block = make_node (BLOCK);
14411 bind = gimple_build_bind (NULL, NULL, block);
14412 gsi_replace (gsi_p, bind, true);
14413 bind_body = NULL;
14414 dlist = NULL;
14415 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14416 &bind_body, &dlist, ctx, NULL);
14417 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14419 gimple_seq_add_stmt (&bind_body, single_stmt);
14421 if (ctx->record_type)
14422 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14423 else
14424 lower_omp_single_simple (single_stmt, &bind_body);
14426 gimple_omp_set_body (single_stmt, NULL);
14428 gimple_seq_add_seq (&bind_body, dlist);
14430 bind_body = maybe_catch_exception (bind_body);
14432 t = gimple_build_omp_return
14433 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14434 OMP_CLAUSE_NOWAIT));
14435 gimple_seq_add_stmt (&bind_body_tail, t);
14436 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14437 if (ctx->record_type)
14439 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14440 tree clobber = build_constructor (ctx->record_type, NULL);
14441 TREE_THIS_VOLATILE (clobber) = 1;
14442 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14443 clobber), GSI_SAME_STMT);
14445 gimple_seq_add_seq (&bind_body, bind_body_tail);
14446 gimple_bind_set_body (bind, bind_body);
14448 pop_gimplify_context (bind);
14450 gimple_bind_append_vars (bind, ctx->block_vars);
14451 BLOCK_VARS (block) = ctx->block_vars;
14452 if (BLOCK_VARS (block))
14453 TREE_USED (block) = 1;
14457 /* Expand code for an OpenMP master directive. */
14459 static void
14460 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14462 tree block, lab = NULL, x, bfn_decl;
14463 gimple *stmt = gsi_stmt (*gsi_p);
14464 gbind *bind;
14465 location_t loc = gimple_location (stmt);
14466 gimple_seq tseq;
14468 push_gimplify_context ();
14470 block = make_node (BLOCK);
14471 bind = gimple_build_bind (NULL, NULL, block);
14472 gsi_replace (gsi_p, bind, true);
14473 gimple_bind_add_stmt (bind, stmt);
14475 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14476 x = build_call_expr_loc (loc, bfn_decl, 0);
14477 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14478 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14479 tseq = NULL;
14480 gimplify_and_add (x, &tseq);
14481 gimple_bind_add_seq (bind, tseq);
14483 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14484 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14485 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14486 gimple_omp_set_body (stmt, NULL);
14488 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14490 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14492 pop_gimplify_context (bind);
14494 gimple_bind_append_vars (bind, ctx->block_vars);
14495 BLOCK_VARS (block) = ctx->block_vars;
14499 /* Expand code for an OpenMP taskgroup directive. */
14501 static void
14502 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14504 gimple *stmt = gsi_stmt (*gsi_p);
14505 gcall *x;
14506 gbind *bind;
14507 tree block = make_node (BLOCK);
14509 bind = gimple_build_bind (NULL, NULL, block);
14510 gsi_replace (gsi_p, bind, true);
14511 gimple_bind_add_stmt (bind, stmt);
14513 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14515 gimple_bind_add_stmt (bind, x);
14517 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14518 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14519 gimple_omp_set_body (stmt, NULL);
14521 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14523 gimple_bind_append_vars (bind, ctx->block_vars);
14524 BLOCK_VARS (block) = ctx->block_vars;
14528 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14530 static void
14531 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14532 omp_context *ctx)
14534 struct omp_for_data fd;
14535 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14536 return;
14538 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14539 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14540 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14541 if (!fd.ordered)
14542 return;
14544 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14545 tree c = gimple_omp_ordered_clauses (ord_stmt);
14546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14547 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14549 /* Merge depend clauses from multiple adjacent
14550 #pragma omp ordered depend(sink:...) constructs
14551 into one #pragma omp ordered depend(sink:...), so that
14552 we can optimize them together. */
14553 gimple_stmt_iterator gsi = *gsi_p;
14554 gsi_next (&gsi);
14555 while (!gsi_end_p (gsi))
14557 gimple *stmt = gsi_stmt (gsi);
14558 if (is_gimple_debug (stmt)
14559 || gimple_code (stmt) == GIMPLE_NOP)
14561 gsi_next (&gsi);
14562 continue;
14564 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14565 break;
14566 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14567 c = gimple_omp_ordered_clauses (ord_stmt2);
14568 if (c == NULL_TREE
14569 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14570 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14571 break;
14572 while (*list_p)
14573 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14574 *list_p = c;
14575 gsi_remove (&gsi, true);
14579 /* Canonicalize sink dependence clauses into one folded clause if
14580 possible.
14582 The basic algorithm is to create a sink vector whose first
14583 element is the GCD of all the first elements, and whose remaining
14584 elements are the minimum of the subsequent columns.
14586 We ignore dependence vectors whose first element is zero because
14587 such dependencies are known to be executed by the same thread.
14589 We take into account the direction of the loop, so a minimum
14590 becomes a maximum if the loop is iterating forwards. We also
14591 ignore sink clauses where the loop direction is unknown, or where
14592 the offsets are clearly invalid because they are not a multiple
14593 of the loop increment.
14595 For example:
14597 #pragma omp for ordered(2)
14598 for (i=0; i < N; ++i)
14599 for (j=0; j < M; ++j)
14601 #pragma omp ordered \
14602 depend(sink:i-8,j-2) \
14603 depend(sink:i,j-1) \ // Completely ignored because i+0.
14604 depend(sink:i-4,j-3) \
14605 depend(sink:i-6,j-4)
14606 #pragma omp ordered depend(source)
14609 Folded clause is:
14611 depend(sink:-gcd(8,4,6),-min(2,3,4))
14612 -or-
14613 depend(sink:-2,-2)
14616 /* FIXME: Computing GCD's where the first element is zero is
14617 non-trivial in the presence of collapsed loops. Do this later. */
14618 if (fd.collapse > 1)
14619 return;
14621 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14622 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14623 tree folded_dep = NULL_TREE;
14624 /* TRUE if the first dimension's offset is negative. */
14625 bool neg_offset_p = false;
14627 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14628 unsigned int i;
14629 while ((c = *list_p) != NULL)
14631 bool remove = false;
14633 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14634 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14635 goto next_ordered_clause;
14637 tree vec;
14638 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14639 vec && TREE_CODE (vec) == TREE_LIST;
14640 vec = TREE_CHAIN (vec), ++i)
14642 gcc_assert (i < len);
14644 /* extract_omp_for_data has canonicalized the condition. */
14645 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14646 || fd.loops[i].cond_code == GT_EXPR);
14647 bool forward = fd.loops[i].cond_code == LT_EXPR;
14648 bool maybe_lexically_later = true;
14650 /* While the committee makes up its mind, bail if we have any
14651 non-constant steps. */
14652 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14653 goto lower_omp_ordered_ret;
14655 tree itype = TREE_TYPE (TREE_VALUE (vec));
14656 if (POINTER_TYPE_P (itype))
14657 itype = sizetype;
14658 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14659 TYPE_PRECISION (itype),
14660 TYPE_SIGN (itype));
14662 /* Ignore invalid offsets that are not multiples of the step. */
14663 if (!wi::multiple_of_p
14664 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14665 UNSIGNED))
14667 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14668 "ignoring sink clause with offset that is not "
14669 "a multiple of the loop step");
14670 remove = true;
14671 goto next_ordered_clause;
14674 /* Calculate the first dimension. The first dimension of
14675 the folded dependency vector is the GCD of the first
14676 elements, while ignoring any first elements whose offset
14677 is 0. */
14678 if (i == 0)
14680 /* Ignore dependence vectors whose first dimension is 0. */
14681 if (offset == 0)
14683 remove = true;
14684 goto next_ordered_clause;
14686 else
14688 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14690 error_at (OMP_CLAUSE_LOCATION (c),
14691 "first offset must be in opposite direction "
14692 "of loop iterations");
14693 goto lower_omp_ordered_ret;
14695 if (forward)
14696 offset = -offset;
14697 neg_offset_p = forward;
14698 /* Initialize the first time around. */
14699 if (folded_dep == NULL_TREE)
14701 folded_dep = c;
14702 folded_deps[0] = offset;
14704 else
14705 folded_deps[0] = wi::gcd (folded_deps[0],
14706 offset, UNSIGNED);
14709 /* Calculate minimum for the remaining dimensions. */
14710 else
14712 folded_deps[len + i - 1] = offset;
14713 if (folded_dep == c)
14714 folded_deps[i] = offset;
14715 else if (maybe_lexically_later
14716 && !wi::eq_p (folded_deps[i], offset))
14718 if (forward ^ wi::gts_p (folded_deps[i], offset))
14720 unsigned int j;
14721 folded_dep = c;
14722 for (j = 1; j <= i; j++)
14723 folded_deps[j] = folded_deps[len + j - 1];
14725 else
14726 maybe_lexically_later = false;
14730 gcc_assert (i == len);
14732 remove = true;
14734 next_ordered_clause:
14735 if (remove)
14736 *list_p = OMP_CLAUSE_CHAIN (c);
14737 else
14738 list_p = &OMP_CLAUSE_CHAIN (c);
14741 if (folded_dep)
14743 if (neg_offset_p)
14744 folded_deps[0] = -folded_deps[0];
14746 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14747 if (POINTER_TYPE_P (itype))
14748 itype = sizetype;
14750 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14751 = wide_int_to_tree (itype, folded_deps[0]);
14752 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14753 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14756 lower_omp_ordered_ret:
14758 /* Ordered without clauses is #pragma omp threads, while we want
14759 a nop instead if we remove all clauses. */
14760 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14761 gsi_replace (gsi_p, gimple_build_nop (), true);
14765 /* Expand code for an OpenMP ordered directive. */
14767 static void
14768 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14770 tree block;
14771 gimple *stmt = gsi_stmt (*gsi_p);
14772 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14773 gcall *x;
14774 gbind *bind;
14775 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14776 OMP_CLAUSE_SIMD);
14777 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14778 OMP_CLAUSE_THREADS);
14780 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14781 OMP_CLAUSE_DEPEND))
14783 /* FIXME: This is needs to be moved to the expansion to verify various
14784 conditions only testable on cfg with dominators computed, and also
14785 all the depend clauses to be merged still might need to be available
14786 for the runtime checks. */
14787 if (0)
14788 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14789 return;
14792 push_gimplify_context ();
14794 block = make_node (BLOCK);
14795 bind = gimple_build_bind (NULL, NULL, block);
14796 gsi_replace (gsi_p, bind, true);
14797 gimple_bind_add_stmt (bind, stmt);
14799 if (simd)
14801 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14802 build_int_cst (NULL_TREE, threads));
14803 cfun->has_simduid_loops = true;
14805 else
14806 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14808 gimple_bind_add_stmt (bind, x);
14810 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14811 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14812 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14813 gimple_omp_set_body (stmt, NULL);
14815 if (simd)
14816 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14817 build_int_cst (NULL_TREE, threads));
14818 else
14819 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14821 gimple_bind_add_stmt (bind, x);
14823 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14825 pop_gimplify_context (bind);
14827 gimple_bind_append_vars (bind, ctx->block_vars);
14828 BLOCK_VARS (block) = gimple_bind_vars (bind);
14832 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14833 substitution of a couple of function calls. But in the NAMED case,
14834 requires that languages coordinate a symbol name. It is therefore
14835 best put here in common code. */
14837 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14839 static void
14840 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14842 tree block;
14843 tree name, lock, unlock;
14844 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14845 gbind *bind;
14846 location_t loc = gimple_location (stmt);
14847 gimple_seq tbody;
14849 name = gimple_omp_critical_name (stmt);
14850 if (name)
14852 tree decl;
14854 if (!critical_name_mutexes)
14855 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14857 tree *n = critical_name_mutexes->get (name);
14858 if (n == NULL)
14860 char *new_str;
14862 decl = create_tmp_var_raw (ptr_type_node);
14864 new_str = ACONCAT ((".gomp_critical_user_",
14865 IDENTIFIER_POINTER (name), NULL));
14866 DECL_NAME (decl) = get_identifier (new_str);
14867 TREE_PUBLIC (decl) = 1;
14868 TREE_STATIC (decl) = 1;
14869 DECL_COMMON (decl) = 1;
14870 DECL_ARTIFICIAL (decl) = 1;
14871 DECL_IGNORED_P (decl) = 1;
14873 varpool_node::finalize_decl (decl);
14875 critical_name_mutexes->put (name, decl);
14877 else
14878 decl = *n;
14880 /* If '#pragma omp critical' is inside offloaded region or
14881 inside function marked as offloadable, the symbol must be
14882 marked as offloadable too. */
14883 omp_context *octx;
14884 if (cgraph_node::get (current_function_decl)->offloadable)
14885 varpool_node::get_create (decl)->offloadable = 1;
14886 else
14887 for (octx = ctx->outer; octx; octx = octx->outer)
14888 if (is_gimple_omp_offloaded (octx->stmt))
14890 varpool_node::get_create (decl)->offloadable = 1;
14891 break;
14894 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14895 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14897 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14898 unlock = build_call_expr_loc (loc, unlock, 1,
14899 build_fold_addr_expr_loc (loc, decl));
14901 else
14903 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14904 lock = build_call_expr_loc (loc, lock, 0);
14906 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14907 unlock = build_call_expr_loc (loc, unlock, 0);
14910 push_gimplify_context ();
14912 block = make_node (BLOCK);
14913 bind = gimple_build_bind (NULL, NULL, block);
14914 gsi_replace (gsi_p, bind, true);
14915 gimple_bind_add_stmt (bind, stmt);
14917 tbody = gimple_bind_body (bind);
14918 gimplify_and_add (lock, &tbody);
14919 gimple_bind_set_body (bind, tbody);
14921 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14922 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14923 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14924 gimple_omp_set_body (stmt, NULL);
14926 tbody = gimple_bind_body (bind);
14927 gimplify_and_add (unlock, &tbody);
14928 gimple_bind_set_body (bind, tbody);
14930 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14932 pop_gimplify_context (bind);
14933 gimple_bind_append_vars (bind, ctx->block_vars);
14934 BLOCK_VARS (block) = gimple_bind_vars (bind);
14938 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14939 for a lastprivate clause. Given a loop control predicate of (V
14940 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14941 is appended to *DLIST, iterator initialization is appended to
14942 *BODY_P. */
14944 static void
14945 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14946 gimple_seq *dlist, struct omp_context *ctx)
14948 tree clauses, cond, vinit;
14949 enum tree_code cond_code;
14950 gimple_seq stmts;
14952 cond_code = fd->loop.cond_code;
14953 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14955 /* When possible, use a strict equality expression. This can let VRP
14956 type optimizations deduce the value and remove a copy. */
14957 if (tree_fits_shwi_p (fd->loop.step))
14959 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14960 if (step == 1 || step == -1)
14961 cond_code = EQ_EXPR;
14964 tree n2 = fd->loop.n2;
14965 if (fd->collapse > 1
14966 && TREE_CODE (n2) != INTEGER_CST
14967 && gimple_omp_for_combined_into_p (fd->for_stmt))
14969 struct omp_context *taskreg_ctx = NULL;
14970 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14972 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14973 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14974 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14976 if (gimple_omp_for_combined_into_p (gfor))
14978 gcc_assert (ctx->outer->outer
14979 && is_parallel_ctx (ctx->outer->outer));
14980 taskreg_ctx = ctx->outer->outer;
14982 else
14984 struct omp_for_data outer_fd;
14985 extract_omp_for_data (gfor, &outer_fd, NULL);
14986 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14989 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14990 taskreg_ctx = ctx->outer->outer;
14992 else if (is_taskreg_ctx (ctx->outer))
14993 taskreg_ctx = ctx->outer;
14994 if (taskreg_ctx)
14996 int i;
14997 tree innerc
14998 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14999 OMP_CLAUSE__LOOPTEMP_);
15000 gcc_assert (innerc);
15001 for (i = 0; i < fd->collapse; i++)
15003 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15004 OMP_CLAUSE__LOOPTEMP_);
15005 gcc_assert (innerc);
15007 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15008 OMP_CLAUSE__LOOPTEMP_);
15009 if (innerc)
15010 n2 = fold_convert (TREE_TYPE (n2),
15011 lookup_decl (OMP_CLAUSE_DECL (innerc),
15012 taskreg_ctx));
15015 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
15017 clauses = gimple_omp_for_clauses (fd->for_stmt);
15018 stmts = NULL;
15019 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
15020 if (!gimple_seq_empty_p (stmts))
15022 gimple_seq_add_seq (&stmts, *dlist);
15023 *dlist = stmts;
15025 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
15026 vinit = fd->loop.n1;
15027 if (cond_code == EQ_EXPR
15028 && tree_fits_shwi_p (fd->loop.n2)
15029 && ! integer_zerop (fd->loop.n2))
15030 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15031 else
15032 vinit = unshare_expr (vinit);
15034 /* Initialize the iterator variable, so that threads that don't execute
15035 any iterations don't execute the lastprivate clauses by accident. */
15036 gimplify_assign (fd->loop.v, vinit, body_p);
15041 /* Lower code for an OMP loop directive. */
15043 static void
15044 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15046 tree *rhs_p, block;
15047 struct omp_for_data fd, *fdp = NULL;
15048 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15049 gbind *new_stmt;
15050 gimple_seq omp_for_body, body, dlist;
15051 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15052 size_t i;
15054 push_gimplify_context ();
15056 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15058 block = make_node (BLOCK);
15059 new_stmt = gimple_build_bind (NULL, NULL, block);
15060 /* Replace at gsi right away, so that 'stmt' is no member
15061 of a sequence anymore as we're going to add to a different
15062 one below. */
15063 gsi_replace (gsi_p, new_stmt, true);
15065 /* Move declaration of temporaries in the loop body before we make
15066 it go away. */
15067 omp_for_body = gimple_omp_body (stmt);
15068 if (!gimple_seq_empty_p (omp_for_body)
15069 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15071 gbind *inner_bind
15072 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15073 tree vars = gimple_bind_vars (inner_bind);
15074 gimple_bind_append_vars (new_stmt, vars);
15075 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15076 keep them on the inner_bind and it's block. */
15077 gimple_bind_set_vars (inner_bind, NULL_TREE);
15078 if (gimple_bind_block (inner_bind))
15079 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15082 if (gimple_omp_for_combined_into_p (stmt))
15084 extract_omp_for_data (stmt, &fd, NULL);
15085 fdp = &fd;
15087 /* We need two temporaries with fd.loop.v type (istart/iend)
15088 and then (fd.collapse - 1) temporaries with the same
15089 type for count2 ... countN-1 vars if not constant. */
15090 size_t count = 2;
15091 tree type = fd.iter_type;
15092 if (fd.collapse > 1
15093 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15094 count += fd.collapse - 1;
15095 bool taskreg_for
15096 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15097 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15098 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15099 tree clauses = *pc;
15100 if (taskreg_for)
15101 outerc
15102 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15103 OMP_CLAUSE__LOOPTEMP_);
15104 for (i = 0; i < count; i++)
15106 tree temp;
15107 if (taskreg_for)
15109 gcc_assert (outerc);
15110 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15111 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15112 OMP_CLAUSE__LOOPTEMP_);
15114 else
15116 temp = create_tmp_var (type);
15117 insert_decl_map (&ctx->outer->cb, temp, temp);
15119 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15120 OMP_CLAUSE_DECL (*pc) = temp;
15121 pc = &OMP_CLAUSE_CHAIN (*pc);
15123 *pc = clauses;
15126 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15127 dlist = NULL;
15128 body = NULL;
15129 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15130 fdp);
15131 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15133 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15135 /* Lower the header expressions. At this point, we can assume that
15136 the header is of the form:
15138 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15140 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15141 using the .omp_data_s mapping, if needed. */
15142 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15144 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15145 if (!is_gimple_min_invariant (*rhs_p))
15146 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15148 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15149 if (!is_gimple_min_invariant (*rhs_p))
15150 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15152 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15153 if (!is_gimple_min_invariant (*rhs_p))
15154 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15157 /* Once lowered, extract the bounds and clauses. */
15158 extract_omp_for_data (stmt, &fd, NULL);
15160 if (is_gimple_omp_oacc (ctx->stmt)
15161 && !ctx_in_oacc_kernels_region (ctx))
15162 lower_oacc_head_tail (gimple_location (stmt),
15163 gimple_omp_for_clauses (stmt),
15164 &oacc_head, &oacc_tail, ctx);
15166 /* Add OpenACC partitioning and reduction markers just before the loop */
15167 if (oacc_head)
15168 gimple_seq_add_seq (&body, oacc_head);
15170 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15172 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15173 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15174 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15175 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15177 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15178 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15179 OMP_CLAUSE_LINEAR_STEP (c)
15180 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15181 ctx);
15184 if (!gimple_omp_for_grid_phony (stmt))
15185 gimple_seq_add_stmt (&body, stmt);
15186 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15188 if (!gimple_omp_for_grid_phony (stmt))
15189 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15190 fd.loop.v));
15192 /* After the loop, add exit clauses. */
15193 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15195 if (ctx->cancellable)
15196 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15198 gimple_seq_add_seq (&body, dlist);
15200 body = maybe_catch_exception (body);
15202 if (!gimple_omp_for_grid_phony (stmt))
15204 /* Region exit marker goes at the end of the loop body. */
15205 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15206 maybe_add_implicit_barrier_cancel (ctx, &body);
15209 /* Add OpenACC joining and reduction markers just after the loop. */
15210 if (oacc_tail)
15211 gimple_seq_add_seq (&body, oacc_tail);
15213 pop_gimplify_context (new_stmt);
15215 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15216 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15217 if (BLOCK_VARS (block))
15218 TREE_USED (block) = 1;
15220 gimple_bind_set_body (new_stmt, body);
15221 gimple_omp_set_body (stmt, NULL);
15222 gimple_omp_for_set_pre_body (stmt, NULL);
15225 /* Callback for walk_stmts. Check if the current statement only contains
15226 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15228 static tree
15229 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15230 bool *handled_ops_p,
15231 struct walk_stmt_info *wi)
15233 int *info = (int *) wi->info;
15234 gimple *stmt = gsi_stmt (*gsi_p);
15236 *handled_ops_p = true;
15237 switch (gimple_code (stmt))
15239 WALK_SUBSTMTS;
15241 case GIMPLE_OMP_FOR:
15242 case GIMPLE_OMP_SECTIONS:
15243 *info = *info == 0 ? 1 : -1;
15244 break;
15245 default:
15246 *info = -1;
15247 break;
15249 return NULL;
15252 struct omp_taskcopy_context
15254 /* This field must be at the beginning, as we do "inheritance": Some
15255 callback functions for tree-inline.c (e.g., omp_copy_decl)
15256 receive a copy_body_data pointer that is up-casted to an
15257 omp_context pointer. */
15258 copy_body_data cb;
15259 omp_context *ctx;
15262 static tree
15263 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15265 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15267 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15268 return create_tmp_var (TREE_TYPE (var));
15270 return var;
15273 static tree
15274 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15276 tree name, new_fields = NULL, type, f;
15278 type = lang_hooks.types.make_type (RECORD_TYPE);
15279 name = DECL_NAME (TYPE_NAME (orig_type));
15280 name = build_decl (gimple_location (tcctx->ctx->stmt),
15281 TYPE_DECL, name, type);
15282 TYPE_NAME (type) = name;
15284 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15286 tree new_f = copy_node (f);
15287 DECL_CONTEXT (new_f) = type;
15288 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15289 TREE_CHAIN (new_f) = new_fields;
15290 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15291 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15292 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15293 &tcctx->cb, NULL);
15294 new_fields = new_f;
15295 tcctx->cb.decl_map->put (f, new_f);
15297 TYPE_FIELDS (type) = nreverse (new_fields);
15298 layout_type (type);
15299 return type;
15302 /* Create task copyfn. */
15304 static void
15305 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15307 struct function *child_cfun;
15308 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15309 tree record_type, srecord_type, bind, list;
15310 bool record_needs_remap = false, srecord_needs_remap = false;
15311 splay_tree_node n;
15312 struct omp_taskcopy_context tcctx;
15313 location_t loc = gimple_location (task_stmt);
15315 child_fn = gimple_omp_task_copy_fn (task_stmt);
15316 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15317 gcc_assert (child_cfun->cfg == NULL);
15318 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15320 /* Reset DECL_CONTEXT on function arguments. */
15321 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15322 DECL_CONTEXT (t) = child_fn;
15324 /* Populate the function. */
15325 push_gimplify_context ();
15326 push_cfun (child_cfun);
15328 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15329 TREE_SIDE_EFFECTS (bind) = 1;
15330 list = NULL;
15331 DECL_SAVED_TREE (child_fn) = bind;
15332 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15334 /* Remap src and dst argument types if needed. */
15335 record_type = ctx->record_type;
15336 srecord_type = ctx->srecord_type;
15337 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15338 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15340 record_needs_remap = true;
15341 break;
15343 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15344 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15346 srecord_needs_remap = true;
15347 break;
15350 if (record_needs_remap || srecord_needs_remap)
15352 memset (&tcctx, '\0', sizeof (tcctx));
15353 tcctx.cb.src_fn = ctx->cb.src_fn;
15354 tcctx.cb.dst_fn = child_fn;
15355 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15356 gcc_checking_assert (tcctx.cb.src_node);
15357 tcctx.cb.dst_node = tcctx.cb.src_node;
15358 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15359 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15360 tcctx.cb.eh_lp_nr = 0;
15361 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15362 tcctx.cb.decl_map = new hash_map<tree, tree>;
15363 tcctx.ctx = ctx;
15365 if (record_needs_remap)
15366 record_type = task_copyfn_remap_type (&tcctx, record_type);
15367 if (srecord_needs_remap)
15368 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15370 else
15371 tcctx.cb.decl_map = NULL;
15373 arg = DECL_ARGUMENTS (child_fn);
15374 TREE_TYPE (arg) = build_pointer_type (record_type);
15375 sarg = DECL_CHAIN (arg);
15376 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15378 /* First pass: initialize temporaries used in record_type and srecord_type
15379 sizes and field offsets. */
15380 if (tcctx.cb.decl_map)
15381 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15384 tree *p;
15386 decl = OMP_CLAUSE_DECL (c);
15387 p = tcctx.cb.decl_map->get (decl);
15388 if (p == NULL)
15389 continue;
15390 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15391 sf = (tree) n->value;
15392 sf = *tcctx.cb.decl_map->get (sf);
15393 src = build_simple_mem_ref_loc (loc, sarg);
15394 src = omp_build_component_ref (src, sf);
15395 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15396 append_to_statement_list (t, &list);
15399 /* Second pass: copy shared var pointers and copy construct non-VLA
15400 firstprivate vars. */
15401 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15402 switch (OMP_CLAUSE_CODE (c))
15404 splay_tree_key key;
15405 case OMP_CLAUSE_SHARED:
15406 decl = OMP_CLAUSE_DECL (c);
15407 key = (splay_tree_key) decl;
15408 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15409 key = (splay_tree_key) &DECL_UID (decl);
15410 n = splay_tree_lookup (ctx->field_map, key);
15411 if (n == NULL)
15412 break;
15413 f = (tree) n->value;
15414 if (tcctx.cb.decl_map)
15415 f = *tcctx.cb.decl_map->get (f);
15416 n = splay_tree_lookup (ctx->sfield_map, key);
15417 sf = (tree) n->value;
15418 if (tcctx.cb.decl_map)
15419 sf = *tcctx.cb.decl_map->get (sf);
15420 src = build_simple_mem_ref_loc (loc, sarg);
15421 src = omp_build_component_ref (src, sf);
15422 dst = build_simple_mem_ref_loc (loc, arg);
15423 dst = omp_build_component_ref (dst, f);
15424 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15425 append_to_statement_list (t, &list);
15426 break;
15427 case OMP_CLAUSE_FIRSTPRIVATE:
15428 decl = OMP_CLAUSE_DECL (c);
15429 if (is_variable_sized (decl))
15430 break;
15431 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15432 if (n == NULL)
15433 break;
15434 f = (tree) n->value;
15435 if (tcctx.cb.decl_map)
15436 f = *tcctx.cb.decl_map->get (f);
15437 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15438 if (n != NULL)
15440 sf = (tree) n->value;
15441 if (tcctx.cb.decl_map)
15442 sf = *tcctx.cb.decl_map->get (sf);
15443 src = build_simple_mem_ref_loc (loc, sarg);
15444 src = omp_build_component_ref (src, sf);
15445 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15446 src = build_simple_mem_ref_loc (loc, src);
15448 else
15449 src = decl;
15450 dst = build_simple_mem_ref_loc (loc, arg);
15451 dst = omp_build_component_ref (dst, f);
15452 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15453 append_to_statement_list (t, &list);
15454 break;
15455 case OMP_CLAUSE_PRIVATE:
15456 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15457 break;
15458 decl = OMP_CLAUSE_DECL (c);
15459 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15460 f = (tree) n->value;
15461 if (tcctx.cb.decl_map)
15462 f = *tcctx.cb.decl_map->get (f);
15463 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15464 if (n != NULL)
15466 sf = (tree) n->value;
15467 if (tcctx.cb.decl_map)
15468 sf = *tcctx.cb.decl_map->get (sf);
15469 src = build_simple_mem_ref_loc (loc, sarg);
15470 src = omp_build_component_ref (src, sf);
15471 if (use_pointer_for_field (decl, NULL))
15472 src = build_simple_mem_ref_loc (loc, src);
15474 else
15475 src = decl;
15476 dst = build_simple_mem_ref_loc (loc, arg);
15477 dst = omp_build_component_ref (dst, f);
15478 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15479 append_to_statement_list (t, &list);
15480 break;
15481 default:
15482 break;
15485 /* Last pass: handle VLA firstprivates. */
15486 if (tcctx.cb.decl_map)
15487 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15488 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15490 tree ind, ptr, df;
15492 decl = OMP_CLAUSE_DECL (c);
15493 if (!is_variable_sized (decl))
15494 continue;
15495 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15496 if (n == NULL)
15497 continue;
15498 f = (tree) n->value;
15499 f = *tcctx.cb.decl_map->get (f);
15500 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15501 ind = DECL_VALUE_EXPR (decl);
15502 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15503 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15504 n = splay_tree_lookup (ctx->sfield_map,
15505 (splay_tree_key) TREE_OPERAND (ind, 0));
15506 sf = (tree) n->value;
15507 sf = *tcctx.cb.decl_map->get (sf);
15508 src = build_simple_mem_ref_loc (loc, sarg);
15509 src = omp_build_component_ref (src, sf);
15510 src = build_simple_mem_ref_loc (loc, src);
15511 dst = build_simple_mem_ref_loc (loc, arg);
15512 dst = omp_build_component_ref (dst, f);
15513 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15514 append_to_statement_list (t, &list);
15515 n = splay_tree_lookup (ctx->field_map,
15516 (splay_tree_key) TREE_OPERAND (ind, 0));
15517 df = (tree) n->value;
15518 df = *tcctx.cb.decl_map->get (df);
15519 ptr = build_simple_mem_ref_loc (loc, arg);
15520 ptr = omp_build_component_ref (ptr, df);
15521 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15522 build_fold_addr_expr_loc (loc, dst));
15523 append_to_statement_list (t, &list);
15526 t = build1 (RETURN_EXPR, void_type_node, NULL);
15527 append_to_statement_list (t, &list);
15529 if (tcctx.cb.decl_map)
15530 delete tcctx.cb.decl_map;
15531 pop_gimplify_context (NULL);
15532 BIND_EXPR_BODY (bind) = list;
15533 pop_cfun ();
15536 static void
15537 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15539 tree c, clauses;
15540 gimple *g;
15541 size_t n_in = 0, n_out = 0, idx = 2, i;
15543 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15544 gcc_assert (clauses);
15545 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15547 switch (OMP_CLAUSE_DEPEND_KIND (c))
15549 case OMP_CLAUSE_DEPEND_IN:
15550 n_in++;
15551 break;
15552 case OMP_CLAUSE_DEPEND_OUT:
15553 case OMP_CLAUSE_DEPEND_INOUT:
15554 n_out++;
15555 break;
15556 case OMP_CLAUSE_DEPEND_SOURCE:
15557 case OMP_CLAUSE_DEPEND_SINK:
15558 /* FALLTHRU */
15559 default:
15560 gcc_unreachable ();
15562 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15563 tree array = create_tmp_var (type);
15564 TREE_ADDRESSABLE (array) = 1;
15565 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15566 NULL_TREE);
15567 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15568 gimple_seq_add_stmt (iseq, g);
15569 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15570 NULL_TREE);
15571 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15572 gimple_seq_add_stmt (iseq, g);
15573 for (i = 0; i < 2; i++)
15575 if ((i ? n_in : n_out) == 0)
15576 continue;
15577 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15578 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15579 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15581 tree t = OMP_CLAUSE_DECL (c);
15582 t = fold_convert (ptr_type_node, t);
15583 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15584 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15585 NULL_TREE, NULL_TREE);
15586 g = gimple_build_assign (r, t);
15587 gimple_seq_add_stmt (iseq, g);
15590 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15591 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15592 OMP_CLAUSE_CHAIN (c) = *pclauses;
15593 *pclauses = c;
15594 tree clobber = build_constructor (type, NULL);
15595 TREE_THIS_VOLATILE (clobber) = 1;
15596 g = gimple_build_assign (array, clobber);
15597 gimple_seq_add_stmt (oseq, g);
15600 /* Lower the OpenMP parallel or task directive in the current statement
15601 in GSI_P. CTX holds context information for the directive. */
15603 static void
15604 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15606 tree clauses;
15607 tree child_fn, t;
15608 gimple *stmt = gsi_stmt (*gsi_p);
15609 gbind *par_bind, *bind, *dep_bind = NULL;
15610 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15611 location_t loc = gimple_location (stmt);
15613 clauses = gimple_omp_taskreg_clauses (stmt);
15614 par_bind
15615 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15616 par_body = gimple_bind_body (par_bind);
15617 child_fn = ctx->cb.dst_fn;
15618 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15619 && !gimple_omp_parallel_combined_p (stmt))
15621 struct walk_stmt_info wi;
15622 int ws_num = 0;
15624 memset (&wi, 0, sizeof (wi));
15625 wi.info = &ws_num;
15626 wi.val_only = true;
15627 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15628 if (ws_num == 1)
15629 gimple_omp_parallel_set_combined_p (stmt, true);
15631 gimple_seq dep_ilist = NULL;
15632 gimple_seq dep_olist = NULL;
15633 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15634 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15636 push_gimplify_context ();
15637 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15638 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15639 &dep_ilist, &dep_olist);
15642 if (ctx->srecord_type)
15643 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15645 push_gimplify_context ();
15647 par_olist = NULL;
15648 par_ilist = NULL;
15649 par_rlist = NULL;
15650 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15651 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15652 if (phony_construct && ctx->record_type)
15654 gcc_checking_assert (!ctx->receiver_decl);
15655 ctx->receiver_decl = create_tmp_var
15656 (build_reference_type (ctx->record_type), ".omp_rec");
15658 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15659 lower_omp (&par_body, ctx);
15660 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15661 lower_reduction_clauses (clauses, &par_rlist, ctx);
15663 /* Declare all the variables created by mapping and the variables
15664 declared in the scope of the parallel body. */
15665 record_vars_into (ctx->block_vars, child_fn);
15666 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15668 if (ctx->record_type)
15670 ctx->sender_decl
15671 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15672 : ctx->record_type, ".omp_data_o");
15673 DECL_NAMELESS (ctx->sender_decl) = 1;
15674 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15675 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15678 olist = NULL;
15679 ilist = NULL;
15680 lower_send_clauses (clauses, &ilist, &olist, ctx);
15681 lower_send_shared_vars (&ilist, &olist, ctx);
15683 if (ctx->record_type)
15685 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15686 TREE_THIS_VOLATILE (clobber) = 1;
15687 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15688 clobber));
15691 /* Once all the expansions are done, sequence all the different
15692 fragments inside gimple_omp_body. */
15694 new_body = NULL;
15696 if (ctx->record_type)
15698 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15699 /* fixup_child_record_type might have changed receiver_decl's type. */
15700 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15701 gimple_seq_add_stmt (&new_body,
15702 gimple_build_assign (ctx->receiver_decl, t));
15705 gimple_seq_add_seq (&new_body, par_ilist);
15706 gimple_seq_add_seq (&new_body, par_body);
15707 gimple_seq_add_seq (&new_body, par_rlist);
15708 if (ctx->cancellable)
15709 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15710 gimple_seq_add_seq (&new_body, par_olist);
15711 new_body = maybe_catch_exception (new_body);
15712 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15713 gimple_seq_add_stmt (&new_body,
15714 gimple_build_omp_continue (integer_zero_node,
15715 integer_zero_node));
15716 if (!phony_construct)
15718 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15719 gimple_omp_set_body (stmt, new_body);
15722 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15723 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15724 gimple_bind_add_seq (bind, ilist);
15725 if (!phony_construct)
15726 gimple_bind_add_stmt (bind, stmt);
15727 else
15728 gimple_bind_add_seq (bind, new_body);
15729 gimple_bind_add_seq (bind, olist);
15731 pop_gimplify_context (NULL);
15733 if (dep_bind)
15735 gimple_bind_add_seq (dep_bind, dep_ilist);
15736 gimple_bind_add_stmt (dep_bind, bind);
15737 gimple_bind_add_seq (dep_bind, dep_olist);
15738 pop_gimplify_context (dep_bind);
15742 /* Lower the GIMPLE_OMP_TARGET in the current statement
15743 in GSI_P. CTX holds context information for the directive. */
15745 static void
15746 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15748 tree clauses;
15749 tree child_fn, t, c;
15750 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15751 gbind *tgt_bind, *bind, *dep_bind = NULL;
15752 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15753 location_t loc = gimple_location (stmt);
15754 bool offloaded, data_region;
15755 unsigned int map_cnt = 0;
15757 offloaded = is_gimple_omp_offloaded (stmt);
15758 switch (gimple_omp_target_kind (stmt))
15760 case GF_OMP_TARGET_KIND_REGION:
15761 case GF_OMP_TARGET_KIND_UPDATE:
15762 case GF_OMP_TARGET_KIND_ENTER_DATA:
15763 case GF_OMP_TARGET_KIND_EXIT_DATA:
15764 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15765 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15766 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15767 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15768 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15769 data_region = false;
15770 break;
15771 case GF_OMP_TARGET_KIND_DATA:
15772 case GF_OMP_TARGET_KIND_OACC_DATA:
15773 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15774 data_region = true;
15775 break;
15776 default:
15777 gcc_unreachable ();
15780 clauses = gimple_omp_target_clauses (stmt);
15782 gimple_seq dep_ilist = NULL;
15783 gimple_seq dep_olist = NULL;
15784 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15786 push_gimplify_context ();
15787 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15788 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15789 &dep_ilist, &dep_olist);
15792 tgt_bind = NULL;
15793 tgt_body = NULL;
15794 if (offloaded)
15796 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15797 tgt_body = gimple_bind_body (tgt_bind);
15799 else if (data_region)
15800 tgt_body = gimple_omp_body (stmt);
15801 child_fn = ctx->cb.dst_fn;
15803 push_gimplify_context ();
15804 fplist = NULL;
15806 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15807 switch (OMP_CLAUSE_CODE (c))
15809 tree var, x;
15811 default:
15812 break;
15813 case OMP_CLAUSE_MAP:
15814 #if CHECKING_P
15815 /* First check what we're prepared to handle in the following. */
15816 switch (OMP_CLAUSE_MAP_KIND (c))
15818 case GOMP_MAP_ALLOC:
15819 case GOMP_MAP_TO:
15820 case GOMP_MAP_FROM:
15821 case GOMP_MAP_TOFROM:
15822 case GOMP_MAP_POINTER:
15823 case GOMP_MAP_TO_PSET:
15824 case GOMP_MAP_DELETE:
15825 case GOMP_MAP_RELEASE:
15826 case GOMP_MAP_ALWAYS_TO:
15827 case GOMP_MAP_ALWAYS_FROM:
15828 case GOMP_MAP_ALWAYS_TOFROM:
15829 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15830 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15831 case GOMP_MAP_STRUCT:
15832 case GOMP_MAP_ALWAYS_POINTER:
15833 break;
15834 case GOMP_MAP_FORCE_ALLOC:
15835 case GOMP_MAP_FORCE_TO:
15836 case GOMP_MAP_FORCE_FROM:
15837 case GOMP_MAP_FORCE_TOFROM:
15838 case GOMP_MAP_FORCE_PRESENT:
15839 case GOMP_MAP_FORCE_DEVICEPTR:
15840 case GOMP_MAP_DEVICE_RESIDENT:
15841 case GOMP_MAP_LINK:
15842 gcc_assert (is_gimple_omp_oacc (stmt));
15843 break;
15844 default:
15845 gcc_unreachable ();
15847 #endif
15848 /* FALLTHRU */
15849 case OMP_CLAUSE_TO:
15850 case OMP_CLAUSE_FROM:
15851 oacc_firstprivate:
15852 var = OMP_CLAUSE_DECL (c);
15853 if (!DECL_P (var))
15855 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15856 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15857 && (OMP_CLAUSE_MAP_KIND (c)
15858 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15859 map_cnt++;
15860 continue;
15863 if (DECL_SIZE (var)
15864 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15866 tree var2 = DECL_VALUE_EXPR (var);
15867 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15868 var2 = TREE_OPERAND (var2, 0);
15869 gcc_assert (DECL_P (var2));
15870 var = var2;
15873 if (offloaded
15874 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15875 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15876 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15878 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15880 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15881 && varpool_node::get_create (var)->offloadable)
15882 continue;
15884 tree type = build_pointer_type (TREE_TYPE (var));
15885 tree new_var = lookup_decl (var, ctx);
15886 x = create_tmp_var_raw (type, get_name (new_var));
15887 gimple_add_tmp_var (x);
15888 x = build_simple_mem_ref (x);
15889 SET_DECL_VALUE_EXPR (new_var, x);
15890 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15892 continue;
15895 if (!maybe_lookup_field (var, ctx))
15896 continue;
15898 /* Don't remap oacc parallel reduction variables, because the
15899 intermediate result must be local to each gang. */
15900 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15901 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15903 x = build_receiver_ref (var, true, ctx);
15904 tree new_var = lookup_decl (var, ctx);
15906 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15907 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15908 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15909 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15910 x = build_simple_mem_ref (x);
15911 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15913 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15914 if (is_reference (new_var))
15916 /* Create a local object to hold the instance
15917 value. */
15918 tree type = TREE_TYPE (TREE_TYPE (new_var));
15919 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15920 tree inst = create_tmp_var (type, id);
15921 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15922 x = build_fold_addr_expr (inst);
15924 gimplify_assign (new_var, x, &fplist);
15926 else if (DECL_P (new_var))
15928 SET_DECL_VALUE_EXPR (new_var, x);
15929 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15931 else
15932 gcc_unreachable ();
15934 map_cnt++;
15935 break;
15937 case OMP_CLAUSE_FIRSTPRIVATE:
15938 if (is_oacc_parallel (ctx))
15939 goto oacc_firstprivate;
15940 map_cnt++;
15941 var = OMP_CLAUSE_DECL (c);
15942 if (!is_reference (var)
15943 && !is_gimple_reg_type (TREE_TYPE (var)))
15945 tree new_var = lookup_decl (var, ctx);
15946 if (is_variable_sized (var))
15948 tree pvar = DECL_VALUE_EXPR (var);
15949 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15950 pvar = TREE_OPERAND (pvar, 0);
15951 gcc_assert (DECL_P (pvar));
15952 tree new_pvar = lookup_decl (pvar, ctx);
15953 x = build_fold_indirect_ref (new_pvar);
15954 TREE_THIS_NOTRAP (x) = 1;
15956 else
15957 x = build_receiver_ref (var, true, ctx);
15958 SET_DECL_VALUE_EXPR (new_var, x);
15959 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15961 break;
15963 case OMP_CLAUSE_PRIVATE:
15964 if (is_gimple_omp_oacc (ctx->stmt))
15965 break;
15966 var = OMP_CLAUSE_DECL (c);
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 break;
15982 case OMP_CLAUSE_USE_DEVICE_PTR:
15983 case OMP_CLAUSE_IS_DEVICE_PTR:
15984 var = OMP_CLAUSE_DECL (c);
15985 map_cnt++;
15986 if (is_variable_sized (var))
15988 tree new_var = lookup_decl (var, ctx);
15989 tree pvar = DECL_VALUE_EXPR (var);
15990 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15991 pvar = TREE_OPERAND (pvar, 0);
15992 gcc_assert (DECL_P (pvar));
15993 tree new_pvar = lookup_decl (pvar, ctx);
15994 x = build_fold_indirect_ref (new_pvar);
15995 TREE_THIS_NOTRAP (x) = 1;
15996 SET_DECL_VALUE_EXPR (new_var, x);
15997 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15999 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16001 tree new_var = lookup_decl (var, ctx);
16002 tree type = build_pointer_type (TREE_TYPE (var));
16003 x = create_tmp_var_raw (type, get_name (new_var));
16004 gimple_add_tmp_var (x);
16005 x = build_simple_mem_ref (x);
16006 SET_DECL_VALUE_EXPR (new_var, x);
16007 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16009 else
16011 tree new_var = lookup_decl (var, ctx);
16012 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
16013 gimple_add_tmp_var (x);
16014 SET_DECL_VALUE_EXPR (new_var, x);
16015 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16017 break;
16020 if (offloaded)
16022 target_nesting_level++;
16023 lower_omp (&tgt_body, ctx);
16024 target_nesting_level--;
16026 else if (data_region)
16027 lower_omp (&tgt_body, ctx);
16029 if (offloaded)
16031 /* Declare all the variables created by mapping and the variables
16032 declared in the scope of the target body. */
16033 record_vars_into (ctx->block_vars, child_fn);
16034 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16037 olist = NULL;
16038 ilist = NULL;
16039 if (ctx->record_type)
16041 ctx->sender_decl
16042 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16043 DECL_NAMELESS (ctx->sender_decl) = 1;
16044 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16045 t = make_tree_vec (3);
16046 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16047 TREE_VEC_ELT (t, 1)
16048 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16049 ".omp_data_sizes");
16050 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16051 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16052 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16053 tree tkind_type = short_unsigned_type_node;
16054 int talign_shift = 8;
16055 TREE_VEC_ELT (t, 2)
16056 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16057 ".omp_data_kinds");
16058 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16059 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16060 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16061 gimple_omp_target_set_data_arg (stmt, t);
16063 vec<constructor_elt, va_gc> *vsize;
16064 vec<constructor_elt, va_gc> *vkind;
16065 vec_alloc (vsize, map_cnt);
16066 vec_alloc (vkind, map_cnt);
16067 unsigned int map_idx = 0;
16069 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16070 switch (OMP_CLAUSE_CODE (c))
16072 tree ovar, nc, s, purpose, var, x, type;
16073 unsigned int talign;
16075 default:
16076 break;
16078 case OMP_CLAUSE_MAP:
16079 case OMP_CLAUSE_TO:
16080 case OMP_CLAUSE_FROM:
16081 oacc_firstprivate_map:
16082 nc = c;
16083 ovar = OMP_CLAUSE_DECL (c);
16084 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16085 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16086 || (OMP_CLAUSE_MAP_KIND (c)
16087 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16088 break;
16089 if (!DECL_P (ovar))
16091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16092 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16094 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16095 == get_base_address (ovar));
16096 nc = OMP_CLAUSE_CHAIN (c);
16097 ovar = OMP_CLAUSE_DECL (nc);
16099 else
16101 tree x = build_sender_ref (ovar, ctx);
16102 tree v
16103 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16104 gimplify_assign (x, v, &ilist);
16105 nc = NULL_TREE;
16108 else
16110 if (DECL_SIZE (ovar)
16111 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16113 tree ovar2 = DECL_VALUE_EXPR (ovar);
16114 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16115 ovar2 = TREE_OPERAND (ovar2, 0);
16116 gcc_assert (DECL_P (ovar2));
16117 ovar = ovar2;
16119 if (!maybe_lookup_field (ovar, ctx))
16120 continue;
16123 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16124 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16125 talign = DECL_ALIGN_UNIT (ovar);
16126 if (nc)
16128 var = lookup_decl_in_outer_ctx (ovar, ctx);
16129 x = build_sender_ref (ovar, ctx);
16131 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16132 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16133 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16134 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16136 gcc_assert (offloaded);
16137 tree avar
16138 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16139 mark_addressable (avar);
16140 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16141 talign = DECL_ALIGN_UNIT (avar);
16142 avar = build_fold_addr_expr (avar);
16143 gimplify_assign (x, avar, &ilist);
16145 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16147 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16148 if (!is_reference (var))
16150 if (is_gimple_reg (var)
16151 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16152 TREE_NO_WARNING (var) = 1;
16153 var = build_fold_addr_expr (var);
16155 else
16156 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16157 gimplify_assign (x, var, &ilist);
16159 else if (is_gimple_reg (var))
16161 gcc_assert (offloaded);
16162 tree avar = create_tmp_var (TREE_TYPE (var));
16163 mark_addressable (avar);
16164 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16165 if (GOMP_MAP_COPY_TO_P (map_kind)
16166 || map_kind == GOMP_MAP_POINTER
16167 || map_kind == GOMP_MAP_TO_PSET
16168 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16170 /* If we need to initialize a temporary
16171 with VAR because it is not addressable, and
16172 the variable hasn't been initialized yet, then
16173 we'll get a warning for the store to avar.
16174 Don't warn in that case, the mapping might
16175 be implicit. */
16176 TREE_NO_WARNING (var) = 1;
16177 gimplify_assign (avar, var, &ilist);
16179 avar = build_fold_addr_expr (avar);
16180 gimplify_assign (x, avar, &ilist);
16181 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16182 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16183 && !TYPE_READONLY (TREE_TYPE (var)))
16185 x = unshare_expr (x);
16186 x = build_simple_mem_ref (x);
16187 gimplify_assign (var, x, &olist);
16190 else
16192 var = build_fold_addr_expr (var);
16193 gimplify_assign (x, var, &ilist);
16196 s = NULL_TREE;
16197 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16199 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16200 s = TREE_TYPE (ovar);
16201 if (TREE_CODE (s) == REFERENCE_TYPE)
16202 s = TREE_TYPE (s);
16203 s = TYPE_SIZE_UNIT (s);
16205 else
16206 s = OMP_CLAUSE_SIZE (c);
16207 if (s == NULL_TREE)
16208 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16209 s = fold_convert (size_type_node, s);
16210 purpose = size_int (map_idx++);
16211 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16212 if (TREE_CODE (s) != INTEGER_CST)
16213 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16215 unsigned HOST_WIDE_INT tkind, tkind_zero;
16216 switch (OMP_CLAUSE_CODE (c))
16218 case OMP_CLAUSE_MAP:
16219 tkind = OMP_CLAUSE_MAP_KIND (c);
16220 tkind_zero = tkind;
16221 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16222 switch (tkind)
16224 case GOMP_MAP_ALLOC:
16225 case GOMP_MAP_TO:
16226 case GOMP_MAP_FROM:
16227 case GOMP_MAP_TOFROM:
16228 case GOMP_MAP_ALWAYS_TO:
16229 case GOMP_MAP_ALWAYS_FROM:
16230 case GOMP_MAP_ALWAYS_TOFROM:
16231 case GOMP_MAP_RELEASE:
16232 case GOMP_MAP_FORCE_TO:
16233 case GOMP_MAP_FORCE_FROM:
16234 case GOMP_MAP_FORCE_TOFROM:
16235 case GOMP_MAP_FORCE_PRESENT:
16236 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16237 break;
16238 case GOMP_MAP_DELETE:
16239 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16240 default:
16241 break;
16243 if (tkind_zero != tkind)
16245 if (integer_zerop (s))
16246 tkind = tkind_zero;
16247 else if (integer_nonzerop (s))
16248 tkind_zero = tkind;
16250 break;
16251 case OMP_CLAUSE_FIRSTPRIVATE:
16252 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16253 tkind = GOMP_MAP_TO;
16254 tkind_zero = tkind;
16255 break;
16256 case OMP_CLAUSE_TO:
16257 tkind = GOMP_MAP_TO;
16258 tkind_zero = tkind;
16259 break;
16260 case OMP_CLAUSE_FROM:
16261 tkind = GOMP_MAP_FROM;
16262 tkind_zero = tkind;
16263 break;
16264 default:
16265 gcc_unreachable ();
16267 gcc_checking_assert (tkind
16268 < (HOST_WIDE_INT_C (1U) << talign_shift));
16269 gcc_checking_assert (tkind_zero
16270 < (HOST_WIDE_INT_C (1U) << talign_shift));
16271 talign = ceil_log2 (talign);
16272 tkind |= talign << talign_shift;
16273 tkind_zero |= talign << talign_shift;
16274 gcc_checking_assert (tkind
16275 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16276 gcc_checking_assert (tkind_zero
16277 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16278 if (tkind == tkind_zero)
16279 x = build_int_cstu (tkind_type, tkind);
16280 else
16282 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16283 x = build3 (COND_EXPR, tkind_type,
16284 fold_build2 (EQ_EXPR, boolean_type_node,
16285 unshare_expr (s), size_zero_node),
16286 build_int_cstu (tkind_type, tkind_zero),
16287 build_int_cstu (tkind_type, tkind));
16289 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16290 if (nc && nc != c)
16291 c = nc;
16292 break;
16294 case OMP_CLAUSE_FIRSTPRIVATE:
16295 if (is_oacc_parallel (ctx))
16296 goto oacc_firstprivate_map;
16297 ovar = OMP_CLAUSE_DECL (c);
16298 if (is_reference (ovar))
16299 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16300 else
16301 talign = DECL_ALIGN_UNIT (ovar);
16302 var = lookup_decl_in_outer_ctx (ovar, ctx);
16303 x = build_sender_ref (ovar, ctx);
16304 tkind = GOMP_MAP_FIRSTPRIVATE;
16305 type = TREE_TYPE (ovar);
16306 if (is_reference (ovar))
16307 type = TREE_TYPE (type);
16308 if ((INTEGRAL_TYPE_P (type)
16309 && TYPE_PRECISION (type) <= POINTER_SIZE)
16310 || TREE_CODE (type) == POINTER_TYPE)
16312 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16313 tree t = var;
16314 if (is_reference (var))
16315 t = build_simple_mem_ref (var);
16316 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16317 TREE_NO_WARNING (var) = 1;
16318 if (TREE_CODE (type) != POINTER_TYPE)
16319 t = fold_convert (pointer_sized_int_node, t);
16320 t = fold_convert (TREE_TYPE (x), t);
16321 gimplify_assign (x, t, &ilist);
16323 else if (is_reference (var))
16324 gimplify_assign (x, var, &ilist);
16325 else if (is_gimple_reg (var))
16327 tree avar = create_tmp_var (TREE_TYPE (var));
16328 mark_addressable (avar);
16329 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16330 TREE_NO_WARNING (var) = 1;
16331 gimplify_assign (avar, var, &ilist);
16332 avar = build_fold_addr_expr (avar);
16333 gimplify_assign (x, avar, &ilist);
16335 else
16337 var = build_fold_addr_expr (var);
16338 gimplify_assign (x, var, &ilist);
16340 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16341 s = size_int (0);
16342 else if (is_reference (var))
16343 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16344 else
16345 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16346 s = fold_convert (size_type_node, s);
16347 purpose = size_int (map_idx++);
16348 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16349 if (TREE_CODE (s) != INTEGER_CST)
16350 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16352 gcc_checking_assert (tkind
16353 < (HOST_WIDE_INT_C (1U) << talign_shift));
16354 talign = ceil_log2 (talign);
16355 tkind |= talign << talign_shift;
16356 gcc_checking_assert (tkind
16357 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16358 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16359 build_int_cstu (tkind_type, tkind));
16360 break;
16362 case OMP_CLAUSE_USE_DEVICE_PTR:
16363 case OMP_CLAUSE_IS_DEVICE_PTR:
16364 ovar = OMP_CLAUSE_DECL (c);
16365 var = lookup_decl_in_outer_ctx (ovar, ctx);
16366 x = build_sender_ref (ovar, ctx);
16367 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16368 tkind = GOMP_MAP_USE_DEVICE_PTR;
16369 else
16370 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16371 type = TREE_TYPE (ovar);
16372 if (TREE_CODE (type) == ARRAY_TYPE)
16373 var = build_fold_addr_expr (var);
16374 else
16376 if (is_reference (ovar))
16378 type = TREE_TYPE (type);
16379 if (TREE_CODE (type) != ARRAY_TYPE)
16380 var = build_simple_mem_ref (var);
16381 var = fold_convert (TREE_TYPE (x), var);
16384 gimplify_assign (x, var, &ilist);
16385 s = size_int (0);
16386 purpose = size_int (map_idx++);
16387 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16388 gcc_checking_assert (tkind
16389 < (HOST_WIDE_INT_C (1U) << talign_shift));
16390 gcc_checking_assert (tkind
16391 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16392 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16393 build_int_cstu (tkind_type, tkind));
16394 break;
16397 gcc_assert (map_idx == map_cnt);
16399 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16400 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16401 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16402 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16403 for (int i = 1; i <= 2; i++)
16404 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16406 gimple_seq initlist = NULL;
16407 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16408 TREE_VEC_ELT (t, i)),
16409 &initlist, true, NULL_TREE);
16410 gimple_seq_add_seq (&ilist, initlist);
16412 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16413 NULL);
16414 TREE_THIS_VOLATILE (clobber) = 1;
16415 gimple_seq_add_stmt (&olist,
16416 gimple_build_assign (TREE_VEC_ELT (t, i),
16417 clobber));
16420 tree clobber = build_constructor (ctx->record_type, NULL);
16421 TREE_THIS_VOLATILE (clobber) = 1;
16422 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16423 clobber));
16426 /* Once all the expansions are done, sequence all the different
16427 fragments inside gimple_omp_body. */
16429 new_body = NULL;
16431 if (offloaded
16432 && ctx->record_type)
16434 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16435 /* fixup_child_record_type might have changed receiver_decl's type. */
16436 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16437 gimple_seq_add_stmt (&new_body,
16438 gimple_build_assign (ctx->receiver_decl, t));
16440 gimple_seq_add_seq (&new_body, fplist);
16442 if (offloaded || data_region)
16444 tree prev = NULL_TREE;
16445 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16446 switch (OMP_CLAUSE_CODE (c))
16448 tree var, x;
16449 default:
16450 break;
16451 case OMP_CLAUSE_FIRSTPRIVATE:
16452 if (is_gimple_omp_oacc (ctx->stmt))
16453 break;
16454 var = OMP_CLAUSE_DECL (c);
16455 if (is_reference (var)
16456 || is_gimple_reg_type (TREE_TYPE (var)))
16458 tree new_var = lookup_decl (var, ctx);
16459 tree type;
16460 type = TREE_TYPE (var);
16461 if (is_reference (var))
16462 type = TREE_TYPE (type);
16463 if ((INTEGRAL_TYPE_P (type)
16464 && TYPE_PRECISION (type) <= POINTER_SIZE)
16465 || TREE_CODE (type) == POINTER_TYPE)
16467 x = build_receiver_ref (var, false, ctx);
16468 if (TREE_CODE (type) != POINTER_TYPE)
16469 x = fold_convert (pointer_sized_int_node, x);
16470 x = fold_convert (type, x);
16471 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16472 fb_rvalue);
16473 if (is_reference (var))
16475 tree v = create_tmp_var_raw (type, get_name (var));
16476 gimple_add_tmp_var (v);
16477 TREE_ADDRESSABLE (v) = 1;
16478 gimple_seq_add_stmt (&new_body,
16479 gimple_build_assign (v, x));
16480 x = build_fold_addr_expr (v);
16482 gimple_seq_add_stmt (&new_body,
16483 gimple_build_assign (new_var, x));
16485 else
16487 x = build_receiver_ref (var, !is_reference (var), ctx);
16488 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16489 fb_rvalue);
16490 gimple_seq_add_stmt (&new_body,
16491 gimple_build_assign (new_var, x));
16494 else if (is_variable_sized (var))
16496 tree pvar = DECL_VALUE_EXPR (var);
16497 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16498 pvar = TREE_OPERAND (pvar, 0);
16499 gcc_assert (DECL_P (pvar));
16500 tree new_var = lookup_decl (pvar, ctx);
16501 x = build_receiver_ref (var, false, ctx);
16502 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16503 gimple_seq_add_stmt (&new_body,
16504 gimple_build_assign (new_var, x));
16506 break;
16507 case OMP_CLAUSE_PRIVATE:
16508 if (is_gimple_omp_oacc (ctx->stmt))
16509 break;
16510 var = OMP_CLAUSE_DECL (c);
16511 if (is_reference (var))
16513 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16514 tree new_var = lookup_decl (var, ctx);
16515 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16516 if (TREE_CONSTANT (x))
16518 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16519 get_name (var));
16520 gimple_add_tmp_var (x);
16521 TREE_ADDRESSABLE (x) = 1;
16522 x = build_fold_addr_expr_loc (clause_loc, x);
16524 else
16525 break;
16527 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16528 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16529 gimple_seq_add_stmt (&new_body,
16530 gimple_build_assign (new_var, x));
16532 break;
16533 case OMP_CLAUSE_USE_DEVICE_PTR:
16534 case OMP_CLAUSE_IS_DEVICE_PTR:
16535 var = OMP_CLAUSE_DECL (c);
16536 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16537 x = build_sender_ref (var, ctx);
16538 else
16539 x = build_receiver_ref (var, false, ctx);
16540 if (is_variable_sized (var))
16542 tree pvar = DECL_VALUE_EXPR (var);
16543 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16544 pvar = TREE_OPERAND (pvar, 0);
16545 gcc_assert (DECL_P (pvar));
16546 tree new_var = lookup_decl (pvar, ctx);
16547 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16548 gimple_seq_add_stmt (&new_body,
16549 gimple_build_assign (new_var, x));
16551 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16553 tree new_var = lookup_decl (var, ctx);
16554 new_var = DECL_VALUE_EXPR (new_var);
16555 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16556 new_var = TREE_OPERAND (new_var, 0);
16557 gcc_assert (DECL_P (new_var));
16558 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16559 gimple_seq_add_stmt (&new_body,
16560 gimple_build_assign (new_var, x));
16562 else
16564 tree type = TREE_TYPE (var);
16565 tree new_var = lookup_decl (var, ctx);
16566 if (is_reference (var))
16568 type = TREE_TYPE (type);
16569 if (TREE_CODE (type) != ARRAY_TYPE)
16571 tree v = create_tmp_var_raw (type, get_name (var));
16572 gimple_add_tmp_var (v);
16573 TREE_ADDRESSABLE (v) = 1;
16574 x = fold_convert (type, x);
16575 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16576 fb_rvalue);
16577 gimple_seq_add_stmt (&new_body,
16578 gimple_build_assign (v, x));
16579 x = build_fold_addr_expr (v);
16582 new_var = DECL_VALUE_EXPR (new_var);
16583 x = fold_convert (TREE_TYPE (new_var), x);
16584 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16585 gimple_seq_add_stmt (&new_body,
16586 gimple_build_assign (new_var, x));
16588 break;
16590 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16591 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16592 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16593 or references to VLAs. */
16594 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16595 switch (OMP_CLAUSE_CODE (c))
16597 tree var;
16598 default:
16599 break;
16600 case OMP_CLAUSE_MAP:
16601 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16602 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16604 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16605 HOST_WIDE_INT offset = 0;
16606 gcc_assert (prev);
16607 var = OMP_CLAUSE_DECL (c);
16608 if (DECL_P (var)
16609 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16610 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16611 ctx))
16612 && varpool_node::get_create (var)->offloadable)
16613 break;
16614 if (TREE_CODE (var) == INDIRECT_REF
16615 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16616 var = TREE_OPERAND (var, 0);
16617 if (TREE_CODE (var) == COMPONENT_REF)
16619 var = get_addr_base_and_unit_offset (var, &offset);
16620 gcc_assert (var != NULL_TREE && DECL_P (var));
16622 else if (DECL_SIZE (var)
16623 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16625 tree var2 = DECL_VALUE_EXPR (var);
16626 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16627 var2 = TREE_OPERAND (var2, 0);
16628 gcc_assert (DECL_P (var2));
16629 var = var2;
16631 tree new_var = lookup_decl (var, ctx), x;
16632 tree type = TREE_TYPE (new_var);
16633 bool is_ref;
16634 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16635 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16636 == COMPONENT_REF))
16638 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16639 is_ref = true;
16640 new_var = build2 (MEM_REF, type,
16641 build_fold_addr_expr (new_var),
16642 build_int_cst (build_pointer_type (type),
16643 offset));
16645 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16647 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16648 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16649 new_var = build2 (MEM_REF, type,
16650 build_fold_addr_expr (new_var),
16651 build_int_cst (build_pointer_type (type),
16652 offset));
16654 else
16655 is_ref = is_reference (var);
16656 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16657 is_ref = false;
16658 bool ref_to_array = false;
16659 if (is_ref)
16661 type = TREE_TYPE (type);
16662 if (TREE_CODE (type) == ARRAY_TYPE)
16664 type = build_pointer_type (type);
16665 ref_to_array = true;
16668 else if (TREE_CODE (type) == ARRAY_TYPE)
16670 tree decl2 = DECL_VALUE_EXPR (new_var);
16671 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16672 decl2 = TREE_OPERAND (decl2, 0);
16673 gcc_assert (DECL_P (decl2));
16674 new_var = decl2;
16675 type = TREE_TYPE (new_var);
16677 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16678 x = fold_convert_loc (clause_loc, type, x);
16679 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16681 tree bias = OMP_CLAUSE_SIZE (c);
16682 if (DECL_P (bias))
16683 bias = lookup_decl (bias, ctx);
16684 bias = fold_convert_loc (clause_loc, sizetype, bias);
16685 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16686 bias);
16687 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16688 TREE_TYPE (x), x, bias);
16690 if (ref_to_array)
16691 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16692 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16693 if (is_ref && !ref_to_array)
16695 tree t = create_tmp_var_raw (type, get_name (var));
16696 gimple_add_tmp_var (t);
16697 TREE_ADDRESSABLE (t) = 1;
16698 gimple_seq_add_stmt (&new_body,
16699 gimple_build_assign (t, x));
16700 x = build_fold_addr_expr_loc (clause_loc, t);
16702 gimple_seq_add_stmt (&new_body,
16703 gimple_build_assign (new_var, x));
16704 prev = NULL_TREE;
16706 else if (OMP_CLAUSE_CHAIN (c)
16707 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16708 == OMP_CLAUSE_MAP
16709 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16710 == GOMP_MAP_FIRSTPRIVATE_POINTER
16711 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16712 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16713 prev = c;
16714 break;
16715 case OMP_CLAUSE_PRIVATE:
16716 var = OMP_CLAUSE_DECL (c);
16717 if (is_variable_sized (var))
16719 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16720 tree new_var = lookup_decl (var, ctx);
16721 tree pvar = DECL_VALUE_EXPR (var);
16722 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16723 pvar = TREE_OPERAND (pvar, 0);
16724 gcc_assert (DECL_P (pvar));
16725 tree new_pvar = lookup_decl (pvar, ctx);
16726 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16727 tree al = size_int (DECL_ALIGN (var));
16728 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16729 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16730 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16731 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16732 gimple_seq_add_stmt (&new_body,
16733 gimple_build_assign (new_pvar, x));
16735 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16737 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16738 tree new_var = lookup_decl (var, ctx);
16739 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16740 if (TREE_CONSTANT (x))
16741 break;
16742 else
16744 tree atmp
16745 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16746 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16747 tree al = size_int (TYPE_ALIGN (rtype));
16748 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16751 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16752 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16753 gimple_seq_add_stmt (&new_body,
16754 gimple_build_assign (new_var, x));
16756 break;
16759 gimple_seq fork_seq = NULL;
16760 gimple_seq join_seq = NULL;
16762 if (is_oacc_parallel (ctx))
16764 /* If there are reductions on the offloaded region itself, treat
16765 them as a dummy GANG loop. */
16766 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16768 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16769 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16772 gimple_seq_add_seq (&new_body, fork_seq);
16773 gimple_seq_add_seq (&new_body, tgt_body);
16774 gimple_seq_add_seq (&new_body, join_seq);
16776 if (offloaded)
16777 new_body = maybe_catch_exception (new_body);
16779 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16780 gimple_omp_set_body (stmt, new_body);
16783 bind = gimple_build_bind (NULL, NULL,
16784 tgt_bind ? gimple_bind_block (tgt_bind)
16785 : NULL_TREE);
16786 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16787 gimple_bind_add_seq (bind, ilist);
16788 gimple_bind_add_stmt (bind, stmt);
16789 gimple_bind_add_seq (bind, olist);
16791 pop_gimplify_context (NULL);
16793 if (dep_bind)
16795 gimple_bind_add_seq (dep_bind, dep_ilist);
16796 gimple_bind_add_stmt (dep_bind, bind);
16797 gimple_bind_add_seq (dep_bind, dep_olist);
16798 pop_gimplify_context (dep_bind);
16802 /* Expand code for an OpenMP teams directive. */
16804 static void
16805 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16807 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16808 push_gimplify_context ();
16810 tree block = make_node (BLOCK);
16811 gbind *bind = gimple_build_bind (NULL, NULL, block);
16812 gsi_replace (gsi_p, bind, true);
16813 gimple_seq bind_body = NULL;
16814 gimple_seq dlist = NULL;
16815 gimple_seq olist = NULL;
16817 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16818 OMP_CLAUSE_NUM_TEAMS);
16819 if (num_teams == NULL_TREE)
16820 num_teams = build_int_cst (unsigned_type_node, 0);
16821 else
16823 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16824 num_teams = fold_convert (unsigned_type_node, num_teams);
16825 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16827 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16828 OMP_CLAUSE_THREAD_LIMIT);
16829 if (thread_limit == NULL_TREE)
16830 thread_limit = build_int_cst (unsigned_type_node, 0);
16831 else
16833 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16834 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16835 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16836 fb_rvalue);
16839 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16840 &bind_body, &dlist, ctx, NULL);
16841 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16842 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16843 if (!gimple_omp_teams_grid_phony (teams_stmt))
16845 gimple_seq_add_stmt (&bind_body, teams_stmt);
16846 location_t loc = gimple_location (teams_stmt);
16847 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16848 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16849 gimple_set_location (call, loc);
16850 gimple_seq_add_stmt (&bind_body, call);
16853 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16854 gimple_omp_set_body (teams_stmt, NULL);
16855 gimple_seq_add_seq (&bind_body, olist);
16856 gimple_seq_add_seq (&bind_body, dlist);
16857 if (!gimple_omp_teams_grid_phony (teams_stmt))
16858 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16859 gimple_bind_set_body (bind, bind_body);
16861 pop_gimplify_context (bind);
16863 gimple_bind_append_vars (bind, ctx->block_vars);
16864 BLOCK_VARS (block) = ctx->block_vars;
16865 if (BLOCK_VARS (block))
16866 TREE_USED (block) = 1;
16869 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16871 static void
16872 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16874 gimple *stmt = gsi_stmt (*gsi_p);
16875 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16876 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16877 gimple_build_omp_return (false));
16881 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16882 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16883 of OMP context, but with task_shared_vars set. */
16885 static tree
16886 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16887 void *data)
16889 tree t = *tp;
16891 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16892 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16893 return t;
16895 if (task_shared_vars
16896 && DECL_P (t)
16897 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16898 return t;
16900 /* If a global variable has been privatized, TREE_CONSTANT on
16901 ADDR_EXPR might be wrong. */
16902 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16903 recompute_tree_invariant_for_addr_expr (t);
16905 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16906 return NULL_TREE;
16909 /* Data to be communicated between lower_omp_regimplify_operands and
16910 lower_omp_regimplify_operands_p. */
16912 struct lower_omp_regimplify_operands_data
16914 omp_context *ctx;
16915 vec<tree> *decls;
16918 /* Helper function for lower_omp_regimplify_operands. Find
16919 omp_member_access_dummy_var vars and adjust temporarily their
16920 DECL_VALUE_EXPRs if needed. */
16922 static tree
16923 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16924 void *data)
16926 tree t = omp_member_access_dummy_var (*tp);
16927 if (t)
16929 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16930 lower_omp_regimplify_operands_data *ldata
16931 = (lower_omp_regimplify_operands_data *) wi->info;
16932 tree o = maybe_lookup_decl (t, ldata->ctx);
16933 if (o != t)
16935 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16936 ldata->decls->safe_push (*tp);
16937 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16938 SET_DECL_VALUE_EXPR (*tp, v);
16941 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16942 return NULL_TREE;
16945 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16946 of omp_member_access_dummy_var vars during regimplification. */
16948 static void
16949 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16950 gimple_stmt_iterator *gsi_p)
16952 auto_vec<tree, 10> decls;
16953 if (ctx)
16955 struct walk_stmt_info wi;
16956 memset (&wi, '\0', sizeof (wi));
16957 struct lower_omp_regimplify_operands_data data;
16958 data.ctx = ctx;
16959 data.decls = &decls;
16960 wi.info = &data;
16961 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16963 gimple_regimplify_operands (stmt, gsi_p);
16964 while (!decls.is_empty ())
16966 tree t = decls.pop ();
16967 tree v = decls.pop ();
16968 SET_DECL_VALUE_EXPR (t, v);
16972 static void
16973 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16975 gimple *stmt = gsi_stmt (*gsi_p);
16976 struct walk_stmt_info wi;
16977 gcall *call_stmt;
16979 if (gimple_has_location (stmt))
16980 input_location = gimple_location (stmt);
16982 if (task_shared_vars)
16983 memset (&wi, '\0', sizeof (wi));
16985 /* If we have issued syntax errors, avoid doing any heavy lifting.
16986 Just replace the OMP directives with a NOP to avoid
16987 confusing RTL expansion. */
16988 if (seen_error () && is_gimple_omp (stmt))
16990 gsi_replace (gsi_p, gimple_build_nop (), true);
16991 return;
16994 switch (gimple_code (stmt))
16996 case GIMPLE_COND:
16998 gcond *cond_stmt = as_a <gcond *> (stmt);
16999 if ((ctx || task_shared_vars)
17000 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
17001 lower_omp_regimplify_p,
17002 ctx ? NULL : &wi, NULL)
17003 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
17004 lower_omp_regimplify_p,
17005 ctx ? NULL : &wi, NULL)))
17006 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
17008 break;
17009 case GIMPLE_CATCH:
17010 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
17011 break;
17012 case GIMPLE_EH_FILTER:
17013 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
17014 break;
17015 case GIMPLE_TRY:
17016 lower_omp (gimple_try_eval_ptr (stmt), ctx);
17017 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
17018 break;
17019 case GIMPLE_TRANSACTION:
17020 lower_omp (gimple_transaction_body_ptr (
17021 as_a <gtransaction *> (stmt)),
17022 ctx);
17023 break;
17024 case GIMPLE_BIND:
17025 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
17026 break;
17027 case GIMPLE_OMP_PARALLEL:
17028 case GIMPLE_OMP_TASK:
17029 ctx = maybe_lookup_ctx (stmt);
17030 gcc_assert (ctx);
17031 if (ctx->cancellable)
17032 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17033 lower_omp_taskreg (gsi_p, ctx);
17034 break;
17035 case GIMPLE_OMP_FOR:
17036 ctx = maybe_lookup_ctx (stmt);
17037 gcc_assert (ctx);
17038 if (ctx->cancellable)
17039 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17040 lower_omp_for (gsi_p, ctx);
17041 break;
17042 case GIMPLE_OMP_SECTIONS:
17043 ctx = maybe_lookup_ctx (stmt);
17044 gcc_assert (ctx);
17045 if (ctx->cancellable)
17046 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17047 lower_omp_sections (gsi_p, ctx);
17048 break;
17049 case GIMPLE_OMP_SINGLE:
17050 ctx = maybe_lookup_ctx (stmt);
17051 gcc_assert (ctx);
17052 lower_omp_single (gsi_p, ctx);
17053 break;
17054 case GIMPLE_OMP_MASTER:
17055 ctx = maybe_lookup_ctx (stmt);
17056 gcc_assert (ctx);
17057 lower_omp_master (gsi_p, ctx);
17058 break;
17059 case GIMPLE_OMP_TASKGROUP:
17060 ctx = maybe_lookup_ctx (stmt);
17061 gcc_assert (ctx);
17062 lower_omp_taskgroup (gsi_p, ctx);
17063 break;
17064 case GIMPLE_OMP_ORDERED:
17065 ctx = maybe_lookup_ctx (stmt);
17066 gcc_assert (ctx);
17067 lower_omp_ordered (gsi_p, ctx);
17068 break;
17069 case GIMPLE_OMP_CRITICAL:
17070 ctx = maybe_lookup_ctx (stmt);
17071 gcc_assert (ctx);
17072 lower_omp_critical (gsi_p, ctx);
17073 break;
17074 case GIMPLE_OMP_ATOMIC_LOAD:
17075 if ((ctx || task_shared_vars)
17076 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17077 as_a <gomp_atomic_load *> (stmt)),
17078 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17079 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17080 break;
17081 case GIMPLE_OMP_TARGET:
17082 ctx = maybe_lookup_ctx (stmt);
17083 gcc_assert (ctx);
17084 lower_omp_target (gsi_p, ctx);
17085 break;
17086 case GIMPLE_OMP_TEAMS:
17087 ctx = maybe_lookup_ctx (stmt);
17088 gcc_assert (ctx);
17089 lower_omp_teams (gsi_p, ctx);
17090 break;
17091 case GIMPLE_OMP_GRID_BODY:
17092 ctx = maybe_lookup_ctx (stmt);
17093 gcc_assert (ctx);
17094 lower_omp_grid_body (gsi_p, ctx);
17095 break;
17096 case GIMPLE_CALL:
17097 tree fndecl;
17098 call_stmt = as_a <gcall *> (stmt);
17099 fndecl = gimple_call_fndecl (call_stmt);
17100 if (fndecl
17101 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17102 switch (DECL_FUNCTION_CODE (fndecl))
17104 case BUILT_IN_GOMP_BARRIER:
17105 if (ctx == NULL)
17106 break;
17107 /* FALLTHRU */
17108 case BUILT_IN_GOMP_CANCEL:
17109 case BUILT_IN_GOMP_CANCELLATION_POINT:
17110 omp_context *cctx;
17111 cctx = ctx;
17112 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17113 cctx = cctx->outer;
17114 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17115 if (!cctx->cancellable)
17117 if (DECL_FUNCTION_CODE (fndecl)
17118 == BUILT_IN_GOMP_CANCELLATION_POINT)
17120 stmt = gimple_build_nop ();
17121 gsi_replace (gsi_p, stmt, false);
17123 break;
17125 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17127 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17128 gimple_call_set_fndecl (call_stmt, fndecl);
17129 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17131 tree lhs;
17132 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17133 gimple_call_set_lhs (call_stmt, lhs);
17134 tree fallthru_label;
17135 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17136 gimple *g;
17137 g = gimple_build_label (fallthru_label);
17138 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17139 g = gimple_build_cond (NE_EXPR, lhs,
17140 fold_convert (TREE_TYPE (lhs),
17141 boolean_false_node),
17142 cctx->cancel_label, fallthru_label);
17143 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17144 break;
17145 default:
17146 break;
17148 /* FALLTHRU */
17149 default:
17150 if ((ctx || task_shared_vars)
17151 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17152 ctx ? NULL : &wi))
17154 /* Just remove clobbers, this should happen only if we have
17155 "privatized" local addressable variables in SIMD regions,
17156 the clobber isn't needed in that case and gimplifying address
17157 of the ARRAY_REF into a pointer and creating MEM_REF based
17158 clobber would create worse code than we get with the clobber
17159 dropped. */
17160 if (gimple_clobber_p (stmt))
17162 gsi_replace (gsi_p, gimple_build_nop (), true);
17163 break;
17165 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17167 break;
17171 static void
17172 lower_omp (gimple_seq *body, omp_context *ctx)
17174 location_t saved_location = input_location;
17175 gimple_stmt_iterator gsi;
17176 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17177 lower_omp_1 (&gsi, ctx);
17178 /* During gimplification, we haven't folded statments inside offloading
17179 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17180 if (target_nesting_level || taskreg_nesting_level)
17181 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17182 fold_stmt (&gsi);
17183 input_location = saved_location;
17186 /* Returen true if STMT is an assignment of a register-type into a local
17187 VAR_DECL. */
17189 static bool
17190 grid_reg_assignment_to_local_var_p (gimple *stmt)
17192 gassign *assign = dyn_cast <gassign *> (stmt);
17193 if (!assign)
17194 return false;
17195 tree lhs = gimple_assign_lhs (assign);
17196 if (TREE_CODE (lhs) != VAR_DECL
17197 || !is_gimple_reg_type (TREE_TYPE (lhs))
17198 || is_global_var (lhs))
17199 return false;
17200 return true;
17203 /* Return true if all statements in SEQ are assignments to local register-type
17204 variables. */
17206 static bool
17207 grid_seq_only_contains_local_assignments (gimple_seq seq)
17209 if (!seq)
17210 return true;
17212 gimple_stmt_iterator gsi;
17213 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17214 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17215 return false;
17216 return true;
17219 /* Scan statements in SEQ and call itself recursively on any bind. If during
17220 whole search only assignments to register-type local variables and one
17221 single OMP statement is encountered, return true, otherwise return false.
17222 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17223 are used for dumping a note about a failure. */
17225 static bool
17226 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17227 const char *name, gimple **ret)
17229 gimple_stmt_iterator gsi;
17230 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17232 gimple *stmt = gsi_stmt (gsi);
17234 if (grid_reg_assignment_to_local_var_p (stmt))
17235 continue;
17236 if (gbind *bind = dyn_cast <gbind *> (stmt))
17238 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17239 target_loc, name, ret))
17240 return false;
17242 else if (is_gimple_omp (stmt))
17244 if (*ret)
17246 if (dump_enabled_p ())
17247 dump_printf_loc (MSG_NOTE, target_loc,
17248 "Will not turn target construct into a simple "
17249 "GPGPU kernel because %s construct contains "
17250 "multiple OpenMP constructs\n", name);
17251 return false;
17253 *ret = stmt;
17255 else
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 contains "
17261 "a complex statement\n", name);
17262 return false;
17265 return true;
17268 /* Scan statements in SEQ and make sure that it and any binds in it contain
17269 only assignments to local register-type variables and one OMP construct. If
17270 so, return that construct, otherwise return NULL. If dumping is enabled and
17271 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17272 failure. */
17274 static gimple *
17275 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17276 const char *name)
17278 if (!seq)
17280 if (dump_enabled_p ())
17281 dump_printf_loc (MSG_NOTE, target_loc,
17282 "Will not turn target construct into a simple "
17283 "GPGPU kernel because %s construct has empty "
17284 "body\n",
17285 name);
17286 return NULL;
17289 gimple *ret = NULL;
17290 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17292 if (!ret && dump_enabled_p ())
17293 dump_printf_loc (MSG_NOTE, target_loc,
17294 "Will not turn target construct into a simple "
17295 "GPGPU kernel because %s construct does not contain"
17296 "any other OpenMP construct\n", name);
17297 return ret;
17299 else
17300 return NULL;
17303 /* Walker function looking for statements there is no point gridifying (and for
17304 noreturn function calls which we cannot do). Return non-NULL if such a
17305 function is found. */
17307 static tree
17308 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17309 bool *handled_ops_p,
17310 struct walk_stmt_info *wi)
17312 *handled_ops_p = false;
17313 gimple *stmt = gsi_stmt (*gsi);
17314 switch (gimple_code (stmt))
17316 case GIMPLE_CALL:
17317 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17319 *handled_ops_p = true;
17320 wi->info = stmt;
17321 return error_mark_node;
17323 break;
17325 /* We may reduce the following list if we find a way to implement the
17326 clauses, but now there is no point trying further. */
17327 case GIMPLE_OMP_CRITICAL:
17328 case GIMPLE_OMP_TASKGROUP:
17329 case GIMPLE_OMP_TASK:
17330 case GIMPLE_OMP_SECTION:
17331 case GIMPLE_OMP_SECTIONS:
17332 case GIMPLE_OMP_SECTIONS_SWITCH:
17333 case GIMPLE_OMP_TARGET:
17334 case GIMPLE_OMP_ORDERED:
17335 *handled_ops_p = true;
17336 wi->info = stmt;
17337 return error_mark_node;
17339 case GIMPLE_OMP_FOR:
17340 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17341 && gimple_omp_for_combined_into_p (stmt))
17343 *handled_ops_p = true;
17344 wi->info = stmt;
17345 return error_mark_node;
17347 break;
17349 default:
17350 break;
17352 return NULL;
17356 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17357 kernel, return true, otherwise return false. In the case of success, also
17358 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17359 none. */
17361 static bool
17362 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17364 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17365 return false;
17367 location_t tloc = gimple_location (target);
17368 gimple *stmt
17369 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17370 tloc, "target");
17371 if (!stmt)
17372 return false;
17373 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17374 tree group_size = NULL;
17375 if (!teams)
17377 dump_printf_loc (MSG_NOTE, tloc,
17378 "Will not turn target construct into a simple "
17379 "GPGPU kernel because it does not have a sole teams "
17380 "construct in it.\n");
17381 return false;
17384 tree clauses = gimple_omp_teams_clauses (teams);
17385 while (clauses)
17387 switch (OMP_CLAUSE_CODE (clauses))
17389 case OMP_CLAUSE_NUM_TEAMS:
17390 if (dump_enabled_p ())
17391 dump_printf_loc (MSG_NOTE, tloc,
17392 "Will not turn target construct into a "
17393 "gridified GPGPU kernel because we cannot "
17394 "handle num_teams clause of teams "
17395 "construct\n ");
17396 return false;
17398 case OMP_CLAUSE_REDUCTION:
17399 if (dump_enabled_p ())
17400 dump_printf_loc (MSG_NOTE, tloc,
17401 "Will not turn target construct into a "
17402 "gridified GPGPU kernel because a reduction "
17403 "clause is present\n ");
17404 return false;
17406 case OMP_CLAUSE_LASTPRIVATE:
17407 if (dump_enabled_p ())
17408 dump_printf_loc (MSG_NOTE, tloc,
17409 "Will not turn target construct into a "
17410 "gridified GPGPU kernel because a lastprivate "
17411 "clause is present\n ");
17412 return false;
17414 case OMP_CLAUSE_THREAD_LIMIT:
17415 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17416 break;
17418 default:
17419 break;
17421 clauses = OMP_CLAUSE_CHAIN (clauses);
17424 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17425 "teams");
17426 if (!stmt)
17427 return false;
17428 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17429 if (!dist)
17431 dump_printf_loc (MSG_NOTE, tloc,
17432 "Will not turn target construct into a simple "
17433 "GPGPU kernel because the teams construct does not have "
17434 "a sole distribute construct in it.\n");
17435 return false;
17438 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17439 if (!gimple_omp_for_combined_p (dist))
17441 if (dump_enabled_p ())
17442 dump_printf_loc (MSG_NOTE, tloc,
17443 "Will not turn target construct into a gridified GPGPU "
17444 "kernel because we cannot handle a standalone "
17445 "distribute construct\n ");
17446 return false;
17448 if (dist->collapse > 1)
17450 if (dump_enabled_p ())
17451 dump_printf_loc (MSG_NOTE, tloc,
17452 "Will not turn target construct into a gridified GPGPU "
17453 "kernel because the distribute construct contains "
17454 "collapse clause\n");
17455 return false;
17457 struct omp_for_data fd;
17458 extract_omp_for_data (dist, &fd, NULL);
17459 if (fd.chunk_size)
17461 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17463 if (dump_enabled_p ())
17464 dump_printf_loc (MSG_NOTE, tloc,
17465 "Will not turn target construct into a "
17466 "gridified GPGPU kernel because the teams "
17467 "thread limit is different from distribute "
17468 "schedule chunk\n");
17469 return false;
17471 group_size = fd.chunk_size;
17473 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17474 "distribute");
17475 gomp_parallel *par;
17476 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17477 return false;
17479 clauses = gimple_omp_parallel_clauses (par);
17480 while (clauses)
17482 switch (OMP_CLAUSE_CODE (clauses))
17484 case OMP_CLAUSE_NUM_THREADS:
17485 if (dump_enabled_p ())
17486 dump_printf_loc (MSG_NOTE, tloc,
17487 "Will not turn target construct into a gridified"
17488 "GPGPU kernel because there is a num_threads "
17489 "clause of the parallel construct\n");
17490 return false;
17492 case OMP_CLAUSE_REDUCTION:
17493 if (dump_enabled_p ())
17494 dump_printf_loc (MSG_NOTE, tloc,
17495 "Will not turn target construct into a "
17496 "gridified GPGPU kernel because a reduction "
17497 "clause is present\n ");
17498 return false;
17500 case OMP_CLAUSE_LASTPRIVATE:
17501 if (dump_enabled_p ())
17502 dump_printf_loc (MSG_NOTE, tloc,
17503 "Will not turn target construct into a "
17504 "gridified GPGPU kernel because a lastprivate "
17505 "clause is present\n ");
17506 return false;
17508 default:
17509 break;
17511 clauses = OMP_CLAUSE_CHAIN (clauses);
17514 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17515 "parallel");
17516 gomp_for *gfor;
17517 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17518 return false;
17520 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17522 if (dump_enabled_p ())
17523 dump_printf_loc (MSG_NOTE, tloc,
17524 "Will not turn target construct into a gridified GPGPU "
17525 "kernel because the inner loop is not a simple for "
17526 "loop\n");
17527 return false;
17529 if (gfor->collapse > 1)
17531 if (dump_enabled_p ())
17532 dump_printf_loc (MSG_NOTE, tloc,
17533 "Will not turn target construct into a gridified GPGPU "
17534 "kernel because the inner loop contains collapse "
17535 "clause\n");
17536 return false;
17539 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17541 if (dump_enabled_p ())
17542 dump_printf_loc (MSG_NOTE, tloc,
17543 "Will not turn target construct into a gridified GPGPU "
17544 "kernel because the inner loop pre_body contains"
17545 "a complex instruction\n");
17546 return false;
17549 clauses = gimple_omp_for_clauses (gfor);
17550 while (clauses)
17552 switch (OMP_CLAUSE_CODE (clauses))
17554 case OMP_CLAUSE_SCHEDULE:
17555 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17557 if (dump_enabled_p ())
17558 dump_printf_loc (MSG_NOTE, tloc,
17559 "Will not turn target construct into a "
17560 "gridified GPGPU kernel because the inner "
17561 "loop has a non-automatic scheduling clause\n");
17562 return false;
17564 break;
17566 case OMP_CLAUSE_REDUCTION:
17567 if (dump_enabled_p ())
17568 dump_printf_loc (MSG_NOTE, tloc,
17569 "Will not turn target construct into a "
17570 "gridified GPGPU kernel because a reduction "
17571 "clause is present\n ");
17572 return false;
17574 case OMP_CLAUSE_LASTPRIVATE:
17575 if (dump_enabled_p ())
17576 dump_printf_loc (MSG_NOTE, tloc,
17577 "Will not turn target construct into a "
17578 "gridified GPGPU kernel because a lastprivate "
17579 "clause is present\n ");
17580 return false;
17582 default:
17583 break;
17585 clauses = OMP_CLAUSE_CHAIN (clauses);
17588 struct walk_stmt_info wi;
17589 memset (&wi, 0, sizeof (wi));
17590 if (walk_gimple_seq (gimple_omp_body (gfor),
17591 grid_find_ungridifiable_statement,
17592 NULL, &wi))
17594 gimple *bad = (gimple *) wi.info;
17595 if (dump_enabled_p ())
17597 if (is_gimple_call (bad))
17598 dump_printf_loc (MSG_NOTE, tloc,
17599 "Will not turn target construct into a gridified "
17600 " GPGPU kernel because the inner loop contains "
17601 "call to a noreturn function\n");
17602 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17603 dump_printf_loc (MSG_NOTE, tloc,
17604 "Will not turn target construct into a gridified "
17605 " GPGPU kernel because the inner loop contains "
17606 "a simd construct\n");
17607 else
17608 dump_printf_loc (MSG_NOTE, tloc,
17609 "Will not turn target construct into a gridified "
17610 "GPGPU kernel because the inner loop contains "
17611 "statement %s which cannot be transformed\n",
17612 gimple_code_name[(int) gimple_code (bad)]);
17614 return false;
17617 *group_size_p = group_size;
17618 return true;
17621 /* Operand walker, used to remap pre-body declarations according to a hash map
17622 provided in DATA. */
17624 static tree
17625 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17627 tree t = *tp;
17629 if (DECL_P (t) || TYPE_P (t))
17630 *walk_subtrees = 0;
17631 else
17632 *walk_subtrees = 1;
17634 if (TREE_CODE (t) == VAR_DECL)
17636 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17637 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17638 tree *repl = declmap->get (t);
17639 if (repl)
17640 *tp = *repl;
17642 return NULL_TREE;
17645 /* Copy leading register-type assignments to local variables in SRC to just
17646 before DST, Creating temporaries, adjusting mapping of operands in WI and
17647 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17648 Return the first statement that does not conform to
17649 grid_reg_assignment_to_local_var_p or NULL. */
17651 static gimple *
17652 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17653 gbind *tgt_bind, struct walk_stmt_info *wi)
17655 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17656 gimple_stmt_iterator gsi;
17657 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17659 gimple *stmt = gsi_stmt (gsi);
17660 if (gbind *bind = dyn_cast <gbind *> (stmt))
17662 gimple *r = grid_copy_leading_local_assignments
17663 (gimple_bind_body (bind), dst, tgt_bind, wi);
17664 if (r)
17665 return r;
17666 else
17667 continue;
17669 if (!grid_reg_assignment_to_local_var_p (stmt))
17670 return stmt;
17671 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17672 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17673 TREE_TYPE (lhs));
17674 DECL_CONTEXT (repl) = current_function_decl;
17675 gimple_bind_append_vars (tgt_bind, repl);
17677 declmap->put (lhs, repl);
17678 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17679 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17680 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17682 return NULL;
17685 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17686 components, mark them as part of kernel and return the inner loop, and copy
17687 assignment leading to them just before DST, remapping them using WI and
17688 adding new temporaries to TGT_BIND. */
17690 static gomp_for *
17691 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17692 gbind *tgt_bind, struct walk_stmt_info *wi)
17694 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17695 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17696 gcc_assert (teams);
17697 gimple_omp_teams_set_grid_phony (teams, true);
17698 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17699 tgt_bind, wi);
17700 gcc_checking_assert (stmt);
17701 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17702 gcc_assert (dist);
17703 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17704 if (prebody)
17705 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17706 gimple_omp_for_set_grid_phony (dist, true);
17707 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17708 tgt_bind, wi);
17709 gcc_checking_assert (stmt);
17711 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17712 gimple_omp_parallel_set_grid_phony (parallel, true);
17713 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17714 tgt_bind, wi);
17715 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17716 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17717 prebody = gimple_omp_for_pre_body (inner_loop);
17718 if (prebody)
17719 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17721 return inner_loop;
17724 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17725 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17726 is the bind into which temporaries inserted before TARGET should be
17727 added. */
17729 static void
17730 grid_attempt_target_gridification (gomp_target *target,
17731 gimple_stmt_iterator *gsi,
17732 gbind *tgt_bind)
17734 tree group_size;
17735 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17736 return;
17738 location_t loc = gimple_location (target);
17739 if (dump_enabled_p ())
17740 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17741 "Target construct will be turned into a gridified GPGPU "
17742 "kernel\n");
17744 /* Copy target body to a GPUKERNEL construct: */
17745 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17746 (gimple_omp_body (target));
17748 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17749 struct walk_stmt_info wi;
17750 memset (&wi, 0, sizeof (struct walk_stmt_info));
17751 wi.info = declmap;
17753 /* Copy assignments in between OMP statements before target, mark OMP
17754 statements within copy appropriatly. */
17755 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17756 tgt_bind, &wi);
17758 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17759 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17760 tree new_block = gimple_bind_block (new_bind);
17761 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17762 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17763 BLOCK_SUBBLOCKS (enc_block) = new_block;
17764 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17765 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17766 gimple_seq_add_stmt
17767 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17768 gpukernel);
17770 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17771 push_gimplify_context ();
17772 size_t collapse = gimple_omp_for_collapse (inner_loop);
17773 for (size_t i = 0; i < collapse; i++)
17775 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17776 if (POINTER_TYPE_P (type))
17777 itype = signed_type_for (type);
17778 else
17779 itype = type;
17781 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17782 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17783 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17784 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17785 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17786 adjust_for_condition (loc, &cond_code, &n2);
17787 tree step;
17788 step = get_omp_for_step_from_incr (loc,
17789 gimple_omp_for_incr (inner_loop, i));
17790 gimple_seq tmpseq = NULL;
17791 n1 = fold_convert (itype, n1);
17792 n2 = fold_convert (itype, n2);
17793 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17794 t = fold_build2 (PLUS_EXPR, itype, step, t);
17795 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17796 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17797 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17798 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17799 fold_build1 (NEGATE_EXPR, itype, t),
17800 fold_build1 (NEGATE_EXPR, itype, step));
17801 else
17802 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17803 tree gs = fold_convert (uint32_type_node, t);
17804 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17805 if (!gimple_seq_empty_p (tmpseq))
17806 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17808 tree ws;
17809 if (i == 0 && group_size)
17811 ws = fold_convert (uint32_type_node, group_size);
17812 tmpseq = NULL;
17813 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17814 if (!gimple_seq_empty_p (tmpseq))
17815 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17817 else
17818 ws = build_zero_cst (uint32_type_node);
17820 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17821 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17822 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17823 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17824 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17825 gimple_omp_target_set_clauses (target, c);
17827 pop_gimplify_context (tgt_bind);
17828 delete declmap;
17829 return;
17832 /* Walker function doing all the work for create_target_kernels. */
17834 static tree
17835 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17836 bool *handled_ops_p,
17837 struct walk_stmt_info *incoming)
17839 *handled_ops_p = false;
17841 gimple *stmt = gsi_stmt (*gsi);
17842 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17843 if (target)
17845 gbind *tgt_bind = (gbind *) incoming->info;
17846 gcc_checking_assert (tgt_bind);
17847 grid_attempt_target_gridification (target, gsi, tgt_bind);
17848 return NULL_TREE;
17850 gbind *bind = dyn_cast <gbind *> (stmt);
17851 if (bind)
17853 *handled_ops_p = true;
17854 struct walk_stmt_info wi;
17855 memset (&wi, 0, sizeof (wi));
17856 wi.info = bind;
17857 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17858 grid_gridify_all_targets_stmt, NULL, &wi);
17860 return NULL_TREE;
17863 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17864 have their bodies duplicated, with the new copy being put into a
17865 gimple_omp_grid_body statement. All kernel-related construct within the
17866 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17867 re-structuring is often needed, such as copying pre-bodies before the target
17868 construct so that kernel grid sizes can be computed. */
17870 static void
17871 grid_gridify_all_targets (gimple_seq *body_p)
17873 struct walk_stmt_info wi;
17874 memset (&wi, 0, sizeof (wi));
17875 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17879 /* Main entry point. */
17881 static unsigned int
17882 execute_lower_omp (void)
17884 gimple_seq body;
17885 int i;
17886 omp_context *ctx;
17888 /* This pass always runs, to provide PROP_gimple_lomp.
17889 But often, there is nothing to do. */
17890 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17891 && flag_openmp_simd == 0)
17892 return 0;
17894 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17895 delete_omp_context);
17897 body = gimple_body (current_function_decl);
17899 if (hsa_gen_requested_p ())
17900 grid_gridify_all_targets (&body);
17902 scan_omp (&body, NULL);
17903 gcc_assert (taskreg_nesting_level == 0);
17904 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17905 finish_taskreg_scan (ctx);
17906 taskreg_contexts.release ();
17908 if (all_contexts->root)
17910 if (task_shared_vars)
17911 push_gimplify_context ();
17912 lower_omp (&body, NULL);
17913 if (task_shared_vars)
17914 pop_gimplify_context (NULL);
17917 if (all_contexts)
17919 splay_tree_delete (all_contexts);
17920 all_contexts = NULL;
17922 BITMAP_FREE (task_shared_vars);
17923 return 0;
17926 namespace {
17928 const pass_data pass_data_lower_omp =
17930 GIMPLE_PASS, /* type */
17931 "omplower", /* name */
17932 OPTGROUP_NONE, /* optinfo_flags */
17933 TV_NONE, /* tv_id */
17934 PROP_gimple_any, /* properties_required */
17935 PROP_gimple_lomp, /* properties_provided */
17936 0, /* properties_destroyed */
17937 0, /* todo_flags_start */
17938 0, /* todo_flags_finish */
17941 class pass_lower_omp : public gimple_opt_pass
17943 public:
17944 pass_lower_omp (gcc::context *ctxt)
17945 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17948 /* opt_pass methods: */
17949 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17951 }; // class pass_lower_omp
17953 } // anon namespace
17955 gimple_opt_pass *
17956 make_pass_lower_omp (gcc::context *ctxt)
17958 return new pass_lower_omp (ctxt);
17961 /* The following is a utility to diagnose structured block violations.
17962 It is not part of the "omplower" pass, as that's invoked too late. It
17963 should be invoked by the respective front ends after gimplification. */
17965 static splay_tree all_labels;
17967 /* Check for mismatched contexts and generate an error if needed. Return
17968 true if an error is detected. */
17970 static bool
17971 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17972 gimple *branch_ctx, gimple *label_ctx)
17974 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17975 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17977 if (label_ctx == branch_ctx)
17978 return false;
17980 const char* kind = NULL;
17982 if (flag_cilkplus)
17984 if ((branch_ctx
17985 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17986 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17987 || (label_ctx
17988 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17989 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17990 kind = "Cilk Plus";
17992 if (flag_openacc)
17994 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17995 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17997 gcc_checking_assert (kind == NULL);
17998 kind = "OpenACC";
18001 if (kind == NULL)
18003 gcc_checking_assert (flag_openmp);
18004 kind = "OpenMP";
18008 Previously we kept track of the label's entire context in diagnose_sb_[12]
18009 so we could traverse it and issue a correct "exit" or "enter" error
18010 message upon a structured block violation.
18012 We built the context by building a list with tree_cons'ing, but there is
18013 no easy counterpart in gimple tuples. It seems like far too much work
18014 for issuing exit/enter error messages. If someone really misses the
18015 distinct error message... patches welcome.
18018 #if 0
18019 /* Try to avoid confusing the user by producing and error message
18020 with correct "exit" or "enter" verbiage. We prefer "exit"
18021 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
18022 if (branch_ctx == NULL)
18023 exit_p = false;
18024 else
18026 while (label_ctx)
18028 if (TREE_VALUE (label_ctx) == branch_ctx)
18030 exit_p = false;
18031 break;
18033 label_ctx = TREE_CHAIN (label_ctx);
18037 if (exit_p)
18038 error ("invalid exit from %s structured block", kind);
18039 else
18040 error ("invalid entry to %s structured block", kind);
18041 #endif
18043 /* If it's obvious we have an invalid entry, be specific about the error. */
18044 if (branch_ctx == NULL)
18045 error ("invalid entry to %s structured block", kind);
18046 else
18048 /* Otherwise, be vague and lazy, but efficient. */
18049 error ("invalid branch to/from %s structured block", kind);
18052 gsi_replace (gsi_p, gimple_build_nop (), false);
18053 return true;
18056 /* Pass 1: Create a minimal tree of structured blocks, and record
18057 where each label is found. */
18059 static tree
18060 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18061 struct walk_stmt_info *wi)
18063 gimple *context = (gimple *) wi->info;
18064 gimple *inner_context;
18065 gimple *stmt = gsi_stmt (*gsi_p);
18067 *handled_ops_p = true;
18069 switch (gimple_code (stmt))
18071 WALK_SUBSTMTS;
18073 case GIMPLE_OMP_PARALLEL:
18074 case GIMPLE_OMP_TASK:
18075 case GIMPLE_OMP_SECTIONS:
18076 case GIMPLE_OMP_SINGLE:
18077 case GIMPLE_OMP_SECTION:
18078 case GIMPLE_OMP_MASTER:
18079 case GIMPLE_OMP_ORDERED:
18080 case GIMPLE_OMP_CRITICAL:
18081 case GIMPLE_OMP_TARGET:
18082 case GIMPLE_OMP_TEAMS:
18083 case GIMPLE_OMP_TASKGROUP:
18084 /* The minimal context here is just the current OMP construct. */
18085 inner_context = stmt;
18086 wi->info = inner_context;
18087 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18088 wi->info = context;
18089 break;
18091 case GIMPLE_OMP_FOR:
18092 inner_context = stmt;
18093 wi->info = inner_context;
18094 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18095 walk them. */
18096 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18097 diagnose_sb_1, NULL, wi);
18098 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18099 wi->info = context;
18100 break;
18102 case GIMPLE_LABEL:
18103 splay_tree_insert (all_labels,
18104 (splay_tree_key) gimple_label_label (
18105 as_a <glabel *> (stmt)),
18106 (splay_tree_value) context);
18107 break;
18109 default:
18110 break;
18113 return NULL_TREE;
18116 /* Pass 2: Check each branch and see if its context differs from that of
18117 the destination label's context. */
18119 static tree
18120 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18121 struct walk_stmt_info *wi)
18123 gimple *context = (gimple *) wi->info;
18124 splay_tree_node n;
18125 gimple *stmt = gsi_stmt (*gsi_p);
18127 *handled_ops_p = true;
18129 switch (gimple_code (stmt))
18131 WALK_SUBSTMTS;
18133 case GIMPLE_OMP_PARALLEL:
18134 case GIMPLE_OMP_TASK:
18135 case GIMPLE_OMP_SECTIONS:
18136 case GIMPLE_OMP_SINGLE:
18137 case GIMPLE_OMP_SECTION:
18138 case GIMPLE_OMP_MASTER:
18139 case GIMPLE_OMP_ORDERED:
18140 case GIMPLE_OMP_CRITICAL:
18141 case GIMPLE_OMP_TARGET:
18142 case GIMPLE_OMP_TEAMS:
18143 case GIMPLE_OMP_TASKGROUP:
18144 wi->info = stmt;
18145 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18146 wi->info = context;
18147 break;
18149 case GIMPLE_OMP_FOR:
18150 wi->info = stmt;
18151 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18152 walk them. */
18153 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18154 diagnose_sb_2, NULL, wi);
18155 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18156 wi->info = context;
18157 break;
18159 case GIMPLE_COND:
18161 gcond *cond_stmt = as_a <gcond *> (stmt);
18162 tree lab = gimple_cond_true_label (cond_stmt);
18163 if (lab)
18165 n = splay_tree_lookup (all_labels,
18166 (splay_tree_key) lab);
18167 diagnose_sb_0 (gsi_p, context,
18168 n ? (gimple *) n->value : NULL);
18170 lab = gimple_cond_false_label (cond_stmt);
18171 if (lab)
18173 n = splay_tree_lookup (all_labels,
18174 (splay_tree_key) lab);
18175 diagnose_sb_0 (gsi_p, context,
18176 n ? (gimple *) n->value : NULL);
18179 break;
18181 case GIMPLE_GOTO:
18183 tree lab = gimple_goto_dest (stmt);
18184 if (TREE_CODE (lab) != LABEL_DECL)
18185 break;
18187 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18188 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18190 break;
18192 case GIMPLE_SWITCH:
18194 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18195 unsigned int i;
18196 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18198 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18199 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18200 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18201 break;
18204 break;
18206 case GIMPLE_RETURN:
18207 diagnose_sb_0 (gsi_p, context, NULL);
18208 break;
18210 default:
18211 break;
18214 return NULL_TREE;
18217 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18218 GIMPLE_* codes. */
18219 bool
18220 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18221 int *region_idx)
18223 gimple *last = last_stmt (bb);
18224 enum gimple_code code = gimple_code (last);
18225 struct omp_region *cur_region = *region;
18226 bool fallthru = false;
18228 switch (code)
18230 case GIMPLE_OMP_PARALLEL:
18231 case GIMPLE_OMP_TASK:
18232 case GIMPLE_OMP_FOR:
18233 case GIMPLE_OMP_SINGLE:
18234 case GIMPLE_OMP_TEAMS:
18235 case GIMPLE_OMP_MASTER:
18236 case GIMPLE_OMP_TASKGROUP:
18237 case GIMPLE_OMP_CRITICAL:
18238 case GIMPLE_OMP_SECTION:
18239 case GIMPLE_OMP_GRID_BODY:
18240 cur_region = new_omp_region (bb, code, cur_region);
18241 fallthru = true;
18242 break;
18244 case GIMPLE_OMP_ORDERED:
18245 cur_region = new_omp_region (bb, code, cur_region);
18246 fallthru = true;
18247 if (find_omp_clause (gimple_omp_ordered_clauses
18248 (as_a <gomp_ordered *> (last)),
18249 OMP_CLAUSE_DEPEND))
18250 cur_region = cur_region->outer;
18251 break;
18253 case GIMPLE_OMP_TARGET:
18254 cur_region = new_omp_region (bb, code, cur_region);
18255 fallthru = true;
18256 switch (gimple_omp_target_kind (last))
18258 case GF_OMP_TARGET_KIND_REGION:
18259 case GF_OMP_TARGET_KIND_DATA:
18260 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18261 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18262 case GF_OMP_TARGET_KIND_OACC_DATA:
18263 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18264 break;
18265 case GF_OMP_TARGET_KIND_UPDATE:
18266 case GF_OMP_TARGET_KIND_ENTER_DATA:
18267 case GF_OMP_TARGET_KIND_EXIT_DATA:
18268 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18269 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18270 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18271 cur_region = cur_region->outer;
18272 break;
18273 default:
18274 gcc_unreachable ();
18276 break;
18278 case GIMPLE_OMP_SECTIONS:
18279 cur_region = new_omp_region (bb, code, cur_region);
18280 fallthru = true;
18281 break;
18283 case GIMPLE_OMP_SECTIONS_SWITCH:
18284 fallthru = false;
18285 break;
18287 case GIMPLE_OMP_ATOMIC_LOAD:
18288 case GIMPLE_OMP_ATOMIC_STORE:
18289 fallthru = true;
18290 break;
18292 case GIMPLE_OMP_RETURN:
18293 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18294 somewhere other than the next block. This will be
18295 created later. */
18296 cur_region->exit = bb;
18297 if (cur_region->type == GIMPLE_OMP_TASK)
18298 /* Add an edge corresponding to not scheduling the task
18299 immediately. */
18300 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18301 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18302 cur_region = cur_region->outer;
18303 break;
18305 case GIMPLE_OMP_CONTINUE:
18306 cur_region->cont = bb;
18307 switch (cur_region->type)
18309 case GIMPLE_OMP_FOR:
18310 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18311 succs edges as abnormal to prevent splitting
18312 them. */
18313 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18314 /* Make the loopback edge. */
18315 make_edge (bb, single_succ (cur_region->entry),
18316 EDGE_ABNORMAL);
18318 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18319 corresponds to the case that the body of the loop
18320 is not executed at all. */
18321 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18322 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18323 fallthru = false;
18324 break;
18326 case GIMPLE_OMP_SECTIONS:
18327 /* Wire up the edges into and out of the nested sections. */
18329 basic_block switch_bb = single_succ (cur_region->entry);
18331 struct omp_region *i;
18332 for (i = cur_region->inner; i ; i = i->next)
18334 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18335 make_edge (switch_bb, i->entry, 0);
18336 make_edge (i->exit, bb, EDGE_FALLTHRU);
18339 /* Make the loopback edge to the block with
18340 GIMPLE_OMP_SECTIONS_SWITCH. */
18341 make_edge (bb, switch_bb, 0);
18343 /* Make the edge from the switch to exit. */
18344 make_edge (switch_bb, bb->next_bb, 0);
18345 fallthru = false;
18347 break;
18349 case GIMPLE_OMP_TASK:
18350 fallthru = true;
18351 break;
18353 default:
18354 gcc_unreachable ();
18356 break;
18358 default:
18359 gcc_unreachable ();
18362 if (*region != cur_region)
18364 *region = cur_region;
18365 if (cur_region)
18366 *region_idx = cur_region->entry->index;
18367 else
18368 *region_idx = 0;
18371 return fallthru;
18374 static unsigned int
18375 diagnose_omp_structured_block_errors (void)
18377 struct walk_stmt_info wi;
18378 gimple_seq body = gimple_body (current_function_decl);
18380 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18382 memset (&wi, 0, sizeof (wi));
18383 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18385 memset (&wi, 0, sizeof (wi));
18386 wi.want_locations = true;
18387 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18389 gimple_set_body (current_function_decl, body);
18391 splay_tree_delete (all_labels);
18392 all_labels = NULL;
18394 return 0;
18397 namespace {
18399 const pass_data pass_data_diagnose_omp_blocks =
18401 GIMPLE_PASS, /* type */
18402 "*diagnose_omp_blocks", /* name */
18403 OPTGROUP_NONE, /* optinfo_flags */
18404 TV_NONE, /* tv_id */
18405 PROP_gimple_any, /* properties_required */
18406 0, /* properties_provided */
18407 0, /* properties_destroyed */
18408 0, /* todo_flags_start */
18409 0, /* todo_flags_finish */
18412 class pass_diagnose_omp_blocks : public gimple_opt_pass
18414 public:
18415 pass_diagnose_omp_blocks (gcc::context *ctxt)
18416 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18419 /* opt_pass methods: */
18420 virtual bool gate (function *)
18422 return flag_cilkplus || flag_openacc || flag_openmp;
18424 virtual unsigned int execute (function *)
18426 return diagnose_omp_structured_block_errors ();
18429 }; // class pass_diagnose_omp_blocks
18431 } // anon namespace
18433 gimple_opt_pass *
18434 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18436 return new pass_diagnose_omp_blocks (ctxt);
18439 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18440 adds their addresses and sizes to constructor-vector V_CTOR. */
18441 static void
18442 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18443 vec<constructor_elt, va_gc> *v_ctor)
18445 unsigned len = vec_safe_length (v_decls);
18446 for (unsigned i = 0; i < len; i++)
18448 tree it = (*v_decls)[i];
18449 bool is_var = TREE_CODE (it) == VAR_DECL;
18450 bool is_link_var
18451 = is_var
18452 #ifdef ACCEL_COMPILER
18453 && DECL_HAS_VALUE_EXPR_P (it)
18454 #endif
18455 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18457 tree size = NULL_TREE;
18458 if (is_var)
18459 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18461 tree addr;
18462 if (!is_link_var)
18463 addr = build_fold_addr_expr (it);
18464 else
18466 #ifdef ACCEL_COMPILER
18467 /* For "omp declare target link" vars add address of the pointer to
18468 the target table, instead of address of the var. */
18469 tree value_expr = DECL_VALUE_EXPR (it);
18470 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18471 varpool_node::finalize_decl (link_ptr_decl);
18472 addr = build_fold_addr_expr (link_ptr_decl);
18473 #else
18474 addr = build_fold_addr_expr (it);
18475 #endif
18477 /* Most significant bit of the size marks "omp declare target link"
18478 vars in host and target tables. */
18479 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18480 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18481 * BITS_PER_UNIT - 1);
18482 size = wide_int_to_tree (const_ptr_type_node, isize);
18485 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18486 if (is_var)
18487 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18491 /* Create new symbols containing (address, size) pairs for global variables,
18492 marked with "omp declare target" attribute, as well as addresses for the
18493 functions, which are outlined offloading regions. */
18494 void
18495 omp_finish_file (void)
18497 unsigned num_funcs = vec_safe_length (offload_funcs);
18498 unsigned num_vars = vec_safe_length (offload_vars);
18500 if (num_funcs == 0 && num_vars == 0)
18501 return;
18503 if (targetm_common.have_named_sections)
18505 vec<constructor_elt, va_gc> *v_f, *v_v;
18506 vec_alloc (v_f, num_funcs);
18507 vec_alloc (v_v, num_vars * 2);
18509 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18510 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18512 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18513 num_vars * 2);
18514 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18515 num_funcs);
18516 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18517 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18518 tree ctor_v = build_constructor (vars_decl_type, v_v);
18519 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18520 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18521 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18522 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18523 get_identifier (".offload_func_table"),
18524 funcs_decl_type);
18525 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18526 get_identifier (".offload_var_table"),
18527 vars_decl_type);
18528 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18529 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18530 otherwise a joint table in a binary will contain padding between
18531 tables from multiple object files. */
18532 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18533 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18534 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18535 DECL_INITIAL (funcs_decl) = ctor_f;
18536 DECL_INITIAL (vars_decl) = ctor_v;
18537 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18538 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18540 varpool_node::finalize_decl (vars_decl);
18541 varpool_node::finalize_decl (funcs_decl);
18543 else
18545 for (unsigned i = 0; i < num_funcs; i++)
18547 tree it = (*offload_funcs)[i];
18548 targetm.record_offload_symbol (it);
18550 for (unsigned i = 0; i < num_vars; i++)
18552 tree it = (*offload_vars)[i];
18553 targetm.record_offload_symbol (it);
18558 /* Find the number of threads (POS = false), or thread number (POS =
18559 true) for an OpenACC region partitioned as MASK. Setup code
18560 required for the calculation is added to SEQ. */
18562 static tree
18563 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18565 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18566 unsigned ix;
18568 /* Start at gang level, and examine relevant dimension indices. */
18569 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18570 if (GOMP_DIM_MASK (ix) & mask)
18572 tree arg = build_int_cst (unsigned_type_node, ix);
18574 if (res)
18576 /* We had an outer index, so scale that by the size of
18577 this dimension. */
18578 tree n = create_tmp_var (integer_type_node);
18579 gimple *call
18580 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18582 gimple_call_set_lhs (call, n);
18583 gimple_seq_add_stmt (seq, call);
18584 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18586 if (pos)
18588 /* Determine index in this dimension. */
18589 tree id = create_tmp_var (integer_type_node);
18590 gimple *call = gimple_build_call_internal
18591 (IFN_GOACC_DIM_POS, 1, arg);
18593 gimple_call_set_lhs (call, id);
18594 gimple_seq_add_stmt (seq, call);
18595 if (res)
18596 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18597 else
18598 res = id;
18602 if (res == NULL_TREE)
18603 res = integer_zero_node;
18605 return res;
18608 /* Transform IFN_GOACC_LOOP calls to actual code. See
18609 expand_oacc_for for where these are generated. At the vector
18610 level, we stride loops, such that each member of a warp will
18611 operate on adjacent iterations. At the worker and gang level,
18612 each gang/warp executes a set of contiguous iterations. Chunking
18613 can override this such that each iteration engine executes a
18614 contiguous chunk, and then moves on to stride to the next chunk. */
18616 static void
18617 oacc_xform_loop (gcall *call)
18619 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18620 enum ifn_goacc_loop_kind code
18621 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18622 tree dir = gimple_call_arg (call, 1);
18623 tree range = gimple_call_arg (call, 2);
18624 tree step = gimple_call_arg (call, 3);
18625 tree chunk_size = NULL_TREE;
18626 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18627 tree lhs = gimple_call_lhs (call);
18628 tree type = TREE_TYPE (lhs);
18629 tree diff_type = TREE_TYPE (range);
18630 tree r = NULL_TREE;
18631 gimple_seq seq = NULL;
18632 bool chunking = false, striding = true;
18633 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18634 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18636 #ifdef ACCEL_COMPILER
18637 chunk_size = gimple_call_arg (call, 4);
18638 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18639 || integer_zerop (chunk_size)) /* Default (also static). */
18641 /* If we're at the gang level, we want each to execute a
18642 contiguous run of iterations. Otherwise we want each element
18643 to stride. */
18644 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18645 chunking = false;
18647 else
18649 /* Chunk of size 1 is striding. */
18650 striding = integer_onep (chunk_size);
18651 chunking = !striding;
18653 #endif
18655 /* striding=true, chunking=true
18656 -> invalid.
18657 striding=true, chunking=false
18658 -> chunks=1
18659 striding=false,chunking=true
18660 -> chunks=ceil (range/(chunksize*threads*step))
18661 striding=false,chunking=false
18662 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18663 push_gimplify_context (true);
18665 switch (code)
18667 default: gcc_unreachable ();
18669 case IFN_GOACC_LOOP_CHUNKS:
18670 if (!chunking)
18671 r = build_int_cst (type, 1);
18672 else
18674 /* chunk_max
18675 = (range - dir) / (chunks * step * num_threads) + dir */
18676 tree per = oacc_thread_numbers (false, mask, &seq);
18677 per = fold_convert (type, per);
18678 chunk_size = fold_convert (type, chunk_size);
18679 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18680 per = fold_build2 (MULT_EXPR, type, per, step);
18681 r = build2 (MINUS_EXPR, type, range, dir);
18682 r = build2 (PLUS_EXPR, type, r, per);
18683 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18685 break;
18687 case IFN_GOACC_LOOP_STEP:
18689 /* If striding, step by the entire compute volume, otherwise
18690 step by the inner volume. */
18691 unsigned volume = striding ? mask : inner_mask;
18693 r = oacc_thread_numbers (false, volume, &seq);
18694 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18696 break;
18698 case IFN_GOACC_LOOP_OFFSET:
18699 if (striding)
18701 r = oacc_thread_numbers (true, mask, &seq);
18702 r = fold_convert (diff_type, r);
18704 else
18706 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18707 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18708 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18709 inner_size, outer_size);
18711 volume = fold_convert (diff_type, volume);
18712 if (chunking)
18713 chunk_size = fold_convert (diff_type, chunk_size);
18714 else
18716 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18718 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18719 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18720 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18723 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18724 fold_convert (diff_type, inner_size));
18725 r = oacc_thread_numbers (true, outer_mask, &seq);
18726 r = fold_convert (diff_type, r);
18727 r = build2 (MULT_EXPR, diff_type, r, span);
18729 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18730 inner = fold_convert (diff_type, inner);
18731 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18733 if (chunking)
18735 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18736 tree per
18737 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18738 per = build2 (MULT_EXPR, diff_type, per, chunk);
18740 r = build2 (PLUS_EXPR, diff_type, r, per);
18743 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18744 if (type != diff_type)
18745 r = fold_convert (type, r);
18746 break;
18748 case IFN_GOACC_LOOP_BOUND:
18749 if (striding)
18750 r = range;
18751 else
18753 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18754 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18755 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18756 inner_size, outer_size);
18758 volume = fold_convert (diff_type, volume);
18759 if (chunking)
18760 chunk_size = fold_convert (diff_type, chunk_size);
18761 else
18763 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18765 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18766 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18767 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18770 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18771 fold_convert (diff_type, inner_size));
18773 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18775 tree offset = gimple_call_arg (call, 6);
18776 r = build2 (PLUS_EXPR, diff_type, r,
18777 fold_convert (diff_type, offset));
18778 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18779 diff_type, r, range);
18781 if (diff_type != type)
18782 r = fold_convert (type, r);
18783 break;
18786 gimplify_assign (lhs, r, &seq);
18788 pop_gimplify_context (NULL);
18790 gsi_replace_with_seq (&gsi, seq, true);
18793 /* Default partitioned and minimum partitioned dimensions. */
18795 static int oacc_default_dims[GOMP_DIM_MAX];
18796 static int oacc_min_dims[GOMP_DIM_MAX];
18798 /* Parse the default dimension parameter. This is a set of
18799 :-separated optional compute dimensions. Each specified dimension
18800 is a positive integer. When device type support is added, it is
18801 planned to be a comma separated list of such compute dimensions,
18802 with all but the first prefixed by the colon-terminated device
18803 type. */
18805 static void
18806 oacc_parse_default_dims (const char *dims)
18808 int ix;
18810 for (ix = GOMP_DIM_MAX; ix--;)
18812 oacc_default_dims[ix] = -1;
18813 oacc_min_dims[ix] = 1;
18816 #ifndef ACCEL_COMPILER
18817 /* Cannot be overridden on the host. */
18818 dims = NULL;
18819 #endif
18820 if (dims)
18822 const char *pos = dims;
18824 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18826 if (ix)
18828 if (*pos != ':')
18829 goto malformed;
18830 pos++;
18833 if (*pos != ':')
18835 long val;
18836 const char *eptr;
18838 errno = 0;
18839 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18840 if (errno || val <= 0 || (int) val != val)
18841 goto malformed;
18842 pos = eptr;
18843 oacc_default_dims[ix] = (int) val;
18846 if (*pos)
18848 malformed:
18849 error_at (UNKNOWN_LOCATION,
18850 "-fopenacc-dim operand is malformed at '%s'", pos);
18854 /* Allow the backend to validate the dimensions. */
18855 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18856 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18859 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18860 raw attribute. DIMS is an array of dimensions, which is filled in.
18861 LEVEL is the partitioning level of a routine, or -1 for an offload
18862 region itself. USED is the mask of partitioned execution in the
18863 function. */
18865 static void
18866 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18868 tree purpose[GOMP_DIM_MAX];
18869 unsigned ix;
18870 tree pos = TREE_VALUE (attrs);
18871 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18873 /* Make sure the attribute creator attached the dimension
18874 information. */
18875 gcc_assert (pos);
18877 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18879 purpose[ix] = TREE_PURPOSE (pos);
18880 tree val = TREE_VALUE (pos);
18881 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18882 pos = TREE_CHAIN (pos);
18885 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18887 /* Default anything left to 1 or a partitioned default. */
18888 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18889 if (dims[ix] < 0)
18891 /* The OpenACC spec says 'If the [num_gangs] clause is not
18892 specified, an implementation-defined default will be used;
18893 the default may depend on the code within the construct.'
18894 (2.5.6). Thus an implementation is free to choose
18895 non-unity default for a parallel region that doesn't have
18896 any gang-partitioned loops. However, it appears that there
18897 is a sufficient body of user code that expects non-gang
18898 partitioned regions to not execute in gang-redundant mode.
18899 So we (a) don't warn about the non-portability and (b) pick
18900 the minimum permissible dimension size when there is no
18901 partitioned execution. Otherwise we pick the global
18902 default for the dimension, which the user can control. The
18903 same wording and logic applies to num_workers and
18904 vector_length, however the worker- or vector- single
18905 execution doesn't have the same impact as gang-redundant
18906 execution. (If the minimum gang-level partioning is not 1,
18907 the target is probably too confusing.) */
18908 dims[ix] = (used & GOMP_DIM_MASK (ix)
18909 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18910 changed = true;
18913 if (changed)
18915 /* Replace the attribute with new values. */
18916 pos = NULL_TREE;
18917 for (ix = GOMP_DIM_MAX; ix--;)
18919 pos = tree_cons (purpose[ix],
18920 build_int_cst (integer_type_node, dims[ix]),
18921 pos);
18922 if (is_kernel)
18923 TREE_PUBLIC (pos) = 1;
18925 replace_oacc_fn_attrib (fn, pos);
18929 /* Create an empty OpenACC loop structure at LOC. */
18931 static oacc_loop *
18932 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18934 oacc_loop *loop = XCNEW (oacc_loop);
18936 loop->parent = parent;
18937 loop->child = loop->sibling = NULL;
18939 if (parent)
18941 loop->sibling = parent->child;
18942 parent->child = loop;
18945 loop->loc = loc;
18946 loop->marker = NULL;
18947 memset (loop->heads, 0, sizeof (loop->heads));
18948 memset (loop->tails, 0, sizeof (loop->tails));
18949 loop->routine = NULL_TREE;
18951 loop->mask = loop->flags = loop->inner = 0;
18952 loop->ifns = 0;
18953 loop->chunk_size = 0;
18954 loop->head_end = NULL;
18956 return loop;
18959 /* Create an outermost, dummy OpenACC loop for offloaded function
18960 DECL. */
18962 static oacc_loop *
18963 new_oacc_loop_outer (tree decl)
18965 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18968 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18969 Link into PARENT loop. Return the new loop. */
18971 static oacc_loop *
18972 new_oacc_loop (oacc_loop *parent, gcall *marker)
18974 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18976 loop->marker = marker;
18978 /* TODO: This is where device_type flattening would occur for the loop
18979 flags. */
18981 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18983 tree chunk_size = integer_zero_node;
18984 if (loop->flags & OLF_GANG_STATIC)
18985 chunk_size = gimple_call_arg (marker, 4);
18986 loop->chunk_size = chunk_size;
18988 return loop;
18991 /* Create a dummy loop encompassing a call to a openACC routine.
18992 Extract the routine's partitioning requirements. */
18994 static void
18995 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18997 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18998 int level = oacc_fn_attrib_level (attrs);
19000 gcc_assert (level >= 0);
19002 loop->marker = call;
19003 loop->routine = decl;
19004 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
19005 ^ (GOMP_DIM_MASK (level) - 1));
19008 /* Finish off the current OpenACC loop ending at tail marker TAIL.
19009 Return the parent loop. */
19011 static oacc_loop *
19012 finish_oacc_loop (oacc_loop *loop)
19014 /* If the loop has been collapsed, don't partition it. */
19015 if (!loop->ifns)
19016 loop->mask = loop->flags = 0;
19017 return loop->parent;
19020 /* Free all OpenACC loop structures within LOOP (inclusive). */
19022 static void
19023 free_oacc_loop (oacc_loop *loop)
19025 if (loop->sibling)
19026 free_oacc_loop (loop->sibling);
19027 if (loop->child)
19028 free_oacc_loop (loop->child);
19030 free (loop);
19033 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19035 static void
19036 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19037 const char *title, int level)
19039 enum ifn_unique_kind kind
19040 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19042 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19043 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19045 gimple *stmt = gsi_stmt (gsi);
19047 if (is_gimple_call (stmt)
19048 && gimple_call_internal_p (stmt)
19049 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19051 enum ifn_unique_kind k
19052 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19053 (gimple_call_arg (stmt, 0)));
19055 if (k == kind && stmt != from)
19056 break;
19058 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19060 gsi_next (&gsi);
19061 while (gsi_end_p (gsi))
19062 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19066 /* Dump OpenACC loops LOOP, its siblings and its children. */
19068 static void
19069 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19071 int ix;
19073 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19074 loop->flags, loop->mask,
19075 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19077 if (loop->marker)
19078 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19080 if (loop->routine)
19081 fprintf (file, "%*sRoutine %s:%u:%s\n",
19082 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19083 DECL_SOURCE_LINE (loop->routine),
19084 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19086 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19087 if (loop->heads[ix])
19088 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19089 for (ix = GOMP_DIM_MAX; ix--;)
19090 if (loop->tails[ix])
19091 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19093 if (loop->child)
19094 dump_oacc_loop (file, loop->child, depth + 1);
19095 if (loop->sibling)
19096 dump_oacc_loop (file, loop->sibling, depth);
19099 void debug_oacc_loop (oacc_loop *);
19101 /* Dump loops to stderr. */
19103 DEBUG_FUNCTION void
19104 debug_oacc_loop (oacc_loop *loop)
19106 dump_oacc_loop (stderr, loop, 0);
19109 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19110 structures as we go. By construction these loops are properly
19111 nested. */
19113 static void
19114 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19116 int marker = 0;
19117 int remaining = 0;
19119 if (bb->flags & BB_VISITED)
19120 return;
19122 follow:
19123 bb->flags |= BB_VISITED;
19125 /* Scan for loop markers. */
19126 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19127 gsi_next (&gsi))
19129 gimple *stmt = gsi_stmt (gsi);
19131 if (!is_gimple_call (stmt))
19132 continue;
19134 gcall *call = as_a <gcall *> (stmt);
19136 /* If this is a routine, make a dummy loop for it. */
19137 if (tree decl = gimple_call_fndecl (call))
19138 if (tree attrs = get_oacc_fn_attrib (decl))
19140 gcc_assert (!marker);
19141 new_oacc_loop_routine (loop, call, decl, attrs);
19144 if (!gimple_call_internal_p (call))
19145 continue;
19147 switch (gimple_call_internal_fn (call))
19149 default:
19150 break;
19152 case IFN_GOACC_LOOP:
19153 /* Count the goacc loop abstraction fns, to determine if the
19154 loop was collapsed already. */
19155 loop->ifns++;
19156 break;
19158 case IFN_UNIQUE:
19159 enum ifn_unique_kind kind
19160 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19161 (gimple_call_arg (call, 0)));
19162 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19163 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19165 if (gimple_call_num_args (call) == 2)
19167 gcc_assert (marker && !remaining);
19168 marker = 0;
19169 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19170 loop = finish_oacc_loop (loop);
19171 else
19172 loop->head_end = call;
19174 else
19176 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19178 if (!marker)
19180 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19181 loop = new_oacc_loop (loop, call);
19182 remaining = count;
19184 gcc_assert (count == remaining);
19185 if (remaining)
19187 remaining--;
19188 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19189 loop->heads[marker] = call;
19190 else
19191 loop->tails[remaining] = call;
19193 marker++;
19198 if (remaining || marker)
19200 bb = single_succ (bb);
19201 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19202 goto follow;
19205 /* Walk successor blocks. */
19206 edge e;
19207 edge_iterator ei;
19209 FOR_EACH_EDGE (e, ei, bb->succs)
19210 oacc_loop_discover_walk (loop, e->dest);
19213 /* LOOP is the first sibling. Reverse the order in place and return
19214 the new first sibling. Recurse to child loops. */
19216 static oacc_loop *
19217 oacc_loop_sibling_nreverse (oacc_loop *loop)
19219 oacc_loop *last = NULL;
19222 if (loop->child)
19223 loop->child = oacc_loop_sibling_nreverse (loop->child);
19225 oacc_loop *next = loop->sibling;
19226 loop->sibling = last;
19227 last = loop;
19228 loop = next;
19230 while (loop);
19232 return last;
19235 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19236 the current function. */
19238 static oacc_loop *
19239 oacc_loop_discovery ()
19241 basic_block bb;
19243 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19244 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19246 /* The siblings were constructed in reverse order, reverse them so
19247 that diagnostics come out in an unsurprising order. */
19248 top = oacc_loop_sibling_nreverse (top);
19250 /* Reset the visited flags. */
19251 FOR_ALL_BB_FN (bb, cfun)
19252 bb->flags &= ~BB_VISITED;
19254 return top;
19257 /* Transform the abstract internal function markers starting at FROM
19258 to be for partitioning level LEVEL. Stop when we meet another HEAD
19259 or TAIL marker. */
19261 static void
19262 oacc_loop_xform_head_tail (gcall *from, int level)
19264 enum ifn_unique_kind kind
19265 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19266 tree replacement = build_int_cst (unsigned_type_node, level);
19268 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19270 gimple *stmt = gsi_stmt (gsi);
19272 if (is_gimple_call (stmt)
19273 && gimple_call_internal_p (stmt)
19274 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19276 enum ifn_unique_kind k
19277 = ((enum ifn_unique_kind)
19278 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19280 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19281 *gimple_call_arg_ptr (stmt, 2) = replacement;
19282 else if (k == kind && stmt != from)
19283 break;
19285 else if (is_gimple_call (stmt)
19286 && gimple_call_internal_p (stmt)
19287 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19288 *gimple_call_arg_ptr (stmt, 3) = replacement;
19290 gsi_next (&gsi);
19291 while (gsi_end_p (gsi))
19292 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19296 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19297 determined partitioning mask and chunking argument. END_MARKER
19298 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19299 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19300 the replacement partitioning mask and CHUNK_ARG is the replacement
19301 chunking arg. */
19303 static void
19304 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19305 tree mask_arg, tree chunk_arg)
19307 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19309 gcc_checking_assert (ifns);
19310 for (;;)
19312 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19314 gimple *stmt = gsi_stmt (gsi);
19316 if (!is_gimple_call (stmt))
19317 continue;
19319 gcall *call = as_a <gcall *> (stmt);
19321 if (!gimple_call_internal_p (call))
19322 continue;
19324 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19325 continue;
19327 *gimple_call_arg_ptr (call, 5) = mask_arg;
19328 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19329 ifns--;
19330 if (!ifns)
19331 return;
19334 /* The LOOP_BOUND ifn could be in the single successor
19335 block. */
19336 basic_block bb = single_succ (gsi_bb (gsi));
19337 gsi = gsi_start_bb (bb);
19341 /* Process the discovered OpenACC loops, setting the correct
19342 partitioning level etc. */
19344 static void
19345 oacc_loop_process (oacc_loop *loop)
19347 if (loop->child)
19348 oacc_loop_process (loop->child);
19350 if (loop->mask && !loop->routine)
19352 int ix;
19353 unsigned mask = loop->mask;
19354 unsigned dim = GOMP_DIM_GANG;
19355 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19356 tree chunk_arg = loop->chunk_size;
19358 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19360 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19362 while (!(GOMP_DIM_MASK (dim) & mask))
19363 dim++;
19365 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19366 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19368 mask ^= GOMP_DIM_MASK (dim);
19372 if (loop->sibling)
19373 oacc_loop_process (loop->sibling);
19376 /* Walk the OpenACC loop heirarchy checking and assigning the
19377 programmer-specified partitionings. OUTER_MASK is the partitioning
19378 this loop is contained within. Return mask of partitioning
19379 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19380 bit. */
19382 static unsigned
19383 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19385 unsigned this_mask = loop->mask;
19386 unsigned mask_all = 0;
19387 bool noisy = true;
19389 #ifdef ACCEL_COMPILER
19390 /* When device_type is supported, we want the device compiler to be
19391 noisy, if the loop parameters are device_type-specific. */
19392 noisy = false;
19393 #endif
19395 if (!loop->routine)
19397 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19398 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19400 this_mask = ((loop->flags >> OLF_DIM_BASE)
19401 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19403 if ((this_mask != 0) + auto_par + seq_par > 1)
19405 if (noisy)
19406 error_at (loop->loc,
19407 seq_par
19408 ? "%<seq%> overrides other OpenACC loop specifiers"
19409 : "%<auto%> conflicts with other OpenACC loop specifiers");
19410 auto_par = false;
19411 loop->flags &= ~OLF_AUTO;
19412 if (seq_par)
19414 loop->flags &=
19415 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19416 this_mask = 0;
19419 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19420 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19423 if (this_mask & outer_mask)
19425 const oacc_loop *outer;
19426 for (outer = loop->parent; outer; outer = outer->parent)
19427 if (outer->mask & this_mask)
19428 break;
19430 if (noisy)
19432 if (outer)
19434 error_at (loop->loc,
19435 "%s uses same OpenACC parallelism as containing loop",
19436 loop->routine ? "routine call" : "inner loop");
19437 inform (outer->loc, "containing loop here");
19439 else
19440 error_at (loop->loc,
19441 "%s uses OpenACC parallelism disallowed by containing routine",
19442 loop->routine ? "routine call" : "loop");
19444 if (loop->routine)
19445 inform (DECL_SOURCE_LOCATION (loop->routine),
19446 "routine %qD declared here", loop->routine);
19448 this_mask &= ~outer_mask;
19450 else
19452 unsigned outermost = this_mask & -this_mask;
19454 if (outermost && outermost <= outer_mask)
19456 if (noisy)
19458 error_at (loop->loc,
19459 "incorrectly nested OpenACC loop parallelism");
19461 const oacc_loop *outer;
19462 for (outer = loop->parent;
19463 outer->flags && outer->flags < outermost;
19464 outer = outer->parent)
19465 continue;
19466 inform (outer->loc, "containing loop here");
19469 this_mask &= ~outermost;
19473 loop->mask = this_mask;
19474 mask_all |= this_mask;
19476 if (loop->child)
19478 loop->inner = oacc_loop_fixed_partitions (loop->child,
19479 outer_mask | this_mask);
19480 mask_all |= loop->inner;
19483 if (loop->sibling)
19484 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19486 return mask_all;
19489 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19490 OUTER_MASK is the partitioning this loop is contained within.
19491 Return the cumulative partitioning used by this loop, siblings and
19492 children. */
19494 static unsigned
19495 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19497 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19498 bool noisy = true;
19500 #ifdef ACCEL_COMPILER
19501 /* When device_type is supported, we want the device compiler to be
19502 noisy, if the loop parameters are device_type-specific. */
19503 noisy = false;
19504 #endif
19506 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19508 /* Allocate the outermost loop at the outermost available
19509 level. */
19510 unsigned this_mask = outer_mask + 1;
19512 if (!(this_mask & loop->inner))
19513 loop->mask = this_mask;
19516 if (loop->child)
19518 unsigned child_mask = outer_mask | loop->mask;
19520 if (loop->mask || assign)
19521 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19523 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19526 if (assign && !loop->mask)
19528 /* Allocate the loop at the innermost available level. */
19529 unsigned this_mask = 0;
19531 /* Determine the outermost partitioning used within this loop. */
19532 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19533 this_mask = (this_mask & -this_mask);
19535 /* Pick the partitioning just inside that one. */
19536 this_mask >>= 1;
19538 /* And avoid picking one use by an outer loop. */
19539 this_mask &= ~outer_mask;
19541 if (!this_mask && noisy)
19542 warning_at (loop->loc, 0,
19543 "insufficient partitioning available to parallelize loop");
19545 loop->mask = this_mask;
19548 if (assign && dump_file)
19549 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19550 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19551 loop->mask);
19553 unsigned inner_mask = 0;
19555 if (loop->sibling)
19556 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19558 inner_mask |= loop->inner | loop->mask;
19560 return inner_mask;
19563 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19564 axes. Return mask of partitioning. */
19566 static unsigned
19567 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19569 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19571 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19573 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19574 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19576 return mask_all;
19579 /* Default fork/join early expander. Delete the function calls if
19580 there is no RTL expander. */
19582 bool
19583 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19584 const int *ARG_UNUSED (dims), bool is_fork)
19586 if (is_fork)
19587 return targetm.have_oacc_fork ();
19588 else
19589 return targetm.have_oacc_join ();
19592 /* Default goacc.reduction early expander.
19594 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19595 If RES_PTR is not integer-zerop:
19596 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19597 TEARDOWN - emit '*RES_PTR = VAR'
19598 If LHS is not NULL
19599 emit 'LHS = VAR' */
19601 void
19602 default_goacc_reduction (gcall *call)
19604 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19605 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19606 tree lhs = gimple_call_lhs (call);
19607 tree var = gimple_call_arg (call, 2);
19608 gimple_seq seq = NULL;
19610 if (code == IFN_GOACC_REDUCTION_SETUP
19611 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19613 /* Setup and Teardown need to copy from/to the receiver object,
19614 if there is one. */
19615 tree ref_to_res = gimple_call_arg (call, 1);
19617 if (!integer_zerop (ref_to_res))
19619 tree dst = build_simple_mem_ref (ref_to_res);
19620 tree src = var;
19622 if (code == IFN_GOACC_REDUCTION_SETUP)
19624 src = dst;
19625 dst = lhs;
19626 lhs = NULL;
19628 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19632 /* Copy VAR to LHS, if there is an LHS. */
19633 if (lhs)
19634 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19636 gsi_replace_with_seq (&gsi, seq, true);
19639 /* Main entry point for oacc transformations which run on the device
19640 compiler after LTO, so we know what the target device is at this
19641 point (including the host fallback). */
19643 static unsigned int
19644 execute_oacc_device_lower ()
19646 tree attrs = get_oacc_fn_attrib (current_function_decl);
19648 if (!attrs)
19649 /* Not an offloaded function. */
19650 return 0;
19652 /* Parse the default dim argument exactly once. */
19653 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19655 oacc_parse_default_dims (flag_openacc_dims);
19656 flag_openacc_dims = (char *)&flag_openacc_dims;
19659 /* Discover, partition and process the loops. */
19660 oacc_loop *loops = oacc_loop_discovery ();
19661 int fn_level = oacc_fn_attrib_level (attrs);
19663 if (dump_file)
19664 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19665 ? "Function is kernels offload\n"
19666 : fn_level < 0 ? "Function is parallel offload\n"
19667 : "Function is routine level %d\n", fn_level);
19669 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19670 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19671 int dims[GOMP_DIM_MAX];
19673 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19675 if (dump_file)
19677 const char *comma = "Compute dimensions [";
19678 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19679 fprintf (dump_file, "%s%d", comma, dims[ix]);
19680 fprintf (dump_file, "]\n");
19683 oacc_loop_process (loops);
19684 if (dump_file)
19686 fprintf (dump_file, "OpenACC loops\n");
19687 dump_oacc_loop (dump_file, loops, 0);
19688 fprintf (dump_file, "\n");
19691 /* Offloaded targets may introduce new basic blocks, which require
19692 dominance information to update SSA. */
19693 calculate_dominance_info (CDI_DOMINATORS);
19695 /* Now lower internal loop functions to target-specific code
19696 sequences. */
19697 basic_block bb;
19698 FOR_ALL_BB_FN (bb, cfun)
19699 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19701 gimple *stmt = gsi_stmt (gsi);
19702 if (!is_gimple_call (stmt))
19704 gsi_next (&gsi);
19705 continue;
19708 gcall *call = as_a <gcall *> (stmt);
19709 if (!gimple_call_internal_p (call))
19711 gsi_next (&gsi);
19712 continue;
19715 /* Rewind to allow rescan. */
19716 gsi_prev (&gsi);
19717 bool rescan = false, remove = false;
19718 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19720 switch (ifn_code)
19722 default: break;
19724 case IFN_GOACC_LOOP:
19725 oacc_xform_loop (call);
19726 rescan = true;
19727 break;
19729 case IFN_GOACC_REDUCTION:
19730 /* Mark the function for SSA renaming. */
19731 mark_virtual_operands_for_renaming (cfun);
19733 /* If the level is -1, this ended up being an unused
19734 axis. Handle as a default. */
19735 if (integer_minus_onep (gimple_call_arg (call, 3)))
19736 default_goacc_reduction (call);
19737 else
19738 targetm.goacc.reduction (call);
19739 rescan = true;
19740 break;
19742 case IFN_UNIQUE:
19744 enum ifn_unique_kind kind
19745 = ((enum ifn_unique_kind)
19746 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19748 switch (kind)
19750 default:
19751 gcc_unreachable ();
19753 case IFN_UNIQUE_OACC_FORK:
19754 case IFN_UNIQUE_OACC_JOIN:
19755 if (integer_minus_onep (gimple_call_arg (call, 2)))
19756 remove = true;
19757 else if (!targetm.goacc.fork_join
19758 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19759 remove = true;
19760 break;
19762 case IFN_UNIQUE_OACC_HEAD_MARK:
19763 case IFN_UNIQUE_OACC_TAIL_MARK:
19764 remove = true;
19765 break;
19767 break;
19771 if (gsi_end_p (gsi))
19772 /* We rewound past the beginning of the BB. */
19773 gsi = gsi_start_bb (bb);
19774 else
19775 /* Undo the rewind. */
19776 gsi_next (&gsi);
19778 if (remove)
19780 if (gimple_vdef (call))
19781 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19782 if (gimple_call_lhs (call))
19784 /* Propagate the data dependency var. */
19785 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19786 gimple_call_arg (call, 1));
19787 gsi_replace (&gsi, ass, false);
19789 else
19790 gsi_remove (&gsi, true);
19792 else if (!rescan)
19793 /* If not rescanning, advance over the call. */
19794 gsi_next (&gsi);
19797 free_oacc_loop (loops);
19799 return 0;
19802 /* Default launch dimension validator. Force everything to 1. A
19803 backend that wants to provide larger dimensions must override this
19804 hook. */
19806 bool
19807 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19808 int ARG_UNUSED (fn_level))
19810 bool changed = false;
19812 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19814 if (dims[ix] != 1)
19816 dims[ix] = 1;
19817 changed = true;
19821 return changed;
19824 /* Default dimension bound is unknown on accelerator and 1 on host. */
19827 default_goacc_dim_limit (int ARG_UNUSED (axis))
19829 #ifdef ACCEL_COMPILER
19830 return 0;
19831 #else
19832 return 1;
19833 #endif
19836 namespace {
19838 const pass_data pass_data_oacc_device_lower =
19840 GIMPLE_PASS, /* type */
19841 "oaccdevlow", /* name */
19842 OPTGROUP_NONE, /* optinfo_flags */
19843 TV_NONE, /* tv_id */
19844 PROP_cfg, /* properties_required */
19845 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19846 0, /* properties_destroyed */
19847 0, /* todo_flags_start */
19848 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19851 class pass_oacc_device_lower : public gimple_opt_pass
19853 public:
19854 pass_oacc_device_lower (gcc::context *ctxt)
19855 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19858 /* opt_pass methods: */
19859 virtual unsigned int execute (function *)
19861 bool gate = flag_openacc != 0;
19863 if (!gate)
19864 return 0;
19866 return execute_oacc_device_lower ();
19869 }; // class pass_oacc_device_lower
19871 } // anon namespace
19873 gimple_opt_pass *
19874 make_pass_oacc_device_lower (gcc::context *ctxt)
19876 return new pass_oacc_device_lower (ctxt);
19879 /* "omp declare target link" handling pass. */
19881 namespace {
19883 const pass_data pass_data_omp_target_link =
19885 GIMPLE_PASS, /* type */
19886 "omptargetlink", /* name */
19887 OPTGROUP_NONE, /* optinfo_flags */
19888 TV_NONE, /* tv_id */
19889 PROP_ssa, /* properties_required */
19890 0, /* properties_provided */
19891 0, /* properties_destroyed */
19892 0, /* todo_flags_start */
19893 TODO_update_ssa, /* todo_flags_finish */
19896 class pass_omp_target_link : public gimple_opt_pass
19898 public:
19899 pass_omp_target_link (gcc::context *ctxt)
19900 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19903 /* opt_pass methods: */
19904 virtual bool gate (function *fun)
19906 #ifdef ACCEL_COMPILER
19907 tree attrs = DECL_ATTRIBUTES (fun->decl);
19908 return lookup_attribute ("omp declare target", attrs)
19909 || lookup_attribute ("omp target entrypoint", attrs);
19910 #else
19911 (void) fun;
19912 return false;
19913 #endif
19916 virtual unsigned execute (function *);
19919 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19921 static tree
19922 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19924 tree t = *tp;
19926 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
19927 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19929 *walk_subtrees = 0;
19930 return t;
19933 return NULL_TREE;
19936 unsigned
19937 pass_omp_target_link::execute (function *fun)
19939 basic_block bb;
19940 FOR_EACH_BB_FN (bb, fun)
19942 gimple_stmt_iterator gsi;
19943 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19944 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19945 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19948 return 0;
19951 } // anon namespace
19953 gimple_opt_pass *
19954 make_pass_omp_target_link (gcc::context *ctxt)
19956 return new pass_omp_target_link (ctxt);
19959 #include "gt-omp-low.h"